From 20026f1b3df75ce39e0e9e4c3e7390621ccd6f47 Mon Sep 17 00:00:00 2001
From: develar <develar@gmail.com>
Date: Sat, 12 Nov 2016 16:35:31 +0100
Subject: [PATCH] feat: more performant and reliable npm rebuild

---
 src/yarn.ts                    | 53 +++++++++++++++++++---------------
 test/src/globTest.ts           |  2 +-
 test/src/helpers/packTester.ts |  2 +-
 yarn.lock                      | 21 ++++++++------
 4 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/src/yarn.ts b/src/yarn.ts
index ef1b92d718e..8da41db73ae 100644
--- a/src/yarn.ts
+++ b/src/yarn.ts
@@ -15,7 +15,7 @@ export async function installOrRebuild(options: BuildMetadata, appDir: string, e
   }
 }
 
-export function getGypEnv(electronVersion: string, arch: string): any {
+export function getGypEnv(electronVersion: string, arch: string) {
   const gypHome = path.join(homedir(), ".electron-gyp")
   return Object.assign({}, process.env, {
     npm_config_disturl: "https://atom.io/download/electron",
@@ -37,10 +37,10 @@ function computeExtraArgs(options: BuildMetadata) {
 
 export function installDependencies(appDir: string, electronVersion: string, arch: string = process.arch, additionalArgs: Array<string>): Promise<any> {
   log(`Installing app dependencies for arch ${arch} to ${appDir}`)
-  let npmExecPath = process.env.npm_execpath || process.env.NPM_CLI_JS
+  let execPath = process.env.npm_execpath || process.env.NPM_CLI_JS
   const npmExecArgs = ["install", "--production"]
 
-  const isYarn = npmExecPath != null && npmExecPath.includes("yarn")
+  const isYarn = isYarnPath(execPath)
   if (!isYarn) {
     if (process.env.NPM_NO_BIN_LINKS === "true") {
       npmExecArgs.push("--no-bin-links")
@@ -48,12 +48,12 @@ export function installDependencies(appDir: string, electronVersion: string, arc
     npmExecArgs.push("--cache-min", "999999999")
   }
 
-  if (npmExecPath == null) {
-    npmExecPath = getPackageToolPath()
+  if (execPath == null) {
+    execPath = getPackageToolPath()
   }
   else {
-    npmExecArgs.unshift(npmExecPath)
-    npmExecPath = process.env.npm_node_execpath || process.env.NODE_EXE || "node"
+    npmExecArgs.unshift(execPath)
+    execPath = process.env.npm_node_execpath || process.env.NODE_EXE || "node"
   }
 
   for (let a of additionalArgs) {
@@ -62,7 +62,7 @@ export function installDependencies(appDir: string, electronVersion: string, arc
     }
   }
 
-  return spawn(npmExecPath, npmExecArgs, {
+  return spawn(execPath, npmExecArgs, {
     cwd: appDir,
     env: getGypEnv(electronVersion, arch),
   })
@@ -115,6 +115,10 @@ function getPackageToolPath() {
   }
 }
 
+function isYarnPath(execPath: string | null) {
+  return execPath != null && path.basename(execPath).startsWith("yarn")
+}
+
 export async function rebuild(appDir: string, electronVersion: string, arch: string = process.arch, additionalArgs: Array<string>) {
   const deps = new Set<string>()
   await dependencies(appDir, false, deps)
@@ -127,27 +131,28 @@ export async function rebuild(appDir: string, electronVersion: string, arch: str
   log(`Rebuilding native production dependencies for arch ${arch}`)
 
   let execPath = process.env.npm_execpath || process.env.NPM_CLI_JS
-  const execArgs = ["run", "install", "--"]
-
+  const execArgs: Array<string> = []
   if (execPath == null) {
     execPath = getPackageToolPath()
   }
   else {
-    execArgs.unshift(execPath)
+    execArgs.push(execPath)
     execPath = process.env.npm_node_execpath || process.env.NODE_EXE || "node"
   }
 
-  const gypHome = path.join(homedir(), ".electron-gyp")
-  const env = Object.assign({}, process.env, {
-    HOME: gypHome,
-    USERPROFILE: gypHome,
-  })
-
-  execArgs.push("--disturl=https://atom.io/download/electron")
-  execArgs.push(`--target=${electronVersion}`)
-  execArgs.push("--runtime=electron")
-  execArgs.push(`--arch=${arch}`)
-  execArgs.push(...additionalArgs)
-
-  await BluebirdPromise.each(nativeDeps, it => spawn(execPath, execArgs, {cwd: it, env: env}))
+  const env = getGypEnv(electronVersion, arch)
+  if (isYarnPath(execPath)) {
+    execArgs.push("run", "install", "--")
+    execArgs.push("--disturl=https://atom.io/download/electron")
+    execArgs.push(`--target=${electronVersion}`)
+    execArgs.push("--runtime=electron")
+    execArgs.push(`--arch=${arch}`)
+    execArgs.push(...additionalArgs)
+    await BluebirdPromise.each(nativeDeps, it => spawn(execPath, execArgs, {cwd: it, env: env}))
+  }
+  else {
+    execArgs.push("rebuild")
+    execArgs.push(...nativeDeps.map(it => path.basename(it)))
+    await spawn(execPath, execArgs, {cwd: appDir, env: env})
+  }
 }
\ No newline at end of file
diff --git a/test/src/globTest.ts b/test/src/globTest.ts
index e717bfee976..ac6dde2505d 100644
--- a/test/src/globTest.ts
+++ b/test/src/globTest.ts
@@ -253,7 +253,7 @@ test("extraResources - one-package", async () => {
     //noinspection SpellCheckingInspection
     await assertPack("test-app-one", {
       // to check NuGet package
-      targets: platform.createTarget(platform === Platform.WINDOWS ? null : DIR_TARGET),
+      targets: platform.createTarget(platform === Platform.WINDOWS ? "squirrel" : DIR_TARGET),
       devMetadata: {
         build: {
           asar: true,
diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts
index 8b64aa71b25..f05548ea613 100755
--- a/test/src/helpers/packTester.ts
+++ b/test/src/helpers/packTester.ts
@@ -92,7 +92,7 @@ export async function assertPack(fixtureName: string, packagerOptions: PackagerO
     if (projectDirCreated != null) {
       await projectDirCreated(projectDir)
       if (checkOptions.npmInstallBefore) {
-        await spawn(process.platform === "win32" ? "yarn.cmd" : "yarn", ["install", "--production"], {
+        await spawn(process.platform === "win32" ? "npm.cmd" : "npm", ["install", "--production", "--cache-min", "999999999", "--no-bin-links"], {
           cwd: projectDir
         })
       }
diff --git a/yarn.lock b/yarn.lock
index e19e6d9f743..e866322108b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1,7 +1,5 @@
 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 # yarn lockfile v1
-
-
 "@develar/semantic-release@^6.3.21":
   version "6.3.23"
   resolved "https://registry.yarnpkg.com/@develar/semantic-release/-/semantic-release-6.3.23.tgz#80c8ecd7369cf4a5c442d59d24bd614c051dd004"
@@ -2447,8 +2445,8 @@ js-tokens@^2.0.0:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5"
 
 js-yaml@^3.4.2, js-yaml@^3.6.1:
-  version "3.6.1"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
   dependencies:
     argparse "^1.0.7"
     esprima "^2.6.0"
@@ -2820,7 +2818,11 @@ minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
 
-minimist@~0.0.1, minimist@0.0.8:
+minimist@~0.0.1:
+  version "0.0.10"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+
+minimist@0.0.8:
   version "0.0.8"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
 
@@ -3453,8 +3455,8 @@ redent@^1.0.0:
     strip-indent "^1.0.1"
 
 regenerate@^1.2.1:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.1.tgz#0300203a5d2fdcf89116dce84275d011f5903f33"
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
 
 regenerator-runtime@^0.9.5:
   version "0.9.6"
@@ -4111,8 +4113,8 @@ which-module@^1.0.0:
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
 
 which@^1.2.9:
-  version "1.2.11"
-  resolved "https://registry.yarnpkg.com/which/-/which-1.2.11.tgz#c8b2eeea6b8c1659fa7c1dd4fdaabe9533dc5e8b"
+  version "1.2.12"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192"
   dependencies:
     isexe "^1.1.1"
 
@@ -4288,3 +4290,4 @@ zip-stream@^1.1.0:
     compress-commons "^1.1.0"
     lodash "^4.8.0"
     readable-stream "^2.0.0"
+