diff --git a/src/node_file.cc b/src/node_file.cc index 8a09b656e5a1..2ba10c4c739a 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -4207,6 +4207,10 @@ static void CpSyncCopyDir(const FunctionCallbackInfo& args) { if (!success) { return false; } + if (preserve_timestamps && + !CopyUtimes(entry_dir_path, dest_file_path, env)) { + return false; + } } else if (dir_entry.is_regular_file()) { std::filesystem::copy_file( dir_entry.path(), dest_file_path, file_copy_opts, error); @@ -4231,7 +4235,9 @@ static void CpSyncCopyDir(const FunctionCallbackInfo& args) { return true; }; - copy_dir_contents(src_path, dest_path); + if (copy_dir_contents(src_path, dest_path) && preserve_timestamps) { + CopyUtimes(src_path, dest_path, env); + } } BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile( diff --git a/test/parallel/test-fs-cp-sync-preserve-timestamps-dir.mjs b/test/parallel/test-fs-cp-sync-preserve-timestamps-dir.mjs index 20d889075988..06d1c3521478 100644 --- a/test/parallel/test-fs-cp-sync-preserve-timestamps-dir.mjs +++ b/test/parallel/test-fs-cp-sync-preserve-timestamps-dir.mjs @@ -1,5 +1,6 @@ -// This tests that cpSync with a filter preserves directory timestamps -// when preserveTimestamps is true. +// This tests that cpSync preserves directory timestamps +// when preserveTimestamps is true, both on the JS fallback path (with filter) +// and the native fast path (without filter). import '../common/index.mjs'; import { nextdir } from '../common/fs.js'; import assert from 'node:assert'; @@ -40,3 +41,21 @@ assert.strictEqual(srcDirStat.mtime.getTime(), destDirStat.mtime.getTime()); const srcRootStat = statSync(src); const destRootStat = statSync(dest); assert.strictEqual(srcRootStat.mtime.getTime(), destRootStat.mtime.getTime()); + +// Copy with preserveTimestamps and NO filter (to exercise the native fast path). +const destFast = nextdir(); +cpSync(src, destFast, { + recursive: true, + preserveTimestamps: true, +}); + +// Verify file timestamps are preserved. +const destFastFileStat = statSync(join(destFast, 'subdir', 'file.txt')); +assert.strictEqual(srcFileStat.mtime.getTime(), destFastFileStat.mtime.getTime()); + +// Verify directory timestamps are preserved. +const destFastDirStat = statSync(join(destFast, 'subdir')); +assert.strictEqual(srcDirStat.mtime.getTime(), destFastDirStat.mtime.getTime()); + +const destFastRootStat = statSync(destFast); +assert.strictEqual(srcRootStat.mtime.getTime(), destFastRootStat.mtime.getTime());