@poe-platform/safe-bash 0.1.609 → 0.1.611

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.
@@ -27194,6 +27194,188 @@ async function publishZip(scope, prepared) {
27194
27194
  if (failure) throw failure.reason;
27195
27195
  }
27196
27196
 
27197
+ // packages/safe-bash/src/commands/archive/unzip/arguments.ts
27198
+ init_platform();
27199
+ function parseArguments(context2, limits) {
27200
+ const { args } = context2;
27201
+ let bytes3 = 0;
27202
+ for (const argument2 of args) {
27203
+ bytes3 += import_buffer.Buffer.byteLength(argument2) + 1;
27204
+ if (bytes3 > limits.maxArgumentBytes) fail("argument byte limit exceeded");
27205
+ if (argument2.includes("\0")) fail("NUL in argument");
27206
+ }
27207
+ if (context2.argumentValues) {
27208
+ const argumentsValue = getCommandArguments(context2);
27209
+ let rawBytes = 0;
27210
+ for (const value2 of argumentsValue.values) {
27211
+ const size = shellValueByteLength(value2) + 1;
27212
+ if (size > limits.maxArgumentBytes - rawBytes) fail("argument byte limit exceeded");
27213
+ rawBytes += size;
27214
+ }
27215
+ for (const value2 of argumentsValue.values) text2(shellValueBytes(value2));
27216
+ }
27217
+ let list = false;
27218
+ let pipe = false;
27219
+ let overwrite = false;
27220
+ let destination2;
27221
+ let archive;
27222
+ let ended = false;
27223
+ const patterns2 = [];
27224
+ for (let index = 0; index < args.length; index++) {
27225
+ const argument2 = args[index];
27226
+ if (!ended && argument2 === "--") {
27227
+ ended = true;
27228
+ continue;
27229
+ }
27230
+ if (!ended && argument2.startsWith("-") && argument2 !== "-") {
27231
+ for (let offset = 1; offset < argument2.length; offset++) {
27232
+ const flag = argument2[offset];
27233
+ if (flag === "l") list = true;
27234
+ else if (flag === "p") pipe = true;
27235
+ else if (flag === "o") overwrite = true;
27236
+ else if (flag === "d") {
27237
+ if (destination2 !== void 0) fail("-d may only be specified once");
27238
+ destination2 = argument2.slice(offset + 1) || args[++index];
27239
+ if (!destination2) fail("must specify directory to which to extract with -d option");
27240
+ checkPath(destination2, limits);
27241
+ break;
27242
+ } else fail(`unsupported option: -${flag}`);
27243
+ }
27244
+ } else if (archive === void 0) archive = argument2;
27245
+ else patterns2.push(argument2);
27246
+ }
27247
+ if (archive === void 0) fail("usage: unzip [-l] [-p] [-o] [-d DIR] ARCHIVE [FILES...]");
27248
+ checkPath(archive, limits);
27249
+ return { list: list && !pipe, pipe, overwrite, destination: destination2, archive, patterns: patterns2 };
27250
+ }
27251
+ function tokenize2(pattern) {
27252
+ const characters = Array.from(pattern);
27253
+ const tokens2 = [];
27254
+ for (let index = 0; index < characters.length; index++) {
27255
+ const character = characters[index];
27256
+ if (character === "*") {
27257
+ if (tokens2.at(-1)?.kind !== "star") tokens2.push({ kind: "star" });
27258
+ } else if (character === "?") tokens2.push({ kind: "any" });
27259
+ else if (character === "\\") {
27260
+ const escaped3 = characters[++index];
27261
+ tokens2.push(escaped3 === void 0 ? { kind: "never" } : { kind: "literal", value: escaped3 });
27262
+ } else if (character === "[") {
27263
+ const negative = characters[index + 1] === "!" || characters[index + 1] === "^";
27264
+ if (negative) index++;
27265
+ const ranges = [];
27266
+ let closed = false;
27267
+ while (++index < characters.length) {
27268
+ let first = characters[index];
27269
+ if (first === "]") {
27270
+ closed = true;
27271
+ break;
27272
+ }
27273
+ if (first === "\\") first = characters[++index] ?? "";
27274
+ let last = first;
27275
+ if (characters[index + 1] === "-" && characters[index + 2] && characters[index + 2] !== "]") {
27276
+ index += 2;
27277
+ last = characters[index];
27278
+ if (last === "\\") last = characters[++index] ?? "";
27279
+ }
27280
+ ranges.push([first.codePointAt(0) ?? -1, last.codePointAt(0) ?? -1]);
27281
+ }
27282
+ tokens2.push(closed ? { kind: "class", ranges, negative } : { kind: "never" });
27283
+ } else tokens2.push({ kind: "literal", value: character });
27284
+ }
27285
+ return tokens2;
27286
+ }
27287
+ var Selection = class {
27288
+ constructor(patterns2, limits, signal) {
27289
+ this.limits = limits;
27290
+ this.signal = signal;
27291
+ this.patterns = patterns2.map(tokenize2);
27292
+ }
27293
+ limits;
27294
+ signal;
27295
+ work = 0;
27296
+ patterns;
27297
+ matched = /* @__PURE__ */ new Set();
27298
+ step() {
27299
+ if (++this.work > this.limits.maxPatternSteps) fail("pattern work limit exceeded");
27300
+ }
27301
+ async matches(name2, firstMatchOnly = false) {
27302
+ if (!this.patterns.length) return true;
27303
+ const characters = Array.from(name2);
27304
+ let selected = false;
27305
+ for (let pattern = 0; pattern < this.patterns.length; pattern++) {
27306
+ this.step();
27307
+ let states = new Uint8Array(characters.length + 1);
27308
+ states[0] = 1;
27309
+ for (const token of this.patterns[pattern]) {
27310
+ const next = new Uint8Array(states.length);
27311
+ for (let index = 0; index < states.length; index++) {
27312
+ this.step();
27313
+ if (token.kind === "star") next[index] = states[index] || (index > 0 ? next[index - 1] : 0);
27314
+ else if (states[index] && index < characters.length) {
27315
+ const character = characters[index];
27316
+ let match = token.kind === "any" || token.kind === "literal" && token.value === character;
27317
+ if (token.kind === "class") {
27318
+ let inRange = false;
27319
+ for (const [first, last] of token.ranges) {
27320
+ this.step();
27321
+ if (character.codePointAt(0) >= first && character.codePointAt(0) <= last) inRange = true;
27322
+ }
27323
+ match = inRange !== token.negative;
27324
+ }
27325
+ if (match) next[index + 1] = 1;
27326
+ }
27327
+ if (this.work % 4096 === 0) await yieldTurn(this.signal);
27328
+ }
27329
+ states = next;
27330
+ }
27331
+ if (states[characters.length]) {
27332
+ this.matched.add(pattern);
27333
+ if (firstMatchOnly) return true;
27334
+ selected = true;
27335
+ }
27336
+ }
27337
+ return selected;
27338
+ }
27339
+ };
27340
+ var Answers = class {
27341
+ constructor(source2, limits, signal) {
27342
+ this.limits = limits;
27343
+ this.signal = signal;
27344
+ this.iterator = readBytes(source2, signal)[Symbol.asyncIterator]();
27345
+ }
27346
+ limits;
27347
+ signal;
27348
+ iterator;
27349
+ chunk = new Uint8Array();
27350
+ offset = 0;
27351
+ bytes = 0;
27352
+ pulls = 0;
27353
+ async read(maximum = 9) {
27354
+ const answer = [];
27355
+ while (answer.length < maximum) {
27356
+ this.signal.throwIfAborted();
27357
+ if (this.offset === this.chunk.length) {
27358
+ if (++this.pulls > this.limits.maxPatternSteps) fail("overwrite input work limit exceeded");
27359
+ if (this.pulls % 64 === 0) await yieldTurn(this.signal);
27360
+ const next = await this.iterator.next();
27361
+ if (next.done) break;
27362
+ if (next.value.length > this.limits.maxFilesFromBytes - this.bytes) fail("overwrite input byte limit exceeded");
27363
+ this.bytes += next.value.length;
27364
+ this.chunk = Uint8Array.from(next.value);
27365
+ this.offset = 0;
27366
+ if (!this.chunk.length) continue;
27367
+ }
27368
+ const byte = this.chunk[this.offset++];
27369
+ answer.push(byte);
27370
+ if (byte === 10) break;
27371
+ }
27372
+ return answer.length ? import_buffer.Buffer.from(answer).toString("utf8") : void 0;
27373
+ }
27374
+ async close() {
27375
+ await this.iterator.return?.();
27376
+ }
27377
+ };
27378
+
27197
27379
  // packages/safe-bash/src/commands/archive/zip.ts
27198
27380
  var ZipFailure = class extends Error {
27199
27381
  constructor(status2, label, detail) {
@@ -27225,19 +27407,46 @@ function parse12(context2, limits) {
27225
27407
  let archive;
27226
27408
  let recursive = false;
27227
27409
  let quiet = false;
27410
+ let junkPaths = false;
27228
27411
  let literal = false;
27229
27412
  let firstOperand = -1;
27230
27413
  const operands = [];
27231
- for (const [index, argument2] of context2.args.entries()) {
27414
+ const includes = [];
27415
+ const excludes = [];
27416
+ for (let index = 0; index < context2.args.length; index++) {
27417
+ const argument2 = context2.args[index];
27232
27418
  checkPath(argument2, limits);
27233
27419
  if (!literal && argument2 === "--") {
27234
27420
  if (archive === void 0) throw new ZipFailure(16, "Invalid command arguments", "can't use -- before archive name");
27235
27421
  literal = true;
27236
27422
  } else if (!literal && argument2.startsWith("-") && argument2 !== "-") {
27237
- for (const flag of argument2.slice(1)) {
27423
+ for (let offset = 1; offset < argument2.length; offset++) {
27424
+ const flag = argument2[offset];
27238
27425
  if (flag === "r") recursive = true;
27239
27426
  else if (flag === "q") quiet = true;
27240
- else throw new ZipFailure(16, "Invalid command arguments", `unsupported option: ${argument2}`);
27427
+ else if (flag === "j") junkPaths = true;
27428
+ else if (flag === "i" || flag === "x") {
27429
+ const patterns2 = flag === "i" ? includes : excludes;
27430
+ const before = patterns2.length;
27431
+ const append = (pattern) => {
27432
+ checkPath(pattern, limits);
27433
+ if (includes.length + excludes.length >= limits.maxMembers) fail("pattern count limit exceeded");
27434
+ patterns2.push(pattern);
27435
+ };
27436
+ if (offset + 1 < argument2.length) append(argument2.slice(offset + 1));
27437
+ while (index + 1 < context2.args.length) {
27438
+ const next = context2.args[index + 1];
27439
+ if (next === "@") {
27440
+ index++;
27441
+ break;
27442
+ }
27443
+ if (next.startsWith("-") && next !== "-") break;
27444
+ append(next);
27445
+ index++;
27446
+ }
27447
+ if (patterns2.length === before) throw new ZipFailure(16, "Invalid command arguments", `option '${flag}' requires a value`);
27448
+ break;
27449
+ } else throw new ZipFailure(16, "Invalid command arguments", `unsupported option: ${argument2}`);
27241
27450
  }
27242
27451
  } else if (archive === void 0) archive = argument2;
27243
27452
  else {
@@ -27246,11 +27455,11 @@ function parse12(context2, limits) {
27246
27455
  operands.push(argument2);
27247
27456
  }
27248
27457
  }
27249
- if (archive === void 0) throw new ZipFailure(16, "Invalid command arguments", "expected zip [-r] [-q] ARCHIVE FILES...");
27458
+ if (archive === void 0) throw new ZipFailure(16, "Invalid command arguments", "expected zip [-r] [-q] [-j] ARCHIVE FILES...");
27250
27459
  if (archive === "-" || operands.includes("-")) throw new ZipFailure(16, "Invalid command arguments", "standard input/output archives are unsupported");
27251
27460
  if (!archive.slice(archive.lastIndexOf("/") + 1).includes(".")) archive += ".zip";
27252
27461
  checkPath(archive, limits);
27253
- return { archive, recursive, quiet, operands, firstOperand };
27462
+ return { archive, recursive, quiet, junkPaths, includes, excludes, operands, firstOperand };
27254
27463
  }
27255
27464
  function memberName(path, limits) {
27256
27465
  if (path.startsWith("//") && !path.startsWith("///")) fail("UNC source paths are unsupported");
@@ -27287,6 +27496,7 @@ async function prepare(scope, parsed, budget) {
27287
27496
  }
27288
27497
  const old = new Map(archive.entries.map((entry) => [entry.name, entry]));
27289
27498
  const selected = /* @__PURE__ */ new Map();
27499
+ const selection = new Selection([...parsed.includes, ...parsed.excludes], limits, context2.signal);
27290
27500
  const ancestors = [];
27291
27501
  let visits = 0;
27292
27502
  let work = 0;
@@ -27321,7 +27531,17 @@ async function prepare(scope, parsed, budget) {
27321
27531
  if (existing2 && !hasIdentity(stat)) fail("cannot exclude archive aliases when source backing identity is unknown");
27322
27532
  const directory2 = stat.type === "directory";
27323
27533
  if (directory2 && name2 && !name2.endsWith("/")) name2 += "/";
27324
- if (name2) {
27534
+ selection.matched.clear();
27535
+ await selection.matches(name2);
27536
+ let included = parsed.includes.length === 0;
27537
+ let excluded = false;
27538
+ for (const pattern of selection.matched) {
27539
+ if (pattern < parsed.includes.length) included = true;
27540
+ else excluded = true;
27541
+ }
27542
+ const sourceName = name2;
27543
+ if (parsed.junkPaths) name2 = directory2 ? "" : name2.slice(name2.lastIndexOf("/") + 1);
27544
+ if (name2 && included && !excluded) {
27325
27545
  checkPath(name2, limits);
27326
27546
  const previous = selected.get(name2);
27327
27547
  if (previous && previous.source !== source2) {
@@ -27356,7 +27576,7 @@ async function prepare(scope, parsed, budget) {
27356
27576
  for (const child of children) {
27357
27577
  if (!child.name || child.name === "." || child.name === ".." || child.name.includes("/") || child.name.includes("\0")) fail("invalid filesystem directory entry");
27358
27578
  const prefix3 = source2 === "." ? "" : source2.endsWith("/") ? source2 : `${source2}/`;
27359
- await visit(`${prefix3}${child.name}`, `${name2}${child.name}`, depth + 1);
27579
+ await visit(`${prefix3}${child.name}`, `${sourceName}${child.name}`, depth + 1);
27360
27580
  }
27361
27581
  } finally {
27362
27582
  ancestors.pop();
@@ -27364,7 +27584,7 @@ async function prepare(scope, parsed, budget) {
27364
27584
  }
27365
27585
  };
27366
27586
  for (const operand of parsed.operands) await visit(operand, memberName(operand, limits), 0);
27367
- if (!selected.size) {
27587
+ if (!selected.size && !parsed.includes.length) {
27368
27588
  const detail = parsed.recursive && parsed.firstOperand >= 0 ? `try: zip ${context2.args.slice(0, parsed.firstOperand).join(" ")} . -i ${context2.args.slice(parsed.firstOperand).join(" ")}` : parsed.archive;
27369
27589
  throw new ZipFailure(12, "Nothing to do!", detail);
27370
27590
  }
@@ -27397,6 +27617,7 @@ async function prepare(scope, parsed, budget) {
27397
27617
  entries2.push(entry);
27398
27618
  append(entry, false);
27399
27619
  }
27620
+ if (!entries2.length && !parsed.quiet) await budget.output(" zip warning: zip file empty\n");
27400
27621
  const bytes3 = await writeZipArchive({ entries: entries2, comment: archive.comment }, limits, context2.signal);
27401
27622
  return { output: output2, parentName, parent, parentStat, existing: existing2, bytes: bytes3, progress };
27402
27623
  }
@@ -27439,188 +27660,6 @@ zip error: ${error.label} (${error.message})
27439
27660
  // packages/safe-bash/src/commands/archive/unzip.ts
27440
27661
  init_platform();
27441
27662
 
27442
- // packages/safe-bash/src/commands/archive/unzip/arguments.ts
27443
- init_platform();
27444
- function parseArguments(context2, limits) {
27445
- const { args } = context2;
27446
- let bytes3 = 0;
27447
- for (const argument2 of args) {
27448
- bytes3 += import_buffer.Buffer.byteLength(argument2) + 1;
27449
- if (bytes3 > limits.maxArgumentBytes) fail("argument byte limit exceeded");
27450
- if (argument2.includes("\0")) fail("NUL in argument");
27451
- }
27452
- if (context2.argumentValues) {
27453
- const argumentsValue = getCommandArguments(context2);
27454
- let rawBytes = 0;
27455
- for (const value2 of argumentsValue.values) {
27456
- const size = shellValueByteLength(value2) + 1;
27457
- if (size > limits.maxArgumentBytes - rawBytes) fail("argument byte limit exceeded");
27458
- rawBytes += size;
27459
- }
27460
- for (const value2 of argumentsValue.values) text2(shellValueBytes(value2));
27461
- }
27462
- let list = false;
27463
- let pipe = false;
27464
- let overwrite = false;
27465
- let destination2;
27466
- let archive;
27467
- let ended = false;
27468
- const patterns2 = [];
27469
- for (let index = 0; index < args.length; index++) {
27470
- const argument2 = args[index];
27471
- if (!ended && argument2 === "--") {
27472
- ended = true;
27473
- continue;
27474
- }
27475
- if (!ended && argument2.startsWith("-") && argument2 !== "-") {
27476
- for (let offset = 1; offset < argument2.length; offset++) {
27477
- const flag = argument2[offset];
27478
- if (flag === "l") list = true;
27479
- else if (flag === "p") pipe = true;
27480
- else if (flag === "o") overwrite = true;
27481
- else if (flag === "d") {
27482
- if (destination2 !== void 0) fail("-d may only be specified once");
27483
- destination2 = argument2.slice(offset + 1) || args[++index];
27484
- if (!destination2) fail("must specify directory to which to extract with -d option");
27485
- checkPath(destination2, limits);
27486
- break;
27487
- } else fail(`unsupported option: -${flag}`);
27488
- }
27489
- } else if (archive === void 0) archive = argument2;
27490
- else patterns2.push(argument2);
27491
- }
27492
- if (archive === void 0) fail("usage: unzip [-l] [-p] [-o] [-d DIR] ARCHIVE [FILES...]");
27493
- checkPath(archive, limits);
27494
- return { list: list && !pipe, pipe, overwrite, destination: destination2, archive, patterns: patterns2 };
27495
- }
27496
- function tokenize2(pattern) {
27497
- const characters = Array.from(pattern);
27498
- const tokens2 = [];
27499
- for (let index = 0; index < characters.length; index++) {
27500
- const character = characters[index];
27501
- if (character === "*") {
27502
- if (tokens2.at(-1)?.kind !== "star") tokens2.push({ kind: "star" });
27503
- } else if (character === "?") tokens2.push({ kind: "any" });
27504
- else if (character === "\\") {
27505
- const escaped3 = characters[++index];
27506
- tokens2.push(escaped3 === void 0 ? { kind: "never" } : { kind: "literal", value: escaped3 });
27507
- } else if (character === "[") {
27508
- const negative = characters[index + 1] === "!" || characters[index + 1] === "^";
27509
- if (negative) index++;
27510
- const ranges = [];
27511
- let closed = false;
27512
- while (++index < characters.length) {
27513
- let first = characters[index];
27514
- if (first === "]") {
27515
- closed = true;
27516
- break;
27517
- }
27518
- if (first === "\\") first = characters[++index] ?? "";
27519
- let last = first;
27520
- if (characters[index + 1] === "-" && characters[index + 2] && characters[index + 2] !== "]") {
27521
- index += 2;
27522
- last = characters[index];
27523
- if (last === "\\") last = characters[++index] ?? "";
27524
- }
27525
- ranges.push([first.codePointAt(0) ?? -1, last.codePointAt(0) ?? -1]);
27526
- }
27527
- tokens2.push(closed ? { kind: "class", ranges, negative } : { kind: "never" });
27528
- } else tokens2.push({ kind: "literal", value: character });
27529
- }
27530
- return tokens2;
27531
- }
27532
- var Selection = class {
27533
- constructor(patterns2, limits, signal) {
27534
- this.limits = limits;
27535
- this.signal = signal;
27536
- this.patterns = patterns2.map(tokenize2);
27537
- }
27538
- limits;
27539
- signal;
27540
- work = 0;
27541
- patterns;
27542
- matched = /* @__PURE__ */ new Set();
27543
- step() {
27544
- if (++this.work > this.limits.maxPatternSteps) fail("pattern work limit exceeded");
27545
- }
27546
- async matches(name2, firstMatchOnly = false) {
27547
- if (!this.patterns.length) return true;
27548
- const characters = Array.from(name2);
27549
- let selected = false;
27550
- for (let pattern = 0; pattern < this.patterns.length; pattern++) {
27551
- this.step();
27552
- let states = new Uint8Array(characters.length + 1);
27553
- states[0] = 1;
27554
- for (const token of this.patterns[pattern]) {
27555
- const next = new Uint8Array(states.length);
27556
- for (let index = 0; index < states.length; index++) {
27557
- this.step();
27558
- if (token.kind === "star") next[index] = states[index] || (index > 0 ? next[index - 1] : 0);
27559
- else if (states[index] && index < characters.length) {
27560
- const character = characters[index];
27561
- let match = token.kind === "any" || token.kind === "literal" && token.value === character;
27562
- if (token.kind === "class") {
27563
- let inRange = false;
27564
- for (const [first, last] of token.ranges) {
27565
- this.step();
27566
- if (character.codePointAt(0) >= first && character.codePointAt(0) <= last) inRange = true;
27567
- }
27568
- match = inRange !== token.negative;
27569
- }
27570
- if (match) next[index + 1] = 1;
27571
- }
27572
- if (this.work % 4096 === 0) await yieldTurn(this.signal);
27573
- }
27574
- states = next;
27575
- }
27576
- if (states[characters.length]) {
27577
- this.matched.add(pattern);
27578
- if (firstMatchOnly) return true;
27579
- selected = true;
27580
- }
27581
- }
27582
- return selected;
27583
- }
27584
- };
27585
- var Answers = class {
27586
- constructor(source2, limits, signal) {
27587
- this.limits = limits;
27588
- this.signal = signal;
27589
- this.iterator = readBytes(source2, signal)[Symbol.asyncIterator]();
27590
- }
27591
- limits;
27592
- signal;
27593
- iterator;
27594
- chunk = new Uint8Array();
27595
- offset = 0;
27596
- bytes = 0;
27597
- pulls = 0;
27598
- async read(maximum = 9) {
27599
- const answer = [];
27600
- while (answer.length < maximum) {
27601
- this.signal.throwIfAborted();
27602
- if (this.offset === this.chunk.length) {
27603
- if (++this.pulls > this.limits.maxPatternSteps) fail("overwrite input work limit exceeded");
27604
- if (this.pulls % 64 === 0) await yieldTurn(this.signal);
27605
- const next = await this.iterator.next();
27606
- if (next.done) break;
27607
- if (next.value.length > this.limits.maxFilesFromBytes - this.bytes) fail("overwrite input byte limit exceeded");
27608
- this.bytes += next.value.length;
27609
- this.chunk = Uint8Array.from(next.value);
27610
- this.offset = 0;
27611
- if (!this.chunk.length) continue;
27612
- }
27613
- const byte = this.chunk[this.offset++];
27614
- answer.push(byte);
27615
- if (byte === 10) break;
27616
- }
27617
- return answer.length ? import_buffer.Buffer.from(answer).toString("utf8") : void 0;
27618
- }
27619
- async close() {
27620
- await this.iterator.return?.();
27621
- }
27622
- };
27623
-
27624
27663
  // packages/safe-bash/src/commands/archive/unzip/safety.ts
27625
27664
  init_platform();
27626
27665
  import { retainFileSystemCleanup as retainFileSystemCleanup3 } from "@poe-platform/safe-fs/core";