modern-tar 0.7.1 → 0.7.2
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/dist/fs/index.js
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
|
-
import { a as normalizeBody, c as LINK, l as SYMLINK, n as createTarPacker, o as DIRECTORY, r as transformHeader, s as FILE, t as createUnpacker } from "../unpacker-
|
|
1
|
+
import { a as normalizeBody, c as LINK, l as SYMLINK, n as createTarPacker, o as DIRECTORY, r as transformHeader, s as FILE, t as createUnpacker } from "../unpacker-EHw0ivci.js";
|
|
2
2
|
import * as fs from "node:fs/promises";
|
|
3
3
|
import { cpus } from "node:os";
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { Readable, Writable } from "node:stream";
|
|
6
6
|
import * as fs$1 from "node:fs";
|
|
7
7
|
|
|
8
|
+
//#region src/fs/cache.ts
|
|
9
|
+
const createCache = () => {
|
|
10
|
+
const m = /* @__PURE__ */ new Map();
|
|
11
|
+
return {
|
|
12
|
+
get(k) {
|
|
13
|
+
const v = m.get(k);
|
|
14
|
+
if (m.delete(k)) m.set(k, v);
|
|
15
|
+
return v;
|
|
16
|
+
},
|
|
17
|
+
set(k, v) {
|
|
18
|
+
if (m.set(k, v).size > 1e4) m.delete(m.keys().next().value);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
8
24
|
//#region src/fs/path.ts
|
|
9
|
-
const unicodeCache =
|
|
25
|
+
const unicodeCache = createCache();
|
|
10
26
|
const normalizeUnicode = (s) => {
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
for (let i = 0; i < s.length; i++) if (s.charCodeAt(i) >= 128) {
|
|
28
|
+
const cached = unicodeCache.get(s);
|
|
29
|
+
if (cached !== void 0) return cached;
|
|
30
|
+
const normalized = s.normalize("NFD");
|
|
31
|
+
unicodeCache.set(s, normalized);
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
return s;
|
|
17
35
|
};
|
|
18
36
|
function validateBounds(targetPath, destDir, errorMessage) {
|
|
19
37
|
const target = normalizeUnicode(path.resolve(targetPath));
|
|
@@ -456,17 +474,18 @@ function createFileSink(path$1, { mode = 438, mtime } = {}) {
|
|
|
456
474
|
|
|
457
475
|
//#endregion
|
|
458
476
|
//#region src/fs/path-cache.ts
|
|
477
|
+
const ENOENT = "ENOENT";
|
|
459
478
|
const createPathCache = (destDirPath, options) => {
|
|
460
|
-
const dirPromises =
|
|
461
|
-
const pathConflicts =
|
|
479
|
+
const dirPromises = createCache();
|
|
480
|
+
const pathConflicts = createCache();
|
|
462
481
|
const deferredLinks = [];
|
|
463
|
-
const realDirCache =
|
|
482
|
+
const realDirCache = createCache();
|
|
464
483
|
const initializeDestDir = async (destDirPath$1) => {
|
|
465
484
|
const symbolic = normalizeUnicode(path.resolve(destDirPath$1));
|
|
466
485
|
try {
|
|
467
486
|
await fs.mkdir(symbolic, { recursive: true });
|
|
468
487
|
} catch (err) {
|
|
469
|
-
if (err.code ===
|
|
488
|
+
if (err.code === ENOENT) {
|
|
470
489
|
const parentDir = path.dirname(symbolic);
|
|
471
490
|
if (parentDir === symbolic) throw err;
|
|
472
491
|
await fs.mkdir(parentDir, { recursive: true });
|
|
@@ -479,7 +498,7 @@ const createPathCache = (destDirPath, options) => {
|
|
|
479
498
|
real: await fs.realpath(symbolic)
|
|
480
499
|
};
|
|
481
500
|
} catch (err) {
|
|
482
|
-
if (err.code ===
|
|
501
|
+
if (err.code === ENOENT) return {
|
|
483
502
|
symbolic,
|
|
484
503
|
real: symbolic
|
|
485
504
|
};
|
|
@@ -519,12 +538,12 @@ const createPathCache = (destDirPath, options) => {
|
|
|
519
538
|
const realPath = await getRealDir(dirPath, `Symlink "${dirPath}" points outside the extraction directory.`);
|
|
520
539
|
if ((await fs.stat(realPath)).isDirectory()) return;
|
|
521
540
|
} catch (err) {
|
|
522
|
-
if (err.code ===
|
|
541
|
+
if (err.code === ENOENT) throw new Error(`Symlink "${dirPath}" points outside the extraction directory.`);
|
|
523
542
|
throw err;
|
|
524
543
|
}
|
|
525
544
|
throw new Error(`"${dirPath}" is not a valid directory component.`);
|
|
526
545
|
} catch (err) {
|
|
527
|
-
if (err.code ===
|
|
546
|
+
if (err.code === ENOENT) {
|
|
528
547
|
await fs.mkdir(dirPath, { mode: mode ?? options.dmode });
|
|
529
548
|
return;
|
|
530
549
|
}
|
|
@@ -535,6 +554,9 @@ const createPathCache = (destDirPath, options) => {
|
|
|
535
554
|
return promise;
|
|
536
555
|
};
|
|
537
556
|
return {
|
|
557
|
+
async ready() {
|
|
558
|
+
await destDirPromise;
|
|
559
|
+
},
|
|
538
560
|
async preparePath(header) {
|
|
539
561
|
const { name, linkname, type, mode, mtime } = header;
|
|
540
562
|
const { maxDepth = 1024, dmode } = options;
|
|
@@ -549,10 +571,7 @@ const createPathCache = (destDirPath, options) => {
|
|
|
549
571
|
const prevOp = pathConflicts.get(normalizedName);
|
|
550
572
|
if (prevOp) {
|
|
551
573
|
if (prevOp === DIRECTORY && type !== DIRECTORY || prevOp !== DIRECTORY && type === DIRECTORY) throw new Error(`Path conflict ${type} over existing ${prevOp} at "${name}"`);
|
|
552
|
-
return
|
|
553
|
-
outPath,
|
|
554
|
-
type: "skip"
|
|
555
|
-
};
|
|
574
|
+
return;
|
|
556
575
|
}
|
|
557
576
|
const parentDir = path.dirname(outPath);
|
|
558
577
|
switch (type) {
|
|
@@ -560,37 +579,22 @@ const createPathCache = (destDirPath, options) => {
|
|
|
560
579
|
pathConflicts.set(normalizedName, DIRECTORY);
|
|
561
580
|
await prepareDirectory(outPath, dmode ?? mode);
|
|
562
581
|
if (mtime) await fs.lutimes(outPath, mtime, mtime).catch(() => {});
|
|
563
|
-
return
|
|
564
|
-
outPath,
|
|
565
|
-
type: "dir"
|
|
566
|
-
};
|
|
582
|
+
return;
|
|
567
583
|
case FILE:
|
|
568
584
|
pathConflicts.set(normalizedName, FILE);
|
|
569
585
|
await prepareDirectory(parentDir);
|
|
570
|
-
return
|
|
571
|
-
outPath,
|
|
572
|
-
type: "file"
|
|
573
|
-
};
|
|
586
|
+
return outPath;
|
|
574
587
|
case SYMLINK:
|
|
575
588
|
pathConflicts.set(normalizedName, SYMLINK);
|
|
576
|
-
if (!linkname) return
|
|
577
|
-
outPath,
|
|
578
|
-
type: "symlink"
|
|
579
|
-
};
|
|
589
|
+
if (!linkname) return;
|
|
580
590
|
await prepareDirectory(parentDir);
|
|
581
591
|
validateBounds(path.resolve(parentDir, linkname), destDir.symbolic, `Symlink "${linkname}" points outside the extraction directory.`);
|
|
582
592
|
await fs.symlink(linkname, outPath);
|
|
583
593
|
if (mtime) await fs.lutimes(outPath, mtime, mtime).catch(() => {});
|
|
584
|
-
return
|
|
585
|
-
outPath,
|
|
586
|
-
type: "symlink"
|
|
587
|
-
};
|
|
594
|
+
return;
|
|
588
595
|
case LINK: {
|
|
589
596
|
pathConflicts.set(normalizedName, LINK);
|
|
590
|
-
if (!linkname) return
|
|
591
|
-
outPath,
|
|
592
|
-
type: "link"
|
|
593
|
-
};
|
|
597
|
+
if (!linkname) return;
|
|
594
598
|
const normalizedLink = normalizeUnicode(linkname);
|
|
595
599
|
if (path.isAbsolute(normalizedLink)) throw new Error(`Hardlink "${linkname}" points outside the extraction directory.`);
|
|
596
600
|
const linkTarget = path.join(destDir.symbolic, normalizedLink);
|
|
@@ -605,22 +609,16 @@ const createPathCache = (destDirPath, options) => {
|
|
|
605
609
|
outPath
|
|
606
610
|
});
|
|
607
611
|
}
|
|
608
|
-
return
|
|
609
|
-
outPath,
|
|
610
|
-
type: "link"
|
|
611
|
-
};
|
|
612
|
+
return;
|
|
612
613
|
}
|
|
613
|
-
default: return
|
|
614
|
-
outPath,
|
|
615
|
-
type: "skip"
|
|
616
|
-
};
|
|
614
|
+
default: return;
|
|
617
615
|
}
|
|
618
616
|
},
|
|
619
617
|
async applyLinks() {
|
|
620
618
|
for (const { linkTarget, outPath } of deferredLinks) try {
|
|
621
619
|
await fs.link(linkTarget, outPath);
|
|
622
620
|
} catch (err) {
|
|
623
|
-
if (err.code ===
|
|
621
|
+
if (err.code === ENOENT) throw new Error(`Hardlink target "${linkTarget}" does not exist for link at "${outPath}".`);
|
|
624
622
|
throw err;
|
|
625
623
|
}
|
|
626
624
|
}
|
|
@@ -669,11 +667,7 @@ function unpackTar(directoryPath, options = {}) {
|
|
|
669
667
|
}
|
|
670
668
|
while (true) {
|
|
671
669
|
const header = unpacker.readHeader();
|
|
672
|
-
if (header === void 0) {
|
|
673
|
-
cb();
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
if (header === null) {
|
|
670
|
+
if (header === void 0 || header === null) {
|
|
677
671
|
cb();
|
|
678
672
|
return;
|
|
679
673
|
}
|
|
@@ -686,9 +680,9 @@ function unpackTar(directoryPath, options = {}) {
|
|
|
686
680
|
}
|
|
687
681
|
continue;
|
|
688
682
|
}
|
|
689
|
-
const
|
|
690
|
-
if (
|
|
691
|
-
const fileStream = createFileSink(
|
|
683
|
+
const outPath = await opQueue.add(() => pathCache.preparePath(transformedHeader));
|
|
684
|
+
if (outPath) {
|
|
685
|
+
const fileStream = createFileSink(outPath, {
|
|
692
686
|
mode: options.fmode ?? transformedHeader.mode ?? void 0,
|
|
693
687
|
mtime: transformedHeader.mtime ?? void 0
|
|
694
688
|
});
|
|
@@ -729,6 +723,7 @@ function unpackTar(directoryPath, options = {}) {
|
|
|
729
723
|
try {
|
|
730
724
|
unpacker.end();
|
|
731
725
|
unpacker.validateEOF();
|
|
726
|
+
await pathCache.ready();
|
|
732
727
|
await opQueue.onIdle();
|
|
733
728
|
await pathCache.applyLinks();
|
|
734
729
|
cb();
|
|
@@ -91,7 +91,7 @@ function readOctal(view, offset, size) {
|
|
|
91
91
|
const charCode = view[i];
|
|
92
92
|
if (charCode === 0) break;
|
|
93
93
|
if (charCode === 32) continue;
|
|
94
|
-
value =
|
|
94
|
+
value = value * 8 + (charCode - 48);
|
|
95
95
|
}
|
|
96
96
|
return value;
|
|
97
97
|
}
|
|
@@ -442,8 +442,9 @@ function createTarPacker(onData, onError, onFinalize) {
|
|
|
442
442
|
|
|
443
443
|
//#endregion
|
|
444
444
|
//#region src/tar/chunk-queue.ts
|
|
445
|
+
const INITIAL_CAPACITY = 256;
|
|
445
446
|
function createChunkQueue() {
|
|
446
|
-
let chunks = new Array(
|
|
447
|
+
let chunks = new Array(INITIAL_CAPACITY);
|
|
447
448
|
let capacityMask = chunks.length - 1;
|
|
448
449
|
let head = 0;
|
|
449
450
|
let tail = 0;
|
|
@@ -455,6 +456,12 @@ function createChunkQueue() {
|
|
|
455
456
|
head = head + 1 & capacityMask;
|
|
456
457
|
} else chunks[head] = chunk.subarray(count);
|
|
457
458
|
totalAvailable -= count;
|
|
459
|
+
if (totalAvailable === 0 && chunks.length > INITIAL_CAPACITY) {
|
|
460
|
+
chunks = new Array(INITIAL_CAPACITY);
|
|
461
|
+
capacityMask = INITIAL_CAPACITY - 1;
|
|
462
|
+
head = 0;
|
|
463
|
+
tail = 0;
|
|
464
|
+
}
|
|
458
465
|
};
|
|
459
466
|
function pull(bytes, callback) {
|
|
460
467
|
if (callback) {
|
package/dist/web/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as normalizeBody, i as isBodyless, n as createTarPacker$1, r as transformHeader, t as createUnpacker } from "../unpacker-
|
|
1
|
+
import { a as normalizeBody, i as isBodyless, n as createTarPacker$1, r as transformHeader, t as createUnpacker } from "../unpacker-EHw0ivci.js";
|
|
2
2
|
|
|
3
3
|
//#region src/web/compression.ts
|
|
4
4
|
function createGzipEncoder() {
|