diff --git a/src/dev/build/lib/__tests__/fs.js b/src/dev/build/lib/__tests__/fs.js index 67b4b35c948cc4..3c0c5153420393 100644 --- a/src/dev/build/lib/__tests__/fs.js +++ b/src/dev/build/lib/__tests__/fs.js @@ -31,6 +31,8 @@ const FOO_TAR_PATH = resolve(FIXTURES, 'foo_dir.tar.gz'); const BAR_TXT_PATH = resolve(FIXTURES, 'foo_dir/bar.txt'); const WORLD_EXECUTABLE = resolve(FIXTURES, 'bin/world_executable'); +const isWindows = /^win/.test(process.platform); + // get the mode of a file as a string, like 777, or 644, function getCommonMode(path) { return statSync(path).mode.toString(8).slice(-3); @@ -184,7 +186,8 @@ describe('dev/build/lib/fs', () => { it('copies the mode of the source file', async () => { const destination = resolve(TMP, 'dest.txt'); await copy(WORLD_EXECUTABLE, destination); - expect(getCommonMode(destination)).to.be('777'); + + expect(getCommonMode(destination)).to.be(isWindows ? '666' : '777'); }); }); @@ -225,8 +228,8 @@ describe('dev/build/lib/fs', () => { resolve(destination, 'foo_dir/foo'), ]); - expect(getCommonMode(resolve(destination, 'bin/world_executable'))).to.be('777'); - expect(getCommonMode(resolve(destination, 'foo_dir/bar.txt'))).to.be('644'); + expect(getCommonMode(resolve(destination, 'bin/world_executable'))).to.be(isWindows ? '666' : '777'); + expect(getCommonMode(resolve(destination, 'foo_dir/bar.txt'))).to.be(isWindows ? '666' : '644'); }); it('applies select globs if specified, ignores dot files', async () => { @@ -270,6 +273,7 @@ describe('dev/build/lib/fs', () => { expect(await read(resolve(destination, 'foo_dir/.bar'))).to.be('dotfile\n'); }); + it('supports atime and mtime', async () => { const destination = resolve(TMP, 'a/b/c/d/e'); const time = new Date(1425298511000); diff --git a/src/dev/build/lib/fs.js b/src/dev/build/lib/fs.js index 1c19a68d7136ae..d6809afded317e 100644 --- a/src/dev/build/lib/fs.js +++ b/src/dev/build/lib/fs.js @@ -129,9 +129,22 @@ export async function copyAll(sourceDir, destination, options = {}) { base: sourceDir, dot, }), - vfs.dest(destination), - ...(Boolean(time) ? [createMapStream(file => utimesAsync(file.path, time, time))] : []), + vfs.dest(destination) ]); + + // we must update access and modified file times after the file copy + // has completed, otherwise the copy action can effect modify times. + if (Boolean(time)) { + await createPromiseFromStreams([ + vfs.src(select, { + buffer: false, + cwd: destination, + base: destination, + dot, + }), + createMapStream(file => utimesAsync(file.path, time, time)) + ]); + } } export async function getFileHash(path, algo) {