@poe-platform/safe-bash 0.1.622 → 0.1.624

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.
@@ -25649,7 +25649,7 @@ var Budget14 = class {
25649
25649
  if (this.members % 128 === 0) await yieldTurn(this.context.signal);
25650
25650
  }
25651
25651
  async output(value2, stderr = false) {
25652
- const bytes3 = import_buffer.Buffer.from(value2);
25652
+ const bytes3 = typeof value2 === "string" ? import_buffer.Buffer.from(value2, "utf8") : import_buffer.Buffer.from(value2);
25653
25653
  if (bytes3.length > this.limits.maxTextBytes - this.textBytes) fail("text output limit exceeded");
25654
25654
  this.textBytes += bytes3.length;
25655
25655
  await writeBytes(stderr ? this.context.stderr : this.context.stdout, bytes3, this.context.signal);
@@ -26637,6 +26637,8 @@ var longOptions = {
26637
26637
  update: "u",
26638
26638
  freshen: "f",
26639
26639
  filesync: "FS",
26640
+ "archive-comment": "z",
26641
+ "entry-comments": "c",
26640
26642
  delete: "d",
26641
26643
  include: "i",
26642
26644
  exclude: "x",
@@ -26667,7 +26669,6 @@ var longOptions = {
26667
26669
  var reservedOptions = [
26668
26670
  "adjust-sfx",
26669
26671
  "temp-path",
26670
- "entry-comments",
26671
26672
  "display-bytes",
26672
26673
  "display-counts",
26673
26674
  "display-dots",
@@ -26706,8 +26707,7 @@ var reservedOptions = [
26706
26707
  "show-options",
26707
26708
  "unzip-command",
26708
26709
  "verbose",
26709
- "version",
26710
- "archive-comment"
26710
+ "version"
26711
26711
  ];
26712
26712
  function normalizeZipOption(argument2) {
26713
26713
  if (!argument2.startsWith("--") || argument2 === "--") return argument2;
@@ -26822,6 +26822,72 @@ function zipEnvironmentArguments(env, argv, limits) {
26822
26822
  return [...defaults, ...argv];
26823
26823
  }
26824
26824
 
26825
+ // packages/safe-bash/src/commands/archive/zip/comments.ts
26826
+ init_platform();
26827
+ var ZipCommentInput = class {
26828
+ constructor(source2, limits, signal) {
26829
+ this.limits = limits;
26830
+ this.signal = signal;
26831
+ this.iterator = readBytes(source2, signal)[Symbol.asyncIterator]();
26832
+ }
26833
+ limits;
26834
+ signal;
26835
+ iterator;
26836
+ chunk = new Uint8Array();
26837
+ offset = 0;
26838
+ bytes = 0;
26839
+ pulls = 0;
26840
+ ended = false;
26841
+ async readLine() {
26842
+ const line = [];
26843
+ while (line.length < 65535) {
26844
+ this.signal.throwIfAborted();
26845
+ if (this.offset === this.chunk.length) {
26846
+ if (this.ended) break;
26847
+ if (++this.pulls > this.limits.maxPatternSteps) fail("ZIP comment input work limit exceeded");
26848
+ const next = await this.iterator.next();
26849
+ if (next.done) {
26850
+ this.ended = true;
26851
+ break;
26852
+ }
26853
+ if (next.value.length > this.limits.maxFilesFromBytes - this.bytes) fail("ZIP comment input byte limit exceeded");
26854
+ this.chunk = new Uint8Array(next.value);
26855
+ this.offset = 0;
26856
+ if (this.pulls % 64 === 0) await yieldTurn(this.signal);
26857
+ if (!this.chunk.length) continue;
26858
+ }
26859
+ if (++this.bytes > this.limits.maxFilesFromBytes) fail("ZIP comment input byte limit exceeded");
26860
+ const byte = this.chunk[this.offset++];
26861
+ line.push(byte);
26862
+ if (this.bytes % 4096 === 0) await yieldTurn(this.signal);
26863
+ if (byte === 10) break;
26864
+ }
26865
+ if (!line.length) return void 0;
26866
+ const zero2 = line.indexOf(0);
26867
+ return Uint8Array.from(line.slice(0, zero2 < 0 ? void 0 : zero2));
26868
+ }
26869
+ };
26870
+ async function readZipComment(source2, limits, signal) {
26871
+ const input3 = source2 instanceof ZipCommentInput ? source2 : new ZipCommentInput(source2, limits, signal);
26872
+ const parts = [];
26873
+ let length = 0;
26874
+ try {
26875
+ for (; ; ) {
26876
+ const line = await input3.readLine();
26877
+ if (line === void 0 || line.length === 2 && line[0] === 46 && line[1] === 10) break;
26878
+ const text3 = line.at(-1) === 10 ? line.subarray(0, -1) : line;
26879
+ const separator = length || !text3.length ? 2 : 0;
26880
+ if (text3.length + separator > Math.min(limits.maxTextBytes, 65535) - length) fail("ZIP archive comment byte limit exceeded");
26881
+ if (separator) parts.push(import_buffer.Buffer.from("\r\n"));
26882
+ if (text3.length) parts.push(text3);
26883
+ length += separator + text3.length;
26884
+ }
26885
+ return import_buffer.Buffer.concat(parts, length);
26886
+ } finally {
26887
+ await input3.iterator.return?.();
26888
+ }
26889
+ }
26890
+
26825
26891
  // packages/safe-bash/src/commands/archive/zip-format.ts
26826
26892
  init_platform();
26827
26893
 
@@ -27296,6 +27362,46 @@ function updateZipExtras(entry, previous, mode, limits) {
27296
27362
  }
27297
27363
  return { ...entry, localExtra: retained[0], centralExtra: retained[1] };
27298
27364
  }
27365
+ function setZipEntryComment(entry, comment2, limits) {
27366
+ number3(comment2.length, Math.min(limits.maxTextBytes, 65535), "entry comment");
27367
+ let flags3 = entry.flags ?? 2048;
27368
+ if (flags3 & 2048) {
27369
+ try {
27370
+ new TextDecoder("utf-8", { fatal: true }).decode(comment2);
27371
+ } catch {
27372
+ flags3 &= ~2048;
27373
+ }
27374
+ }
27375
+ const rawName = entry.rawName ?? pathBytes(entry.name, limits);
27376
+ const needUnicodePath = !(flags3 & 2048) && legacyName(rawName) !== entry.name;
27377
+ const metadata3 = [];
27378
+ for (const [original, central] of [[entry.localExtra ?? timestampExtra(entry.modified), false], [entry.centralExtra ?? timestampExtra(entry.modified), true]]) {
27379
+ extras(original, rawName, entry.comment ?? new Uint8Array(), central, limits);
27380
+ const fields4 = [];
27381
+ const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
27382
+ for (let offset = 0; offset < original.length; ) {
27383
+ const identifier = view.getUint16(offset, true);
27384
+ const next = offset + 4 + view.getUint16(offset + 2, true);
27385
+ if (identifier !== 25461 && !(needUnicodePath && identifier === 28789)) fields4.push(original.subarray(offset, next));
27386
+ offset = next;
27387
+ }
27388
+ if (needUnicodePath) {
27389
+ const name2 = pathBytes(entry.name, limits);
27390
+ const field2 = new Uint8Array(9 + name2.length);
27391
+ const header3 = new DataView(field2.buffer);
27392
+ header3.setUint16(0, 28789, true);
27393
+ header3.setUint16(2, 5 + name2.length, true);
27394
+ field2[4] = 1;
27395
+ header3.setUint32(5, crc322(rawName), true);
27396
+ field2.set(name2, 9);
27397
+ fields4.push(field2);
27398
+ }
27399
+ const rebuilt = import_buffer.Buffer.concat(fields4);
27400
+ number3(rebuilt.length, Math.min(limits.maxPaxBytes, 65535), "extra field");
27401
+ metadata3.push(rebuilt);
27402
+ }
27403
+ return { ...entry, comment: new Uint8Array(comment2), flags: flags3, localExtra: metadata3[0], centralExtra: metadata3[1] };
27404
+ }
27299
27405
  async function* streamZipArchive(archive, limits, signal, descriptors = false, forceZip64 = false) {
27300
27406
  const chunkSize2 = admit(limits, signal);
27301
27407
  number3(archive.entries.length, Math.min(limits.maxMembers, 65534), "member");
@@ -27667,23 +27773,30 @@ function tokenize2(pattern, noWild, stopAtDirectories) {
27667
27773
  const negative = characters[index + 1] === "!" || characters[index + 1] === "^";
27668
27774
  if (negative) index++;
27669
27775
  const ranges = [];
27670
- let closed = false;
27671
- while (++index < characters.length) {
27672
- let first = characters[index];
27673
- if (first === "]") {
27674
- closed = true;
27675
- break;
27676
- }
27677
- if (first === "\\") first = characters[++index] ?? "";
27678
- let last = first;
27679
- if (characters[index + 1] === "-" && characters[index + 2] && characters[index + 2] !== "]") {
27680
- index += 2;
27681
- last = characters[index];
27682
- if (last === "\\") last = characters[++index] ?? "";
27776
+ const start = index + 1;
27777
+ let closing = start;
27778
+ let escaped3 = false;
27779
+ for (; closing < characters.length; closing++) {
27780
+ const current = characters[closing];
27781
+ if (escaped3) escaped3 = false;
27782
+ else if (current === "\\") escaped3 = true;
27783
+ else if (current === "]") break;
27784
+ }
27785
+ let first;
27786
+ escaped3 = characters[start] === "-";
27787
+ for (let position = start; position < closing; position++) {
27788
+ const current = characters[position];
27789
+ if (!escaped3 && current === "\\") escaped3 = true;
27790
+ else if (!escaped3 && current === "-") first = characters[position - 1].codePointAt(0);
27791
+ else {
27792
+ const last = current.codePointAt(0);
27793
+ if (characters[position + 1] !== "-") ranges.push([first ?? last, last]);
27794
+ first = void 0;
27795
+ escaped3 = false;
27683
27796
  }
27684
- ranges.push([first.codePointAt(0) ?? -1, last.codePointAt(0) ?? -1]);
27685
27797
  }
27686
- tokens2.push(closed ? { kind: "class", ranges, negative } : { kind: "never" });
27798
+ index = closing;
27799
+ tokens2.push(closing < characters.length ? { kind: "class", ranges, negative } : { kind: "never" });
27687
27800
  } else tokens2.push({ kind: "literal", value: character });
27688
27801
  }
27689
27802
  return tokens2;
@@ -27824,6 +27937,8 @@ async function parse12(scope, limits) {
27824
27937
  let test = false;
27825
27938
  let mustMatch = false;
27826
27939
  let filesync = false;
27940
+ let archiveComment = false;
27941
+ let entryComments = false;
27827
27942
  let fromDate;
27828
27943
  let beforeDate;
27829
27944
  let descriptors = false;
@@ -27877,6 +27992,8 @@ async function parse12(scope, limits) {
27877
27992
  filesync = true;
27878
27993
  offset++;
27879
27994
  } else if (flag === "q") quiet = true;
27995
+ else if (flag === "z") archiveComment = true;
27996
+ else if (flag === "c") entryComments = true;
27880
27997
  else if (flag === "j") junkPaths = true;
27881
27998
  else if (flag === "X") {
27882
27999
  metadata3 = argument2[offset + 1] === "-" ? "all" : "strip";
@@ -27995,7 +28112,7 @@ async function parse12(scope, limits) {
27995
28112
  }
27996
28113
  if (recursivePatterns && !names.length && !operands.length) throw new ZipFailure(16, "Invalid command arguments", "nothing to select from");
27997
28114
  if (filesync && action !== "add") throw new ZipFailure(16, "Invalid command arguments", "can't use -d, -f, -u, -U, or -g with filesync -FS\n");
27998
- return { args, action, archive, output: output2, recursive, recursivePatterns, noWild, stopAtDirectories, quiet, junkPaths, omitDirectories, storeLinks, test, mustMatch, filesync, fromDate, beforeDate, descriptors, zip64, metadata: metadata3, includes, excludes, level, method, suffixes, operands: [...names, ...operands], firstOperand };
28115
+ return { args, action, archive, output: output2, recursive, recursivePatterns, noWild, stopAtDirectories, quiet, junkPaths, omitDirectories, storeLinks, test, mustMatch, filesync, archiveComment, entryComments, fromDate, beforeDate, descriptors, zip64, metadata: metadata3, includes, excludes, level, method, suffixes, operands: [...names, ...operands], firstOperand };
27999
28116
  }
28000
28117
  function memberName(path, limits) {
28001
28118
  if (path.startsWith("//") && !path.startsWith("///")) fail("UNC source paths are unsupported");
@@ -28089,6 +28206,7 @@ async function prepare(scope, parsed, budget) {
28089
28206
  const selected = /* @__PURE__ */ new Map();
28090
28207
  const deleted = /* @__PURE__ */ new Set();
28091
28208
  const synchronized = /* @__PURE__ */ new Map();
28209
+ const commentNames = /* @__PURE__ */ new Set();
28092
28210
  const selection = new Selection([...parsed.includes, ...parsed.excludes], limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
28093
28211
  const recursiveSelection = parsed.recursivePatterns ? new Selection(parsed.operands, limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories, trailingComponents: true }) : void 0;
28094
28212
  let archiveOperandMatches;
@@ -28109,6 +28227,7 @@ async function prepare(scope, parsed, budget) {
28109
28227
  if (entry.data.length > limits.maxArchiveBytes - compressedBytes) fail("archive byte limit exceeded");
28110
28228
  compressedBytes += entry.data.length;
28111
28229
  selected.set(name2, { entry, source: source2 });
28230
+ if (parsed.entryComments) commentNames.add(name2);
28112
28231
  };
28113
28232
  const visit = async (source2, name2, depth) => {
28114
28233
  context2.signal.throwIfAborted();
@@ -28144,6 +28263,7 @@ async function prepare(scope, parsed, budget) {
28144
28263
  if (typeof error !== "object" || error === null || !("code" in error)) throw error;
28145
28264
  if (parsed.mustMatch && error.code === "EACCES") throw new ZipFailure(18, "File not found or no read permission", source2);
28146
28265
  if (error.code !== "ENOENT") throw error;
28266
+ if (parsed.entryComments && old.has(name2) && await filterName(name2, selection, parsed.includes.length)) commentNames.add(name2);
28147
28267
  if (parsed.mustMatch && !old.has(name2)) {
28148
28268
  if (!archiveOperandMatches) {
28149
28269
  const fallback = new Selection(parsed.operands.map((operand) => {
@@ -28177,6 +28297,7 @@ async function prepare(scope, parsed, budget) {
28177
28297
  const sourceName = name2;
28178
28298
  if (parsed.junkPaths) name2 = directory2 ? "" : name2.slice(name2.lastIndexOf("/") + 1);
28179
28299
  const prior = old.get(name2);
28300
+ if (parsed.entryComments && prior && included && !(directory2 && parsed.omitDirectories)) commentNames.add(name2);
28180
28301
  if (parsed.filesync && name2 && included && !(directory2 && parsed.omitDirectories)) {
28181
28302
  if (synchronized.has(name2) && synchronized.get(name2) !== source2) throw new ZipFailure(16, "Invalid command arguments", "cannot repeat names in zip file");
28182
28303
  synchronized.set(name2, source2);
@@ -28233,6 +28354,9 @@ async function prepare(scope, parsed, budget) {
28233
28354
  }
28234
28355
  }
28235
28356
  };
28357
+ const editComment = parsed.archiveComment && parsed.action !== "delete" && parsed.action !== "copy";
28358
+ const editEntries = parsed.entryComments && parsed.action !== "delete" && parsed.action !== "copy";
28359
+ if ((parsed.archiveComment || parsed.entryComments) && parsed.action === "copy" && !parsed.quiet) await budget.output(" zip warning: can't set method, move, recurse, or comments with copy mode.\n");
28236
28360
  if (parsed.action === "copy") {
28237
28361
  const operands = new Selection(parsed.operands, limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
28238
28362
  for (const entry of archive.entries) {
@@ -28242,7 +28366,7 @@ async function prepare(scope, parsed, budget) {
28242
28366
  }
28243
28367
  }
28244
28368
  } else if (parsed.action === "delete") {
28245
- if (!parsed.quiet && parsed.recursive) await budget.output(" zip warning: invalid option(s) used with -d; ignored.\n");
28369
+ if (!parsed.quiet && (parsed.recursive || parsed.archiveComment || parsed.entryComments)) await budget.output(" zip warning: invalid option(s) used with -d; ignored.\n");
28246
28370
  if (!parsed.quiet && !archive.entries.length) await budget.output(` zip warning: ${parsed.archive} not found or empty
28247
28371
  `);
28248
28372
  const operands = new Selection(parsed.recursivePatterns ? [] : parsed.operands, limits, context2.signal, { noWild: parsed.noWild, stopAtDirectories: parsed.stopAtDirectories });
@@ -28275,8 +28399,8 @@ async function prepare(scope, parsed, budget) {
28275
28399
  return { kind: "current" };
28276
28400
  }
28277
28401
  }
28278
- if (!selected.size && (parsed.action === "freshen" || parsed.action === "update" && (existing2 || !parsed.includes.length))) return void 0;
28279
- if (!selected.size && !deleted.size && (parsed.action === "delete" || parsed.action === "copy" || parsed.recursivePatterns || parsed.fromDate !== void 0 || parsed.beforeDate !== void 0 || !parsed.includes.length)) {
28402
+ if (!selected.size && !((editComment || editEntries) && archive.entries.length) && (parsed.action === "freshen" || parsed.action === "update" && (existing2 || !parsed.includes.length))) return void 0;
28403
+ if (!selected.size && !deleted.size && !((editComment || editEntries) && archive.entries.length) && (parsed.action === "delete" || parsed.action === "copy" || parsed.recursivePatterns || parsed.fromDate !== void 0 || parsed.beforeDate !== void 0 || !parsed.includes.length)) {
28280
28404
  const detail = parsed.action !== "delete" && parsed.recursive && parsed.firstOperand >= 0 ? `try: zip ${parsed.args.slice(0, parsed.firstOperand).join(" ")} . -i ${parsed.args.slice(parsed.firstOperand).join(" ")}` : parsed.archive;
28281
28405
  throw new ZipFailure(12, "Nothing to do!", detail);
28282
28406
  }
@@ -28326,8 +28450,34 @@ async function prepare(scope, parsed, budget) {
28326
28450
  append(entry, false);
28327
28451
  }
28328
28452
  if (!entries2.length) queue(" zip warning: zip file empty\n");
28329
- if (!publication) return { kind: "stream", archive: { entries: entries2, comment: archive.comment }, progress };
28330
- const bytes3 = await writeZipArchive({ entries: entries2, comment: archive.comment }, limits, context2.signal, false, parsed.zip64 === true);
28453
+ let comment2 = archive.comment;
28454
+ if (editComment || editEntries && commentNames.size) {
28455
+ for (const message3 of progress) await budget.output(message3);
28456
+ progress.length = 0;
28457
+ progressBytes = 0;
28458
+ const commentInput = new ZipCommentInput(scope.stdin, limits, context2.signal);
28459
+ if (editEntries) {
28460
+ for (let index = 0; index < entries2.length; index++) {
28461
+ const entry = entries2[index];
28462
+ if (!commentNames.has(entry.name)) continue;
28463
+ if (!parsed.quiet) await budget.output(`Enter comment for ${entry.name}:
28464
+ `);
28465
+ const line = await commentInput.readLine();
28466
+ if (line !== void 0) entries2[index] = setZipEntryComment(entry, line.at(-1) === 10 ? line.subarray(0, -1) : line, limits);
28467
+ }
28468
+ }
28469
+ if (editComment && !parsed.quiet) {
28470
+ if (comment2.length) {
28471
+ await budget.output("current zip file comment is:\n");
28472
+ await budget.output(comment2);
28473
+ if (comment2.at(-1) !== 10) await budget.output("\n");
28474
+ }
28475
+ await budget.output("enter new zip file comment (end with .):\n");
28476
+ }
28477
+ if (editComment) comment2 = await readZipComment(commentInput, limits, context2.signal);
28478
+ }
28479
+ if (!publication) return { kind: "stream", archive: { entries: entries2, comment: comment2 }, progress };
28480
+ const bytes3 = await writeZipArchive({ entries: entries2, comment: comment2 }, limits, context2.signal, false, parsed.zip64 === true);
28331
28481
  if (parsed.test && parsed.archive !== "-") {
28332
28482
  for (const message3 of progress) await budget.output(message3);
28333
28483
  progress.length = 0;