@brainervirus/workit-pi 8.12.2 → 8.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worker.js +50 -2
- package/dist/workit.js +1367 -209
- package/package.json +1 -1
- package/skills/workit-ship/SKILL.md +20 -20
- package/skills/workit-ship/references/release.md +26 -0
package/dist/workit.js
CHANGED
|
@@ -13020,6 +13020,15 @@ var repoBranchPreset = (workspaceRoot) => {
|
|
|
13020
13020
|
const detected = detectBranchPolicy(workspaceRoot);
|
|
13021
13021
|
return detected.developBranch || detected.allowed.length ? detected.preset : null;
|
|
13022
13022
|
};
|
|
13023
|
+
var releaseTagPrefixOf = (workspaceRoot, policyPrefix) => {
|
|
13024
|
+
if (typeof policyPrefix === "string")
|
|
13025
|
+
return policyPrefix.trim();
|
|
13026
|
+
const r = spawnSync5("git", ["config", "--get", "gitflow.prefix.versiontag"], {
|
|
13027
|
+
cwd: workspaceRoot,
|
|
13028
|
+
encoding: "utf8"
|
|
13029
|
+
});
|
|
13030
|
+
return r.status === 0 ? (r.stdout ?? "").trim() : "v";
|
|
13031
|
+
};
|
|
13023
13032
|
|
|
13024
13033
|
// packages/workit-core/src/core/workspaces.ts
|
|
13025
13034
|
var nonBlank = string2().refine((value) => value.trim().length > 0, "must not be blank");
|
|
@@ -15795,11 +15804,11 @@ what and whether, the CLI does how and records what it observed.
|
|
|
15795
15804
|
Native host allow/ask/deny, sandbox and org rules stay authoritative. Never
|
|
15796
15805
|
switch paths to evade a denial, never claim enforcement a host cannot provide,
|
|
15797
15806
|
and never fabricate an approval or verdict. A question answer is not
|
|
15798
|
-
host permission, and imported decisions or handoffs
|
|
15807
|
+
host permission, and imported decisions or handoffs grant no authority.
|
|
15799
15808
|
|
|
15800
15809
|
Autonomy contract:
|
|
15801
15810
|
- Continue to the requested endpoint (commit, push, PR, green CI, verified,
|
|
15802
|
-
merged) without asking "continue?", running checks and repairs
|
|
15811
|
+
merged) without asking "continue?", running checks and repairs.
|
|
15803
15812
|
Stop only for a new consequential choice, a host denial, a conflicting edit
|
|
15804
15813
|
or an unresolved blocker; report open gaps and uncertain workers.
|
|
15805
15814
|
- No endpoint named: stop at a local commit on a policy-compliant branch and
|
|
@@ -15809,7 +15818,8 @@ Autonomy contract:
|
|
|
15809
15818
|
never merging; \`merged\` also lands it with \`workit pr merge\`.
|
|
15810
15819
|
Merge and release need a workspace grant only the user raises from their
|
|
15811
15820
|
own terminal (a blocked verb names how); never edit workspaces.json or route
|
|
15812
|
-
around
|
|
15821
|
+
around grant_required. Release: \`workit release start <v>\`, commits,
|
|
15822
|
+
\`finish\`; \`publish\` if asked.
|
|
15813
15823
|
- Ask only for a product or preference choice, or for authority you lack, with
|
|
15814
15824
|
your recommended answer. Facts are yours: read, run or prototype.
|
|
15815
15825
|
- Label claims measured (run and seen this session), inferred, or guess.
|
|
@@ -15824,22 +15834,22 @@ Autonomy contract:
|
|
|
15824
15834
|
reconcile every requested item and observe it (\`workit verify-delivery\`).
|
|
15825
15835
|
|
|
15826
15836
|
CLI first: if a step has one right answer, use the \`workit\` verb instead of
|
|
15827
|
-
hand-running git, gh or glab (\`workit git|pr|ci|check\`;
|
|
15828
|
-
|
|
15837
|
+
hand-running git, gh or glab (\`workit git|pr|ci|check|help\`;
|
|
15838
|
+
else \`npx -y @brainervirus/workit-cli\`).
|
|
15829
15839
|
Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
|
|
15830
15840
|
an amend.
|
|
15831
15841
|
The task families (task, policy, evidence, finding, decision, worker, state)
|
|
15832
15842
|
are optional continuity for tracked work; each branch has one implicit task,
|
|
15833
|
-
and a solo edit needs no task. A decision
|
|
15834
|
-
|
|
15843
|
+
and a solo edit needs no task. A decision records a user choice; it never
|
|
15844
|
+
authorizes an effect. Judge work once with
|
|
15835
15845
|
\`workit policy assess --judge risk= behavior= product-choice= plan=\`.
|
|
15836
|
-
Across repositories, bind
|
|
15837
|
-
|
|
15838
|
-
external effect before
|
|
15846
|
+
Across repositories, bind items to checkout, branch and endpoint, resolve
|
|
15847
|
+
competing targets before a mutation, and reconcile an uncertain
|
|
15848
|
+
external effect before a retry.
|
|
15839
15849
|
|
|
15840
15850
|
Mid-task: never silently drop or resume an objective (workit-continue).
|
|
15841
15851
|
|
|
15842
|
-
Skills: load the skill, never act from memory
|
|
15852
|
+
Skills: load the skill, never act from memory (aliases /wk-<name>).
|
|
15843
15853
|
- brainstorm, plan, spec, grill, should we: workit-shape
|
|
15844
15854
|
- implement, build, add a feature: workit-implement
|
|
15845
15855
|
- review, blast radius: workit-review
|
|
@@ -16298,7 +16308,76 @@ var writeSessionMarker = (file, marker) => {
|
|
|
16298
16308
|
};
|
|
16299
16309
|
|
|
16300
16310
|
// packages/workit-core/src/hooks/shell-words.ts
|
|
16301
|
-
|
|
16311
|
+
class ShellAnalysisError extends Error {
|
|
16312
|
+
}
|
|
16313
|
+
var MAX_NESTING = 64;
|
|
16314
|
+
var OPEN = "";
|
|
16315
|
+
var COMMA = "";
|
|
16316
|
+
var CLOSE = "";
|
|
16317
|
+
var MARKERS = /[\uE000-\uE002]/u;
|
|
16318
|
+
var literal2 = (word) => word.replaceAll(OPEN, "{").replaceAll(COMMA, ",").replaceAll(CLOSE, "}");
|
|
16319
|
+
var BRACE_LIMIT = 64;
|
|
16320
|
+
var BRACE_PENDING = 512;
|
|
16321
|
+
var BRACE_DEPTH = 16;
|
|
16322
|
+
var braceGroup = (word) => {
|
|
16323
|
+
for (let start = 0;start < word.length; start++) {
|
|
16324
|
+
if (word[start] !== OPEN)
|
|
16325
|
+
continue;
|
|
16326
|
+
let depth = 0;
|
|
16327
|
+
let end = start;
|
|
16328
|
+
const commas = [];
|
|
16329
|
+
for (;end < word.length; end++) {
|
|
16330
|
+
if (word[end] === OPEN)
|
|
16331
|
+
depth++;
|
|
16332
|
+
else if (word[end] === CLOSE && --depth === 0)
|
|
16333
|
+
break;
|
|
16334
|
+
else if (word[end] === COMMA && depth === 1)
|
|
16335
|
+
commas.push(end);
|
|
16336
|
+
}
|
|
16337
|
+
if (end < word.length && commas.length)
|
|
16338
|
+
return { start, end, commas };
|
|
16339
|
+
}
|
|
16340
|
+
return null;
|
|
16341
|
+
};
|
|
16342
|
+
var expandBraces = (word) => {
|
|
16343
|
+
let depth = 0;
|
|
16344
|
+
for (const char of word) {
|
|
16345
|
+
if (char === OPEN && ++depth > BRACE_DEPTH)
|
|
16346
|
+
return [literal2(word)];
|
|
16347
|
+
if (char === CLOSE && depth > 0)
|
|
16348
|
+
depth--;
|
|
16349
|
+
}
|
|
16350
|
+
const done = new Set;
|
|
16351
|
+
const queue = [word];
|
|
16352
|
+
const queued = new Set(queue);
|
|
16353
|
+
for (let at = 0;at < queue.length; at++) {
|
|
16354
|
+
const current = queue[at];
|
|
16355
|
+
const group = braceGroup(current);
|
|
16356
|
+
if (!group) {
|
|
16357
|
+
const text = literal2(current);
|
|
16358
|
+
if (text)
|
|
16359
|
+
done.add(text);
|
|
16360
|
+
if (done.size > BRACE_LIMIT)
|
|
16361
|
+
return [literal2(word)];
|
|
16362
|
+
continue;
|
|
16363
|
+
}
|
|
16364
|
+
const pre = current.slice(0, group.start);
|
|
16365
|
+
const post = current.slice(group.end + 1);
|
|
16366
|
+
let from = group.start + 1;
|
|
16367
|
+
for (const comma of [...group.commas, group.end]) {
|
|
16368
|
+
const next = pre + current.slice(from, comma) + post;
|
|
16369
|
+
from = comma + 1;
|
|
16370
|
+
if (queued.has(next))
|
|
16371
|
+
continue;
|
|
16372
|
+
queued.add(next);
|
|
16373
|
+
queue.push(next);
|
|
16374
|
+
}
|
|
16375
|
+
if (queue.length - at > BRACE_PENDING)
|
|
16376
|
+
return [literal2(word)];
|
|
16377
|
+
}
|
|
16378
|
+
return [...done];
|
|
16379
|
+
};
|
|
16380
|
+
var closingQuote = (command, start, dialect, nesting = 0) => {
|
|
16302
16381
|
const quote = command[start];
|
|
16303
16382
|
for (let index = start + 1;index < command.length; index++) {
|
|
16304
16383
|
const char = command[index];
|
|
@@ -16315,51 +16394,265 @@ var closingQuote = (command, start, dialect) => {
|
|
|
16315
16394
|
index++;
|
|
16316
16395
|
continue;
|
|
16317
16396
|
}
|
|
16397
|
+
if (dialect === "posix" && char === "$" && command[index + 1] === "(") {
|
|
16398
|
+
index = substitutionEnd(command, index + 1, nesting + 1);
|
|
16399
|
+
continue;
|
|
16400
|
+
}
|
|
16401
|
+
if (dialect === "posix" && char === "`") {
|
|
16402
|
+
index = backtickEnd(command, index);
|
|
16403
|
+
continue;
|
|
16404
|
+
}
|
|
16318
16405
|
if (char === '"')
|
|
16319
16406
|
return index;
|
|
16320
16407
|
}
|
|
16321
16408
|
return -1;
|
|
16322
16409
|
};
|
|
16410
|
+
var backtickEnd = (command, start) => {
|
|
16411
|
+
for (let index = start + 1;index < command.length; index++) {
|
|
16412
|
+
if (command[index] === "\\")
|
|
16413
|
+
index++;
|
|
16414
|
+
else if (command[index] === "`")
|
|
16415
|
+
return index;
|
|
16416
|
+
}
|
|
16417
|
+
return command.length;
|
|
16418
|
+
};
|
|
16419
|
+
var heredocDelimiter = (command, start) => {
|
|
16420
|
+
let index = start;
|
|
16421
|
+
if (command[index] === "-")
|
|
16422
|
+
index++;
|
|
16423
|
+
while (command[index] === " " || command[index] === "\t")
|
|
16424
|
+
index++;
|
|
16425
|
+
let delimiter = "";
|
|
16426
|
+
for (;index < command.length && !/[\s;&|<>()]/.test(command[index]); index++) {
|
|
16427
|
+
const char = command[index];
|
|
16428
|
+
if (char === "'" || char === '"') {
|
|
16429
|
+
const end = command.indexOf(char, index + 1);
|
|
16430
|
+
if (end < 0)
|
|
16431
|
+
break;
|
|
16432
|
+
delimiter += command.slice(index + 1, end);
|
|
16433
|
+
index = end;
|
|
16434
|
+
} else if (char === "\\")
|
|
16435
|
+
delimiter += command[++index] ?? "";
|
|
16436
|
+
else
|
|
16437
|
+
delimiter += char;
|
|
16438
|
+
}
|
|
16439
|
+
return { delimiter, end: index - 1 };
|
|
16440
|
+
};
|
|
16441
|
+
var skipHeredocs = (command, newline, delimiters) => {
|
|
16442
|
+
let index = newline;
|
|
16443
|
+
while (delimiters.length) {
|
|
16444
|
+
const delimiter = delimiters.shift();
|
|
16445
|
+
for (;; ) {
|
|
16446
|
+
const lineEnd = command.indexOf(`
|
|
16447
|
+
`, index + 1);
|
|
16448
|
+
const line = command.slice(index + 1, lineEnd < 0 ? undefined : lineEnd);
|
|
16449
|
+
index = lineEnd < 0 ? command.length : lineEnd;
|
|
16450
|
+
if (line.trim() === delimiter || lineEnd < 0)
|
|
16451
|
+
break;
|
|
16452
|
+
}
|
|
16453
|
+
}
|
|
16454
|
+
return index;
|
|
16455
|
+
};
|
|
16456
|
+
var substitutionEnd = (command, start, nesting = 0) => {
|
|
16457
|
+
if (nesting > MAX_NESTING)
|
|
16458
|
+
throw new ShellAnalysisError("substitutions nest too deep");
|
|
16459
|
+
let depth = 0;
|
|
16460
|
+
let wordStart = true;
|
|
16461
|
+
const heredocs = [];
|
|
16462
|
+
for (let index = start;index < command.length; index++) {
|
|
16463
|
+
const char = command[index];
|
|
16464
|
+
const atWordStart = wordStart;
|
|
16465
|
+
wordStart = /[\s;&|()]/.test(char);
|
|
16466
|
+
if (char === "\\")
|
|
16467
|
+
index++;
|
|
16468
|
+
else if (char === `
|
|
16469
|
+
` && heredocs.length) {
|
|
16470
|
+
index = skipHeredocs(command, index, heredocs);
|
|
16471
|
+
wordStart = true;
|
|
16472
|
+
} else if (char === "'" || char === '"') {
|
|
16473
|
+
const end = closingQuote(command, index, "posix", nesting);
|
|
16474
|
+
if (end < 0)
|
|
16475
|
+
return command.length;
|
|
16476
|
+
index = end;
|
|
16477
|
+
} else if (char === "`")
|
|
16478
|
+
index = backtickEnd(command, index);
|
|
16479
|
+
else if (char === "#" && atWordStart) {
|
|
16480
|
+
const newline = command.indexOf(`
|
|
16481
|
+
`, index);
|
|
16482
|
+
index = newline < 0 ? command.length : newline - 1;
|
|
16483
|
+
} else if (char === "<" && command[index + 1] === "<" && command[index + 2] !== "<") {
|
|
16484
|
+
const { delimiter, end } = heredocDelimiter(command, index + 2);
|
|
16485
|
+
if (delimiter)
|
|
16486
|
+
heredocs.push(delimiter);
|
|
16487
|
+
index = end;
|
|
16488
|
+
} else if (char === "<" && command[index + 1] === "<")
|
|
16489
|
+
index += 2;
|
|
16490
|
+
else if (char === "$" && command[index + 1] === "(")
|
|
16491
|
+
index = substitutionEnd(command, index + 1, nesting + 1);
|
|
16492
|
+
else if (char === "(")
|
|
16493
|
+
depth++;
|
|
16494
|
+
else if (char === ")" && --depth === 0)
|
|
16495
|
+
return index;
|
|
16496
|
+
}
|
|
16497
|
+
return command.length;
|
|
16498
|
+
};
|
|
16323
16499
|
var unquote = (body, quote, dialect) => {
|
|
16324
16500
|
if (quote === "'")
|
|
16325
16501
|
return dialect === "powershell" ? body.replaceAll("''", "'") : body;
|
|
16326
|
-
return dialect === "posix" ? body.replace(/\\(["\\$`])/g, "$1") : body.replace(/`(.)/g, "$1");
|
|
16502
|
+
return dialect === "posix" ? body.replace(/\\\n/g, "").replace(/\\(["\\$`])/g, "$1") : body.replace(/`(.)/g, "$1");
|
|
16503
|
+
};
|
|
16504
|
+
var C_ESCAPES = {
|
|
16505
|
+
n: `
|
|
16506
|
+
`,
|
|
16507
|
+
t: "\t",
|
|
16508
|
+
r: "\r",
|
|
16509
|
+
a: "\x07",
|
|
16510
|
+
b: "\b",
|
|
16511
|
+
e: "\x1B",
|
|
16512
|
+
E: "\x1B",
|
|
16513
|
+
f: "\f",
|
|
16514
|
+
v: "\v"
|
|
16515
|
+
};
|
|
16516
|
+
var ansiC = (command, start) => {
|
|
16517
|
+
let text = "";
|
|
16518
|
+
let index = start + 1;
|
|
16519
|
+
for (;index < command.length && command[index] !== "'"; index++) {
|
|
16520
|
+
const char = command[index];
|
|
16521
|
+
if (char !== "\\" || index + 1 >= command.length) {
|
|
16522
|
+
text += char;
|
|
16523
|
+
continue;
|
|
16524
|
+
}
|
|
16525
|
+
const rest = command.slice(++index);
|
|
16526
|
+
const hex = /^x([0-9a-fA-F]{1,2})/.exec(rest);
|
|
16527
|
+
const octal = /^[0-7]{1,3}/.exec(rest);
|
|
16528
|
+
if (hex) {
|
|
16529
|
+
text += String.fromCharCode(Number.parseInt(hex[1], 16));
|
|
16530
|
+
index += hex[0].length - 1;
|
|
16531
|
+
} else if (octal) {
|
|
16532
|
+
text += String.fromCharCode(Number.parseInt(octal[0], 8));
|
|
16533
|
+
index += octal[0].length - 1;
|
|
16534
|
+
} else
|
|
16535
|
+
text += C_ESCAPES[rest[0]] ?? rest[0];
|
|
16536
|
+
}
|
|
16537
|
+
return { text, end: index };
|
|
16538
|
+
};
|
|
16539
|
+
var substitutions = (body) => {
|
|
16540
|
+
const found = [];
|
|
16541
|
+
for (let index = 0;index < body.length; index++) {
|
|
16542
|
+
const char = body[index];
|
|
16543
|
+
if (char === "\\")
|
|
16544
|
+
index++;
|
|
16545
|
+
else if (char === "`") {
|
|
16546
|
+
const end = backtickEnd(body, index);
|
|
16547
|
+
found.push(body.slice(index + 1, end).replace(/\\(.)/g, "$1"));
|
|
16548
|
+
index = end;
|
|
16549
|
+
} else if (char === "$" && body[index + 1] === "(") {
|
|
16550
|
+
const end = substitutionEnd(body, index + 1);
|
|
16551
|
+
found.push(body.slice(index + 2, end));
|
|
16552
|
+
index = end;
|
|
16553
|
+
}
|
|
16554
|
+
}
|
|
16555
|
+
return found;
|
|
16556
|
+
};
|
|
16557
|
+
var PLAIN_POSIX = /[^\s'"\\`$(){},<>|;&#]+/uy;
|
|
16558
|
+
var PLAIN_POWERSHELL = /[^\s'"`(){}<>|;&#]+/uy;
|
|
16559
|
+
var arithmeticEnd = (command, start) => {
|
|
16560
|
+
const end = substitutionEnd(command, start);
|
|
16561
|
+
return command[end - 1] === ")" && end > start + 2 ? end : 0;
|
|
16327
16562
|
};
|
|
16328
16563
|
var segmentsOf = (command, dialect = "posix") => {
|
|
16564
|
+
try {
|
|
16565
|
+
return tokenize(command, dialect);
|
|
16566
|
+
} catch (error) {
|
|
16567
|
+
const why = error instanceof ShellAnalysisError ? error.message : String(error);
|
|
16568
|
+
return [{ words: [], redirects: [], unanalyzable: why }];
|
|
16569
|
+
}
|
|
16570
|
+
};
|
|
16571
|
+
var tokenize = (command, dialect) => {
|
|
16572
|
+
const posix = dialect === "posix";
|
|
16329
16573
|
const segments = [];
|
|
16330
16574
|
let current = { words: [], redirects: [] };
|
|
16331
16575
|
let word = "";
|
|
16332
16576
|
let inWord = false;
|
|
16333
16577
|
let pending = null;
|
|
16334
16578
|
const heredocs = [];
|
|
16335
|
-
const escape =
|
|
16579
|
+
const escape = posix ? "\\" : "`";
|
|
16336
16580
|
const flushWord = () => {
|
|
16337
16581
|
if (!inWord)
|
|
16338
16582
|
return;
|
|
16583
|
+
const text = MARKERS.test(word) ? literal2(word) : word;
|
|
16339
16584
|
if (pending === "redirect") {
|
|
16340
|
-
if (!
|
|
16341
|
-
current.redirects.push(
|
|
16585
|
+
if (!text.startsWith("&"))
|
|
16586
|
+
current.redirects.push(text);
|
|
16342
16587
|
} else if (pending === "heredoc")
|
|
16343
|
-
heredocs.push(
|
|
16588
|
+
heredocs.push({ delimiter: text.replace(/^-/, ""), owner: current });
|
|
16589
|
+
else if (pending === "herestring")
|
|
16590
|
+
(current.stdin ??= []).push(text);
|
|
16344
16591
|
else if (pending !== "input")
|
|
16345
|
-
current.words.push(word);
|
|
16592
|
+
current.words.push(...MARKERS.test(word) ? expandBraces(word) : [word]);
|
|
16346
16593
|
pending = null;
|
|
16347
16594
|
word = "";
|
|
16348
16595
|
inWord = false;
|
|
16349
16596
|
};
|
|
16350
16597
|
const flushSegment = () => {
|
|
16351
16598
|
flushWord();
|
|
16352
|
-
if (current.words.length || current.redirects.length)
|
|
16599
|
+
if (current.words.length || current.redirects.length || current.stdin || current.subs)
|
|
16353
16600
|
segments.push(current);
|
|
16354
16601
|
current = { words: [], redirects: [] };
|
|
16355
16602
|
};
|
|
16603
|
+
const group = (kind) => {
|
|
16604
|
+
flushSegment();
|
|
16605
|
+
pending = null;
|
|
16606
|
+
segments.push({ words: [], redirects: [], group: kind });
|
|
16607
|
+
};
|
|
16608
|
+
const substitution = (inner, text) => {
|
|
16609
|
+
(current.subs ??= []).push(inner);
|
|
16610
|
+
word += text;
|
|
16611
|
+
inWord = true;
|
|
16612
|
+
};
|
|
16613
|
+
const plain = posix ? PLAIN_POSIX : PLAIN_POWERSHELL;
|
|
16356
16614
|
for (let index = 0;index < command.length; index++) {
|
|
16615
|
+
plain.lastIndex = index;
|
|
16616
|
+
const run = plain.exec(command);
|
|
16617
|
+
if (run) {
|
|
16618
|
+
word += run[0];
|
|
16619
|
+
inWord = true;
|
|
16620
|
+
index += run[0].length - 1;
|
|
16621
|
+
continue;
|
|
16622
|
+
}
|
|
16357
16623
|
const char = command[index];
|
|
16358
|
-
|
|
16624
|
+
const next = command[index + 1];
|
|
16625
|
+
if (char === escape && (next === `
|
|
16626
|
+
` || next === "\r" && command[index + 2] === `
|
|
16627
|
+
`))
|
|
16628
|
+
index += next === "\r" ? 2 : 1;
|
|
16629
|
+
else if (char === "#" && !inWord) {
|
|
16630
|
+
const newline = command.indexOf(`
|
|
16631
|
+
`, index);
|
|
16632
|
+
index = (newline < 0 ? command.length : newline) - 1;
|
|
16633
|
+
} else if (!posix && char === "<" && next === "#") {
|
|
16634
|
+
const end = command.indexOf("#>", index + 2);
|
|
16635
|
+
index = end < 0 ? command.length : end + 1;
|
|
16636
|
+
} else if (posix && char === "$" && next === "'") {
|
|
16637
|
+
const { text, end } = ansiC(command, index + 1);
|
|
16638
|
+
word += text;
|
|
16639
|
+
inWord = true;
|
|
16640
|
+
index = end;
|
|
16641
|
+
} else if (posix && char === "$" && next === '"')
|
|
16642
|
+
continue;
|
|
16643
|
+
else if (char === "'" || char === '"') {
|
|
16359
16644
|
const end = closingQuote(command, index, dialect);
|
|
16360
|
-
|
|
16645
|
+
const body = command.slice(index + 1, end < 0 ? undefined : end);
|
|
16646
|
+
if (posix && char === '"' && /\$\(|`/.test(body))
|
|
16647
|
+
(current.subs ??= []).push(...substitutions(body));
|
|
16648
|
+
word += unquote(body, char, dialect);
|
|
16361
16649
|
inWord = true;
|
|
16362
16650
|
index = end < 0 ? command.length : end;
|
|
16651
|
+
} else if (posix && char === "`") {
|
|
16652
|
+
const end = backtickEnd(command, index);
|
|
16653
|
+
const inner = command.slice(index + 1, end);
|
|
16654
|
+
substitution(inner.replace(/\\(.)/g, "$1"), `\`${inner}\``);
|
|
16655
|
+
index = end;
|
|
16363
16656
|
} else if (char === escape && index + 1 < command.length) {
|
|
16364
16657
|
word += command[++index];
|
|
16365
16658
|
inWord = true;
|
|
@@ -16367,26 +16660,56 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
16367
16660
|
`) {
|
|
16368
16661
|
flushSegment();
|
|
16369
16662
|
while (heredocs.length) {
|
|
16370
|
-
const delimiter = heredocs.shift();
|
|
16663
|
+
const { delimiter, owner } = heredocs.shift();
|
|
16371
16664
|
const lines = command.slice(index + 1).split(`
|
|
16372
16665
|
`);
|
|
16373
16666
|
const at = lines.findIndex((line) => line.trim() === delimiter);
|
|
16374
|
-
|
|
16667
|
+
(owner.stdin ??= []).push((at < 0 ? lines : lines.slice(0, at)).join(`
|
|
16668
|
+
`));
|
|
16669
|
+
index += (at < 0 ? lines : lines.slice(0, at + 1)).join(`
|
|
16375
16670
|
`).length + 1;
|
|
16376
|
-
index += skipped;
|
|
16377
16671
|
}
|
|
16378
16672
|
} else if (/\s/.test(char))
|
|
16379
16673
|
flushWord();
|
|
16380
|
-
else if (char === "("
|
|
16674
|
+
else if (posix && char === "(" && inWord && word.endsWith("$")) {
|
|
16675
|
+
const end = substitutionEnd(command, index);
|
|
16676
|
+
const inner = command.slice(index + 1, end);
|
|
16677
|
+
substitution(inner, `(${inner})`);
|
|
16678
|
+
index = end;
|
|
16679
|
+
} else if (posix && char === "(" && (pending === "input" || pending === "redirect")) {
|
|
16680
|
+
const sign = pending === "input" ? "<" : ">";
|
|
16681
|
+
pending = null;
|
|
16682
|
+
const end = substitutionEnd(command, index);
|
|
16683
|
+
const inner = command.slice(index + 1, end);
|
|
16684
|
+
substitution(inner, `${sign}(${inner})`);
|
|
16685
|
+
index = end;
|
|
16686
|
+
} else if (posix && char === "(" && next === "(" && !inWord && arithmeticEnd(command, index)) {
|
|
16687
|
+
flushSegment();
|
|
16688
|
+
index = arithmeticEnd(command, index);
|
|
16689
|
+
} else if (char === "(" || char === ")") {
|
|
16381
16690
|
if (char === "(" && inWord && word.endsWith("$")) {
|
|
16382
16691
|
word = word.slice(0, -1);
|
|
16383
16692
|
inWord = word !== "";
|
|
16384
16693
|
}
|
|
16694
|
+
group(char === "(" ? "open" : "close");
|
|
16695
|
+
} else if (!posix && (char === "{" || char === "}")) {
|
|
16696
|
+
if (char === "{" && inWord && word.endsWith("@")) {
|
|
16697
|
+
word += char;
|
|
16698
|
+
continue;
|
|
16699
|
+
}
|
|
16385
16700
|
flushSegment();
|
|
16386
|
-
segments.push({ words: [], redirects: [], group: char === "(" ? "open" : "close" });
|
|
16387
16701
|
} else if (";&|".includes(char)) {
|
|
16388
|
-
if (char === "&" &&
|
|
16702
|
+
if (char === "&" && next === ">")
|
|
16389
16703
|
continue;
|
|
16704
|
+
if (char === "|" && next === "|")
|
|
16705
|
+
index++;
|
|
16706
|
+
else if (char === "|") {
|
|
16707
|
+
flushWord();
|
|
16708
|
+
if (current.words.length)
|
|
16709
|
+
current.pipe = true;
|
|
16710
|
+
if (next === "&")
|
|
16711
|
+
index++;
|
|
16712
|
+
}
|
|
16390
16713
|
flushSegment();
|
|
16391
16714
|
} else if (char === ">") {
|
|
16392
16715
|
if (inWord && /^\d$/.test(word)) {
|
|
@@ -16402,16 +16725,24 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
16402
16725
|
inWord = true;
|
|
16403
16726
|
}
|
|
16404
16727
|
pending = "redirect";
|
|
16405
|
-
} else if (char === "<" &&
|
|
16728
|
+
} else if (char === "<" && posix) {
|
|
16406
16729
|
flushWord();
|
|
16407
|
-
if (command[index +
|
|
16730
|
+
if (next === "<" && command[index + 2] === "<") {
|
|
16731
|
+
index += 2;
|
|
16732
|
+
pending = "herestring";
|
|
16733
|
+
} else if (next === "<") {
|
|
16408
16734
|
index++;
|
|
16409
|
-
if (command[index + 1] === "<")
|
|
16410
|
-
index++;
|
|
16411
16735
|
pending = "heredoc";
|
|
16412
16736
|
} else
|
|
16413
16737
|
pending = "input";
|
|
16414
|
-
} else {
|
|
16738
|
+
} else if (posix && char === "{" && !word.endsWith("$")) {
|
|
16739
|
+
word += OPEN;
|
|
16740
|
+
inWord = true;
|
|
16741
|
+
} else if (posix && char === "," && word.includes(OPEN))
|
|
16742
|
+
word += COMMA;
|
|
16743
|
+
else if (posix && char === "}" && word.includes(OPEN))
|
|
16744
|
+
word += CLOSE;
|
|
16745
|
+
else {
|
|
16415
16746
|
word += char;
|
|
16416
16747
|
inWord = true;
|
|
16417
16748
|
}
|
|
@@ -16422,8 +16753,35 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
16422
16753
|
|
|
16423
16754
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
16424
16755
|
var NONE2 = { kind: "none" };
|
|
16425
|
-
var SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
16426
|
-
var
|
|
16756
|
+
var SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh", "ash", "mksh", "yash", "fish"]);
|
|
16757
|
+
var POWERSHELLS = new Set(["pwsh", "powershell"]);
|
|
16758
|
+
var EVALS = new Set(["eval", "iex", "invoke-expression"]);
|
|
16759
|
+
var WRAPPERS = {
|
|
16760
|
+
sudo: { values: "-u -g -h -p -C -D -R -T -r -t -U --user --group --host --prompt --chdir" },
|
|
16761
|
+
doas: { values: "-u -C" },
|
|
16762
|
+
command: { values: "" },
|
|
16763
|
+
builtin: { values: "" },
|
|
16764
|
+
env: { values: "-u -C --unset --chdir" },
|
|
16765
|
+
nohup: { values: "" },
|
|
16766
|
+
setsid: { values: "" },
|
|
16767
|
+
time: { values: "-f -o --format --output" },
|
|
16768
|
+
exec: { values: "-a" },
|
|
16769
|
+
nice: { values: "-n --adjustment" },
|
|
16770
|
+
ionice: { values: "-c -n -p --class --classdata" },
|
|
16771
|
+
stdbuf: { values: "-i -o -e --input --output --error" },
|
|
16772
|
+
chronic: { values: "" },
|
|
16773
|
+
unbuffer: { values: "" },
|
|
16774
|
+
wsl: { values: "-d -u --cd --distribution --user" },
|
|
16775
|
+
timeout: { values: "-s -k --signal --kill-after", operands: 1 },
|
|
16776
|
+
flock: { values: "-w -E --timeout --conflict-exit-code", operands: 1 },
|
|
16777
|
+
coproc: { values: "" },
|
|
16778
|
+
taskset: { values: "", operands: 1 },
|
|
16779
|
+
watch: { values: "-n -d --interval --differences -q --equexit" },
|
|
16780
|
+
"&": { values: "" }
|
|
16781
|
+
};
|
|
16782
|
+
var WRAPPER_VALUES = new Map(Object.entries(WRAPPERS).map(([name, wrapper]) => [name, new Set(wrapper.values.split(" "))]));
|
|
16783
|
+
var KEYWORDS = new Set(["if", "then", "else", "elif", "while", "until", "do", "!", "{"]);
|
|
16784
|
+
var DECLARATIONS = new Set(["export", "local", "declare", "readonly", "typeset"]);
|
|
16427
16785
|
var SCRIPT_FLAG = /^-[a-zA-Z]*c[a-zA-Z]*$/;
|
|
16428
16786
|
var CD = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
16429
16787
|
var PUSHD = new Set(["pushd", "push-location"]);
|
|
@@ -16437,13 +16795,21 @@ var GIT_VALUE_OPTIONS = new Set([
|
|
|
16437
16795
|
"--config-env",
|
|
16438
16796
|
"--super-prefix"
|
|
16439
16797
|
]);
|
|
16798
|
+
var GIT_CONFIG_OPTIONS = new Set(["-c", "--config-env", "--git-dir"]);
|
|
16799
|
+
var GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
|
|
16800
|
+
var ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
|
|
16801
|
+
var MAX_DEPTH = 4;
|
|
16802
|
+
var MAX_EXPANSIONS = 16;
|
|
16440
16803
|
var isAbsolute = (value) => path18.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
16441
|
-
var
|
|
16804
|
+
var HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
|
|
16805
|
+
var joinDir = (base, raw) => {
|
|
16806
|
+
const next = raw.replace(HERE, ".");
|
|
16442
16807
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
16443
16808
|
return;
|
|
16444
16809
|
const expanded = next === "~" || next.startsWith("~/") ? path18.join(os4.homedir(), next.slice(1)) : next;
|
|
16445
16810
|
return base === null || isAbsolute(expanded) ? expanded : path18.join(base, expanded);
|
|
16446
16811
|
};
|
|
16812
|
+
var rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner);
|
|
16447
16813
|
var cdTarget = (words) => {
|
|
16448
16814
|
const args = words.slice(1);
|
|
16449
16815
|
const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
|
|
@@ -16453,88 +16819,433 @@ var cdTarget = (words) => {
|
|
|
16453
16819
|
};
|
|
16454
16820
|
var stripPrefixes = (input) => {
|
|
16455
16821
|
let words = input;
|
|
16822
|
+
const env = {};
|
|
16456
16823
|
for (;; ) {
|
|
16457
16824
|
const first = words[0];
|
|
16458
16825
|
if (first === undefined)
|
|
16459
|
-
return words;
|
|
16460
|
-
|
|
16826
|
+
return { words, env };
|
|
16827
|
+
const assignment = ASSIGNMENT.exec(first);
|
|
16828
|
+
if (assignment) {
|
|
16829
|
+
if (GIT_CONFIG_ENV.test(assignment[1]))
|
|
16830
|
+
env[assignment[1]] = assignment[2];
|
|
16461
16831
|
words = words.slice(1);
|
|
16462
|
-
else if (
|
|
16832
|
+
} else if (KEYWORDS.has(first))
|
|
16463
16833
|
words = words.slice(1);
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16834
|
+
else if (first === "function")
|
|
16835
|
+
words = words.slice(2);
|
|
16836
|
+
else if (Object.hasOwn(WRAPPERS, commandName(first))) {
|
|
16837
|
+
const name = commandName(first);
|
|
16838
|
+
const values = WRAPPER_VALUES.get(name);
|
|
16467
16839
|
words = words.slice(1);
|
|
16468
|
-
|
|
16840
|
+
const takesValue = (option) => values.has(option) || /^-[a-zA-Z]{2,}$/.test(option) && values.has(`-${option.at(-1)}`);
|
|
16841
|
+
while (words[0]?.startsWith("-") && words[0] !== "--")
|
|
16842
|
+
words = words.slice(takesValue(words[0]) ? 2 : 1);
|
|
16843
|
+
if (words[0] === "--")
|
|
16469
16844
|
words = words.slice(1);
|
|
16470
|
-
words = words.slice(
|
|
16845
|
+
words = words.slice(WRAPPERS[name].operands ?? 0);
|
|
16471
16846
|
} else
|
|
16472
|
-
return words;
|
|
16847
|
+
return { words, env };
|
|
16473
16848
|
}
|
|
16474
16849
|
};
|
|
16475
16850
|
var commandName = (word) => (word?.split(/[\\/]/).at(-1) ?? "").toLowerCase().replace(/\.exe$/, "");
|
|
16851
|
+
var VARIABLE = /\$(?:\{(\w+)\}|(\w+))/g;
|
|
16852
|
+
var expandWord = (word, vars) => {
|
|
16853
|
+
if (!word.includes("$"))
|
|
16854
|
+
return [word];
|
|
16855
|
+
let results = [""];
|
|
16856
|
+
let last = 0;
|
|
16857
|
+
for (const match of word.matchAll(VARIABLE)) {
|
|
16858
|
+
const values = vars.get(match[1] ?? match[2]) ?? [match[0]];
|
|
16859
|
+
const before = word.slice(last, match.index);
|
|
16860
|
+
results = results.flatMap((result) => values.map((value) => result + before + value)).slice(0, MAX_EXPANSIONS);
|
|
16861
|
+
last = match.index + match[0].length;
|
|
16862
|
+
}
|
|
16863
|
+
return results.map((result) => result + word.slice(last));
|
|
16864
|
+
};
|
|
16865
|
+
var substitute = (words, vars) => {
|
|
16866
|
+
if (vars.size === 0)
|
|
16867
|
+
return [words];
|
|
16868
|
+
let lines = [[]];
|
|
16869
|
+
for (const word of words) {
|
|
16870
|
+
const values = expandWord(word, vars);
|
|
16871
|
+
lines = lines.flatMap((line) => values.map((value) => [...line, value])).slice(0, MAX_EXPANSIONS);
|
|
16872
|
+
}
|
|
16873
|
+
return lines;
|
|
16874
|
+
};
|
|
16875
|
+
var assignments = (words, vars) => {
|
|
16876
|
+
if (words[0] === "for" && words[2] === "in" && /^\w+$/.test(words[1] ?? "")) {
|
|
16877
|
+
const values = words.slice(3).flatMap((word) => expandWord(word, vars));
|
|
16878
|
+
return [[words[1], values.slice(0, MAX_EXPANSIONS)]];
|
|
16879
|
+
}
|
|
16880
|
+
let rest = words;
|
|
16881
|
+
if (DECLARATIONS.has(rest[0] ?? "")) {
|
|
16882
|
+
rest = rest.slice(1);
|
|
16883
|
+
while (rest[0]?.startsWith("-"))
|
|
16884
|
+
rest = rest.slice(1);
|
|
16885
|
+
}
|
|
16886
|
+
if (rest.length === 0 || !rest.every((word) => ASSIGNMENT.test(word)))
|
|
16887
|
+
return null;
|
|
16888
|
+
return rest.map((word) => {
|
|
16889
|
+
const [, name, value] = ASSIGNMENT.exec(word);
|
|
16890
|
+
return [name, expandWord(value, vars)];
|
|
16891
|
+
});
|
|
16892
|
+
};
|
|
16893
|
+
var literalOutput = (segment) => {
|
|
16894
|
+
if (!segment?.pipe)
|
|
16895
|
+
return;
|
|
16896
|
+
const { words } = stripPrefixes(segment.words);
|
|
16897
|
+
const name = commandName(words[0]);
|
|
16898
|
+
if (name === "echo") {
|
|
16899
|
+
let args = words.slice(1);
|
|
16900
|
+
while (/^-[neE]+$/.test(args[0] ?? ""))
|
|
16901
|
+
args = args.slice(1);
|
|
16902
|
+
return args.join(" ");
|
|
16903
|
+
}
|
|
16904
|
+
if (name === "printf") {
|
|
16905
|
+
const [format = "", ...args] = words.slice(1);
|
|
16906
|
+
return (args.length ? args.join(`
|
|
16907
|
+
`) : format).replace(/\\n/g, `
|
|
16908
|
+
`);
|
|
16909
|
+
}
|
|
16910
|
+
if (name === "cat" && words.length === 1 && segment.stdin)
|
|
16911
|
+
return segment.stdin.join(`
|
|
16912
|
+
`);
|
|
16913
|
+
return;
|
|
16914
|
+
};
|
|
16915
|
+
var stdinOf = (segment, previous) => segment.stdin ? segment.stdin.join(`
|
|
16916
|
+
`) : literalOutput(previous);
|
|
16917
|
+
var XARGS_VALUES = new Set(["-n", "-L", "-l", "-P", "-d", "-E", "-e", "-s", "-a", "--arg-file", "--delimiter"].concat([
|
|
16918
|
+
"--max-args",
|
|
16919
|
+
"--max-lines",
|
|
16920
|
+
"--max-procs",
|
|
16921
|
+
"--eof",
|
|
16922
|
+
"--max-chars",
|
|
16923
|
+
"--process-slot-var"
|
|
16924
|
+
]));
|
|
16925
|
+
var xargsCommands = (words, input) => {
|
|
16926
|
+
let replace = null;
|
|
16927
|
+
let index = 1;
|
|
16928
|
+
for (;index < words.length; index++) {
|
|
16929
|
+
const word = words[index];
|
|
16930
|
+
if (word === "--") {
|
|
16931
|
+
index++;
|
|
16932
|
+
break;
|
|
16933
|
+
}
|
|
16934
|
+
if (!word.startsWith("-"))
|
|
16935
|
+
break;
|
|
16936
|
+
if (word === "-I")
|
|
16937
|
+
replace = words[++index] ?? "{}";
|
|
16938
|
+
else if (word === "--replace" || word === "-i")
|
|
16939
|
+
replace = "{}";
|
|
16940
|
+
else if (word.startsWith("--replace="))
|
|
16941
|
+
replace = word.slice("--replace=".length);
|
|
16942
|
+
else if (/^-[Ii]./.test(word))
|
|
16943
|
+
replace = word.slice(2);
|
|
16944
|
+
else if (XARGS_VALUES.has(word))
|
|
16945
|
+
index++;
|
|
16946
|
+
}
|
|
16947
|
+
const command = words.slice(index);
|
|
16948
|
+
if (command.length === 0)
|
|
16949
|
+
return [];
|
|
16950
|
+
if (input === undefined)
|
|
16951
|
+
return [command];
|
|
16952
|
+
if (replace === null)
|
|
16953
|
+
return [[...command, ...input.split(/\s+/).filter(Boolean)]];
|
|
16954
|
+
const token = replace;
|
|
16955
|
+
return input.split(`
|
|
16956
|
+
`).map((line) => line.trim()).filter(Boolean).slice(0, MAX_EXPANSIONS).map((line) => command.map((word) => word.replaceAll(token, line)));
|
|
16957
|
+
};
|
|
16958
|
+
var findCommands = (words) => {
|
|
16959
|
+
const found = [];
|
|
16960
|
+
for (let index = 1;index < words.length; index++) {
|
|
16961
|
+
if (!/^-(?:exec|execdir|ok|okdir)$/.test(words[index]))
|
|
16962
|
+
continue;
|
|
16963
|
+
const end = words.findIndex((word, at) => at > index && (word === ";" || word === "+"));
|
|
16964
|
+
found.push(words.slice(index + 1, end < 0 ? undefined : end));
|
|
16965
|
+
if (end < 0)
|
|
16966
|
+
break;
|
|
16967
|
+
index = end;
|
|
16968
|
+
}
|
|
16969
|
+
return found;
|
|
16970
|
+
};
|
|
16971
|
+
var POWERSHELL_VALUES = /^-(?:f|file|ex|executionpolicy|wd|workingdirectory|config|configurationname|o|outputformat|if|inputformat|inp|w|windowstyle|settingsfile|custompipename|psconsolefile)$/;
|
|
16972
|
+
var powershellScript = (words, stdin) => {
|
|
16973
|
+
for (let index = 1;index < words.length; index++) {
|
|
16974
|
+
const word = words[index];
|
|
16975
|
+
if (!/^[-/]/.test(word))
|
|
16976
|
+
return null;
|
|
16977
|
+
const flag = word.replace(/^[-/]+/, "").toLowerCase();
|
|
16978
|
+
if (!flag)
|
|
16979
|
+
return null;
|
|
16980
|
+
if (flag === "e" || flag === "ec" || flag.length >= 2 && "encodedcommand".startsWith(flag)) {
|
|
16981
|
+
try {
|
|
16982
|
+
return Buffer.from(words[index + 1] ?? "", "base64").toString("utf16le");
|
|
16983
|
+
} catch {
|
|
16984
|
+
return null;
|
|
16985
|
+
}
|
|
16986
|
+
}
|
|
16987
|
+
if (flag === "cwa" || flag.length >= 8 && "commandwithargs".startsWith(flag))
|
|
16988
|
+
return words[index + 1] ?? null;
|
|
16989
|
+
if ("command".startsWith(flag))
|
|
16990
|
+
return words[index + 1] === "-" ? stdin ?? null : words.slice(index + 1).join(" ");
|
|
16991
|
+
if (POWERSHELL_VALUES.test(`-${flag}`)) {
|
|
16992
|
+
if (flag === "f" || flag === "file")
|
|
16993
|
+
return null;
|
|
16994
|
+
index++;
|
|
16995
|
+
}
|
|
16996
|
+
}
|
|
16997
|
+
return null;
|
|
16998
|
+
};
|
|
16999
|
+
var cmdScript = (words) => {
|
|
17000
|
+
const at = words.findIndex((word, index) => index > 0 && /^\/[ck]$/i.test(word));
|
|
17001
|
+
if (at > 0)
|
|
17002
|
+
return words.slice(at + 1).join(" ");
|
|
17003
|
+
const attached = words.find((word, index) => index > 0 && /^\/[ck]./i.test(word));
|
|
17004
|
+
return attached ? [attached.slice(2), ...words.slice(words.indexOf(attached) + 1)].join(" ") : null;
|
|
17005
|
+
};
|
|
17006
|
+
var processSubstitutionText = (word) => {
|
|
17007
|
+
const inner = /^<\(([\s\S]*)\)$/.exec(word ?? "")?.[1];
|
|
17008
|
+
if (inner === undefined)
|
|
17009
|
+
return;
|
|
17010
|
+
const segments = segmentsOf(inner);
|
|
17011
|
+
return segments.length === 1 ? literalOutput({ ...segments[0], pipe: true }) : undefined;
|
|
17012
|
+
};
|
|
17013
|
+
var shellScript = (words, stdin) => {
|
|
17014
|
+
const flag = words.findIndex((word, index) => index > 0 && SCRIPT_FLAG.test(word));
|
|
17015
|
+
if (flag > 0)
|
|
17016
|
+
return words[flag + 1] === "--" ? words[flag + 2] : words[flag + 1];
|
|
17017
|
+
const operand = words.slice(1).find((word) => !word.startsWith("-"));
|
|
17018
|
+
if (operand !== undefined)
|
|
17019
|
+
return processSubstitutionText(operand);
|
|
17020
|
+
return stdin;
|
|
17021
|
+
};
|
|
17022
|
+
var scriptCommand = (words) => {
|
|
17023
|
+
for (let index = 1;index < words.length; index++) {
|
|
17024
|
+
const word = words[index];
|
|
17025
|
+
if (word === "--command" || /^-[a-zA-Z]*c$/.test(word))
|
|
17026
|
+
return words[index + 1];
|
|
17027
|
+
if (word.startsWith("--command="))
|
|
17028
|
+
return word.slice("--command=".length);
|
|
17029
|
+
}
|
|
17030
|
+
return;
|
|
17031
|
+
};
|
|
17032
|
+
var PARALLEL_VALUES = new Set(["-j", "--jobs", "-N", "-n", "-S", "--sshlogin", "-P", "--delay"]);
|
|
17033
|
+
var parallelCommands = (words) => {
|
|
17034
|
+
let index = 1;
|
|
17035
|
+
while (index < words.length && words[index].startsWith("-"))
|
|
17036
|
+
index += PARALLEL_VALUES.has(words[index]) ? 2 : 1;
|
|
17037
|
+
const separator = words.indexOf(":::", index);
|
|
17038
|
+
const command = words.slice(index, separator < 0 ? undefined : separator);
|
|
17039
|
+
if (separator < 0)
|
|
17040
|
+
return command.length ? [command] : [];
|
|
17041
|
+
return words.slice(separator + 1).filter((arg) => !arg.startsWith(":::")).slice(0, MAX_EXPANSIONS).map((arg) => command.some((word) => word.includes("{}")) ? command.map((word) => word.replaceAll("{}", arg)) : [...command, arg]);
|
|
17042
|
+
};
|
|
17043
|
+
var START_PROCESS_VALUES = /^-(?:workingdirectory|wd|redirectstandard\w*|verb|windowstyle|credential|environment)$/i;
|
|
17044
|
+
var startProcessCommand = (words) => {
|
|
17045
|
+
let file;
|
|
17046
|
+
let args;
|
|
17047
|
+
const positionals = [];
|
|
17048
|
+
for (let index = 1;index < words.length; index++) {
|
|
17049
|
+
const word = words[index];
|
|
17050
|
+
const flag = word.startsWith("-") ? word.slice(1).toLowerCase() : null;
|
|
17051
|
+
if (flag === null)
|
|
17052
|
+
positionals.push(word);
|
|
17053
|
+
else if (flag && "filepath".startsWith(flag))
|
|
17054
|
+
file = words[++index];
|
|
17055
|
+
else if (flag && (flag === "args" || "argumentlist".startsWith(flag)))
|
|
17056
|
+
args = words[++index];
|
|
17057
|
+
else if (START_PROCESS_VALUES.test(word))
|
|
17058
|
+
index++;
|
|
17059
|
+
}
|
|
17060
|
+
file ??= positionals.shift();
|
|
17061
|
+
args ??= positionals.shift();
|
|
17062
|
+
if (!file)
|
|
17063
|
+
return null;
|
|
17064
|
+
return [file, ...(args ?? "").split(/[\s,]+/).filter(Boolean)];
|
|
17065
|
+
};
|
|
17066
|
+
var splitString = (line) => {
|
|
17067
|
+
if (commandName(line[0]) !== "env")
|
|
17068
|
+
return null;
|
|
17069
|
+
for (let index = 1;index < line.length; index++) {
|
|
17070
|
+
const word = line[index];
|
|
17071
|
+
if (word === "-S" || word === "--split-string")
|
|
17072
|
+
return line.slice(index + 1).join(" ");
|
|
17073
|
+
if (word.startsWith("--split-string="))
|
|
17074
|
+
return line.slice(index).join(" ").slice(15);
|
|
17075
|
+
if (/^-S./.test(word))
|
|
17076
|
+
return [word.slice(2), ...line.slice(index + 1)].join(" ");
|
|
17077
|
+
if (!word.startsWith("-") && !ASSIGNMENT.test(word))
|
|
17078
|
+
return null;
|
|
17079
|
+
}
|
|
17080
|
+
return null;
|
|
17081
|
+
};
|
|
17082
|
+
var CONFIG_READS = /^(?:--get\S*|-l|--list|--unset\S*|--remove-section|--rename-section|-e|--edit|--show-\S+|--name-only)$/;
|
|
17083
|
+
var configSetBy = (args) => {
|
|
17084
|
+
const positionals = args.filter((arg, index) => index > 0 && !arg.startsWith("-"));
|
|
17085
|
+
if (args[0] === "remote" && (positionals[0] === "add" || positionals[0] === "set-url")) {
|
|
17086
|
+
const [, name, url] = positionals;
|
|
17087
|
+
const key = args.includes("--push") ? "pushurl" : "url";
|
|
17088
|
+
return name && url ? ["-c", `remote.${name}.${key}=${url}`] : [];
|
|
17089
|
+
}
|
|
17090
|
+
if (args[0] !== "config" || args.some((arg) => CONFIG_READS.test(arg)))
|
|
17091
|
+
return [];
|
|
17092
|
+
const [key, value] = positionals[0] === "set" ? positionals.slice(1) : positionals;
|
|
17093
|
+
return key?.includes(".") && value !== undefined && positionals.length <= 3 ? ["-c", `${key}=${value}`] : [];
|
|
17094
|
+
};
|
|
17095
|
+
var gitInvocation = (words, dir, env = {}, stdin, inherited = []) => {
|
|
17096
|
+
let here = dir;
|
|
17097
|
+
const config = [...inherited];
|
|
17098
|
+
let gitDir = env.GIT_DIR;
|
|
17099
|
+
let index = 0;
|
|
17100
|
+
for (;index < words.length; index++) {
|
|
17101
|
+
const word = words[index];
|
|
17102
|
+
if (word === "-C")
|
|
17103
|
+
here = words[index + 1] ? joinDir(here, words[++index]) : here;
|
|
17104
|
+
else if (GIT_CONFIG_OPTIONS.has(word)) {
|
|
17105
|
+
if (word === "--git-dir")
|
|
17106
|
+
gitDir = words[index + 1];
|
|
17107
|
+
if (words[index + 1] !== undefined)
|
|
17108
|
+
config.push(word, words[++index]);
|
|
17109
|
+
} else if (/^--(?:config-env|git-dir)=/.test(word)) {
|
|
17110
|
+
if (word.startsWith("--git-dir="))
|
|
17111
|
+
gitDir = word.slice("--git-dir=".length);
|
|
17112
|
+
config.push(word);
|
|
17113
|
+
} else if (GIT_VALUE_OPTIONS.has(word))
|
|
17114
|
+
index++;
|
|
17115
|
+
else if (!word.startsWith("-"))
|
|
17116
|
+
break;
|
|
17117
|
+
}
|
|
17118
|
+
if (gitDir)
|
|
17119
|
+
here = joinDir(here, gitDir.replace(/(?:^|[\\/]+)\.git[\\/]*$/, "") || ".");
|
|
17120
|
+
return {
|
|
17121
|
+
tool: "git",
|
|
17122
|
+
dir: here,
|
|
17123
|
+
args: words.slice(index),
|
|
17124
|
+
...config.length ? { config } : {},
|
|
17125
|
+
...Object.keys(env).length ? { env } : {},
|
|
17126
|
+
...stdin === undefined ? {} : { stdin }
|
|
17127
|
+
};
|
|
17128
|
+
};
|
|
16476
17129
|
function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
17130
|
+
if (depth > 0)
|
|
17131
|
+
return walk2(command, dialect, depth);
|
|
17132
|
+
const key = `${dialect}\x00${command}`;
|
|
17133
|
+
const cached = RECENT.get(key);
|
|
17134
|
+
if (cached)
|
|
17135
|
+
return cached;
|
|
17136
|
+
let found;
|
|
17137
|
+
try {
|
|
17138
|
+
found = walk2(command, dialect, depth);
|
|
17139
|
+
} catch (error) {
|
|
17140
|
+
throw error instanceof ShellAnalysisError ? error : new ShellAnalysisError(error instanceof Error ? error.message : String(error));
|
|
17141
|
+
}
|
|
17142
|
+
RECENT.set(key, found);
|
|
17143
|
+
if (RECENT.size > 8)
|
|
17144
|
+
RECENT.delete(RECENT.keys().next().value);
|
|
17145
|
+
return found;
|
|
17146
|
+
}
|
|
17147
|
+
var RECENT = new Map;
|
|
17148
|
+
function walk2(command, dialect, depth) {
|
|
16477
17149
|
const found = [];
|
|
16478
17150
|
let dir = null;
|
|
16479
17151
|
const groups = [];
|
|
16480
17152
|
let stack = [];
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
const
|
|
17153
|
+
const vars = new Map;
|
|
17154
|
+
const exported = {};
|
|
17155
|
+
const sessionConfig = [];
|
|
17156
|
+
const nested = (script, inner) => {
|
|
17157
|
+
if (!script || depth >= MAX_DEPTH)
|
|
17158
|
+
return;
|
|
17159
|
+
for (const invocation of rawInvocations(script, inner, depth + 1))
|
|
17160
|
+
found.push({ ...invocation, dir: rebase(dir, invocation.dir) });
|
|
17161
|
+
};
|
|
17162
|
+
const visit = (input, stdin, hops) => {
|
|
17163
|
+
const line = /^\$[\w:]+$/.test(input[0] ?? "") && input[1] === "=" ? input.slice(2) : input;
|
|
17164
|
+
const split = splitString(line);
|
|
17165
|
+
if (split !== null)
|
|
17166
|
+
return nested(split, "posix");
|
|
17167
|
+
const { words, env } = stripPrefixes(line);
|
|
16493
17168
|
const name = commandName(words[0]);
|
|
17169
|
+
if (!name)
|
|
17170
|
+
return;
|
|
17171
|
+
const runs = (lines) => {
|
|
17172
|
+
if (hops < MAX_DEPTH)
|
|
17173
|
+
for (const next of lines)
|
|
17174
|
+
visit(next, undefined, hops + 1);
|
|
17175
|
+
};
|
|
16494
17176
|
if (CD.has(name)) {
|
|
16495
17177
|
const target = cdTarget(words);
|
|
16496
17178
|
dir = target === null ? os4.homedir() : joinDir(dir, target);
|
|
16497
|
-
|
|
16498
|
-
}
|
|
16499
|
-
if (PUSHD.has(name)) {
|
|
17179
|
+
} else if (PUSHD.has(name)) {
|
|
16500
17180
|
const target = cdTarget(words);
|
|
16501
17181
|
stack.push(dir);
|
|
16502
17182
|
dir = target === null || target === "-" ? undefined : joinDir(dir, target);
|
|
16503
|
-
|
|
16504
|
-
}
|
|
16505
|
-
if (POPD.has(name)) {
|
|
17183
|
+
} else if (POPD.has(name))
|
|
16506
17184
|
dir = stack.length ? stack.pop() : undefined;
|
|
16507
|
-
|
|
17185
|
+
else if (EVALS.has(name)) {
|
|
17186
|
+
const args = /^-c(?:o(?:m(?:m(?:a(?:n(?:d)?)?)?)?)?)?$/i.test(words[1] ?? "") ? words.slice(2) : words.slice(1);
|
|
17187
|
+
nested(args.join(" "), dialect);
|
|
17188
|
+
} else if (SHELLS.has(name))
|
|
17189
|
+
nested(shellScript(words, stdin), "posix");
|
|
17190
|
+
else if ((name === "source" || name === ".") && dialect === "posix")
|
|
17191
|
+
nested(processSubstitutionText(words[1]), "posix");
|
|
17192
|
+
else if (name === "trap" && dialect === "posix" && !/^-[lp]$/.test(words[1] ?? ""))
|
|
17193
|
+
nested(words[1], "posix");
|
|
17194
|
+
else if (name === "script")
|
|
17195
|
+
nested(scriptCommand(words), "posix");
|
|
17196
|
+
else if (name === "parallel")
|
|
17197
|
+
runs(parallelCommands(words));
|
|
17198
|
+
else if (dialect === "powershell" && /^(?:start-process|saps|start)$/.test(name)) {
|
|
17199
|
+
const started = startProcessCommand(words);
|
|
17200
|
+
if (started)
|
|
17201
|
+
runs([started]);
|
|
17202
|
+
} else if (POWERSHELLS.has(name))
|
|
17203
|
+
nested(powershellScript(words, stdin), "powershell");
|
|
17204
|
+
else if (name === "cmd")
|
|
17205
|
+
nested(cmdScript(words), "powershell");
|
|
17206
|
+
else if (name === "xargs" || name === "find")
|
|
17207
|
+
runs(name === "xargs" ? xargsCommands(words, stdin) : findCommands(words));
|
|
17208
|
+
else if (name === "gh" || name === "glab")
|
|
17209
|
+
found.push({
|
|
17210
|
+
tool: name,
|
|
17211
|
+
dir,
|
|
17212
|
+
args: words.slice(1),
|
|
17213
|
+
...stdin === undefined ? {} : { stdin }
|
|
17214
|
+
});
|
|
17215
|
+
else if (name === "git") {
|
|
17216
|
+
const invocation = gitInvocation(words.slice(1), dir, { ...exported, ...env }, stdin, sessionConfig);
|
|
17217
|
+
found.push(invocation);
|
|
17218
|
+
sessionConfig.push(...configSetBy(invocation.args));
|
|
16508
17219
|
}
|
|
16509
|
-
|
|
16510
|
-
|
|
16511
|
-
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
found.push({
|
|
16515
|
-
...inner,
|
|
16516
|
-
dir: inner.dir === null ? dir : inner.dir === undefined ? undefined : joinDir(dir, inner.dir)
|
|
16517
|
-
});
|
|
17220
|
+
};
|
|
17221
|
+
const segments = segmentsOf(command, dialect);
|
|
17222
|
+
for (const [index, segment] of segments.entries()) {
|
|
17223
|
+
if (segment.group === "open") {
|
|
17224
|
+
groups.push({ dir, stack: [...stack] });
|
|
16518
17225
|
continue;
|
|
16519
17226
|
}
|
|
16520
|
-
if (
|
|
16521
|
-
|
|
17227
|
+
if (segment.group === "close") {
|
|
17228
|
+
const saved = groups.pop();
|
|
17229
|
+
if (saved)
|
|
17230
|
+
({ dir, stack } = saved);
|
|
16522
17231
|
continue;
|
|
16523
17232
|
}
|
|
16524
|
-
if (
|
|
17233
|
+
if (segment.unanalyzable)
|
|
17234
|
+
throw new ShellAnalysisError(segment.unanalyzable);
|
|
17235
|
+
for (const sub of segment.subs ?? [])
|
|
17236
|
+
nested(sub, "posix");
|
|
17237
|
+
const set = assignments(segment.words, vars);
|
|
17238
|
+
if (set) {
|
|
17239
|
+
for (const [name, values] of set) {
|
|
17240
|
+
vars.set(name, values);
|
|
17241
|
+
if (segment.words[0] === "export" && GIT_CONFIG_ENV.test(name) && values[0] !== undefined)
|
|
17242
|
+
exported[name] = values[0];
|
|
17243
|
+
}
|
|
16525
17244
|
continue;
|
|
16526
|
-
let here = dir;
|
|
16527
|
-
let index = 1;
|
|
16528
|
-
for (;index < words.length; index++) {
|
|
16529
|
-
const word = words[index];
|
|
16530
|
-
if (word === "-C")
|
|
16531
|
-
here = words[index + 1] ? joinDir(here, words[++index]) : here;
|
|
16532
|
-
else if (GIT_VALUE_OPTIONS.has(word))
|
|
16533
|
-
index++;
|
|
16534
|
-
else if (!word.startsWith("-"))
|
|
16535
|
-
break;
|
|
16536
17245
|
}
|
|
16537
|
-
|
|
17246
|
+
const stdin = stdinOf(segment, segments[index - 1]);
|
|
17247
|
+
for (const line of substitute(segment.words, vars))
|
|
17248
|
+
visit(line, stdin, 0);
|
|
16538
17249
|
}
|
|
16539
17250
|
return found;
|
|
16540
17251
|
}
|
|
@@ -16570,6 +17281,55 @@ function workitInvocations(command, dialect = "posix", depth = 0) {
|
|
|
16570
17281
|
return found;
|
|
16571
17282
|
}
|
|
16572
17283
|
var PUSH_VALUE_OPTIONS = new Set(["-o", "--push-option", "--receive-pack", "--exec", "--repo"]);
|
|
17284
|
+
var CURRENT_BRANCH = /^\$\(\s*git\s+(?:branch\s+--show-current|rev-parse\s+--abbrev-ref\s+HEAD|symbolic-ref\s+--short\s+HEAD)\s*\)$/;
|
|
17285
|
+
var pushDestination = (destination) => {
|
|
17286
|
+
if (destination === "HEAD" || destination === "@" || CURRENT_BRANCH.test(destination))
|
|
17287
|
+
return { name: null };
|
|
17288
|
+
if (destination.startsWith("refs/heads/"))
|
|
17289
|
+
return { name: destination.slice(11) };
|
|
17290
|
+
if (destination.startsWith("refs/tags/"))
|
|
17291
|
+
return { name: undefined, tag: destination.slice(10) };
|
|
17292
|
+
if (destination.startsWith("refs/"))
|
|
17293
|
+
return { name: undefined };
|
|
17294
|
+
return { name: destination };
|
|
17295
|
+
};
|
|
17296
|
+
var pushRefspecs = (specs) => {
|
|
17297
|
+
let force = false;
|
|
17298
|
+
let matching = false;
|
|
17299
|
+
const targets = [];
|
|
17300
|
+
const tags = [];
|
|
17301
|
+
const deleted = [];
|
|
17302
|
+
const globs = [];
|
|
17303
|
+
for (const raw of specs) {
|
|
17304
|
+
if (raw.startsWith("+"))
|
|
17305
|
+
force = true;
|
|
17306
|
+
const spec = raw.replace(/^\+/, "");
|
|
17307
|
+
if (spec.startsWith("^"))
|
|
17308
|
+
continue;
|
|
17309
|
+
if (spec === ":") {
|
|
17310
|
+
matching = true;
|
|
17311
|
+
continue;
|
|
17312
|
+
}
|
|
17313
|
+
const colon = spec.indexOf(":");
|
|
17314
|
+
const source = colon >= 0 ? spec.slice(0, colon) : spec;
|
|
17315
|
+
const destination = colon >= 0 ? spec.slice(colon + 1) : spec;
|
|
17316
|
+
if (!destination)
|
|
17317
|
+
continue;
|
|
17318
|
+
if (destination.includes("*")) {
|
|
17319
|
+
globs.push({ source, destination });
|
|
17320
|
+
continue;
|
|
17321
|
+
}
|
|
17322
|
+
const { name, tag } = pushDestination(destination);
|
|
17323
|
+
if (tag !== undefined)
|
|
17324
|
+
tags.push(tag);
|
|
17325
|
+
if (name === undefined)
|
|
17326
|
+
continue;
|
|
17327
|
+
targets.push(name);
|
|
17328
|
+
if (colon === 0 && name !== null)
|
|
17329
|
+
deleted.push(name);
|
|
17330
|
+
}
|
|
17331
|
+
return { force, matching, targets, tags, deleted, globs };
|
|
17332
|
+
};
|
|
16573
17333
|
var pushAction = (args) => {
|
|
16574
17334
|
let force = false;
|
|
16575
17335
|
let lease = false;
|
|
@@ -16579,6 +17339,7 @@ var pushAction = (args) => {
|
|
|
16579
17339
|
let allBranches = false;
|
|
16580
17340
|
let mirror = false;
|
|
16581
17341
|
let remote = null;
|
|
17342
|
+
let dryRun = false;
|
|
16582
17343
|
const positionals = [];
|
|
16583
17344
|
for (let index = 1;index < args.length; index++) {
|
|
16584
17345
|
const arg = args[index];
|
|
@@ -16586,9 +17347,11 @@ var pushAction = (args) => {
|
|
|
16586
17347
|
positionals.push(...args.slice(index + 1));
|
|
16587
17348
|
break;
|
|
16588
17349
|
}
|
|
16589
|
-
if (arg
|
|
16590
|
-
|
|
16591
|
-
if (arg
|
|
17350
|
+
if (/^--dr(?:y(?:-(?:r(?:un?)?)?)?)?$/.test(arg) || /^-[a-zA-Z]*n[a-zA-Z]*$/.test(arg))
|
|
17351
|
+
dryRun = true;
|
|
17352
|
+
else if (/^--no-dr(?:y(?:-(?:r(?:un?)?)?)?)?$/.test(arg))
|
|
17353
|
+
dryRun = false;
|
|
17354
|
+
else if (arg === "--repo")
|
|
16592
17355
|
remote = args[++index] ?? null;
|
|
16593
17356
|
else if (arg.startsWith("--repo="))
|
|
16594
17357
|
remote = arg.slice("--repo=".length);
|
|
@@ -16609,41 +17372,28 @@ var pushAction = (args) => {
|
|
|
16609
17372
|
else if (!arg.startsWith("-"))
|
|
16610
17373
|
positionals.push(arg);
|
|
16611
17374
|
}
|
|
17375
|
+
if (dryRun)
|
|
17376
|
+
return null;
|
|
16612
17377
|
const specs = remote === null ? positionals.slice(1) : positionals;
|
|
16613
17378
|
remote ??= positionals[0] ?? null;
|
|
16614
|
-
const
|
|
16615
|
-
const
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
if (raw.startsWith("+"))
|
|
16619
|
-
force = true;
|
|
16620
|
-
const spec = raw.replace(/^\+/, "");
|
|
16621
|
-
const colon = spec.indexOf(":");
|
|
16622
|
-
const destination = colon >= 0 ? spec.slice(colon + 1) : spec;
|
|
16623
|
-
if (!destination)
|
|
16624
|
-
continue;
|
|
16625
|
-
const name = destination === "HEAD" ? null : destination.startsWith("refs/heads/") ? destination.slice(11) : destination.startsWith("refs/") ? undefined : destination;
|
|
16626
|
-
if (destination.startsWith("refs/tags/"))
|
|
16627
|
-
tags.push(destination.slice(10));
|
|
16628
|
-
if (name === undefined)
|
|
16629
|
-
continue;
|
|
16630
|
-
targets.push(name);
|
|
16631
|
-
if (colon === 0 && name !== null)
|
|
16632
|
-
deleted.push(name);
|
|
16633
|
-
}
|
|
16634
|
-
if (specs.length === 0 && !wholesale)
|
|
16635
|
-
targets.push(null);
|
|
17379
|
+
const parsed = pushRefspecs(specs);
|
|
17380
|
+
const implicit = specs.length === 0 && !wholesale;
|
|
17381
|
+
if (implicit)
|
|
17382
|
+
parsed.targets.push(null);
|
|
16636
17383
|
return {
|
|
16637
17384
|
kind: "push",
|
|
16638
|
-
targets,
|
|
16639
|
-
blindForce: force && !lease,
|
|
17385
|
+
targets: parsed.targets,
|
|
17386
|
+
blindForce: (force || parsed.force) && !lease,
|
|
16640
17387
|
remote,
|
|
16641
|
-
...tags.length ? { tags } : {},
|
|
17388
|
+
...parsed.tags.length ? { tags: parsed.tags } : {},
|
|
16642
17389
|
...allTags ? { allTags: true } : {},
|
|
16643
17390
|
...deletes ? { deletes: true } : {},
|
|
16644
|
-
...deleted.length ? { deleted } : {},
|
|
17391
|
+
...parsed.deleted.length ? { deleted: parsed.deleted } : {},
|
|
16645
17392
|
...allBranches ? { allBranches: true } : {},
|
|
16646
|
-
...mirror ? { mirror: true } : {}
|
|
17393
|
+
...mirror ? { mirror: true } : {},
|
|
17394
|
+
...implicit ? { implicit: true } : {},
|
|
17395
|
+
...parsed.globs.length ? { globs: parsed.globs } : {},
|
|
17396
|
+
...parsed.matching ? { matching: true } : {}
|
|
16647
17397
|
};
|
|
16648
17398
|
};
|
|
16649
17399
|
var VALUE_OPTIONS = {
|
|
@@ -16689,22 +17439,110 @@ var asksHelp = (invocation) => {
|
|
|
16689
17439
|
}
|
|
16690
17440
|
return false;
|
|
16691
17441
|
};
|
|
17442
|
+
var API_VALUES = new Set(["--method", "--header", "--raw-field", "--field", "--jq", "--template", "--input"].concat([
|
|
17443
|
+
"--hostname",
|
|
17444
|
+
"--preview",
|
|
17445
|
+
"--cache",
|
|
17446
|
+
"--output"
|
|
17447
|
+
]));
|
|
17448
|
+
var API_SHORT_VALUES = "XHfFqtp";
|
|
17449
|
+
var API_FIELDS = new Set(["-f", "-F", "--raw-field", "--field"]);
|
|
17450
|
+
var API_MERGE = {
|
|
17451
|
+
gh: /(?:^|\/)(?:pulls\/[^/?#]+\/merge|merges)\/?(?:[?#]|$)/i,
|
|
17452
|
+
glab: /(?:^|\/)merge_requests\/[^/?#]+\/merge\/?(?:[?#]|$)/i
|
|
17453
|
+
};
|
|
17454
|
+
var GRAPHQL_MERGE = /\b(?:mergePullRequest|enablePullRequestAutoMerge|mergeBranch|mergeRequestAccept)\b/;
|
|
17455
|
+
var apiMerges = (tool, args, stdin) => {
|
|
17456
|
+
const request = { method: null, body: false };
|
|
17457
|
+
let endpoint = null;
|
|
17458
|
+
const values = [];
|
|
17459
|
+
const take = (name, value) => {
|
|
17460
|
+
if (name === "-X" || name === "--method")
|
|
17461
|
+
request.method = value.toUpperCase();
|
|
17462
|
+
if (API_FIELDS.has(name) || name === "--input")
|
|
17463
|
+
request.body = true;
|
|
17464
|
+
values.push(value);
|
|
17465
|
+
const fromStdin = name === "--input" ? value === "-" : /^(?:[^=]*=)?@-$/.test(value);
|
|
17466
|
+
if (fromStdin && stdin !== undefined)
|
|
17467
|
+
values.push(stdin);
|
|
17468
|
+
};
|
|
17469
|
+
for (let index = 1;index < args.length; index++) {
|
|
17470
|
+
const arg = args[index];
|
|
17471
|
+
if (arg === "--") {
|
|
17472
|
+
endpoint ??= args[index + 1] ?? null;
|
|
17473
|
+
break;
|
|
17474
|
+
}
|
|
17475
|
+
if (arg.startsWith("--")) {
|
|
17476
|
+
const eq = arg.indexOf("=");
|
|
17477
|
+
const name = eq > 0 ? arg.slice(0, eq) : arg;
|
|
17478
|
+
if (API_VALUES.has(name))
|
|
17479
|
+
take(name, eq > 0 ? arg.slice(eq + 1) : args[++index] ?? "");
|
|
17480
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
17481
|
+
for (let at = 1;at < arg.length; at++) {
|
|
17482
|
+
if (!API_SHORT_VALUES.includes(arg[at]))
|
|
17483
|
+
continue;
|
|
17484
|
+
take(`-${arg[at]}`, at + 1 < arg.length ? arg.slice(at + 1) : args[++index] ?? "");
|
|
17485
|
+
break;
|
|
17486
|
+
}
|
|
17487
|
+
} else
|
|
17488
|
+
endpoint ??= arg;
|
|
17489
|
+
}
|
|
17490
|
+
if (!endpoint)
|
|
17491
|
+
return false;
|
|
17492
|
+
endpoint = endpoint.replace(/(?<!:)\/{2,}/g, "/");
|
|
17493
|
+
if (/(?:^|\/)graphql\/?$/i.test(endpoint))
|
|
17494
|
+
return values.some((value) => GRAPHQL_MERGE.test(value));
|
|
17495
|
+
const verb = request.method ?? (request.body ? "POST" : "GET");
|
|
17496
|
+
return verb !== "GET" && verb !== "HEAD" && API_MERGE[tool].test(endpoint);
|
|
17497
|
+
};
|
|
17498
|
+
var subtreePush = (args) => {
|
|
17499
|
+
const positionals = [];
|
|
17500
|
+
for (let index = 2;index < args.length; index++) {
|
|
17501
|
+
const arg = args[index];
|
|
17502
|
+
if (arg === "-P" || arg === "--prefix" || arg === "-m" || arg === "--message")
|
|
17503
|
+
index++;
|
|
17504
|
+
else if (!arg.startsWith("-"))
|
|
17505
|
+
positionals.push(arg);
|
|
17506
|
+
}
|
|
17507
|
+
const [remote, branch] = positionals;
|
|
17508
|
+
return remote && branch ? pushAction(["push", remote, `HEAD:refs/heads/${branch}`]) : null;
|
|
17509
|
+
};
|
|
16692
17510
|
function rawAction(invocation) {
|
|
16693
17511
|
const args = invocation.args;
|
|
17512
|
+
if (invocation.tool !== "git" && args[0] === "api")
|
|
17513
|
+
return apiMerges(invocation.tool, args, invocation.stdin) ? { kind: "merge", forge: invocation.tool, via: "api" } : null;
|
|
16694
17514
|
if (asksHelp(invocation))
|
|
16695
17515
|
return null;
|
|
16696
|
-
const [first
|
|
17516
|
+
const [first] = args;
|
|
16697
17517
|
if (invocation.tool === "git") {
|
|
17518
|
+
const second = args[1];
|
|
16698
17519
|
if (first === "commit")
|
|
16699
17520
|
return args.includes("--dry-run") ? null : { kind: "commit", amend: args.includes("--amend") };
|
|
16700
17521
|
if (first === "push")
|
|
16701
17522
|
return pushAction(args);
|
|
17523
|
+
if (first === "send-pack")
|
|
17524
|
+
return pushAction([
|
|
17525
|
+
"push",
|
|
17526
|
+
...args.slice(1).filter((arg) => arg !== "--stdin"),
|
|
17527
|
+
...args.includes("--stdin") ? (invocation.stdin ?? "").split(/\s+/).filter(Boolean) : []
|
|
17528
|
+
]);
|
|
17529
|
+
if (first === "subtree" && second === "push")
|
|
17530
|
+
return subtreePush(args);
|
|
16702
17531
|
return null;
|
|
16703
17532
|
}
|
|
16704
17533
|
const forge = invocation.tool;
|
|
16705
17534
|
const noun = forge === "gh" ? "pr" : "mr";
|
|
16706
17535
|
if (first !== noun)
|
|
16707
17536
|
return null;
|
|
17537
|
+
const values = VALUE_OPTIONS[forge];
|
|
17538
|
+
let second;
|
|
17539
|
+
for (let index = 1;index < args.length && second === undefined; index++) {
|
|
17540
|
+
const arg = args[index];
|
|
17541
|
+
if (values.has(arg))
|
|
17542
|
+
index++;
|
|
17543
|
+
else if (!arg.startsWith("-"))
|
|
17544
|
+
second = arg;
|
|
17545
|
+
}
|
|
16708
17546
|
if (second === "merge")
|
|
16709
17547
|
return { kind: "merge", forge };
|
|
16710
17548
|
if (second === "create")
|
|
@@ -16736,16 +17574,6 @@ var guardedBranch = (dir, branch) => {
|
|
|
16736
17574
|
return false;
|
|
16737
17575
|
}
|
|
16738
17576
|
};
|
|
16739
|
-
var toPushRemote = (repo, remote) => {
|
|
16740
|
-
if (remote === null)
|
|
16741
|
-
return true;
|
|
16742
|
-
try {
|
|
16743
|
-
const pushRemote = pushRemoteName(repo.dir, repo.branch);
|
|
16744
|
-
return pushRemote === null || pushRemote === remote;
|
|
16745
|
-
} catch {
|
|
16746
|
-
return false;
|
|
16747
|
-
}
|
|
16748
|
-
};
|
|
16749
17577
|
var headSha2 = (repo) => {
|
|
16750
17578
|
const git = repo.location.git;
|
|
16751
17579
|
if (!git || git.reftable)
|
|
@@ -16767,13 +17595,172 @@ var headSha2 = (repo) => {
|
|
|
16767
17595
|
return null;
|
|
16768
17596
|
}
|
|
16769
17597
|
};
|
|
17598
|
+
var gitConfig = (dir, invocation, cache) => {
|
|
17599
|
+
const key = JSON.stringify([dir, invocation.config ?? [], invocation.env ?? {}]);
|
|
17600
|
+
const cached = cache.get(key);
|
|
17601
|
+
if (cached)
|
|
17602
|
+
return cached;
|
|
17603
|
+
const config = new Map;
|
|
17604
|
+
const listed = spawnSync11("git", [...invocation.config ?? [], "config", "-z", "--list"], {
|
|
17605
|
+
cwd: dir,
|
|
17606
|
+
encoding: "utf8",
|
|
17607
|
+
timeout: 3000,
|
|
17608
|
+
windowsHide: true,
|
|
17609
|
+
env: { ...process.env, ...invocation.env, GIT_TERMINAL_PROMPT: "0", GIT_OPTIONAL_LOCKS: "0" }
|
|
17610
|
+
});
|
|
17611
|
+
for (const entry of (listed.status === 0 ? listed.stdout : "").split("\x00")) {
|
|
17612
|
+
if (!entry)
|
|
17613
|
+
continue;
|
|
17614
|
+
const newline = entry.indexOf(`
|
|
17615
|
+
`);
|
|
17616
|
+
const name = newline < 0 ? entry : entry.slice(0, newline);
|
|
17617
|
+
config.set(name, [
|
|
17618
|
+
...config.get(name) ?? [],
|
|
17619
|
+
newline < 0 ? "true" : entry.slice(newline + 1)
|
|
17620
|
+
]);
|
|
17621
|
+
}
|
|
17622
|
+
cache.set(key, config);
|
|
17623
|
+
return config;
|
|
17624
|
+
};
|
|
17625
|
+
var configValue = (config, key) => config.get(key)?.at(-1);
|
|
17626
|
+
var GIT_COMMANDS = new Set(("add am annotate apply archive bisect blame branch bugreport bundle cat-file check-attr " + "check-ignore check-mailmap check-ref-format checkout checkout-index cherry cherry-pick " + "citool clean clone column commit commit-graph commit-tree config count-objects credential " + "daemon describe diagnose diff diff-files diff-index diff-tree difftool fast-export " + "fast-import fetch fetch-pack filter-branch fmt-merge-msg for-each-ref for-each-repo " + "format-patch fsck gc get-tar-commit-id grep gui hash-object help hook index-pack init " + "instaweb interpret-trailers lfs log ls-files ls-remote ls-tree mailinfo mailsplit " + "maintenance merge merge-base merge-file merge-index merge-tree mergetool mktag mktree " + "multi-pack-index mv name-rev notes pack-objects pack-refs patch-id prune pull push " + "range-diff read-tree rebase reflog remote repack replace request-pull rerere reset " + "restore rev-list rev-parse revert rm send-email shortlog show show-branch show-ref " + "sparse-checkout stage stash status stripspace submodule subtree switch symbolic-ref tag " + "update-index update-ref var verify-commit verify-pack verify-tag version whatchanged " + "worktree write-tree").split(" "));
|
|
17627
|
+
var JUDGED_COMMANDS = [
|
|
17628
|
+
"push",
|
|
17629
|
+
"commit",
|
|
17630
|
+
"switch",
|
|
17631
|
+
"checkout",
|
|
17632
|
+
"branch",
|
|
17633
|
+
"worktree",
|
|
17634
|
+
"stash",
|
|
17635
|
+
"update-ref",
|
|
17636
|
+
"symbolic-ref",
|
|
17637
|
+
"fetch",
|
|
17638
|
+
"pull",
|
|
17639
|
+
"subtree"
|
|
17640
|
+
];
|
|
17641
|
+
var editDistance2 = (a, b) => {
|
|
17642
|
+
let before = [];
|
|
17643
|
+
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
17644
|
+
for (let i = 1;i <= a.length; i++) {
|
|
17645
|
+
const row = [i];
|
|
17646
|
+
for (let j = 1;j <= b.length; j++) {
|
|
17647
|
+
row[j] = Math.min(previous[j] + 1, row[j - 1] + 1, previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
17648
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1])
|
|
17649
|
+
row[j] = Math.min(row[j], before[j - 2] + 1);
|
|
17650
|
+
}
|
|
17651
|
+
[before, previous] = [previous, row];
|
|
17652
|
+
}
|
|
17653
|
+
return previous[b.length];
|
|
17654
|
+
};
|
|
17655
|
+
var autocorrected = (name, config) => {
|
|
17656
|
+
const setting = (configValue(config, "help.autocorrect") ?? "0").toLowerCase();
|
|
17657
|
+
if (setting !== "immediate" && !/^-?[1-9]\d*$/.test(setting))
|
|
17658
|
+
return null;
|
|
17659
|
+
let best = null;
|
|
17660
|
+
let bestDistance = 3;
|
|
17661
|
+
let tie = false;
|
|
17662
|
+
for (const command of JUDGED_COMMANDS) {
|
|
17663
|
+
const distance = editDistance2(name, command);
|
|
17664
|
+
if (distance < bestDistance)
|
|
17665
|
+
[best, bestDistance, tie] = [command, distance, false];
|
|
17666
|
+
else if (distance === bestDistance)
|
|
17667
|
+
tie = true;
|
|
17668
|
+
}
|
|
17669
|
+
return tie ? null : best;
|
|
17670
|
+
};
|
|
17671
|
+
var shellQuote = (word) => `'${word.replaceAll("'", "'\\''")}'`;
|
|
17672
|
+
var positional = (script, args) => {
|
|
17673
|
+
const word = (arg) => /^[\w./@+:=-]+$/.test(arg) ? arg : shellQuote(arg);
|
|
17674
|
+
return script.replace(/\$\{?([1-9])\}?/g, (_, n) => word(args[Number(n) - 1] ?? "")).replace(/\$\{?[@*]\}?/g, args.map(word).join(" "));
|
|
17675
|
+
};
|
|
17676
|
+
var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
17677
|
+
const sub = invocation.args[0];
|
|
17678
|
+
if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
|
|
17679
|
+
return [invocation];
|
|
17680
|
+
const dir = path18.resolve(root, invocation.dir ?? ".");
|
|
17681
|
+
if (!fs15.existsSync(dir))
|
|
17682
|
+
return [invocation];
|
|
17683
|
+
const config = gitConfig(dir, invocation, cache);
|
|
17684
|
+
const alias = configValue(config, `alias.${sub.toLowerCase()}`);
|
|
17685
|
+
if (alias === undefined) {
|
|
17686
|
+
const corrected = autocorrected(sub, config);
|
|
17687
|
+
return corrected ? [{ ...invocation, args: [corrected, ...invocation.args.slice(1)] }] : [invocation];
|
|
17688
|
+
}
|
|
17689
|
+
const rest = invocation.args.slice(1);
|
|
17690
|
+
const expanded = alias.startsWith("!") ? rawInvocations([positional(alias.slice(1), rest), ...rest.map(shellQuote)].join(" ")).map((inner) => ({
|
|
17691
|
+
...inner,
|
|
17692
|
+
dir: rebase(invocation.dir, inner.dir),
|
|
17693
|
+
...inner.tool === "git" && (invocation.config || inner.config) ? { config: [...invocation.config ?? [], ...inner.config ?? []] } : {},
|
|
17694
|
+
...inner.tool === "git" && (invocation.env || inner.env) ? { env: { ...invocation.env, ...inner.env } } : {}
|
|
17695
|
+
})) : [
|
|
17696
|
+
gitInvocation([...segmentsOf(alias)[0]?.words ?? [], ...rest], invocation.dir, invocation.env, invocation.stdin, invocation.config)
|
|
17697
|
+
];
|
|
17698
|
+
return expanded.flatMap((inner) => expandGitAliases(root, inner, cache, depth + 1));
|
|
17699
|
+
};
|
|
17700
|
+
var normalizedUrl = (url, dir) => {
|
|
17701
|
+
const trimmed = url.trim();
|
|
17702
|
+
if (/^file:\/\//i.test(trimmed))
|
|
17703
|
+
return path18.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
17704
|
+
const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
|
|
17705
|
+
const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
|
|
17706
|
+
if (!scheme && !scp)
|
|
17707
|
+
return path18.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
17708
|
+
const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
|
|
17709
|
+
return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
17710
|
+
};
|
|
17711
|
+
var rewrittenUrl = (url, config) => {
|
|
17712
|
+
for (const kind of ["pushinsteadof", "insteadof"]) {
|
|
17713
|
+
let best = null;
|
|
17714
|
+
for (const [key, prefixes] of config) {
|
|
17715
|
+
if (!key.startsWith("url.") || !key.endsWith(`.${kind}`))
|
|
17716
|
+
continue;
|
|
17717
|
+
const base = key.slice(4, -(kind.length + 1));
|
|
17718
|
+
for (const prefix of prefixes)
|
|
17719
|
+
if (url.startsWith(prefix) && prefix.length > (best?.prefix.length ?? -1))
|
|
17720
|
+
best = { base, prefix };
|
|
17721
|
+
}
|
|
17722
|
+
if (best)
|
|
17723
|
+
return best.base + url.slice(best.prefix.length);
|
|
17724
|
+
}
|
|
17725
|
+
return url;
|
|
17726
|
+
};
|
|
17727
|
+
var pushUrl = (config, remote, dir) => {
|
|
17728
|
+
const configured = configValue(config, `remote.${remote}.pushurl`) ?? configValue(config, `remote.${remote}.url`);
|
|
17729
|
+
return normalizedUrl(rewrittenUrl(configured ?? remote, config), dir);
|
|
17730
|
+
};
|
|
17731
|
+
var pushRemoteOf = (config, branch) => {
|
|
17732
|
+
const remotes = new Set;
|
|
17733
|
+
for (const key of config.keys()) {
|
|
17734
|
+
const name = /^remote\.(.+)\.url$/.exec(key)?.[1];
|
|
17735
|
+
if (name)
|
|
17736
|
+
remotes.add(name);
|
|
17737
|
+
}
|
|
17738
|
+
for (const candidate of [
|
|
17739
|
+
branch ? configValue(config, `branch.${branch}.pushremote`) : undefined,
|
|
17740
|
+
configValue(config, "remote.pushdefault"),
|
|
17741
|
+
branch ? configValue(config, `branch.${branch}.remote`) : undefined
|
|
17742
|
+
])
|
|
17743
|
+
if (candidate && candidate !== "." && remotes.has(candidate))
|
|
17744
|
+
return candidate;
|
|
17745
|
+
if (remotes.has("origin"))
|
|
17746
|
+
return "origin";
|
|
17747
|
+
return remotes.size === 1 ? [...remotes][0] : null;
|
|
17748
|
+
};
|
|
17749
|
+
var toPushRemote = (repo, remote, config) => {
|
|
17750
|
+
if (remote === null || /[$`]/.test(remote))
|
|
17751
|
+
return true;
|
|
17752
|
+
const pushRemote = pushRemoteOf(config, repo.branch);
|
|
17753
|
+
if (pushRemote === null || pushRemote === remote)
|
|
17754
|
+
return true;
|
|
17755
|
+
return pushUrl(config, remote, repo.dir) === pushUrl(config, pushRemote, repo.dir);
|
|
17756
|
+
};
|
|
16770
17757
|
var quote = (text) => `\`${text}\``;
|
|
16771
17758
|
var refusal = (action, branch, dir) => {
|
|
16772
17759
|
if (action.kind === "merge")
|
|
16773
|
-
return `workit: raw ${quote(action.forge === "gh" ? "gh pr merge" : "glab mr merge")} bypasses the merge grant and the verdict gate. Run ${quote("workit pr merge")} instead (it checks both; ${quote("workit help pr")}).`;
|
|
17760
|
+
return `workit: raw ${quote(action.via === "api" ? `${action.forge} api` : action.forge === "gh" ? "gh pr merge" : "glab mr merge")}${action.via === "api" ? " merge" : ""} bypasses the merge grant and the verdict gate. Run ${quote("workit pr merge")} instead (it checks both; ${quote("workit help pr")}).`;
|
|
16774
17761
|
const plainPush = action.kind === "push" && !action.blindForce && !action.deletes;
|
|
16775
17762
|
if (dir && branch && plainPush && releaseBranch(dir, branch))
|
|
16776
|
-
return `workit: raw ${quote("git push")} onto ${branch}, a protected release branch, bypasses workit's protected-branch check. To finish a release or hotfix, push it with ${quote(`workit git push --release ${branch} [--release
|
|
17763
|
+
return `workit: raw ${quote("git push")} onto ${branch}, a protected release branch, bypasses workit's protected-branch check. To finish a release or hotfix, push it with ${quote(`workit git push --release ${branch} [--release ${releaseTagPrefixOf(dir)}<version>]`)}: it pushes ${branch} (fast-forward only) and the release tag, verifies the remote and records it, under the ${quote("release")} grant (if refused, ask the user to run ${quote("workit grant set <workspace> release=true")}). Feature work goes through ${quote("workit git push")} and ${quote("workit pr merge")}.`;
|
|
16777
17764
|
return `workit: raw ${quote("git push")}${action.kind === "push" && action.blindForce ? " --force" : ""} onto ${branch}, a protected branch or the default target, bypasses workit's protected-branch check. Push your feature branch with ${quote("workit git push")} (${quote("workit git push --force-with-lease")} to rewrite it) and land it with ${quote("workit pr merge")}.`;
|
|
16778
17765
|
};
|
|
16779
17766
|
var refFacts = (repo, remote) => {
|
|
@@ -16791,35 +17778,112 @@ var refFacts = (repo, remote) => {
|
|
|
16791
17778
|
}
|
|
16792
17779
|
return facts;
|
|
16793
17780
|
};
|
|
17781
|
+
var globBranches = (repo, glob) => {
|
|
17782
|
+
const source = glob.source.startsWith("refs/") ? glob.source : `refs/heads/${glob.source}`;
|
|
17783
|
+
const [sourcePrefix, sourceSuffix = ""] = source.split("*");
|
|
17784
|
+
const [destinationPrefix, destinationSuffix = ""] = glob.destination.split("*");
|
|
17785
|
+
const listed = spawnSync11("git", [
|
|
17786
|
+
"for-each-ref",
|
|
17787
|
+
"--format=%(refname)",
|
|
17788
|
+
sourcePrefix.slice(0, sourcePrefix.lastIndexOf("/") + 1)
|
|
17789
|
+
], { cwd: repo.dir, encoding: "utf8", timeout: 5000, windowsHide: true });
|
|
17790
|
+
const names = [];
|
|
17791
|
+
for (const ref of (listed.stdout ?? "").split(`
|
|
17792
|
+
`)) {
|
|
17793
|
+
if (!ref.startsWith(sourcePrefix) || !ref.endsWith(sourceSuffix))
|
|
17794
|
+
continue;
|
|
17795
|
+
const middle = ref.slice(sourcePrefix.length, ref.length - sourceSuffix.length);
|
|
17796
|
+
const { name } = pushDestination(destinationPrefix + middle + destinationSuffix);
|
|
17797
|
+
if (name)
|
|
17798
|
+
names.push(name);
|
|
17799
|
+
}
|
|
17800
|
+
return names;
|
|
17801
|
+
};
|
|
17802
|
+
var pushedBranches = (action, repo, config, facts, remote) => {
|
|
17803
|
+
const targets = action.implicit ? [] : [...action.targets];
|
|
17804
|
+
const globs = [...action.globs ?? []];
|
|
17805
|
+
let matching = action.matching === true;
|
|
17806
|
+
const configured = action.implicit ? config.get(`remote.${remote}.push`) : undefined;
|
|
17807
|
+
if (configured?.length) {
|
|
17808
|
+
const parsed = pushRefspecs(configured);
|
|
17809
|
+
targets.push(...parsed.targets);
|
|
17810
|
+
globs.push(...parsed.globs);
|
|
17811
|
+
matching ||= parsed.matching;
|
|
17812
|
+
} else if (action.implicit) {
|
|
17813
|
+
const mode = (configValue(config, "push.default") ?? "simple").toLowerCase();
|
|
17814
|
+
const merge = repo.branch ? configValue(config, `branch.${repo.branch}.merge`) : undefined;
|
|
17815
|
+
if (mode === "matching")
|
|
17816
|
+
matching = true;
|
|
17817
|
+
else if ((mode === "upstream" || mode === "tracking") && merge?.startsWith("refs/heads/"))
|
|
17818
|
+
targets.push(merge.slice(11));
|
|
17819
|
+
else if (mode !== "nothing")
|
|
17820
|
+
targets.push(null);
|
|
17821
|
+
}
|
|
17822
|
+
if (action.allBranches)
|
|
17823
|
+
targets.push(...facts.heads);
|
|
17824
|
+
if (matching) {
|
|
17825
|
+
for (const head of facts.heads)
|
|
17826
|
+
if (facts.remoteHeads.has(head))
|
|
17827
|
+
targets.push(head);
|
|
17828
|
+
}
|
|
17829
|
+
for (const glob of globs)
|
|
17830
|
+
targets.push(...globBranches(repo, glob));
|
|
17831
|
+
return targets;
|
|
17832
|
+
};
|
|
17833
|
+
var literalReadings = (name) => {
|
|
17834
|
+
if (!/[$`]/.test(name))
|
|
17835
|
+
return [name];
|
|
17836
|
+
const withDefaults = name.replace(/\$\{\w+:?[-=]([^}$`]*)\}/g, "$1").replace(/\$\{\w+\}|\$\w+/g, "");
|
|
17837
|
+
return /[$`]/.test(withDefaults) || !withDefaults ? [] : [withDefaults];
|
|
17838
|
+
};
|
|
17839
|
+
var guardedTarget = (dir, target) => {
|
|
17840
|
+
for (const branch of literalReadings(target)) {
|
|
17841
|
+
if (guardedBranch(dir, branch))
|
|
17842
|
+
return branch;
|
|
17843
|
+
const bare = branch.startsWith("heads/") ? branch.slice(6) : null;
|
|
17844
|
+
if (bare && guardedBranch(dir, bare))
|
|
17845
|
+
return bare;
|
|
17846
|
+
}
|
|
17847
|
+
return null;
|
|
17848
|
+
};
|
|
16794
17849
|
var isTag = (facts, name) => facts.tags.has(name) && !facts.heads.has(name);
|
|
16795
|
-
var tagRefusal = (action, facts) => {
|
|
17850
|
+
var tagRefusal = (action, facts, dir) => {
|
|
16796
17851
|
const tags = [
|
|
16797
17852
|
...action.tags ?? [],
|
|
16798
17853
|
...action.targets.filter((name) => name !== null && isTag(facts, name))
|
|
16799
17854
|
];
|
|
16800
17855
|
if (!tags.length && !action.allTags)
|
|
16801
17856
|
return null;
|
|
16802
|
-
const
|
|
16803
|
-
|
|
17857
|
+
const shape = `${releaseTagPrefixOf(dir)}<version>`;
|
|
17858
|
+
const named = tags.length ? tags.join(" --release ") : shape;
|
|
17859
|
+
return `workit: raw ${quote(`git push${action.allTags ? " --tags" : ""}`)} of ${tags.length ? `tag ${tags.join(", ")}` : "tags"} bypasses the release grant. Push a release tag with ${quote(`workit git push --release ${named}`)} (${shape} tags whose commit the production branch already has; a tag never moves), under the ${quote("release")} grant (if refused, ask the user to run ${quote("workit grant set <workspace> release=true")}).`;
|
|
16804
17860
|
};
|
|
16805
|
-
var
|
|
16806
|
-
const listed = spawnSync11("git", ["ls-remote", "--heads", remote
|
|
17861
|
+
var remoteHeads = (repo, remote) => {
|
|
17862
|
+
const listed = spawnSync11("git", ["ls-remote", "--heads", remote], {
|
|
16807
17863
|
cwd: repo.dir,
|
|
16808
17864
|
encoding: "utf8",
|
|
16809
17865
|
timeout: 3000,
|
|
17866
|
+
windowsHide: true,
|
|
16810
17867
|
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
16811
17868
|
});
|
|
16812
|
-
|
|
17869
|
+
if (listed.status !== 0)
|
|
17870
|
+
return null;
|
|
17871
|
+
return new Set((listed.stdout ?? "").split(`
|
|
17872
|
+
`).map((line) => line.split("\t")[1] ?? "").filter((ref) => ref.startsWith("refs/heads/")).map((ref) => ref.slice(11)));
|
|
16813
17873
|
};
|
|
16814
17874
|
var offPolicyPush = (action, repo, facts, remote) => {
|
|
16815
17875
|
const names = action.allBranches ? [...facts.heads] : action.targets.map((target) => target ?? repo.branch);
|
|
17876
|
+
let listed;
|
|
17877
|
+
const remoteHas = (branch) => (listed === undefined ? listed = remoteHeads(repo, remote) : listed)?.has(branch) ?? true;
|
|
16816
17878
|
for (const branch of names) {
|
|
16817
|
-
if (!branch ||
|
|
17879
|
+
if (!branch || /[$`]/.test(branch))
|
|
17880
|
+
continue;
|
|
17881
|
+
if (action.deleted?.includes(branch) || isTag(facts, branch))
|
|
16818
17882
|
continue;
|
|
16819
17883
|
if (facts.remoteHeads.has(branch))
|
|
16820
17884
|
continue;
|
|
16821
17885
|
const check = validateBranchNameFor(repo.dir, branch);
|
|
16822
|
-
if (check.ok || check.rule !== "allowed_pattern" || remoteHas(
|
|
17886
|
+
if (check.ok || check.rule !== "allowed_pattern" || remoteHas(branch))
|
|
16823
17887
|
continue;
|
|
16824
17888
|
return `workit: raw ${quote("git push")} onto ${branch}: ${check.error}`;
|
|
16825
17889
|
}
|
|
@@ -16841,23 +17905,50 @@ var nudgeFor = (action, host, session) => {
|
|
|
16841
17905
|
return null;
|
|
16842
17906
|
}
|
|
16843
17907
|
};
|
|
16844
|
-
var
|
|
17908
|
+
var pushRefusal = (action, repo, config) => {
|
|
17909
|
+
if (!toPushRemote(repo, action.remote, config))
|
|
17910
|
+
return null;
|
|
17911
|
+
if (action.mirror)
|
|
17912
|
+
return `workit: raw ${quote("git push --mirror")} rewrites and deletes every remote ref, protected branches and tags included. Push one branch with ${quote("workit git push")}.`;
|
|
17913
|
+
const remote = action.remote ?? pushRemoteOf(config, repo.branch) ?? "origin";
|
|
17914
|
+
const facts = refFacts(repo, remote);
|
|
17915
|
+
const targets = pushedBranches(action, repo, config, facts, remote);
|
|
17916
|
+
const pushed = { ...action, targets };
|
|
17917
|
+
const offPolicy = action.allBranches ? offPolicyPush(pushed, repo, facts, remote) : null;
|
|
17918
|
+
if (offPolicy)
|
|
17919
|
+
return offPolicy;
|
|
17920
|
+
for (const target of targets) {
|
|
17921
|
+
const guarded = guardedTarget(repo.dir, target ?? repo.branch ?? "");
|
|
17922
|
+
if (guarded)
|
|
17923
|
+
return refusal(action, guarded, repo.dir);
|
|
17924
|
+
}
|
|
17925
|
+
return tagRefusal(pushed, facts, repo.dir) ?? (action.deletes ? null : offPolicyPush(pushed, repo, facts, remote));
|
|
17926
|
+
};
|
|
17927
|
+
var actionsIn = (cwd, command, dialect, cache = new Map) => {
|
|
16845
17928
|
const out = [];
|
|
16846
17929
|
const repos = new Map;
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
continue;
|
|
16850
|
-
const action = rawAction(invocation);
|
|
16851
|
-
if (!action)
|
|
16852
|
-
continue;
|
|
16853
|
-
const dir = path18.resolve(cwd, invocation.dir ?? ".");
|
|
17930
|
+
const repoFor = (relative) => {
|
|
17931
|
+
const dir = path18.resolve(cwd, relative ?? ".");
|
|
16854
17932
|
if (!repos.has(dir)) {
|
|
16855
17933
|
const repo = repoAt(dir);
|
|
16856
17934
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
16857
17935
|
}
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
17936
|
+
return repos.get(dir) ?? null;
|
|
17937
|
+
};
|
|
17938
|
+
for (const raw of rawInvocations(command, dialect)) {
|
|
17939
|
+
if (raw.dir === undefined)
|
|
17940
|
+
continue;
|
|
17941
|
+
const known = raw.tool !== "git" || GIT_COMMANDS.has(raw.args[0] ?? "");
|
|
17942
|
+
if (!known && !repoFor(raw.dir))
|
|
17943
|
+
continue;
|
|
17944
|
+
for (const invocation of known ? [raw] : expandGitAliases(cwd, raw, cache)) {
|
|
17945
|
+
if (invocation.dir === undefined)
|
|
17946
|
+
continue;
|
|
17947
|
+
const action = rawAction(invocation);
|
|
17948
|
+
const repo = action ? repoFor(invocation.dir) : null;
|
|
17949
|
+
if (action && repo)
|
|
17950
|
+
out.push({ action, repo, invocation });
|
|
17951
|
+
}
|
|
16861
17952
|
}
|
|
16862
17953
|
return out;
|
|
16863
17954
|
};
|
|
@@ -16886,31 +17977,18 @@ var unseenNudges = (input, nudges, store) => {
|
|
|
16886
17977
|
};
|
|
16887
17978
|
function rawGitPre(input, command, options = {}) {
|
|
16888
17979
|
try {
|
|
16889
|
-
if (!mentionsRawTool(command))
|
|
16890
|
-
return NONE2;
|
|
16891
17980
|
const dialect = dialectOf(input);
|
|
16892
17981
|
const nudges = new Map;
|
|
16893
17982
|
let store = null;
|
|
16894
|
-
|
|
17983
|
+
const cache = new Map;
|
|
17984
|
+
for (const { action, repo, invocation } of actionsIn(input.cwd, command, dialect, cache)) {
|
|
16895
17985
|
store ??= repo.location.dir;
|
|
16896
17986
|
if (action.kind === "merge")
|
|
16897
17987
|
return deny(refusal(action, null));
|
|
16898
|
-
if (action.kind === "push"
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
const branch = target ?? repo.branch;
|
|
16903
|
-
if (branch && guardedBranch(repo.dir, branch))
|
|
16904
|
-
return deny(refusal(action, branch, repo.dir));
|
|
16905
|
-
}
|
|
16906
|
-
const remote = action.remote ?? pushRemoteName(repo.dir, repo.branch) ?? "origin";
|
|
16907
|
-
const facts = refFacts(repo, remote);
|
|
16908
|
-
const tagDeny = tagRefusal(action, facts);
|
|
16909
|
-
if (tagDeny)
|
|
16910
|
-
return deny(tagDeny);
|
|
16911
|
-
const nameDeny = action.deletes ? null : offPolicyPush(action, repo, facts, remote);
|
|
16912
|
-
if (nameDeny)
|
|
16913
|
-
return deny(nameDeny);
|
|
17988
|
+
if (action.kind === "push") {
|
|
17989
|
+
const refused = pushRefusal(action, repo, gitConfig(repo.dir, invocation, cache));
|
|
17990
|
+
if (refused)
|
|
17991
|
+
return deny(refused);
|
|
16914
17992
|
}
|
|
16915
17993
|
const nudge = nudgeFor(action, input.host, input.session.id);
|
|
16916
17994
|
if (nudge && !nudges.has(nudgeKind(action)))
|
|
@@ -16923,11 +18001,17 @@ function rawGitPre(input, command, options = {}) {
|
|
|
16923
18001
|
const shown = unseenNudges(input, nudges, store);
|
|
16924
18002
|
return shown.length ? { kind: "context", text: shown.join(`
|
|
16925
18003
|
`) } : NONE2;
|
|
16926
|
-
} catch {
|
|
16927
|
-
return NONE2;
|
|
18004
|
+
} catch (error) {
|
|
18005
|
+
return error instanceof ShellAnalysisError ? analysisDenial(error) : NONE2;
|
|
16928
18006
|
}
|
|
16929
18007
|
}
|
|
16930
18008
|
var deny = (reason) => ({ kind: "deny", reason, unblock: null });
|
|
18009
|
+
var SPLIT_IT = "Split it into simpler commands (no deeply nested substitutions or huge brace lists) and run them one at a time.";
|
|
18010
|
+
var analysisDenial = (error) => ({
|
|
18011
|
+
kind: "deny",
|
|
18012
|
+
reason: `workit: the shell hook could not analyze this command (${error.message}), so it does not run. ${SPLIT_IT}`,
|
|
18013
|
+
unblock: SPLIT_IT
|
|
18014
|
+
});
|
|
16931
18015
|
var NEXT_COMMAND = "next";
|
|
16932
18016
|
var MARKER_TTL_SECONDS = 3600;
|
|
16933
18017
|
var markerFile = (repo, session, key) => path18.join(repo.location.dir, "hooks", `commit-${createHash13("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
|
|
@@ -17028,20 +18112,28 @@ var UNKNOWABLE = /[$`*?[\]{}~]/u;
|
|
|
17028
18112
|
var SWITCH_CREATE = new Set(["-c", "--create", "-C", "--force-create", "--orphan"]);
|
|
17029
18113
|
var CHECKOUT_CREATE = new Set(["-b", "-B", "--orphan"]);
|
|
17030
18114
|
var WORKTREE_CREATE = new Set(["-b", "-B"]);
|
|
18115
|
+
var SUBTREE_CREATE = new Set(["-b", "--branch"]);
|
|
17031
18116
|
var BRANCH_NO_CREATE = new Set(["-d", "-D", "--delete", "-l", "--list", "-a", "--all", "-r", "--remotes", "--show-current"].concat(["-v", "-vv", "--verbose", "--contains", "--no-contains", "--merged", "--no-merged"]).concat(["--points-at", "--sort", "--format", "--column", "--no-column", "-u"]).concat(["--set-upstream-to", "--unset-upstream", "--edit-description", "-i", "--ignore-case"]));
|
|
17032
18117
|
var BRANCH_RENAME = new Set(["-m", "-M", "--move", "-c", "-C", "--copy"]);
|
|
18118
|
+
var longOption = (name, flags) => flags.has(name) || name.length >= 3 && [...flags].some((flag) => flag.startsWith("--") && flag.startsWith(name));
|
|
18119
|
+
var shortsOf = (flags) => [...flags].filter((flag) => /^-[^-]$/u.test(flag)).join("").replaceAll("-", "");
|
|
17033
18120
|
var flagValue = (args, flags) => {
|
|
18121
|
+
const shorts = shortsOf(flags);
|
|
17034
18122
|
for (let index = 1;index < args.length; index++) {
|
|
17035
18123
|
const arg = args[index];
|
|
17036
18124
|
if (arg === "--")
|
|
17037
18125
|
return null;
|
|
17038
|
-
if (
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
return arg.slice(eq + 1);
|
|
17043
|
-
|
|
17044
|
-
|
|
18126
|
+
if (arg.startsWith("--")) {
|
|
18127
|
+
const eq = arg.indexOf("=");
|
|
18128
|
+
if (!longOption(eq > 0 ? arg.slice(0, eq) : arg, flags))
|
|
18129
|
+
continue;
|
|
18130
|
+
return eq > 0 ? arg.slice(eq + 1) : args[index + 1] ?? null;
|
|
18131
|
+
}
|
|
18132
|
+
if (!arg.startsWith("-") || arg.length < 2)
|
|
18133
|
+
continue;
|
|
18134
|
+
for (let at = 1;at < arg.length; at++)
|
|
18135
|
+
if (shorts.includes(arg[at]))
|
|
18136
|
+
return at + 1 < arg.length ? arg.slice(at + 1) : args[index + 1] ?? null;
|
|
17045
18137
|
}
|
|
17046
18138
|
return null;
|
|
17047
18139
|
};
|
|
@@ -17074,55 +18166,114 @@ var branchCommandTarget = (args) => {
|
|
|
17074
18166
|
positionals.push(...args.slice(index + 1));
|
|
17075
18167
|
break;
|
|
17076
18168
|
}
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
18169
|
+
if (arg.startsWith("--")) {
|
|
18170
|
+
const flag = arg.split("=", 1)[0];
|
|
18171
|
+
if (longOption(flag, BRANCH_NO_CREATE))
|
|
18172
|
+
return null;
|
|
18173
|
+
if (longOption(flag, BRANCH_RENAME))
|
|
18174
|
+
rename = true;
|
|
18175
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
18176
|
+
const shorts = arg.slice(1).split("");
|
|
18177
|
+
if (shorts.some((short) => BRANCH_NO_CREATE.has(`-${short}`)))
|
|
18178
|
+
return null;
|
|
18179
|
+
if (shorts.some((short) => BRANCH_RENAME.has(`-${short}`)))
|
|
18180
|
+
rename = true;
|
|
18181
|
+
} else
|
|
17083
18182
|
positionals.push(arg);
|
|
17084
18183
|
}
|
|
17085
18184
|
if (positionals.length < 1 || positionals.length > 2)
|
|
17086
18185
|
return null;
|
|
17087
18186
|
return rename ? positionals.at(-1) ?? null : positionals[0];
|
|
17088
18187
|
};
|
|
17089
|
-
var
|
|
17090
|
-
const
|
|
17091
|
-
|
|
17092
|
-
|
|
18188
|
+
var positionalsOf = (args, skip, values = new Set) => {
|
|
18189
|
+
const found = [];
|
|
18190
|
+
for (let index = skip;index < args.length; index++) {
|
|
18191
|
+
const arg = args[index];
|
|
18192
|
+
if (arg === "--")
|
|
18193
|
+
return [...found, ...args.slice(index + 1)];
|
|
18194
|
+
if (values.has(arg))
|
|
18195
|
+
index++;
|
|
18196
|
+
else if (!arg.startsWith("-") || arg === "-")
|
|
18197
|
+
found.push(arg);
|
|
18198
|
+
}
|
|
18199
|
+
return found;
|
|
17093
18200
|
};
|
|
17094
|
-
var
|
|
17095
|
-
|
|
18201
|
+
var localHead = (ref) => ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : null;
|
|
18202
|
+
var updateRefTargets = (args, stdin) => {
|
|
18203
|
+
if (args.some((arg) => arg === "-d" || arg === "--delete"))
|
|
17096
18204
|
return [];
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
18205
|
+
if (args.includes("--stdin"))
|
|
18206
|
+
return (stdin ?? "").split(/[\n\0]/u).map((line) => /^\s*(?:create|update)\s+(\S+)/u.exec(line)?.[1] ?? "").map(localHead).filter((name) => name !== null);
|
|
18207
|
+
const [ref] = positionalsOf(args, 1, new Set(["-m"]));
|
|
18208
|
+
const name = ref ? localHead(ref) : null;
|
|
18209
|
+
return name ? [name] : [];
|
|
18210
|
+
};
|
|
18211
|
+
var symbolicRefTarget = (args) => {
|
|
18212
|
+
if (args.some((arg) => arg === "-d" || arg === "--delete"))
|
|
18213
|
+
return null;
|
|
18214
|
+
const [, ref] = positionalsOf(args, 1, new Set(["-m"]));
|
|
18215
|
+
return ref ? localHead(ref) : null;
|
|
18216
|
+
};
|
|
18217
|
+
var FETCH_VALUES = new Set(["--depth", "--deepen", "--shallow-since", "--shallow-exclude", "--refmap", "-j", "--jobs"].concat(["--upload-pack", "-o", "--server-option", "--negotiation-tip", "--filter"]).concat(["--recurse-submodules-default", "--submodule-prefix", "-s", "--strategy", "-X"]).concat(["--strategy-option"]));
|
|
18218
|
+
var fetchTargets = (args, stdin) => {
|
|
18219
|
+
if (args.includes("--all") || args.includes("--multiple"))
|
|
18220
|
+
return [];
|
|
18221
|
+
const specs = args.includes("--stdin") ? (stdin ?? "").split(/\s+/u).filter(Boolean) : positionalsOf(args, 1, FETCH_VALUES).slice(1);
|
|
18222
|
+
const names = [];
|
|
18223
|
+
for (const raw of specs) {
|
|
18224
|
+
const colon = raw.indexOf(":");
|
|
18225
|
+
const destination = colon >= 0 ? raw.slice(colon + 1) : "";
|
|
18226
|
+
if (!destination || destination.includes("*"))
|
|
17100
18227
|
continue;
|
|
17101
|
-
const
|
|
17102
|
-
if (
|
|
17103
|
-
|
|
18228
|
+
const name = destination.startsWith("refs/") ? localHead(destination) : destination;
|
|
18229
|
+
if (name)
|
|
18230
|
+
names.push(name);
|
|
17104
18231
|
}
|
|
17105
|
-
return
|
|
18232
|
+
return names;
|
|
18233
|
+
};
|
|
18234
|
+
var localPushTargets = (args) => {
|
|
18235
|
+
const action = pushAction(args);
|
|
18236
|
+
if (action?.kind !== "push" || action.remote !== "." || action.deletes)
|
|
18237
|
+
return [];
|
|
18238
|
+
return action.targets.filter((name) => name !== null);
|
|
18239
|
+
};
|
|
18240
|
+
var gitBranchCreations = (args, stdin) => {
|
|
18241
|
+
const [sub, second] = args;
|
|
18242
|
+
const targets = sub === "switch" ? [flagValue(args, SWITCH_CREATE)] : sub === "checkout" ? [flagValue(args, CHECKOUT_CREATE)] : sub === "branch" ? [branchCommandTarget(args)] : sub === "worktree" && second === "add" ? [worktreeTarget(args.slice(1))] : sub === "stash" && second === "branch" ? positionalsOf(args, 2).slice(0, 1) : sub === "update-ref" ? updateRefTargets(args, stdin) : sub === "symbolic-ref" ? [symbolicRefTarget(args)] : sub === "fetch" || sub === "pull" ? fetchTargets(args, stdin) : sub === "push" ? localPushTargets(args) : sub === "subtree" && second === "split" ? [flagValue(args.slice(1), SUBTREE_CREATE)] : [];
|
|
18243
|
+
return targets.filter((target) => target !== null && target !== "" && !target.startsWith("-") && !UNKNOWABLE.test(target));
|
|
17106
18244
|
};
|
|
18245
|
+
var targetsOf = (invocations) => invocations.flatMap((invocation) => invocation.tool === "git" ? gitBranchCreations(invocation.args, invocation.stdin).map((branch) => ({
|
|
18246
|
+
branch,
|
|
18247
|
+
dir: invocation.dir
|
|
18248
|
+
})) : []);
|
|
17107
18249
|
var localBranchExists = (dir, branch) => spawnSync12("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], {
|
|
17108
18250
|
cwd: dir,
|
|
17109
18251
|
stdio: "ignore",
|
|
17110
18252
|
timeout: 5000
|
|
17111
18253
|
}).status === 0;
|
|
18254
|
+
var judgedDir = (root, dir) => {
|
|
18255
|
+
if (dir === undefined)
|
|
18256
|
+
return null;
|
|
18257
|
+
if (dir === null)
|
|
18258
|
+
return root;
|
|
18259
|
+
const resolved = path19.resolve(root, dir);
|
|
18260
|
+
return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
|
|
18261
|
+
};
|
|
17112
18262
|
var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
17113
18263
|
let judged = false;
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
const dir = target.dir === null ? root : path19.resolve(root, target.dir);
|
|
17118
|
-
if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
|
|
18264
|
+
const cache = new Map;
|
|
18265
|
+
for (const raw of rawInvocations(command, dialect)) {
|
|
18266
|
+
if (raw.tool !== "git" || judgedDir(root, raw.dir) === null)
|
|
17119
18267
|
continue;
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
|
|
17125
|
-
|
|
18268
|
+
for (const target of targetsOf(expandGitAliases(root, raw, cache))) {
|
|
18269
|
+
const dir = judgedDir(root, target.dir);
|
|
18270
|
+
if (dir === null || localBranchExists(dir, target.branch))
|
|
18271
|
+
continue;
|
|
18272
|
+
judged = true;
|
|
18273
|
+
const check = validateBranchNameFor(dir, target.branch);
|
|
18274
|
+
if (!check.ok)
|
|
18275
|
+
return check;
|
|
18276
|
+
}
|
|
17126
18277
|
}
|
|
17127
18278
|
return judged ? { ok: true } : null;
|
|
17128
18279
|
};
|
|
@@ -20449,7 +21600,14 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
|
|
|
20449
21600
|
};
|
|
20450
21601
|
// packages/workit-core/src/hooks/policy.ts
|
|
20451
21602
|
var shellPolicy = (cwd, command, dialect = "posix") => {
|
|
20452
|
-
|
|
21603
|
+
let policy;
|
|
21604
|
+
try {
|
|
21605
|
+
policy = shellBranchPolicyViolation(cwd, command, dialect);
|
|
21606
|
+
} catch (error) {
|
|
21607
|
+
if (error instanceof ShellAnalysisError)
|
|
21608
|
+
return analysisDenial(error);
|
|
21609
|
+
throw error;
|
|
21610
|
+
}
|
|
20453
21611
|
return policy && !policy.ok ? { kind: "deny", reason: `branch_policy_denied: ${policy.error}`, unblock: null } : { kind: "none" };
|
|
20454
21612
|
};
|
|
20455
21613
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
@@ -20478,11 +21636,11 @@ var exempt = (cwd, root, file, plans) => {
|
|
|
20478
21636
|
const segments = posix.split("/");
|
|
20479
21637
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
20480
21638
|
};
|
|
20481
|
-
var
|
|
21639
|
+
var PREFIXES2 = new Set(["sudo", "command", "env", "nohup", "time", "exec", "xargs"]);
|
|
20482
21640
|
var operands = (words) => words.filter((item) => !item.startsWith("-"));
|
|
20483
21641
|
var editsOf = (input) => {
|
|
20484
21642
|
let words = input;
|
|
20485
|
-
while (words.length && (
|
|
21643
|
+
while (words.length && (PREFIXES2.has(words[0]) || /^\w+=/.test(words[0])))
|
|
20486
21644
|
words = words.slice(1);
|
|
20487
21645
|
const [verb, ...args] = words;
|
|
20488
21646
|
const name = (verb?.split(/[\\/]/).at(-1) ?? "").toLowerCase();
|