diff --git a/.travis.yml b/.travis.yml
index 7d9b4f19b55..8266f2499dd 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ osx_image: xcode7.3
env:
- NODE_VERSION=4
- - NODE_VERSION=5.8
+ - NODE_VERSION=5
language: ruby
@@ -32,8 +32,8 @@ before_install:
install:
- nvm install $NODE_VERSION
- npm install npm -g
-- npm prune
- npm install
+- npm prune
script:
- npm run test
diff --git a/docs/options.md b/docs/options.md
index 6164909b15e..0f6e766a863 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -31,26 +31,37 @@ Don't customize paths to background and icon, — just follow conventions (if yo
Here documented only `electron-builder` specific options:
-
+
+
# Application `package.json`
| Name | Description
| --- | ---
-| name | The application name.
-| productName |
As [name](#AppMetadata-name), but allows you to specify a product name for your executable which contains spaces and other special characters not allowed in the [name property](https://docs.npmjs.com/files/package.json#name}).
-
+| name | The application name.
+| productName | As [name](#AppMetadata-name), but allows you to specify a product name for your executable which contains spaces and other special characters not allowed in the [name property](https://docs.npmjs.com/files/package.json#name}).
+
+
# Development `package.json`
| Name | Description
| --- | ---
-| homepage | The url to the project homepage (NuGet Package `projectUrl` or Linux Package URL).
-| build | See [BuildMetadata](#BuildMetadata).
-
+| homepage | The url to the project [homepage](https://docs.npmjs.com/files/package.json#homepage) (NuGet Package projectUrl
(optional) or Linux Package URL (required)).
If not specified and your project repository is public on GitHub, it will be https://github.com/${user}/${project}
by default.
+| license | *linux-only.* The [license](https://docs.npmjs.com/files/package.json#license) name for this package.
+| build | See [.build](#BuildMetadata).
+
+
## `.build`
| Name | Description
| --- | ---
-| iconUrl | *windows-only.* A URL to an ICO file to use as the application icon (displayed in Control Panel > Programs and Features). Defaults to the Atom icon.
Please note — [local icon file url is not accepted](https://github.com/atom/grunt-electron-installer/issues/73), must be https/http.
- If you don’t plan to build windows installer, you can omit it.
- If your project repository is public on GitHub, it will be
https://raw.githubusercontent.com/${info.user}/${info.project}/master/build/icon.ico
by default.
-| productName | See [AppMetadata.productName](#AppMetadata-productName).
-| extraResources | A [glob expression](https://www.npmjs.com/package/glob#glob-primer), when specified, copy the file or directory with matching names directly into the app’s directory (Contents/Resources
for OS X).
You can use ${os}
(expanded to osx, linux or win according to current platform) and ${arch}
in the pattern.
If directory matched, all contents are copied. So, you can just specify foo
to copy <project_dir>/foo
directory.
May be specified in the platform options (i.e. in the build.osx
).
-| osx | See [OS X options](https://www.npmjs.com/package/appdmg#json-specification)
-| win | See [windows-installer options](https://github.com/electronjs/windows-installer#usage)
+| iconUrl | *windows-only.* A URL to an ICO file to use as the application icon (displayed in Control Panel > Programs and Features). Defaults to the Atom icon.
Please note — [local icon file url is not accepted](https://github.com/atom/grunt-electron-installer/issues/73), must be https/http.
- If you don’t plan to build windows installer, you can omit it.
- If your project repository is public on GitHub, it will be
https://raw.githubusercontent.com/${user}/${project}/master/build/icon.ico
by default.
+| productName | See [AppMetadata.productName](#AppMetadata-productName).
+| extraResources | A [glob expression](https://www.npmjs.com/package/glob#glob-primer), when specified, copy the file or directory with matching names directly into the app’s directory (Contents/Resources
for OS X).
You can use ${os}
(expanded to osx, linux or win according to current platform) and ${arch}
in the pattern.
If directory matched, all contents are copied. So, you can just specify foo
to copy <project_dir>/foo
directory.
May be specified in the platform options (i.e. in the build.osx
).
+| osx | See [OS X options](https://www.npmjs.com/package/appdmg#json-specification)
+| win | See [windows-installer options](https://github.com/electronjs/windows-installer#usage)
+| linux | See [.linux](#DebOptions).
+
+
+### `.build.linux`
+| Name | Description
+| --- | ---
+| compression | *deb-only.* The compression type to use, must be one of gz, bzip2, xz. (default: `xz`)
diff --git a/package.json b/package.json
index c44872b7803..b759b7faf7e 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,7 @@
"ava-tf": "^0.12.4-beta.6",
"babel-plugin-array-includes": "^2.0.3",
"babel-plugin-transform-es2015-parameters": "^6.7.0",
+ "babel-plugin-transform-es2015-spread": "^6.6.5",
"decompress-zip": "^0.3.0",
"electron-download": "^2.1.0",
"json-parse-helpfulerror": "^1.0.3",
@@ -85,7 +86,7 @@
"pre-commit": "^1.1.2",
"semantic-release": "^4.3.5",
"should": "^8.3.0",
- "ts-babel": "^0.6.5",
+ "ts-babel": "^0.6.7",
"tsconfig-glob": "^0.4.3",
"tslint": "next",
"typescript": "^1.9.0-dev.20160325",
@@ -94,6 +95,7 @@
"babel": {
"plugins": [
"transform-es2015-parameters",
+ "transform-es2015-spread",
"array-includes"
]
},
diff --git a/src/index.ts b/src/index.ts
index a92758314c4..c030e46f500 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,4 @@
export { Packager } from "./packager"
export { PackagerOptions, ArtifactCreated } from "./platformPackager"
export { BuildOptions, build, createPublisher } from "./builder"
-export { AppMetadata, DevMetadata, Platform, getProductName } from "./metadata"
\ No newline at end of file
+export { AppMetadata, DevMetadata, Platform, getProductName, BuildMetadata, DebOptions } from "./metadata"
\ No newline at end of file
diff --git a/src/linuxPackager.ts b/src/linuxPackager.ts
index 3c2007fbf33..e5b2d30fcf8 100755
--- a/src/linuxPackager.ts
+++ b/src/linuxPackager.ts
@@ -1,7 +1,7 @@
import * as path from "path"
import { Promise as BluebirdPromise } from "bluebird"
import { PlatformPackager, BuildInfo } from "./platformPackager"
-import { Platform } from "./metadata"
+import { Platform, DebOptions } from "./metadata"
import { dir as _tpmDir, TmpOptions } from "tmp"
import { exec, log } from "./util"
import { outputFile, readFile, readdir } from "fs-extra-p"
@@ -172,7 +172,13 @@ Icon=${this.metadata.name}
const target = "deb"
const destination = path.join(outDir, `${this.metadata.name}-${this.metadata.version}-${archName}.${target}`)
const scripts = await this.scriptFiles
- await exec("fpm", [
+
+ const projectUrl = await this.computePackageUrl()
+ if (projectUrl == null) {
+ throw new Error("Please specify project homepage")
+ }
+
+ const args = [
"-s", "dir",
"-t", target,
"--architecture", archName,
@@ -186,12 +192,25 @@ Icon=${this.metadata.name}
"--version", this.metadata.version,
"--package", destination,
"--deb-compression", options.compression || "xz",
- appOutDir + "/=/opt/" + this.appName,
- ].concat(await this.packageFiles))
+ "--url", projectUrl,
+ ]
+
+ use(this.devMetadata.license, it => args.push("--license", it))
+ use(this.computeBuildNumber(), it => args.push("--iteration", it))
+
+ args.push(`${appOutDir}/=/opt/${this.appName}`)
+ args.push(...(await this.packageFiles))
+ await exec("fpm", args)
return destination
}
}
+function use(value: T, task: (it: T) => void) {
+ if (value != null) {
+ task(value)
+ }
+}
+
async function writeConfigFile(tempDir: string, templatePath: string, options: any): Promise {
const config = template(await readFile(templatePath, "utf8"),
{
@@ -202,21 +221,4 @@ async function writeConfigFile(tempDir: string, templatePath: string, options: a
const outputPath = path.join(tempDir, path.basename(templatePath, ".tpl"))
await outputFile(outputPath, config)
return outputPath
-}
-
-export interface DebOptions {
- name: string
- comment: string
-
- maintainer: string
-
- /**
- * .desktop file template
- */
- desktop?: string
-
- afterInstall?: string
- afterRemove?: string
-
- compression?: string
}
\ No newline at end of file
diff --git a/src/metadata.ts b/src/metadata.ts
index 5a140899580..8b3cfac0a9d 100755
--- a/src/metadata.ts
+++ b/src/metadata.ts
@@ -29,12 +29,19 @@ export interface AppMetadata extends Metadata {
*/
export interface DevMetadata extends Metadata {
/**
- The url to the project homepage (NuGet Package `projectUrl` or Linux Package URL).
+ The url to the project [homepage](https://docs.npmjs.com/files/package.json#homepage) (NuGet Package `projectUrl` (optional) or Linux Package URL (required)).
+
+ If not specified and your project repository is public on GitHub, it will be `https://github.com/${user}/${project}` by default.
*/
readonly homepage?: string
/**
- See [BuildMetadata](#BuildMetadata).
+ *linux-only.* The [license](https://docs.npmjs.com/files/package.json#license) name for this package.
+ */
+ readonly license?: string
+
+ /**
+ See [.build](#BuildMetadata).
*/
readonly build?: BuildMetadata
@@ -67,7 +74,7 @@ export interface BuildMetadata {
Please note — [local icon file url is not accepted](https://github.com/atom/grunt-electron-installer/issues/73), must be https/http.
* If you don't plan to build windows installer, you can omit it.
- * If your project repository is public on GitHub, it will be `https://raw.githubusercontent.com/${info.user}/${info.project}/master/build/icon.ico` by default.
+ * If your project repository is public on GitHub, it will be `https://raw.githubusercontent.com/${user}/${project}/master/build/icon.ico` by default.
*/
readonly iconUrl: string
@@ -97,9 +104,33 @@ export interface BuildMetadata {
*/
readonly win?: any,
+ /**
+ See [.linux](#DebOptions).
+ */
readonly linux?: any
}
+/**
+ ### `.build.linux`
+ */
+export interface DebOptions {
+ name: string
+ comment: string
+
+ maintainer: string
+
+ //.desktop file template
+ desktop?: string
+
+ afterInstall?: string
+ afterRemove?: string
+
+ /*
+ *deb-only.* The compression type to use, must be one of gz, bzip2, xz. (default: `xz`)
+ */
+ readonly compression?: string
+}
+
export interface PlatformSpecificBuildOptions {
readonly extraResources?: Array
}
diff --git a/src/platformPackager.ts b/src/platformPackager.ts
index d721f37ff1d..02540c20c0a 100644
--- a/src/platformPackager.ts
+++ b/src/platformPackager.ts
@@ -96,7 +96,7 @@ export abstract class PlatformPackager
protected async doPack(outDir: string, arch: string) {
const version = this.metadata.version
let buildVersion = version
- const buildNumber = process.env.TRAVIS_BUILD_NUMBER || process.env.APPVEYOR_BUILD_NUMBER || process.env.CIRCLE_BUILD_NUM
+ const buildNumber = this.computeBuildNumber()
if (buildNumber != null) {
buildVersion += "." + buildNumber
}
@@ -158,11 +158,30 @@ export abstract class PlatformPackager
if (this.platform === Platform.OSX) {
resourcesDir = path.join(resourcesDir, this.appName + ".app", "Contents", "Resources")
}
-
return await BluebirdPromise.map(await this.getExtraResources(arch), it => copy(path.join(this.projectDir, it), path.join(resourcesDir, it)))
}
abstract packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise
+
+ protected async computePackageUrl(): Promise {
+ const url = this.devMetadata.homepage
+ if (url != null) {
+ return url
+ }
+
+ if (this.info.repositoryInfo != null) {
+ const info = await this.info.repositoryInfo.getInfo(this)
+ if (info != null) {
+ return `https://github.com/${info.user}/${info.project}`
+ }
+ }
+ return null
+ }
+
+ //noinspection JSMethodCanBeStatic
+ protected computeBuildNumber(): string {
+ return process.env.TRAVIS_BUILD_NUMBER || process.env.APPVEYOR_BUILD_NUMBER || process.env.CIRCLE_BUILD_NUM
+ }
}
function checkConflictingOptions(options: any): void {
diff --git a/src/util.ts b/src/util.ts
index 62c34b7193f..3e5ef679e5e 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -79,9 +79,11 @@ export function exec(file: string, args?: string[], options?: ExecOptions): Blue
console.error(stdout.toString())
}
if (stderr.length !== 0) {
- console.error(stderr.toString())
+ reject(new Error(stderr.toString() + "\n" + error.toString()))
+ }
+ else {
+ reject(error)
}
- reject(error)
}
})
})
diff --git a/src/winPackager.ts b/src/winPackager.ts
index 3fae7e4e20b..d674f1649c0 100644
--- a/src/winPackager.ts
+++ b/src/winPackager.ts
@@ -115,7 +115,7 @@ export default class WinPackager extends PlatformPackager {
const version = this.metadata.version
const installerOutDir = WinPackager.computeDistOut(outDir, arch)
const archSuffix = arch === "x64" ? "" : ("-" + arch)
- const projectUrl = this.devMetadata.homepage
+ const projectUrl = await this.computePackageUrl()
const options = Object.assign({
name: this.metadata.name,
diff --git a/test/fixtures/test-app-one/package.json b/test/fixtures/test-app-one/package.json
index a65af155d69..5b4199af852 100755
--- a/test/fixtures/test-app-one/package.json
+++ b/test/fixtures/test-app-one/package.json
@@ -8,6 +8,7 @@
"start": "electron ."
},
"author": "Foo Bar ",
+ "license": "MIT",
"devDependencies": {
"electron-prebuilt": "^0.37.3"
},
diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts
index a54952e0d60..46e81195955 100755
--- a/test/src/helpers/packTester.ts
+++ b/test/src/helpers/packTester.ts
@@ -106,26 +106,7 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions
await checkOsXResult(packager, artifacts.get(Platform.OSX))
}
else if (platform === "linux") {
- const productName = getProductName(packager.metadata, packager.devMetadata)
- const expectedContents = expectedLinuxContents.map(it => {
- if (it === "/opt/TestApp/TestApp") {
- return "/opt/" + productName + "/" + productName
- }
- else if (it === "/usr/share/applications/TestApp.desktop") {
- return `/usr/share/applications/${productName}.desktop`
- }
- else {
- return it.replace(new RegExp("/opt/TestApp/", "g"), `/opt/${productName}/`)
- }
- })
-
- // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb", productName), null, 2))
- // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName), null, 2))
-
- assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb", productName)).deepEqual(expectedContents)
- if (packagerOptions.arch === "all" || packagerOptions.arch === "ia32") {
- assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName)).deepEqual(expectedContents)
- }
+ await checkLinuxResult(projectDir, packager, packagerOptions)
}
else if (platform === "win32") {
await checkWindowsResult(packager, packagerOptions, checkOptions, artifacts.get(Platform.WINDOWS))
@@ -133,6 +114,45 @@ async function packAndCheck(projectDir: string, packagerOptions: PackagerOptions
}
}
+async function checkLinuxResult(projectDir: string, packager: Packager, packagerOptions: PackagerOptions) {
+ const productName = getProductName(packager.metadata, packager.devMetadata)
+ const expectedContents = expectedLinuxContents.map(it => {
+ if (it === "/opt/TestApp/TestApp") {
+ return "/opt/" + productName + "/" + productName
+ }
+ else if (it === "/usr/share/applications/TestApp.desktop") {
+ return `/usr/share/applications/${productName}.desktop`
+ }
+ else {
+ return it.replace(new RegExp("/opt/TestApp/", "g"), `/opt/${productName}/`)
+ }
+ })
+
+ // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb", productName), null, 2))
+ // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName), null, 2))
+
+ const packageFile = projectDir + "/dist/TestApp-1.0.0-amd64.deb"
+ assertThat(await getContents(packageFile, productName)).deepEqual(expectedContents)
+ if (packagerOptions.arch === "all" || packagerOptions.arch === "ia32") {
+ assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb", productName)).deepEqual(expectedContents)
+ }
+
+ const regexp = /^ *(\w+): *(.+)$/gm
+ const info = (await exec("dpkg", ["--info", packageFile])).toString()
+ let match: Array
+ const metadata: any = {}
+ while ((match = regexp.exec(info)) !== null) {
+ metadata[match[1]] = match[2]
+ }
+ assertThat(metadata).has.properties({
+ License: "MIT",
+ Homepage: "http://foo.example.com",
+ Maintainer: "Foo Bar ",
+ Package: "testapp",
+ Description: "Test Application",
+ })
+}
+
async function checkOsXResult(packager: Packager, artifacts: Array) {
const productName = getProductName(packager.metadata, packager.devMetadata)
const packedAppDir = path.join(path.dirname(artifacts[0].file), (productName || packager.metadata.name) + ".app")