Skip to content

Commit

Permalink
feat: if only ignored patterns are specified — all not ignored files …
Browse files Browse the repository at this point in the history
…is copied

Closes #927
  • Loading branch information
develar committed Nov 25, 2016
1 parent f4d7a2e commit a55c573
Show file tree
Hide file tree
Showing 15 changed files with 126 additions and 97 deletions.
13 changes: 6 additions & 7 deletions docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,12 @@ Windows specific build options.

| Name | Description
| --- | ---
| target | <a name="WinBuildOptions-target"></a>Target package type: list of `nsis`, `squirrel`, `7z`, `zip`, `tar.xz`, `tar.lz`, `tar.gz`, `tar.bz2`, `dir`. Defaults to `nsis`.
| signingHashAlgorithms | <a name="WinBuildOptions-signingHashAlgorithms"></a>Array of signing algorithms used. Defaults to `['sha1', 'sha256']`
| target | <a name="WinBuildOptions-target"></a><p>Target package type: list of <code>nsis</code>, <code>appx</code>, <code>squirrel</code>, <code>7z</code>, <code>zip</code>, <code>tar.xz</code>, <code>tar.lz</code>, <code>tar.gz</code>, <code>tar.bz2</code>, <code>dir</code>. Defaults to <code>nsis</code>.</p> <p>AppX package can be built only on Windows 10.</p>
| signingHashAlgorithms | <a name="WinBuildOptions-signingHashAlgorithms"></a><p>Array of signing algorithms used. Defaults to <code>['sha1', 'sha256']</code></p> <p>Fo AppX <code>sha256</code> is always used.</p>
| icon | <a name="WinBuildOptions-icon"></a>The path to application icon. Defaults to `build/icon.ico` (consider using this convention instead of complicating your configuration).
| legalTrademarks | <a name="WinBuildOptions-legalTrademarks"></a>The trademarks and registered trademarks.
| certificateFile | <a name="WinBuildOptions-certificateFile"></a>The path to the *.pfx certificate you want to sign with. Required only if you build on macOS and need different certificate than the one set in `CSC_LINK` - see [Code Signing](https://github.com/electron-userland/electron-builder/wiki/Code-Signing).
| certificatePassword | <a name="WinBuildOptions-certificatePassword"></a>The password to the certificate provided in `certificateFile`. Required only if you build on macOS and need to use a different password than the one set in `CSC_KEY_PASSWORD` - see [Code Signing](https://github.com/electron-userland/electron-builder/wiki/Code-Signing).
| certificateFile | <a name="WinBuildOptions-certificateFile"></a><p>The path to the *.pfx certificate you want to sign with. Please use it only if you cannot use env variable <code>CSC_LINK</code> (<code>WIN_CSC_LINK</code>) for some reason. Please see [Code Signing](https://github.com/electron-userland/electron-builder/wiki/Code-Signing).</p>
| certificatePassword | <a name="WinBuildOptions-certificatePassword"></a><p>The password to the certificate provided in <code>certificateFile</code>. Please use it only if you cannot use env variable <code>CSC_KEY_PASSWORD</code> (<code>WIN_CSC_KEY_PASSWORD</code>) for some reason. Please see [Code Signing](https://github.com/electron-userland/electron-builder/wiki/Code-Signing).</p>
| certificateSubjectName | <a name="WinBuildOptions-certificateSubjectName"></a>The name of the subject of the signing certificate. Required only for EV Code Signing and works only on Windows.
| rfc3161TimeStampServer | <a name="WinBuildOptions-rfc3161TimeStampServer"></a>The URL of the RFC 3161 time stamp server. Defaults to `http://timestamp.comodoca.com/rfc3161`.

Expand Down Expand Up @@ -306,9 +306,8 @@ Development dependencies are never copied in any case. You don't need to ignore
[Multiple patterns](#multiple-glob-patterns) are supported. You can use `${os}` (expanded to mac, 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 `foo` directory.

Remember that default pattern `**/*` is not added to your custom, so, you have to add it explicitly — e.g. `["**/*", "!ignoreMe${/*}"]`.

`package.json` is added to your custom in any case.
Remember that default pattern `**/*` **is not added to your custom** if some of your patterns is not ignore (i.e. not starts with `!`).
`package.json` is added to your custom in any case.

May be specified in the platform options (e.g. in the `build.mac`).

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"update-wiki": "git subtree split -b wiki --prefix docs/ && git push -f wiki wiki:master",
"whitespace": "whitespace 'src/**/*.ts'",
"docker-images": "docker/build.sh",
"test-deps-mac": "brew install rpm dpkg mono lzip gnu-tar graphicsmagick xz && brew install wine --without-x11",
"precommit": "validate-commit-msg"
},
"repository": "electron-userland/electron-builder",
Expand Down
2 changes: 1 addition & 1 deletion src/codeSign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ async function _findIdentity(type: CertType, qualifier?: string | null, keychain
export async function findIdentity(certType: CertType, qualifier?: string | null, keychain?: string | null): Promise<string | null> {
let identity = process.env.CSC_NAME || qualifier
if (isEmptyOrSpaces(identity)) {
if (keychain == null && !isCi() && (process.env.CSC_IDENTITY_AUTO_DISCOVERY === "false")) {
if (keychain == null && !isCi() && process.env.CSC_IDENTITY_AUTO_DISCOVERY === "false") {
return null
}
else {
Expand Down
20 changes: 12 additions & 8 deletions src/fileMatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,20 @@ export class FileMatcher {
return this.patterns.length === 0
}

containsOnlyIgnore(): boolean {
return !this.isEmpty() && this.patterns.find(it => !it.startsWith("!")) == null
}

getParsedPatterns(fromDir?: string): Array<Minimatch> {
// https://github.com/electron-userland/electron-builder/issues/733
const minimatchOptions = {dot: true}

const parsedPatterns: Array<Minimatch> = []
const pathDifference = fromDir ? path.relative(fromDir, this.from) : null

for (let i = 0; i < this.patterns.length; i++) {
let expandedPattern = this.expandPattern(this.patterns[i])
if (pathDifference) {
for (const p of this.patterns) {
let expandedPattern = this.expandPattern(p)
if (pathDifference != null) {
expandedPattern = path.join(pathDifference, expandedPattern)
}

Expand Down Expand Up @@ -72,19 +76,19 @@ export class FileMatcher {
}
}

export function deprecatedUserIgnoreFilter(ignore: any, appDir: string) {
export function deprecatedUserIgnoreFilter(ignore: Array<RegExp> | ((file: string) => boolean), appDir: string) {
let ignoreFunc: any
if (typeof (ignore) === "function") {
ignoreFunc = function (file: string) { return !ignore(file) }
if (typeof ignore === "function") {
ignoreFunc = function (file: string) { return !(<any>ignore)(file) }
}
else {
if (!Array.isArray(ignore)) {
ignore = [ignore]
}

ignoreFunc = function (file: string) {
for (let i = 0; i < ignore.length; i++) {
if (file.match(ignore[i])) {
for (const i of <Array<RegExp>>ignore) {
if (file.match(i)) {
return false
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>

const patterns = this.getFileMatchers("files", appDir, path.join(resourcesPath, "app"), false, fileMatchOptions, platformSpecificBuildOptions)
let defaultMatcher = patterns == null ? new FileMatcher(appDir, path.join(resourcesPath, "app"), fileMatchOptions) : patterns[0]
if (defaultMatcher.isEmpty()) {
if (defaultMatcher.isEmpty() || defaultMatcher.containsOnlyIgnore()) {
defaultMatcher.addPattern("**/*")
}
else {
Expand Down Expand Up @@ -252,7 +252,7 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
//noinspection ES6MissingAwait
const promises = [promise, unlinkIfExists(path.join(resourcesPath, "default_app.asar")), unlinkIfExists(path.join(appOutDir, "version")), this.postInitApp(appOutDir)]
if (this.platform !== Platform.MAC) {
promises.push(rename(path.join(appOutDir, "LICENSE"), path.join(appOutDir, "LICENSE.electron.txt")) .catch(() => {/* ignore */}))
promises.push(rename(path.join(appOutDir, "LICENSE"), path.join(appOutDir, "LICENSE.electron.txt")).catch(() => {/* ignore */}))
}
if (this.info.electronVersion != null && this.info.electronVersion[0] === "0") {
// electron release >= 0.37.4 - the default_app/ folder is a default_app.asar file
Expand Down
6 changes: 6 additions & 0 deletions src/targets/appx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ import BluebirdPromise from "bluebird-lst-c"
import { Target } from "./targetFactory"
import { getSignVendorPath } from "../windowsCodeSign"
import sanitizeFileName from "sanitize-filename"
import { release } from "os"

export default class AppXTarget extends Target {
private readonly options: AppXOptions = Object.assign({}, this.packager.platformSpecificBuildOptions, this.packager.devMetadata.build.appx)

constructor(private readonly packager: WinPackager, private readonly outDir: string) {
super("appx")

const osVersion = release()
if (process.platform !== "win32" || parseInt(osVersion.substring(0, osVersion.indexOf(".")), 10) < 10) {
throw new Error("AppX is supported only on Windows 10")
}
}

// no flatten - use asar or npm 3 or yarn
Expand Down
5 changes: 2 additions & 3 deletions src/util/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function hasMagic(pattern: Minimatch) {
return true
}

for (let i of set[0]) {
for (const i of set[0]) {
if (typeof i !== "string") {
return true
}
Expand All @@ -44,7 +44,6 @@ export function createFilter(src: string, patterns: Array<Minimatch>, ignoreFile
}

let relative = it.substring(src.length + 1)

if (path.sep === "\\") {
relative = relative.replace(/\\/g, "/")
}
Expand All @@ -56,7 +55,7 @@ export function createFilter(src: string, patterns: Array<Minimatch>, ignoreFile
// https://github.com/joshwnj/minimatch-all/blob/master/index.js
function minimatchAll(path: string, patterns: Array<Minimatch>, stat: Stats): boolean {
let match = false
for (let pattern of patterns) {
for (const pattern of patterns) {
// If we've got a match, only re-test for exclusions.
// if we don't have a match, only re-test for inclusions.
if (match !== pattern.negate) {
Expand Down
2 changes: 0 additions & 2 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
In addition to [required system packages](./multi-platform-build.md), on MacOS `dpkg` is required to run Linux tests: `brew install dpkg`

# Inspect output if test uses temporary directory
Set environment variable `TEST_APP_TMP_DIR` (e.g. `/tmp/electron-builder-test`).
Specified directory will be used instead of random temporary directory and *cleared* on each run.
Expand Down
5 changes: 4 additions & 1 deletion test/jestSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ test.ifNotCiMac = isCi && process.platform === "darwin" ? skip : test

test.ifDevOrWinCi = !isCi || isWindows ? test : skip
test.ifDevOrLinuxCi = !isCi || process.platform === "linux" ? test : skip
test.ifWinCi = isCi && isWindows ? test : skip
test.ifWinCi = isCi && isWindows ? test : skip

delete process.env.CSC_NAME
process.env.CSC_IDENTITY_AUTO_DISCOVERY = "false"
6 changes: 6 additions & 0 deletions test/src/ArtifactPublisherTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ if (process.env.CI && process.platform === "win32") {
})
}

if (process.env.ELECTRON_BUILDER_OFFLINE === "true") {
fit("Skip ArtifactPublisherTest suite — ELECTRON_BUILDER_OFFLINE is defined", () => {
console.warn("[SKIP] Skip ArtifactPublisherTest suite — ELECTRON_BUILDER_OFFLINE is defined")
})
}

function getRandomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
Expand Down
137 changes: 69 additions & 68 deletions test/src/filesTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ test.ifDevOrLinuxCi("files", app({
devMetadata: {
build: {
asar: false,
files: ["**/*", "!ignoreMe${/*}"]
files: ["!ignoreMe${/*}"]
}
}
}, {
Expand All @@ -25,7 +25,7 @@ test.ifDevOrLinuxCi("files", app({
}))

test("extraResources", async () => {
for (let platform of getPossiblePlatforms().keys()) {
for (const platform of getPossiblePlatforms().keys()) {
const osName = platform.buildConfigurationKey

const winDirPrefix = "lib/net45/resources/"
Expand Down Expand Up @@ -90,78 +90,79 @@ test("extraResources", async () => {
}
})

test("extraResources - one-package", async () => {
for (let platform of [process.platform === "win32" ? Platform.WINDOWS : Platform.LINUX]) {
const osName = platform.buildConfigurationKey
test("extraResources - one-package", () => {
const platform = process.platform === "win32" ? Platform.WINDOWS : Platform.LINUX
const osName = platform.buildConfigurationKey

const winDirPrefix = "lib/net45/resources/"
const winDirPrefix = "lib/net45/resources/"

//noinspection SpellCheckingInspection
await assertPack("test-app-one", {
// to check NuGet package
targets: platform.createTarget(platform === Platform.WINDOWS ? "squirrel" : DIR_TARGET),
devMetadata: {
build: {
asar: true,
},
//noinspection SpellCheckingInspection
return assertPack("test-app-one", {
// to check NuGet package
targets: platform.createTarget(platform === Platform.WINDOWS ? "squirrel" : DIR_TARGET),
devMetadata: {
build: {
asar: true,
},
}, {
projectDirCreated: projectDir => {
return BluebirdPromise.all([
modifyPackageJson(projectDir, data => {
data.build.extraResources = [
"foo",
"bar/hello.txt",
"bar/${arch}.txt",
"${os}/${arch}.txt",
]
},
}, {
projectDirCreated: projectDir => {
return BluebirdPromise.all([
modifyPackageJson(projectDir, data => {
data.build.extraResources = [
"foo",
"bar/hello.txt",
"bar/${arch}.txt",
"${os}/${arch}.txt",
]

data.build[osName] = {
extraResources: [
"platformSpecificR"
],
extraFiles: [
"platformSpecificF"
],
}
}),
outputFile(path.join(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"),
outputFile(path.join(projectDir, "bar/hello.txt"), "data"),
outputFile(path.join(projectDir, `bar/${process.arch}.txt`), "data"),
outputFile(path.join(projectDir, `${osName}/${process.arch}.txt`), "data"),
outputFile(path.join(projectDir, "platformSpecificR"), "platformSpecificR"),
outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"),
])
},
packed: async context => {
const base = path.join(context.outDir, platform.buildConfigurationKey + `${platform === Platform.MAC ? "" : "-unpacked"}`)
let resourcesDir = path.join(base, "resources")
if (platform === Platform.MAC) {
resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources")
}
const appDir = path.join(resourcesDir, "app")
data.build[osName] = {
extraResources: [
"platformSpecificR"
],
extraFiles: [
"platformSpecificF"
],
}
}),
outputFile(path.join(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"),
outputFile(path.join(projectDir, "bar/hello.txt"), "data"),
outputFile(path.join(projectDir, `bar/${process.arch}.txt`), "data"),
outputFile(path.join(projectDir, `${osName}/${process.arch}.txt`), "data"),
outputFile(path.join(projectDir, "platformSpecificR"), "platformSpecificR"),
outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"),
])
},
packed: async context => {
const base = path.join(context.outDir, platform.buildConfigurationKey + `${platform === Platform.MAC ? "" : "-unpacked"}`)
let resourcesDir = path.join(base, "resources")
if (platform === Platform.MAC) {
resourcesDir = path.join(base, "TestApp.app", "Contents", "Resources")
}
const appDir = path.join(resourcesDir, "app")

await assertThat(path.join(resourcesDir, "foo")).isDirectory()
await assertThat(path.join(appDir, "foo")).doesNotExist()
await assertThat(path.join(resourcesDir, "foo")).isDirectory()
await assertThat(path.join(appDir, "foo")).doesNotExist()

await assertThat(path.join(resourcesDir, "foo", "nameWithoutDot")).isFile()
await assertThat(path.join(appDir, "foo", "nameWithoutDot")).doesNotExist()
await assertThat(path.join(resourcesDir, "foo", "nameWithoutDot")).isFile()
await assertThat(path.join(appDir, "foo", "nameWithoutDot")).doesNotExist()

await assertThat(path.join(resourcesDir, "bar", "hello.txt")).isFile()
await assertThat(path.join(resourcesDir, "bar", `${process.arch}.txt`)).isFile()
await assertThat(path.join(appDir, "bar", `${process.arch}.txt`)).doesNotExist()
await assertThat(path.join(resourcesDir, "bar", "hello.txt")).isFile()
await assertThat(path.join(resourcesDir, "bar", `${process.arch}.txt`)).isFile()
await assertThat(path.join(appDir, "bar", `${process.arch}.txt`)).doesNotExist()

await assertThat(path.join(resourcesDir, osName, `${process.arch}.txt`)).isFile()
await assertThat(path.join(resourcesDir, "platformSpecificR")).isFile()
await assertThat(path.join(resourcesDir, "ignoreMe.txt")).doesNotExist()
},
expectedContents: platform === Platform.WINDOWS ? pathSorter(expectedWinContents.concat(
winDirPrefix + "bar/hello.txt",
winDirPrefix + "bar/x64.txt",
winDirPrefix + "foo/nameWithoutDot",
winDirPrefix + "platformSpecificR",
winDirPrefix + "win/x64.txt"
)) : null,
})
}
await BluebirdPromise.all([
assertThat(path.join(resourcesDir, osName, `${process.arch}.txt`)).isFile(),
assertThat(path.join(resourcesDir, "platformSpecificR")).isFile(),
assertThat(path.join(resourcesDir, "ignoreMe.txt")).doesNotExist(),
])
},
expectedContents: platform === Platform.WINDOWS ? pathSorter(expectedWinContents.concat(
winDirPrefix + "bar/hello.txt",
winDirPrefix + "bar/x64.txt",
winDirPrefix + "foo/nameWithoutDot",
winDirPrefix + "platformSpecificR",
winDirPrefix + "win/x64.txt"
)) : null,
})
})
1 change: 0 additions & 1 deletion test/src/helpers/runTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ async function runTests() {
}

process.env.SKIP_WIN = skipWin
process.env.CSC_IDENTITY_AUTO_DISCOVERY = "false"
process.env.TEST_DIR = TEST_DIR

const rootDir = path.join(__dirname, "..", "..", "..")
Expand Down
8 changes: 7 additions & 1 deletion test/src/httpRequestTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import { randomBytes } from "crypto"
import { assertThat } from "./helpers/fileAssert"
import * as path from "path"

if (process.env.ELECTRON_BUILDER_OFFLINE === "true") {
fit("Skip httpRequestTest — ELECTRON_BUILDER_OFFLINE is defined", () => {
console.warn("[SKIP] Skip httpRequestTest — ELECTRON_BUILDER_OFFLINE is defined")
})
}

test.ifDevOrLinuxCi("download to nonexistent dir", async () => {
const tempFile = path.join(tmpdir(), `${process.pid}-${randomBytes(8).toString("hex")}`, Date.now().toString(), "foo.txt")
const tempFile = path.join(process.env.TEST_DIR || tmpdir(), `${process.pid}-${randomBytes(8).toString("hex")}`, Date.now().toString(16), "foo.txt")
await download("https://drive.google.com/uc?export=download&id=0Bz3JwZ-jqfRONTkzTGlsMkM2TlE", tempFile)
await assertThat(tempFile).isFile()
})
4 changes: 3 additions & 1 deletion test/src/mac/macArchiveTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ test.ifMac("invalid target", () => assertThat(createMacTargetTest([<any>"ttt"],

test("only zip", createMacTargetTest(["zip"], ["Test App ßW-1.1.0-mac.zip"]))

test.ifMac("pkg", createMacTargetTest(["pkg"], ["Test App ßW-1.1.0.pkg"]))
if (process.env.CSC_KEY_PASSWORD != null) {
test.ifMac("pkg", createMacTargetTest(["pkg"], ["Test App ßW-1.1.0.pkg"]))
}

test("tar.gz", createMacTargetTest(["tar.gz"], ["Test App ßW-1.1.0-mac.tar.gz"]))

Expand Down
Loading

0 comments on commit a55c573

Please sign in to comment.