1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.DmgTarget = void 0;
|
7 |
|
8 | function _appBuilderLib() {
|
9 | const data = require("app-builder-lib");
|
10 |
|
11 | _appBuilderLib = function () {
|
12 | return data;
|
13 | };
|
14 |
|
15 | return data;
|
16 | }
|
17 |
|
18 | function _macCodeSign() {
|
19 | const data = require("app-builder-lib/out/codeSign/macCodeSign");
|
20 |
|
21 | _macCodeSign = function () {
|
22 | return data;
|
23 | };
|
24 |
|
25 | return data;
|
26 | }
|
27 |
|
28 | function _differentialUpdateInfoBuilder() {
|
29 | const data = require("app-builder-lib/out/targets/differentialUpdateInfoBuilder");
|
30 |
|
31 | _differentialUpdateInfoBuilder = function () {
|
32 | return data;
|
33 | };
|
34 |
|
35 | return data;
|
36 | }
|
37 |
|
38 | function _appBuilder() {
|
39 | const data = require("app-builder-lib/out/util/appBuilder");
|
40 |
|
41 | _appBuilder = function () {
|
42 | return data;
|
43 | };
|
44 |
|
45 | return data;
|
46 | }
|
47 |
|
48 | function _builderUtil() {
|
49 | const data = require("builder-util");
|
50 |
|
51 | _builderUtil = function () {
|
52 | return data;
|
53 | };
|
54 |
|
55 | return data;
|
56 | }
|
57 |
|
58 | function _fs() {
|
59 | const data = require("builder-util/out/fs");
|
60 |
|
61 | _fs = function () {
|
62 | return data;
|
63 | };
|
64 |
|
65 | return data;
|
66 | }
|
67 |
|
68 | function _fsExtra() {
|
69 | const data = require("fs-extra");
|
70 |
|
71 | _fsExtra = function () {
|
72 | return data;
|
73 | };
|
74 |
|
75 | return data;
|
76 | }
|
77 |
|
78 | var path = _interopRequireWildcard(require("path"));
|
79 |
|
80 | function _sanitizeFilename() {
|
81 | const data = _interopRequireDefault(require("sanitize-filename"));
|
82 |
|
83 | _sanitizeFilename = function () {
|
84 | return data;
|
85 | };
|
86 |
|
87 | return data;
|
88 | }
|
89 |
|
90 | function _dmgLicense() {
|
91 | const data = require("./dmgLicense");
|
92 |
|
93 | _dmgLicense = function () {
|
94 | return data;
|
95 | };
|
96 |
|
97 | return data;
|
98 | }
|
99 |
|
100 | function _dmgUtil() {
|
101 | const data = require("./dmgUtil");
|
102 |
|
103 | _dmgUtil = function () {
|
104 | return data;
|
105 | };
|
106 |
|
107 | return data;
|
108 | }
|
109 |
|
110 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
111 |
|
112 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
113 |
|
114 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
115 |
|
116 | class DmgTarget extends _appBuilderLib().Target {
|
117 | constructor(packager, outDir) {
|
118 | super("dmg");
|
119 | this.packager = packager;
|
120 | this.outDir = outDir;
|
121 | this.options = this.packager.config.dmg || Object.create(null);
|
122 | }
|
123 |
|
124 | async build(appPath, arch) {
|
125 | const packager = this.packager;
|
126 |
|
127 | const artifactName = packager.expandArtifactNamePattern(packager.config.dmg, "dmg", null, "${productName}-" + (packager.platformSpecificBuildOptions.bundleShortVersion || "${version}") + ".${ext}");
|
128 | const artifactPath = path.join(this.outDir, artifactName);
|
129 | await packager.info.callArtifactBuildStarted({
|
130 | targetPresentableName: "DMG",
|
131 | file: artifactPath,
|
132 | arch
|
133 | });
|
134 | const volumeName = (0, _sanitizeFilename().default)(this.computeVolumeName(this.options.title));
|
135 | const tempDmg = await createStageDmg((await packager.getTempFile(".dmg")), appPath, volumeName);
|
136 | const specification = await this.computeDmgOptions();
|
137 |
|
138 | const backgroundFile = specification.background == null ? null : await transformBackgroundFileIfNeed(specification.background, packager.info.tempDirManager);
|
139 | const finalSize = await computeAssetSize(packager.info.cancellationToken, tempDmg, specification, backgroundFile);
|
140 | const expandingFinalSize = finalSize * 0.1 + finalSize;
|
141 | await (0, _builderUtil().exec)("hdiutil", ["resize", "-size", expandingFinalSize.toString(), tempDmg]);
|
142 | const volumePath = path.join("/Volumes", volumeName);
|
143 |
|
144 | if (await (0, _fs().exists)(volumePath)) {
|
145 | _builderUtil().log.debug({
|
146 | volumePath
|
147 | }, "unmounting previous disk image");
|
148 |
|
149 | await (0, _dmgUtil().detach)(volumePath);
|
150 | }
|
151 |
|
152 | if (!(await (0, _dmgUtil().attachAndExecute)(tempDmg, true, () => customizeDmg(volumePath, specification, packager, backgroundFile)))) {
|
153 | return;
|
154 | }
|
155 |
|
156 |
|
157 | const args = ["convert", tempDmg, "-ov", "-format", specification.format, "-o", artifactPath];
|
158 |
|
159 | if (specification.format === "UDZO") {
|
160 | args.push("-imagekey", `zlib-level=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL || "9"}`);
|
161 | }
|
162 |
|
163 | await (0, _builderUtil().spawn)("hdiutil", addLogLevel(args));
|
164 |
|
165 | if (this.options.internetEnabled && parseInt(require("os").split(".")[0], 10) < 19) {
|
166 | await (0, _builderUtil().exec)("hdiutil", addLogLevel(["internet-enable"]).concat(artifactPath));
|
167 | }
|
168 |
|
169 | const licenseData = await (0, _dmgLicense().addLicenseToDmg)(packager, artifactPath);
|
170 |
|
171 | if (packager.packagerOptions.effectiveOptionComputed != null) {
|
172 | await packager.packagerOptions.effectiveOptionComputed({
|
173 | licenseData
|
174 | });
|
175 | }
|
176 |
|
177 | if (this.options.sign === true) {
|
178 | await this.signDmg(artifactPath);
|
179 | }
|
180 |
|
181 | const safeArtifactName = packager.computeSafeArtifactName(artifactName, "dmg");
|
182 | const updateInfo = this.options.writeUpdateInfo === false ? null : await (0, _differentialUpdateInfoBuilder().createBlockmap)(artifactPath, this, packager, safeArtifactName);
|
183 | await packager.info.callArtifactBuildCompleted({
|
184 | file: artifactPath,
|
185 | safeArtifactName,
|
186 | target: this,
|
187 | arch,
|
188 | packager,
|
189 | isWriteUpdateInfo: updateInfo != null,
|
190 | updateInfo
|
191 | });
|
192 | }
|
193 |
|
194 | async signDmg(artifactPath) {
|
195 | if (!(0, _macCodeSign().isSignAllowed)(false)) {
|
196 | return;
|
197 | }
|
198 |
|
199 | const packager = this.packager;
|
200 | const qualifier = packager.platformSpecificBuildOptions.identity;
|
201 |
|
202 | if (qualifier === null) {
|
203 |
|
204 | return;
|
205 | }
|
206 |
|
207 | const keychainFile = (await packager.codeSigningInfo.value).keychainFile;
|
208 | const certificateType = "Developer ID Application";
|
209 | let identity = await (0, _macCodeSign().findIdentity)(certificateType, qualifier, keychainFile);
|
210 |
|
211 | if (identity == null) {
|
212 | identity = await (0, _macCodeSign().findIdentity)("Mac Developer", qualifier, keychainFile);
|
213 |
|
214 | if (identity == null) {
|
215 | return;
|
216 | }
|
217 | }
|
218 |
|
219 | const args = ["--sign", identity.hash];
|
220 |
|
221 | if (keychainFile != null) {
|
222 | args.push("--keychain", keychainFile);
|
223 | }
|
224 |
|
225 | args.push(artifactPath);
|
226 | await (0, _builderUtil().exec)("codesign", args);
|
227 | }
|
228 |
|
229 | computeVolumeName(custom) {
|
230 | const appInfo = this.packager.appInfo;
|
231 | const shortVersion = this.packager.platformSpecificBuildOptions.bundleShortVersion || appInfo.version;
|
232 |
|
233 | if (custom == null) {
|
234 | return `${appInfo.productFilename} ${shortVersion}`;
|
235 | }
|
236 |
|
237 | return custom.replace(/\${shortVersion}/g, shortVersion).replace(/\${version}/g, appInfo.version).replace(/\${name}/g, appInfo.name).replace(/\${productName}/g, appInfo.productName);
|
238 | }
|
239 |
|
240 |
|
241 | async computeDmgOptions() {
|
242 | const packager = this.packager;
|
243 | const specification = Object.assign({}, this.options);
|
244 |
|
245 | if (specification.icon == null && specification.icon !== null) {
|
246 | specification.icon = await packager.getIconPath();
|
247 | }
|
248 |
|
249 | if (specification.icon != null && (0, _builderUtil().isEmptyOrSpaces)(specification.icon)) {
|
250 | throw new (_builderUtil().InvalidConfigurationError)("dmg.icon cannot be specified as empty string");
|
251 | }
|
252 |
|
253 | const background = specification.background;
|
254 |
|
255 | if (specification.backgroundColor != null) {
|
256 | if (background != null) {
|
257 | throw new (_builderUtil().InvalidConfigurationError)("Both dmg.backgroundColor and dmg.background are specified — please set the only one");
|
258 | }
|
259 | } else if (background == null) {
|
260 | specification.background = await (0, _dmgUtil().computeBackground)(packager);
|
261 | } else {
|
262 | specification.background = path.resolve(packager.info.projectDir, background);
|
263 | }
|
264 |
|
265 | if (specification.format == null) {
|
266 | if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {
|
267 | specification.format = "UDZO";
|
268 | } else if (packager.compression === "store") {
|
269 | specification.format = "UDRO";
|
270 | } else {
|
271 | specification.format = packager.compression === "maximum" ? "UDBZ" : "UDZO";
|
272 | }
|
273 | }
|
274 |
|
275 | if (specification.contents == null) {
|
276 | specification.contents = [{
|
277 | x: 130,
|
278 | y: 220
|
279 | }, {
|
280 | x: 410,
|
281 | y: 220,
|
282 | type: "link",
|
283 | path: "/Applications"
|
284 | }];
|
285 | }
|
286 |
|
287 | return specification;
|
288 | }
|
289 |
|
290 | }
|
291 |
|
292 | exports.DmgTarget = DmgTarget;
|
293 |
|
294 | async function createStageDmg(tempDmg, appPath, volumeName) {
|
295 |
|
296 | const imageArgs = addLogLevel(["create", "-srcfolder", appPath, "-volname", volumeName, "-anyowners", "-nospotlight", "-format", "UDRW"]);
|
297 | imageArgs.push("-fs", "HFS+", "-fsargs", "-c c=64,a=16,e=16");
|
298 | imageArgs.push(tempDmg);
|
299 | await (0, _builderUtil().spawn)("hdiutil", imageArgs);
|
300 | return tempDmg;
|
301 | }
|
302 |
|
303 | function addLogLevel(args) {
|
304 | args.push(process.env.DEBUG_DMG === "true" ? "-verbose" : "-quiet");
|
305 | return args;
|
306 | }
|
307 |
|
308 | async function computeAssetSize(cancellationToken, dmgFile, specification, backgroundFile) {
|
309 | const asyncTaskManager = new (_builderUtil().AsyncTaskManager)(cancellationToken);
|
310 | asyncTaskManager.addTask((0, _fsExtra().stat)(dmgFile));
|
311 |
|
312 | if (specification.icon != null) {
|
313 | asyncTaskManager.addTask((0, _fs().statOrNull)(specification.icon));
|
314 | }
|
315 |
|
316 | if (backgroundFile != null) {
|
317 | asyncTaskManager.addTask((0, _fsExtra().stat)(backgroundFile));
|
318 | }
|
319 |
|
320 | let result = 32 * 1024;
|
321 |
|
322 | for (const stat of await asyncTaskManager.awaitTasks()) {
|
323 | if (stat != null) {
|
324 | result += stat.size;
|
325 | }
|
326 | }
|
327 |
|
328 | return result;
|
329 | }
|
330 |
|
331 | async function customizeDmg(volumePath, specification, packager, backgroundFile) {
|
332 | const window = specification.window;
|
333 | const env = Object.assign(Object.assign({}, process.env), {
|
334 | volumePath,
|
335 | appFileName: `${packager.appInfo.productFilename}.app`,
|
336 | iconSize: specification.iconSize || 80,
|
337 | iconTextSize: specification.iconTextSize || 12,
|
338 | PYTHONIOENCODING: "utf8"
|
339 | });
|
340 |
|
341 | if (specification.backgroundColor != null || specification.background == null) {
|
342 | env.backgroundColor = specification.backgroundColor || "#ffffff";
|
343 |
|
344 | if (window != null) {
|
345 | env.windowX = (window.x == null ? 100 : window.x).toString();
|
346 | env.windowY = (window.y == null ? 400 : window.y).toString();
|
347 | env.windowWidth = (window.width || 540).toString();
|
348 | env.windowHeight = (window.height || 380).toString();
|
349 | }
|
350 | } else {
|
351 | delete env.backgroundColor;
|
352 | }
|
353 |
|
354 | const args = ["dmg", "--volume", volumePath];
|
355 |
|
356 | if (specification.icon != null) {
|
357 | args.push("--icon", (await packager.getResource(specification.icon)));
|
358 | }
|
359 |
|
360 | if (backgroundFile != null) {
|
361 | args.push("--background", backgroundFile);
|
362 | }
|
363 |
|
364 | const data = await (0, _appBuilder().executeAppBuilderAsJson)(args);
|
365 |
|
366 | if (data.backgroundWidth != null) {
|
367 | env.windowWidth = window == null ? null : window.width;
|
368 | env.windowHeight = window == null ? null : window.height;
|
369 |
|
370 | if (env.windowWidth == null) {
|
371 | env.windowWidth = data.backgroundWidth.toString();
|
372 | }
|
373 |
|
374 | if (env.windowHeight == null) {
|
375 | env.windowHeight = data.backgroundHeight.toString();
|
376 | }
|
377 |
|
378 | if (env.windowX == null) {
|
379 | env.windowX = 400;
|
380 | }
|
381 |
|
382 | if (env.windowY == null) {
|
383 | env.windowY = Math.round((1440 - env.windowHeight) / 2).toString();
|
384 | }
|
385 | }
|
386 |
|
387 | Object.assign(env, data);
|
388 | const asyncTaskManager = new (_builderUtil().AsyncTaskManager)(packager.info.cancellationToken);
|
389 | env.iconLocations = await computeDmgEntries(specification, volumePath, packager, asyncTaskManager);
|
390 | await asyncTaskManager.awaitTasks();
|
391 | await (0, _builderUtil().exec)("/usr/bin/python", [path.join((0, _dmgUtil().getDmgVendorPath)(), "dmgbuild/core.py")], {
|
392 | cwd: (0, _dmgUtil().getDmgVendorPath)(),
|
393 | env
|
394 | });
|
395 | return packager.packagerOptions.effectiveOptionComputed == null || !(await packager.packagerOptions.effectiveOptionComputed({
|
396 | volumePath,
|
397 | specification,
|
398 | packager
|
399 | }));
|
400 | }
|
401 |
|
402 | async function computeDmgEntries(specification, volumePath, packager, asyncTaskManager) {
|
403 | let result = "";
|
404 |
|
405 | for (const c of specification.contents) {
|
406 | if (c.path != null && c.path.endsWith(".app") && c.type !== "link") {
|
407 | _builderUtil().log.warn({
|
408 | path: c.path,
|
409 | reason: "actual path to app will be used instead"
|
410 | }, "do not specify path for application");
|
411 | }
|
412 |
|
413 | const entryPath = c.path || `${packager.appInfo.productFilename}.app`;
|
414 | const entryName = c.name || path.basename(entryPath);
|
415 |
|
416 | if (result.length !== 0) {
|
417 | result += ",\n";
|
418 | }
|
419 |
|
420 | result += `'${entryName}': (${c.x}, ${c.y})`;
|
421 |
|
422 | if (c.type === "link") {
|
423 | asyncTaskManager.addTask((0, _builderUtil().exec)("ln", ["-s", `/${entryPath.startsWith("/") ? entryPath.substring(1) : entryPath}`, `${volumePath}/${entryName}`]));
|
424 | }
|
425 | else if (!(0, _builderUtil().isEmptyOrSpaces)(c.path) && (c.type === "file" || c.type === "dir")) {
|
426 | const source = await packager.getResource(c.path);
|
427 |
|
428 | if (source == null) {
|
429 | _builderUtil().log.warn({
|
430 | entryPath,
|
431 | reason: "doesn't exist"
|
432 | }, "skipped DMG item copying");
|
433 |
|
434 | continue;
|
435 | }
|
436 |
|
437 | const destination = `${volumePath}/${entryName}`;
|
438 | asyncTaskManager.addTask(c.type === "dir" || (await (0, _fsExtra().stat)(source)).isDirectory() ? (0, _fs().copyDir)(source, destination) : (0, _fs().copyFile)(source, destination));
|
439 | }
|
440 | }
|
441 |
|
442 | return result;
|
443 | }
|
444 |
|
445 | async function transformBackgroundFileIfNeed(file, tmpDir) {
|
446 | if (file.endsWith(".tiff") || file.endsWith(".TIFF")) {
|
447 | return file;
|
448 | }
|
449 |
|
450 | const retinaFile = file.replace(/\.([a-z]+)$/, "@2x.$1");
|
451 |
|
452 | if (await (0, _fs().exists)(retinaFile)) {
|
453 | const tiffFile = await tmpDir.getTempFile({
|
454 | suffix: ".tiff"
|
455 | });
|
456 | await (0, _builderUtil().exec)("tiffutil", ["-cathidpicheck", file, retinaFile, "-out", tiffFile]);
|
457 | return tiffFile;
|
458 | }
|
459 |
|
460 | return file;
|
461 | }
|
462 |
|
463 |
|
\ | No newline at end of file |