@appium/support 7.1.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/console.d.ts +2 -2
- package/build/lib/console.d.ts.map +1 -1
- package/build/lib/console.js +4 -5
- package/build/lib/console.js.map +1 -1
- package/build/lib/doctor.d.ts +6 -6
- package/build/lib/doctor.d.ts.map +1 -1
- package/build/lib/doctor.js +7 -7
- package/build/lib/doctor.js.map +1 -1
- package/build/lib/env.d.ts +12 -5
- package/build/lib/env.d.ts.map +1 -1
- package/build/lib/env.js +5 -5
- package/build/lib/env.js.map +1 -1
- package/build/lib/fs.d.ts.map +1 -1
- package/build/lib/fs.js +11 -14
- package/build/lib/fs.js.map +1 -1
- package/build/lib/image-util.d.ts.map +1 -1
- package/build/lib/image-util.js +1 -1
- package/build/lib/image-util.js.map +1 -1
- package/build/lib/index.d.ts +1 -1
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/logging.d.ts.map +1 -1
- package/build/lib/logging.js +5 -8
- package/build/lib/logging.js.map +1 -1
- package/build/lib/mjpeg.d.ts.map +1 -1
- package/build/lib/mjpeg.js +7 -7
- package/build/lib/mjpeg.js.map +1 -1
- package/build/lib/net.d.ts.map +1 -1
- package/build/lib/net.js +21 -14
- package/build/lib/net.js.map +1 -1
- package/build/lib/node.d.ts.map +1 -1
- package/build/lib/node.js +7 -8
- package/build/lib/node.js.map +1 -1
- package/build/lib/npm.d.ts.map +1 -1
- package/build/lib/npm.js +3 -3
- package/build/lib/npm.js.map +1 -1
- package/build/lib/plist.js +11 -11
- package/build/lib/plist.js.map +1 -1
- package/build/lib/process.d.ts.map +1 -1
- package/build/lib/process.js +2 -2
- package/build/lib/process.js.map +1 -1
- package/build/lib/system.d.ts.map +1 -1
- package/build/lib/system.js +2 -3
- package/build/lib/system.js.map +1 -1
- package/build/lib/tempdir.d.ts +3 -2
- package/build/lib/tempdir.d.ts.map +1 -1
- package/build/lib/tempdir.js +2 -2
- package/build/lib/tempdir.js.map +1 -1
- package/build/lib/timing.d.ts.map +1 -1
- package/build/lib/timing.js +3 -7
- package/build/lib/timing.js.map +1 -1
- package/build/lib/util.d.ts +103 -24
- package/build/lib/util.d.ts.map +1 -1
- package/build/lib/util.js +158 -22
- package/build/lib/util.js.map +1 -1
- package/build/lib/zip.d.ts +42 -42
- package/build/lib/zip.d.ts.map +1 -1
- package/build/lib/zip.js +142 -142
- package/build/lib/zip.js.map +1 -1
- package/lib/console.ts +8 -9
- package/lib/doctor.ts +6 -6
- package/lib/env.ts +5 -5
- package/lib/fs.ts +14 -14
- package/lib/image-util.ts +2 -1
- package/lib/index.ts +7 -1
- package/lib/logging.ts +5 -5
- package/lib/mjpeg.ts +9 -7
- package/lib/net.ts +25 -19
- package/lib/node.ts +7 -8
- package/lib/npm.ts +5 -3
- package/lib/plist.ts +11 -11
- package/lib/process.ts +8 -2
- package/lib/system.ts +2 -3
- package/lib/tempdir.ts +2 -2
- package/lib/timing.ts +3 -5
- package/lib/util.ts +197 -44
- package/lib/zip.ts +223 -221
- package/package.json +11 -12
- package/tsconfig.json +1 -0
package/lib/zip.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
1
|
import {promisify} from 'node:util';
|
|
3
2
|
import * as yauzl from 'yauzl';
|
|
4
3
|
import archiver from 'archiver';
|
|
@@ -9,7 +8,7 @@ import {pipeline} from 'node:stream/promises';
|
|
|
9
8
|
import {fs} from './fs';
|
|
10
9
|
import {isWindows} from './system';
|
|
11
10
|
import {Base64Encode} from 'base64-stream';
|
|
12
|
-
import {isSubPath, toReadableSizeString, GiB} from './util';
|
|
11
|
+
import {isSubPath, memoize, toReadableSizeString, GiB} from './util';
|
|
13
12
|
import {Timer} from './timing';
|
|
14
13
|
import log from './logger';
|
|
15
14
|
import getStream from 'get-stream';
|
|
@@ -43,6 +42,210 @@ export interface ExtractAllOptions {
|
|
|
43
42
|
useSystemUnzip?: boolean;
|
|
44
43
|
}
|
|
45
44
|
|
|
45
|
+
export interface ZipEntry {
|
|
46
|
+
/** The actual entry instance */
|
|
47
|
+
entry: yauzl.Entry;
|
|
48
|
+
/**
|
|
49
|
+
* Async function which accepts the destination folder path
|
|
50
|
+
* and extracts this entry into it.
|
|
51
|
+
*/
|
|
52
|
+
extractEntryTo: (destDir: string) => Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ZipOptions {
|
|
56
|
+
/** Whether to encode the resulting archive to a base64-encoded string */
|
|
57
|
+
encodeToBase64?: boolean;
|
|
58
|
+
/** Whether to log the actual archiver performance */
|
|
59
|
+
isMetered?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* The maximum size of the resulting archive in bytes.
|
|
62
|
+
* This is set to 1GB by default, because Appium limits the maximum HTTP body size to 1GB.
|
|
63
|
+
* Also, the NodeJS heap size must be enough to keep the resulting object
|
|
64
|
+
* (usually this size is limited to 1.4 GB)
|
|
65
|
+
*/
|
|
66
|
+
maxSize?: number;
|
|
67
|
+
/**
|
|
68
|
+
* The compression level.
|
|
69
|
+
* The maximum level is 9 (the best compression, worst performance).
|
|
70
|
+
* The minimum compression level is 0 (no compression).
|
|
71
|
+
*/
|
|
72
|
+
level?: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface ZipCompressionOptions {
|
|
76
|
+
/**
|
|
77
|
+
* Compression level in range 0..9
|
|
78
|
+
* (greater numbers mean better compression, but longer processing time)
|
|
79
|
+
*/
|
|
80
|
+
level?: number;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface ZipSourceOptions {
|
|
84
|
+
/** GLOB pattern for compression */
|
|
85
|
+
pattern?: string;
|
|
86
|
+
/** The source root folder (the parent folder of the destination file by default) */
|
|
87
|
+
cwd?: string;
|
|
88
|
+
/** The list of ignored patterns */
|
|
89
|
+
ignore?: string[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface ZipExtractorOptions {
|
|
93
|
+
dir: string;
|
|
94
|
+
fileNamesEncoding?: BufferEncoding;
|
|
95
|
+
defaultDirMode?: string;
|
|
96
|
+
defaultFileMode?: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// This class is mostly copied from https://github.com/maxogden/extract-zip/blob/master/index.js
|
|
100
|
+
class ZipExtractor {
|
|
101
|
+
zipfile!: yauzl.ZipFile;
|
|
102
|
+
private readonly zipPath: string;
|
|
103
|
+
private readonly opts: ZipExtractorOptions;
|
|
104
|
+
private canceled = false;
|
|
105
|
+
|
|
106
|
+
constructor(sourcePath: string, opts: ZipExtractorOptions) {
|
|
107
|
+
this.zipPath = sourcePath;
|
|
108
|
+
this.opts = opts;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async extract(): Promise<void> {
|
|
112
|
+
const {dir, fileNamesEncoding} = this.opts;
|
|
113
|
+
this.zipfile = await openZip(this.zipPath, {
|
|
114
|
+
lazyEntries: true,
|
|
115
|
+
// https://github.com/thejoshwolfe/yauzl/commit/cc7455ac789ba84973184e5ebde0581cdc4c3b39#diff-04c6e90faac2675aa89e2176d2eec7d8R95
|
|
116
|
+
decodeStrings: !fileNamesEncoding,
|
|
117
|
+
});
|
|
118
|
+
this.canceled = false;
|
|
119
|
+
|
|
120
|
+
return new Promise<void>((resolve, reject) => {
|
|
121
|
+
this.zipfile.on('error', (err: Error) => {
|
|
122
|
+
this.canceled = true;
|
|
123
|
+
reject(err);
|
|
124
|
+
});
|
|
125
|
+
this.zipfile.readEntry();
|
|
126
|
+
|
|
127
|
+
this.zipfile.on('close', () => {
|
|
128
|
+
if (!this.canceled) {
|
|
129
|
+
resolve();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
this.zipfile.on('entry', async (entry: yauzl.Entry) => {
|
|
134
|
+
if (this.canceled) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const fileName = this.extractFileName(entry);
|
|
139
|
+
if (fileName.startsWith('__MACOSX/')) {
|
|
140
|
+
this.zipfile.readEntry();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const destDir = path.dirname(path.join(dir, fileName));
|
|
145
|
+
try {
|
|
146
|
+
await fs.mkdir(destDir, {recursive: true});
|
|
147
|
+
|
|
148
|
+
const canonicalDestDir = await fs.realpath(destDir);
|
|
149
|
+
const relativeDestDir = path.relative(dir, canonicalDestDir);
|
|
150
|
+
|
|
151
|
+
if (relativeDestDir.split(path.sep).includes('..')) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Out of bound path "${canonicalDestDir}" found while processing file ${fileName}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
await this.extractEntry(entry);
|
|
158
|
+
this.zipfile.readEntry();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
this.canceled = true;
|
|
161
|
+
this.zipfile.close();
|
|
162
|
+
reject(err);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private extractFileName(entry: yauzl.Entry): string {
|
|
169
|
+
if (Buffer.isBuffer(entry.fileName)) {
|
|
170
|
+
return entry.fileName.toString(this.opts.fileNamesEncoding);
|
|
171
|
+
}
|
|
172
|
+
return entry.fileName;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private async extractEntry(entry: yauzl.Entry): Promise<void> {
|
|
176
|
+
if (this.canceled) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const {dir} = this.opts;
|
|
181
|
+
|
|
182
|
+
const fileName = this.extractFileName(entry);
|
|
183
|
+
const dest = path.join(dir, fileName);
|
|
184
|
+
|
|
185
|
+
// convert external file attr int into a fs stat mode int
|
|
186
|
+
const mode = (entry.externalFileAttributes >> 16) & 0xffff;
|
|
187
|
+
// check if it's a symlink or dir (using stat mode constants)
|
|
188
|
+
const isSymlink = (mode & IFMT) === IFLNK;
|
|
189
|
+
const isDir =
|
|
190
|
+
(mode & IFMT) === IFDIR ||
|
|
191
|
+
// Failsafe, borrowed from jsZip
|
|
192
|
+
fileName.endsWith('/') ||
|
|
193
|
+
// check for windows weird way of specifying a directory
|
|
194
|
+
// https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
|
|
195
|
+
(entry.versionMadeBy >> 8 === 0 && entry.externalFileAttributes === 16);
|
|
196
|
+
const procMode = this.getExtractedMode(mode, isDir) & 0o777;
|
|
197
|
+
// always ensure folders are created
|
|
198
|
+
const destDir = isDir ? dest : path.dirname(dest);
|
|
199
|
+
const mkdirOptions: Parameters<typeof fs.mkdir>[1] = {recursive: true};
|
|
200
|
+
if (isDir) {
|
|
201
|
+
mkdirOptions.mode = procMode;
|
|
202
|
+
}
|
|
203
|
+
await fs.mkdir(destDir, mkdirOptions);
|
|
204
|
+
if (isDir) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const openReadStream = promisify(
|
|
209
|
+
this.zipfile.openReadStream.bind(this.zipfile)
|
|
210
|
+
) as (entry: yauzl.Entry) => Promise<NodeJS.ReadableStream>;
|
|
211
|
+
const readStream = await openReadStream(entry);
|
|
212
|
+
if (isSymlink) {
|
|
213
|
+
const link = await getStream(readStream);
|
|
214
|
+
await fs.symlink(link, dest);
|
|
215
|
+
} else {
|
|
216
|
+
await pipeline(readStream, fs.createWriteStream(dest, {mode: procMode}));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private getExtractedMode(entryMode: number, isDir: boolean): number {
|
|
221
|
+
const {defaultDirMode, defaultFileMode} = this.opts;
|
|
222
|
+
|
|
223
|
+
let mode = entryMode;
|
|
224
|
+
// Set defaults, if necessary
|
|
225
|
+
if (mode === 0) {
|
|
226
|
+
if (isDir) {
|
|
227
|
+
if (defaultDirMode) {
|
|
228
|
+
mode = parseInt(defaultDirMode, 10);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (!mode) {
|
|
232
|
+
mode = 0o755;
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
if (defaultFileMode) {
|
|
236
|
+
mode = parseInt(defaultFileMode, 10);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!mode) {
|
|
240
|
+
mode = 0o644;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return mode;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
46
249
|
/**
|
|
47
250
|
* Extract zipfile to a directory
|
|
48
251
|
*
|
|
@@ -127,16 +330,6 @@ export async function _extractEntryTo(
|
|
|
127
330
|
await Promise.all([zipReadStreamPromise, writeStreamPromise]);
|
|
128
331
|
}
|
|
129
332
|
|
|
130
|
-
export interface ZipEntry {
|
|
131
|
-
/** The actual entry instance */
|
|
132
|
-
entry: yauzl.Entry;
|
|
133
|
-
/**
|
|
134
|
-
* Async function which accepts the destination folder path
|
|
135
|
-
* and extracts this entry into it.
|
|
136
|
-
*/
|
|
137
|
-
extractEntryTo: (destDir: string) => Promise<void>;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
333
|
/**
|
|
141
334
|
* Get entries for a zip folder
|
|
142
335
|
*
|
|
@@ -174,26 +367,6 @@ export async function readEntries(
|
|
|
174
367
|
await zipReadStreamPromise;
|
|
175
368
|
}
|
|
176
369
|
|
|
177
|
-
export interface ZipOptions {
|
|
178
|
-
/** Whether to encode the resulting archive to a base64-encoded string */
|
|
179
|
-
encodeToBase64?: boolean;
|
|
180
|
-
/** Whether to log the actual archiver performance */
|
|
181
|
-
isMetered?: boolean;
|
|
182
|
-
/**
|
|
183
|
-
* The maximum size of the resulting archive in bytes.
|
|
184
|
-
* This is set to 1GB by default, because Appium limits the maximum HTTP body size to 1GB.
|
|
185
|
-
* Also, the NodeJS heap size must be enough to keep the resulting object
|
|
186
|
-
* (usually this size is limited to 1.4 GB)
|
|
187
|
-
*/
|
|
188
|
-
maxSize?: number;
|
|
189
|
-
/**
|
|
190
|
-
* The compression level.
|
|
191
|
-
* The maximum level is 9 (the best compression, worst performance).
|
|
192
|
-
* The minimum compression level is 0 (no compression).
|
|
193
|
-
*/
|
|
194
|
-
level?: number;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
370
|
/**
|
|
198
371
|
* Converts contents of local directory to an in-memory .zip buffer
|
|
199
372
|
*
|
|
@@ -276,10 +449,8 @@ export async function toInMemoryZip(
|
|
|
276
449
|
} else {
|
|
277
450
|
archive.pipe(resultWriteStream);
|
|
278
451
|
}
|
|
279
|
-
archive.finalize();
|
|
280
452
|
|
|
281
|
-
|
|
282
|
-
await Promise.all([archiveStreamPromise, resultWriteStreamPromise]);
|
|
453
|
+
await Promise.all([archive.finalize(), archiveStreamPromise, resultWriteStreamPromise]);
|
|
283
454
|
|
|
284
455
|
if (timer) {
|
|
285
456
|
log.debug(
|
|
@@ -326,23 +497,6 @@ export async function assertValidZip(filePath: string): Promise<boolean> {
|
|
|
326
497
|
}
|
|
327
498
|
}
|
|
328
499
|
|
|
329
|
-
export interface ZipCompressionOptions {
|
|
330
|
-
/**
|
|
331
|
-
* Compression level in range 0..9
|
|
332
|
-
* (greater numbers mean better compression, but longer processing time)
|
|
333
|
-
*/
|
|
334
|
-
level?: number;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export interface ZipSourceOptions {
|
|
338
|
-
/** GLOB pattern for compression */
|
|
339
|
-
pattern?: string;
|
|
340
|
-
/** The source root folder (the parent folder of the destination file by default) */
|
|
341
|
-
cwd?: string;
|
|
342
|
-
/** The list of ignored patterns */
|
|
343
|
-
ignore?: string[];
|
|
344
|
-
}
|
|
345
|
-
|
|
346
500
|
/**
|
|
347
501
|
* Creates an archive based on the given glob pattern
|
|
348
502
|
*
|
|
@@ -361,6 +515,16 @@ export async function toArchive(
|
|
|
361
515
|
const archive = archiver('zip', {zlib: {level}});
|
|
362
516
|
const outStream = fs.createWriteStream(dstPath);
|
|
363
517
|
await new Promise<void>((resolve, reject) => {
|
|
518
|
+
const outFinished = new Promise<void>((_resolve, _reject) => {
|
|
519
|
+
outStream.once('error', (e: Error) => {
|
|
520
|
+
archive.unpipe(outStream);
|
|
521
|
+
archive.abort();
|
|
522
|
+
archive.destroy();
|
|
523
|
+
_reject(e);
|
|
524
|
+
});
|
|
525
|
+
outStream.once('finish', () => _resolve());
|
|
526
|
+
});
|
|
527
|
+
|
|
364
528
|
archive
|
|
365
529
|
.glob(pattern, {
|
|
366
530
|
cwd,
|
|
@@ -368,173 +532,11 @@ export async function toArchive(
|
|
|
368
532
|
})
|
|
369
533
|
.on('error', reject)
|
|
370
534
|
.pipe(outStream);
|
|
371
|
-
outStream
|
|
372
|
-
.on('error', (e: Error) => {
|
|
373
|
-
archive.unpipe(outStream);
|
|
374
|
-
archive.abort();
|
|
375
|
-
archive.destroy();
|
|
376
|
-
reject(e);
|
|
377
|
-
})
|
|
378
|
-
.on('finish', resolve);
|
|
379
|
-
archive.finalize();
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
535
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
defaultFileMode?: string;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// This class is mostly copied from https://github.com/maxogden/extract-zip/blob/master/index.js
|
|
391
|
-
class ZipExtractor {
|
|
392
|
-
zipfile!: yauzl.ZipFile;
|
|
393
|
-
private readonly zipPath: string;
|
|
394
|
-
private readonly opts: ZipExtractorOptions;
|
|
395
|
-
private canceled = false;
|
|
396
|
-
|
|
397
|
-
constructor(sourcePath: string, opts: ZipExtractorOptions) {
|
|
398
|
-
this.zipPath = sourcePath;
|
|
399
|
-
this.opts = opts;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
private extractFileName(entry: yauzl.Entry): string {
|
|
403
|
-
if (Buffer.isBuffer(entry.fileName)) {
|
|
404
|
-
return entry.fileName.toString(this.opts.fileNamesEncoding);
|
|
405
|
-
}
|
|
406
|
-
return entry.fileName;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
async extract(): Promise<void> {
|
|
410
|
-
const {dir, fileNamesEncoding} = this.opts;
|
|
411
|
-
this.zipfile = await openZip(this.zipPath, {
|
|
412
|
-
lazyEntries: true,
|
|
413
|
-
// https://github.com/thejoshwolfe/yauzl/commit/cc7455ac789ba84973184e5ebde0581cdc4c3b39#diff-04c6e90faac2675aa89e2176d2eec7d8R95
|
|
414
|
-
decodeStrings: !fileNamesEncoding,
|
|
415
|
-
});
|
|
416
|
-
this.canceled = false;
|
|
417
|
-
|
|
418
|
-
return new Promise<void>((resolve, reject) => {
|
|
419
|
-
this.zipfile.on('error', (err: Error) => {
|
|
420
|
-
this.canceled = true;
|
|
421
|
-
reject(err);
|
|
422
|
-
});
|
|
423
|
-
this.zipfile.readEntry();
|
|
424
|
-
|
|
425
|
-
this.zipfile.on('close', () => {
|
|
426
|
-
if (!this.canceled) {
|
|
427
|
-
resolve();
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
this.zipfile.on('entry', async (entry: yauzl.Entry) => {
|
|
432
|
-
if (this.canceled) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
const fileName = this.extractFileName(entry);
|
|
437
|
-
if (fileName.startsWith('__MACOSX/')) {
|
|
438
|
-
this.zipfile.readEntry();
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
const destDir = path.dirname(path.join(dir, fileName));
|
|
443
|
-
try {
|
|
444
|
-
await fs.mkdir(destDir, {recursive: true});
|
|
445
|
-
|
|
446
|
-
const canonicalDestDir = await fs.realpath(destDir);
|
|
447
|
-
const relativeDestDir = path.relative(dir, canonicalDestDir);
|
|
448
|
-
|
|
449
|
-
if (relativeDestDir.split(path.sep).includes('..')) {
|
|
450
|
-
throw new Error(
|
|
451
|
-
`Out of bound path "${canonicalDestDir}" found while processing file ${fileName}`
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
await this.extractEntry(entry);
|
|
456
|
-
this.zipfile.readEntry();
|
|
457
|
-
} catch (err) {
|
|
458
|
-
this.canceled = true;
|
|
459
|
-
this.zipfile.close();
|
|
460
|
-
reject(err);
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
private async extractEntry(entry: yauzl.Entry): Promise<void> {
|
|
467
|
-
if (this.canceled) {
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
const {dir} = this.opts;
|
|
472
|
-
|
|
473
|
-
const fileName = this.extractFileName(entry);
|
|
474
|
-
const dest = path.join(dir, fileName);
|
|
475
|
-
|
|
476
|
-
// convert external file attr int into a fs stat mode int
|
|
477
|
-
const mode = (entry.externalFileAttributes >> 16) & 0xffff;
|
|
478
|
-
// check if it's a symlink or dir (using stat mode constants)
|
|
479
|
-
const isSymlink = (mode & IFMT) === IFLNK;
|
|
480
|
-
const isDir =
|
|
481
|
-
(mode & IFMT) === IFDIR ||
|
|
482
|
-
// Failsafe, borrowed from jsZip
|
|
483
|
-
fileName.endsWith('/') ||
|
|
484
|
-
// check for windows weird way of specifying a directory
|
|
485
|
-
// https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
|
|
486
|
-
(entry.versionMadeBy >> 8 === 0 && entry.externalFileAttributes === 16);
|
|
487
|
-
const procMode = this.getExtractedMode(mode, isDir) & 0o777;
|
|
488
|
-
// always ensure folders are created
|
|
489
|
-
const destDir = isDir ? dest : path.dirname(dest);
|
|
490
|
-
const mkdirOptions: Parameters<typeof fs.mkdir>[1] = {recursive: true};
|
|
491
|
-
if (isDir) {
|
|
492
|
-
mkdirOptions.mode = procMode;
|
|
493
|
-
}
|
|
494
|
-
await fs.mkdir(destDir, mkdirOptions);
|
|
495
|
-
if (isDir) {
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const openReadStream = promisify(
|
|
500
|
-
this.zipfile.openReadStream.bind(this.zipfile)
|
|
501
|
-
) as (entry: yauzl.Entry) => Promise<NodeJS.ReadableStream>;
|
|
502
|
-
const readStream = await openReadStream(entry);
|
|
503
|
-
if (isSymlink) {
|
|
504
|
-
const link = await getStream(readStream);
|
|
505
|
-
await fs.symlink(link, dest);
|
|
506
|
-
} else {
|
|
507
|
-
await pipeline(readStream, fs.createWriteStream(dest, {mode: procMode}));
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
private getExtractedMode(entryMode: number, isDir: boolean): number {
|
|
512
|
-
const {defaultDirMode, defaultFileMode} = this.opts;
|
|
513
|
-
|
|
514
|
-
let mode = entryMode;
|
|
515
|
-
// Set defaults, if necessary
|
|
516
|
-
if (mode === 0) {
|
|
517
|
-
if (isDir) {
|
|
518
|
-
if (defaultDirMode) {
|
|
519
|
-
mode = parseInt(defaultDirMode, 10);
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
if (!mode) {
|
|
523
|
-
mode = 0o755;
|
|
524
|
-
}
|
|
525
|
-
} else {
|
|
526
|
-
if (defaultFileMode) {
|
|
527
|
-
mode = parseInt(defaultFileMode, 10);
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (!mode) {
|
|
531
|
-
mode = 0o644;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
return mode;
|
|
537
|
-
}
|
|
536
|
+
void Promise.all([archive.finalize(), outFinished])
|
|
537
|
+
.then(() => resolve())
|
|
538
|
+
.catch(reject);
|
|
539
|
+
});
|
|
538
540
|
}
|
|
539
541
|
|
|
540
542
|
/**
|
|
@@ -551,8 +553,8 @@ async function extractWithSystemUnzip(zipFilePath: string, destDir: string): Pro
|
|
|
551
553
|
let executablePath: string;
|
|
552
554
|
try {
|
|
553
555
|
executablePath = await getExecutablePath(isWindowsHost ? 'powershell.exe' : 'unzip');
|
|
554
|
-
} catch {
|
|
555
|
-
throw new Error('Could not find system unzip');
|
|
556
|
+
} catch (e) {
|
|
557
|
+
throw new Error('Could not find system unzip', {cause: e});
|
|
556
558
|
}
|
|
557
559
|
|
|
558
560
|
if (isWindowsHost) {
|
|
@@ -578,7 +580,7 @@ async function extractWithSystemUnzip(zipFilePath: string, destDir: string): Pro
|
|
|
578
580
|
* Finds and memoizes the full path to the given executable.
|
|
579
581
|
* Rejects if it is not found.
|
|
580
582
|
*/
|
|
581
|
-
const getExecutablePath =
|
|
583
|
+
const getExecutablePath = memoize(
|
|
582
584
|
/**
|
|
583
585
|
* @returns Full Path to the executable
|
|
584
586
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appium/support",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "Support libs used across Appium packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -40,28 +40,27 @@
|
|
|
40
40
|
"test:unit": "mocha \"./test/unit/**/*.spec.ts\""
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@appium/logger": "2.0.
|
|
43
|
+
"@appium/logger": "2.0.7",
|
|
44
44
|
"@appium/tsconfig": "1.1.2",
|
|
45
|
-
"@appium/types": "1.
|
|
45
|
+
"@appium/types": "1.4.0",
|
|
46
46
|
"@colors/colors": "1.6.0",
|
|
47
47
|
"archiver": "7.0.1",
|
|
48
|
-
"asyncbox": "6.
|
|
49
|
-
"axios": "1.15.
|
|
48
|
+
"asyncbox": "6.2.0",
|
|
49
|
+
"axios": "1.15.2",
|
|
50
50
|
"base64-stream": "1.0.0",
|
|
51
51
|
"bluebird": "3.7.2",
|
|
52
52
|
"bplist-creator": "0.1.1",
|
|
53
53
|
"bplist-parser": "0.3.2",
|
|
54
54
|
"form-data": "4.0.5",
|
|
55
55
|
"get-stream": "9.0.1",
|
|
56
|
-
"glob": "13.0.
|
|
56
|
+
"glob": "13.0.5",
|
|
57
57
|
"jsftp": "2.1.3",
|
|
58
58
|
"klaw": "4.1.0",
|
|
59
59
|
"lockfile": "1.0.4",
|
|
60
|
-
"lodash": "4.18.1",
|
|
61
60
|
"log-symbols": "7.0.1",
|
|
62
61
|
"ncp": "2.0.0",
|
|
63
62
|
"package-directory": "8.2.0",
|
|
64
|
-
"plist": "
|
|
63
|
+
"plist": "4.0.0",
|
|
65
64
|
"pluralize": "8.0.0",
|
|
66
65
|
"read-pkg": "10.1.0",
|
|
67
66
|
"resolve-from": "5.0.0",
|
|
@@ -69,9 +68,9 @@
|
|
|
69
68
|
"semver": "7.7.4",
|
|
70
69
|
"shell-quote": "1.8.3",
|
|
71
70
|
"supports-color": "10.2.2",
|
|
72
|
-
"teen_process": "4.1.
|
|
73
|
-
"type-fest": "5.
|
|
74
|
-
"uuid": "
|
|
71
|
+
"teen_process": "4.1.3",
|
|
72
|
+
"type-fest": "5.6.0",
|
|
73
|
+
"uuid": "14.0.0",
|
|
75
74
|
"which": "6.0.1",
|
|
76
75
|
"yauzl": "3.3.0"
|
|
77
76
|
},
|
|
@@ -85,5 +84,5 @@
|
|
|
85
84
|
"publishConfig": {
|
|
86
85
|
"access": "public"
|
|
87
86
|
},
|
|
88
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "915d767085c6b40ae90b7592d5130c76414ca3b5"
|
|
89
88
|
}
|