diff --git a/mtime.js b/mtime.js index ec17f52..fcde770 100644 --- a/mtime.js +++ b/mtime.js @@ -32,7 +32,7 @@ function getFilesChanges(filesMtimes, concurrencyLimit, done) { } var mtimeNew = stat.mtime.getTime(); - if (!(filesMtimes[file] && mtimeNew && mtimeNew <= filesMtimes[file])) { + if (mtimeNew > Number(filesMtimes[file])) { changed.push(file); } fileDone(); diff --git a/support/testUtils.js b/support/testUtils.js index 3ce7416..cd21da9 100644 --- a/support/testUtils.js +++ b/support/testUtils.js @@ -54,8 +54,12 @@ function readFile(filepath) { return contents; } -function writeFile(filepath, content) { +function writeFile(filepath, content, unixtime) { fs.writeFileSync(filepath, content, {encoding: 'utf8'}); + + if (typeof unixtime !== 'undefined') { + fs.utimesSync(filepath, unixtime, unixtime); + } } module.exports = { diff --git a/test/plugin-test.js b/test/plugin-test.js index 3fdd96e..f8d281b 100644 --- a/test/plugin-test.js +++ b/test/plugin-test.js @@ -84,37 +84,77 @@ test('it rebuilds when output files change', (t) => { }); }); -test('it does not rebuild when input and output files do not change', (t) => { - var bundleFile1 = 'bundle-1.js'; - var dependency1 = path.join(testOutputDir, 'stuff.js'); - var inputContent1 = 'console.log("123")'; +test('when input and output files do not change', (t) => { + var test = t.test; - cleanupTestOutputDir((cleanupErr) => { - t.notOk(cleanupErr, 'clean up test output dir'); + test('it does not rebuild', (t) => { + var bundleFile1 = 'bundle-1.js'; + var dependency1 = path.join(testOutputDir, 'stuff.js'); + var inputContent1 = 'console.log("123")'; - writeFile(entry, `require('${dependency1}');`); - writeFile(dependency1, inputContent1); - var bundleOutputFile = path.join(testOutputDir, bundleFile1); - doBuild(bundleFile1, (build1Err) => { - t.notOk(build1Err, 'built first time'); + cleanupTestOutputDir((cleanupErr) => { + t.notOk(cleanupErr, 'clean up test output dir'); - var output1 = readFile(bundleOutputFile); - t.match(output1, inputContent1, 'built bundle containing initial content'); + writeFile(entry, `require('${dependency1}');`); + writeFile(dependency1, inputContent1); + var bundleOutputFile = path.join(testOutputDir, bundleFile1); + doBuild(bundleFile1, (build1Err) => { + t.notOk(build1Err, 'built first time'); - var mtime1 = fs.statSync(bundleOutputFile).mtime.getTime(); + var output1 = readFile(bundleOutputFile); + t.match(output1, inputContent1, 'built bundle containing initial content'); - doBuild(bundleFile1, build2Err => { - t.notOk(build2Err, 'built second time'); + var mtime1 = fs.statSync(bundleOutputFile).mtime.getTime(); - var mtime2 = fs.statSync(bundleOutputFile).mtime.getTime(); - t.ok(mtime1 === mtime2, 'does not rebuild files'); + doBuild(bundleFile1, build2Err => { + t.notOk(build2Err, 'built second time'); - t.end(); + var mtime2 = fs.statSync(bundleOutputFile).mtime.getTime(); + t.ok(mtime1 === mtime2, 'does not rebuild files'); + + t.end(); + }); + }); + }); + }); + + test('it does not rebuild when a file has Epoch timestamp', (t) => { + // see https://github.com/npm/npm/issues/19968#issuecomment-372799983 for why we need to support this + + var bundleFile1 = 'bundle-1.js'; + var dependency1 = path.join(testOutputDir, 'stuff.js'); + var inputContent1 = 'console.log("123")'; + + cleanupTestOutputDir((cleanupErr) => { + t.notOk(cleanupErr, 'clean up test output dir'); + + writeFile(entry, `require('${dependency1}');`); + writeFile(dependency1, inputContent1, 0); // zero timestamp + var bundleOutputFile = path.join(testOutputDir, bundleFile1); + doBuild(bundleFile1, (build1Err) => { + t.notOk(build1Err, 'built first time'); + + var output1 = readFile(bundleOutputFile); + t.match(output1, inputContent1, 'built bundle containing initial content'); + + var mtime1 = fs.statSync(bundleOutputFile).mtime.getTime(); + + doBuild(bundleFile1, build2Err => { + t.notOk(build2Err, 'built second time'); + + var mtime2 = fs.statSync(bundleOutputFile).mtime.getTime(); + t.ok(mtime1 === mtime2, 'does not rebuild files'); + + t.end(); + }); }); }); }); + + t.end(); }); + function doBuild(filename, done) { webpackConfig.entry = entry;