From 58016ffac5ed9338b63ecc2a63710f5027362bae Mon Sep 17 00:00:00 2001 From: Vlad Filippov Date: Sat, 23 Apr 2022 16:28:10 -0400 Subject: [PATCH] Patch up race condition in symlink copying. --- CHANGELOG | 4 ++++ lib/grunt/file.js | 9 ++------- test/grunt/file_test.js | 10 +++++++++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bd1848ca..17bb4b7f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +v1.5.3 + date: 2022-04-23 + changes: + - Patch up race condition in symlink copying. v1.5.2 date: 2022-04-12 changes: diff --git a/lib/grunt/file.js b/lib/grunt/file.js index 604736cd..82863f35 100644 --- a/lib/grunt/file.js +++ b/lib/grunt/file.js @@ -294,11 +294,6 @@ file.write = function(filepath, contents, options) { // processing content, writing output. // Handles symlinks by coping them as files or directories. file.copy = function copy(srcpath, destpath, options) { - if (file.isLink(destpath)) { - // in case destpath is a symlink, avoid following the symlink, instead overwrite it later - fs.unlinkSync(destpath); - } - if (file.isLink(srcpath)) { file._copySymbolicLink(srcpath, destpath); } else if (file.isDir(srcpath)) { @@ -338,8 +333,8 @@ file._copy = function(srcpath, destpath, options) { } } // Abort copy if the process function returns false. - if (contents === false) { - grunt.verbose.writeln('Write aborted.'); + if (contents === false || file.isLink(destpath)) { + grunt.verbose.writeln('Write aborted. Either the process function returned false or the destination is a symlink'); } else { file.write(destpath, contents, readWriteOptions); } diff --git a/test/grunt/file_test.js b/test/grunt/file_test.js index 0448f305..eafc5774 100644 --- a/test/grunt/file_test.js +++ b/test/grunt/file_test.js @@ -916,5 +916,13 @@ exports.file = { test.ok(fs.lstatSync(path.join(destdir.path, path.basename(fixtures))).isSymbolicLink()); test.done(); }, - } + }, + 'symbolicLinkDestError': function(test) { + test.expect(1); + var tmpfile = new Tempdir(); + fs.symlinkSync(path.resolve('test/fixtures/octocat.png'), path.join(tmpfile.path, 'octocat.png'), 'file'); + grunt.file.copy(path.resolve('test/fixtures/octocat.png'), path.join(tmpfile.path, 'octocat.png')); + test.ok(fs.lstatSync(path.join(tmpfile.path, 'octocat.png')).isSymbolicLink()); + test.done(); + }, };