@poe-platform/safe-bash 0.1.814 → 0.1.815

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.
Files changed (59) hide show
  1. package/dist/mp4-ast/index.d.ts +1 -0
  2. package/dist/mp4-ast/mp4-fragment-source.d.ts +35 -0
  3. package/dist/mp4-ast/mp4-sample-source.d.ts +5 -2
  4. package/dist/mp4-ast/types.d.ts +11 -0
  5. package/dist/pdf-ast/cos/object-reader.d.ts +3 -2
  6. package/dist/pdf-ast/edit/forms.d.ts +1 -0
  7. package/dist/pdf-ast/edit/retained-form-data.d.ts +9 -0
  8. package/dist/pdf-ast/index.d.ts +1 -0
  9. package/dist/pdf-ast/index.js +476 -55
  10. package/dist/safe-bash/command-chunks/{biff-KRHJ63K3-VQPJCVIL.js → biff-A7XPBWAK-DCLG5QKF.js} +1775 -1667
  11. package/dist/safe-bash/command-chunks/{chunk-AVGXFWEB.js → chunk-44F5TOHZ.js} +179 -58
  12. package/dist/safe-bash/command-chunks/{chunk-PIVH35EQ.js → chunk-6CDDKNNA.js} +1 -0
  13. package/dist/safe-bash/command-chunks/{chunk-K4XNUJVJ.js → chunk-6EINUY5G.js} +149 -165
  14. package/dist/safe-bash/command-chunks/{chunk-5BIQWWLB.js → chunk-CFMJXJS5.js} +1 -1
  15. package/dist/safe-bash/command-chunks/{chunk-3JM7E42I.js → chunk-GPGLTWNR.js} +106 -32
  16. package/dist/safe-bash/command-chunks/{chunk-2ETEJOYX.js → chunk-HQ2UN2L2.js} +8 -8
  17. package/dist/safe-bash/command-chunks/{chunk-CK2WFJZN.js → chunk-KASXIRKD.js} +12 -14
  18. package/dist/safe-bash/command-chunks/chunk-KHUT7BB5.js +65 -0
  19. package/dist/safe-bash/command-chunks/{chunk-LAPOMHGY.js → chunk-NEYITAAO.js} +114 -97
  20. package/dist/safe-bash/command-chunks/{chunk-FF7UGJWS.js → chunk-QDVDBN2N.js} +1 -1
  21. package/dist/safe-bash/command-chunks/{chunk-SW37YCBW.js → chunk-U3C6IT2C.js} +44 -30
  22. package/dist/safe-bash/command-chunks/{chunk-G3TAX3CV.js → chunk-WAT2562G.js} +610 -539
  23. package/dist/safe-bash/command-chunks/{chunk-VT7UBPAE.js → chunk-YW2VYN4V.js} +23 -11
  24. package/dist/safe-bash/command-chunks/{chunk-GQGMQMIM.js → chunk-ZIGENXGC.js} +243 -1
  25. package/dist/safe-bash/command-chunks/{command-engine-7V6PZR7G.js → command-engine-M7S4QIXV.js} +12 -4
  26. package/dist/safe-bash/command-chunks/{engine-UYJENSWK-VSCGKSQV.js → engine-YUYZJIB4-NZUDFEHL.js} +1 -1
  27. package/dist/safe-bash-command-ffmpeg/index.js +1 -1
  28. package/dist/safe-bash-command-ffprobe/index.js +2 -2
  29. package/dist/safe-bash-command-ffprobe/media.d.ts +8 -2
  30. package/dist/safe-bash-command-ffprobe/media.js +4 -2
  31. package/dist/safe-bash-command-pandoc/command.js +3 -3
  32. package/dist/safe-bash-command-pandoc/index.js +8 -8
  33. package/dist/safe-bash-command-patch/index.js +7 -6
  34. package/dist/safe-bash-command-patch/patch-formats.d.ts +6 -5
  35. package/dist/safe-bash-command-patch/patch-formats.js +3 -2
  36. package/dist/safe-bash-command-patch/patch-gnu-paths.d.ts +7 -7
  37. package/dist/safe-bash-command-patch/patch-gnu-reject.d.ts +1 -1
  38. package/dist/safe-bash-command-patch/patch-gnu-reject.js +3 -2
  39. package/dist/safe-bash-command-patch/patch-publication.js +3 -2
  40. package/dist/safe-bash-command-patch/patch-text.d.ts +13 -0
  41. package/dist/safe-bash-command-patch/patch.js +7 -6
  42. package/dist/safe-bash-command-patch/stored-patch.d.ts +29 -4
  43. package/dist/safe-bash-command-patch/stored-target.d.ts +2 -1
  44. package/dist/safe-bash-command-patch/unified.d.ts +18 -4
  45. package/dist/safe-bash-command-patch/unified.js +2 -1
  46. package/dist/safe-bash-command-pdftk/index.js +30 -20
  47. package/dist/safe-bash-command-pptx/engine.js +1 -1
  48. package/dist/safe-bash-command-ssconvert/index.js +2 -2
  49. package/dist/safe-bash-presentation-engine/index.js +1 -1
  50. package/dist/safe-bash-presentation-engine/notes.d.ts +1 -0
  51. package/dist/safe-bash-presentation-engine/notes.js +7 -1
  52. package/dist/safe-bash-presentation-engine/retained-notes.d.ts +27 -0
  53. package/dist/safe-bash-xml-engine/document.js +2 -2
  54. package/dist/safe-bash-xml-engine/index.js +2 -2
  55. package/dist/safe-bash-xml-engine/stored-document.js +1 -1
  56. package/dist/spreadsheet-format-xls/biff-properties-merge.js +40 -21
  57. package/dist/spreadsheet-format-xls/biff-property-values.d.ts +31 -0
  58. package/dist/spreadsheet-format-xls/biff-property-values.js +158 -0
  59. package/package.json +3 -2
@@ -1,25 +1,27 @@
1
1
  import {
2
2
  PatchBodyStore,
3
+ patchHunk,
4
+ patchHunks,
3
5
  patchLine,
4
6
  rejectBytes,
5
7
  reverseStoredPatch
6
- } from "./chunk-3JM7E42I.js";
8
+ } from "./chunk-GPGLTWNR.js";
7
9
  import {
8
10
  PatchPublication
9
- } from "./chunk-5BIQWWLB.js";
11
+ } from "./chunk-CFMJXJS5.js";
10
12
  import {
11
13
  TargetDocuments,
12
14
  TargetOutput,
13
15
  equalTargetLines,
14
16
  targetBytes
15
- } from "./chunk-CK2WFJZN.js";
17
+ } from "./chunk-KASXIRKD.js";
16
18
  import {
17
19
  parsePatchWith
18
- } from "./chunk-SW37YCBW.js";
20
+ } from "./chunk-U3C6IT2C.js";
19
21
  import {
20
22
  parseUnifiedReader,
21
23
  startIndex
22
- } from "./chunk-VT7UBPAE.js";
24
+ } from "./chunk-YW2VYN4V.js";
23
25
  import {
24
26
  authorizeOutputs,
25
27
  authorizePaths,
@@ -38,7 +40,7 @@ import {
38
40
 
39
41
  // packages/safe-bash-command-patch/src/patch.ts
40
42
  import { closeDocumentResources as closeDocumentResources2 } from "../../safe-bash-diff-engine/document.js";
41
- import { PagedStorage as PagedStorage2 } from "@poe-platform/safe-fs/storage";
43
+ import { PagedStorage as PagedStorage3 } from "@poe-platform/safe-fs/storage";
42
44
 
43
45
  // packages/safe-bash-command-patch/src/stored-hunks.ts
44
46
  import { closeDocumentResources } from "../../safe-bash-diff-engine/document.js";
@@ -55,7 +57,7 @@ async function applyStoredHunks(original, patch, fuzz, budget, ignoreWhitespace
55
57
  let cursor = 0;
56
58
  let offset = 0;
57
59
  let outputOffset = 0;
58
- for (const [hunkIndex, hunk] of patch.hunks.entries()) {
60
+ for await (const [hunkIndex, hunk] of patchHunks(patch)) {
59
61
  budget.step();
60
62
  const oldIndex = indices.allocate((hunk.oldCount + hunk.newCount) * 8), newIndex = oldIndex + hunk.oldCount * 8;
61
63
  let oldPosition = oldIndex, newPosition = newIndex;
@@ -169,7 +171,7 @@ async function applyStoredHunks(original, patch, fuzz, budget, ignoreWhitespace
169
171
  const matched = found;
170
172
  if (matched >= 0) offset = matched - startIndex(hunk.oldStart, hunk.oldCount);
171
173
  if (misordered) found = -1;
172
- application.outcomes?.push({
174
+ await application.outcomes?.push({
173
175
  hunk,
174
176
  index: hunkIndex + 1,
175
177
  failed: found < 0,
@@ -204,8 +206,8 @@ async function applyStoredHunks(original, patch, fuzz, budget, ignoreWhitespace
204
206
  let identical = localLength === hunk.newCount;
205
207
  for (let index = 0; identical && index < localLength; index++) identical = await equalTargetLines(source.at(cursor + index), await indexedLine(newIndex, index), budget);
206
208
  if (identical) {
207
- const last = application.outcomes?.pop();
208
- if (last) application.outcomes.push({ ...last, failed: false, fuzz: 0, offset: position - startIndex(hunk.oldStart, hunk.oldCount) });
209
+ const last = await application.outcomes?.pop();
210
+ if (last) await application.outcomes.push({ ...last, failed: false, fuzz: 0, offset: position - startIndex(hunk.oldStart, hunk.oldCount) });
209
211
  for (let index = prefix; index < localLength - suffix; index++) await result.append(source.at(cursor + index));
210
212
  } else {
211
213
  await result.append("<<<<<<<\n");
@@ -217,8 +219,8 @@ async function applyStoredHunks(original, patch, fuzz, budget, ignoreWhitespace
217
219
  await result.append("=======\n");
218
220
  for (let index = prefix; index < hunk.newCount - suffix; index++) await result.append(await indexedLine(newIndex, index));
219
221
  await result.append(">>>>>>>\n");
220
- const last = application.outcomes?.pop();
221
- if (last) application.outcomes.push({ ...last, mergeRange: [mergeStart, result.length] });
222
+ const last = await application.outcomes?.pop();
223
+ if (last) await application.outcomes.push({ ...last, mergeRange: [mergeStart, result.length] });
222
224
  }
223
225
  for (let index = localLength - suffix; index < localLength; index++) await result.append(source.at(cursor + index));
224
226
  cursor += localLength;
@@ -285,10 +287,14 @@ var StoredPatchInput = class {
285
287
  length;
286
288
  cachedIndex = -1;
287
289
  cachedLine = "";
288
- async read(index) {
290
+ async read(index, prefix) {
289
291
  if (index < 0 || index >= this.length) return void 0;
290
- if (index === this.cachedIndex) return this.cachedLine;
292
+ if (index === this.cachedIndex) return prefix === void 0 ? this.cachedLine : this.cachedLine.slice(0, prefix);
291
293
  const line = await this.document.line(this.start + index);
294
+ if (prefix !== void 0) {
295
+ const size = Math.min(prefix, line.end - line.start - (this.crlf ? 2 : 1));
296
+ return new TextDecoder("utf-8", { ignoreBOM: true }).decode(await this.document.data.read(8 + line.start, size));
297
+ }
292
298
  const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
293
299
  let text = "";
294
300
  for await (const block of this.document.range(line.start, line.end - (this.crlf ? 2 : 1))) text += decoder.decode(block, { stream: true });
@@ -297,12 +303,49 @@ var StoredPatchInput = class {
297
303
  this.cachedLine = text;
298
304
  return text;
299
305
  }
306
+ async matches(index, text) {
307
+ if (index < 0 || index >= this.length) return false;
308
+ const line = await this.document.line(this.start + index), bytes = new TextEncoder().encode(text);
309
+ if (line.end - line.start - (this.crlf ? 2 : 1) !== bytes.length) return false;
310
+ let at = 0;
311
+ for await (const block of this.document.range(line.start, line.end - (this.crlf ? 2 : 1)))
312
+ for (const byte of block) if (byte !== bytes[at++]) return false;
313
+ return true;
314
+ }
315
+ async body(index, skip, incomplete) {
316
+ const line = await this.document.line(this.start + index), document = this.document;
317
+ const end = line.end - (this.crlf ? 2 : 1), start = Math.min(line.start + skip, end);
318
+ return { size: end - start + (incomplete ? 0 : 1), terminated: !incomplete, bytes: {
319
+ async *[Symbol.asyncIterator]() {
320
+ yield* document.range(start, end);
321
+ if (!incomplete) yield new Uint8Array([10]);
322
+ }
323
+ } };
324
+ }
300
325
  async signature(index) {
301
326
  const line = await this.document.line(this.start + index);
302
327
  if (line.end - line.start !== (this.crlf ? 5 : 4)) return false;
303
328
  const bytes = await this.document.data.read(8 + line.start, 3);
304
329
  return bytes[0] === 45 && bytes[1] === 45 && bytes[2] === 32;
305
330
  }
331
+ /** Recognize the unbounded numeric prefix used by mail patch admission. */
332
+ async normalCommand(index) {
333
+ const line = await this.document.line(this.start + index);
334
+ let state = "start";
335
+ for await (const block of this.document.range(line.start, line.end)) for (const byte of block) {
336
+ const digit = byte >= 48 && byte <= 57;
337
+ if (state === "operation") return digit;
338
+ if (state === "start" || state === "comma") {
339
+ if (!digit) return false;
340
+ state = state === "start" ? "first" : "second";
341
+ } else if (!digit) {
342
+ if (state === "first" && byte === 44) state = "comma";
343
+ else if (byte === 97 || byte === 99 || byte === 100) state = "operation";
344
+ else return false;
345
+ }
346
+ }
347
+ return false;
348
+ }
306
349
  };
307
350
  async function unwrapStoredPatch(document, budget) {
308
351
  if (document.size && (await document.data.read(8 + document.size - 1, 1))[0] !== 10) throw new ToolError2("patch is truncated: missing final LF");
@@ -320,13 +363,13 @@ async function unwrapStoredPatch(document, budget) {
320
363
  }
321
364
  const input = new StoredPatchInput(document, crlf);
322
365
  let start = 0;
323
- if (/^(?:From [0-9a-f]{40,64} |(?:From|Date|Subject|To|Cc|MIME-Version|Content-Type):)/u.test(await input.read(0) ?? "")) {
366
+ if (/^(?:From [0-9a-f]{40,64} |(?:From|Date|Subject|To|Cc|MIME-Version|Content-Type):)/u.test(await input.read(0, 128) ?? "")) {
324
367
  while (start < input.length) {
325
368
  budget.step();
326
369
  const pause = budget.checkpoint();
327
370
  if (pause) await pause;
328
- const line = await input.read(start);
329
- if (/^(?:--- |\*\*\* |diff |\d+(?:,\d+)?[acd]\d)/u.test(line)) break;
371
+ const line = await input.read(start, 128);
372
+ if (/^(?:--- |\*\*\* |diff )/u.test(line) || /^\d/u.test(line) && await input.normalCommand(start)) break;
330
373
  if (/^(?:old mode |new mode |new file mode |deleted file mode |rename |copy |similarity index |dissimilarity index |GIT binary patch|Binary files |index |@@|[+\\])/u.test(line)) throw new ToolError2("unsupported or malformed mail patch metadata");
331
374
  if (++start > budget.limits.maxLines) throw new ToolError2("mail preamble limit exceeded");
332
375
  }
@@ -344,12 +387,77 @@ async function unwrapStoredPatch(document, budget) {
344
387
  budget.step();
345
388
  const pause2 = budget.checkpoint();
346
389
  if (pause2) await pause2;
347
- if (/^(?:diff |---|\+\+\+|\*\*\*|@@|index |old mode |new mode |new file mode |deleted file mode |rename |copy |similarity index |dissimilarity index |GIT binary patch|Binary files |[+\\]|\d+(?:,\d+)?[acd]\d)/u.test(await input.read(index))) throw new ToolError2("patch data after mail signature");
390
+ const line = await input.read(index, 128);
391
+ if (/^(?:diff |---|\+\+\+|\*\*\*|@@|index |old mode |new mode |new file mode |deleted file mode |rename |copy |similarity index |dissimilarity index |GIT binary patch|Binary files |[+\\])/u.test(line) || /^\d/u.test(line) && await input.normalCommand(index)) throw new ToolError2("patch data after mail signature");
348
392
  }
349
393
  }
350
394
  return new StoredPatchInput(document, crlf, start, end - start);
351
395
  }
352
396
 
397
+ // packages/safe-bash-command-patch/src/stored-outcomes.ts
398
+ import { PagedStorage as PagedStorage2 } from "@poe-platform/safe-fs/storage";
399
+ var OutcomeStore = class {
400
+ records;
401
+ constructor(documents) {
402
+ this.records = new PagedStorage2(documents.budget.context, 16, documents.cache);
403
+ }
404
+ create(patch) {
405
+ return new StoredOutcomes(this.records, this.records.allocate(patch.hunks.length * 64), patch);
406
+ }
407
+ close() {
408
+ return this.records.close();
409
+ }
410
+ };
411
+ var StoredOutcomes = class {
412
+ constructor(records, start, patch) {
413
+ this.records = records;
414
+ this.start = start;
415
+ this.patch = patch;
416
+ }
417
+ records;
418
+ start;
419
+ patch;
420
+ length = 0;
421
+ async push(outcome) {
422
+ if (this.length >= this.patch.hunks.length) throw new RangeError("Too many patch outcomes");
423
+ const bytes = new Uint8Array(64), view = new DataView(bytes.buffer);
424
+ view.setFloat64(0, outcome.index, true);
425
+ view.setFloat64(8, outcome.line, true);
426
+ view.setFloat64(16, outcome.outputOffset, true);
427
+ view.setFloat64(24, outcome.offset, true);
428
+ view.setFloat64(32, outcome.fuzz, true);
429
+ view.setFloat64(40, outcome.mergeRange?.[0] ?? NaN, true);
430
+ view.setFloat64(48, outcome.mergeRange?.[1] ?? NaN, true);
431
+ bytes[56] = (outcome.failed ? 1 : 0) | (outcome.misordered ? 2 : 0);
432
+ await this.records.write(this.start + this.length * 64, bytes);
433
+ this.length++;
434
+ }
435
+ async at(position) {
436
+ if (!Number.isSafeInteger(position) || position < 0 || position >= this.length) return void 0;
437
+ const bytes = await this.records.read(this.start + position * 64, 64), view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
438
+ const index = view.getFloat64(0, true), mergeStart = view.getFloat64(40, true);
439
+ return {
440
+ hunk: await patchHunk(this.patch, index - 1),
441
+ index,
442
+ line: view.getFloat64(8, true),
443
+ outputOffset: view.getFloat64(16, true),
444
+ offset: view.getFloat64(24, true),
445
+ fuzz: view.getFloat64(32, true),
446
+ failed: !!(bytes[56] & 1),
447
+ misordered: !!(bytes[56] & 2),
448
+ ...Number.isNaN(mergeStart) ? {} : { mergeRange: [mergeStart, view.getFloat64(48, true)] }
449
+ };
450
+ }
451
+ async pop() {
452
+ const outcome = await this.at(this.length - 1);
453
+ if (outcome) this.length--;
454
+ return outcome;
455
+ }
456
+ async *[Symbol.asyncIterator]() {
457
+ for (let index = 0; index < this.length; index++) yield await this.at(index);
458
+ }
459
+ };
460
+
353
461
  // packages/safe-bash-command-patch/src/patch.ts
354
462
  import { FsError, dirname, pathOf, pipeBytes, resolvePath, writeBytes } from "../../safe-bash-contracts/index.js";
355
463
  import { publicDiagnosticMessage } from "../../safe-bash-contracts/diagnostics.js";
@@ -481,55 +589,59 @@ function flags(args) {
481
589
  if (result.posix && !backupSelected) result.backup = false;
482
590
  return result;
483
591
  }
484
- async function applyContent(sourcePatch, current, exists, options, budget, documents) {
592
+ async function applyContent(sourcePatch, current, exists, options, budget, documents, outcomeStore) {
485
593
  let reversed = options.reverse;
486
594
  let patch = reversed ? reverseStoredPatch(sourcePatch) : sourcePatch;
487
- const emptyOld = () => patch.hunks.every((hunk) => hunk.oldCount === 0 && hunk.oldStart === 0);
488
- const creation = () => patch.oldPath === "/dev/null" || emptyOld() && (patch.oldEpoch || !exists);
595
+ const emptySide = async (side, checkStart = true) => {
596
+ for await (const [, hunk] of patchHunks(patch)) if (hunk[`${side}Count`] !== 0 || checkStart && hunk[`${side}Start`] !== 0) return false;
597
+ return true;
598
+ };
599
+ const creation = async () => patch.oldPath === "/dev/null" || await emptySide("old") && (patch.oldEpoch || !exists);
489
600
  let autoReversed = false;
490
601
  let reverseMismatch = false;
491
- const declaredCreation = patch.oldPath === "/dev/null" || patch.oldEpoch && emptyOld();
492
- const declaredDeletion = patch.newPath === "/dev/null" || patch.newEpoch && patch.hunks.every((hunk) => hunk.newCount === 0);
602
+ const declaredCreation = patch.oldPath === "/dev/null" || patch.oldEpoch && await emptySide("old");
603
+ const declaredDeletion = patch.newPath === "/dev/null" || patch.newEpoch && await emptySide("new", false);
493
604
  if (!options.force && (declaredCreation && current.size !== 0 || declaredDeletion && !exists)) {
494
605
  patch = reverseStoredPatch(patch);
495
606
  reversed = !reversed;
496
607
  autoReversed = true;
497
608
  }
498
- if (!creation() && !exists) return void 0;
499
- let outcomes = [];
609
+ if (!await creation() && !exists) return void 0;
610
+ let outcomes = outcomeStore.create(patch);
500
611
  let result = await applyStoredHunks(current, patch, options.fuzz, budget, options.ignoreWhitespace, {
501
612
  partial: true,
502
613
  outcomes,
503
614
  ...options.ifdef === void 0 ? {} : { ifdef: options.ifdef },
504
615
  ...options.merge === void 0 ? {} : { merge: options.merge },
505
- rejectAll: creation() && current.size !== 0
616
+ rejectAll: await creation() && current.size !== 0
506
617
  }, documents);
507
- if (!options.merge && !options.force && !autoReversed && (outcomes[0]?.failed || outcomes[0]?.fuzz)) {
618
+ const first = await outcomes.at(0);
619
+ if (!options.merge && !options.force && !autoReversed && (first?.failed || first?.fuzz)) {
508
620
  const opposite = reverseStoredPatch(patch);
509
- const probe = [];
510
- const reverseFuzz = outcomes[0].failed ? options.fuzz : outcomes[0].fuzz - 1;
511
- const probeResult = await applyStoredHunks(current, { ...opposite, hunks: opposite.hunks.slice(0, 1) }, reverseFuzz, budget, options.ignoreWhitespace, { partial: true, outcomes: probe }, documents);
621
+ const probe = outcomeStore.create(opposite);
622
+ const reverseFuzz = first.failed ? options.fuzz : first.fuzz - 1;
623
+ const probeResult = await applyStoredHunks(current, { ...opposite, hunks: [await patchHunk(opposite, 0)] }, reverseFuzz, budget, options.ignoreWhitespace, { partial: true, outcomes: probe }, documents);
512
624
  await documents.release(probeResult);
513
- if (!probe[0]?.failed) {
625
+ if (!(await probe.at(0))?.failed) {
514
626
  patch = opposite;
515
627
  reversed = !reversed;
516
628
  autoReversed = true;
517
629
  reverseMismatch = true;
518
- outcomes = [];
630
+ outcomes = outcomeStore.create(patch);
519
631
  await documents.release(result);
520
632
  result = await applyStoredHunks(current, patch, options.fuzz, budget, options.ignoreWhitespace, {
521
633
  partial: true,
522
634
  outcomes,
523
635
  ...options.ifdef === void 0 ? {} : { ifdef: options.ifdef },
524
636
  ...options.merge === void 0 ? {} : { merge: options.merge },
525
- rejectAll: creation() && current.size !== 0
637
+ rejectAll: await creation() && current.size !== 0
526
638
  }, documents);
527
639
  }
528
640
  }
529
- const deletion = patch.newPath === "/dev/null" || patch.newEpoch && patch.hunks.every((hunk) => hunk.newCount === 0 && hunk.newStart === 0);
641
+ const deletion = patch.newPath === "/dev/null" || patch.newEpoch && await emptySide("new");
530
642
  if (autoReversed && options.forward) {
531
643
  await documents.release(result);
532
- return { result: current, outcomes: [], reversed, autoReversed, reverseMismatch, deletion: false, skipped: true };
644
+ return { result: current, outcomes: outcomeStore.create(patch), reversed, autoReversed, reverseMismatch, deletion: false, skipped: true };
533
645
  }
534
646
  return { result, outcomes, reversed, autoReversed, reverseMismatch, deletion };
535
647
  }
@@ -613,7 +725,8 @@ async function run(context, budget) {
613
725
  }
614
726
  const documents = new TargetDocuments(budget);
615
727
  const bodies = new PatchBodyStore(documents);
616
- const messages = new PagedStorage2(budget.context, 16, documents.cache);
728
+ const outcomeStore = new OutcomeStore(documents);
729
+ const messages = new PagedStorage3(budget.context, 16, documents.cache);
617
730
  try {
618
731
  const empty = await documents.load({ async *[Symbol.asyncIterator]() {
619
732
  } });
@@ -631,14 +744,14 @@ async function run(context, budget) {
631
744
  const input = options.input === "-" ? await documents.load(budget.stdinSource()) : inputCapabilities?.retainedRead && context.fs.openReadFile ? await documents.read(inputPath) : context.fs.readStream && inputCapabilities?.streamingRead !== false ? await documents.load(budget.streamSource(inputPath)) : await documents.load(targetBytes(await budget.read(inputPath)));
632
745
  const progress = options.atomic ? void 0 : {};
633
746
  const sections = await parsePatchWith(await unwrapStoredPatch(input, budget), budget, options.format, explicit, {
634
- unified: (cursor) => parseUnifiedReader(cursor, budget, true, () => bodies.begin()),
747
+ unified: (cursor) => parseUnifiedReader(cursor, budget, true, () => bodies.begin(), () => bodies.beginHunks()),
635
748
  converted: async (chunks) => {
636
749
  const converted = await documents.load({ async *[Symbol.asyncIterator]() {
637
750
  for await (const chunk of chunks) yield* targetBytes(chunk);
638
751
  } });
639
752
  try {
640
753
  budget.countLines(converted.length);
641
- return await parseUnifiedReader({ input: new StoredPatchInput(converted), index: 0 }, budget, false, () => bodies.begin());
754
+ return await parseUnifiedReader({ input: new StoredPatchInput(converted), index: 0 }, budget, false, () => bodies.begin(), () => bodies.beginHunks());
642
755
  } finally {
643
756
  await documents.release(converted);
644
757
  }
@@ -665,7 +778,7 @@ async function run(context, budget) {
665
778
  if (outputToStdout) return;
666
779
  const path = resolvePath(context.cwd, item.selected);
667
780
  const current = preview.has(path) ? preview.get(path) : await inspect(budget, path) ? await documents.read(path) : void 0;
668
- const applied = await applyContent(item.patch, current ?? empty, current !== void 0, options, budget, documents);
781
+ const applied = await applyContent(item.patch, current ?? empty, current !== void 0, options, budget, documents, outcomeStore);
669
782
  if (current && current !== applied?.result) await documents.release(current);
670
783
  if (!applied) return;
671
784
  const remove = options.ifdef === void 0 && applied.result.size === 0 && (!options.posix && applied.deletion || options.removeEmpty);
@@ -746,16 +859,18 @@ ${sourcePatch.hunks.length} out of ${sourcePatch.hunks.length} hunks ignored
746
859
  await authorizeOutputs([rejectPath2], targets, paths.input, budget);
747
860
  if (backupPaths.has(rejectPath2)) throw new ToolError3("reject path aliases another section's backup");
748
861
  const patch = options.reverse ? reverseStoredPatch(sourcePatch) : sourcePatch;
749
- const outcomes2 = patch.hunks.map((hunk, index) => ({
750
- hunk,
751
- index: index + 1,
752
- failed: true,
753
- misordered: false,
754
- line: hunk.oldStart,
755
- outputOffset: 0,
756
- offset: 0,
757
- fuzz: 0
758
- }));
862
+ const outcomes2 = { async *[Symbol.asyncIterator]() {
863
+ for await (const [index, hunk] of patchHunks(patch)) yield {
864
+ hunk,
865
+ index: index + 1,
866
+ failed: true,
867
+ misordered: false,
868
+ line: hunk.oldStart,
869
+ outputOffset: 0,
870
+ offset: 0,
871
+ fuzz: 0
872
+ };
873
+ } };
759
874
  const reject2 = await documents.load(rejectBytes(sourcePatch, outcomes2, authorizedPatch.oldName, authorizedPatch.newName, authorizedPatch.indexName, options.reverse, budget, options.rejectFormat));
760
875
  const original2 = await documents.read(path);
761
876
  publishing = true;
@@ -781,7 +896,7 @@ ${sourcePatch.hunks.length} out of ${sourcePatch.hunks.length} hunks ignored
781
896
  exitCode = 1;
782
897
  return;
783
898
  }
784
- const applied = await applyContent(sourcePatch, current, exists, options, budget, documents);
899
+ const applied = await applyContent(sourcePatch, current, exists, options, budget, documents, outcomeStore);
785
900
  if (!applied) {
786
901
  if (options.atomic) throw new ToolError3(`patch target does not exist: ${path}`, 1);
787
902
  await status(`No file to patch. Skipping patch ${name}.
@@ -798,15 +913,21 @@ ${sourcePatch.hunks.length} out of ${sourcePatch.hunks.length} hunks ignored
798
913
  exitCode = 1;
799
914
  return;
800
915
  }
801
- const failed = outcomes.filter((outcome) => outcome.failed);
802
- const conflict = failed.length > 0 || deletion && result.size !== 0;
803
- if (options.atomic && conflict) throw new ToolError3(failed.length ? `hunk ${failed[0].index} does not match ${name}` : `deletion patch leaves content: ${name}`, 1);
916
+ let failedCount = 0, firstFailed = 0, mismatch = reverseMismatch;
917
+ for await (const outcome of outcomes) {
918
+ if (outcome.failed) {
919
+ if (!failedCount) firstFailed = outcome.index;
920
+ failedCount++;
921
+ }
922
+ mismatch ||= outcome.failed || outcome.offset !== 0 || outcome.fuzz !== 0;
923
+ }
924
+ const conflict = failedCount > 0 || deletion && result.size !== 0;
925
+ if (options.atomic && conflict) throw new ToolError3(failedCount ? `hunk ${firstFailed} does not match ${name}` : `deletion patch leaves content: ${name}`, 1);
804
926
  if (conflict) exitCode = 1;
805
- const mismatch = reverseMismatch || outcomes.some((outcome) => outcome.failed || outcome.offset !== 0 || outcome.fuzz !== 0);
806
927
  const backup = !options.dryRun && !outputToStdout && (options.alwaysBackup || options.backup && mismatch) && !touched.has(path) ? original ?? empty : void 0;
807
928
  const backupPath = backup === void 0 ? prior?.backupPath : await backupName(path, budget, options);
808
929
  const rejectDestination = rejectName(outputToStdout ? "-" : name, paths);
809
- const rejectPath = !options.dryRun && !options.merge && failed.length && rejectDestination !== void 0 ? resolvePath(context.cwd, rejectDestination) : void 0;
930
+ const rejectPath = !options.dryRun && !options.merge && failedCount && rejectDestination !== void 0 ? resolvePath(context.cwd, rejectDestination) : void 0;
810
931
  const rejected = rejectPath === void 0 ? void 0 : await documents.load(rejectBytes(sourcePatch, outcomes, authorizedPatch.oldName, authorizedPatch.newName, authorizedPatch.indexName, reversed, budget, options.rejectFormat));
811
932
  await authorizeOutputs([outputPath, backupPath, rejectPath], targets, paths.input, budget);
812
933
  if (backupPath !== void 0 && rejectPaths.has(backupPath) || rejectPath !== void 0 && backupPaths.has(rejectPath)) {
@@ -865,7 +986,7 @@ ${headers}--------------------------
865
986
  if (!options.quiet) await appendStatus(`${options.dryRun ? "checking" : "patching"} file ${output === void 0 ? displayName : `${quotePatchName(output, options.quotingStyle)} (read from ${displayName})`}
866
987
  `);
867
988
  if (autoReversed) await appendStatus("Reversed (or previously applied) patch detected! Assuming -R.\n");
868
- for (const outcome of outcomes) {
989
+ for await (const outcome of outcomes) {
869
990
  if (outcome.misordered) await appendStatus("misordered hunks! output would be garbled\n");
870
991
  if (options.quiet) continue;
871
992
  if (outcome.failed && options.merge) await appendStatus(`Hunk #${outcome.index} NOT MERGED at ${outcome.mergeRange?.[0] ?? outcome.line}-${outcome.mergeRange?.[1] ?? outcome.line}.
@@ -875,7 +996,7 @@ ${headers}--------------------------
875
996
  else if (options.verbose || outcome.offset || outcome.fuzz) await appendStatus(`Hunk #${outcome.index} succeeded at ${outcome.line}${outcome.fuzz ? ` with fuzz ${outcome.fuzz}` : ""}${outcome.offset ? ` (offset ${outcome.offset} ${outcome.offset === 1 ? "line" : "lines"})` : ""}.
876
997
  `);
877
998
  }
878
- if (failed.length && !options.merge) await appendStatus(`${failed.length} out of ${outcomes.length} ${outcomes.length === 1 ? "hunk" : "hunks"} FAILED${options.dryRun || rejectPath === void 0 ? "" : ` -- saving rejects to file ${rejectDestination}`}
999
+ if (failedCount && !options.merge) await appendStatus(`${failedCount} out of ${outcomes.length} ${outcomes.length === 1 ? "hunk" : "hunks"} FAILED${options.dryRun || rejectPath === void 0 ? "" : ` -- saving rejects to file ${rejectDestination}`}
879
1000
  `);
880
1001
  if (deletion && result.size !== 0) await appendStatus(`Not deleting file ${name} as content differs from patch
881
1002
  `);
@@ -928,7 +1049,7 @@ ${headers}--------------------------
928
1049
  if (progress?.error) throw progress.error;
929
1050
  return exitCode;
930
1051
  } finally {
931
- await closeDocumentResources2([messages, documents, bodies]);
1052
+ await closeDocumentResources2([messages, documents, bodies, outcomeStore]);
932
1053
  }
933
1054
  }
934
1055
  function patchCommand(options = {}) {
@@ -94,6 +94,7 @@ async function parseStoredXml(source, context, budget, recover, consume) {
94
94
  retainTree: false,
95
95
  storeFrames: true,
96
96
  fragmentContent: true,
97
+ compactDeclaration: true,
97
98
  ...recover ? { recover } : {},
98
99
  ...consume ? { events: (event) => {
99
100
  queued.push(event);