@poe-platform/safe-bash 0.1.535 → 0.1.537

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 (66) hide show
  1. package/dist/safe-bash/chunks/chunk-JWUT4LBW.js +617 -0
  2. package/dist/safe-bash/chunks/chunk-JWUT4LBW.js.map +7 -0
  3. package/dist/safe-bash/chunks/chunk-PY37EOPJ.js +1236 -0
  4. package/dist/safe-bash/chunks/chunk-PY37EOPJ.js.map +7 -0
  5. package/dist/safe-bash/commands/pr/command.d.ts +4 -0
  6. package/dist/safe-bash/commands/pr/command.d.ts.map +1 -0
  7. package/dist/safe-bash/commands/pr/command.js +117 -0
  8. package/dist/safe-bash/commands/pr/command.js.map +1 -0
  9. package/dist/safe-bash/commands/pr/format.d.ts +52 -0
  10. package/dist/safe-bash/commands/pr/format.d.ts.map +1 -0
  11. package/dist/safe-bash/commands/pr/format.js +527 -0
  12. package/dist/safe-bash/commands/pr/format.js.map +1 -0
  13. package/dist/safe-bash/commands/pr/index.browser.js +13 -0
  14. package/dist/safe-bash/commands/pr/index.browser.js.map +7 -0
  15. package/dist/safe-bash/commands/pr/index.d.ts +7 -0
  16. package/dist/safe-bash/commands/pr/index.d.ts.map +1 -0
  17. package/dist/safe-bash/commands/pr/index.js +13 -0
  18. package/dist/safe-bash/commands/pr/index.js.map +1 -0
  19. package/dist/safe-bash/commands/pr/internal.d.ts +61 -0
  20. package/dist/safe-bash/commands/pr/internal.d.ts.map +1 -0
  21. package/dist/safe-bash/commands/pr/internal.js +181 -0
  22. package/dist/safe-bash/commands/pr/internal.js.map +1 -0
  23. package/dist/safe-bash/commands/pr/io.d.ts +37 -0
  24. package/dist/safe-bash/commands/pr/io.d.ts.map +1 -0
  25. package/dist/safe-bash/commands/pr/io.js +210 -0
  26. package/dist/safe-bash/commands/pr/io.js.map +1 -0
  27. package/dist/safe-bash/commands/pr/options.d.ts +36 -0
  28. package/dist/safe-bash/commands/pr/options.d.ts.map +1 -0
  29. package/dist/safe-bash/commands/pr/options.js +250 -0
  30. package/dist/safe-bash/commands/pr/options.js.map +1 -0
  31. package/dist/safe-bash/commands/tsort/command.d.ts +4 -0
  32. package/dist/safe-bash/commands/tsort/command.d.ts.map +1 -0
  33. package/dist/safe-bash/commands/tsort/command.js +72 -0
  34. package/dist/safe-bash/commands/tsort/command.js.map +1 -0
  35. package/dist/safe-bash/commands/tsort/graph.d.ts +3 -0
  36. package/dist/safe-bash/commands/tsort/graph.d.ts.map +1 -0
  37. package/dist/safe-bash/commands/tsort/graph.js +183 -0
  38. package/dist/safe-bash/commands/tsort/graph.js.map +1 -0
  39. package/dist/safe-bash/commands/tsort/index.browser.js +13 -0
  40. package/dist/safe-bash/commands/tsort/index.browser.js.map +7 -0
  41. package/dist/safe-bash/commands/tsort/index.d.ts +7 -0
  42. package/dist/safe-bash/commands/tsort/index.d.ts.map +1 -0
  43. package/dist/safe-bash/commands/tsort/index.js +13 -0
  44. package/dist/safe-bash/commands/tsort/index.js.map +1 -0
  45. package/dist/safe-bash/commands/tsort/internal.d.ts +50 -0
  46. package/dist/safe-bash/commands/tsort/internal.d.ts.map +1 -0
  47. package/dist/safe-bash/commands/tsort/internal.js +176 -0
  48. package/dist/safe-bash/commands/tsort/internal.js.map +1 -0
  49. package/dist/safe-bash/commands/tsort/io.d.ts +29 -0
  50. package/dist/safe-bash/commands/tsort/io.d.ts.map +1 -0
  51. package/dist/safe-bash/commands/tsort/io.js +192 -0
  52. package/dist/safe-bash/commands/tsort/io.js.map +1 -0
  53. package/dist/safe-bash/core.browser.js +46 -5
  54. package/dist/safe-bash/core.browser.js.map +3 -3
  55. package/dist/safe-bash/core.d.ts +2 -0
  56. package/dist/safe-bash/core.d.ts.map +1 -1
  57. package/dist/safe-bash/core.js +2 -0
  58. package/dist/safe-bash/core.js.map +1 -1
  59. package/dist/safe-bash/plugins/composition.d.ts +4 -0
  60. package/dist/safe-bash/plugins/composition.d.ts.map +1 -1
  61. package/dist/safe-bash/plugins/composition.js +7 -1
  62. package/dist/safe-bash/plugins/composition.js.map +1 -1
  63. package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
  64. package/dist/safe-bash/shell/runtime.js +28 -3
  65. package/dist/safe-bash/shell/runtime.js.map +1 -1
  66. package/package.json +14 -2
@@ -0,0 +1,617 @@
1
+ import {
2
+ createOutputOperation
3
+ } from "./chunk-PPVCI2F2.js";
4
+ import {
5
+ FsError,
6
+ PublicDiagnostic,
7
+ getCommandArguments,
8
+ init_platform,
9
+ resolvePath,
10
+ shellValueByteLength,
11
+ shellValueBytes,
12
+ yieldTurn
13
+ } from "./chunk-L2GZSOSJ.js";
14
+
15
+ // packages/safe-bash/src/commands/tsort/index.ts
16
+ init_platform();
17
+
18
+ // packages/safe-bash/src/commands/tsort/command.ts
19
+ init_platform();
20
+
21
+ // packages/safe-bash/src/commands/tsort/internal.ts
22
+ init_platform();
23
+ function settings(options) {
24
+ const limits = {
25
+ maxArguments: 4096,
26
+ maxArgumentBytes: 65536,
27
+ maxInputBytes: 33554432,
28
+ maxTokenBytes: 1048576,
29
+ maxTokens: 2097152,
30
+ maxNodes: 131072,
31
+ maxEdges: 1048576,
32
+ maxBufferedBytes: 33554432,
33
+ maxOutputBytes: 67108864,
34
+ maxDiagnosticBytes: 65536,
35
+ maxWork: 134217728,
36
+ maxEmptyChunks: 4096,
37
+ ...options.limits
38
+ };
39
+ for (const [name, value] of Object.entries(limits)) {
40
+ if (!Number.isSafeInteger(value) || value < 1) throw new RangeError(`Invalid tsort limit: ${name}`);
41
+ }
42
+ return Object.freeze(limits);
43
+ }
44
+ var TsortError = class extends PublicDiagnostic {
45
+ constructor(message, usage = false) {
46
+ super(message);
47
+ this.usage = usage;
48
+ }
49
+ usage;
50
+ };
51
+ function raw(value) {
52
+ let result = "";
53
+ for (let offset = 0; offset < value.length; offset += 4096) result += String.fromCharCode(...value.subarray(offset, offset + 4096));
54
+ return result;
55
+ }
56
+ function bytes(value) {
57
+ return Uint8Array.from(value, (character) => character.charCodeAt(0));
58
+ }
59
+ function pathText(value) {
60
+ try {
61
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes(value));
62
+ } catch {
63
+ throw new TsortError("filesystem paths must be valid UTF-8");
64
+ }
65
+ }
66
+ function quote(value) {
67
+ const escapes = { "\x07": "\\a", "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", " ": "\\t", "\v": "\\v", "\\": "\\\\", "'": "\\'" };
68
+ let result = "'";
69
+ for (const character of value) {
70
+ const code = character.charCodeAt(0);
71
+ result += escapes[character] ?? (code >= 32 && code < 127 ? character : `\\${code.toString(8).padStart(3, "0")}`);
72
+ }
73
+ return `${result}'`;
74
+ }
75
+ function fileQuote(value) {
76
+ let safe = value.length > 0;
77
+ let escaped = false;
78
+ for (const character of value) {
79
+ const code = character.charCodeAt(0);
80
+ if (!(character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character >= "0" && character <= "9" || "_./-".includes(character))) safe = false;
81
+ if (code < 32 || code >= 127) escaped = true;
82
+ }
83
+ if (safe) return value;
84
+ if (!escaped) {
85
+ if (value.includes("'") && !["$", "`", "\\", '"'].some((character) => value.includes(character))) return `"${value}"`;
86
+ return `'${value.split("'").join("'\\''")}'`;
87
+ }
88
+ const escapes = { "\x07": "\\a", "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", " ": "\\t", "\v": "\\v" };
89
+ let result = "'", inEscape = false;
90
+ for (const character of value) {
91
+ const code = character.charCodeAt(0);
92
+ if (code < 32 || code >= 127) {
93
+ if (!inEscape) {
94
+ result += "'$'";
95
+ inEscape = true;
96
+ }
97
+ result += escapes[character] ?? `\\${code.toString(8).padStart(3, "0")}`;
98
+ } else {
99
+ if (inEscape) {
100
+ result += "''";
101
+ inEscape = false;
102
+ }
103
+ result += character === "'" ? "'\\''" : character;
104
+ }
105
+ }
106
+ return `${result}'`;
107
+ }
108
+ var Budget = class {
109
+ constructor(context, limits, signal) {
110
+ this.context = context;
111
+ this.limits = limits;
112
+ this.signal = signal;
113
+ }
114
+ context;
115
+ limits;
116
+ signal;
117
+ work = 0;
118
+ checkpoint = 0;
119
+ retained = 0;
120
+ input = 0;
121
+ output = 0;
122
+ diagnostics = 0;
123
+ check(value, maximum, label) {
124
+ if (!Number.isSafeInteger(value) || value < 0 || value > maximum) throw new TsortError(`${label} limit exceeded`);
125
+ }
126
+ charge(amount = 1) {
127
+ this.signal.throwIfAborted();
128
+ this.check(this.work + amount, this.limits.maxWork, "work");
129
+ this.work += amount;
130
+ }
131
+ async checkpointWork() {
132
+ this.signal.throwIfAborted();
133
+ if (this.work - this.checkpoint >= 4096) {
134
+ this.checkpoint = this.work;
135
+ await yieldTurn(this.signal);
136
+ }
137
+ }
138
+ retain(amount) {
139
+ this.check(this.retained + amount, this.limits.maxBufferedBytes, "buffered bytes");
140
+ this.retained += amount;
141
+ }
142
+ inputBytes(amount) {
143
+ this.check(this.input + amount, this.limits.maxInputBytes, "input bytes");
144
+ this.input += amount;
145
+ }
146
+ emitted(amount, diagnostic) {
147
+ if (diagnostic) {
148
+ this.check(this.diagnostics + amount, this.limits.maxDiagnosticBytes, "diagnostic bytes");
149
+ this.diagnostics += amount;
150
+ } else {
151
+ this.check(this.output + amount, this.limits.maxOutputBytes, "output bytes");
152
+ this.output += amount;
153
+ this.charge(amount);
154
+ }
155
+ }
156
+ arguments() {
157
+ this.check(this.context.args.length, this.limits.maxArguments, "argument count");
158
+ let total = 0;
159
+ for (const argument of this.context.args) {
160
+ total += argument.length;
161
+ this.check(total, this.limits.maxArgumentBytes, "argument bytes");
162
+ for (let offset = 0; offset < argument.length; offset++) {
163
+ const unit = argument.charCodeAt(offset);
164
+ if (unit >= 55296 && unit <= 56319) {
165
+ const next = argument.charCodeAt(++offset);
166
+ if (!(next >= 56320 && next <= 57343)) throw new TsortError("arguments must contain well-formed Unicode");
167
+ } else if (unit >= 56320 && unit <= 57343) throw new TsortError("arguments must contain well-formed Unicode");
168
+ }
169
+ }
170
+ total = 0;
171
+ const values = this.context.argumentValues === void 0 ? this.context.args : getCommandArguments(this.context).values;
172
+ for (const argument of values) {
173
+ total += shellValueByteLength(argument);
174
+ this.check(total, this.limits.maxArgumentBytes, "argument bytes");
175
+ }
176
+ this.charge(total);
177
+ this.retain(total * 8 + this.context.args.length * 64 + 128);
178
+ total = 0;
179
+ return getCommandArguments(this.context).values.map((argument) => {
180
+ total += shellValueByteLength(argument);
181
+ this.check(total, this.limits.maxArgumentBytes, "argument bytes");
182
+ this.charge(shellValueByteLength(argument));
183
+ const value = shellValueBytes(argument);
184
+ if (value.includes(0)) throw new TsortError("NUL is not supported in arguments");
185
+ return raw(value);
186
+ });
187
+ }
188
+ };
189
+
190
+ // packages/safe-bash/src/commands/tsort/io.ts
191
+ init_platform();
192
+ var Lifecycle = class {
193
+ constructor(budget, output) {
194
+ this.budget = budget;
195
+ output.registerCleanup(() => this.close());
196
+ }
197
+ budget;
198
+ pending = /* @__PURE__ */ new Set();
199
+ cleanups = [];
200
+ closing;
201
+ cleanup(action) {
202
+ this.assertOpen();
203
+ this.cleanups.push(action);
204
+ }
205
+ assertOpen() {
206
+ this.budget.signal.throwIfAborted();
207
+ if (this.closing) throw new TsortError("command is closed");
208
+ }
209
+ async operation(action, diagnostic = false) {
210
+ this.assertOpen();
211
+ if (!diagnostic) this.budget.charge();
212
+ const pending = Promise.resolve().then(() => {
213
+ this.assertOpen();
214
+ return action();
215
+ });
216
+ this.pending.add(pending);
217
+ try {
218
+ const value = await pending;
219
+ this.assertOpen();
220
+ return value;
221
+ } finally {
222
+ this.pending.delete(pending);
223
+ }
224
+ }
225
+ close() {
226
+ return this.closing ??= Promise.resolve().then(async () => {
227
+ while (this.pending.size) await Promise.allSettled([...this.pending]);
228
+ const failures = [];
229
+ for (const cleanup of this.cleanups) {
230
+ try {
231
+ await cleanup();
232
+ } catch (error) {
233
+ failures.push(error);
234
+ }
235
+ }
236
+ if (failures.length === 1) throw failures[0];
237
+ if (failures.length > 1) throw new AggregateError(failures, "tsort cleanup failed");
238
+ });
239
+ }
240
+ async write(value, diagnostic = false) {
241
+ this.budget.emitted(value.length, diagnostic);
242
+ await this.operation(async () => {
243
+ if (!diagnostic) this.budget.retain(value.length * 3);
244
+ try {
245
+ const sink = diagnostic ? this.budget.context.stderr : this.budget.context.stdout;
246
+ await (sink.ownedOutput ?? sink).write(bytes(value));
247
+ } finally {
248
+ if (!diagnostic) this.budget.retain(-value.length * 3);
249
+ }
250
+ }, diagnostic);
251
+ }
252
+ };
253
+ var Reader = class {
254
+ constructor(name, lifecycle) {
255
+ this.name = name;
256
+ this.lifecycle = lifecycle;
257
+ lifecycle.cleanup(async () => {
258
+ try {
259
+ if (!this.ended) await this.iterator?.return?.();
260
+ } finally {
261
+ this.iterator = void 0;
262
+ this.releaseSnapshot();
263
+ lifecycle.budget.retain(-this.chunk.length);
264
+ this.chunk = new Uint8Array();
265
+ }
266
+ });
267
+ }
268
+ name;
269
+ lifecycle;
270
+ iterator;
271
+ chunk = new Uint8Array();
272
+ offset = 0;
273
+ ended = false;
274
+ empties = 0;
275
+ snapshotBytes = 0;
276
+ releaseSnapshot = () => {
277
+ this.lifecycle.budget.retain(-this.snapshotBytes);
278
+ this.snapshotBytes = 0;
279
+ };
280
+ async open() {
281
+ const { budget } = this.lifecycle;
282
+ const { fs, stdin } = budget.context;
283
+ try {
284
+ await this.lifecycle.operation(async () => {
285
+ let source;
286
+ if (this.name === "-") source = stdin;
287
+ else {
288
+ const path = resolvePath(budget.context.cwd, pathText(this.name));
289
+ const stat = await fs.stat(path, { signal: budget.signal });
290
+ budget.signal.throwIfAborted();
291
+ if (stat.type === "directory") {
292
+ this.ended = true;
293
+ return;
294
+ }
295
+ if (stat.type !== "file" && stat.type !== "character") throw new FsError("ENOTSUP", { path });
296
+ const capabilities = await fs.capabilitiesFor?.(path, { signal: budget.signal }) ?? fs.capabilities;
297
+ budget.signal.throwIfAborted();
298
+ if (fs.readStream && capabilities.streamingRead !== false) source = fs.readStream(path, { signal: budget.signal, chunkSize: 16384 });
299
+ else {
300
+ const maximum = Math.min(budget.limits.maxInputBytes, Math.floor(budget.limits.maxBufferedBytes / 2));
301
+ budget.check(stat.size, maximum, "buffered input bytes");
302
+ budget.retain(maximum);
303
+ this.snapshotBytes = maximum;
304
+ const content = await fs.readFile(path, { signal: budget.signal, maxBytes: maximum });
305
+ if (!(content instanceof Uint8Array)) throw new TypeError("tsort input requires bytes");
306
+ budget.check(content.length, maximum, "buffered input bytes");
307
+ budget.retain(content.length - maximum);
308
+ this.snapshotBytes = content.length;
309
+ const { releaseSnapshot } = this;
310
+ source = { async *[Symbol.asyncIterator]() {
311
+ try {
312
+ yield content;
313
+ } finally {
314
+ releaseSnapshot();
315
+ }
316
+ } };
317
+ }
318
+ }
319
+ this.iterator = source[Symbol.asyncIterator]();
320
+ });
321
+ } catch (error) {
322
+ if (error instanceof FsError) throw new TsortError(`${fileQuote(this.name)}: ${fsDetail(error)}`);
323
+ throw error;
324
+ }
325
+ }
326
+ async get() {
327
+ const { budget } = this.lifecycle;
328
+ budget.charge();
329
+ await budget.checkpointWork();
330
+ while (this.offset === this.chunk.length) {
331
+ if (this.ended) return -1;
332
+ let next;
333
+ try {
334
+ next = await this.lifecycle.operation(() => this.iterator.next());
335
+ } catch (error) {
336
+ if (error instanceof FsError) throw new TsortError(`${fileQuote(this.name)}: ${fsDetail(error)}`);
337
+ throw error;
338
+ }
339
+ budget.retain(-this.chunk.length);
340
+ this.chunk = new Uint8Array();
341
+ this.offset = 0;
342
+ if (next.done) {
343
+ this.ended = true;
344
+ this.iterator = void 0;
345
+ return -1;
346
+ }
347
+ if (!(next.value instanceof Uint8Array)) throw new TypeError("tsort input requires bytes");
348
+ budget.inputBytes(next.value.length);
349
+ budget.charge(next.value.length);
350
+ budget.retain(next.value.length);
351
+ this.chunk = Uint8Array.from(next.value);
352
+ if (!this.chunk.length) budget.check(++this.empties, budget.limits.maxEmptyChunks, "empty input chunks");
353
+ }
354
+ return this.chunk[this.offset++];
355
+ }
356
+ };
357
+ function fsDetail(error) {
358
+ const details = {
359
+ EACCES: "Permission denied",
360
+ EPERM: "Operation not permitted",
361
+ ENOENT: "No such file or directory",
362
+ EISDIR: "Is a directory",
363
+ ENOTDIR: "Not a directory",
364
+ EIO: "Input/output error",
365
+ ELOOP: "Too many levels of symbolic links",
366
+ ENAMETOOLONG: "File name too long",
367
+ ENOTSUP: "Operation not supported"
368
+ };
369
+ return details[error.code] ?? error.message;
370
+ }
371
+
372
+ // packages/safe-bash/src/commands/tsort/graph.ts
373
+ init_platform();
374
+ async function sort(reader, lifecycle) {
375
+ const { budget } = lifecycle;
376
+ const nodes = /* @__PURE__ */ new Map();
377
+ let tokens = 0, edges = 0, length = 0, nameLength = 0;
378
+ let nul = false;
379
+ let token = new Uint8Array();
380
+ let predecessor;
381
+ const admitToken = () => {
382
+ budget.check(++tokens, budget.limits.maxTokens, "tokens");
383
+ budget.charge(nameLength + 1);
384
+ budget.retain(nameLength * 4);
385
+ const name = raw(token.subarray(0, nameLength));
386
+ let node = nodes.get(name);
387
+ if (!node) {
388
+ budget.check(nodes.size + 1, budget.limits.maxNodes, "nodes");
389
+ budget.retain(160);
390
+ node = { name, count: 0, printed: false, top: void 0, link: void 0 };
391
+ nodes.set(name, node);
392
+ } else budget.retain(-nameLength * 4);
393
+ if (!predecessor) predecessor = node;
394
+ else {
395
+ if (predecessor !== node) {
396
+ budget.check(++edges, budget.limits.maxEdges, "edges");
397
+ budget.retain(48);
398
+ predecessor.top = { target: node, next: predecessor.top };
399
+ node.count++;
400
+ }
401
+ predecessor = void 0;
402
+ }
403
+ length = 0;
404
+ nameLength = 0;
405
+ nul = false;
406
+ };
407
+ for (; ; ) {
408
+ const value = await reader.get();
409
+ if (value < 0 || value === 32 || value === 9 || value === 10) {
410
+ if (length) admitToken();
411
+ if (value < 0) break;
412
+ } else {
413
+ budget.check(++length, budget.limits.maxTokenBytes, "token bytes");
414
+ if (value === 0) nul = true;
415
+ if (!nul) {
416
+ if (nameLength === token.length) {
417
+ const capacity = Math.min(budget.limits.maxTokenBytes, Math.max(64, token.length * 2));
418
+ budget.retain(capacity);
419
+ budget.charge(token.length);
420
+ const grown = new Uint8Array(capacity);
421
+ grown.set(token);
422
+ budget.retain(-token.length);
423
+ token = grown;
424
+ }
425
+ token[nameLength++] = value;
426
+ }
427
+ }
428
+ }
429
+ budget.retain(-token.length);
430
+ token = new Uint8Array();
431
+ if (predecessor) throw new TsortError(`${fileQuote(reader.name)}: input contains an odd number of tokens`);
432
+ budget.retain(nodes.size * 16);
433
+ let ordered = [...nodes.values()];
434
+ let scratch = new Array(ordered.length);
435
+ for (let width = 1; width < ordered.length; width *= 2) {
436
+ for (let start = 0; start < ordered.length; start += width * 2) {
437
+ const middle = Math.min(start + width, ordered.length), end = Math.min(start + width * 2, ordered.length);
438
+ let left = start, right = middle;
439
+ for (let offset = start; offset < end; offset++) {
440
+ budget.charge();
441
+ let useLeft = right === end;
442
+ if (left < middle && right < end) {
443
+ budget.charge(Math.min(ordered[left].name.length, ordered[right].name.length) + 1);
444
+ useLeft = ordered[left].name < ordered[right].name;
445
+ }
446
+ scratch[offset] = left < middle && useLeft ? ordered[left++] : ordered[right++];
447
+ await budget.checkpointWork();
448
+ }
449
+ }
450
+ [ordered, scratch] = [scratch, ordered];
451
+ }
452
+ let remaining = ordered.length, status = 0;
453
+ while (remaining) {
454
+ let head, tail;
455
+ for (const node of ordered) {
456
+ budget.charge();
457
+ if (!node.printed && !node.count) {
458
+ if (tail) tail.link = node;
459
+ else head = node;
460
+ tail = node;
461
+ node.link = void 0;
462
+ }
463
+ await budget.checkpointWork();
464
+ }
465
+ while (head) {
466
+ const node = head;
467
+ budget.check(node.name.length + 1, budget.limits.maxOutputBytes, "output bytes");
468
+ await lifecycle.write(`${node.name}
469
+ `);
470
+ node.printed = true;
471
+ remaining--;
472
+ for (let edge = node.top; edge; edge = edge.next) {
473
+ budget.charge();
474
+ if (!--edge.target.count) {
475
+ tail.link = edge.target;
476
+ tail = edge.target;
477
+ tail.link = void 0;
478
+ }
479
+ await budget.checkpointWork();
480
+ }
481
+ head = node.link;
482
+ node.link = void 0;
483
+ }
484
+ if (!remaining) break;
485
+ status = 1;
486
+ await lifecycle.write(`tsort: ${fileQuote(reader.name)}: input contains a loop:
487
+ `, true);
488
+ let loop;
489
+ do {
490
+ let found = false;
491
+ for (const node of ordered) {
492
+ budget.charge();
493
+ await budget.checkpointWork();
494
+ if (!node.count) continue;
495
+ if (!loop) {
496
+ loop = node;
497
+ continue;
498
+ }
499
+ let previous;
500
+ for (let edge = node.top; edge; edge = edge.next) {
501
+ budget.charge();
502
+ await budget.checkpointWork();
503
+ if (edge.target === loop) {
504
+ if (node.link) {
505
+ while (loop) {
506
+ budget.charge();
507
+ const next = loop.link;
508
+ await lifecycle.write(`tsort: ${loop.name}
509
+ `, true);
510
+ if (loop === node) {
511
+ edge.target.count--;
512
+ if (previous) previous.next = edge.next;
513
+ else node.top = edge.next;
514
+ break;
515
+ }
516
+ loop.link = void 0;
517
+ loop = next;
518
+ }
519
+ while (loop) {
520
+ budget.charge();
521
+ const next = loop.link;
522
+ loop.link = void 0;
523
+ loop = next;
524
+ await budget.checkpointWork();
525
+ }
526
+ found = true;
527
+ } else {
528
+ node.link = loop;
529
+ loop = node;
530
+ }
531
+ break;
532
+ }
533
+ previous = edge;
534
+ }
535
+ if (found) break;
536
+ }
537
+ } while (loop);
538
+ }
539
+ return status;
540
+ }
541
+
542
+ // packages/safe-bash/src/commands/tsort/command.ts
543
+ function createTsortCommand(options = {}) {
544
+ const limits = settings(options);
545
+ return { name: "tsort", description: "Topologically sort pairs of byte-valued node names", async execute(context) {
546
+ const output = createOutputOperation(context, context.stdout);
547
+ const budget = new Budget(context, limits, output.signal);
548
+ let lifecycle;
549
+ let failure;
550
+ let primary;
551
+ let exitCode = 0;
552
+ try {
553
+ lifecycle = new Lifecycle(budget, output);
554
+ const args = budget.arguments();
555
+ const lone = args.length === 1 ? args[0] : "";
556
+ if (lone.length > 2 && ("--help".startsWith(lone) || "--version".startsWith(lone))) {
557
+ await lifecycle.write("--help".startsWith(lone) ? "Usage: tsort [OPTION] [FILE]\nWrite a topological ordering of whitespace-separated node pairs.\nWith no FILE, or FILE -, read standard input.\nOptions: --help --version\n" : "tsort (virtual-bash)\n");
558
+ } else {
559
+ let optionsEnded = false;
560
+ const files = [];
561
+ for (const argument of args) {
562
+ if (!optionsEnded && argument === "--") {
563
+ optionsEnded = true;
564
+ continue;
565
+ }
566
+ if (!optionsEnded && argument.startsWith("--")) throw new TsortError(`unrecognized option '${argument}'`, true);
567
+ if (!optionsEnded && argument.length > 1 && argument.startsWith("-")) throw new TsortError(`invalid option -- '${argument[1]}'`, true);
568
+ files.push(argument);
569
+ if (context.env.POSIXLY_CORRECT !== void 0) optionsEnded = true;
570
+ }
571
+ if (files.length > 1) throw new TsortError(`extra operand ${quote(files[1])}`, true);
572
+ const reader = new Reader(files[0] ?? "-", lifecycle);
573
+ await reader.open();
574
+ exitCode = await sort(reader, lifecycle);
575
+ }
576
+ } catch (error) {
577
+ primary = { reason: error };
578
+ if (error instanceof TsortError && !output.signal.aborted && lifecycle) {
579
+ exitCode = 1;
580
+ try {
581
+ await lifecycle.write(`tsort: ${error.message}
582
+ ${error.usage ? "Try 'tsort --help' for more information.\n" : ""}`, true);
583
+ } catch (reporting) {
584
+ failure = { reason: new AggregateError([error, reporting], "tsort failure reporting failed") };
585
+ }
586
+ } else failure = { reason: error };
587
+ }
588
+ try {
589
+ await output.close();
590
+ } catch (cleanup) {
591
+ const previous = failure ?? primary;
592
+ failure = { reason: previous ? new AggregateError([previous.reason, cleanup], "tsort execution and cleanup failed") : cleanup };
593
+ }
594
+ context.signal.throwIfAborted();
595
+ output.signal.throwIfAborted();
596
+ if (failure) throw failure.reason;
597
+ return { exitCode };
598
+ } };
599
+ }
600
+
601
+ // packages/safe-bash/src/commands/tsort/index.ts
602
+ function createTsortCommands(options = {}) {
603
+ return [createTsortCommand(options)];
604
+ }
605
+ function tsortCommands(options = {}) {
606
+ const commands = createTsortCommands(options);
607
+ return { name: "tsort-commands", setup(host) {
608
+ for (const command of commands) host.commands.register(command, { replace: options.replace ?? false });
609
+ } };
610
+ }
611
+
612
+ export {
613
+ createTsortCommand,
614
+ createTsortCommands,
615
+ tsortCommands
616
+ };
617
+ //# sourceMappingURL=chunk-JWUT4LBW.js.map