1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const builder_util_1 = require("builder-util");
|
4 | const fs_1 = require("builder-util/out/fs");
|
5 | const fs_extra_1 = require("fs-extra");
|
6 | const promises_1 = require("fs/promises");
|
7 | const path = require("path");
|
8 | const appInfo_1 = require("../appInfo");
|
9 | const core_1 = require("../core");
|
10 | const errorMessages = require("../errorMessages");
|
11 | const appBuilder_1 = require("../util/appBuilder");
|
12 | const bundledTool_1 = require("../util/bundledTool");
|
13 | const macosVersion_1 = require("../util/macosVersion");
|
14 | const pathManager_1 = require("../util/pathManager");
|
15 | const LinuxTargetHelper_1 = require("./LinuxTargetHelper");
|
16 | const tools_1 = require("./tools");
|
17 | const hash_1 = require("../util/hash");
|
18 | const PublishManager_1 = require("../publish/PublishManager");
|
19 | const builder_util_2 = require("builder-util");
|
20 | class FpmTarget extends core_1.Target {
|
21 | constructor(name, packager, helper, outDir) {
|
22 | super(name, false);
|
23 | this.packager = packager;
|
24 | this.helper = helper;
|
25 | this.outDir = outDir;
|
26 | this.options = { ...this.packager.platformSpecificBuildOptions, ...this.packager.config[this.name] };
|
27 | this.scriptFiles = this.createScripts();
|
28 | }
|
29 | async createScripts() {
|
30 | const defaultTemplatesDir = (0, pathManager_1.getTemplatePath)("linux");
|
31 | const packager = this.packager;
|
32 | const templateOptions = {
|
33 |
|
34 | executable: packager.executableName,
|
35 | sanitizedProductName: packager.appInfo.sanitizedProductName,
|
36 | productFilename: packager.appInfo.productFilename,
|
37 | ...packager.platformSpecificBuildOptions,
|
38 | };
|
39 | function getResource(value, defaultFile) {
|
40 | if (value == null) {
|
41 | return path.join(defaultTemplatesDir, defaultFile);
|
42 | }
|
43 | return path.resolve(packager.projectDir, value);
|
44 | }
|
45 | return await Promise.all([
|
46 | writeConfigFile(packager.info.tempDirManager, getResource(this.options.afterInstall, "after-install.tpl"), templateOptions),
|
47 | writeConfigFile(packager.info.tempDirManager, getResource(this.options.afterRemove, "after-remove.tpl"), templateOptions),
|
48 | ]);
|
49 | }
|
50 | checkOptions() {
|
51 | return this.computeFpmMetaInfoOptions();
|
52 | }
|
53 | async computeFpmMetaInfoOptions() {
|
54 | var _a;
|
55 | const packager = this.packager;
|
56 | const projectUrl = await packager.appInfo.computePackageUrl();
|
57 | const errors = [];
|
58 | if (projectUrl == null) {
|
59 | errors.push("Please specify project homepage, see https://electron.build/configuration/configuration#Metadata-homepage");
|
60 | }
|
61 | const options = this.options;
|
62 | let author = options.maintainer;
|
63 | if (author == null) {
|
64 | const a = packager.info.metadata.author;
|
65 | if (a == null || a.email == null) {
|
66 | errors.push(errorMessages.authorEmailIsMissed);
|
67 | }
|
68 | else {
|
69 | author = `${a.name} <${a.email}>`;
|
70 | }
|
71 | }
|
72 | if (errors.length > 0) {
|
73 | throw new Error(errors.join("\n\n"));
|
74 | }
|
75 | return {
|
76 | name: (_a = options.packageName) !== null && _a !== void 0 ? _a : this.packager.appInfo.linuxPackageName,
|
77 | maintainer: author,
|
78 | url: projectUrl,
|
79 | vendor: options.vendor || author,
|
80 | };
|
81 | }
|
82 | async build(appOutDir, arch) {
|
83 | var _a;
|
84 | const target = this.name;
|
85 |
|
86 | let nameFormat = "${name}-${version}-${arch}.${ext}";
|
87 | let isUseArchIfX64 = false;
|
88 | if (target === "deb") {
|
89 | nameFormat = "${name}_${version}_${arch}.${ext}";
|
90 | isUseArchIfX64 = true;
|
91 | }
|
92 | else if (target === "rpm") {
|
93 | nameFormat = "${name}-${version}.${arch}.${ext}";
|
94 | isUseArchIfX64 = true;
|
95 | }
|
96 | const packager = this.packager;
|
97 | const artifactName = packager.expandArtifactNamePattern(this.options, target, arch, nameFormat, !isUseArchIfX64);
|
98 | const artifactPath = path.join(this.outDir, artifactName);
|
99 | await packager.info.callArtifactBuildStarted({
|
100 | targetPresentableName: target,
|
101 | file: artifactPath,
|
102 | arch,
|
103 | });
|
104 | await (0, fs_1.unlinkIfExists)(artifactPath);
|
105 | if (packager.packagerOptions.prepackaged != null) {
|
106 | await (0, promises_1.mkdir)(this.outDir, { recursive: true });
|
107 | }
|
108 | const publishConfig = this.supportsAutoUpdate(target)
|
109 | ? await (0, PublishManager_1.getAppUpdatePublishConfiguration)(packager, arch, false )
|
110 | : null;
|
111 | if (publishConfig != null) {
|
112 | const linuxDistType = this.packager.packagerOptions.prepackaged || path.join(this.outDir, `linux${(0, builder_util_1.getArchSuffix)(arch)}-unpacked`);
|
113 | const resourceDir = packager.getResourcesDir(linuxDistType);
|
114 | builder_util_1.log.info({ resourceDir }, `adding autoupdate files for: ${target}. (Beta feature)`);
|
115 | await (0, fs_extra_1.outputFile)(path.join(resourceDir, "app-update.yml"), (0, builder_util_1.serializeToYaml)(publishConfig));
|
116 |
|
117 | await (0, fs_extra_1.outputFile)(path.join(resourceDir, "package-type"), target);
|
118 | }
|
119 | const scripts = await this.scriptFiles;
|
120 | const appInfo = packager.appInfo;
|
121 | const options = this.options;
|
122 | const synopsis = options.synopsis;
|
123 | const args = [
|
124 | "--architecture",
|
125 | (0, builder_util_1.toLinuxArchString)(arch, target),
|
126 | "--after-install",
|
127 | scripts[0],
|
128 | "--after-remove",
|
129 | scripts[1],
|
130 | "--description",
|
131 | (0, appInfo_1.smarten)(target === "rpm" ? this.helper.getDescription(options) : `${synopsis || ""}\n ${this.helper.getDescription(options)}`),
|
132 | "--version",
|
133 | this.helper.getSanitizedVersion(target),
|
134 | "--package",
|
135 | artifactPath,
|
136 | ];
|
137 | (0, appBuilder_1.objectToArgs)(args, (await this.computeFpmMetaInfoOptions()));
|
138 | const packageCategory = options.packageCategory;
|
139 | if (packageCategory != null) {
|
140 | args.push("--category", packageCategory);
|
141 | }
|
142 | if (target === "deb") {
|
143 | args.push("--deb-priority", (_a = options.priority) !== null && _a !== void 0 ? _a : "optional");
|
144 | }
|
145 | else if (target === "rpm") {
|
146 | if (synopsis != null) {
|
147 | args.push("--rpm-summary", (0, appInfo_1.smarten)(synopsis));
|
148 | }
|
149 | }
|
150 | const fpmConfiguration = {
|
151 | args,
|
152 | target,
|
153 | };
|
154 | if (options.compression != null) {
|
155 | fpmConfiguration.compression = options.compression;
|
156 | }
|
157 |
|
158 | const depends = options.depends;
|
159 | if (depends != null) {
|
160 | if (Array.isArray(depends)) {
|
161 | fpmConfiguration.customDepends = depends;
|
162 | }
|
163 | else {
|
164 |
|
165 | if (typeof depends === "string") {
|
166 | fpmConfiguration.customDepends = [depends];
|
167 | }
|
168 | else {
|
169 | throw new Error(`depends must be Array or String, but specified as: ${depends}`);
|
170 | }
|
171 | }
|
172 | }
|
173 | if (target === "deb") {
|
174 | const recommends = options.recommends;
|
175 | if (recommends) {
|
176 | fpmConfiguration.customRecommends = (0, builder_util_1.asArray)(recommends);
|
177 | }
|
178 | }
|
179 | (0, builder_util_1.use)(packager.info.metadata.license, it => args.push("--license", it));
|
180 | (0, builder_util_1.use)(appInfo.buildNumber, it => args.push("--iteration",
|
181 |
|
182 |
|
183 | it.split("-").join("_")));
|
184 | (0, builder_util_1.use)(options.fpm, it => args.push(...it));
|
185 | args.push(`${appOutDir}/=${LinuxTargetHelper_1.installPrefix}/${appInfo.sanitizedProductName}`);
|
186 | for (const icon of await this.helper.icons) {
|
187 | const extWithDot = path.extname(icon.file);
|
188 | const sizeName = extWithDot === ".svg" ? "scalable" : `${icon.size}x${icon.size}`;
|
189 | args.push(`${icon.file}=/usr/share/icons/hicolor/${sizeName}/apps/${packager.executableName}${extWithDot}`);
|
190 | }
|
191 | const mimeTypeFilePath = await this.helper.mimeTypeFiles;
|
192 | if (mimeTypeFilePath != null) {
|
193 | args.push(`${mimeTypeFilePath}=/usr/share/mime/packages/${packager.executableName}.xml`);
|
194 | }
|
195 | const desktopFilePath = await this.helper.writeDesktopEntry(this.options);
|
196 | args.push(`${desktopFilePath}=/usr/share/applications/${packager.executableName}.desktop`);
|
197 | if (packager.packagerOptions.effectiveOptionComputed != null && (await packager.packagerOptions.effectiveOptionComputed([args, desktopFilePath]))) {
|
198 | return;
|
199 | }
|
200 | const env = {
|
201 | ...process.env,
|
202 | SZA_PATH: await (0, builder_util_2.getPath7za)(),
|
203 | SZA_COMPRESSION_LEVEL: packager.compression === "store" ? "0" : "9",
|
204 | };
|
205 |
|
206 |
|
207 | if (target !== "rpm" && (await (0, macosVersion_1.isMacOsSierra)())) {
|
208 | const linuxToolsPath = await (0, tools_1.getLinuxToolsPath)();
|
209 | Object.assign(env, {
|
210 | PATH: (0, bundledTool_1.computeEnv)(process.env.PATH, [path.join(linuxToolsPath, "bin")]),
|
211 | DYLD_LIBRARY_PATH: (0, bundledTool_1.computeEnv)(process.env.DYLD_LIBRARY_PATH, [path.join(linuxToolsPath, "lib")]),
|
212 | });
|
213 | }
|
214 | await (0, builder_util_1.executeAppBuilder)(["fpm", "--configuration", JSON.stringify(fpmConfiguration)], undefined, { env });
|
215 | let info = {
|
216 | file: artifactPath,
|
217 | target: this,
|
218 | arch,
|
219 | packager,
|
220 | };
|
221 | if (publishConfig != null) {
|
222 | info = {
|
223 | ...info,
|
224 | safeArtifactName: packager.computeSafeArtifactName(artifactName, target, arch, !isUseArchIfX64),
|
225 | isWriteUpdateInfo: true,
|
226 | updateInfo: {
|
227 | sha512: await (0, hash_1.hashFile)(artifactPath),
|
228 | size: (await (0, fs_extra_1.stat)(artifactPath)).size,
|
229 | },
|
230 | };
|
231 | }
|
232 | await packager.info.callArtifactBuildCompleted(info);
|
233 | }
|
234 | supportsAutoUpdate(target) {
|
235 | return ["deb", "rpm"].includes(target);
|
236 | }
|
237 | }
|
238 | exports.default = FpmTarget;
|
239 | async function writeConfigFile(tmpDir, templatePath, options) {
|
240 |
|
241 | function replacer(match, p1) {
|
242 | if (p1 in options) {
|
243 | return options[p1];
|
244 | }
|
245 | else {
|
246 | throw new Error(`Macro ${p1} is not defined`);
|
247 | }
|
248 | }
|
249 | const config = (await (0, promises_1.readFile)(templatePath, "utf8")).replace(/\${([a-zA-Z]+)}/g, replacer).replace(/<%=([a-zA-Z]+)%>/g, (match, p1) => {
|
250 | builder_util_1.log.warn("<%= varName %> is deprecated, please use ${varName} instead");
|
251 | return replacer(match, p1.trim());
|
252 | });
|
253 | const outputPath = await tmpDir.getTempFile({ suffix: path.basename(templatePath, ".tpl") });
|
254 | await (0, fs_extra_1.outputFile)(outputPath, config);
|
255 | return outputPath;
|
256 | }
|
257 |
|
\ | No newline at end of file |