Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get rid of nuget #77

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,5 @@ function handleSquirrelEvent() {
You can get debug messages from this package by running with the environment variable `DEBUG=electron-windows-installer:main` e.g.

```
DEBUG=electron-windows-installer:main node tasks/electron-winstaller.js
DEBUG=electron-windows-installer node tasks/electron-winstaller.js
Copy link
Contributor Author

@develar develar Apr 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to debug — you need all categories in any case.

The issue — if you use different categories, you cannot get time information (debug measures time per category).

```
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@
"tdd": "ava --watch"
},
"dependencies": {
"asar": "~0.10.0",
"bluebird": "^3.3.4",
"archiver": "^1.0.0",
"asar": "~0.11.0",
"bluebird": "^3.3.5",
"debug": "^2.2.0",
"fs-extra": "^0.26.7",
"lodash.template": "^4.2.2",
"temp": "^0.8.3"
"fs-extra": "^0.28.0"
},
"devDependencies": {
"ava": "^0.13.0",
"babel-cli": "^6.6.5",
"ava": "^0.14.0",
"babel-cli": "^6.7.5",
"babel-eslint": "^6.0.2",
"babel-plugin-transform-async-to-module-method": "^6.7.0",
"babel-plugin-transform-runtime": "^6.6.0",
"babel-preset-es2015-node4": "^2.0.3",
"babel-plugin-transform-runtime": "^6.7.5",
"babel-preset-es2015-node4": "^2.1.0",
"babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.7.2",
"eslint": "^2.4.0"
"eslint": "^2.8.0",
"temp": "^0.8.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move temp in dev deps.

},
"engines": {
"node": ">=0.4.0"
Expand Down
8 changes: 7 additions & 1 deletion spec/installer-spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import test from 'ava';
import path from 'path';
import { createTempDir, fileExists, unlink, readDir } from '../src/fs-utils';
import { fileExists, unlink, readDir } from '../src/fs-utils';
import { createWindowsInstaller } from '../src/index.js';
import { Promise } from 'bluebird';
import temp from 'temp';

temp.track();

const createTempDir = Promise.promisify(temp.mkdir);

const log = require('debug')('electron-windows-installer:spec');

Expand Down
12 changes: 4 additions & 8 deletions src/fs-utils.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { copy as extraCopy } from 'fs-extra';
import { Promise } from 'bluebird';
import temp from 'temp';
import fs from 'fs';
import * as fs from 'fs-extra';

const log = require('debug')('electron-windows-installer:fs-utils');

temp.track();

export const copy = Promise.promisify(extraCopy);
export const createTempDir = Promise.promisify(temp.mkdir);
export const copy = Promise.promisify(fs.copy);
export const readFile = Promise.promisify(fs.readFile);
export const readDir = Promise.promisify(fs.readdir);
export const unlink = Promise.promisify(fs.unlink);
export const writeFile = Promise.promisify(fs.writeFile);
export const rename = Promise.promisify(fs.rename);
export const mkdirs = Promise.promisify(fs.mkdirs);
export const remove = Promise.promisify(fs.remove);

const inspect = Promise.promisify(fs.stat);
export async function fileExists(file) {
Expand Down
217 changes: 124 additions & 93 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import template from 'lodash.template';
import spawn from './spawn-promise';
import asar from 'asar';
import path from 'path';
import * as fsUtils from './fs-utils';
import archiver from 'archiver';
import * as fs from 'fs-extra';
import { Promise } from 'bluebird';

const log = require('debug')('electron-windows-installer:main');
const log = require('debug')('electron-windows-installer');

export function convertVersion(version) {
const parts = version.split('-');
Expand All @@ -18,29 +20,13 @@ export function convertVersion(version) {
}

export async function createWindowsInstaller(options) {
let useMono = false;

const monoExe = 'mono';
const wineExe = 'wine';

if (process.platform !== 'win32') {
useMono = true;
if (!wineExe || !monoExe) {
throw new Error('You must install both Mono and Wine on non-Windows');
}

log(`Using Mono: '${monoExe}'`);
log(`Using Wine: '${wineExe}'`);
}

let { appDirectory, outputDirectory, loadingGif } = options;
outputDirectory = path.resolve(outputDirectory || 'installer');
const useMono = process.platform !== 'win32';
const { appDirectory } = options;

const vendorPath = path.join(__dirname, '..', 'vendor');
const vendorUpdate = path.join(vendorPath, 'Update.exe');
const appUpdate = path.join(appDirectory, 'Update.exe');

await fsUtils.copy(vendorUpdate, appUpdate);
await fsUtils.copy(path.join(vendorPath, 'Update.exe'), appUpdate);
if (options.setupIcon && (options.skipUpdateIcon !== true)) {
let cmd = path.join(vendorPath, 'rcedit.exe');
let args = [
Expand All @@ -50,17 +36,12 @@ export async function createWindowsInstaller(options) {

if (useMono) {
args.unshift(cmd);
cmd = wineExe;
cmd = 'wine';
}

await spawn(cmd, args);
}

const defaultLoadingGif = path.join(__dirname, '..', 'resources', 'install-spinner.gif');
loadingGif = loadingGif ? path.resolve(loadingGif) : defaultLoadingGif;

let {certificateFile, certificatePassword, remoteReleases, signWithParams, remoteToken} = options;

const metadata = {
description: '',
iconUrl: 'https://raw.githubusercontent.com/atom/electron/master/atom/browser/resources/win/atom.ico'
Expand Down Expand Up @@ -93,69 +74,139 @@ export async function createWindowsInstaller(options) {
}
}

metadata.owners = metadata.owners || metadata.authors;
metadata.version = convertVersion(metadata.version);
metadata.copyright = metadata.copyright ||
`Copyright © ${new Date().getFullYear()} ${metadata.authors || metadata.owners}`;

let templateData = await fsUtils.readFile(path.join(__dirname, '..', 'template.nuspec'), 'utf8');
if (path.sep === '/') {
templateData = templateData.replace(/\\/g, '/');
}
const nuspecContent = template(templateData)(metadata);

log(`Created NuSpec file:\n${nuspecContent}`);
const outputDirectory = path.resolve(options.outputDirectory || 'installer');
if (options.remoteReleases) {
let cmd = path.join(vendorPath, 'SyncReleases.exe');
let args = ['-u', options.remoteReleases, '-r', outputDirectory];

const nugetOutput = await fsUtils.createTempDir('si-');
const targetNuspecPath = path.join(nugetOutput, metadata.name + '.nuspec');

await fsUtils.writeFile(targetNuspecPath, nuspecContent);
if (useMono) {
args.unshift(cmd);
cmd = 'mono';
}

let cmd = path.join(vendorPath, 'nuget.exe');
let args = [
'pack', targetNuspecPath,
'-BasePath', appDirectory,
'-OutputDirectory', nugetOutput,
'-NoDefaultExcludes'
];
if (options.remoteToken) {
args.push('-t', options.remoteToken);
}

if (useMono) {
args.unshift(cmd);
cmd = monoExe;
await spawn(cmd, args);
}

// Call NuGet to create our package
log(await spawn(cmd, args));
const nupkgPath = path.join(nugetOutput, `${metadata.name}.${metadata.version}.nupkg`);
// todo fix Squirrel.windows "Sharing violation on path" (avoid copy, use file directly)
const squirrelWorkaroundDir = path.join(outputDirectory, '.tmp');
await fsUtils.mkdirs(squirrelWorkaroundDir);
try {
const nupkgPath = path.join(squirrelWorkaroundDir, 'in.nupkg');
await pack(metadata, appDirectory, nupkgPath);
await releasify(nupkgPath, outputDirectory, options, vendorPath);
}
finally {
await fsUtils.remove(squirrelWorkaroundDir);
}

if (remoteReleases) {
cmd = path.join(vendorPath, 'SyncReleases.exe');
args = ['-u', remoteReleases, '-r', outputDirectory];
if (options.fixUpPaths !== false) {
log('Fixing up paths');

if (useMono) {
args.unshift(cmd);
cmd = monoExe;
if (metadata.productName || options.setupExe) {
const setupPath = path.join(outputDirectory, options.setupExe || `${metadata.productName}Setup.exe`);
const unfixedSetupPath = path.join(outputDirectory, 'Setup.exe');
log(`Renaming ${unfixedSetupPath} => ${setupPath}`);
await fsUtils.rename(unfixedSetupPath, setupPath);
}

if (remoteToken) {
args.push('-t', remoteToken);
if (metadata.productName) {
const msiPath = path.join(outputDirectory, `${metadata.productName}Setup.msi`);
const unfixedMsiPath = path.join(outputDirectory, 'Setup.msi');
if (await fsUtils.fileExists(unfixedMsiPath)) {
log(`Renaming ${unfixedMsiPath} => ${msiPath}`);
await fsUtils.rename(unfixedMsiPath, msiPath);
}
}

log(await spawn(cmd, args));
}
}

function pack(metadata, appDirectory, outFile) {
Copy link
Contributor Author

@develar develar Apr 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No way to use 7z here because 7z doesn't support directory prefix. Anyway, we don't need to compress here, so, node implementation is ok.

return new Promise(function (resolve, reject) {
const archive = archiver('zip', {store: true});
const out = fs.createWriteStream(outFile);
out.on('close', function () {
resolve(outFile);
});
archive.on('error', reject);
archive.pipe(out);

archive.directory(appDirectory, 'lib/net45');

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

const author = metadata.authors || metadata.owners;
const copyright = metadata.copyright ||
`Copyright © ${new Date().getFullYear()} ${author}`;
const version = convertVersion(metadata.version);
const nuspecContent = `<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>${metadata.name}</id>
<title>${metadata.title}</title>
<version>${version}</version>
<authors>${author}</authors>
<owners>${metadata.owners || metadata.authors}</owners>
<iconUrl>${metadata.iconUrl}</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>${metadata.description}</description>
<copyright>${copyright}</copyright>${metadata.extraMetadataSpecs || ''}
</metadata>
</package>`;
log(`Created NuSpec file:\n${nuspecContent}`);

archive.append(nuspecContent, {name: metadata.name + '.nuspec'});

archive.append(`<?xml version="1.0"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>
<Default ContentType="application/octet" Extension="nuspec"/>
<Default ContentType="application/octet" Extension="pak"/>
<Default ContentType="application/octet" Extension="asar"/>
<Default ContentType="application/octet" Extension="bin"/>
<Default ContentType="application/octet" Extension="dll"/>
<Default ContentType="application/octet" Extension="exe"/>
<Default ContentType="application/octet" Extension="dat"/>
<Default ContentType="application/vnd.openxmlformats-package.core-properties+xml" Extension="psmdcp"/>
</Types>`, {name: '[Content_Types].xml'});

archive.append(`<?xml version="1.0"?>
<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>${metadata.description}</dc:description>
<dc:identifier>${metadata.name}</dc:identifier>
<keywords/>
<lastModifiedBy>NuGet, Version=3.4.0.653, Culture=neutral, PublicKeyToken=31bf3856ad364e35;Unix 15.4.0.0;.NET Framework 4.5</lastModifiedBy>
<dc:title>${metadata.title}</dc:title>
<version>${version}</version>
</coreProperties>`, {name: '1.psmdcp', prefix: 'package/services/metadata/core-properties'});

archive.finalize();
});
}

cmd = path.join(vendorPath, 'Update.com');
args = [
async function releasify(nupkgPath, outputDirectory, options, vendorPath) {
let cmd = path.join(vendorPath, 'Update.com');
const args = [
'--releasify', nupkgPath,
'--releaseDir', outputDirectory,
'--loadingGif', loadingGif
'--loadingGif', options.loadingGif ? path.resolve(options.loadingGif) : path.join(__dirname, '..', 'resources', 'install-spinner.gif')
];

if (useMono) {
if (process.platform !== 'win32') {
args.unshift(path.join(vendorPath, 'Update-Mono.exe'));
cmd = monoExe;
cmd = 'mono';
}

const {certificateFile, certificatePassword, signWithParams} = options;
if (signWithParams) {
args.push('--signWithParams');
args.push(signWithParams);
Expand All @@ -173,25 +224,5 @@ export async function createWindowsInstaller(options) {
args.push('--no-msi');
}

log(await spawn(cmd, args));

if (options.fixUpPaths !== false) {
log('Fixing up paths');

if (metadata.productName || options.setupExe) {
const setupPath = path.join(outputDirectory, options.setupExe || `${metadata.productName}Setup.exe`);
const unfixedSetupPath = path.join(outputDirectory, 'Setup.exe');
log(`Renaming ${unfixedSetupPath} => ${setupPath}`);
await fsUtils.rename(unfixedSetupPath, setupPath);
}

if (metadata.productName) {
const msiPath = path.join(outputDirectory, `${metadata.productName}Setup.msi`);
const unfixedMsiPath = path.join(outputDirectory, 'Setup.msi');
if (await fsUtils.fileExists(unfixedMsiPath)) {
log(`Renaming ${unfixedMsiPath} => ${msiPath}`);
await fsUtils.rename(unfixedMsiPath, msiPath);
}
}
}
}
await spawn(cmd, args);
}
2 changes: 1 addition & 1 deletion src/spawn-promise.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { spawn as spawnOg } from 'child_process';
import { Promise } from 'bluebird';

const d = require('debug')('electron-windows-installer:spawn');
const d = require('debug')('electron-windows-installer');

// Public: Maps a process's output into an {Observable}
//
Expand Down
Binary file removed vendor/nuget.exe
Binary file not shown.