Repository: nodejs/node
Pull request: src: add new CopyUtimes function to reduce code duplication

<!--
Before submitting a pull request, please read:

- the CONTRIBUTING guide at https://github.com/nodejs/node/blob/HEAD/CONTRIBUTING.md
- the commit message formatting guidelines at
  https://github.com/nodejs/node/blob/HEAD/doc/contributing/pull-requests.md#commit-message-guidelines

For code changes:
1. Include tests for any bug fixes or new features.
2. Update documentation if relevant.
3. Ensure that `make -j4 test` (UNIX), or `vcbuild test` (Windows) passes.

If you believe this PR should be highlighted in the Node.js CHANGELOG
please add the `notable-change` label.

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
-->


Changed files:
filename: src/node_file.cc
patch: @@ -3326,6 +3326,38 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
   }
 }
 
+static bool CopyUtimes(const std::filesystem::path& src,
+                       const std::filesystem::path& dest,
+                       Environment* env) {
+  uv_fs_t req;
+  auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
+
+  auto src_path_str = PathToString(src);
+  int result = uv_fs_stat(nullptr, &req, src_path_str.c_str(), nullptr);
+  if (is_uv_error(result)) {
+    env->ThrowUVException(result, "stat", nullptr, src_path_str.c_str());
+    return false;
+  }
+
+  const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr);
+  const double source_atime = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
+  const double source_mtime = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
+
+  auto dest_file_path_str = PathToString(dest);
+  int utime_result = uv_fs_utime(nullptr,
+                                 &req,
+                                 dest_file_path_str.c_str(),
+                                 source_atime,
+                                 source_mtime,
+                                 nullptr);
+  if (is_uv_error(utime_result)) {
+    env->ThrowUVException(
+        utime_result, "utime", nullptr, dest_file_path_str.c_str());
+    return false;
+  }
+  return true;
+}
+
 static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
   Isolate* isolate = env->isolate();
@@ -3373,22 +3405,7 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {
   }
 
   if (preserve_timestamps) {
-    uv_fs_t req;
-    auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
-    int result = uv_fs_stat(nullptr, &req, *src, nullptr);
-    if (is_uv_error(result)) {
-      return env->ThrowUVException(result, "stat", nullptr, *src);
-    }
-
-    const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr);
-    const double source_atime = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
-    const double source_mtime = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
-
-    int utime_result =
-        uv_fs_utime(nullptr, &req, *dest, source_atime, source_mtime, nullptr);
-    if (is_uv_error(utime_result)) {
-      return env->ThrowUVException(utime_result, "utime", nullptr, *dest);
-    }
+    CopyUtimes(*src, *dest, env);
   }
 }
 
@@ -3569,37 +3586,9 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
           return false;
         }
 
-        if (preserve_timestamps) {
-          uv_fs_t req;
-          auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
-
-          auto dir_entry_path_str = PathToString(dir_entry.path());
-          int result =
-              uv_fs_stat(nullptr, &req, dir_entry_path_str.c_str(), nullptr);
-          if (is_uv_error(result)) {
-            env->ThrowUVException(
-                result, "stat", nullptr, dir_entry_path_str.c_str());
-            return false;
-          }
-
-          const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr);
-          const double source_atime =
-              s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
-          const double source_mtime =
-              s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
-
-          auto dest_file_path_str = PathToString(dest_file_path);
-          int utime_result = uv_fs_utime(nullptr,
-                                         &req,
-                                         dest_file_path_str.c_str(),
-                                         source_atime,
-                                         source_mtime,
-                                         nullptr);
-          if (is_uv_error(utime_result)) {
-            env->ThrowUVException(
-                utime_result, "utime", nullptr, dest_file_path_str.c_str());
-            return false;
-          }
+        if (preserve_timestamps &&
+            !CopyUtimes(dir_entry.path(), dest_file_path, env)) {
+          return false;
         }
       }
     }