@poe-platform/safe-bash 0.1.620 → 0.1.622
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/safe-bash/commands/archive/zip/dates.d.ts +3 -0
- package/dist/safe-bash/commands/archive/zip/dates.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/zip/dates.js +49 -0
- package/dist/safe-bash/commands/archive/zip/dates.js.map +1 -0
- package/dist/safe-bash/commands/archive/zip/environment.d.ts +3 -0
- package/dist/safe-bash/commands/archive/zip/environment.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/zip/environment.js +62 -0
- package/dist/safe-bash/commands/archive/zip/environment.js.map +1 -0
- package/dist/safe-bash/commands/archive/zip/options.js +6 -6
- package/dist/safe-bash/commands/archive/zip/options.js.map +1 -1
- package/dist/safe-bash/commands/archive/zip.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/zip.js +194 -27
- package/dist/safe-bash/commands/archive/zip.js.map +1 -1
- package/dist/safe-bash/core.browser.js +568 -345
- package/dist/safe-bash/core.browser.js.map +4 -4
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../../../src/commands/archive/zip/dates.ts"],"names":[],"mappings":"AA2BA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI,GAAG,MAAM,CAOtE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAO3G"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ZipFailure } from "./options.js";
|
|
2
|
+
function integer(input, start, width) {
|
|
3
|
+
let offset = start;
|
|
4
|
+
while (" \t\r\n\v\f".includes(input[offset] ?? "\0"))
|
|
5
|
+
offset++;
|
|
6
|
+
const end = offset + width;
|
|
7
|
+
let sign = 1;
|
|
8
|
+
if (input[offset] === "+" || input[offset] === "-") {
|
|
9
|
+
sign = input[offset] === "-" ? -1 : 1;
|
|
10
|
+
offset++;
|
|
11
|
+
}
|
|
12
|
+
let digits = 0;
|
|
13
|
+
let value = 0;
|
|
14
|
+
while (offset < end && input[offset] !== undefined && input[offset] >= "0" && input[offset] <= "9") {
|
|
15
|
+
value = value * 10 + Number(input[offset++]);
|
|
16
|
+
digits++;
|
|
17
|
+
}
|
|
18
|
+
return digits ? { value: value * sign, end: offset } : undefined;
|
|
19
|
+
}
|
|
20
|
+
function fields(input, iso) {
|
|
21
|
+
const first = integer(input, 0, iso ? 4 : 2);
|
|
22
|
+
if (!first || iso && input[first.end] !== "-")
|
|
23
|
+
return;
|
|
24
|
+
const second = integer(input, first.end + (iso ? 1 : 0), 2);
|
|
25
|
+
if (!second || iso && input[second.end] !== "-")
|
|
26
|
+
return;
|
|
27
|
+
const third = integer(input, second.end + (iso ? 1 : 0), iso ? 2 : 4);
|
|
28
|
+
if (!third)
|
|
29
|
+
return;
|
|
30
|
+
return iso ? [first.value, second.value, third.value] : [third.value, first.value, second.value];
|
|
31
|
+
}
|
|
32
|
+
export function parseZipDate(input, option) {
|
|
33
|
+
const result = fields(input, true) ?? fields(input, false);
|
|
34
|
+
if (!result || result[1] < 1 || result[1] > 12 || result[2] < 1 || result[2] > 31) {
|
|
35
|
+
throw new ZipFailure(16, "Invalid command arguments", `invalid date entered for -${option} option - use mmddyyyy or yyyy-mm-dd`);
|
|
36
|
+
}
|
|
37
|
+
const [year, month, day] = result;
|
|
38
|
+
return year < 1980 ? 2162688 : (year - 1980) * 33554432 + month * 2097152 + day * 65536;
|
|
39
|
+
}
|
|
40
|
+
export function zipDateMatches(modified, from, until) {
|
|
41
|
+
if (from === undefined && until === undefined)
|
|
42
|
+
return true;
|
|
43
|
+
const rounded = new Date(Math.ceil(Math.floor(modified.getTime() / 1000) / 2) * 2000);
|
|
44
|
+
const key = rounded.getFullYear() < 1980 ? 2162688 : (rounded.getFullYear() - 1980) * 33554432
|
|
45
|
+
+ (rounded.getMonth() + 1) * 2097152 + rounded.getDate() * 65536
|
|
46
|
+
+ rounded.getHours() * 2048 + rounded.getMinutes() * 32 + rounded.getSeconds() / 2;
|
|
47
|
+
return (from === undefined || key >= from) && (until === undefined || key < until);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=dates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dates.js","sourceRoot":"","sources":["../../../../src/commands/archive/zip/dates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../../../src/commands/archive/zip/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAM1D,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,aAAa,GAAG,SAAS,MAAM,EAAE,CAyChJ"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { fail } from "../internal.js";
|
|
2
|
+
function whitespace(character) {
|
|
3
|
+
return character === " " || character === "\t" || character === "\n" || character === "\r" || character === "\v" || character === "\f";
|
|
4
|
+
}
|
|
5
|
+
export function zipEnvironmentArguments(env, argv, limits) {
|
|
6
|
+
let value = "";
|
|
7
|
+
let selectedBytes = 0;
|
|
8
|
+
for (const key of ["ZIPOPT", "ZIP_OPTS"]) {
|
|
9
|
+
const candidate = env[key] ?? "";
|
|
10
|
+
if (Buffer.byteLength(candidate) > limits.maxArgumentBytes)
|
|
11
|
+
fail("environment argument byte limit exceeded");
|
|
12
|
+
let start = 0;
|
|
13
|
+
while (whitespace(candidate[start]))
|
|
14
|
+
start++;
|
|
15
|
+
if (start < candidate.length) {
|
|
16
|
+
value = candidate.slice(start);
|
|
17
|
+
selectedBytes = Buffer.byteLength(candidate);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (!value)
|
|
22
|
+
return argv;
|
|
23
|
+
if (value.includes("\0") || Buffer.from(value).toString("utf8") !== value)
|
|
24
|
+
fail("invalid environment argument text");
|
|
25
|
+
let bytes = selectedBytes;
|
|
26
|
+
for (const argument of argv) {
|
|
27
|
+
bytes += Buffer.byteLength(argument);
|
|
28
|
+
if (bytes > limits.maxArgumentBytes)
|
|
29
|
+
fail("argument byte limit exceeded");
|
|
30
|
+
}
|
|
31
|
+
const defaults = [];
|
|
32
|
+
let offset = 0;
|
|
33
|
+
while (offset < value.length) {
|
|
34
|
+
let argument = "";
|
|
35
|
+
if (value[offset] === '"') {
|
|
36
|
+
offset++;
|
|
37
|
+
while (offset < value.length && value[offset] !== '"') {
|
|
38
|
+
if (value[offset] === "\\") {
|
|
39
|
+
offset++;
|
|
40
|
+
if (offset === value.length)
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
argument += value[offset++];
|
|
44
|
+
}
|
|
45
|
+
if (value[offset] === '"')
|
|
46
|
+
offset++;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const start = offset;
|
|
50
|
+
while (offset < value.length && !whitespace(value[offset]))
|
|
51
|
+
offset++;
|
|
52
|
+
argument = value.slice(start, offset);
|
|
53
|
+
}
|
|
54
|
+
if (defaults.length + argv.length >= limits.maxArgumentBytes)
|
|
55
|
+
fail("argument count limit exceeded");
|
|
56
|
+
defaults.push(argument);
|
|
57
|
+
while (whitespace(value[offset]))
|
|
58
|
+
offset++;
|
|
59
|
+
}
|
|
60
|
+
return [...defaults, ...argv];
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../../src/commands/archive/zip/environment.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,24 +9,24 @@ export class ZipFailure extends Error {
|
|
|
9
9
|
}
|
|
10
10
|
const longOptions = {
|
|
11
11
|
"recurse-paths": "r", quiet: "q", "junk-paths": "j", "no-dir-entries": "D",
|
|
12
|
-
symlinks: "y", test: "T", "names-stdin": "@", update: "u", freshen: "f",
|
|
12
|
+
symlinks: "y", test: "T", "names-stdin": "@", update: "u", freshen: "f", filesync: "FS",
|
|
13
13
|
delete: "d", include: "i", exclude: "x", suffixes: "n", store: "0", "compression-method": "Z",
|
|
14
14
|
"compress-1": "1", "compress-2": "2", "compress-3": "3", "compress-4": "4",
|
|
15
15
|
"compress-5": "5", "compress-6": "6", "compress-7": "7", "compress-8": "8",
|
|
16
|
-
"compress-9": "9", "force-zip64": "fz", "strip-extra": "X", "force-descriptors": "fd", "no-wild": "nw", "wild-stop-dirs": "ws", "recurse-patterns": "R",
|
|
16
|
+
"compress-9": "9", "force-zip64": "fz", "strip-extra": "X", "force-descriptors": "fd", "no-wild": "nw", "wild-stop-dirs": "ws", "recurse-patterns": "R", "from-date": "t", "before-date": "tt", "copy-entries": "U", "output-file": "O", "must-match": "MM",
|
|
17
17
|
};
|
|
18
18
|
// Include unimplemented Unix options when resolving abbreviations: a partial
|
|
19
19
|
// implementation must not make native-ambiguous prefixes uniquely resolvable.
|
|
20
20
|
const reservedOptions = [
|
|
21
21
|
"adjust-sfx", "temp-path", "entry-comments", "display-bytes", "display-counts",
|
|
22
22
|
"display-dots", "display-globaldots", "dot-size", "display-usize", "display-volume",
|
|
23
|
-
"difference-archive", "encrypt", "fix", "fixfix", "fifo",
|
|
23
|
+
"difference-archive", "encrypt", "fix", "fixfix", "fifo",
|
|
24
24
|
"grow", "help", "more-help", "junk-sfx",
|
|
25
25
|
"DOS-names", "to-crlf", "from-crlf", "logfile-path", "log-append", "log-info",
|
|
26
|
-
"license", "move", "
|
|
26
|
+
"license", "move", "latest-time",
|
|
27
27
|
"paths", "password", "regex", "split-size", "split-pause",
|
|
28
28
|
"split-verbose", "split-bell", "show-command", "show-debug", "show-files",
|
|
29
|
-
"show-options", "
|
|
29
|
+
"show-options", "unzip-command",
|
|
30
30
|
"verbose", "version", "archive-comment",
|
|
31
31
|
];
|
|
32
32
|
export function normalizeZipOption(argument) {
|
|
@@ -46,7 +46,7 @@ export function normalizeZipOption(argument) {
|
|
|
46
46
|
throw new ZipFailure(16, "Invalid command arguments", `unsupported option: ${argument}`);
|
|
47
47
|
if (negate && short !== "fz" && short !== "X")
|
|
48
48
|
throw new ZipFailure(16, "Invalid command arguments", `option ${matched} is not negatable`);
|
|
49
|
-
if (equal >= 0 && short !== "i" && short !== "x" && short !== "n" && short !== "Z") {
|
|
49
|
+
if (equal >= 0 && short !== "i" && short !== "x" && short !== "n" && short !== "Z" && short !== "t" && short !== "tt" && short !== "O") {
|
|
50
50
|
throw new ZipFailure(16, "Invalid command arguments", `option '${matched}' does not allow a value`);
|
|
51
51
|
}
|
|
52
52
|
return `-${short}${negate ? "-" : ""}${equal < 0 ? "" : argument.slice(equal)}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../src/commands/archive/zip/options.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACd;IAAyB;IAA9C,YAAqB,MAAc,EAAW,KAAa,EAAE,MAAc;QAAI,KAAK,CAAC,MAAM,CAAC,CAAC;QAAxE,WAAM,GAAN,MAAM,CAAQ;QAAW,UAAK,GAAL,KAAK,CAAQ;IAAmC,CAAC;CAChG;AAED,MAAM,WAAW,GAAqC;IACpD,eAAe,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG;IAC1E,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../src/commands/archive/zip/options.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../../src/commands/archive/zip.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../../src/commands/archive/zip.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0D,KAAK,iBAAiB,EAAiB,MAAM,0BAA0B,CAAC;AAOzI,OAAO,EAAwF,KAAK,sBAAsB,EAAsB,MAAM,eAAe,CAAC;AA8kBtK,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,sBAA2B,GAAG,iBAAiB,CA2CxF"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { parseZipDate, zipDateMatches } from "./zip/dates.js";
|
|
2
|
+
import { zipEnvironmentArguments } from "./zip/environment.js";
|
|
1
3
|
import { collectBytes, dirname, getCommandArguments, writeBytes } from "../../contracts/index.js";
|
|
2
4
|
import { shellValueByteLength, shellValueBytes } from "../../contracts/value.js";
|
|
3
5
|
import { writeFileOutput } from "../../contracts/filesystem-output.js";
|
|
@@ -13,10 +15,11 @@ import { normalizeZipOption, ZipFailure } from "./zip/options.js";
|
|
|
13
15
|
const defaultStoreSuffixes = [".Z", ".zip", ".zoo", ".arc", ".lzh", ".arj"];
|
|
14
16
|
async function parse(scope, limits) {
|
|
15
17
|
const context = scope.context;
|
|
16
|
-
|
|
18
|
+
const args = zipEnvironmentArguments(context.env, context.args, limits);
|
|
19
|
+
if (args.length > limits.maxArgumentBytes)
|
|
17
20
|
fail("argument count limit exceeded");
|
|
18
21
|
let bytes = 0;
|
|
19
|
-
for (const argument of
|
|
22
|
+
for (const argument of args) {
|
|
20
23
|
const size = Buffer.byteLength(argument);
|
|
21
24
|
if (size > limits.maxArgumentBytes - bytes)
|
|
22
25
|
fail("argument byte limit exceeded");
|
|
@@ -35,6 +38,7 @@ async function parse(scope, limits) {
|
|
|
35
38
|
text(shellValueBytes(value));
|
|
36
39
|
}
|
|
37
40
|
let archive;
|
|
41
|
+
let output;
|
|
38
42
|
let action = "add";
|
|
39
43
|
let recursive = false;
|
|
40
44
|
let recursivePatterns = false;
|
|
@@ -45,6 +49,10 @@ async function parse(scope, limits) {
|
|
|
45
49
|
let omitDirectories = false;
|
|
46
50
|
let storeLinks = false;
|
|
47
51
|
let test = false;
|
|
52
|
+
let mustMatch = false;
|
|
53
|
+
let filesync = false;
|
|
54
|
+
let fromDate;
|
|
55
|
+
let beforeDate;
|
|
48
56
|
let descriptors = false;
|
|
49
57
|
let zip64;
|
|
50
58
|
let metadata = "default";
|
|
@@ -57,8 +65,8 @@ async function parse(scope, limits) {
|
|
|
57
65
|
const operands = [];
|
|
58
66
|
const includes = [];
|
|
59
67
|
const excludes = [];
|
|
60
|
-
for (let index = 0; index <
|
|
61
|
-
const original =
|
|
68
|
+
for (let index = 0; index < args.length; index++) {
|
|
69
|
+
const original = args[index];
|
|
62
70
|
checkPath(original, limits);
|
|
63
71
|
const argument = literal ? original : normalizeZipOption(original);
|
|
64
72
|
if (!literal && argument === "--") {
|
|
@@ -87,8 +95,8 @@ async function parse(scope, limits) {
|
|
|
87
95
|
zip64 = argument[offset + 2] !== "-";
|
|
88
96
|
offset += zip64 ? 1 : 2;
|
|
89
97
|
}
|
|
90
|
-
else if (flag === "d" || flag === "u" || flag === "f") {
|
|
91
|
-
const next = flag === "d" ? "delete" : flag === "u" ? "update" : "freshen";
|
|
98
|
+
else if (flag === "d" || flag === "u" || flag === "f" || flag === "U") {
|
|
99
|
+
const next = flag === "d" ? "delete" : flag === "u" ? "update" : flag === "U" ? "copy" : "freshen";
|
|
92
100
|
if (action !== "add" && action !== next)
|
|
93
101
|
throw new ZipFailure(16, "Invalid command arguments", "specify just one action");
|
|
94
102
|
action = next;
|
|
@@ -102,6 +110,18 @@ async function parse(scope, limits) {
|
|
|
102
110
|
stopAtDirectories = true;
|
|
103
111
|
offset++;
|
|
104
112
|
}
|
|
113
|
+
else if (flag === "M" && argument[offset + 1] === "M") {
|
|
114
|
+
if (argument[offset + 2] === "-")
|
|
115
|
+
throw new ZipFailure(16, "Invalid command arguments", "option MM is not negatable");
|
|
116
|
+
mustMatch = true;
|
|
117
|
+
offset++;
|
|
118
|
+
}
|
|
119
|
+
else if (flag === "F" && argument[offset + 1] === "S") {
|
|
120
|
+
if (argument[offset + 2] === "-")
|
|
121
|
+
throw new ZipFailure(16, "Invalid command arguments", "option FS is not negatable");
|
|
122
|
+
filesync = true;
|
|
123
|
+
offset++;
|
|
124
|
+
}
|
|
105
125
|
else if (flag === "q")
|
|
106
126
|
quiet = true;
|
|
107
127
|
else if (flag === "j")
|
|
@@ -124,10 +144,35 @@ async function parse(scope, limits) {
|
|
|
124
144
|
if (level === 0)
|
|
125
145
|
method = "store";
|
|
126
146
|
}
|
|
147
|
+
else if (flag === "O") {
|
|
148
|
+
let value = argument.slice(offset + 1) || args[++index];
|
|
149
|
+
if (value?.startsWith("="))
|
|
150
|
+
value = value.slice(1);
|
|
151
|
+
if (value === undefined)
|
|
152
|
+
throw new ZipFailure(16, "Invalid command arguments", "option O requires a value");
|
|
153
|
+
output = value;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
else if (flag === "t") {
|
|
157
|
+
const option = argument[offset + 1] === "t" ? "tt" : "t";
|
|
158
|
+
if (option === "tt")
|
|
159
|
+
offset++;
|
|
160
|
+
let value = argument.slice(offset + 1);
|
|
161
|
+
if (!value)
|
|
162
|
+
value = args[++index] ?? "";
|
|
163
|
+
if (value.startsWith("="))
|
|
164
|
+
value = value.slice(1);
|
|
165
|
+
const date = parseZipDate(value, option);
|
|
166
|
+
if (option === "t")
|
|
167
|
+
fromDate = date;
|
|
168
|
+
else
|
|
169
|
+
beforeDate = date;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
127
172
|
else if (flag === "n" || flag === "Z") {
|
|
128
173
|
let value = argument.slice(offset + 1);
|
|
129
174
|
if (!value) {
|
|
130
|
-
const next =
|
|
175
|
+
const next = args[index + 1];
|
|
131
176
|
if (next === undefined || next.startsWith("-") && next !== "-")
|
|
132
177
|
throw new ZipFailure(16, "Invalid command arguments", `option '${flag}' requires a value`);
|
|
133
178
|
value = next;
|
|
@@ -166,8 +211,8 @@ async function parse(scope, limits) {
|
|
|
166
211
|
const value = argument.slice(offset + 1);
|
|
167
212
|
append(value.startsWith("=") ? value.slice(1) : value);
|
|
168
213
|
}
|
|
169
|
-
while (!attached && index + 1 <
|
|
170
|
-
const next =
|
|
214
|
+
while (!attached && index + 1 < args.length) {
|
|
215
|
+
const next = args[index + 1];
|
|
171
216
|
if (next === "@") {
|
|
172
217
|
index++;
|
|
173
218
|
break;
|
|
@@ -196,6 +241,8 @@ async function parse(scope, limits) {
|
|
|
196
241
|
}
|
|
197
242
|
}
|
|
198
243
|
if (archive === undefined) {
|
|
244
|
+
if (includes.length || excludes.length)
|
|
245
|
+
throw new ZipFailure(16, "Invalid command arguments", "nothing to select from");
|
|
199
246
|
if (action !== "add")
|
|
200
247
|
throw new ZipFailure(16, "Invalid command arguments", "expected archive name");
|
|
201
248
|
archive = "-";
|
|
@@ -205,6 +252,15 @@ async function parse(scope, limits) {
|
|
|
205
252
|
if (archive !== "-" && !archive.slice(archive.lastIndexOf("/") + 1).includes("."))
|
|
206
253
|
archive += ".zip";
|
|
207
254
|
checkPath(archive, limits);
|
|
255
|
+
if (output !== undefined) {
|
|
256
|
+
if (!output.slice(output.lastIndexOf("/") + 1).includes("."))
|
|
257
|
+
output += ".zip";
|
|
258
|
+
checkPath(output, limits);
|
|
259
|
+
if (action === "add" && archive !== "-" && !operands.length && !stdinNames)
|
|
260
|
+
action = "copy";
|
|
261
|
+
}
|
|
262
|
+
if (action === "copy" && output === undefined)
|
|
263
|
+
throw new ZipFailure(16, "Invalid command arguments", "-U (--copy) requires -O (--out)");
|
|
208
264
|
const names = [];
|
|
209
265
|
if (stdinNames) {
|
|
210
266
|
const input = await collectBytes(scope.stdin, { maxBytes: limits.maxFilesFromBytes, signal: context.signal });
|
|
@@ -234,7 +290,9 @@ async function parse(scope, limits) {
|
|
|
234
290
|
}
|
|
235
291
|
if (recursivePatterns && !names.length && !operands.length)
|
|
236
292
|
throw new ZipFailure(16, "Invalid command arguments", "nothing to select from");
|
|
237
|
-
|
|
293
|
+
if (filesync && action !== "add")
|
|
294
|
+
throw new ZipFailure(16, "Invalid command arguments", "can't use -d, -f, -u, -U, or -g with filesync -FS\n");
|
|
295
|
+
return { args, action, archive, output, recursive, recursivePatterns, noWild, stopAtDirectories, quiet, junkPaths, omitDirectories, storeLinks, test, mustMatch, filesync, fromDate, beforeDate, descriptors, zip64, metadata, includes, excludes, level, method, suffixes, operands: [...names, ...operands], firstOperand };
|
|
238
296
|
}
|
|
239
297
|
function memberName(path, limits) {
|
|
240
298
|
if (path.startsWith("//") && !path.startsWith("///"))
|
|
@@ -288,7 +346,7 @@ async function prepare(scope, parsed, budget) {
|
|
|
288
346
|
throw new ZipFailure(16, "Invalid command arguments", "can't use -d, -f, -u, -U, or -g on stdout\n");
|
|
289
347
|
let publication;
|
|
290
348
|
if (parsed.archive !== "-") {
|
|
291
|
-
const outputName = vfsPath(context.cwd, parsed.archive);
|
|
349
|
+
const outputName = vfsPath(context.cwd, parsed.output ?? parsed.archive);
|
|
292
350
|
const parentName = dirname(outputName);
|
|
293
351
|
const parent = await scope.operation(() => context.fs.realpath(parentName, { signal: context.signal }));
|
|
294
352
|
const parentStat = await scope.operation(() => context.fs.lstat(parent, { signal: context.signal }));
|
|
@@ -298,20 +356,47 @@ async function prepare(scope, parsed, budget) {
|
|
|
298
356
|
publication = { output, parentName, parent, parentStat, existing };
|
|
299
357
|
}
|
|
300
358
|
const output = publication?.output;
|
|
301
|
-
|
|
359
|
+
let input = publication?.output;
|
|
360
|
+
let existing = publication?.existing;
|
|
361
|
+
if (parsed.output !== undefined) {
|
|
362
|
+
if (parsed.archive === "-") {
|
|
363
|
+
input = undefined;
|
|
364
|
+
existing = undefined;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
const name = vfsPath(context.cwd, parsed.archive);
|
|
368
|
+
try {
|
|
369
|
+
const parent = await scope.operation(() => context.fs.realpath(dirname(name), { signal: context.signal }));
|
|
370
|
+
input = `${parent === "/" ? "" : parent}/${name.slice(name.lastIndexOf("/") + 1)}`;
|
|
371
|
+
existing = await scope.stat(input);
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
context.signal.throwIfAborted();
|
|
375
|
+
if (typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "EACCES"))
|
|
376
|
+
throw new ZipFailure(18, "File not found or no read permission", parsed.archive);
|
|
377
|
+
throw error;
|
|
378
|
+
}
|
|
379
|
+
if (input === output || existing && publication?.existing && sameIdentity(existing, publication.existing))
|
|
380
|
+
throw new ZipFailure(16, "Invalid command arguments", `--out path must be different than in path: ${parsed.archive}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if ((parsed.action === "copy" || parsed.output !== undefined && parsed.archive !== "-") && !existing)
|
|
384
|
+
throw new ZipFailure(18, "File not found or no read permission", parsed.archive);
|
|
385
|
+
if (publication?.existing && (publication.existing.type !== "file" || !hasIdentity(publication.existing) || publication.existing.nlink !== 1))
|
|
386
|
+
fail("output archive requires a regular, single-link file with known backing identity");
|
|
302
387
|
if (parsed.archive === "-" && parsed.test && !parsed.quiet)
|
|
303
388
|
await budget.output("\tzip warning: can't use -T on stdout, -T ignored\n");
|
|
304
389
|
if (existing && (existing.type !== "file" || !hasIdentity(existing) || existing.nlink !== 1))
|
|
305
390
|
fail("updating archive requires a regular, single-link file with known backing identity; archive aliases are unsupported");
|
|
306
391
|
let archive = { entries: [], comment: new Uint8Array() };
|
|
307
|
-
if (existing &&
|
|
392
|
+
if (existing && input) {
|
|
308
393
|
if (!Number.isSafeInteger(existing.size) || existing.size < 0 || existing.size > limits.maxArchiveBytes)
|
|
309
394
|
fail("archive byte limit exceeded");
|
|
310
|
-
const bytes = await collectBytes(scope.input(
|
|
395
|
+
const bytes = await collectBytes(scope.input(input), { maxBytes: limits.maxArchiveBytes, signal: context.signal });
|
|
311
396
|
if (bytes.length !== existing.size)
|
|
312
397
|
fail("archive changed while reading");
|
|
313
398
|
archive = await readZipArchive(bytes, limits, context.signal);
|
|
314
|
-
const current = await scope.stat(
|
|
399
|
+
const current = await scope.stat(input);
|
|
315
400
|
if (!current || !unchanged(existing, current))
|
|
316
401
|
fail("archive changed while reading");
|
|
317
402
|
}
|
|
@@ -320,8 +405,10 @@ async function prepare(scope, parsed, budget) {
|
|
|
320
405
|
await budget.output(`\tzip warning: ${parsed.archive} not found or empty\n`);
|
|
321
406
|
const selected = new Map();
|
|
322
407
|
const deleted = new Set();
|
|
408
|
+
const synchronized = new Map();
|
|
323
409
|
const selection = new Selection([...parsed.includes, ...parsed.excludes], limits, context.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
|
|
324
410
|
const recursiveSelection = parsed.recursivePatterns ? new Selection(parsed.operands, limits, context.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories, trailingComponents: true }) : undefined;
|
|
411
|
+
let archiveOperandMatches;
|
|
325
412
|
const ancestors = [];
|
|
326
413
|
let visits = 0;
|
|
327
414
|
let work = 0;
|
|
@@ -364,6 +451,13 @@ async function prepare(scope, parsed, budget) {
|
|
|
364
451
|
return;
|
|
365
452
|
const prior = old.get(name);
|
|
366
453
|
const modified = new Date();
|
|
454
|
+
if (!zipDateMatches(modified, parsed.fromDate, parsed.beforeDate))
|
|
455
|
+
return;
|
|
456
|
+
if (parsed.filesync) {
|
|
457
|
+
if (synchronized.has(name) && synchronized.get(name) !== source)
|
|
458
|
+
throw new ZipFailure(16, "Invalid command arguments", "cannot repeat names in zip file");
|
|
459
|
+
synchronized.set(name, source);
|
|
460
|
+
}
|
|
367
461
|
if (parsed.action === "freshen" && !prior || prior && (parsed.action === "update" || parsed.action === "freshen") && Math.floor(modified.getTime() / 1000) <= Math.floor(prior.modified.getTime() / 1000))
|
|
368
462
|
return;
|
|
369
463
|
const bytes = await collectBytes(scope.stdin, { maxBytes: Math.min(limits.maxEntryBytes, limits.maxTotalBytes - budget.totalBytes), signal: context.signal });
|
|
@@ -380,14 +474,34 @@ async function prepare(scope, parsed, budget) {
|
|
|
380
474
|
}
|
|
381
475
|
catch (error) {
|
|
382
476
|
context.signal.throwIfAborted();
|
|
383
|
-
if (typeof error !== "object" || error === null || !("code" in error)
|
|
477
|
+
if (typeof error !== "object" || error === null || !("code" in error))
|
|
384
478
|
throw error;
|
|
479
|
+
if (parsed.mustMatch && error.code === "EACCES")
|
|
480
|
+
throw new ZipFailure(18, "File not found or no read permission", source);
|
|
481
|
+
if (error.code !== "ENOENT")
|
|
482
|
+
throw error;
|
|
483
|
+
if (parsed.mustMatch && !old.has(name)) {
|
|
484
|
+
if (!archiveOperandMatches) {
|
|
485
|
+
const fallback = new Selection(parsed.operands.map(operand => {
|
|
486
|
+
const pattern = memberName(operand, limits);
|
|
487
|
+
return parsed.junkPaths ? pattern.slice(pattern.lastIndexOf("/") + 1) : pattern;
|
|
488
|
+
}), limits, context.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
|
|
489
|
+
for (const entry of archive.entries)
|
|
490
|
+
await fallback.matches(entry.name);
|
|
491
|
+
archiveOperandMatches = new Set([...fallback.matched].map(index => parsed.operands[index]));
|
|
492
|
+
}
|
|
493
|
+
if (archiveOperandMatches.has(source))
|
|
494
|
+
return;
|
|
495
|
+
if (!parsed.quiet)
|
|
496
|
+
await budget.output(`\tzip warning: name not matched: ${source}\n`);
|
|
497
|
+
throw new ZipFailure(18, "File not found or no read permission", source);
|
|
498
|
+
}
|
|
385
499
|
if (!parsed.quiet && !old.has(name))
|
|
386
500
|
await budget.output(`\tzip warning: name not matched: ${source}\n`);
|
|
387
501
|
return;
|
|
388
502
|
}
|
|
389
503
|
checkPath(canonical, limits);
|
|
390
|
-
if (canonical === output || (existing && sameIdentity(existing, stat)))
|
|
504
|
+
if (canonical === output || canonical === input || (existing && sameIdentity(existing, stat)) || (publication?.existing && sameIdentity(publication.existing, stat)))
|
|
391
505
|
return;
|
|
392
506
|
const symlink = parsed.storeLinks && stat.type === "symlink";
|
|
393
507
|
if (stat.type !== "file" && stat.type !== "directory" && !symlink) {
|
|
@@ -395,19 +509,26 @@ async function prepare(scope, parsed, budget) {
|
|
|
395
509
|
await budget.output(`\tzip warning: ignoring special file: ${source}\n`);
|
|
396
510
|
return;
|
|
397
511
|
}
|
|
398
|
-
if (existing && !hasIdentity(stat))
|
|
512
|
+
if ((existing || publication?.existing) && !hasIdentity(stat))
|
|
399
513
|
fail("cannot exclude archive aliases when source backing identity is unknown");
|
|
400
514
|
const directory = stat.type === "directory";
|
|
401
515
|
if (directory && name && !name.endsWith("/"))
|
|
402
516
|
name += "/";
|
|
403
|
-
const included = await filterName(name, selection, parsed.includes.length) && (!recursiveSelection || await recursiveSelection.matches(name, true));
|
|
517
|
+
const included = zipDateMatches(new Date(stat.mtimeMs), parsed.fromDate, parsed.beforeDate) && await filterName(name, selection, parsed.includes.length) && (!recursiveSelection || await recursiveSelection.matches(name, true));
|
|
404
518
|
const sourceName = name;
|
|
405
519
|
if (parsed.junkPaths)
|
|
406
520
|
name = directory ? "" : name.slice(name.lastIndexOf("/") + 1);
|
|
407
521
|
const prior = old.get(name);
|
|
522
|
+
if (parsed.filesync && name && included && !(directory && parsed.omitDirectories)) {
|
|
523
|
+
if (synchronized.has(name) && synchronized.get(name) !== source)
|
|
524
|
+
throw new ZipFailure(16, "Invalid command arguments", "cannot repeat names in zip file");
|
|
525
|
+
synchronized.set(name, source);
|
|
526
|
+
}
|
|
527
|
+
const current = parsed.filesync && prior && prior.size === (directory ? 0 : stat.size)
|
|
528
|
+
&& Math.ceil(Math.floor(stat.mtimeMs / 1000) / 2) === Math.ceil(Math.floor(prior.modified.getTime() / 1000) / 2);
|
|
408
529
|
const eligible = parsed.action !== "update" && parsed.action !== "freshen"
|
|
409
530
|
|| (prior ? Math.floor(stat.mtimeMs / 1000) > Math.floor(prior.modified.getTime() / 1000) : parsed.action === "update");
|
|
410
|
-
if (name && included && eligible && !(directory && parsed.omitDirectories)) {
|
|
531
|
+
if (name && included && eligible && !current && !(directory && parsed.omitDirectories)) {
|
|
411
532
|
checkPath(name, limits);
|
|
412
533
|
const previous = selected.get(name);
|
|
413
534
|
if (previous && previous.source !== source) {
|
|
@@ -428,8 +549,17 @@ async function prepare(scope, parsed, budget) {
|
|
|
428
549
|
fail(`source changed while reading: ${source}`);
|
|
429
550
|
bytes = Buffer.from(target);
|
|
430
551
|
}
|
|
431
|
-
else
|
|
432
|
-
|
|
552
|
+
else {
|
|
553
|
+
try {
|
|
554
|
+
bytes = await collectBytes(scope.input(path), { maxBytes: stat.size, signal: context.signal });
|
|
555
|
+
}
|
|
556
|
+
catch (error) {
|
|
557
|
+
context.signal.throwIfAborted();
|
|
558
|
+
if (parsed.mustMatch && typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "EACCES"))
|
|
559
|
+
throw new ZipFailure(18, "File not found or no read permission", `was zipping ${source}`);
|
|
560
|
+
throw error;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
433
563
|
if (!directory && bytes.length !== stat.size)
|
|
434
564
|
fail(`source changed while reading: ${source}`);
|
|
435
565
|
const current = await inspectSource(scope, path, parsed.storeLinks);
|
|
@@ -458,7 +588,16 @@ async function prepare(scope, parsed, budget) {
|
|
|
458
588
|
}
|
|
459
589
|
}
|
|
460
590
|
};
|
|
461
|
-
if (parsed.action === "
|
|
591
|
+
if (parsed.action === "copy") {
|
|
592
|
+
const operands = new Selection(parsed.operands, limits, context.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
|
|
593
|
+
for (const entry of archive.entries) {
|
|
594
|
+
if (await operands.matches(entry.name) && await filterName(entry.name, selection, parsed.includes.length) && zipDateMatches(entry.modified, parsed.fromDate, parsed.beforeDate)) {
|
|
595
|
+
await budget.member(entry.size);
|
|
596
|
+
selected.set(entry.name, { entry, source: entry.name });
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
else if (parsed.action === "delete") {
|
|
462
601
|
if (!parsed.quiet && parsed.recursive)
|
|
463
602
|
await budget.output("\tzip warning: invalid option(s) used with -d; ignored.\n");
|
|
464
603
|
if (!parsed.quiet && !archive.entries.length)
|
|
@@ -466,10 +605,16 @@ async function prepare(scope, parsed, budget) {
|
|
|
466
605
|
const operands = new Selection(parsed.recursivePatterns ? [] : parsed.operands, limits, context.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
|
|
467
606
|
if (parsed.operands.length && !parsed.recursivePatterns) {
|
|
468
607
|
for (const entry of archive.entries) {
|
|
469
|
-
if (await operands.matches(entry.name) && await filterName(entry.name, selection, parsed.includes.length))
|
|
608
|
+
if (await operands.matches(entry.name) && await filterName(entry.name, selection, parsed.includes.length) && zipDateMatches(entry.modified, parsed.fromDate, parsed.beforeDate))
|
|
470
609
|
deleted.add(entry.name);
|
|
471
610
|
}
|
|
472
611
|
}
|
|
612
|
+
if (parsed.mustMatch && !parsed.recursivePatterns) {
|
|
613
|
+
for (const [index, operand] of parsed.operands.entries()) {
|
|
614
|
+
if (!operands.matched.has(index))
|
|
615
|
+
throw new ZipFailure(18, "File not found or no read permission", operand);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
473
618
|
if (!parsed.quiet) {
|
|
474
619
|
for (const [index, operand] of parsed.operands.entries()) {
|
|
475
620
|
if (!operands.matched.has(index))
|
|
@@ -485,11 +630,23 @@ async function prepare(scope, parsed, budget) {
|
|
|
485
630
|
for (const operand of operands)
|
|
486
631
|
await visit(operand, memberName(operand, limits), 0);
|
|
487
632
|
}
|
|
633
|
+
if (parsed.filesync) {
|
|
634
|
+
if (!synchronized.size)
|
|
635
|
+
throw new ZipFailure(12, "Nothing to do!", parsed.archive);
|
|
636
|
+
for (const entry of archive.entries)
|
|
637
|
+
if (!synchronized.has(entry.name))
|
|
638
|
+
deleted.add(entry.name);
|
|
639
|
+
if (!selected.size && !deleted.size) {
|
|
640
|
+
if (!parsed.quiet)
|
|
641
|
+
await budget.output("Archive is current\n");
|
|
642
|
+
return { kind: "current" };
|
|
643
|
+
}
|
|
644
|
+
}
|
|
488
645
|
if (!selected.size && (parsed.action === "freshen" || parsed.action === "update" && (existing || !parsed.includes.length)))
|
|
489
646
|
return undefined;
|
|
490
|
-
if (!selected.size && !deleted.size && (parsed.action === "delete" || parsed.recursivePatterns || !parsed.includes.length)) {
|
|
647
|
+
if (!selected.size && !deleted.size && (parsed.action === "delete" || parsed.action === "copy" || parsed.recursivePatterns || parsed.fromDate !== undefined || parsed.beforeDate !== undefined || !parsed.includes.length)) {
|
|
491
648
|
const detail = parsed.action !== "delete" && parsed.recursive && parsed.firstOperand >= 0
|
|
492
|
-
? `try: zip ${
|
|
649
|
+
? `try: zip ${parsed.args.slice(0, parsed.firstOperand).join(" ")} . -i ${parsed.args.slice(parsed.firstOperand).join(" ")}`
|
|
493
650
|
: parsed.archive;
|
|
494
651
|
throw new ZipFailure(12, "Nothing to do!", detail);
|
|
495
652
|
}
|
|
@@ -517,6 +674,14 @@ async function prepare(scope, parsed, budget) {
|
|
|
517
674
|
continue;
|
|
518
675
|
}
|
|
519
676
|
const replacement = selected.get(entry.name);
|
|
677
|
+
if (parsed.action === "copy") {
|
|
678
|
+
if (replacement) {
|
|
679
|
+
entries.push(replacement.entry);
|
|
680
|
+
queue(` copying: ${entry.name}\n`);
|
|
681
|
+
selected.delete(entry.name);
|
|
682
|
+
}
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
520
685
|
if (replacement) {
|
|
521
686
|
entries.push(replacement.entry);
|
|
522
687
|
append(replacement.entry, true);
|
|
@@ -533,7 +698,7 @@ async function prepare(scope, parsed, budget) {
|
|
|
533
698
|
}
|
|
534
699
|
if (!entries.length)
|
|
535
700
|
queue("\tzip warning: zip file empty\n");
|
|
536
|
-
if (
|
|
701
|
+
if (!publication)
|
|
537
702
|
return { kind: "stream", archive: { entries, comment: archive.comment }, progress };
|
|
538
703
|
const bytes = await writeZipArchive({ entries, comment: archive.comment }, limits, context.signal, false, parsed.zip64 === true);
|
|
539
704
|
if (parsed.test && parsed.archive !== "-") {
|
|
@@ -580,6 +745,8 @@ export function createZipCommand(options = {}) {
|
|
|
580
745
|
const prepared = await prepare(scope, parsed, budget);
|
|
581
746
|
if (!prepared)
|
|
582
747
|
return { exitCode: 12 };
|
|
748
|
+
if (prepared.kind === "current")
|
|
749
|
+
return { exitCode: 0 };
|
|
583
750
|
if (prepared.kind === "file") {
|
|
584
751
|
const publication = prepared.publication;
|
|
585
752
|
if (!publication)
|