forked from rockybars/atom-shell-packager
-
Notifications
You must be signed in to change notification settings - Fork 0
/
platform.js
177 lines (146 loc) · 5.25 KB
/
platform.js
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
166
167
168
169
170
171
172
173
174
175
176
177
'use strict'
const asar = require('asar')
const debug = require('debug')('electron-packager')
const fs = require('fs-extra')
const path = require('path')
const pify = require('pify')
const hooks = require('./hooks')
const ignore = require('./ignore')
const pruneModules = require('./prune').pruneModules
const common = require('./common')
class App {
constructor (opts, templatePath) {
this.opts = opts
this.templatePath = templatePath
}
/**
* Resource directory path before renaming.
*/
get originalResourcesDir () {
return this.resourcesDir
}
/**
* Resource directory path after renaming.
*/
get resourcesDir () {
return path.join(this.stagingPath, 'resources')
}
get originalResourcesAppDir () {
return path.join(this.originalResourcesDir, 'app')
}
get electronBinaryDir () {
return this.stagingPath
}
get originalElectronName () {
/* istanbul ignore next */
throw new Error('Child classes must implement this')
}
get newElectronName () {
/* istanbul ignore next */
throw new Error('Child classes must implement this')
}
get executableName () {
return this.opts.executableName || this.opts.name
}
get stagingPath () {
if (this.opts.tmpdir === false) {
return common.generateFinalPath(this.opts)
} else {
return path.join(
common.baseTempDir(this.opts),
`${this.opts.platform}-${this.opts.arch}`,
common.generateFinalBasename(this.opts)
)
}
}
relativeRename (basePath, oldName, newName) {
debug(`Renaming ${oldName} to ${newName} in ${basePath}`)
return fs.rename(path.join(basePath, oldName), path.join(basePath, newName))
}
renameElectron () {
return this.relativeRename(this.electronBinaryDir, this.originalElectronName, this.newElectronName)
}
/**
* Performs the following initial operations for an app:
* * Creates temporary directory
* * Copies template into temporary directory
* * Copies user's app into temporary directory
* * Prunes non-production node_modules (if opts.prune is either truthy or undefined)
* * Creates an asar (if opts.asar is set)
*/
initialize () {
debug(`Initializing app in ${this.stagingPath} from ${this.templatePath} template`)
return fs.move(this.templatePath, this.stagingPath, { clobber: true })
.then(() => this.copyTemplate())
.then(() => {
// Support removing old default_app folder that is now an asar archive
return fs.remove(path.join(this.originalResourcesDir, 'default_app'))
}).then(() => fs.remove(path.join(this.originalResourcesDir, 'default_app.asar')))
// Prune and asar are performed before platform-specific logic, primarily so that
// this.originalResourcesAppDir is predictable (e.g. before .app is renamed for mac)
.then(() => this.prune())
.then(() => this.asarApp())
}
copyTemplate () {
return fs.copy(this.opts.dir, this.originalResourcesAppDir, {
filter: ignore.userIgnoreFilter(this.opts),
dereference: this.opts.derefSymlinks
}).then(() => hooks.promisifyHooks(this.opts.afterCopy, [
this.originalResourcesAppDir,
this.opts.electronVersion,
this.opts.platform,
this.opts.arch
]))
}
/**
* Forces an icon filename to a given extension and returns the normalized filename,
* if it exists. Otherwise, returns null.
*
* This error path is used by win32 if no icon is specified.
*/
normalizeIconExtension (targetExt) {
if (!this.opts.icon) throw new Error('No filename specified to normalizeExt')
let iconFilename = this.opts.icon
const ext = path.extname(iconFilename)
if (ext !== targetExt) {
iconFilename = path.join(path.dirname(iconFilename), path.basename(iconFilename, ext) + targetExt)
}
return fs.pathExists(iconFilename)
.then(() => iconFilename)
.catch(/* istanbul ignore next */ () => null)
}
prune () {
if (this.opts.prune || this.opts.prune === undefined) {
return pruneModules(this.opts, this.originalResourcesAppDir)
.then(() => hooks.promisifyHooks(this.opts.afterPrune, [this.originalResourcesAppDir, this.opts.electronVersion, this.opts.platform, this.opts.arch]))
}
return Promise.resolve()
}
asarApp () {
const asarOptions = common.createAsarOpts(this.opts)
if (!asarOptions) {
return Promise.resolve()
}
const dest = path.join(this.originalResourcesDir, 'app.asar')
debug(`Running asar with the options ${JSON.stringify(asarOptions)}`)
return pify(asar.createPackageWithOptions)(this.originalResourcesAppDir, dest, asarOptions)
.then(() => fs.remove(this.originalResourcesAppDir))
}
copyExtraResources () {
if (!this.opts.extraResource) return Promise.resolve()
const extraResources = common.ensureArray(this.opts.extraResource)
return Promise.all(extraResources.map(
resource => fs.copy(resource, path.resolve(this.stagingPath, this.resourcesDir, path.basename(resource)))
))
}
move () {
const finalPath = common.generateFinalPath(this.opts)
if (this.opts.tmpdir === false) {
return Promise.resolve(finalPath)
}
debug(`Moving ${this.stagingPath} to ${finalPath}`)
return fs.move(this.stagingPath, finalPath)
.then(() => finalPath)
}
}
module.exports = App