Skip to content

Commit

Permalink
refactor: extract fs util
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Nov 28, 2016
1 parent 71aa620 commit b91c1d1
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 118 deletions.
1 change: 1 addition & 0 deletions .idea/codeStyleSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 4 additions & 63 deletions src/asarUtil.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,20 @@
import { AsarFileInfo, listPackage, statFile, AsarOptions } from "asar-electron-builder"
import { statOrNull, debug, isCi } from "./util/util"
import {
lstat,
readdir,
readFile,
Stats,
createWriteStream,
ensureDir,
createReadStream,
readJson,
writeFile,
realpath,
link
} from "fs-extra-p"
import { debug, isCi } from "./util/util"
import { readFile, Stats, createWriteStream, ensureDir, createReadStream, readJson, writeFile, realpath, link } from "fs-extra-p"
import BluebirdPromise from "bluebird-lst-c"
import * as path from "path"
import { log } from "./util/log"
import { deepAssign } from "./util/deepAssign"
import { Filter } from "./util/filter"
import { walk, statOrNull, CONCURRENCY, MAX_FILE_REQUESTS } from "./util/fs"

const isBinaryFile: any = BluebirdPromise.promisify(require("isbinaryfile"))
const pickle = require ("chromium-pickle-js")
const Filesystem = require("asar-electron-builder/lib/filesystem")
const UINT64 = require("cuint").UINT64

const MAX_FILE_REQUESTS = 8
const concurrency = {concurrency: MAX_FILE_REQUESTS}
const NODE_MODULES_PATTERN = path.sep + "node_modules" + path.sep

export async function walk(initialDirPath: string, consumer?: (file: string, stat: Stats) => void, filter?: Filter): Promise<Array<string>> {
const result: Array<string> = []
const queue: Array<string> = [initialDirPath]
let addDirToResult = false
while (queue.length > 0) {
const dirPath = queue.pop()!
if (addDirToResult) {
result.push(dirPath)
}
else {
addDirToResult = true
}

const childNames = await readdir(dirPath)
childNames.sort()

const dirs: Array<string> = []
await BluebirdPromise.map(childNames, name => {
const filePath = dirPath + path.sep + name
return lstat(filePath)
.then(stat => {
if (filter != null && !filter(filePath, stat)) {
return
}

if (consumer != null) {
consumer(filePath, stat)
}

if (stat.isDirectory()) {
dirs.push(filePath)
}
else {
result.push(filePath)
}
})
}, concurrency)

for (let i = dirs.length - 1; i > -1; i--) {
queue.push(dirs[i])
}
}

return result
}

export async function createAsarArchive(src: string, resourcesPath: string, options: AsarOptions, filter: Filter, unpackPattern: Filter | null): Promise<any> {
// sort files to minimize file change (i.e. asar file is not changed dramatically on small change)
await new AsarPackager(src, resourcesPath, options, unpackPattern).pack(filter)
Expand Down Expand Up @@ -191,7 +132,7 @@ class AsarPackager {
const base = path.join(unpackedDest, it)
await ensureDir(base)
await BluebirdPromise.each(dirToCreate.get(it)!, it => ensureDir(path.join(base, it)))
}, concurrency)
}, CONCURRENCY)
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/cli/create-self-signed-cert.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import yargs from "yargs"
import { printErrorAndExit } from "../util/promise"
import { exec, spawn, unlinkIfExists } from "../util/util"
import { exec, spawn } from "../util/util"
import { getSignVendorPath } from "../windowsCodeSign"
import * as path from "path"
import sanitizeFileName from "sanitize-filename"
import { log } from "../util/log"
import { TmpDir } from "../util/tmp"
import { unlinkIfExists } from "../util/fs"

async function main() {
const args: any = yargs
Expand All @@ -31,7 +32,7 @@ async function main() {
log(`${pfx} created. Please see https://github.com/electron-userland/electron-builder/wiki/Code-Signing how do use it to sign.`)

const certLocation = "Cert:\\LocalMachine\\TrustedPeople"
log(`${pfx} will be imported into ${certLocation} Operation will be succeded only if runned from root. Otherwise import file manually.`)
log(`${pfx} will be imported into ${certLocation} Operation will be succeed only if runned from root. Otherwise import file manually.`)
await spawn("powershell.exe", ["Import-PfxCertificate", "-FilePath", `"${pfx}"`, "-CertStoreLocation", ""])
tmpDir.cleanup()
}
Expand Down
3 changes: 2 additions & 1 deletion src/codeSign.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec, getTempName, isEmptyOrSpaces, isCi, getCacheDirectory, statOrNull } from "./util/util"
import { exec, getTempName, isEmptyOrSpaces, isCi, getCacheDirectory } from "./util/util"
import { deleteFile, outputFile, copy, rename } from "fs-extra-p"
import { download } from "./util/httpRequest"
import * as path from "path"
Expand All @@ -7,6 +7,7 @@ import BluebirdPromise from "bluebird-lst-c"
import { randomBytes } from "crypto"
import { TmpDir } from "./util/tmp"
import { homedir } from "os"
import { statOrNull } from "./util/fs"

export const appleCertificatePrefixes = ["Developer ID Application:", "Developer ID Installer:", "3rd Party Mac Developer Application:", "3rd Party Mac Developer Installer:"]

Expand Down
2 changes: 0 additions & 2 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,6 @@ export interface BuildMetadata {
// deprecated
readonly "app-bundle-id"?: string | null

readonly dereference?: boolean

/*
See [.build.publish](#PublishConfiguration).
*/
Expand Down
20 changes: 9 additions & 11 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AppMetadata, DevMetadata, Platform, PlatformSpecificBuildOptions, Arch,
import BluebirdPromise from "bluebird-lst-c"
import * as path from "path"
import { readdir, remove, rename } from "fs-extra-p"
import { statOrNull, use, unlinkIfExists, isEmptyOrSpaces, asArray, debug } from "./util/util"
import { use, isEmptyOrSpaces, asArray, debug } from "./util/util"
import { Packager } from "./packager"
import { AsarOptions } from "asar-electron-builder"
import { Minimatch } from "minimatch"
Expand All @@ -19,6 +19,7 @@ import { getRepositoryInfo } from "./repositoryInfo"
import { dependencies } from "./yarn"
import { Target } from "./targets/targetFactory"
import { deepAssign } from "./util/deepAssign"
import { statOrNull, unlinkIfExists } from "./util/fs"
import EventEmitter = NodeJS.EventEmitter

export interface PackagerOptions {
Expand Down Expand Up @@ -242,7 +243,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
const filter = defaultMatcher.createFilter(ignoreFiles, rawFilter, excludePatterns.length ? excludePatterns : null)
let promise
if (asarOptions == null) {
promise = copyFiltered(appDir, path.join(resourcesPath, "app"), filter, this.info.devMetadata.build.dereference || this.platform === Platform.WINDOWS)
promise = copyFiltered(appDir, path.join(resourcesPath, "app"), filter, this.platform === Platform.WINDOWS)
}
else {
const unpackPattern = this.getFileMatchers("asarUnpack", appDir, path.join(resourcesPath, "app"), false, fileMatchOptions, platformSpecificBuildOptions)
Expand Down Expand Up @@ -330,16 +331,13 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
if (patterns == null || patterns.length === 0) {
return BluebirdPromise.resolve()
}
else {
const promises: Array<Promise<any>> = []
for (const pattern of patterns) {
if (pattern.isEmpty() || pattern.containsOnlyIgnore()) {
pattern.addAllPattern()
}
promises.push(copyFiltered(pattern.from, pattern.to, pattern.createFilter(), this.platform === Platform.WINDOWS))

return BluebirdPromise.map(patterns, pattern => {
if (pattern.isEmpty() || pattern.containsOnlyIgnore()) {
pattern.addAllPattern()
}
return BluebirdPromise.all(promises)
}
return copyFiltered(pattern.from, pattern.to, pattern.createFilter(), this.platform === Platform.WINDOWS)
})
}

private getFileMatchers(name: "files" | "extraFiles" | "extraResources" | "asarUnpack", defaultSrc: string, defaultDest: string, allowAdvancedMatching: boolean, fileMatchOptions: FileMatchOptions, customBuildOptions: DC): Array<FileMatcher> | null {
Expand Down
3 changes: 2 additions & 1 deletion src/targets/appImage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Arch } from "../metadata"
import * as path from "path"
import { exec, unlinkIfExists } from "../util/util"
import { exec } from "../util/util"
import { open, write, createReadStream, createWriteStream, close, chmod } from "fs-extra-p"
import { LinuxTargetHelper } from "./LinuxTargetHelper"
import { getBin } from "../util/binDownload"
Expand All @@ -9,6 +9,7 @@ import { v1 as uuid1 } from "uuid-1345"
import { LinuxPackager } from "../linuxPackager"
import { log } from "../util/log"
import { Target } from "./targetFactory"
import { unlinkIfExists } from "../util/fs"

const appImageVersion = process.platform === "darwin" ? "AppImage-09-07-16-mac" : "AppImage-09-07-16-linux"
//noinspection SpellCheckingInspection
Expand Down
3 changes: 2 additions & 1 deletion src/targets/dmg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { log, warn } from "../util/log"
import { PlatformPackager } from "../platformPackager"
import { MacOptions, DmgOptions, DmgContent } from "../options/macOptions"
import BluebirdPromise from "bluebird-lst-c"
import { debug, use, exec, statOrNull, isEmptyOrSpaces, spawn, exists } from "../util/util"
import { debug, use, exec, isEmptyOrSpaces, spawn } from "../util/util"
import { copy, unlink, outputFile, remove } from "fs-extra-p"
import { executeFinally } from "../util/promise"
import sanitizeFileName from "sanitize-filename"
import { Arch } from "../metadata"
import { Target } from "./targetFactory"
import { exists, statOrNull } from "../util/fs"

export class DmgTarget extends Target {
private helperDir = path.join(__dirname, "..", "..", "templates", "dmg")
Expand Down
3 changes: 2 additions & 1 deletion src/util/binDownload.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { statOrNull, spawn, debug, debug7zArgs, getTempName, getCacheDirectory } from "./util"
import { spawn, debug, debug7zArgs, getTempName, getCacheDirectory } from "./util"
import { rename, unlink, emptyDir } from "fs-extra-p"
import { download } from "./httpRequest"
import { path7za } from "7zip-bin"
import * as path from "path"
import BluebirdPromise from "bluebird-lst-c"
import { statOrNull } from "./fs"

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

Expand Down
1 change: 0 additions & 1 deletion src/util/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { copy, Stats } from "fs-extra-p"
import { Minimatch } from "minimatch"
import * as path from "path"

// we use relative path to avoid canonical path issue - e.g. /tmp vs /private/tmp
export function copyFiltered(src: string, destination: string, filter: Filter, dereference: boolean): Promise<any> {
return copy(src, destination, {
dereference: dereference,
Expand Down
84 changes: 84 additions & 0 deletions src/util/fs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { unlink, access, stat, Stats, lstat, readdir } from "fs-extra-p"
import { Filter } from "./filter"
import BluebirdPromise from "bluebird-lst-c"
import * as path from "path"

export const MAX_FILE_REQUESTS = 8
export const CONCURRENCY = {concurrency: MAX_FILE_REQUESTS}

export function unlinkIfExists(file: string) {
return unlink(file)
.catch(() => {
// ignore
})
}

export async function statOrNull(file: string): Promise<Stats | null> {
try {
return await stat(file)
}
catch (e) {
if (e.code === "ENOENT") {
return null
}
else {
throw e
}
}
}

export async function exists(file: string): Promise<boolean> {
try {
await access(file)
return true
}
catch (e) {
return false
}
}

export async function walk(initialDirPath: string, consumer?: (file: string, stat: Stats) => void, filter?: Filter): Promise<Array<string>> {
const result: Array<string> = []
const queue: Array<string> = [initialDirPath]
let addDirToResult = false
while (queue.length > 0) {
const dirPath = queue.pop()!
if (addDirToResult) {
result.push(dirPath)
}
else {
addDirToResult = true
}

const childNames = await readdir(dirPath)
childNames.sort()

const dirs: Array<string> = []
await BluebirdPromise.map(childNames, name => {
const filePath = dirPath + path.sep + name
return lstat(filePath)
.then(stat => {
if (filter != null && !filter(filePath, stat)) {
return
}

if (consumer != null) {
consumer(filePath, stat)
}

if (stat.isDirectory()) {
dirs.push(filePath)
}
else {
result.push(filePath)
}
})
}, CONCURRENCY)

for (let i = dirs.length - 1; i > -1; i--) {
queue.push(dirs[i])
}
}

return result
}
34 changes: 2 additions & 32 deletions src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { execFile, spawn as _spawn, ChildProcess, SpawnOptions } from "child_pro
import BluebirdPromise from "bluebird-lst-c"
import { homedir } from "os"
import * as path from "path"
import { readJson, stat, Stats, unlink, access } from "fs-extra-p"
import { readJson } from "fs-extra-p"
import { yellow, red } from "chalk"
import _debug from "debug"
import { warn, log } from "./log"
import { createHash } from "crypto"
import "source-map-support/register"
import { statOrNull } from "./fs"
import Debugger = debug.Debugger

export const debug: Debugger = _debug("electron-builder")
Expand Down Expand Up @@ -182,30 +183,6 @@ function findFromElectronPrebuilt(packageData: any): any {
return null
}

export async function statOrNull(file: string): Promise<Stats | null> {
try {
return await stat(file)
}
catch (e) {
if (e.code === "ENOENT") {
return null
}
else {
throw e
}
}
}

export async function exists(file: string): Promise<boolean> {
try {
await access(file)
return true
}
catch (e) {
return false
}
}

export async function computeDefaultAppDirectory(projectDir: string, userAppDir: string | null | undefined): Promise<string> {
if (userAppDir != null) {
const absolutePath = path.resolve(projectDir, userAppDir)
Expand Down Expand Up @@ -260,13 +237,6 @@ export function isEmptyOrSpaces(s: string | n) {
return s == null || s.trim().length === 0
}

export function unlinkIfExists(file: string) {
return unlink(file)
.catch(() => {
// ignore
})
}

export function asArray<T>(v: n | T | Array<T>): Array<T> {
if (v == null) {
return []
Expand Down
Loading

0 comments on commit b91c1d1

Please sign in to comment.