UNPKG

12.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.copyFiles = exports.getFileMatchers = exports.getNodeModuleFileMatcher = exports.getMainFileMatchers = exports.FileMatcher = exports.excludedExts = exports.excludedNames = void 0;
4const bluebird_lst_1 = require("bluebird-lst");
5const builder_util_1 = require("builder-util");
6const fs_1 = require("builder-util/out/fs");
7const promises_1 = require("fs/promises");
8const minimatch_1 = require("minimatch");
9const path = require("path");
10const filter_1 = require("./util/filter");
11// https://github.com/electron-userland/electron-builder/issues/733
12const minimatchOptions = { dot: true };
13// noinspection SpellCheckingInspection
14exports.excludedNames = ".git,.hg,.svn,CVS,RCS,SCCS," +
15 "__pycache__,.DS_Store,thumbs.db,.gitignore,.gitkeep,.gitattributes,.npmignore," +
16 ".idea,.vs,.flowconfig,.jshintrc,.eslintrc,.circleci," +
17 ".yarn-integrity,.yarn-metadata.json,yarn-error.log,yarn.lock,package-lock.json,npm-debug.log," +
18 "appveyor.yml,.travis.yml,circle.yml,.nyc_output,.husky,.github,electron-builder.env";
19exports.excludedExts = "iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts," +
20 // https://github.com/electron-userland/electron-builder/issues/7512
21 "mk,a,o,forge-meta";
22function ensureNoEndSlash(file) {
23 if (path.sep !== "/") {
24 file = file.replace(/\//g, path.sep);
25 }
26 if (path.sep !== "\\") {
27 file = file.replace(/\\/g, path.sep);
28 }
29 if (file.endsWith(path.sep)) {
30 return file.substring(0, file.length - 1);
31 }
32 else {
33 return file;
34 }
35}
36/** @internal */
37class FileMatcher {
38 constructor(from, to, macroExpander, patterns) {
39 this.macroExpander = macroExpander;
40 this.excludePatterns = null;
41 this.from = ensureNoEndSlash(macroExpander(from));
42 this.to = ensureNoEndSlash(macroExpander(to));
43 this.patterns = (0, builder_util_1.asArray)(patterns).map(it => this.normalizePattern(it));
44 this.isSpecifiedAsEmptyArray = Array.isArray(patterns) && patterns.length === 0;
45 }
46 normalizePattern(pattern) {
47 if (pattern.startsWith("./")) {
48 pattern = pattern.substring("./".length);
49 }
50 return path.posix.normalize(this.macroExpander(pattern.replace(/\\/g, "/")));
51 }
52 addPattern(pattern) {
53 this.patterns.push(this.normalizePattern(pattern));
54 }
55 prependPattern(pattern) {
56 this.patterns.unshift(this.normalizePattern(pattern));
57 }
58 isEmpty() {
59 return this.patterns.length === 0;
60 }
61 containsOnlyIgnore() {
62 return !this.isEmpty() && this.patterns.find(it => !it.startsWith("!")) == null;
63 }
64 computeParsedPatterns(result, fromDir) {
65 const relativeFrom = fromDir == null ? null : path.relative(fromDir, this.from);
66 if (this.patterns.length === 0 && relativeFrom != null) {
67 // file mappings, from here is a file
68 result.push(new minimatch_1.Minimatch(relativeFrom, minimatchOptions));
69 return;
70 }
71 for (let pattern of this.patterns) {
72 if (relativeFrom != null) {
73 pattern = path.join(relativeFrom, pattern);
74 }
75 const parsedPattern = new minimatch_1.Minimatch(pattern, minimatchOptions);
76 result.push(parsedPattern);
77 // do not add if contains dot (possibly file if has extension)
78 if (!pattern.includes(".") && !(0, filter_1.hasMagic)(parsedPattern)) {
79 // https://github.com/electron-userland/electron-builder/issues/545
80 // add **/*
81 result.push(new minimatch_1.Minimatch(`${pattern}/**/*`, minimatchOptions));
82 }
83 }
84 }
85 createFilter() {
86 const parsedPatterns = [];
87 this.computeParsedPatterns(parsedPatterns);
88 return (0, filter_1.createFilter)(this.from, parsedPatterns, this.excludePatterns);
89 }
90 toString() {
91 return `from: ${this.from}, to: ${this.to}, patterns: ${this.patterns.join(", ")}`;
92 }
93}
94exports.FileMatcher = FileMatcher;
95/** @internal */
96function getMainFileMatchers(appDir, destination, macroExpander, platformSpecificBuildOptions, platformPackager, outDir, isElectronCompile) {
97 const packager = platformPackager.info;
98 const buildResourceDir = path.resolve(packager.projectDir, packager.buildResourcesDir);
99 let matchers = packager.isPrepackedAppAsar
100 ? null
101 : getFileMatchers(packager.config, "files", destination, {
102 macroExpander,
103 customBuildOptions: platformSpecificBuildOptions,
104 globalOutDir: outDir,
105 defaultSrc: appDir,
106 });
107 if (matchers == null) {
108 matchers = [new FileMatcher(appDir, destination, macroExpander)];
109 }
110 const matcher = matchers[0];
111 // add default patterns, but only if from equals to app dir
112 if (matcher.from !== appDir) {
113 return matchers;
114 }
115 // https://github.com/electron-userland/electron-builder/issues/1741#issuecomment-311111418 so, do not use inclusive patterns
116 const patterns = matcher.patterns;
117 const customFirstPatterns = [];
118 // electron-webpack - we need to copy only package.json and node_modules from root dir (and these files are added by default), so, explicit empty array is specified
119 if (!matcher.isSpecifiedAsEmptyArray && (matcher.isEmpty() || matcher.containsOnlyIgnore())) {
120 customFirstPatterns.push("**/*");
121 }
122 else if (!patterns.includes("package.json")) {
123 patterns.push("package.json");
124 }
125 customFirstPatterns.push("!**/node_modules");
126 // https://github.com/electron-userland/electron-builder/issues/1482
127 const relativeBuildResourceDir = path.relative(matcher.from, buildResourceDir);
128 if (relativeBuildResourceDir.length !== 0 && !relativeBuildResourceDir.startsWith(".")) {
129 customFirstPatterns.push(`!${relativeBuildResourceDir}{,/**/*}`);
130 }
131 const relativeOutDir = matcher.normalizePattern(path.relative(packager.projectDir, outDir));
132 if (!relativeOutDir.startsWith(".")) {
133 customFirstPatterns.push(`!${relativeOutDir}{,/**/*}`);
134 }
135 // add our default exclusions after last user possibly defined "all"/permissive pattern
136 let insertIndex = 0;
137 for (let i = patterns.length - 1; i >= 0; i--) {
138 if (patterns[i].startsWith("**/")) {
139 insertIndex = i + 1;
140 break;
141 }
142 }
143 patterns.splice(insertIndex, 0, ...customFirstPatterns);
144 patterns.push(`!**/*.{${exports.excludedExts}${packager.config.includePdb === true ? "" : ",pdb"}}`);
145 patterns.push("!**/._*");
146 patterns.push("!**/electron-builder.{yaml,yml,json,json5,toml,ts}");
147 patterns.push(`!**/{${exports.excludedNames}}`);
148 if (isElectronCompile) {
149 patterns.push("!.cache{,/**/*}");
150 }
151 patterns.push("!.yarn{,/**/*}");
152 // https://github.com/electron-userland/electron-builder/issues/1969
153 // exclude ony for app root, use .yarnclean to clean node_modules
154 patterns.push("!.editorconfig");
155 patterns.push("!.yarnrc.yml");
156 const debugLogger = packager.debugLogger;
157 if (debugLogger.isEnabled) {
158 //tslint:disable-next-line:no-invalid-template-strings
159 debugLogger.add(`${macroExpander("${arch}")}.firstOrDefaultFilePatterns`, patterns);
160 }
161 return matchers;
162}
163exports.getMainFileMatchers = getMainFileMatchers;
164/** @internal */
165function getNodeModuleFileMatcher(appDir, destination, macroExpander, platformSpecificBuildOptions, packager) {
166 // https://github.com/electron-userland/electron-builder/pull/2948#issuecomment-392241632
167 // grab only excludes
168 const matcher = new FileMatcher(appDir, destination, macroExpander);
169 function addPatterns(patterns) {
170 if (patterns == null) {
171 return;
172 }
173 else if (!Array.isArray(patterns)) {
174 if (typeof patterns === "string" && patterns.startsWith("!")) {
175 matcher.addPattern(patterns);
176 return;
177 }
178 // ignore object form
179 return;
180 }
181 for (const pattern of patterns) {
182 if (typeof pattern === "string") {
183 if (pattern.startsWith("!")) {
184 matcher.addPattern(pattern);
185 }
186 }
187 else {
188 const fileSet = pattern;
189 if (fileSet.from == null || fileSet.from === ".") {
190 for (const p of (0, builder_util_1.asArray)(fileSet.filter)) {
191 matcher.addPattern(p);
192 }
193 }
194 }
195 }
196 }
197 addPatterns(packager.config.files);
198 addPatterns(platformSpecificBuildOptions.files);
199 if (!matcher.isEmpty()) {
200 matcher.prependPattern("**/*");
201 }
202 const debugLogger = packager.debugLogger;
203 if (debugLogger.isEnabled) {
204 //tslint:disable-next-line:no-invalid-template-strings
205 debugLogger.add(`${macroExpander("${arch}")}.nodeModuleFilePatterns`, matcher.patterns);
206 }
207 return matcher;
208}
209exports.getNodeModuleFileMatcher = getNodeModuleFileMatcher;
210/** @internal */
211function getFileMatchers(config, name, defaultDestination, options) {
212 const defaultMatcher = new FileMatcher(options.defaultSrc, defaultDestination, options.macroExpander);
213 const fileMatchers = [];
214 function addPatterns(patterns) {
215 if (patterns == null) {
216 return;
217 }
218 else if (!Array.isArray(patterns)) {
219 if (typeof patterns === "string") {
220 defaultMatcher.addPattern(patterns);
221 return;
222 }
223 patterns = [patterns];
224 }
225 for (const pattern of patterns) {
226 if (typeof pattern === "string") {
227 // use normalize to transform ./foo to foo
228 defaultMatcher.addPattern(pattern);
229 }
230 else if (name === "asarUnpack") {
231 throw new Error(`Advanced file copying not supported for "${name}"`);
232 }
233 else {
234 const from = pattern.from == null ? options.defaultSrc : path.resolve(options.defaultSrc, pattern.from);
235 const to = pattern.to == null ? defaultDestination : path.resolve(defaultDestination, pattern.to);
236 fileMatchers.push(new FileMatcher(from, to, options.macroExpander, pattern.filter));
237 }
238 }
239 }
240 if (name !== "extraDistFiles") {
241 addPatterns(config[name]);
242 }
243 addPatterns(options.customBuildOptions[name]);
244 if (!defaultMatcher.isEmpty()) {
245 // default matcher should be first in the array
246 fileMatchers.unshift(defaultMatcher);
247 }
248 // we cannot exclude the whole out dir, because sometimes users want to use some file in the out dir in the patterns
249 const relativeOutDir = defaultMatcher.normalizePattern(path.relative(options.defaultSrc, options.globalOutDir));
250 if (!relativeOutDir.startsWith(".")) {
251 defaultMatcher.addPattern(`!${relativeOutDir}/*-unpacked{,/**/*}`);
252 }
253 return fileMatchers.length === 0 ? null : fileMatchers;
254}
255exports.getFileMatchers = getFileMatchers;
256/** @internal */
257function copyFiles(matchers, transformer, isUseHardLink) {
258 if (matchers == null || matchers.length === 0) {
259 return Promise.resolve();
260 }
261 return bluebird_lst_1.default.map(matchers, async (matcher) => {
262 const fromStat = await (0, fs_1.statOrNull)(matcher.from);
263 if (fromStat == null) {
264 builder_util_1.log.warn({ from: matcher.from }, `file source doesn't exist`);
265 return;
266 }
267 if (fromStat.isFile()) {
268 const toStat = await (0, fs_1.statOrNull)(matcher.to);
269 // https://github.com/electron-userland/electron-builder/issues/1245
270 if (toStat != null && toStat.isDirectory()) {
271 return await (0, fs_1.copyOrLinkFile)(matcher.from, path.join(matcher.to, path.basename(matcher.from)), fromStat, isUseHardLink);
272 }
273 await (0, promises_1.mkdir)(path.dirname(matcher.to), { recursive: true });
274 return await (0, fs_1.copyOrLinkFile)(matcher.from, matcher.to, fromStat);
275 }
276 if (matcher.isEmpty() || matcher.containsOnlyIgnore()) {
277 matcher.prependPattern("**/*");
278 }
279 builder_util_1.log.debug({ matcher }, "copying files using pattern");
280 return await (0, fs_1.copyDir)(matcher.from, matcher.to, { filter: matcher.createFilter(), transformer, isUseHardLink: isUseHardLink ? fs_1.USE_HARD_LINKS : null });
281 });
282}
283exports.copyFiles = copyFiles;
284//# sourceMappingURL=fileMatcher.js.map
\No newline at end of file