diff --git a/e2e/nx-misc/src/extras.test.ts b/e2e/nx-misc/src/extras.test.ts index 9e1812dfb092b..f15ff9497c29b 100644 --- a/e2e/nx-misc/src/extras.test.ts +++ b/e2e/nx-misc/src/extras.test.ts @@ -1,4 +1,5 @@ import { + checkFilesExist, cleanupProject, isNotWindows, newProject, @@ -221,5 +222,46 @@ describe('Extra Nx Misc Tests', () => { }) ).not.toThrow(); }, 1000000); + + it('should handle caching output directories containing trailing slashes', async () => { + // this test relates to https://github.com/nrwl/nx/issues/10549 + // 'cp -a /path/dir/ dest/' operates differently to 'cp -a /path/dir dest/' + // --> which means actual build works but subsequent populate from cache (using cp -a) does not + // --> the fix is to remove trailing slashes to ensure consistent & expected behaviour + + const mylib = uniq('lib'); + + const folder = `dist/libs/${mylib}/some-folder`; + + runCLI(`generate @nrwl/workspace:lib ${mylib}`); + + runCLI( + `generate @nrwl/workspace:run-commands build --command=echo --outputs=${folder}/ --project=${mylib}` + ); + + const commands = [ + process.platform === 'win32' + ? `mkdir ${folder}` // Windows + : `mkdir -p ${folder}`, + `echo dummy > ${folder}/dummy.txt`, + ]; + updateProjectConfig(mylib, (config) => { + delete config.targets.build.options.command; + config.targets.build.options = { + ...config.targets.build.options, + parallel: false, + commands: commands, + }; + return config; + }); + + // confirm that it builds correctly + runCLI(`build ${mylib}`); + checkFilesExist(`${folder}/dummy.txt`); + + // confirm that it populates correctly from the cache + runCLI(`build ${mylib}`); + checkFilesExist(`${folder}/dummy.txt`); + }, 120000); }); }); diff --git a/packages/nx/src/tasks-runner/cache.ts b/packages/nx/src/tasks-runner/cache.ts index 431d070aeaa50..04fcc6d1c0473 100644 --- a/packages/nx/src/tasks-runner/cache.ts +++ b/packages/nx/src/tasks-runner/cache.ts @@ -181,6 +181,11 @@ export class Cache { } private async copy(src: string, destination: string): Promise { + // 'cp -a /path/dir/ dest/' operates differently to 'cp -a /path/dir dest/' + // --> which means actual build works but subsequent populate from cache (using cp -a) does not + // --> the fix is to remove trailing slashes to ensure consistent & expected behaviour + src = src.replace(/[\/\\]$/, ''); + if (this.useFsExtraToCopyAndRemove) { return copy(src, destination); }