Skip to content

Commit

Permalink
fix: Bump electron-wininstaller-fixed to Squirrel 1.4.4
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Aug 12, 2016
1 parent 8665ef4 commit 8008734
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 43 deletions.
2 changes: 2 additions & 0 deletions .idea/dictionaries/develar.xml

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

2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
osx_image: xcode7.3
osx_image: xcode8

matrix:
include:
Expand Down
5 changes: 0 additions & 5 deletions docker/winSign.sh

This file was deleted.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"dependencies": {
"7zip-bin": "^1.0.6",
"ansi-escapes": "^1.4.0",
"archiver": "^1.0.1",
"archiver-utils": "^1.2.0",
"asar-electron-builder": "^0.13.2",
"bluebird": "^3.4.1",
"chalk": "^1.1.3",
Expand All @@ -69,7 +71,6 @@
"debug": "^2.2.0",
"electron-download": "^2.1.2",
"electron-osx-sign": "^0.4.0-beta4",
"electron-winstaller-fixed": "~4.0.0",
"extract-zip": "^1.5.0",
"fs-extra-p": "^1.0.6",
"hosted-git-info": "^2.1.5",
Expand Down Expand Up @@ -102,7 +103,6 @@
]
},
"devDependencies": {
"path-sort": "^0.1.0",
"@develar/semantic-release": "^6.3.6",
"@types/debug": "0.0.28",
"@types/mime": "0.0.28",
Expand All @@ -117,6 +117,7 @@
"decompress-zip": "^0.3.0",
"diff": "^2.2.3",
"json8": "^0.9.2",
"path-sort": "^0.1.0",
"pre-git": "^3.10.0",
"ts-babel": "^1.0.4",
"tslint": "^3.14.0-dev.1",
Expand Down
6 changes: 3 additions & 3 deletions src/targets/nsis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Arch, NsisOptions } from "../metadata"
import { debug, doSpawn, handleProcess, use } from "../util/util"
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
import { getBin } from "../util/binDownload"
import { getBinFromBintray } from "../util/binDownload"
import { v5 as uuid5 } from "uuid-1345"
import { Target } from "../platformPackager"
import { archiveApp } from "./archive"
Expand All @@ -14,14 +14,14 @@ import semver = require("semver")
//noinspection JSUnusedLocalSymbols
const __awaiter = require("../util/awaiter")

const NSIS_VERSION = "nsis-3.0.0"
const NSIS_VERSION = "3.0.0"
//noinspection SpellCheckingInspection
const NSIS_SHA2 = "7741089f3ca13de879f87836156ef785eab49844cacbeeabaeaefd1ade325ee7"

//noinspection SpellCheckingInspection
const ELECTRON_BUILDER_NS_UUID = "50e065bc-3134-11e6-9bab-38c9862bdaf3"

const nsisPathPromise = getBin("nsis", NSIS_VERSION, `https://dl.bintray.com/electron-userland/bin/${NSIS_VERSION}.7z`, NSIS_SHA2)
const nsisPathPromise = getBinFromBintray("nsis", NSIS_VERSION, NSIS_SHA2)

export default class NsisTarget extends Target {
private readonly options: NsisOptions
Expand Down
250 changes: 250 additions & 0 deletions src/targets/squirrelPack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
import { emptyDir, copy, createWriteStream, unlink } from "fs-extra-p"
import { spawn, exec } from "../util/util"
import { debug } from "../util/util"
import { WinPackager } from "../winPackager"

const archiverUtil = require("archiver-utils")
const archiver = require("archiver")

//noinspection JSUnusedLocalSymbols
const __awaiter = require("../util/awaiter")

export function convertVersion(version: string): string {
const parts = version.split("-")
const mainVersion = parts.shift()
if (parts.length > 0) {
return [mainVersion, parts.join("-").replace(/\./g, "")].join("-")
}
else {
return mainVersion!
}
}

function syncReleases(outputDirectory: string, options: SquirrelOptions) {
const args = prepareArgs(["-u", options.remoteReleases!, "-r", outputDirectory], path.join(options.vendorPath, "SyncReleases.exe"))
if (options.remoteToken) {
args.push("-t", options.remoteToken)
}
return spawn(process.platform === "win32" ? path.join(options.vendorPath, "SyncReleases.exe") : "mono", args)
}

export interface SquirrelOptions {
vendorPath: string
remoteReleases?: string
remoteToken?: string
loadingGif?: string
productName?: string
name: string
packageCompressionLevel?: number
version: string
msi?: any

owners?: string
description?: string
iconUrl?: string
authors?: string
extraMetadataSpecs?: string
copyright?: string
}

export async function buildInstaller(options: SquirrelOptions, outputDirectory: string, stageDir: string, setupExe: string, packager: WinPackager, appOutDir: string) {
const appUpdate = path.join(stageDir, "Update.exe")
const promises = [
copy(path.join(options.vendorPath, "Update.exe"), appUpdate)
.then(() => packager.sign(appUpdate)),
emptyDir(outputDirectory)
]
if (options.remoteReleases) {
promises.push(syncReleases(outputDirectory, options))
}
await BluebirdPromise.all(promises)

const embeddedArchiveFile = path.join(stageDir, "setup.zip")
const embeddedArchive = archiver("zip", {zlib: {level: options.packageCompressionLevel == null ? 6 : options.packageCompressionLevel}})
const embeddedArchiveOut = createWriteStream(embeddedArchiveFile)
const embeddedArchivePromise = new BluebirdPromise(function (resolve, reject) {
embeddedArchive.on("error", reject)
embeddedArchiveOut.on("close", resolve)
})
embeddedArchive.pipe(embeddedArchiveOut)

embeddedArchive.file(appUpdate, {name: "Update.exe"})
embeddedArchive.file(options.loadingGif ? path.resolve(options.loadingGif) : path.join(__dirname, "..", "..", "templates", "install-spinner.gif"), {name: "background.gif"})

const version = convertVersion(options.version)
const packageName = `${options.name}-${version}-full.nupkg`
const nupkgPath = path.join(outputDirectory, packageName)
const setupPath = path.join(outputDirectory, setupExe || `${options.name || options.productName}Setup.exe`)

await BluebirdPromise.all<any>([
pack(options, appOutDir, appUpdate, nupkgPath, version, options.packageCompressionLevel),
copy(path.join(options.vendorPath, "Setup.exe"), setupPath),
])

embeddedArchive.file(nupkgPath, {name: packageName})

const releaseEntry = await releasify(options, nupkgPath, outputDirectory, packageName)

embeddedArchive.append(releaseEntry, {name: "RELEASES"})
embeddedArchive.finalize()
await embeddedArchivePromise

const writeZipToSetup = path.join(options.vendorPath, "WriteZipToSetup.exe")
await exec(process.platform === "win32" ? writeZipToSetup : "wine", prepareArgs([setupPath, embeddedArchiveFile], writeZipToSetup))

await packager.signAndEditResources(setupPath)
if (options.msi && process.platform === "win32") {
const outFile = setupExe.replace(".exe", ".msi")
await msi(options, nupkgPath, setupPath, outputDirectory, outFile)
await packager.signAndEditResources(path.join(outputDirectory, outFile))
}
}

async function pack(options: SquirrelOptions, directory: string, updateFile: string, outFile: string, version: string, packageCompressionLevel?: number) {
const archive = archiver("zip", {zlib: {level: packageCompressionLevel == null ? 9 : packageCompressionLevel}})
// const archiveOut = createWriteStream('/Users/develar/test.zip')
const archiveOut = createWriteStream(outFile)
const archivePromise = new BluebirdPromise(function (resolve, reject) {
archive.on("error", reject)
archiveOut.on("close", resolve)
})
archive.pipe(archiveOut)

const author = options.authors || options.owners
const copyright = options.copyright || `Copyright © ${new Date().getFullYear()} ${author}`
const nuspecContent = `<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>${options.name}</id>
<version>${version}</version>
<title>${options.productName}</title>
<authors>${author}</authors>
<owners>${options.owners || options.authors}</owners>
<iconUrl>${options.iconUrl}</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>${options.description}</description>
<copyright>${copyright}</copyright>${options.extraMetadataSpecs || ""}
</metadata>
</package>`
debug(`Created NuSpec file:\n${nuspecContent}`)
archive.append(nuspecContent.replace(/\n/, "\r\n"), {name: `${encodeURI(options.name).replace(/%5B/g, "[").replace(/%5D/g, "]")}.nuspec`})

//noinspection SpellCheckingInspection
archive.append(`<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.microsoft.com/packaging/2010/07/manifest" Target="/${options.name}.nuspec" Id="Re0" />
<Relationship Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="/package/services/metadata/core-properties/1.psmdcp" Id="Re1" />
</Relationships>`.replace(/\n/, "\r\n"), {name: ".rels", prefix: "_rels"})

//noinspection SpellCheckingInspection
archive.append(`<?xml version="1.0" encoding="utf-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
<Default Extension="nuspec" ContentType="application/octet" />
<Default Extension="pak" ContentType="application/octet" />
<Default Extension="asar" ContentType="application/octet" />
<Default Extension="bin" ContentType="application/octet" />
<Default Extension="dll" ContentType="application/octet" />
<Default Extension="exe" ContentType="application/octet" />
<Default Extension="dat" ContentType="application/octet" />
<Default Extension="psmdcp" ContentType="application/vnd.openxmlformats-package.core-properties+xml" />
<Override PartName="/lib/net45/LICENSE" ContentType="application/octet" />
<Default Extension="diff" ContentType="application/octet" />
<Default Extension="bsdiff" ContentType="application/octet" />
<Default Extension="shasum" ContentType="text/plain" />
</Types>`.replace(/\n/, "\r\n"), {name: "[Content_Types].xml"})

archive.append(`<?xml version="1.0" encoding="utf-8"?>
<coreProperties xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.openxmlformats.org/package/2006/metadata/core-properties">
<dc:creator>${author}</dc:creator>
<dc:description>${options.description}</dc:description>
<dc:identifier>${options.name}</dc:identifier>
<version>${version}</version>
<keywords/>
<dc:title>${options.productName}</dc:title>
<lastModifiedBy>NuGet, Version=2.8.50926.602, Culture=neutral, PublicKeyToken=null;Microsoft Windows NT 6.2.9200.0;.NET Framework 4</lastModifiedBy>
</coreProperties>`.replace(/\n/, "\r\n"), {name: "1.psmdcp", prefix: "package/services/metadata/core-properties"})

archive.file(updateFile, {name: "Update.exe", prefix: "lib/net45"})
encodedZip(archive, directory, "lib/net45")
await archivePromise
}

async function releasify(options: SquirrelOptions, nupkgPath: string, outputDirectory: string, packageName: string) {
const args = [
"--releasify", nupkgPath,
"--releaseDir", outputDirectory
]
const out = (await exec(process.platform === "win32" ? path.join(options.vendorPath, "Update.com") : "mono", prepareArgs(args, path.join(options.vendorPath, "Update-Mono.exe")))).trim()
if (debug.enabled) {
debug(out)
}

const lines = out.split("\n")
for (let i = lines.length - 1; i > -1; i--) {
const line = lines[i]
if (line.includes(packageName)) {
return line.trim()
}
}

throw new Error("Invalid output, cannot find last release entry")
}

async function msi(options: SquirrelOptions, nupkgPath: string, setupPath: string, outputDirectory: string, outFile: string) {
const args = [
"--createMsi", nupkgPath,
"--bootstrapperExe", setupPath
]
await exec(process.platform === "win32" ? path.join(options.vendorPath, "Update.com") : "mono", prepareArgs(args, path.join(options.vendorPath, "Update-Mono.exe")))
//noinspection SpellCheckingInspection
await exec(path.join(options.vendorPath, "candle.exe"), ["-nologo", "-ext", "WixNetFxExtension", "-out", "Setup.wixobj", "Setup.wxs"], {
cwd: outputDirectory,
})
//noinspection SpellCheckingInspection
await exec(path.join(options.vendorPath, "light.exe"), ["-ext", "WixNetFxExtension", "-sval", "-out", outFile, "Setup.wixobj"], {
cwd: outputDirectory,
})

//noinspection SpellCheckingInspection
await BluebirdPromise.all([
unlink(path.join(outputDirectory, "Setup.wxs")),
unlink(path.join(outputDirectory, "Setup.wixobj")),
unlink(path.join(outputDirectory, outFile.replace(".msi", ".wixpdb"))).catch(e => debug(e.toString())),
])
}

function prepareArgs(args: Array<string>, exePath: string) {
if (process.platform !== "win32") {
args.unshift(exePath)
}
return args
}

function encodedZip(archive: any, dir: string, prefix: string) {
archiverUtil.walkdir(dir, function (error: any, files: any) {
if (error) {
archive.emit("error", error)
return
}

for (let file of files) {
if (file.stats.isDirectory()) {
continue
}

// GBK file name encoding (or Non-English file name) caused a problem
const entryData = {
name: encodeURI(file.relative.replace(/\\/g, "/")).replace(/%5B/g, "[").replace(/%5D/g, "]"),
prefix: prefix,
stats: file.stats,
}
archive._append(file.path, entryData)
}

archive.finalize()
})
}
Loading

0 comments on commit 8008734

Please sign in to comment.