From e83d90a8f0ccac1efb0f8818a4d85a686e7ccdf1 Mon Sep 17 00:00:00 2001
From: Julien Roncaglia <julien@roncaglia.fr>
Date: Mon, 20 Mar 2017 18:45:11 +0100
Subject: [PATCH] Avoid node issue with utimes on Windows

Lot of nodejs versions are buggy on windows regarding utime : It's not
setting the milliseconds part.

Issue: https://github.com/nodejs/node/issues/2069

With this change file date comparison is now done with only seconds
precision on windows when copying files. It make linking fast again under
windows.
---
 src/util/fs.js | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/util/fs.js b/src/util/fs.js
index 0bd23c7cf5..547294a0fd 100644
--- a/src/util/fs.js
+++ b/src/util/fs.js
@@ -80,6 +80,29 @@ type CopyOptions = {
   artifactFiles: Array<string>,
 };
 
+let fileDatesEqual = (a: Date, b: Date) => {
+  return a.getTime() === b.getTime();
+};
+
+if (os.platform() === 'win32') {
+  fileDatesEqual = (a: Date, b: Date) => {
+    const aTime = a.getTime();
+    const bTime = b.getTime();
+    const aTimeSec = Math.floor(aTime / 1000);
+    const bTimeSec = Math.floor(bTime / 1000);
+
+    // See https://github.com/nodejs/node/issues/2069
+    // Some versions of Node on windows zero the milliseconds when utime is used
+    // So if any of the time has a milliseconds part of zero we suspect that the
+    // bug is present and compare only seconds.
+    if ((aTime - aTimeSec * 1000 === 0) || (bTime - bTimeSec * 1000 === 0)) {
+      return aTimeSec === bTimeSec;
+    }
+
+    return aTime === bTime;
+  };
+}
+
 async function buildActionsForCopy(
   queue: CopyQueue,
   events: CopyOptions,
@@ -162,7 +185,7 @@ async function buildActionsForCopy(
         }
       }
 
-      if (bothFiles && srcStat.size === destStat.size && +srcStat.mtime === +destStat.mtime) {
+      if (bothFiles && srcStat.size === destStat.size && fileDatesEqual(srcStat.mtime, destStat.mtime)) {
         // we can safely assume this is the same file
         onDone();
         reporter.verbose(reporter.lang('verboseFileSkip', src, dest, srcStat.size, +srcStat.mtime));