-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
appInfo.ts
165 lines (139 loc) · 5.71 KB
/
appInfo.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import { isEmptyOrSpaces, log } from "builder-util"
import { prerelease, SemVer } from "semver"
import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions"
import { Packager } from "./packager"
import { expandMacro } from "./util/macroExpander"
import { sanitizeFileName } from "./util/filename"
// fpm bug - rpm build --description is not escaped, well... decided to replace quite to smart quote
// http://leancrew.com/all-this/2010/11/smart-quotes-in-javascript/
export function smarten(s: string): string {
// opening singles
s = s.replace(/(^|[-\u2014\s(["])'/g, "$1\u2018")
// closing singles & apostrophes
s = s.replace(/'/g, "\u2019")
// opening doubles
s = s.replace(/(^|[-\u2014/[(\u2018\s])"/g, "$1\u201c")
// closing doubles
s = s.replace(/"/g, "\u201d")
return s
}
export class AppInfo {
readonly description = smarten(this.info.metadata.description || "")
readonly version: string
readonly shortVersion: string | undefined
readonly shortVersionWindows: string | undefined
readonly buildNumber: string | undefined
readonly buildVersion: string
readonly productName: string
readonly sanitizedProductName: string
readonly productFilename: string
constructor(private readonly info: Packager, buildVersion: string | null | undefined, private readonly platformSpecificOptions: PlatformSpecificBuildOptions | null = null) {
this.version = info.metadata.version!
if (buildVersion == null) {
buildVersion = info.config.buildVersion
}
const buildNumberEnvs =
process.env.BUILD_NUMBER ||
process.env.TRAVIS_BUILD_NUMBER ||
process.env.APPVEYOR_BUILD_NUMBER ||
process.env.CIRCLE_BUILD_NUM ||
process.env.BUILD_BUILDNUMBER ||
process.env.CI_PIPELINE_IID
this.buildNumber = info.config.buildNumber || buildNumberEnvs
if (buildVersion == null) {
buildVersion = this.version
if (!isEmptyOrSpaces(this.buildNumber)) {
buildVersion += `.${this.buildNumber}`
}
}
this.buildVersion = buildVersion
if (info.metadata.shortVersion) {
this.shortVersion = info.metadata.shortVersion
}
if (info.metadata.shortVersionWindows) {
this.shortVersionWindows = info.metadata.shortVersionWindows
}
this.productName = info.config.productName || info.metadata.productName || info.metadata.name!
this.sanitizedProductName = sanitizeFileName(this.productName)
this.productFilename = platformSpecificOptions?.executableName != null ? sanitizeFileName(platformSpecificOptions.executableName) : this.sanitizedProductName
}
get channel(): string | null {
const prereleaseInfo = prerelease(this.version)
if (prereleaseInfo != null && prereleaseInfo.length > 0) {
return prereleaseInfo[0] as string | null
}
return null
}
getVersionInWeirdWindowsForm(isSetBuildNumber = true): string {
const parsedVersion = new SemVer(this.version)
// https://github.com/electron-userland/electron-builder/issues/2635#issuecomment-371792272
let buildNumber = isSetBuildNumber ? this.buildNumber : null
if (buildNumber == null || !/^\d+$/.test(buildNumber)) {
buildNumber = "0"
}
return `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}.${buildNumber}`
}
private get notNullDevMetadata() {
return this.info.devMetadata || {}
}
get companyName(): string | null {
const author = this.info.metadata.author || this.notNullDevMetadata.author
return author == null ? null : author.name
}
get id(): string {
let appId: string | null | undefined = null
for (const options of [this.platformSpecificOptions, this.info.config]) {
if (options != null && appId == null) {
appId = options.appId
}
}
const generateDefaultAppId = () => {
const info = this.info
return `${info.framework.defaultAppIdPrefix}${info.metadata.name!.toLowerCase()}`
}
if (appId != null && (appId === "your.id" || isEmptyOrSpaces(appId))) {
const incorrectAppId = appId
appId = generateDefaultAppId()
log.warn(`do not use "${incorrectAppId}" as appId, "${appId}" will be used instead`)
}
return appId == null ? generateDefaultAppId() : appId
}
get macBundleIdentifier(): string {
return filterCFBundleIdentifier(this.id)
}
get name(): string {
return this.info.metadata.name!
}
get linuxPackageName(): string {
const name = this.name
// https://github.com/electron-userland/electron-builder/issues/2963
return name.startsWith("@") ? this.sanitizedProductName : name
}
get sanitizedName(): string {
return sanitizeFileName(this.name)
}
get updaterCacheDirName(): string {
return this.sanitizedName.toLowerCase() + "-updater"
}
get copyright(): string {
const copyright = this.info.config.copyright
if (copyright != null) {
return expandMacro(copyright, null, this)
}
return `Copyright © ${new Date().getFullYear()} ${this.companyName || this.productName}`
}
async computePackageUrl(): Promise<string | null> {
const url = this.info.metadata.homepage || this.notNullDevMetadata.homepage
if (url != null) {
return url
}
const info = await this.info.repositoryInfo
return info == null || info.type !== "github" ? null : `https://${info.domain}/${info.user}/${info.project}`
}
}
/** @internal */
export function filterCFBundleIdentifier(identifier: string) {
// Remove special characters and allow only alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.)
// Apple documentation: https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070
return identifier.replace(/ /g, "-").replace(/[^a-zA-Z0-9.-]/g, "")
}