UNPKG

11.1 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.unlinkIfExists = unlinkIfExists;
7exports.statOrNull = statOrNull;
8exports.exists = exists;
9exports.walk = walk;
10exports.copyFile = copyFile;
11exports.copyOrLinkFile = copyOrLinkFile;
12exports.copyDir = copyDir;
13exports.USE_HARD_LINKS = exports.DO_NOT_USE_HARD_LINKS = exports.FileCopier = exports.CopyFileTransformer = exports.CONCURRENCY = exports.MAX_FILE_REQUESTS = void 0;
14
15function _bluebirdLst() {
16 const data = _interopRequireDefault(require("bluebird-lst"));
17
18 _bluebirdLst = function () {
19 return data;
20 };
21
22 return data;
23}
24
25function _fsExtra() {
26 const data = require("fs-extra");
27
28 _fsExtra = function () {
29 return data;
30 };
31
32 return data;
33}
34
35var path = _interopRequireWildcard(require("path"));
36
37function _statMode() {
38 const data = require("stat-mode");
39
40 _statMode = function () {
41 return data;
42 };
43
44 return data;
45}
46
47function _log() {
48 const data = require("./log");
49
50 _log = function () {
51 return data;
52 };
53
54 return data;
55}
56
57function _promise() {
58 const data = require("./promise");
59
60 _promise = function () {
61 return data;
62 };
63
64 return data;
65}
66
67function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
68
69function _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; }
70
71function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
72
73const MAX_FILE_REQUESTS = 8;
74exports.MAX_FILE_REQUESTS = MAX_FILE_REQUESTS;
75const CONCURRENCY = {
76 concurrency: MAX_FILE_REQUESTS
77};
78exports.CONCURRENCY = CONCURRENCY;
79
80class CopyFileTransformer {
81 constructor(afterCopyTransformer) {
82 this.afterCopyTransformer = afterCopyTransformer;
83 }
84
85}
86
87exports.CopyFileTransformer = CopyFileTransformer;
88
89function unlinkIfExists(file) {
90 return (0, _fsExtra().unlink)(file).catch(() => {});
91}
92
93async function statOrNull(file) {
94 return (0, _promise().orNullIfFileNotExist)((0, _fsExtra().stat)(file));
95}
96
97async function exists(file) {
98 try {
99 await (0, _fsExtra().access)(file);
100 return true;
101 } catch (e) {
102 return false;
103 }
104}
105/**
106 * Returns list of file paths (system-dependent file separator)
107 */
108
109
110async function walk(initialDirPath, filter, consumer) {
111 let result = [];
112 const queue = [initialDirPath];
113 let addDirToResult = false;
114 const isIncludeDir = consumer == null ? false : consumer.isIncludeDir === true;
115
116 while (queue.length > 0) {
117 const dirPath = queue.pop();
118
119 if (isIncludeDir) {
120 if (addDirToResult) {
121 result.push(dirPath);
122 } else {
123 addDirToResult = true;
124 }
125 }
126
127 const childNames = await (0, _promise().orIfFileNotExist)((0, _fsExtra().readdir)(dirPath), []);
128 childNames.sort();
129 let nodeModuleContent = null;
130 const dirs = []; // our handler is async, but we should add sorted files, so, we add file to result not in the mapper, but after map
131
132 const sortedFilePaths = await _bluebirdLst().default.map(childNames, name => {
133 if (name === ".DS_Store" || name === ".gitkeep") {
134 return null;
135 }
136
137 const filePath = dirPath + path.sep + name;
138 return (0, _fsExtra().lstat)(filePath).then(stat => {
139 if (filter != null && !filter(filePath, stat)) {
140 return null;
141 }
142
143 const consumerResult = consumer == null ? null : consumer.consume(filePath, stat, dirPath, childNames);
144
145 if (consumerResult === false) {
146 return null;
147 } else if (consumerResult == null || !("then" in consumerResult)) {
148 if (stat.isDirectory()) {
149 dirs.push(name);
150 return null;
151 } else {
152 return filePath;
153 }
154 } else {
155 return consumerResult.then(it => {
156 if (it != null && Array.isArray(it)) {
157 nodeModuleContent = it;
158 return null;
159 } // asarUtil can return modified stat (symlink handling)
160
161
162 if ((it != null && "isDirectory" in it ? it : stat).isDirectory()) {
163 dirs.push(name);
164 return null;
165 } else {
166 return filePath;
167 }
168 });
169 }
170 });
171 }, CONCURRENCY);
172
173 for (const child of sortedFilePaths) {
174 if (child != null) {
175 result.push(child);
176 }
177 }
178
179 dirs.sort();
180
181 for (const child of dirs) {
182 queue.push(dirPath + path.sep + child);
183 }
184
185 if (nodeModuleContent != null) {
186 result = result.concat(nodeModuleContent);
187 }
188 }
189
190 return result;
191}
192
193const _isUseHardLink = process.platform !== "win32" && process.env.USE_HARD_LINKS !== "false" && (require("is-ci") || process.env.USE_HARD_LINKS === "true");
194
195function copyFile(src, dest, isEnsureDir = true) {
196 return (isEnsureDir ? (0, _fsExtra().ensureDir)(path.dirname(dest)) : Promise.resolve()).then(() => copyOrLinkFile(src, dest, null, false));
197}
198/**
199 * Hard links is used if supported and allowed.
200 * File permission is fixed — allow execute for all if owner can, allow read for all if owner can.
201 *
202 * ensureDir is not called, dest parent dir must exists
203 */
204
205
206function copyOrLinkFile(src, dest, stats, isUseHardLink, exDevErrorHandler) {
207 if (isUseHardLink === undefined) {
208 isUseHardLink = _isUseHardLink;
209 }
210
211 if (stats != null) {
212 const originalModeNumber = stats.mode;
213 const mode = new (_statMode().Mode)(stats);
214
215 if (mode.owner.execute) {
216 mode.group.execute = true;
217 mode.others.execute = true;
218 }
219
220 mode.group.read = true;
221 mode.others.read = true;
222 mode.setuid = false;
223 mode.setgid = false;
224
225 if (originalModeNumber !== stats.mode) {
226 if (_log().log.isDebugEnabled) {
227 const oldMode = new (_statMode().Mode)({
228 mode: originalModeNumber
229 });
230
231 _log().log.debug({
232 file: dest,
233 oldMode,
234 mode
235 }, "permissions fixed from");
236 } // https://helgeklein.com/blog/2009/05/hard-links-and-permissions-acls/
237 // Permissions on all hard links to the same data on disk are always identical. The same applies to attributes.
238 // That means if you change the permissions/owner/attributes on one hard link, you will immediately see the changes on all other hard links.
239
240
241 if (isUseHardLink) {
242 isUseHardLink = false;
243
244 _log().log.debug({
245 dest
246 }, "copied, but not linked, because file permissions need to be fixed");
247 }
248 }
249 }
250
251 if (isUseHardLink) {
252 return (0, _fsExtra().link)(src, dest).catch(e => {
253 if (e.code === "EXDEV") {
254 const isLog = exDevErrorHandler == null ? true : exDevErrorHandler();
255
256 if (isLog && _log().log.isDebugEnabled) {
257 _log().log.debug({
258 error: e.message
259 }, "cannot copy using hard link");
260 }
261
262 return doCopyFile(src, dest, stats);
263 } else {
264 throw e;
265 }
266 });
267 }
268
269 return doCopyFile(src, dest, stats);
270}
271
272function doCopyFile(src, dest, stats) {
273 const promise = (0, _fsExtra().copyFile)(src, dest);
274
275 if (stats == null) {
276 return promise;
277 }
278
279 return promise.then(() => (0, _fsExtra().chmod)(dest, stats.mode));
280}
281
282class FileCopier {
283 constructor(isUseHardLinkFunction, transformer) {
284 this.isUseHardLinkFunction = isUseHardLinkFunction;
285 this.transformer = transformer;
286
287 if (isUseHardLinkFunction === USE_HARD_LINKS) {
288 this.isUseHardLink = true;
289 } else {
290 this.isUseHardLink = _isUseHardLink && isUseHardLinkFunction !== DO_NOT_USE_HARD_LINKS;
291 }
292 }
293
294 async copy(src, dest, stat) {
295 let afterCopyTransformer = null;
296
297 if (this.transformer != null && stat != null && stat.isFile()) {
298 let data = this.transformer(src);
299
300 if (data != null) {
301 if (typeof data === "object" && "then" in data) {
302 data = await data;
303 }
304
305 if (data != null) {
306 if (data instanceof CopyFileTransformer) {
307 afterCopyTransformer = data.afterCopyTransformer;
308 } else {
309 await (0, _fsExtra().writeFile)(dest, data);
310 return;
311 }
312 }
313 }
314 }
315
316 const isUseHardLink = afterCopyTransformer == null && (!this.isUseHardLink || this.isUseHardLinkFunction == null ? this.isUseHardLink : this.isUseHardLinkFunction(dest));
317 await copyOrLinkFile(src, dest, stat, isUseHardLink, isUseHardLink ? () => {
318 // files are copied concurrently, so, we must not check here currentIsUseHardLink — our code can be executed after that other handler will set currentIsUseHardLink to false
319 if (this.isUseHardLink) {
320 this.isUseHardLink = false;
321 return true;
322 } else {
323 return false;
324 }
325 } : null);
326
327 if (afterCopyTransformer != null) {
328 await afterCopyTransformer(dest);
329 }
330 }
331
332}
333/**
334 * Empty directories is never created.
335 * Hard links is used if supported and allowed.
336 */
337
338
339exports.FileCopier = FileCopier;
340
341function copyDir(src, destination, options = {}) {
342 const fileCopier = new FileCopier(options.isUseHardLink, options.transformer);
343
344 if (_log().log.isDebugEnabled) {
345 _log().log.debug({
346 src,
347 destination
348 }, `copying${fileCopier.isUseHardLink ? " using hard links" : ""}`);
349 }
350
351 const createdSourceDirs = new Set();
352 const links = [];
353 return walk(src, options.filter, {
354 consume: async (file, stat, parent) => {
355 if (!stat.isFile() && !stat.isSymbolicLink()) {
356 return;
357 }
358
359 if (!createdSourceDirs.has(parent)) {
360 await (0, _fsExtra().ensureDir)(parent.replace(src, destination));
361 createdSourceDirs.add(parent);
362 }
363
364 const destFile = file.replace(src, destination);
365
366 if (stat.isFile()) {
367 await fileCopier.copy(file, destFile, stat);
368 } else {
369 links.push({
370 file: destFile,
371 link: await (0, _fsExtra().readlink)(file)
372 });
373 }
374 }
375 }).then(() => _bluebirdLst().default.map(links, it => (0, _fsExtra().symlink)(it.link, it.file), CONCURRENCY));
376} // eslint-disable-next-line @typescript-eslint/no-unused-vars
377
378
379const DO_NOT_USE_HARD_LINKS = file => false; // eslint-disable-next-line @typescript-eslint/no-unused-vars
380
381
382exports.DO_NOT_USE_HARD_LINKS = DO_NOT_USE_HARD_LINKS;
383
384const USE_HARD_LINKS = file => true; exports.USE_HARD_LINKS = USE_HARD_LINKS;
385// __ts-babel@6.0.4
386//# sourceMappingURL=fs.js.map
\No newline at end of file