Skip to content

Commit

Permalink
refactor: move doGetBin implementation to app-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Feb 7, 2018
1 parent 7a37cef commit 8363b2f
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 223 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
"////": "All typings are added into root `package.json` to avoid duplication errors in the IDE compiler (several `node.d.ts` files).",
"dependencies": {
"7zip-bin": "~3.1.0",
"app-builder-bin": "1.0.5",
"app-builder-bin": "1.1.0",
"archiver": "^2.1.1",
"async-exit-hook": "^2.0.1",
"aws-sdk": "^2.188.0",
"aws-sdk": "^2.190.0",
"bluebird-lst": "^1.0.5",
"chalk": "^2.3.0",
"chromium-pickle-js": "^0.2.0",
Expand Down Expand Up @@ -95,7 +95,7 @@
"gitbook-plugin-github": "^2.0.0",
"gitbook-plugin-github-buttons": "^3.0.0",
"globby": "^7.1.1",
"jest-cli": "^22.1.4",
"jest-cli": "^22.2.1",
"jest-junit": "^3.5.0",
"jsdoc-to-markdown": "^4.0.1",
"path-sort": "^0.1.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/builder-util/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"out"
],
"dependencies": {
"app-builder-bin": "1.0.5",
"app-builder-bin": "1.1.0",
"temp-file": "^3.1.1",
"fs-extra-p": "^4.5.0",
"is-ci": "^1.1.0",
Expand Down
71 changes: 22 additions & 49 deletions packages/builder-util/src/binDownload.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,45 @@
import { path7za } from "7zip-bin"
import { appBuilderPath } from "app-builder-bin"
import { emptyDir, rename, unlink } from "fs-extra-p"
import * as path from "path"
import { getTempName } from "temp-file"
import { statOrNull } from "./fs"
import { debug7zArgs, getCacheDirectory, log, spawn } from "./util"
import { spawn } from "./util"

const versionToPromise = new Map<string, Promise<string>>()

export function download(url: string, output: string, checksum?: string | null): Promise<void> {
const args = ["download", "--url", url, "--output", output]
if (checksum != null) {
args.push("--sha512", checksum)
}
return spawn(appBuilderPath, args)
}

export function getBinFromGithub(name: string, version: string, checksum: string): Promise<string> {
const dirName = `${name}-${version}`
return getBin(name, dirName, `https://github.com/electron-userland/electron-builder-binaries/releases/download/${dirName}/${dirName}.7z`, checksum)
return getBin(dirName, `https://github.com/electron-userland/electron-builder-binaries/releases/download/${dirName}/${dirName}.7z`, checksum)
}

export function getBin(name: string, dirName: string, url: string, checksum: string): Promise<string> {
let promise = versionToPromise.get(dirName)
export function getBin(name: string, url: string, checksum: string): Promise<string> {
let promise = versionToPromise.get(name)
// if rejected, we will try to download again
if (promise != null) {
return promise
}

promise = doGetBin(name, dirName, url, checksum)
versionToPromise.set(dirName, promise)
promise = doGetBin(name, url, checksum)
versionToPromise.set(name, promise)
return promise
}

export function download(url: string, output: string, checksum?: string | null): Promise<void> {
const args = ["download", "--url", url, "--output", output]
function doGetBin(name: string, url: string, checksum: string): Promise<string> {
const args = ["download-artifact", "--url", url, "--name", name]
if (checksum != null) {
args.push("--sha512", checksum)
}
return spawn(appBuilderPath, args)
}

// we cache in the global location - in the home dir, not in the node_modules/.cache (https://www.npmjs.com/package/find-cache-dir) because
// * don't need to find node_modules
// * don't pollute user project dir (important in case of 1-package.json project structure)
// * simplify/speed-up tests (don't download fpm for each test project)
async function doGetBin(name: string, dirName: string, url: string, checksum: string): Promise<string> {
const cachePath = path.join(getCacheDirectory(), name)
const dirPath = path.join(cachePath, dirName)

const logFlags = {path: dirPath}

const dirStat = await statOrNull(dirPath)
if (dirStat != null && dirStat.isDirectory()) {
log.debug(logFlags, "found existing")
return dirPath
}

log.info({...logFlags, url}, "downloading")

// 7z cannot be extracted from the input stream, temp file is required
const tempUnpackDir = path.join(cachePath, getTempName())
const archiveName = `${tempUnpackDir}.7z`
// 7z doesn't create out dir, so, we don't create dir in parallel to download - dir creation will create parent dirs for archive file also
await emptyDir(tempUnpackDir)
await download(url, archiveName, checksum)
await spawn(path7za, debug7zArgs("x").concat(archiveName, `-o${tempUnpackDir}`), {
cwd: cachePath,
return spawn(appBuilderPath, args, {
env: {
...process.env,
SZA_PATH: path7za,
},
stdio: ["ignore", "pipe", "inherit"]
})

await Promise.all([
rename(tempUnpackDir, dirPath)
.catch(e => log.debug({...logFlags, tempUnpackDir, e}, `cannot move downloaded into final location (another process downloaded faster?)`)),
unlink(archiveName),
])

log.debug(logFlags, `downloaded`)
return dirPath
}
36 changes: 7 additions & 29 deletions packages/builder-util/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ChildProcess, execFile, ExecFileOptions, spawn as _spawn, SpawnOptions
import { createHash } from "crypto"
import _debug from "debug"
import { safeDump } from "js-yaml"
import { homedir, tmpdir } from "os"
import * as path from "path"
import "source-map-support/register"
import { debug, log } from "./log"
Expand Down Expand Up @@ -147,8 +146,8 @@ export function doSpawn(command: string, args: Array<string>, options?: SpawnOpt

options.env = getProcessEnv(options.env)

const isDebugEnabled = extraOptions == null || extraOptions.isDebugEnabled == null ? debug.enabled : extraOptions.isDebugEnabled
if (options.stdio == null) {
const isDebugEnabled = extraOptions == null || extraOptions.isDebugEnabled == null ? debug.enabled : extraOptions.isDebugEnabled
// do not ignore stdout/stderr if not debug, because in this case we will read into buffer and print on error
options.stdio = [extraOptions != null && extraOptions.isPipeInput ? "pipe" : "ignore", isDebugEnabled ? "inherit" : "pipe", isDebugEnabled ? "inherit" : "pipe"]
}
Expand Down Expand Up @@ -178,7 +177,7 @@ export function spawnAndWrite(command: string, args: Array<string>, data: string
const childProcess = doSpawn(command, args, options, {isPipeInput: true, isDebugEnabled})
const timeout = setTimeout(() => childProcess.kill(), 4 * 60 * 1000)
return new BluebirdPromise<any>((resolve, reject) => {
handleProcess("close", childProcess, command, () => {
handleProcess("close", childProcess, command, false, () => {
try {
clearTimeout(timeout)
}
Expand All @@ -200,15 +199,16 @@ export function spawnAndWrite(command: string, args: Array<string>, data: string

export function spawn(command: string, args?: Array<string> | null, options?: SpawnOptions, extraOptions?: ExtraSpawnOptions): Promise<any> {
return new BluebirdPromise<any>((resolve, reject) => {
handleProcess("close", doSpawn(command, args || [], options, extraOptions), command, resolve, reject)
const isCollectOutput = options != null && (options.stdio === "pipe" || (Array.isArray(options.stdio) && options.stdio.length === 3 && options.stdio[1] === "pipe"))
handleProcess("close", doSpawn(command, args || [], options, extraOptions), command, isCollectOutput, resolve, reject)
})
}

export function handleProcess(event: string, childProcess: ChildProcess, command: string, resolve: ((value?: any) => void) | null, reject: (reason?: any) => void) {
function handleProcess(event: string, childProcess: ChildProcess, command: string, isCollectOutput: boolean, resolve: ((value?: any) => void) | null, reject: (reason?: any) => void) {
childProcess.on("error", reject)

let out = ""
if (!debug.enabled && childProcess.stdout != null) {
if (isCollectOutput && childProcess.stdout != null) {
childProcess.stdout.on("data", (data: string) => {
out += data
})
Expand All @@ -232,7 +232,7 @@ export function handleProcess(event: string, childProcess: ChildProcess, command

if (code === 0) {
if (resolve != null) {
resolve()
resolve(out)
}
}
else {
Expand Down Expand Up @@ -265,28 +265,6 @@ export function isTokenCharValid(token: string) {
return /^[\w\/=+-]+$/.test(token)
}

export function getCacheDirectory(): string {
const env = process.env.ELECTRON_BUILDER_CACHE
if (!isEmptyOrSpaces(env)) {
return env!
}

if (process.platform === "darwin") {
return path.join(homedir(), "Library", "Caches", "electron-builder")
}

const localappdata = process.env.LOCALAPPDATA
if (process.platform === "win32" && localappdata != null) {
// https://github.com/electron-userland/electron-builder/issues/1164
if (localappdata.toLowerCase().includes("\\windows\\system32\\") || (process.env.USERNAME || "").toLowerCase() === "system") {
return path.join(tmpdir(), "electron-builder-cache")
}
return path.join(localappdata, "electron-builder", "cache")
}

return path.join(homedir(), ".cache", "electron-builder")
}

// fpm bug - rpm build --description is not escaped, well... decided to replace quite to smart quote
// http://leancrew.com/all-this/2010/11/smart-quotes-in-javascript/
export function smarten(s: string): string {
Expand Down
2 changes: 1 addition & 1 deletion packages/electron-builder-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"homepage": "https://github.com/electron-userland/electron-builder",
"dependencies": {
"7zip-bin": "~3.1.0",
"app-builder-bin": "1.0.5",
"app-builder-bin": "1.1.0",
"async-exit-hook": "^2.0.1",
"bluebird-lst": "^1.0.5",
"chromium-pickle-js": "^0.2.0",
Expand Down
16 changes: 10 additions & 6 deletions packages/electron-builder-lib/src/codeSign.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { appBuilderPath } from "app-builder-bin"
import BluebirdPromise from "bluebird-lst"
import { exec, getCacheDirectory, InvalidConfigurationError, isEmptyOrSpaces, isEnvTrue, isMacOsSierra, isPullRequest, log, TmpDir } from "builder-util"
import { exec, InvalidConfigurationError, isEmptyOrSpaces, isEnvTrue, isMacOsSierra, isPullRequest, log, TmpDir } from "builder-util"
import { copyFile, statOrNull, unlinkIfExists } from "builder-util/out/fs"
import { Fields, Logger } from "builder-util/out/log"
import { randomBytes } from "crypto"
Expand Down Expand Up @@ -132,16 +132,15 @@ export async function downloadCertificate(urlOrBase64: string, tmpDir: TmpDir, c
}
}

const bundledCertKeychainAdded = new Lazy<void>(createCustomCertKeychain)

// "Note that filename will not be searched to resolve the signing identity's certificate chain unless it is also on the user's keychain search list."
// but "security list-keychains" doesn't support add - we should 1) get current list 2) set new list - it is very bad http://stackoverflow.com/questions/10538942/add-a-keychain-to-search-list
// "overly complicated and introduces a race condition."
// https://github.com/electron-userland/electron-builder/issues/398
async function createCustomCertKeychain() {
const bundledCertKeychainAdded = new Lazy<void>(async () => {
// copy to temp and then atomic rename to final path
const tmpKeychainPath = path.join(getCacheDirectory(), getTempName("electron-builder-root-certs"))
const keychainPath = path.join(getCacheDirectory(), "electron-builder-root-certs.keychain")
const cacheDir = getCacheDirectory()
const tmpKeychainPath = path.join(cacheDir, getTempName("electron-builder-root-certs"))
const keychainPath = path.join(cacheDir, "electron-builder-root-certs.keychain")
const results = await Promise.all<any>([
listUserKeychains(),
copyFile(path.join(__dirname, "..", "certs", "root_certs.keychain"), tmpKeychainPath)
Expand All @@ -151,6 +150,11 @@ async function createCustomCertKeychain() {
if (!list.includes(keychainPath)) {
await exec("security", ["list-keychains", "-d", "user", "-s", keychainPath].concat(list))
}
})

function getCacheDirectory(): string {
const env = process.env.ELECTRON_BUILDER_CACHE
return isEmptyOrSpaces(env) ? path.join(homedir(), "Library", "Caches", "electron-builder") : env!!
}

function listUserKeychains(): Promise<Array<string>> {
Expand Down
2 changes: 1 addition & 1 deletion packages/electron-builder-lib/src/targets/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,6 @@ export function getTool(descriptor: ToolDescriptor): Promise<string> {
const name = descriptor.name
const repository = descriptor.repository || "electron-userland/electron-builder-binaries"
const tagPrefix = descriptor.repository == null ? `${name}-` : "v"
return getBin(name, `${name}-v${version}-${process.arch}`, `https://github.com/${repository}/releases/download/${tagPrefix}${version}/${name}-v${version}-${platform.buildConfigurationKey}${archQualifier}.7z`, checksum)
return getBin(`${name}-${version}-${process.arch}`, `https://github.com/${repository}/releases/download/${tagPrefix}${version}/${name}-v${version}-${platform.buildConfigurationKey}${archQualifier}.7z`, checksum)
.then(it => path.join(it, `${name}${platform === Platform.WINDOWS ? ".exe" : ""}`))
}
2 changes: 1 addition & 1 deletion packages/electron-publisher-s3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
],
"dependencies": {
"fs-extra-p": "^4.5.0",
"aws-sdk": "^2.188.0",
"aws-sdk": "^2.190.0",
"mime": "^2.2.0",
"electron-publish": "~0.0.0-semantic-release",
"builder-util": "^0.0.0-semantic-release",
Expand Down
Loading

0 comments on commit 8363b2f

Please sign in to comment.