diff --git a/src/node_file.cc b/src/node_file.cc index a76bbf510983f3..a12bb9e1a94ad7 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -3060,7 +3060,9 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo& args) { bool dest_exists = !error_code && dest_status.type() != std::filesystem::file_type::not_found; - bool src_is_dir = src_status.type() == std::filesystem::file_type::directory; + bool src_is_dir = + (src_status.type() == std::filesystem::file_type::directory) || + (dereference && src_status.type() == std::filesystem::file_type::symlink); if (!error_code) { // Check if src and dest are identical. diff --git a/test/parallel/test-fs-cp.mjs b/test/parallel/test-fs-cp.mjs index 63bc813ae226c7..c888b5c30e042d 100644 --- a/test/parallel/test-fs-cp.mjs +++ b/test/parallel/test-fs-cp.mjs @@ -119,6 +119,23 @@ function nextdir() { } +// It overrides target directory with what symlink points to, when dereference is true. +{ + const src = nextdir(); + const symlink = nextdir(); + const dest = nextdir(); + mkdirSync(src, mustNotMutateObjectDeep({ recursive: true })); + writeFileSync(join(src, 'foo.js'), 'foo', 'utf8'); + symlinkSync(src, symlink); + + mkdirSync(dest, mustNotMutateObjectDeep({ recursive: true })); + + cpSync(symlink, dest, mustNotMutateObjectDeep({ dereference: true, recursive: true })); + const destStat = lstatSync(dest); + assert(!destStat.isSymbolicLink()); + assertDirEquivalent(src, dest); +} + // It throws error when verbatimSymlinks is not a boolean. { const src = './test/fixtures/copy/kitchen-sink';