@brainervirus/workit-opencode 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/assets/skills/workit-ship/SKILL.md +20 -20
- package/assets/skills/workit-ship/references/release.md +26 -0
- package/dist/plugin.js +1367 -209
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -12965,6 +12965,15 @@ var repoBranchPreset = (workspaceRoot) => {
|
|
|
12965
12965
|
const detected = detectBranchPolicy(workspaceRoot);
|
|
12966
12966
|
return detected.developBranch || detected.allowed.length ? detected.preset : null;
|
|
12967
12967
|
};
|
|
12968
|
+
var releaseTagPrefixOf = (workspaceRoot, policyPrefix) => {
|
|
12969
|
+
if (typeof policyPrefix === "string")
|
|
12970
|
+
return policyPrefix.trim();
|
|
12971
|
+
const r = spawnSync5("git", ["config", "--get", "gitflow.prefix.versiontag"], {
|
|
12972
|
+
cwd: workspaceRoot,
|
|
12973
|
+
encoding: "utf8"
|
|
12974
|
+
});
|
|
12975
|
+
return r.status === 0 ? (r.stdout ?? "").trim() : "v";
|
|
12976
|
+
};
|
|
12968
12977
|
|
|
12969
12978
|
// packages/workit-core/src/core/workspaces.ts
|
|
12970
12979
|
var nonBlank = string2().refine((value) => value.trim().length > 0, "must not be blank");
|
|
@@ -15722,11 +15731,11 @@ what and whether, the CLI does how and records what it observed.
|
|
|
15722
15731
|
Native host allow/ask/deny, sandbox and org rules stay authoritative. Never
|
|
15723
15732
|
switch paths to evade a denial, never claim enforcement a host cannot provide,
|
|
15724
15733
|
and never fabricate an approval or verdict. A question answer is not
|
|
15725
|
-
host permission, and imported decisions or handoffs
|
|
15734
|
+
host permission, and imported decisions or handoffs grant no authority.
|
|
15726
15735
|
|
|
15727
15736
|
Autonomy contract:
|
|
15728
15737
|
- Continue to the requested endpoint (commit, push, PR, green CI, verified,
|
|
15729
|
-
merged) without asking "continue?", running checks and repairs
|
|
15738
|
+
merged) without asking "continue?", running checks and repairs.
|
|
15730
15739
|
Stop only for a new consequential choice, a host denial, a conflicting edit
|
|
15731
15740
|
or an unresolved blocker; report open gaps and uncertain workers.
|
|
15732
15741
|
- No endpoint named: stop at a local commit on a policy-compliant branch and
|
|
@@ -15736,7 +15745,8 @@ Autonomy contract:
|
|
|
15736
15745
|
never merging; \`merged\` also lands it with \`workit pr merge\`.
|
|
15737
15746
|
Merge and release need a workspace grant only the user raises from their
|
|
15738
15747
|
own terminal (a blocked verb names how); never edit workspaces.json or route
|
|
15739
|
-
around
|
|
15748
|
+
around grant_required. Release: \`workit release start <v>\`, commits,
|
|
15749
|
+
\`finish\`; \`publish\` if asked.
|
|
15740
15750
|
- Ask only for a product or preference choice, or for authority you lack, with
|
|
15741
15751
|
your recommended answer. Facts are yours: read, run or prototype.
|
|
15742
15752
|
- Label claims measured (run and seen this session), inferred, or guess.
|
|
@@ -15751,22 +15761,22 @@ Autonomy contract:
|
|
|
15751
15761
|
reconcile every requested item and observe it (\`workit verify-delivery\`).
|
|
15752
15762
|
|
|
15753
15763
|
CLI first: if a step has one right answer, use the \`workit\` verb instead of
|
|
15754
|
-
hand-running git, gh or glab (\`workit git|pr|ci|check\`;
|
|
15755
|
-
|
|
15764
|
+
hand-running git, gh or glab (\`workit git|pr|ci|check|help\`;
|
|
15765
|
+
else \`npx -y @brainervirus/workit-cli\`).
|
|
15756
15766
|
Add Co-Authored-By via \`workit git commit --trailer "K: v" -- <paths>\`, never
|
|
15757
15767
|
an amend.
|
|
15758
15768
|
The task families (task, policy, evidence, finding, decision, worker, state)
|
|
15759
15769
|
are optional continuity for tracked work; each branch has one implicit task,
|
|
15760
|
-
and a solo edit needs no task. A decision
|
|
15761
|
-
|
|
15770
|
+
and a solo edit needs no task. A decision records a user choice; it never
|
|
15771
|
+
authorizes an effect. Judge work once with
|
|
15762
15772
|
\`workit policy assess --judge risk= behavior= product-choice= plan=\`.
|
|
15763
|
-
Across repositories, bind
|
|
15764
|
-
|
|
15765
|
-
external effect before
|
|
15773
|
+
Across repositories, bind items to checkout, branch and endpoint, resolve
|
|
15774
|
+
competing targets before a mutation, and reconcile an uncertain
|
|
15775
|
+
external effect before a retry.
|
|
15766
15776
|
|
|
15767
15777
|
Mid-task: never silently drop or resume an objective (workit-continue).
|
|
15768
15778
|
|
|
15769
|
-
Skills: load the skill, never act from memory
|
|
15779
|
+
Skills: load the skill, never act from memory (aliases /wk-<name>).
|
|
15770
15780
|
- brainstorm, plan, spec, grill, should we: workit-shape
|
|
15771
15781
|
- implement, build, add a feature: workit-implement
|
|
15772
15782
|
- review, blast radius: workit-review
|
|
@@ -16195,7 +16205,76 @@ var writeSessionMarker = (file, marker) => {
|
|
|
16195
16205
|
};
|
|
16196
16206
|
|
|
16197
16207
|
// packages/workit-core/src/hooks/shell-words.ts
|
|
16198
|
-
|
|
16208
|
+
class ShellAnalysisError extends Error {
|
|
16209
|
+
}
|
|
16210
|
+
var MAX_NESTING = 64;
|
|
16211
|
+
var OPEN = "";
|
|
16212
|
+
var COMMA = "";
|
|
16213
|
+
var CLOSE = "";
|
|
16214
|
+
var MARKERS = /[\uE000-\uE002]/u;
|
|
16215
|
+
var literal2 = (word) => word.replaceAll(OPEN, "{").replaceAll(COMMA, ",").replaceAll(CLOSE, "}");
|
|
16216
|
+
var BRACE_LIMIT = 64;
|
|
16217
|
+
var BRACE_PENDING = 512;
|
|
16218
|
+
var BRACE_DEPTH = 16;
|
|
16219
|
+
var braceGroup = (word) => {
|
|
16220
|
+
for (let start = 0;start < word.length; start++) {
|
|
16221
|
+
if (word[start] !== OPEN)
|
|
16222
|
+
continue;
|
|
16223
|
+
let depth = 0;
|
|
16224
|
+
let end = start;
|
|
16225
|
+
const commas = [];
|
|
16226
|
+
for (;end < word.length; end++) {
|
|
16227
|
+
if (word[end] === OPEN)
|
|
16228
|
+
depth++;
|
|
16229
|
+
else if (word[end] === CLOSE && --depth === 0)
|
|
16230
|
+
break;
|
|
16231
|
+
else if (word[end] === COMMA && depth === 1)
|
|
16232
|
+
commas.push(end);
|
|
16233
|
+
}
|
|
16234
|
+
if (end < word.length && commas.length)
|
|
16235
|
+
return { start, end, commas };
|
|
16236
|
+
}
|
|
16237
|
+
return null;
|
|
16238
|
+
};
|
|
16239
|
+
var expandBraces = (word) => {
|
|
16240
|
+
let depth = 0;
|
|
16241
|
+
for (const char of word) {
|
|
16242
|
+
if (char === OPEN && ++depth > BRACE_DEPTH)
|
|
16243
|
+
return [literal2(word)];
|
|
16244
|
+
if (char === CLOSE && depth > 0)
|
|
16245
|
+
depth--;
|
|
16246
|
+
}
|
|
16247
|
+
const done = new Set;
|
|
16248
|
+
const queue = [word];
|
|
16249
|
+
const queued = new Set(queue);
|
|
16250
|
+
for (let at = 0;at < queue.length; at++) {
|
|
16251
|
+
const current = queue[at];
|
|
16252
|
+
const group = braceGroup(current);
|
|
16253
|
+
if (!group) {
|
|
16254
|
+
const text = literal2(current);
|
|
16255
|
+
if (text)
|
|
16256
|
+
done.add(text);
|
|
16257
|
+
if (done.size > BRACE_LIMIT)
|
|
16258
|
+
return [literal2(word)];
|
|
16259
|
+
continue;
|
|
16260
|
+
}
|
|
16261
|
+
const pre = current.slice(0, group.start);
|
|
16262
|
+
const post = current.slice(group.end + 1);
|
|
16263
|
+
let from = group.start + 1;
|
|
16264
|
+
for (const comma of [...group.commas, group.end]) {
|
|
16265
|
+
const next = pre + current.slice(from, comma) + post;
|
|
16266
|
+
from = comma + 1;
|
|
16267
|
+
if (queued.has(next))
|
|
16268
|
+
continue;
|
|
16269
|
+
queued.add(next);
|
|
16270
|
+
queue.push(next);
|
|
16271
|
+
}
|
|
16272
|
+
if (queue.length - at > BRACE_PENDING)
|
|
16273
|
+
return [literal2(word)];
|
|
16274
|
+
}
|
|
16275
|
+
return [...done];
|
|
16276
|
+
};
|
|
16277
|
+
var closingQuote = (command, start, dialect, nesting = 0) => {
|
|
16199
16278
|
const quote = command[start];
|
|
16200
16279
|
for (let index = start + 1;index < command.length; index++) {
|
|
16201
16280
|
const char = command[index];
|
|
@@ -16212,51 +16291,265 @@ var closingQuote = (command, start, dialect) => {
|
|
|
16212
16291
|
index++;
|
|
16213
16292
|
continue;
|
|
16214
16293
|
}
|
|
16294
|
+
if (dialect === "posix" && char === "$" && command[index + 1] === "(") {
|
|
16295
|
+
index = substitutionEnd(command, index + 1, nesting + 1);
|
|
16296
|
+
continue;
|
|
16297
|
+
}
|
|
16298
|
+
if (dialect === "posix" && char === "`") {
|
|
16299
|
+
index = backtickEnd(command, index);
|
|
16300
|
+
continue;
|
|
16301
|
+
}
|
|
16215
16302
|
if (char === '"')
|
|
16216
16303
|
return index;
|
|
16217
16304
|
}
|
|
16218
16305
|
return -1;
|
|
16219
16306
|
};
|
|
16307
|
+
var backtickEnd = (command, start) => {
|
|
16308
|
+
for (let index = start + 1;index < command.length; index++) {
|
|
16309
|
+
if (command[index] === "\\")
|
|
16310
|
+
index++;
|
|
16311
|
+
else if (command[index] === "`")
|
|
16312
|
+
return index;
|
|
16313
|
+
}
|
|
16314
|
+
return command.length;
|
|
16315
|
+
};
|
|
16316
|
+
var heredocDelimiter = (command, start) => {
|
|
16317
|
+
let index = start;
|
|
16318
|
+
if (command[index] === "-")
|
|
16319
|
+
index++;
|
|
16320
|
+
while (command[index] === " " || command[index] === "\t")
|
|
16321
|
+
index++;
|
|
16322
|
+
let delimiter = "";
|
|
16323
|
+
for (;index < command.length && !/[\s;&|<>()]/.test(command[index]); index++) {
|
|
16324
|
+
const char = command[index];
|
|
16325
|
+
if (char === "'" || char === '"') {
|
|
16326
|
+
const end = command.indexOf(char, index + 1);
|
|
16327
|
+
if (end < 0)
|
|
16328
|
+
break;
|
|
16329
|
+
delimiter += command.slice(index + 1, end);
|
|
16330
|
+
index = end;
|
|
16331
|
+
} else if (char === "\\")
|
|
16332
|
+
delimiter += command[++index] ?? "";
|
|
16333
|
+
else
|
|
16334
|
+
delimiter += char;
|
|
16335
|
+
}
|
|
16336
|
+
return { delimiter, end: index - 1 };
|
|
16337
|
+
};
|
|
16338
|
+
var skipHeredocs = (command, newline, delimiters) => {
|
|
16339
|
+
let index = newline;
|
|
16340
|
+
while (delimiters.length) {
|
|
16341
|
+
const delimiter = delimiters.shift();
|
|
16342
|
+
for (;; ) {
|
|
16343
|
+
const lineEnd = command.indexOf(`
|
|
16344
|
+
`, index + 1);
|
|
16345
|
+
const line = command.slice(index + 1, lineEnd < 0 ? undefined : lineEnd);
|
|
16346
|
+
index = lineEnd < 0 ? command.length : lineEnd;
|
|
16347
|
+
if (line.trim() === delimiter || lineEnd < 0)
|
|
16348
|
+
break;
|
|
16349
|
+
}
|
|
16350
|
+
}
|
|
16351
|
+
return index;
|
|
16352
|
+
};
|
|
16353
|
+
var substitutionEnd = (command, start, nesting = 0) => {
|
|
16354
|
+
if (nesting > MAX_NESTING)
|
|
16355
|
+
throw new ShellAnalysisError("substitutions nest too deep");
|
|
16356
|
+
let depth = 0;
|
|
16357
|
+
let wordStart = true;
|
|
16358
|
+
const heredocs = [];
|
|
16359
|
+
for (let index = start;index < command.length; index++) {
|
|
16360
|
+
const char = command[index];
|
|
16361
|
+
const atWordStart = wordStart;
|
|
16362
|
+
wordStart = /[\s;&|()]/.test(char);
|
|
16363
|
+
if (char === "\\")
|
|
16364
|
+
index++;
|
|
16365
|
+
else if (char === `
|
|
16366
|
+
` && heredocs.length) {
|
|
16367
|
+
index = skipHeredocs(command, index, heredocs);
|
|
16368
|
+
wordStart = true;
|
|
16369
|
+
} else if (char === "'" || char === '"') {
|
|
16370
|
+
const end = closingQuote(command, index, "posix", nesting);
|
|
16371
|
+
if (end < 0)
|
|
16372
|
+
return command.length;
|
|
16373
|
+
index = end;
|
|
16374
|
+
} else if (char === "`")
|
|
16375
|
+
index = backtickEnd(command, index);
|
|
16376
|
+
else if (char === "#" && atWordStart) {
|
|
16377
|
+
const newline = command.indexOf(`
|
|
16378
|
+
`, index);
|
|
16379
|
+
index = newline < 0 ? command.length : newline - 1;
|
|
16380
|
+
} else if (char === "<" && command[index + 1] === "<" && command[index + 2] !== "<") {
|
|
16381
|
+
const { delimiter, end } = heredocDelimiter(command, index + 2);
|
|
16382
|
+
if (delimiter)
|
|
16383
|
+
heredocs.push(delimiter);
|
|
16384
|
+
index = end;
|
|
16385
|
+
} else if (char === "<" && command[index + 1] === "<")
|
|
16386
|
+
index += 2;
|
|
16387
|
+
else if (char === "$" && command[index + 1] === "(")
|
|
16388
|
+
index = substitutionEnd(command, index + 1, nesting + 1);
|
|
16389
|
+
else if (char === "(")
|
|
16390
|
+
depth++;
|
|
16391
|
+
else if (char === ")" && --depth === 0)
|
|
16392
|
+
return index;
|
|
16393
|
+
}
|
|
16394
|
+
return command.length;
|
|
16395
|
+
};
|
|
16220
16396
|
var unquote = (body, quote, dialect) => {
|
|
16221
16397
|
if (quote === "'")
|
|
16222
16398
|
return dialect === "powershell" ? body.replaceAll("''", "'") : body;
|
|
16223
|
-
return dialect === "posix" ? body.replace(/\\(["\\$`])/g, "$1") : body.replace(/`(.)/g, "$1");
|
|
16399
|
+
return dialect === "posix" ? body.replace(/\\\n/g, "").replace(/\\(["\\$`])/g, "$1") : body.replace(/`(.)/g, "$1");
|
|
16400
|
+
};
|
|
16401
|
+
var C_ESCAPES = {
|
|
16402
|
+
n: `
|
|
16403
|
+
`,
|
|
16404
|
+
t: "\t",
|
|
16405
|
+
r: "\r",
|
|
16406
|
+
a: "\x07",
|
|
16407
|
+
b: "\b",
|
|
16408
|
+
e: "\x1B",
|
|
16409
|
+
E: "\x1B",
|
|
16410
|
+
f: "\f",
|
|
16411
|
+
v: "\v"
|
|
16412
|
+
};
|
|
16413
|
+
var ansiC = (command, start) => {
|
|
16414
|
+
let text = "";
|
|
16415
|
+
let index = start + 1;
|
|
16416
|
+
for (;index < command.length && command[index] !== "'"; index++) {
|
|
16417
|
+
const char = command[index];
|
|
16418
|
+
if (char !== "\\" || index + 1 >= command.length) {
|
|
16419
|
+
text += char;
|
|
16420
|
+
continue;
|
|
16421
|
+
}
|
|
16422
|
+
const rest = command.slice(++index);
|
|
16423
|
+
const hex = /^x([0-9a-fA-F]{1,2})/.exec(rest);
|
|
16424
|
+
const octal = /^[0-7]{1,3}/.exec(rest);
|
|
16425
|
+
if (hex) {
|
|
16426
|
+
text += String.fromCharCode(Number.parseInt(hex[1], 16));
|
|
16427
|
+
index += hex[0].length - 1;
|
|
16428
|
+
} else if (octal) {
|
|
16429
|
+
text += String.fromCharCode(Number.parseInt(octal[0], 8));
|
|
16430
|
+
index += octal[0].length - 1;
|
|
16431
|
+
} else
|
|
16432
|
+
text += C_ESCAPES[rest[0]] ?? rest[0];
|
|
16433
|
+
}
|
|
16434
|
+
return { text, end: index };
|
|
16435
|
+
};
|
|
16436
|
+
var substitutions = (body) => {
|
|
16437
|
+
const found = [];
|
|
16438
|
+
for (let index = 0;index < body.length; index++) {
|
|
16439
|
+
const char = body[index];
|
|
16440
|
+
if (char === "\\")
|
|
16441
|
+
index++;
|
|
16442
|
+
else if (char === "`") {
|
|
16443
|
+
const end = backtickEnd(body, index);
|
|
16444
|
+
found.push(body.slice(index + 1, end).replace(/\\(.)/g, "$1"));
|
|
16445
|
+
index = end;
|
|
16446
|
+
} else if (char === "$" && body[index + 1] === "(") {
|
|
16447
|
+
const end = substitutionEnd(body, index + 1);
|
|
16448
|
+
found.push(body.slice(index + 2, end));
|
|
16449
|
+
index = end;
|
|
16450
|
+
}
|
|
16451
|
+
}
|
|
16452
|
+
return found;
|
|
16453
|
+
};
|
|
16454
|
+
var PLAIN_POSIX = /[^\s'"\\`$(){},<>|;&#]+/uy;
|
|
16455
|
+
var PLAIN_POWERSHELL = /[^\s'"`(){}<>|;&#]+/uy;
|
|
16456
|
+
var arithmeticEnd = (command, start) => {
|
|
16457
|
+
const end = substitutionEnd(command, start);
|
|
16458
|
+
return command[end - 1] === ")" && end > start + 2 ? end : 0;
|
|
16224
16459
|
};
|
|
16225
16460
|
var segmentsOf = (command, dialect = "posix") => {
|
|
16461
|
+
try {
|
|
16462
|
+
return tokenize(command, dialect);
|
|
16463
|
+
} catch (error) {
|
|
16464
|
+
const why = error instanceof ShellAnalysisError ? error.message : String(error);
|
|
16465
|
+
return [{ words: [], redirects: [], unanalyzable: why }];
|
|
16466
|
+
}
|
|
16467
|
+
};
|
|
16468
|
+
var tokenize = (command, dialect) => {
|
|
16469
|
+
const posix = dialect === "posix";
|
|
16226
16470
|
const segments = [];
|
|
16227
16471
|
let current = { words: [], redirects: [] };
|
|
16228
16472
|
let word = "";
|
|
16229
16473
|
let inWord = false;
|
|
16230
16474
|
let pending = null;
|
|
16231
16475
|
const heredocs = [];
|
|
16232
|
-
const escape =
|
|
16476
|
+
const escape = posix ? "\\" : "`";
|
|
16233
16477
|
const flushWord = () => {
|
|
16234
16478
|
if (!inWord)
|
|
16235
16479
|
return;
|
|
16480
|
+
const text = MARKERS.test(word) ? literal2(word) : word;
|
|
16236
16481
|
if (pending === "redirect") {
|
|
16237
|
-
if (!
|
|
16238
|
-
current.redirects.push(
|
|
16482
|
+
if (!text.startsWith("&"))
|
|
16483
|
+
current.redirects.push(text);
|
|
16239
16484
|
} else if (pending === "heredoc")
|
|
16240
|
-
heredocs.push(
|
|
16485
|
+
heredocs.push({ delimiter: text.replace(/^-/, ""), owner: current });
|
|
16486
|
+
else if (pending === "herestring")
|
|
16487
|
+
(current.stdin ??= []).push(text);
|
|
16241
16488
|
else if (pending !== "input")
|
|
16242
|
-
current.words.push(word);
|
|
16489
|
+
current.words.push(...MARKERS.test(word) ? expandBraces(word) : [word]);
|
|
16243
16490
|
pending = null;
|
|
16244
16491
|
word = "";
|
|
16245
16492
|
inWord = false;
|
|
16246
16493
|
};
|
|
16247
16494
|
const flushSegment = () => {
|
|
16248
16495
|
flushWord();
|
|
16249
|
-
if (current.words.length || current.redirects.length)
|
|
16496
|
+
if (current.words.length || current.redirects.length || current.stdin || current.subs)
|
|
16250
16497
|
segments.push(current);
|
|
16251
16498
|
current = { words: [], redirects: [] };
|
|
16252
16499
|
};
|
|
16500
|
+
const group = (kind) => {
|
|
16501
|
+
flushSegment();
|
|
16502
|
+
pending = null;
|
|
16503
|
+
segments.push({ words: [], redirects: [], group: kind });
|
|
16504
|
+
};
|
|
16505
|
+
const substitution = (inner, text) => {
|
|
16506
|
+
(current.subs ??= []).push(inner);
|
|
16507
|
+
word += text;
|
|
16508
|
+
inWord = true;
|
|
16509
|
+
};
|
|
16510
|
+
const plain = posix ? PLAIN_POSIX : PLAIN_POWERSHELL;
|
|
16253
16511
|
for (let index = 0;index < command.length; index++) {
|
|
16512
|
+
plain.lastIndex = index;
|
|
16513
|
+
const run = plain.exec(command);
|
|
16514
|
+
if (run) {
|
|
16515
|
+
word += run[0];
|
|
16516
|
+
inWord = true;
|
|
16517
|
+
index += run[0].length - 1;
|
|
16518
|
+
continue;
|
|
16519
|
+
}
|
|
16254
16520
|
const char = command[index];
|
|
16255
|
-
|
|
16521
|
+
const next = command[index + 1];
|
|
16522
|
+
if (char === escape && (next === `
|
|
16523
|
+
` || next === "\r" && command[index + 2] === `
|
|
16524
|
+
`))
|
|
16525
|
+
index += next === "\r" ? 2 : 1;
|
|
16526
|
+
else if (char === "#" && !inWord) {
|
|
16527
|
+
const newline = command.indexOf(`
|
|
16528
|
+
`, index);
|
|
16529
|
+
index = (newline < 0 ? command.length : newline) - 1;
|
|
16530
|
+
} else if (!posix && char === "<" && next === "#") {
|
|
16531
|
+
const end = command.indexOf("#>", index + 2);
|
|
16532
|
+
index = end < 0 ? command.length : end + 1;
|
|
16533
|
+
} else if (posix && char === "$" && next === "'") {
|
|
16534
|
+
const { text, end } = ansiC(command, index + 1);
|
|
16535
|
+
word += text;
|
|
16536
|
+
inWord = true;
|
|
16537
|
+
index = end;
|
|
16538
|
+
} else if (posix && char === "$" && next === '"')
|
|
16539
|
+
continue;
|
|
16540
|
+
else if (char === "'" || char === '"') {
|
|
16256
16541
|
const end = closingQuote(command, index, dialect);
|
|
16257
|
-
|
|
16542
|
+
const body = command.slice(index + 1, end < 0 ? undefined : end);
|
|
16543
|
+
if (posix && char === '"' && /\$\(|`/.test(body))
|
|
16544
|
+
(current.subs ??= []).push(...substitutions(body));
|
|
16545
|
+
word += unquote(body, char, dialect);
|
|
16258
16546
|
inWord = true;
|
|
16259
16547
|
index = end < 0 ? command.length : end;
|
|
16548
|
+
} else if (posix && char === "`") {
|
|
16549
|
+
const end = backtickEnd(command, index);
|
|
16550
|
+
const inner = command.slice(index + 1, end);
|
|
16551
|
+
substitution(inner.replace(/\\(.)/g, "$1"), `\`${inner}\``);
|
|
16552
|
+
index = end;
|
|
16260
16553
|
} else if (char === escape && index + 1 < command.length) {
|
|
16261
16554
|
word += command[++index];
|
|
16262
16555
|
inWord = true;
|
|
@@ -16264,26 +16557,56 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
16264
16557
|
`) {
|
|
16265
16558
|
flushSegment();
|
|
16266
16559
|
while (heredocs.length) {
|
|
16267
|
-
const delimiter = heredocs.shift();
|
|
16560
|
+
const { delimiter, owner } = heredocs.shift();
|
|
16268
16561
|
const lines = command.slice(index + 1).split(`
|
|
16269
16562
|
`);
|
|
16270
16563
|
const at = lines.findIndex((line) => line.trim() === delimiter);
|
|
16271
|
-
|
|
16564
|
+
(owner.stdin ??= []).push((at < 0 ? lines : lines.slice(0, at)).join(`
|
|
16565
|
+
`));
|
|
16566
|
+
index += (at < 0 ? lines : lines.slice(0, at + 1)).join(`
|
|
16272
16567
|
`).length + 1;
|
|
16273
|
-
index += skipped;
|
|
16274
16568
|
}
|
|
16275
16569
|
} else if (/\s/.test(char))
|
|
16276
16570
|
flushWord();
|
|
16277
|
-
else if (char === "("
|
|
16571
|
+
else if (posix && char === "(" && inWord && word.endsWith("$")) {
|
|
16572
|
+
const end = substitutionEnd(command, index);
|
|
16573
|
+
const inner = command.slice(index + 1, end);
|
|
16574
|
+
substitution(inner, `(${inner})`);
|
|
16575
|
+
index = end;
|
|
16576
|
+
} else if (posix && char === "(" && (pending === "input" || pending === "redirect")) {
|
|
16577
|
+
const sign = pending === "input" ? "<" : ">";
|
|
16578
|
+
pending = null;
|
|
16579
|
+
const end = substitutionEnd(command, index);
|
|
16580
|
+
const inner = command.slice(index + 1, end);
|
|
16581
|
+
substitution(inner, `${sign}(${inner})`);
|
|
16582
|
+
index = end;
|
|
16583
|
+
} else if (posix && char === "(" && next === "(" && !inWord && arithmeticEnd(command, index)) {
|
|
16584
|
+
flushSegment();
|
|
16585
|
+
index = arithmeticEnd(command, index);
|
|
16586
|
+
} else if (char === "(" || char === ")") {
|
|
16278
16587
|
if (char === "(" && inWord && word.endsWith("$")) {
|
|
16279
16588
|
word = word.slice(0, -1);
|
|
16280
16589
|
inWord = word !== "";
|
|
16281
16590
|
}
|
|
16591
|
+
group(char === "(" ? "open" : "close");
|
|
16592
|
+
} else if (!posix && (char === "{" || char === "}")) {
|
|
16593
|
+
if (char === "{" && inWord && word.endsWith("@")) {
|
|
16594
|
+
word += char;
|
|
16595
|
+
continue;
|
|
16596
|
+
}
|
|
16282
16597
|
flushSegment();
|
|
16283
|
-
segments.push({ words: [], redirects: [], group: char === "(" ? "open" : "close" });
|
|
16284
16598
|
} else if (";&|".includes(char)) {
|
|
16285
|
-
if (char === "&" &&
|
|
16599
|
+
if (char === "&" && next === ">")
|
|
16286
16600
|
continue;
|
|
16601
|
+
if (char === "|" && next === "|")
|
|
16602
|
+
index++;
|
|
16603
|
+
else if (char === "|") {
|
|
16604
|
+
flushWord();
|
|
16605
|
+
if (current.words.length)
|
|
16606
|
+
current.pipe = true;
|
|
16607
|
+
if (next === "&")
|
|
16608
|
+
index++;
|
|
16609
|
+
}
|
|
16287
16610
|
flushSegment();
|
|
16288
16611
|
} else if (char === ">") {
|
|
16289
16612
|
if (inWord && /^\d$/.test(word)) {
|
|
@@ -16299,16 +16622,24 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
16299
16622
|
inWord = true;
|
|
16300
16623
|
}
|
|
16301
16624
|
pending = "redirect";
|
|
16302
|
-
} else if (char === "<" &&
|
|
16625
|
+
} else if (char === "<" && posix) {
|
|
16303
16626
|
flushWord();
|
|
16304
|
-
if (command[index +
|
|
16627
|
+
if (next === "<" && command[index + 2] === "<") {
|
|
16628
|
+
index += 2;
|
|
16629
|
+
pending = "herestring";
|
|
16630
|
+
} else if (next === "<") {
|
|
16305
16631
|
index++;
|
|
16306
|
-
if (command[index + 1] === "<")
|
|
16307
|
-
index++;
|
|
16308
16632
|
pending = "heredoc";
|
|
16309
16633
|
} else
|
|
16310
16634
|
pending = "input";
|
|
16311
|
-
} else {
|
|
16635
|
+
} else if (posix && char === "{" && !word.endsWith("$")) {
|
|
16636
|
+
word += OPEN;
|
|
16637
|
+
inWord = true;
|
|
16638
|
+
} else if (posix && char === "," && word.includes(OPEN))
|
|
16639
|
+
word += COMMA;
|
|
16640
|
+
else if (posix && char === "}" && word.includes(OPEN))
|
|
16641
|
+
word += CLOSE;
|
|
16642
|
+
else {
|
|
16312
16643
|
word += char;
|
|
16313
16644
|
inWord = true;
|
|
16314
16645
|
}
|
|
@@ -16319,8 +16650,35 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
16319
16650
|
|
|
16320
16651
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
16321
16652
|
var NONE2 = { kind: "none" };
|
|
16322
|
-
var SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
16323
|
-
var
|
|
16653
|
+
var SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh", "ash", "mksh", "yash", "fish"]);
|
|
16654
|
+
var POWERSHELLS = new Set(["pwsh", "powershell"]);
|
|
16655
|
+
var EVALS = new Set(["eval", "iex", "invoke-expression"]);
|
|
16656
|
+
var WRAPPERS = {
|
|
16657
|
+
sudo: { values: "-u -g -h -p -C -D -R -T -r -t -U --user --group --host --prompt --chdir" },
|
|
16658
|
+
doas: { values: "-u -C" },
|
|
16659
|
+
command: { values: "" },
|
|
16660
|
+
builtin: { values: "" },
|
|
16661
|
+
env: { values: "-u -C --unset --chdir" },
|
|
16662
|
+
nohup: { values: "" },
|
|
16663
|
+
setsid: { values: "" },
|
|
16664
|
+
time: { values: "-f -o --format --output" },
|
|
16665
|
+
exec: { values: "-a" },
|
|
16666
|
+
nice: { values: "-n --adjustment" },
|
|
16667
|
+
ionice: { values: "-c -n -p --class --classdata" },
|
|
16668
|
+
stdbuf: { values: "-i -o -e --input --output --error" },
|
|
16669
|
+
chronic: { values: "" },
|
|
16670
|
+
unbuffer: { values: "" },
|
|
16671
|
+
wsl: { values: "-d -u --cd --distribution --user" },
|
|
16672
|
+
timeout: { values: "-s -k --signal --kill-after", operands: 1 },
|
|
16673
|
+
flock: { values: "-w -E --timeout --conflict-exit-code", operands: 1 },
|
|
16674
|
+
coproc: { values: "" },
|
|
16675
|
+
taskset: { values: "", operands: 1 },
|
|
16676
|
+
watch: { values: "-n -d --interval --differences -q --equexit" },
|
|
16677
|
+
"&": { values: "" }
|
|
16678
|
+
};
|
|
16679
|
+
var WRAPPER_VALUES = new Map(Object.entries(WRAPPERS).map(([name, wrapper]) => [name, new Set(wrapper.values.split(" "))]));
|
|
16680
|
+
var KEYWORDS = new Set(["if", "then", "else", "elif", "while", "until", "do", "!", "{"]);
|
|
16681
|
+
var DECLARATIONS = new Set(["export", "local", "declare", "readonly", "typeset"]);
|
|
16324
16682
|
var SCRIPT_FLAG = /^-[a-zA-Z]*c[a-zA-Z]*$/;
|
|
16325
16683
|
var CD = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
16326
16684
|
var PUSHD = new Set(["pushd", "push-location"]);
|
|
@@ -16334,13 +16692,21 @@ var GIT_VALUE_OPTIONS = new Set([
|
|
|
16334
16692
|
"--config-env",
|
|
16335
16693
|
"--super-prefix"
|
|
16336
16694
|
]);
|
|
16695
|
+
var GIT_CONFIG_OPTIONS = new Set(["-c", "--config-env", "--git-dir"]);
|
|
16696
|
+
var GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
|
|
16697
|
+
var ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
|
|
16698
|
+
var MAX_DEPTH = 4;
|
|
16699
|
+
var MAX_EXPANSIONS = 16;
|
|
16337
16700
|
var isAbsolute = (value) => path16.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
16338
|
-
var
|
|
16701
|
+
var HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
|
|
16702
|
+
var joinDir = (base, raw) => {
|
|
16703
|
+
const next = raw.replace(HERE, ".");
|
|
16339
16704
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
16340
16705
|
return;
|
|
16341
16706
|
const expanded = next === "~" || next.startsWith("~/") ? path16.join(os4.homedir(), next.slice(1)) : next;
|
|
16342
16707
|
return base === null || isAbsolute(expanded) ? expanded : path16.join(base, expanded);
|
|
16343
16708
|
};
|
|
16709
|
+
var rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner);
|
|
16344
16710
|
var cdTarget = (words) => {
|
|
16345
16711
|
const args = words.slice(1);
|
|
16346
16712
|
const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
|
|
@@ -16350,88 +16716,433 @@ var cdTarget = (words) => {
|
|
|
16350
16716
|
};
|
|
16351
16717
|
var stripPrefixes = (input) => {
|
|
16352
16718
|
let words = input;
|
|
16719
|
+
const env = {};
|
|
16353
16720
|
for (;; ) {
|
|
16354
16721
|
const first = words[0];
|
|
16355
16722
|
if (first === undefined)
|
|
16356
|
-
return words;
|
|
16357
|
-
|
|
16723
|
+
return { words, env };
|
|
16724
|
+
const assignment = ASSIGNMENT.exec(first);
|
|
16725
|
+
if (assignment) {
|
|
16726
|
+
if (GIT_CONFIG_ENV.test(assignment[1]))
|
|
16727
|
+
env[assignment[1]] = assignment[2];
|
|
16358
16728
|
words = words.slice(1);
|
|
16359
|
-
else if (
|
|
16729
|
+
} else if (KEYWORDS.has(first))
|
|
16360
16730
|
words = words.slice(1);
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
|
|
16731
|
+
else if (first === "function")
|
|
16732
|
+
words = words.slice(2);
|
|
16733
|
+
else if (Object.hasOwn(WRAPPERS, commandName(first))) {
|
|
16734
|
+
const name = commandName(first);
|
|
16735
|
+
const values = WRAPPER_VALUES.get(name);
|
|
16364
16736
|
words = words.slice(1);
|
|
16365
|
-
|
|
16737
|
+
const takesValue = (option) => values.has(option) || /^-[a-zA-Z]{2,}$/.test(option) && values.has(`-${option.at(-1)}`);
|
|
16738
|
+
while (words[0]?.startsWith("-") && words[0] !== "--")
|
|
16739
|
+
words = words.slice(takesValue(words[0]) ? 2 : 1);
|
|
16740
|
+
if (words[0] === "--")
|
|
16366
16741
|
words = words.slice(1);
|
|
16367
|
-
words = words.slice(
|
|
16742
|
+
words = words.slice(WRAPPERS[name].operands ?? 0);
|
|
16368
16743
|
} else
|
|
16369
|
-
return words;
|
|
16744
|
+
return { words, env };
|
|
16370
16745
|
}
|
|
16371
16746
|
};
|
|
16372
16747
|
var commandName = (word) => (word?.split(/[\\/]/).at(-1) ?? "").toLowerCase().replace(/\.exe$/, "");
|
|
16748
|
+
var VARIABLE = /\$(?:\{(\w+)\}|(\w+))/g;
|
|
16749
|
+
var expandWord = (word, vars) => {
|
|
16750
|
+
if (!word.includes("$"))
|
|
16751
|
+
return [word];
|
|
16752
|
+
let results = [""];
|
|
16753
|
+
let last = 0;
|
|
16754
|
+
for (const match of word.matchAll(VARIABLE)) {
|
|
16755
|
+
const values = vars.get(match[1] ?? match[2]) ?? [match[0]];
|
|
16756
|
+
const before = word.slice(last, match.index);
|
|
16757
|
+
results = results.flatMap((result) => values.map((value) => result + before + value)).slice(0, MAX_EXPANSIONS);
|
|
16758
|
+
last = match.index + match[0].length;
|
|
16759
|
+
}
|
|
16760
|
+
return results.map((result) => result + word.slice(last));
|
|
16761
|
+
};
|
|
16762
|
+
var substitute = (words, vars) => {
|
|
16763
|
+
if (vars.size === 0)
|
|
16764
|
+
return [words];
|
|
16765
|
+
let lines = [[]];
|
|
16766
|
+
for (const word of words) {
|
|
16767
|
+
const values = expandWord(word, vars);
|
|
16768
|
+
lines = lines.flatMap((line) => values.map((value) => [...line, value])).slice(0, MAX_EXPANSIONS);
|
|
16769
|
+
}
|
|
16770
|
+
return lines;
|
|
16771
|
+
};
|
|
16772
|
+
var assignments = (words, vars) => {
|
|
16773
|
+
if (words[0] === "for" && words[2] === "in" && /^\w+$/.test(words[1] ?? "")) {
|
|
16774
|
+
const values = words.slice(3).flatMap((word) => expandWord(word, vars));
|
|
16775
|
+
return [[words[1], values.slice(0, MAX_EXPANSIONS)]];
|
|
16776
|
+
}
|
|
16777
|
+
let rest = words;
|
|
16778
|
+
if (DECLARATIONS.has(rest[0] ?? "")) {
|
|
16779
|
+
rest = rest.slice(1);
|
|
16780
|
+
while (rest[0]?.startsWith("-"))
|
|
16781
|
+
rest = rest.slice(1);
|
|
16782
|
+
}
|
|
16783
|
+
if (rest.length === 0 || !rest.every((word) => ASSIGNMENT.test(word)))
|
|
16784
|
+
return null;
|
|
16785
|
+
return rest.map((word) => {
|
|
16786
|
+
const [, name, value] = ASSIGNMENT.exec(word);
|
|
16787
|
+
return [name, expandWord(value, vars)];
|
|
16788
|
+
});
|
|
16789
|
+
};
|
|
16790
|
+
var literalOutput = (segment) => {
|
|
16791
|
+
if (!segment?.pipe)
|
|
16792
|
+
return;
|
|
16793
|
+
const { words } = stripPrefixes(segment.words);
|
|
16794
|
+
const name = commandName(words[0]);
|
|
16795
|
+
if (name === "echo") {
|
|
16796
|
+
let args = words.slice(1);
|
|
16797
|
+
while (/^-[neE]+$/.test(args[0] ?? ""))
|
|
16798
|
+
args = args.slice(1);
|
|
16799
|
+
return args.join(" ");
|
|
16800
|
+
}
|
|
16801
|
+
if (name === "printf") {
|
|
16802
|
+
const [format = "", ...args] = words.slice(1);
|
|
16803
|
+
return (args.length ? args.join(`
|
|
16804
|
+
`) : format).replace(/\\n/g, `
|
|
16805
|
+
`);
|
|
16806
|
+
}
|
|
16807
|
+
if (name === "cat" && words.length === 1 && segment.stdin)
|
|
16808
|
+
return segment.stdin.join(`
|
|
16809
|
+
`);
|
|
16810
|
+
return;
|
|
16811
|
+
};
|
|
16812
|
+
var stdinOf = (segment, previous) => segment.stdin ? segment.stdin.join(`
|
|
16813
|
+
`) : literalOutput(previous);
|
|
16814
|
+
var XARGS_VALUES = new Set(["-n", "-L", "-l", "-P", "-d", "-E", "-e", "-s", "-a", "--arg-file", "--delimiter"].concat([
|
|
16815
|
+
"--max-args",
|
|
16816
|
+
"--max-lines",
|
|
16817
|
+
"--max-procs",
|
|
16818
|
+
"--eof",
|
|
16819
|
+
"--max-chars",
|
|
16820
|
+
"--process-slot-var"
|
|
16821
|
+
]));
|
|
16822
|
+
var xargsCommands = (words, input) => {
|
|
16823
|
+
let replace = null;
|
|
16824
|
+
let index = 1;
|
|
16825
|
+
for (;index < words.length; index++) {
|
|
16826
|
+
const word = words[index];
|
|
16827
|
+
if (word === "--") {
|
|
16828
|
+
index++;
|
|
16829
|
+
break;
|
|
16830
|
+
}
|
|
16831
|
+
if (!word.startsWith("-"))
|
|
16832
|
+
break;
|
|
16833
|
+
if (word === "-I")
|
|
16834
|
+
replace = words[++index] ?? "{}";
|
|
16835
|
+
else if (word === "--replace" || word === "-i")
|
|
16836
|
+
replace = "{}";
|
|
16837
|
+
else if (word.startsWith("--replace="))
|
|
16838
|
+
replace = word.slice("--replace=".length);
|
|
16839
|
+
else if (/^-[Ii]./.test(word))
|
|
16840
|
+
replace = word.slice(2);
|
|
16841
|
+
else if (XARGS_VALUES.has(word))
|
|
16842
|
+
index++;
|
|
16843
|
+
}
|
|
16844
|
+
const command = words.slice(index);
|
|
16845
|
+
if (command.length === 0)
|
|
16846
|
+
return [];
|
|
16847
|
+
if (input === undefined)
|
|
16848
|
+
return [command];
|
|
16849
|
+
if (replace === null)
|
|
16850
|
+
return [[...command, ...input.split(/\s+/).filter(Boolean)]];
|
|
16851
|
+
const token = replace;
|
|
16852
|
+
return input.split(`
|
|
16853
|
+
`).map((line) => line.trim()).filter(Boolean).slice(0, MAX_EXPANSIONS).map((line) => command.map((word) => word.replaceAll(token, line)));
|
|
16854
|
+
};
|
|
16855
|
+
var findCommands = (words) => {
|
|
16856
|
+
const found = [];
|
|
16857
|
+
for (let index = 1;index < words.length; index++) {
|
|
16858
|
+
if (!/^-(?:exec|execdir|ok|okdir)$/.test(words[index]))
|
|
16859
|
+
continue;
|
|
16860
|
+
const end = words.findIndex((word, at) => at > index && (word === ";" || word === "+"));
|
|
16861
|
+
found.push(words.slice(index + 1, end < 0 ? undefined : end));
|
|
16862
|
+
if (end < 0)
|
|
16863
|
+
break;
|
|
16864
|
+
index = end;
|
|
16865
|
+
}
|
|
16866
|
+
return found;
|
|
16867
|
+
};
|
|
16868
|
+
var POWERSHELL_VALUES = /^-(?:f|file|ex|executionpolicy|wd|workingdirectory|config|configurationname|o|outputformat|if|inputformat|inp|w|windowstyle|settingsfile|custompipename|psconsolefile)$/;
|
|
16869
|
+
var powershellScript = (words, stdin) => {
|
|
16870
|
+
for (let index = 1;index < words.length; index++) {
|
|
16871
|
+
const word = words[index];
|
|
16872
|
+
if (!/^[-/]/.test(word))
|
|
16873
|
+
return null;
|
|
16874
|
+
const flag = word.replace(/^[-/]+/, "").toLowerCase();
|
|
16875
|
+
if (!flag)
|
|
16876
|
+
return null;
|
|
16877
|
+
if (flag === "e" || flag === "ec" || flag.length >= 2 && "encodedcommand".startsWith(flag)) {
|
|
16878
|
+
try {
|
|
16879
|
+
return Buffer.from(words[index + 1] ?? "", "base64").toString("utf16le");
|
|
16880
|
+
} catch {
|
|
16881
|
+
return null;
|
|
16882
|
+
}
|
|
16883
|
+
}
|
|
16884
|
+
if (flag === "cwa" || flag.length >= 8 && "commandwithargs".startsWith(flag))
|
|
16885
|
+
return words[index + 1] ?? null;
|
|
16886
|
+
if ("command".startsWith(flag))
|
|
16887
|
+
return words[index + 1] === "-" ? stdin ?? null : words.slice(index + 1).join(" ");
|
|
16888
|
+
if (POWERSHELL_VALUES.test(`-${flag}`)) {
|
|
16889
|
+
if (flag === "f" || flag === "file")
|
|
16890
|
+
return null;
|
|
16891
|
+
index++;
|
|
16892
|
+
}
|
|
16893
|
+
}
|
|
16894
|
+
return null;
|
|
16895
|
+
};
|
|
16896
|
+
var cmdScript = (words) => {
|
|
16897
|
+
const at = words.findIndex((word, index) => index > 0 && /^\/[ck]$/i.test(word));
|
|
16898
|
+
if (at > 0)
|
|
16899
|
+
return words.slice(at + 1).join(" ");
|
|
16900
|
+
const attached = words.find((word, index) => index > 0 && /^\/[ck]./i.test(word));
|
|
16901
|
+
return attached ? [attached.slice(2), ...words.slice(words.indexOf(attached) + 1)].join(" ") : null;
|
|
16902
|
+
};
|
|
16903
|
+
var processSubstitutionText = (word) => {
|
|
16904
|
+
const inner = /^<\(([\s\S]*)\)$/.exec(word ?? "")?.[1];
|
|
16905
|
+
if (inner === undefined)
|
|
16906
|
+
return;
|
|
16907
|
+
const segments = segmentsOf(inner);
|
|
16908
|
+
return segments.length === 1 ? literalOutput({ ...segments[0], pipe: true }) : undefined;
|
|
16909
|
+
};
|
|
16910
|
+
var shellScript = (words, stdin) => {
|
|
16911
|
+
const flag = words.findIndex((word, index) => index > 0 && SCRIPT_FLAG.test(word));
|
|
16912
|
+
if (flag > 0)
|
|
16913
|
+
return words[flag + 1] === "--" ? words[flag + 2] : words[flag + 1];
|
|
16914
|
+
const operand = words.slice(1).find((word) => !word.startsWith("-"));
|
|
16915
|
+
if (operand !== undefined)
|
|
16916
|
+
return processSubstitutionText(operand);
|
|
16917
|
+
return stdin;
|
|
16918
|
+
};
|
|
16919
|
+
var scriptCommand = (words) => {
|
|
16920
|
+
for (let index = 1;index < words.length; index++) {
|
|
16921
|
+
const word = words[index];
|
|
16922
|
+
if (word === "--command" || /^-[a-zA-Z]*c$/.test(word))
|
|
16923
|
+
return words[index + 1];
|
|
16924
|
+
if (word.startsWith("--command="))
|
|
16925
|
+
return word.slice("--command=".length);
|
|
16926
|
+
}
|
|
16927
|
+
return;
|
|
16928
|
+
};
|
|
16929
|
+
var PARALLEL_VALUES = new Set(["-j", "--jobs", "-N", "-n", "-S", "--sshlogin", "-P", "--delay"]);
|
|
16930
|
+
var parallelCommands = (words) => {
|
|
16931
|
+
let index = 1;
|
|
16932
|
+
while (index < words.length && words[index].startsWith("-"))
|
|
16933
|
+
index += PARALLEL_VALUES.has(words[index]) ? 2 : 1;
|
|
16934
|
+
const separator = words.indexOf(":::", index);
|
|
16935
|
+
const command = words.slice(index, separator < 0 ? undefined : separator);
|
|
16936
|
+
if (separator < 0)
|
|
16937
|
+
return command.length ? [command] : [];
|
|
16938
|
+
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]);
|
|
16939
|
+
};
|
|
16940
|
+
var START_PROCESS_VALUES = /^-(?:workingdirectory|wd|redirectstandard\w*|verb|windowstyle|credential|environment)$/i;
|
|
16941
|
+
var startProcessCommand = (words) => {
|
|
16942
|
+
let file;
|
|
16943
|
+
let args;
|
|
16944
|
+
const positionals = [];
|
|
16945
|
+
for (let index = 1;index < words.length; index++) {
|
|
16946
|
+
const word = words[index];
|
|
16947
|
+
const flag = word.startsWith("-") ? word.slice(1).toLowerCase() : null;
|
|
16948
|
+
if (flag === null)
|
|
16949
|
+
positionals.push(word);
|
|
16950
|
+
else if (flag && "filepath".startsWith(flag))
|
|
16951
|
+
file = words[++index];
|
|
16952
|
+
else if (flag && (flag === "args" || "argumentlist".startsWith(flag)))
|
|
16953
|
+
args = words[++index];
|
|
16954
|
+
else if (START_PROCESS_VALUES.test(word))
|
|
16955
|
+
index++;
|
|
16956
|
+
}
|
|
16957
|
+
file ??= positionals.shift();
|
|
16958
|
+
args ??= positionals.shift();
|
|
16959
|
+
if (!file)
|
|
16960
|
+
return null;
|
|
16961
|
+
return [file, ...(args ?? "").split(/[\s,]+/).filter(Boolean)];
|
|
16962
|
+
};
|
|
16963
|
+
var splitString = (line) => {
|
|
16964
|
+
if (commandName(line[0]) !== "env")
|
|
16965
|
+
return null;
|
|
16966
|
+
for (let index = 1;index < line.length; index++) {
|
|
16967
|
+
const word = line[index];
|
|
16968
|
+
if (word === "-S" || word === "--split-string")
|
|
16969
|
+
return line.slice(index + 1).join(" ");
|
|
16970
|
+
if (word.startsWith("--split-string="))
|
|
16971
|
+
return line.slice(index).join(" ").slice(15);
|
|
16972
|
+
if (/^-S./.test(word))
|
|
16973
|
+
return [word.slice(2), ...line.slice(index + 1)].join(" ");
|
|
16974
|
+
if (!word.startsWith("-") && !ASSIGNMENT.test(word))
|
|
16975
|
+
return null;
|
|
16976
|
+
}
|
|
16977
|
+
return null;
|
|
16978
|
+
};
|
|
16979
|
+
var CONFIG_READS = /^(?:--get\S*|-l|--list|--unset\S*|--remove-section|--rename-section|-e|--edit|--show-\S+|--name-only)$/;
|
|
16980
|
+
var configSetBy = (args) => {
|
|
16981
|
+
const positionals = args.filter((arg, index) => index > 0 && !arg.startsWith("-"));
|
|
16982
|
+
if (args[0] === "remote" && (positionals[0] === "add" || positionals[0] === "set-url")) {
|
|
16983
|
+
const [, name, url] = positionals;
|
|
16984
|
+
const key = args.includes("--push") ? "pushurl" : "url";
|
|
16985
|
+
return name && url ? ["-c", `remote.${name}.${key}=${url}`] : [];
|
|
16986
|
+
}
|
|
16987
|
+
if (args[0] !== "config" || args.some((arg) => CONFIG_READS.test(arg)))
|
|
16988
|
+
return [];
|
|
16989
|
+
const [key, value] = positionals[0] === "set" ? positionals.slice(1) : positionals;
|
|
16990
|
+
return key?.includes(".") && value !== undefined && positionals.length <= 3 ? ["-c", `${key}=${value}`] : [];
|
|
16991
|
+
};
|
|
16992
|
+
var gitInvocation = (words, dir, env = {}, stdin, inherited = []) => {
|
|
16993
|
+
let here = dir;
|
|
16994
|
+
const config = [...inherited];
|
|
16995
|
+
let gitDir = env.GIT_DIR;
|
|
16996
|
+
let index = 0;
|
|
16997
|
+
for (;index < words.length; index++) {
|
|
16998
|
+
const word = words[index];
|
|
16999
|
+
if (word === "-C")
|
|
17000
|
+
here = words[index + 1] ? joinDir(here, words[++index]) : here;
|
|
17001
|
+
else if (GIT_CONFIG_OPTIONS.has(word)) {
|
|
17002
|
+
if (word === "--git-dir")
|
|
17003
|
+
gitDir = words[index + 1];
|
|
17004
|
+
if (words[index + 1] !== undefined)
|
|
17005
|
+
config.push(word, words[++index]);
|
|
17006
|
+
} else if (/^--(?:config-env|git-dir)=/.test(word)) {
|
|
17007
|
+
if (word.startsWith("--git-dir="))
|
|
17008
|
+
gitDir = word.slice("--git-dir=".length);
|
|
17009
|
+
config.push(word);
|
|
17010
|
+
} else if (GIT_VALUE_OPTIONS.has(word))
|
|
17011
|
+
index++;
|
|
17012
|
+
else if (!word.startsWith("-"))
|
|
17013
|
+
break;
|
|
17014
|
+
}
|
|
17015
|
+
if (gitDir)
|
|
17016
|
+
here = joinDir(here, gitDir.replace(/(?:^|[\\/]+)\.git[\\/]*$/, "") || ".");
|
|
17017
|
+
return {
|
|
17018
|
+
tool: "git",
|
|
17019
|
+
dir: here,
|
|
17020
|
+
args: words.slice(index),
|
|
17021
|
+
...config.length ? { config } : {},
|
|
17022
|
+
...Object.keys(env).length ? { env } : {},
|
|
17023
|
+
...stdin === undefined ? {} : { stdin }
|
|
17024
|
+
};
|
|
17025
|
+
};
|
|
16373
17026
|
function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
17027
|
+
if (depth > 0)
|
|
17028
|
+
return walk2(command, dialect, depth);
|
|
17029
|
+
const key = `${dialect}\x00${command}`;
|
|
17030
|
+
const cached = RECENT.get(key);
|
|
17031
|
+
if (cached)
|
|
17032
|
+
return cached;
|
|
17033
|
+
let found;
|
|
17034
|
+
try {
|
|
17035
|
+
found = walk2(command, dialect, depth);
|
|
17036
|
+
} catch (error) {
|
|
17037
|
+
throw error instanceof ShellAnalysisError ? error : new ShellAnalysisError(error instanceof Error ? error.message : String(error));
|
|
17038
|
+
}
|
|
17039
|
+
RECENT.set(key, found);
|
|
17040
|
+
if (RECENT.size > 8)
|
|
17041
|
+
RECENT.delete(RECENT.keys().next().value);
|
|
17042
|
+
return found;
|
|
17043
|
+
}
|
|
17044
|
+
var RECENT = new Map;
|
|
17045
|
+
function walk2(command, dialect, depth) {
|
|
16374
17046
|
const found = [];
|
|
16375
17047
|
let dir = null;
|
|
16376
17048
|
const groups = [];
|
|
16377
17049
|
let stack = [];
|
|
16378
|
-
|
|
16379
|
-
|
|
16380
|
-
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
|
|
16388
|
-
|
|
16389
|
-
const
|
|
17050
|
+
const vars = new Map;
|
|
17051
|
+
const exported = {};
|
|
17052
|
+
const sessionConfig = [];
|
|
17053
|
+
const nested = (script, inner) => {
|
|
17054
|
+
if (!script || depth >= MAX_DEPTH)
|
|
17055
|
+
return;
|
|
17056
|
+
for (const invocation of rawInvocations(script, inner, depth + 1))
|
|
17057
|
+
found.push({ ...invocation, dir: rebase(dir, invocation.dir) });
|
|
17058
|
+
};
|
|
17059
|
+
const visit = (input, stdin, hops) => {
|
|
17060
|
+
const line = /^\$[\w:]+$/.test(input[0] ?? "") && input[1] === "=" ? input.slice(2) : input;
|
|
17061
|
+
const split = splitString(line);
|
|
17062
|
+
if (split !== null)
|
|
17063
|
+
return nested(split, "posix");
|
|
17064
|
+
const { words, env } = stripPrefixes(line);
|
|
16390
17065
|
const name = commandName(words[0]);
|
|
17066
|
+
if (!name)
|
|
17067
|
+
return;
|
|
17068
|
+
const runs = (lines) => {
|
|
17069
|
+
if (hops < MAX_DEPTH)
|
|
17070
|
+
for (const next of lines)
|
|
17071
|
+
visit(next, undefined, hops + 1);
|
|
17072
|
+
};
|
|
16391
17073
|
if (CD.has(name)) {
|
|
16392
17074
|
const target = cdTarget(words);
|
|
16393
17075
|
dir = target === null ? os4.homedir() : joinDir(dir, target);
|
|
16394
|
-
|
|
16395
|
-
}
|
|
16396
|
-
if (PUSHD.has(name)) {
|
|
17076
|
+
} else if (PUSHD.has(name)) {
|
|
16397
17077
|
const target = cdTarget(words);
|
|
16398
17078
|
stack.push(dir);
|
|
16399
17079
|
dir = target === null || target === "-" ? undefined : joinDir(dir, target);
|
|
16400
|
-
|
|
16401
|
-
}
|
|
16402
|
-
if (POPD.has(name)) {
|
|
17080
|
+
} else if (POPD.has(name))
|
|
16403
17081
|
dir = stack.length ? stack.pop() : undefined;
|
|
16404
|
-
|
|
17082
|
+
else if (EVALS.has(name)) {
|
|
17083
|
+
const args = /^-c(?:o(?:m(?:m(?:a(?:n(?:d)?)?)?)?)?)?$/i.test(words[1] ?? "") ? words.slice(2) : words.slice(1);
|
|
17084
|
+
nested(args.join(" "), dialect);
|
|
17085
|
+
} else if (SHELLS.has(name))
|
|
17086
|
+
nested(shellScript(words, stdin), "posix");
|
|
17087
|
+
else if ((name === "source" || name === ".") && dialect === "posix")
|
|
17088
|
+
nested(processSubstitutionText(words[1]), "posix");
|
|
17089
|
+
else if (name === "trap" && dialect === "posix" && !/^-[lp]$/.test(words[1] ?? ""))
|
|
17090
|
+
nested(words[1], "posix");
|
|
17091
|
+
else if (name === "script")
|
|
17092
|
+
nested(scriptCommand(words), "posix");
|
|
17093
|
+
else if (name === "parallel")
|
|
17094
|
+
runs(parallelCommands(words));
|
|
17095
|
+
else if (dialect === "powershell" && /^(?:start-process|saps|start)$/.test(name)) {
|
|
17096
|
+
const started = startProcessCommand(words);
|
|
17097
|
+
if (started)
|
|
17098
|
+
runs([started]);
|
|
17099
|
+
} else if (POWERSHELLS.has(name))
|
|
17100
|
+
nested(powershellScript(words, stdin), "powershell");
|
|
17101
|
+
else if (name === "cmd")
|
|
17102
|
+
nested(cmdScript(words), "powershell");
|
|
17103
|
+
else if (name === "xargs" || name === "find")
|
|
17104
|
+
runs(name === "xargs" ? xargsCommands(words, stdin) : findCommands(words));
|
|
17105
|
+
else if (name === "gh" || name === "glab")
|
|
17106
|
+
found.push({
|
|
17107
|
+
tool: name,
|
|
17108
|
+
dir,
|
|
17109
|
+
args: words.slice(1),
|
|
17110
|
+
...stdin === undefined ? {} : { stdin }
|
|
17111
|
+
});
|
|
17112
|
+
else if (name === "git") {
|
|
17113
|
+
const invocation = gitInvocation(words.slice(1), dir, { ...exported, ...env }, stdin, sessionConfig);
|
|
17114
|
+
found.push(invocation);
|
|
17115
|
+
sessionConfig.push(...configSetBy(invocation.args));
|
|
16405
17116
|
}
|
|
16406
|
-
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
found.push({
|
|
16412
|
-
...inner,
|
|
16413
|
-
dir: inner.dir === null ? dir : inner.dir === undefined ? undefined : joinDir(dir, inner.dir)
|
|
16414
|
-
});
|
|
17117
|
+
};
|
|
17118
|
+
const segments = segmentsOf(command, dialect);
|
|
17119
|
+
for (const [index, segment] of segments.entries()) {
|
|
17120
|
+
if (segment.group === "open") {
|
|
17121
|
+
groups.push({ dir, stack: [...stack] });
|
|
16415
17122
|
continue;
|
|
16416
17123
|
}
|
|
16417
|
-
if (
|
|
16418
|
-
|
|
17124
|
+
if (segment.group === "close") {
|
|
17125
|
+
const saved = groups.pop();
|
|
17126
|
+
if (saved)
|
|
17127
|
+
({ dir, stack } = saved);
|
|
16419
17128
|
continue;
|
|
16420
17129
|
}
|
|
16421
|
-
if (
|
|
17130
|
+
if (segment.unanalyzable)
|
|
17131
|
+
throw new ShellAnalysisError(segment.unanalyzable);
|
|
17132
|
+
for (const sub of segment.subs ?? [])
|
|
17133
|
+
nested(sub, "posix");
|
|
17134
|
+
const set = assignments(segment.words, vars);
|
|
17135
|
+
if (set) {
|
|
17136
|
+
for (const [name, values] of set) {
|
|
17137
|
+
vars.set(name, values);
|
|
17138
|
+
if (segment.words[0] === "export" && GIT_CONFIG_ENV.test(name) && values[0] !== undefined)
|
|
17139
|
+
exported[name] = values[0];
|
|
17140
|
+
}
|
|
16422
17141
|
continue;
|
|
16423
|
-
let here = dir;
|
|
16424
|
-
let index = 1;
|
|
16425
|
-
for (;index < words.length; index++) {
|
|
16426
|
-
const word = words[index];
|
|
16427
|
-
if (word === "-C")
|
|
16428
|
-
here = words[index + 1] ? joinDir(here, words[++index]) : here;
|
|
16429
|
-
else if (GIT_VALUE_OPTIONS.has(word))
|
|
16430
|
-
index++;
|
|
16431
|
-
else if (!word.startsWith("-"))
|
|
16432
|
-
break;
|
|
16433
17142
|
}
|
|
16434
|
-
|
|
17143
|
+
const stdin = stdinOf(segment, segments[index - 1]);
|
|
17144
|
+
for (const line of substitute(segment.words, vars))
|
|
17145
|
+
visit(line, stdin, 0);
|
|
16435
17146
|
}
|
|
16436
17147
|
return found;
|
|
16437
17148
|
}
|
|
@@ -16467,6 +17178,55 @@ function workitInvocations(command, dialect = "posix", depth = 0) {
|
|
|
16467
17178
|
return found;
|
|
16468
17179
|
}
|
|
16469
17180
|
var PUSH_VALUE_OPTIONS = new Set(["-o", "--push-option", "--receive-pack", "--exec", "--repo"]);
|
|
17181
|
+
var CURRENT_BRANCH = /^\$\(\s*git\s+(?:branch\s+--show-current|rev-parse\s+--abbrev-ref\s+HEAD|symbolic-ref\s+--short\s+HEAD)\s*\)$/;
|
|
17182
|
+
var pushDestination = (destination) => {
|
|
17183
|
+
if (destination === "HEAD" || destination === "@" || CURRENT_BRANCH.test(destination))
|
|
17184
|
+
return { name: null };
|
|
17185
|
+
if (destination.startsWith("refs/heads/"))
|
|
17186
|
+
return { name: destination.slice(11) };
|
|
17187
|
+
if (destination.startsWith("refs/tags/"))
|
|
17188
|
+
return { name: undefined, tag: destination.slice(10) };
|
|
17189
|
+
if (destination.startsWith("refs/"))
|
|
17190
|
+
return { name: undefined };
|
|
17191
|
+
return { name: destination };
|
|
17192
|
+
};
|
|
17193
|
+
var pushRefspecs = (specs) => {
|
|
17194
|
+
let force = false;
|
|
17195
|
+
let matching = false;
|
|
17196
|
+
const targets = [];
|
|
17197
|
+
const tags = [];
|
|
17198
|
+
const deleted = [];
|
|
17199
|
+
const globs = [];
|
|
17200
|
+
for (const raw of specs) {
|
|
17201
|
+
if (raw.startsWith("+"))
|
|
17202
|
+
force = true;
|
|
17203
|
+
const spec = raw.replace(/^\+/, "");
|
|
17204
|
+
if (spec.startsWith("^"))
|
|
17205
|
+
continue;
|
|
17206
|
+
if (spec === ":") {
|
|
17207
|
+
matching = true;
|
|
17208
|
+
continue;
|
|
17209
|
+
}
|
|
17210
|
+
const colon = spec.indexOf(":");
|
|
17211
|
+
const source = colon >= 0 ? spec.slice(0, colon) : spec;
|
|
17212
|
+
const destination = colon >= 0 ? spec.slice(colon + 1) : spec;
|
|
17213
|
+
if (!destination)
|
|
17214
|
+
continue;
|
|
17215
|
+
if (destination.includes("*")) {
|
|
17216
|
+
globs.push({ source, destination });
|
|
17217
|
+
continue;
|
|
17218
|
+
}
|
|
17219
|
+
const { name, tag } = pushDestination(destination);
|
|
17220
|
+
if (tag !== undefined)
|
|
17221
|
+
tags.push(tag);
|
|
17222
|
+
if (name === undefined)
|
|
17223
|
+
continue;
|
|
17224
|
+
targets.push(name);
|
|
17225
|
+
if (colon === 0 && name !== null)
|
|
17226
|
+
deleted.push(name);
|
|
17227
|
+
}
|
|
17228
|
+
return { force, matching, targets, tags, deleted, globs };
|
|
17229
|
+
};
|
|
16470
17230
|
var pushAction = (args) => {
|
|
16471
17231
|
let force = false;
|
|
16472
17232
|
let lease = false;
|
|
@@ -16476,6 +17236,7 @@ var pushAction = (args) => {
|
|
|
16476
17236
|
let allBranches = false;
|
|
16477
17237
|
let mirror = false;
|
|
16478
17238
|
let remote = null;
|
|
17239
|
+
let dryRun = false;
|
|
16479
17240
|
const positionals = [];
|
|
16480
17241
|
for (let index = 1;index < args.length; index++) {
|
|
16481
17242
|
const arg = args[index];
|
|
@@ -16483,9 +17244,11 @@ var pushAction = (args) => {
|
|
|
16483
17244
|
positionals.push(...args.slice(index + 1));
|
|
16484
17245
|
break;
|
|
16485
17246
|
}
|
|
16486
|
-
if (arg
|
|
16487
|
-
|
|
16488
|
-
if (arg
|
|
17247
|
+
if (/^--dr(?:y(?:-(?:r(?:un?)?)?)?)?$/.test(arg) || /^-[a-zA-Z]*n[a-zA-Z]*$/.test(arg))
|
|
17248
|
+
dryRun = true;
|
|
17249
|
+
else if (/^--no-dr(?:y(?:-(?:r(?:un?)?)?)?)?$/.test(arg))
|
|
17250
|
+
dryRun = false;
|
|
17251
|
+
else if (arg === "--repo")
|
|
16489
17252
|
remote = args[++index] ?? null;
|
|
16490
17253
|
else if (arg.startsWith("--repo="))
|
|
16491
17254
|
remote = arg.slice("--repo=".length);
|
|
@@ -16506,41 +17269,28 @@ var pushAction = (args) => {
|
|
|
16506
17269
|
else if (!arg.startsWith("-"))
|
|
16507
17270
|
positionals.push(arg);
|
|
16508
17271
|
}
|
|
17272
|
+
if (dryRun)
|
|
17273
|
+
return null;
|
|
16509
17274
|
const specs = remote === null ? positionals.slice(1) : positionals;
|
|
16510
17275
|
remote ??= positionals[0] ?? null;
|
|
16511
|
-
const
|
|
16512
|
-
const
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
if (raw.startsWith("+"))
|
|
16516
|
-
force = true;
|
|
16517
|
-
const spec = raw.replace(/^\+/, "");
|
|
16518
|
-
const colon = spec.indexOf(":");
|
|
16519
|
-
const destination = colon >= 0 ? spec.slice(colon + 1) : spec;
|
|
16520
|
-
if (!destination)
|
|
16521
|
-
continue;
|
|
16522
|
-
const name = destination === "HEAD" ? null : destination.startsWith("refs/heads/") ? destination.slice(11) : destination.startsWith("refs/") ? undefined : destination;
|
|
16523
|
-
if (destination.startsWith("refs/tags/"))
|
|
16524
|
-
tags.push(destination.slice(10));
|
|
16525
|
-
if (name === undefined)
|
|
16526
|
-
continue;
|
|
16527
|
-
targets.push(name);
|
|
16528
|
-
if (colon === 0 && name !== null)
|
|
16529
|
-
deleted.push(name);
|
|
16530
|
-
}
|
|
16531
|
-
if (specs.length === 0 && !wholesale)
|
|
16532
|
-
targets.push(null);
|
|
17276
|
+
const parsed = pushRefspecs(specs);
|
|
17277
|
+
const implicit = specs.length === 0 && !wholesale;
|
|
17278
|
+
if (implicit)
|
|
17279
|
+
parsed.targets.push(null);
|
|
16533
17280
|
return {
|
|
16534
17281
|
kind: "push",
|
|
16535
|
-
targets,
|
|
16536
|
-
blindForce: force && !lease,
|
|
17282
|
+
targets: parsed.targets,
|
|
17283
|
+
blindForce: (force || parsed.force) && !lease,
|
|
16537
17284
|
remote,
|
|
16538
|
-
...tags.length ? { tags } : {},
|
|
17285
|
+
...parsed.tags.length ? { tags: parsed.tags } : {},
|
|
16539
17286
|
...allTags ? { allTags: true } : {},
|
|
16540
17287
|
...deletes ? { deletes: true } : {},
|
|
16541
|
-
...deleted.length ? { deleted } : {},
|
|
17288
|
+
...parsed.deleted.length ? { deleted: parsed.deleted } : {},
|
|
16542
17289
|
...allBranches ? { allBranches: true } : {},
|
|
16543
|
-
...mirror ? { mirror: true } : {}
|
|
17290
|
+
...mirror ? { mirror: true } : {},
|
|
17291
|
+
...implicit ? { implicit: true } : {},
|
|
17292
|
+
...parsed.globs.length ? { globs: parsed.globs } : {},
|
|
17293
|
+
...parsed.matching ? { matching: true } : {}
|
|
16544
17294
|
};
|
|
16545
17295
|
};
|
|
16546
17296
|
var VALUE_OPTIONS = {
|
|
@@ -16586,22 +17336,110 @@ var asksHelp = (invocation) => {
|
|
|
16586
17336
|
}
|
|
16587
17337
|
return false;
|
|
16588
17338
|
};
|
|
17339
|
+
var API_VALUES = new Set(["--method", "--header", "--raw-field", "--field", "--jq", "--template", "--input"].concat([
|
|
17340
|
+
"--hostname",
|
|
17341
|
+
"--preview",
|
|
17342
|
+
"--cache",
|
|
17343
|
+
"--output"
|
|
17344
|
+
]));
|
|
17345
|
+
var API_SHORT_VALUES = "XHfFqtp";
|
|
17346
|
+
var API_FIELDS = new Set(["-f", "-F", "--raw-field", "--field"]);
|
|
17347
|
+
var API_MERGE = {
|
|
17348
|
+
gh: /(?:^|\/)(?:pulls\/[^/?#]+\/merge|merges)\/?(?:[?#]|$)/i,
|
|
17349
|
+
glab: /(?:^|\/)merge_requests\/[^/?#]+\/merge\/?(?:[?#]|$)/i
|
|
17350
|
+
};
|
|
17351
|
+
var GRAPHQL_MERGE = /\b(?:mergePullRequest|enablePullRequestAutoMerge|mergeBranch|mergeRequestAccept)\b/;
|
|
17352
|
+
var apiMerges = (tool, args, stdin) => {
|
|
17353
|
+
const request = { method: null, body: false };
|
|
17354
|
+
let endpoint = null;
|
|
17355
|
+
const values = [];
|
|
17356
|
+
const take = (name, value) => {
|
|
17357
|
+
if (name === "-X" || name === "--method")
|
|
17358
|
+
request.method = value.toUpperCase();
|
|
17359
|
+
if (API_FIELDS.has(name) || name === "--input")
|
|
17360
|
+
request.body = true;
|
|
17361
|
+
values.push(value);
|
|
17362
|
+
const fromStdin = name === "--input" ? value === "-" : /^(?:[^=]*=)?@-$/.test(value);
|
|
17363
|
+
if (fromStdin && stdin !== undefined)
|
|
17364
|
+
values.push(stdin);
|
|
17365
|
+
};
|
|
17366
|
+
for (let index = 1;index < args.length; index++) {
|
|
17367
|
+
const arg = args[index];
|
|
17368
|
+
if (arg === "--") {
|
|
17369
|
+
endpoint ??= args[index + 1] ?? null;
|
|
17370
|
+
break;
|
|
17371
|
+
}
|
|
17372
|
+
if (arg.startsWith("--")) {
|
|
17373
|
+
const eq = arg.indexOf("=");
|
|
17374
|
+
const name = eq > 0 ? arg.slice(0, eq) : arg;
|
|
17375
|
+
if (API_VALUES.has(name))
|
|
17376
|
+
take(name, eq > 0 ? arg.slice(eq + 1) : args[++index] ?? "");
|
|
17377
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
17378
|
+
for (let at = 1;at < arg.length; at++) {
|
|
17379
|
+
if (!API_SHORT_VALUES.includes(arg[at]))
|
|
17380
|
+
continue;
|
|
17381
|
+
take(`-${arg[at]}`, at + 1 < arg.length ? arg.slice(at + 1) : args[++index] ?? "");
|
|
17382
|
+
break;
|
|
17383
|
+
}
|
|
17384
|
+
} else
|
|
17385
|
+
endpoint ??= arg;
|
|
17386
|
+
}
|
|
17387
|
+
if (!endpoint)
|
|
17388
|
+
return false;
|
|
17389
|
+
endpoint = endpoint.replace(/(?<!:)\/{2,}/g, "/");
|
|
17390
|
+
if (/(?:^|\/)graphql\/?$/i.test(endpoint))
|
|
17391
|
+
return values.some((value) => GRAPHQL_MERGE.test(value));
|
|
17392
|
+
const verb = request.method ?? (request.body ? "POST" : "GET");
|
|
17393
|
+
return verb !== "GET" && verb !== "HEAD" && API_MERGE[tool].test(endpoint);
|
|
17394
|
+
};
|
|
17395
|
+
var subtreePush = (args) => {
|
|
17396
|
+
const positionals = [];
|
|
17397
|
+
for (let index = 2;index < args.length; index++) {
|
|
17398
|
+
const arg = args[index];
|
|
17399
|
+
if (arg === "-P" || arg === "--prefix" || arg === "-m" || arg === "--message")
|
|
17400
|
+
index++;
|
|
17401
|
+
else if (!arg.startsWith("-"))
|
|
17402
|
+
positionals.push(arg);
|
|
17403
|
+
}
|
|
17404
|
+
const [remote, branch] = positionals;
|
|
17405
|
+
return remote && branch ? pushAction(["push", remote, `HEAD:refs/heads/${branch}`]) : null;
|
|
17406
|
+
};
|
|
16589
17407
|
function rawAction(invocation) {
|
|
16590
17408
|
const args = invocation.args;
|
|
17409
|
+
if (invocation.tool !== "git" && args[0] === "api")
|
|
17410
|
+
return apiMerges(invocation.tool, args, invocation.stdin) ? { kind: "merge", forge: invocation.tool, via: "api" } : null;
|
|
16591
17411
|
if (asksHelp(invocation))
|
|
16592
17412
|
return null;
|
|
16593
|
-
const [first
|
|
17413
|
+
const [first] = args;
|
|
16594
17414
|
if (invocation.tool === "git") {
|
|
17415
|
+
const second = args[1];
|
|
16595
17416
|
if (first === "commit")
|
|
16596
17417
|
return args.includes("--dry-run") ? null : { kind: "commit", amend: args.includes("--amend") };
|
|
16597
17418
|
if (first === "push")
|
|
16598
17419
|
return pushAction(args);
|
|
17420
|
+
if (first === "send-pack")
|
|
17421
|
+
return pushAction([
|
|
17422
|
+
"push",
|
|
17423
|
+
...args.slice(1).filter((arg) => arg !== "--stdin"),
|
|
17424
|
+
...args.includes("--stdin") ? (invocation.stdin ?? "").split(/\s+/).filter(Boolean) : []
|
|
17425
|
+
]);
|
|
17426
|
+
if (first === "subtree" && second === "push")
|
|
17427
|
+
return subtreePush(args);
|
|
16599
17428
|
return null;
|
|
16600
17429
|
}
|
|
16601
17430
|
const forge = invocation.tool;
|
|
16602
17431
|
const noun = forge === "gh" ? "pr" : "mr";
|
|
16603
17432
|
if (first !== noun)
|
|
16604
17433
|
return null;
|
|
17434
|
+
const values = VALUE_OPTIONS[forge];
|
|
17435
|
+
let second;
|
|
17436
|
+
for (let index = 1;index < args.length && second === undefined; index++) {
|
|
17437
|
+
const arg = args[index];
|
|
17438
|
+
if (values.has(arg))
|
|
17439
|
+
index++;
|
|
17440
|
+
else if (!arg.startsWith("-"))
|
|
17441
|
+
second = arg;
|
|
17442
|
+
}
|
|
16605
17443
|
if (second === "merge")
|
|
16606
17444
|
return { kind: "merge", forge };
|
|
16607
17445
|
if (second === "create")
|
|
@@ -16633,16 +17471,6 @@ var guardedBranch = (dir, branch) => {
|
|
|
16633
17471
|
return false;
|
|
16634
17472
|
}
|
|
16635
17473
|
};
|
|
16636
|
-
var toPushRemote = (repo, remote) => {
|
|
16637
|
-
if (remote === null)
|
|
16638
|
-
return true;
|
|
16639
|
-
try {
|
|
16640
|
-
const pushRemote = pushRemoteName(repo.dir, repo.branch);
|
|
16641
|
-
return pushRemote === null || pushRemote === remote;
|
|
16642
|
-
} catch {
|
|
16643
|
-
return false;
|
|
16644
|
-
}
|
|
16645
|
-
};
|
|
16646
17474
|
var headSha2 = (repo) => {
|
|
16647
17475
|
const git = repo.location.git;
|
|
16648
17476
|
if (!git || git.reftable)
|
|
@@ -16664,13 +17492,172 @@ var headSha2 = (repo) => {
|
|
|
16664
17492
|
return null;
|
|
16665
17493
|
}
|
|
16666
17494
|
};
|
|
17495
|
+
var gitConfig = (dir, invocation, cache) => {
|
|
17496
|
+
const key = JSON.stringify([dir, invocation.config ?? [], invocation.env ?? {}]);
|
|
17497
|
+
const cached = cache.get(key);
|
|
17498
|
+
if (cached)
|
|
17499
|
+
return cached;
|
|
17500
|
+
const config = new Map;
|
|
17501
|
+
const listed = spawnSync11("git", [...invocation.config ?? [], "config", "-z", "--list"], {
|
|
17502
|
+
cwd: dir,
|
|
17503
|
+
encoding: "utf8",
|
|
17504
|
+
timeout: 3000,
|
|
17505
|
+
windowsHide: true,
|
|
17506
|
+
env: { ...process.env, ...invocation.env, GIT_TERMINAL_PROMPT: "0", GIT_OPTIONAL_LOCKS: "0" }
|
|
17507
|
+
});
|
|
17508
|
+
for (const entry of (listed.status === 0 ? listed.stdout : "").split("\x00")) {
|
|
17509
|
+
if (!entry)
|
|
17510
|
+
continue;
|
|
17511
|
+
const newline = entry.indexOf(`
|
|
17512
|
+
`);
|
|
17513
|
+
const name = newline < 0 ? entry : entry.slice(0, newline);
|
|
17514
|
+
config.set(name, [
|
|
17515
|
+
...config.get(name) ?? [],
|
|
17516
|
+
newline < 0 ? "true" : entry.slice(newline + 1)
|
|
17517
|
+
]);
|
|
17518
|
+
}
|
|
17519
|
+
cache.set(key, config);
|
|
17520
|
+
return config;
|
|
17521
|
+
};
|
|
17522
|
+
var configValue = (config, key) => config.get(key)?.at(-1);
|
|
17523
|
+
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(" "));
|
|
17524
|
+
var JUDGED_COMMANDS = [
|
|
17525
|
+
"push",
|
|
17526
|
+
"commit",
|
|
17527
|
+
"switch",
|
|
17528
|
+
"checkout",
|
|
17529
|
+
"branch",
|
|
17530
|
+
"worktree",
|
|
17531
|
+
"stash",
|
|
17532
|
+
"update-ref",
|
|
17533
|
+
"symbolic-ref",
|
|
17534
|
+
"fetch",
|
|
17535
|
+
"pull",
|
|
17536
|
+
"subtree"
|
|
17537
|
+
];
|
|
17538
|
+
var editDistance2 = (a, b) => {
|
|
17539
|
+
let before = [];
|
|
17540
|
+
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
17541
|
+
for (let i = 1;i <= a.length; i++) {
|
|
17542
|
+
const row = [i];
|
|
17543
|
+
for (let j = 1;j <= b.length; j++) {
|
|
17544
|
+
row[j] = Math.min(previous[j] + 1, row[j - 1] + 1, previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
17545
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1])
|
|
17546
|
+
row[j] = Math.min(row[j], before[j - 2] + 1);
|
|
17547
|
+
}
|
|
17548
|
+
[before, previous] = [previous, row];
|
|
17549
|
+
}
|
|
17550
|
+
return previous[b.length];
|
|
17551
|
+
};
|
|
17552
|
+
var autocorrected = (name, config) => {
|
|
17553
|
+
const setting = (configValue(config, "help.autocorrect") ?? "0").toLowerCase();
|
|
17554
|
+
if (setting !== "immediate" && !/^-?[1-9]\d*$/.test(setting))
|
|
17555
|
+
return null;
|
|
17556
|
+
let best = null;
|
|
17557
|
+
let bestDistance = 3;
|
|
17558
|
+
let tie = false;
|
|
17559
|
+
for (const command of JUDGED_COMMANDS) {
|
|
17560
|
+
const distance = editDistance2(name, command);
|
|
17561
|
+
if (distance < bestDistance)
|
|
17562
|
+
[best, bestDistance, tie] = [command, distance, false];
|
|
17563
|
+
else if (distance === bestDistance)
|
|
17564
|
+
tie = true;
|
|
17565
|
+
}
|
|
17566
|
+
return tie ? null : best;
|
|
17567
|
+
};
|
|
17568
|
+
var shellQuote = (word) => `'${word.replaceAll("'", "'\\''")}'`;
|
|
17569
|
+
var positional = (script, args) => {
|
|
17570
|
+
const word = (arg) => /^[\w./@+:=-]+$/.test(arg) ? arg : shellQuote(arg);
|
|
17571
|
+
return script.replace(/\$\{?([1-9])\}?/g, (_, n) => word(args[Number(n) - 1] ?? "")).replace(/\$\{?[@*]\}?/g, args.map(word).join(" "));
|
|
17572
|
+
};
|
|
17573
|
+
var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
17574
|
+
const sub = invocation.args[0];
|
|
17575
|
+
if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
|
|
17576
|
+
return [invocation];
|
|
17577
|
+
const dir = path16.resolve(root, invocation.dir ?? ".");
|
|
17578
|
+
if (!fs14.existsSync(dir))
|
|
17579
|
+
return [invocation];
|
|
17580
|
+
const config = gitConfig(dir, invocation, cache);
|
|
17581
|
+
const alias = configValue(config, `alias.${sub.toLowerCase()}`);
|
|
17582
|
+
if (alias === undefined) {
|
|
17583
|
+
const corrected = autocorrected(sub, config);
|
|
17584
|
+
return corrected ? [{ ...invocation, args: [corrected, ...invocation.args.slice(1)] }] : [invocation];
|
|
17585
|
+
}
|
|
17586
|
+
const rest = invocation.args.slice(1);
|
|
17587
|
+
const expanded = alias.startsWith("!") ? rawInvocations([positional(alias.slice(1), rest), ...rest.map(shellQuote)].join(" ")).map((inner) => ({
|
|
17588
|
+
...inner,
|
|
17589
|
+
dir: rebase(invocation.dir, inner.dir),
|
|
17590
|
+
...inner.tool === "git" && (invocation.config || inner.config) ? { config: [...invocation.config ?? [], ...inner.config ?? []] } : {},
|
|
17591
|
+
...inner.tool === "git" && (invocation.env || inner.env) ? { env: { ...invocation.env, ...inner.env } } : {}
|
|
17592
|
+
})) : [
|
|
17593
|
+
gitInvocation([...segmentsOf(alias)[0]?.words ?? [], ...rest], invocation.dir, invocation.env, invocation.stdin, invocation.config)
|
|
17594
|
+
];
|
|
17595
|
+
return expanded.flatMap((inner) => expandGitAliases(root, inner, cache, depth + 1));
|
|
17596
|
+
};
|
|
17597
|
+
var normalizedUrl = (url, dir) => {
|
|
17598
|
+
const trimmed = url.trim();
|
|
17599
|
+
if (/^file:\/\//i.test(trimmed))
|
|
17600
|
+
return path16.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
17601
|
+
const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
|
|
17602
|
+
const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
|
|
17603
|
+
if (!scheme && !scp)
|
|
17604
|
+
return path16.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
17605
|
+
const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
|
|
17606
|
+
return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
17607
|
+
};
|
|
17608
|
+
var rewrittenUrl = (url, config) => {
|
|
17609
|
+
for (const kind of ["pushinsteadof", "insteadof"]) {
|
|
17610
|
+
let best = null;
|
|
17611
|
+
for (const [key, prefixes] of config) {
|
|
17612
|
+
if (!key.startsWith("url.") || !key.endsWith(`.${kind}`))
|
|
17613
|
+
continue;
|
|
17614
|
+
const base = key.slice(4, -(kind.length + 1));
|
|
17615
|
+
for (const prefix of prefixes)
|
|
17616
|
+
if (url.startsWith(prefix) && prefix.length > (best?.prefix.length ?? -1))
|
|
17617
|
+
best = { base, prefix };
|
|
17618
|
+
}
|
|
17619
|
+
if (best)
|
|
17620
|
+
return best.base + url.slice(best.prefix.length);
|
|
17621
|
+
}
|
|
17622
|
+
return url;
|
|
17623
|
+
};
|
|
17624
|
+
var pushUrl = (config, remote, dir) => {
|
|
17625
|
+
const configured = configValue(config, `remote.${remote}.pushurl`) ?? configValue(config, `remote.${remote}.url`);
|
|
17626
|
+
return normalizedUrl(rewrittenUrl(configured ?? remote, config), dir);
|
|
17627
|
+
};
|
|
17628
|
+
var pushRemoteOf = (config, branch) => {
|
|
17629
|
+
const remotes = new Set;
|
|
17630
|
+
for (const key of config.keys()) {
|
|
17631
|
+
const name = /^remote\.(.+)\.url$/.exec(key)?.[1];
|
|
17632
|
+
if (name)
|
|
17633
|
+
remotes.add(name);
|
|
17634
|
+
}
|
|
17635
|
+
for (const candidate of [
|
|
17636
|
+
branch ? configValue(config, `branch.${branch}.pushremote`) : undefined,
|
|
17637
|
+
configValue(config, "remote.pushdefault"),
|
|
17638
|
+
branch ? configValue(config, `branch.${branch}.remote`) : undefined
|
|
17639
|
+
])
|
|
17640
|
+
if (candidate && candidate !== "." && remotes.has(candidate))
|
|
17641
|
+
return candidate;
|
|
17642
|
+
if (remotes.has("origin"))
|
|
17643
|
+
return "origin";
|
|
17644
|
+
return remotes.size === 1 ? [...remotes][0] : null;
|
|
17645
|
+
};
|
|
17646
|
+
var toPushRemote = (repo, remote, config) => {
|
|
17647
|
+
if (remote === null || /[$`]/.test(remote))
|
|
17648
|
+
return true;
|
|
17649
|
+
const pushRemote = pushRemoteOf(config, repo.branch);
|
|
17650
|
+
if (pushRemote === null || pushRemote === remote)
|
|
17651
|
+
return true;
|
|
17652
|
+
return pushUrl(config, remote, repo.dir) === pushUrl(config, pushRemote, repo.dir);
|
|
17653
|
+
};
|
|
16667
17654
|
var quote = (text) => `\`${text}\``;
|
|
16668
17655
|
var refusal = (action, branch, dir) => {
|
|
16669
17656
|
if (action.kind === "merge")
|
|
16670
|
-
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")}).`;
|
|
17657
|
+
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")}).`;
|
|
16671
17658
|
const plainPush = action.kind === "push" && !action.blindForce && !action.deletes;
|
|
16672
17659
|
if (dir && branch && plainPush && releaseBranch(dir, branch))
|
|
16673
|
-
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
|
|
17660
|
+
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")}.`;
|
|
16674
17661
|
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")}.`;
|
|
16675
17662
|
};
|
|
16676
17663
|
var refFacts = (repo, remote) => {
|
|
@@ -16688,35 +17675,112 @@ var refFacts = (repo, remote) => {
|
|
|
16688
17675
|
}
|
|
16689
17676
|
return facts;
|
|
16690
17677
|
};
|
|
17678
|
+
var globBranches = (repo, glob) => {
|
|
17679
|
+
const source = glob.source.startsWith("refs/") ? glob.source : `refs/heads/${glob.source}`;
|
|
17680
|
+
const [sourcePrefix, sourceSuffix = ""] = source.split("*");
|
|
17681
|
+
const [destinationPrefix, destinationSuffix = ""] = glob.destination.split("*");
|
|
17682
|
+
const listed = spawnSync11("git", [
|
|
17683
|
+
"for-each-ref",
|
|
17684
|
+
"--format=%(refname)",
|
|
17685
|
+
sourcePrefix.slice(0, sourcePrefix.lastIndexOf("/") + 1)
|
|
17686
|
+
], { cwd: repo.dir, encoding: "utf8", timeout: 5000, windowsHide: true });
|
|
17687
|
+
const names = [];
|
|
17688
|
+
for (const ref of (listed.stdout ?? "").split(`
|
|
17689
|
+
`)) {
|
|
17690
|
+
if (!ref.startsWith(sourcePrefix) || !ref.endsWith(sourceSuffix))
|
|
17691
|
+
continue;
|
|
17692
|
+
const middle = ref.slice(sourcePrefix.length, ref.length - sourceSuffix.length);
|
|
17693
|
+
const { name } = pushDestination(destinationPrefix + middle + destinationSuffix);
|
|
17694
|
+
if (name)
|
|
17695
|
+
names.push(name);
|
|
17696
|
+
}
|
|
17697
|
+
return names;
|
|
17698
|
+
};
|
|
17699
|
+
var pushedBranches = (action, repo, config, facts, remote) => {
|
|
17700
|
+
const targets = action.implicit ? [] : [...action.targets];
|
|
17701
|
+
const globs = [...action.globs ?? []];
|
|
17702
|
+
let matching = action.matching === true;
|
|
17703
|
+
const configured = action.implicit ? config.get(`remote.${remote}.push`) : undefined;
|
|
17704
|
+
if (configured?.length) {
|
|
17705
|
+
const parsed = pushRefspecs(configured);
|
|
17706
|
+
targets.push(...parsed.targets);
|
|
17707
|
+
globs.push(...parsed.globs);
|
|
17708
|
+
matching ||= parsed.matching;
|
|
17709
|
+
} else if (action.implicit) {
|
|
17710
|
+
const mode = (configValue(config, "push.default") ?? "simple").toLowerCase();
|
|
17711
|
+
const merge = repo.branch ? configValue(config, `branch.${repo.branch}.merge`) : undefined;
|
|
17712
|
+
if (mode === "matching")
|
|
17713
|
+
matching = true;
|
|
17714
|
+
else if ((mode === "upstream" || mode === "tracking") && merge?.startsWith("refs/heads/"))
|
|
17715
|
+
targets.push(merge.slice(11));
|
|
17716
|
+
else if (mode !== "nothing")
|
|
17717
|
+
targets.push(null);
|
|
17718
|
+
}
|
|
17719
|
+
if (action.allBranches)
|
|
17720
|
+
targets.push(...facts.heads);
|
|
17721
|
+
if (matching) {
|
|
17722
|
+
for (const head of facts.heads)
|
|
17723
|
+
if (facts.remoteHeads.has(head))
|
|
17724
|
+
targets.push(head);
|
|
17725
|
+
}
|
|
17726
|
+
for (const glob of globs)
|
|
17727
|
+
targets.push(...globBranches(repo, glob));
|
|
17728
|
+
return targets;
|
|
17729
|
+
};
|
|
17730
|
+
var literalReadings = (name) => {
|
|
17731
|
+
if (!/[$`]/.test(name))
|
|
17732
|
+
return [name];
|
|
17733
|
+
const withDefaults = name.replace(/\$\{\w+:?[-=]([^}$`]*)\}/g, "$1").replace(/\$\{\w+\}|\$\w+/g, "");
|
|
17734
|
+
return /[$`]/.test(withDefaults) || !withDefaults ? [] : [withDefaults];
|
|
17735
|
+
};
|
|
17736
|
+
var guardedTarget = (dir, target) => {
|
|
17737
|
+
for (const branch of literalReadings(target)) {
|
|
17738
|
+
if (guardedBranch(dir, branch))
|
|
17739
|
+
return branch;
|
|
17740
|
+
const bare = branch.startsWith("heads/") ? branch.slice(6) : null;
|
|
17741
|
+
if (bare && guardedBranch(dir, bare))
|
|
17742
|
+
return bare;
|
|
17743
|
+
}
|
|
17744
|
+
return null;
|
|
17745
|
+
};
|
|
16691
17746
|
var isTag = (facts, name) => facts.tags.has(name) && !facts.heads.has(name);
|
|
16692
|
-
var tagRefusal = (action, facts) => {
|
|
17747
|
+
var tagRefusal = (action, facts, dir) => {
|
|
16693
17748
|
const tags = [
|
|
16694
17749
|
...action.tags ?? [],
|
|
16695
17750
|
...action.targets.filter((name) => name !== null && isTag(facts, name))
|
|
16696
17751
|
];
|
|
16697
17752
|
if (!tags.length && !action.allTags)
|
|
16698
17753
|
return null;
|
|
16699
|
-
const
|
|
16700
|
-
|
|
17754
|
+
const shape = `${releaseTagPrefixOf(dir)}<version>`;
|
|
17755
|
+
const named = tags.length ? tags.join(" --release ") : shape;
|
|
17756
|
+
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")}).`;
|
|
16701
17757
|
};
|
|
16702
|
-
var
|
|
16703
|
-
const listed = spawnSync11("git", ["ls-remote", "--heads", remote
|
|
17758
|
+
var remoteHeads = (repo, remote) => {
|
|
17759
|
+
const listed = spawnSync11("git", ["ls-remote", "--heads", remote], {
|
|
16704
17760
|
cwd: repo.dir,
|
|
16705
17761
|
encoding: "utf8",
|
|
16706
17762
|
timeout: 3000,
|
|
17763
|
+
windowsHide: true,
|
|
16707
17764
|
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
16708
17765
|
});
|
|
16709
|
-
|
|
17766
|
+
if (listed.status !== 0)
|
|
17767
|
+
return null;
|
|
17768
|
+
return new Set((listed.stdout ?? "").split(`
|
|
17769
|
+
`).map((line) => line.split("\t")[1] ?? "").filter((ref) => ref.startsWith("refs/heads/")).map((ref) => ref.slice(11)));
|
|
16710
17770
|
};
|
|
16711
17771
|
var offPolicyPush = (action, repo, facts, remote) => {
|
|
16712
17772
|
const names = action.allBranches ? [...facts.heads] : action.targets.map((target) => target ?? repo.branch);
|
|
17773
|
+
let listed;
|
|
17774
|
+
const remoteHas = (branch) => (listed === undefined ? listed = remoteHeads(repo, remote) : listed)?.has(branch) ?? true;
|
|
16713
17775
|
for (const branch of names) {
|
|
16714
|
-
if (!branch ||
|
|
17776
|
+
if (!branch || /[$`]/.test(branch))
|
|
17777
|
+
continue;
|
|
17778
|
+
if (action.deleted?.includes(branch) || isTag(facts, branch))
|
|
16715
17779
|
continue;
|
|
16716
17780
|
if (facts.remoteHeads.has(branch))
|
|
16717
17781
|
continue;
|
|
16718
17782
|
const check = validateBranchNameFor(repo.dir, branch);
|
|
16719
|
-
if (check.ok || check.rule !== "allowed_pattern" || remoteHas(
|
|
17783
|
+
if (check.ok || check.rule !== "allowed_pattern" || remoteHas(branch))
|
|
16720
17784
|
continue;
|
|
16721
17785
|
return `workit: raw ${quote("git push")} onto ${branch}: ${check.error}`;
|
|
16722
17786
|
}
|
|
@@ -16738,23 +17802,50 @@ var nudgeFor = (action, host, session) => {
|
|
|
16738
17802
|
return null;
|
|
16739
17803
|
}
|
|
16740
17804
|
};
|
|
16741
|
-
var
|
|
17805
|
+
var pushRefusal = (action, repo, config) => {
|
|
17806
|
+
if (!toPushRemote(repo, action.remote, config))
|
|
17807
|
+
return null;
|
|
17808
|
+
if (action.mirror)
|
|
17809
|
+
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")}.`;
|
|
17810
|
+
const remote = action.remote ?? pushRemoteOf(config, repo.branch) ?? "origin";
|
|
17811
|
+
const facts = refFacts(repo, remote);
|
|
17812
|
+
const targets = pushedBranches(action, repo, config, facts, remote);
|
|
17813
|
+
const pushed = { ...action, targets };
|
|
17814
|
+
const offPolicy = action.allBranches ? offPolicyPush(pushed, repo, facts, remote) : null;
|
|
17815
|
+
if (offPolicy)
|
|
17816
|
+
return offPolicy;
|
|
17817
|
+
for (const target of targets) {
|
|
17818
|
+
const guarded = guardedTarget(repo.dir, target ?? repo.branch ?? "");
|
|
17819
|
+
if (guarded)
|
|
17820
|
+
return refusal(action, guarded, repo.dir);
|
|
17821
|
+
}
|
|
17822
|
+
return tagRefusal(pushed, facts, repo.dir) ?? (action.deletes ? null : offPolicyPush(pushed, repo, facts, remote));
|
|
17823
|
+
};
|
|
17824
|
+
var actionsIn = (cwd, command, dialect, cache = new Map) => {
|
|
16742
17825
|
const out = [];
|
|
16743
17826
|
const repos = new Map;
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
continue;
|
|
16747
|
-
const action = rawAction(invocation);
|
|
16748
|
-
if (!action)
|
|
16749
|
-
continue;
|
|
16750
|
-
const dir = path16.resolve(cwd, invocation.dir ?? ".");
|
|
17827
|
+
const repoFor = (relative) => {
|
|
17828
|
+
const dir = path16.resolve(cwd, relative ?? ".");
|
|
16751
17829
|
if (!repos.has(dir)) {
|
|
16752
17830
|
const repo = repoAt(dir);
|
|
16753
17831
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
16754
17832
|
}
|
|
16755
|
-
|
|
16756
|
-
|
|
16757
|
-
|
|
17833
|
+
return repos.get(dir) ?? null;
|
|
17834
|
+
};
|
|
17835
|
+
for (const raw of rawInvocations(command, dialect)) {
|
|
17836
|
+
if (raw.dir === undefined)
|
|
17837
|
+
continue;
|
|
17838
|
+
const known = raw.tool !== "git" || GIT_COMMANDS.has(raw.args[0] ?? "");
|
|
17839
|
+
if (!known && !repoFor(raw.dir))
|
|
17840
|
+
continue;
|
|
17841
|
+
for (const invocation of known ? [raw] : expandGitAliases(cwd, raw, cache)) {
|
|
17842
|
+
if (invocation.dir === undefined)
|
|
17843
|
+
continue;
|
|
17844
|
+
const action = rawAction(invocation);
|
|
17845
|
+
const repo = action ? repoFor(invocation.dir) : null;
|
|
17846
|
+
if (action && repo)
|
|
17847
|
+
out.push({ action, repo, invocation });
|
|
17848
|
+
}
|
|
16758
17849
|
}
|
|
16759
17850
|
return out;
|
|
16760
17851
|
};
|
|
@@ -16783,31 +17874,18 @@ var unseenNudges = (input, nudges, store) => {
|
|
|
16783
17874
|
};
|
|
16784
17875
|
function rawGitPre(input, command, options = {}) {
|
|
16785
17876
|
try {
|
|
16786
|
-
if (!mentionsRawTool(command))
|
|
16787
|
-
return NONE2;
|
|
16788
17877
|
const dialect = dialectOf(input);
|
|
16789
17878
|
const nudges = new Map;
|
|
16790
17879
|
let store = null;
|
|
16791
|
-
|
|
17880
|
+
const cache = new Map;
|
|
17881
|
+
for (const { action, repo, invocation } of actionsIn(input.cwd, command, dialect, cache)) {
|
|
16792
17882
|
store ??= repo.location.dir;
|
|
16793
17883
|
if (action.kind === "merge")
|
|
16794
17884
|
return deny(refusal(action, null));
|
|
16795
|
-
if (action.kind === "push"
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
const branch = target ?? repo.branch;
|
|
16800
|
-
if (branch && guardedBranch(repo.dir, branch))
|
|
16801
|
-
return deny(refusal(action, branch, repo.dir));
|
|
16802
|
-
}
|
|
16803
|
-
const remote = action.remote ?? pushRemoteName(repo.dir, repo.branch) ?? "origin";
|
|
16804
|
-
const facts = refFacts(repo, remote);
|
|
16805
|
-
const tagDeny = tagRefusal(action, facts);
|
|
16806
|
-
if (tagDeny)
|
|
16807
|
-
return deny(tagDeny);
|
|
16808
|
-
const nameDeny = action.deletes ? null : offPolicyPush(action, repo, facts, remote);
|
|
16809
|
-
if (nameDeny)
|
|
16810
|
-
return deny(nameDeny);
|
|
17885
|
+
if (action.kind === "push") {
|
|
17886
|
+
const refused = pushRefusal(action, repo, gitConfig(repo.dir, invocation, cache));
|
|
17887
|
+
if (refused)
|
|
17888
|
+
return deny(refused);
|
|
16811
17889
|
}
|
|
16812
17890
|
const nudge = nudgeFor(action, input.host, input.session.id);
|
|
16813
17891
|
if (nudge && !nudges.has(nudgeKind(action)))
|
|
@@ -16820,11 +17898,17 @@ function rawGitPre(input, command, options = {}) {
|
|
|
16820
17898
|
const shown = unseenNudges(input, nudges, store);
|
|
16821
17899
|
return shown.length ? { kind: "context", text: shown.join(`
|
|
16822
17900
|
`) } : NONE2;
|
|
16823
|
-
} catch {
|
|
16824
|
-
return NONE2;
|
|
17901
|
+
} catch (error) {
|
|
17902
|
+
return error instanceof ShellAnalysisError ? analysisDenial(error) : NONE2;
|
|
16825
17903
|
}
|
|
16826
17904
|
}
|
|
16827
17905
|
var deny = (reason) => ({ kind: "deny", reason, unblock: null });
|
|
17906
|
+
var SPLIT_IT = "Split it into simpler commands (no deeply nested substitutions or huge brace lists) and run them one at a time.";
|
|
17907
|
+
var analysisDenial = (error) => ({
|
|
17908
|
+
kind: "deny",
|
|
17909
|
+
reason: `workit: the shell hook could not analyze this command (${error.message}), so it does not run. ${SPLIT_IT}`,
|
|
17910
|
+
unblock: SPLIT_IT
|
|
17911
|
+
});
|
|
16828
17912
|
var MARKER_TTL_SECONDS = 3600;
|
|
16829
17913
|
var markerFile = (repo, session, key) => path16.join(repo.location.dir, "hooks", `commit-${createHash12("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
|
|
16830
17914
|
var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash12("sha256").update(command).digest("hex")}`;
|
|
@@ -16912,20 +17996,28 @@ var UNKNOWABLE = /[$`*?[\]{}~]/u;
|
|
|
16912
17996
|
var SWITCH_CREATE = new Set(["-c", "--create", "-C", "--force-create", "--orphan"]);
|
|
16913
17997
|
var CHECKOUT_CREATE = new Set(["-b", "-B", "--orphan"]);
|
|
16914
17998
|
var WORKTREE_CREATE = new Set(["-b", "-B"]);
|
|
17999
|
+
var SUBTREE_CREATE = new Set(["-b", "--branch"]);
|
|
16915
18000
|
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"]));
|
|
16916
18001
|
var BRANCH_RENAME = new Set(["-m", "-M", "--move", "-c", "-C", "--copy"]);
|
|
18002
|
+
var longOption = (name, flags) => flags.has(name) || name.length >= 3 && [...flags].some((flag) => flag.startsWith("--") && flag.startsWith(name));
|
|
18003
|
+
var shortsOf = (flags) => [...flags].filter((flag) => /^-[^-]$/u.test(flag)).join("").replaceAll("-", "");
|
|
16917
18004
|
var flagValue = (args, flags) => {
|
|
18005
|
+
const shorts = shortsOf(flags);
|
|
16918
18006
|
for (let index = 1;index < args.length; index++) {
|
|
16919
18007
|
const arg = args[index];
|
|
16920
18008
|
if (arg === "--")
|
|
16921
18009
|
return null;
|
|
16922
|
-
if (
|
|
16923
|
-
|
|
16924
|
-
|
|
16925
|
-
|
|
16926
|
-
return arg.slice(eq + 1);
|
|
16927
|
-
|
|
16928
|
-
|
|
18010
|
+
if (arg.startsWith("--")) {
|
|
18011
|
+
const eq = arg.indexOf("=");
|
|
18012
|
+
if (!longOption(eq > 0 ? arg.slice(0, eq) : arg, flags))
|
|
18013
|
+
continue;
|
|
18014
|
+
return eq > 0 ? arg.slice(eq + 1) : args[index + 1] ?? null;
|
|
18015
|
+
}
|
|
18016
|
+
if (!arg.startsWith("-") || arg.length < 2)
|
|
18017
|
+
continue;
|
|
18018
|
+
for (let at = 1;at < arg.length; at++)
|
|
18019
|
+
if (shorts.includes(arg[at]))
|
|
18020
|
+
return at + 1 < arg.length ? arg.slice(at + 1) : args[index + 1] ?? null;
|
|
16929
18021
|
}
|
|
16930
18022
|
return null;
|
|
16931
18023
|
};
|
|
@@ -16958,55 +18050,114 @@ var branchCommandTarget = (args) => {
|
|
|
16958
18050
|
positionals.push(...args.slice(index + 1));
|
|
16959
18051
|
break;
|
|
16960
18052
|
}
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
18053
|
+
if (arg.startsWith("--")) {
|
|
18054
|
+
const flag = arg.split("=", 1)[0];
|
|
18055
|
+
if (longOption(flag, BRANCH_NO_CREATE))
|
|
18056
|
+
return null;
|
|
18057
|
+
if (longOption(flag, BRANCH_RENAME))
|
|
18058
|
+
rename = true;
|
|
18059
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
18060
|
+
const shorts = arg.slice(1).split("");
|
|
18061
|
+
if (shorts.some((short) => BRANCH_NO_CREATE.has(`-${short}`)))
|
|
18062
|
+
return null;
|
|
18063
|
+
if (shorts.some((short) => BRANCH_RENAME.has(`-${short}`)))
|
|
18064
|
+
rename = true;
|
|
18065
|
+
} else
|
|
16967
18066
|
positionals.push(arg);
|
|
16968
18067
|
}
|
|
16969
18068
|
if (positionals.length < 1 || positionals.length > 2)
|
|
16970
18069
|
return null;
|
|
16971
18070
|
return rename ? positionals.at(-1) ?? null : positionals[0];
|
|
16972
18071
|
};
|
|
16973
|
-
var
|
|
16974
|
-
const
|
|
16975
|
-
|
|
16976
|
-
|
|
18072
|
+
var positionalsOf = (args, skip, values = new Set) => {
|
|
18073
|
+
const found = [];
|
|
18074
|
+
for (let index = skip;index < args.length; index++) {
|
|
18075
|
+
const arg = args[index];
|
|
18076
|
+
if (arg === "--")
|
|
18077
|
+
return [...found, ...args.slice(index + 1)];
|
|
18078
|
+
if (values.has(arg))
|
|
18079
|
+
index++;
|
|
18080
|
+
else if (!arg.startsWith("-") || arg === "-")
|
|
18081
|
+
found.push(arg);
|
|
18082
|
+
}
|
|
18083
|
+
return found;
|
|
16977
18084
|
};
|
|
16978
|
-
var
|
|
16979
|
-
|
|
18085
|
+
var localHead = (ref) => ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : null;
|
|
18086
|
+
var updateRefTargets = (args, stdin) => {
|
|
18087
|
+
if (args.some((arg) => arg === "-d" || arg === "--delete"))
|
|
16980
18088
|
return [];
|
|
16981
|
-
|
|
16982
|
-
|
|
16983
|
-
|
|
18089
|
+
if (args.includes("--stdin"))
|
|
18090
|
+
return (stdin ?? "").split(/[\n\0]/u).map((line) => /^\s*(?:create|update)\s+(\S+)/u.exec(line)?.[1] ?? "").map(localHead).filter((name) => name !== null);
|
|
18091
|
+
const [ref] = positionalsOf(args, 1, new Set(["-m"]));
|
|
18092
|
+
const name = ref ? localHead(ref) : null;
|
|
18093
|
+
return name ? [name] : [];
|
|
18094
|
+
};
|
|
18095
|
+
var symbolicRefTarget = (args) => {
|
|
18096
|
+
if (args.some((arg) => arg === "-d" || arg === "--delete"))
|
|
18097
|
+
return null;
|
|
18098
|
+
const [, ref] = positionalsOf(args, 1, new Set(["-m"]));
|
|
18099
|
+
return ref ? localHead(ref) : null;
|
|
18100
|
+
};
|
|
18101
|
+
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"]));
|
|
18102
|
+
var fetchTargets = (args, stdin) => {
|
|
18103
|
+
if (args.includes("--all") || args.includes("--multiple"))
|
|
18104
|
+
return [];
|
|
18105
|
+
const specs = args.includes("--stdin") ? (stdin ?? "").split(/\s+/u).filter(Boolean) : positionalsOf(args, 1, FETCH_VALUES).slice(1);
|
|
18106
|
+
const names = [];
|
|
18107
|
+
for (const raw of specs) {
|
|
18108
|
+
const colon = raw.indexOf(":");
|
|
18109
|
+
const destination = colon >= 0 ? raw.slice(colon + 1) : "";
|
|
18110
|
+
if (!destination || destination.includes("*"))
|
|
16984
18111
|
continue;
|
|
16985
|
-
const
|
|
16986
|
-
if (
|
|
16987
|
-
|
|
18112
|
+
const name = destination.startsWith("refs/") ? localHead(destination) : destination;
|
|
18113
|
+
if (name)
|
|
18114
|
+
names.push(name);
|
|
16988
18115
|
}
|
|
16989
|
-
return
|
|
18116
|
+
return names;
|
|
18117
|
+
};
|
|
18118
|
+
var localPushTargets = (args) => {
|
|
18119
|
+
const action = pushAction(args);
|
|
18120
|
+
if (action?.kind !== "push" || action.remote !== "." || action.deletes)
|
|
18121
|
+
return [];
|
|
18122
|
+
return action.targets.filter((name) => name !== null);
|
|
18123
|
+
};
|
|
18124
|
+
var gitBranchCreations = (args, stdin) => {
|
|
18125
|
+
const [sub, second] = args;
|
|
18126
|
+
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)] : [];
|
|
18127
|
+
return targets.filter((target) => target !== null && target !== "" && !target.startsWith("-") && !UNKNOWABLE.test(target));
|
|
16990
18128
|
};
|
|
18129
|
+
var targetsOf = (invocations) => invocations.flatMap((invocation) => invocation.tool === "git" ? gitBranchCreations(invocation.args, invocation.stdin).map((branch) => ({
|
|
18130
|
+
branch,
|
|
18131
|
+
dir: invocation.dir
|
|
18132
|
+
})) : []);
|
|
16991
18133
|
var localBranchExists = (dir, branch) => spawnSync12("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], {
|
|
16992
18134
|
cwd: dir,
|
|
16993
18135
|
stdio: "ignore",
|
|
16994
18136
|
timeout: 5000
|
|
16995
18137
|
}).status === 0;
|
|
18138
|
+
var judgedDir = (root, dir) => {
|
|
18139
|
+
if (dir === undefined)
|
|
18140
|
+
return null;
|
|
18141
|
+
if (dir === null)
|
|
18142
|
+
return root;
|
|
18143
|
+
const resolved = path17.resolve(root, dir);
|
|
18144
|
+
return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
|
|
18145
|
+
};
|
|
16996
18146
|
var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
16997
18147
|
let judged = false;
|
|
16998
|
-
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
const dir = target.dir === null ? root : path17.resolve(root, target.dir);
|
|
17002
|
-
if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
|
|
18148
|
+
const cache = new Map;
|
|
18149
|
+
for (const raw of rawInvocations(command, dialect)) {
|
|
18150
|
+
if (raw.tool !== "git" || judgedDir(root, raw.dir) === null)
|
|
17003
18151
|
continue;
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
18152
|
+
for (const target of targetsOf(expandGitAliases(root, raw, cache))) {
|
|
18153
|
+
const dir = judgedDir(root, target.dir);
|
|
18154
|
+
if (dir === null || localBranchExists(dir, target.branch))
|
|
18155
|
+
continue;
|
|
18156
|
+
judged = true;
|
|
18157
|
+
const check = validateBranchNameFor(dir, target.branch);
|
|
18158
|
+
if (!check.ok)
|
|
18159
|
+
return check;
|
|
18160
|
+
}
|
|
17010
18161
|
}
|
|
17011
18162
|
return judged ? { ok: true } : null;
|
|
17012
18163
|
};
|
|
@@ -20281,7 +21432,14 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
20281
21432
|
var TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
20282
21433
|
// packages/workit-core/src/hooks/policy.ts
|
|
20283
21434
|
var shellPolicy = (cwd, command, dialect = "posix") => {
|
|
20284
|
-
|
|
21435
|
+
let policy;
|
|
21436
|
+
try {
|
|
21437
|
+
policy = shellBranchPolicyViolation(cwd, command, dialect);
|
|
21438
|
+
} catch (error) {
|
|
21439
|
+
if (error instanceof ShellAnalysisError)
|
|
21440
|
+
return analysisDenial(error);
|
|
21441
|
+
throw error;
|
|
21442
|
+
}
|
|
20285
21443
|
return policy && !policy.ok ? { kind: "deny", reason: `branch_policy_denied: ${policy.error}`, unblock: null } : { kind: "none" };
|
|
20286
21444
|
};
|
|
20287
21445
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
@@ -20310,11 +21468,11 @@ var exempt = (cwd, root, file, plans) => {
|
|
|
20310
21468
|
const segments = posix.split("/");
|
|
20311
21469
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
20312
21470
|
};
|
|
20313
|
-
var
|
|
21471
|
+
var PREFIXES2 = new Set(["sudo", "command", "env", "nohup", "time", "exec", "xargs"]);
|
|
20314
21472
|
var operands = (words) => words.filter((item) => !item.startsWith("-"));
|
|
20315
21473
|
var editsOf = (input) => {
|
|
20316
21474
|
let words = input;
|
|
20317
|
-
while (words.length && (
|
|
21475
|
+
while (words.length && (PREFIXES2.has(words[0]) || /^\w+=/.test(words[0])))
|
|
20318
21476
|
words = words.slice(1);
|
|
20319
21477
|
const [verb, ...args] = words;
|
|
20320
21478
|
const name = (verb?.split(/[\\/]/).at(-1) ?? "").toLowerCase();
|