@brainervirus/workit-codex 8.12.1 → 8.12.3
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.
|
@@ -18033,7 +18033,76 @@ var writeSessionMarker = (file, marker) => {
|
|
|
18033
18033
|
};
|
|
18034
18034
|
|
|
18035
18035
|
// packages/workit-core/src/hooks/shell-words.ts
|
|
18036
|
-
|
|
18036
|
+
class ShellAnalysisError extends Error {
|
|
18037
|
+
}
|
|
18038
|
+
var MAX_NESTING = 64;
|
|
18039
|
+
var OPEN = "";
|
|
18040
|
+
var COMMA = "";
|
|
18041
|
+
var CLOSE = "";
|
|
18042
|
+
var MARKERS = /[\uE000-\uE002]/u;
|
|
18043
|
+
var literal2 = (word) => word.replaceAll(OPEN, "{").replaceAll(COMMA, ",").replaceAll(CLOSE, "}");
|
|
18044
|
+
var BRACE_LIMIT = 64;
|
|
18045
|
+
var BRACE_PENDING = 512;
|
|
18046
|
+
var BRACE_DEPTH = 16;
|
|
18047
|
+
var braceGroup = (word) => {
|
|
18048
|
+
for (let start = 0;start < word.length; start++) {
|
|
18049
|
+
if (word[start] !== OPEN)
|
|
18050
|
+
continue;
|
|
18051
|
+
let depth = 0;
|
|
18052
|
+
let end = start;
|
|
18053
|
+
const commas = [];
|
|
18054
|
+
for (;end < word.length; end++) {
|
|
18055
|
+
if (word[end] === OPEN)
|
|
18056
|
+
depth++;
|
|
18057
|
+
else if (word[end] === CLOSE && --depth === 0)
|
|
18058
|
+
break;
|
|
18059
|
+
else if (word[end] === COMMA && depth === 1)
|
|
18060
|
+
commas.push(end);
|
|
18061
|
+
}
|
|
18062
|
+
if (end < word.length && commas.length)
|
|
18063
|
+
return { start, end, commas };
|
|
18064
|
+
}
|
|
18065
|
+
return null;
|
|
18066
|
+
};
|
|
18067
|
+
var expandBraces = (word) => {
|
|
18068
|
+
let depth = 0;
|
|
18069
|
+
for (const char of word) {
|
|
18070
|
+
if (char === OPEN && ++depth > BRACE_DEPTH)
|
|
18071
|
+
return [literal2(word)];
|
|
18072
|
+
if (char === CLOSE && depth > 0)
|
|
18073
|
+
depth--;
|
|
18074
|
+
}
|
|
18075
|
+
const done = new Set;
|
|
18076
|
+
const queue = [word];
|
|
18077
|
+
const queued = new Set(queue);
|
|
18078
|
+
for (let at = 0;at < queue.length; at++) {
|
|
18079
|
+
const current = queue[at];
|
|
18080
|
+
const group = braceGroup(current);
|
|
18081
|
+
if (!group) {
|
|
18082
|
+
const text = literal2(current);
|
|
18083
|
+
if (text)
|
|
18084
|
+
done.add(text);
|
|
18085
|
+
if (done.size > BRACE_LIMIT)
|
|
18086
|
+
return [literal2(word)];
|
|
18087
|
+
continue;
|
|
18088
|
+
}
|
|
18089
|
+
const pre = current.slice(0, group.start);
|
|
18090
|
+
const post = current.slice(group.end + 1);
|
|
18091
|
+
let from = group.start + 1;
|
|
18092
|
+
for (const comma of [...group.commas, group.end]) {
|
|
18093
|
+
const next = pre + current.slice(from, comma) + post;
|
|
18094
|
+
from = comma + 1;
|
|
18095
|
+
if (queued.has(next))
|
|
18096
|
+
continue;
|
|
18097
|
+
queued.add(next);
|
|
18098
|
+
queue.push(next);
|
|
18099
|
+
}
|
|
18100
|
+
if (queue.length - at > BRACE_PENDING)
|
|
18101
|
+
return [literal2(word)];
|
|
18102
|
+
}
|
|
18103
|
+
return [...done];
|
|
18104
|
+
};
|
|
18105
|
+
var closingQuote = (command, start, dialect, nesting = 0) => {
|
|
18037
18106
|
const quote = command[start];
|
|
18038
18107
|
for (let index = start + 1;index < command.length; index++) {
|
|
18039
18108
|
const char = command[index];
|
|
@@ -18050,51 +18119,265 @@ var closingQuote = (command, start, dialect) => {
|
|
|
18050
18119
|
index++;
|
|
18051
18120
|
continue;
|
|
18052
18121
|
}
|
|
18122
|
+
if (dialect === "posix" && char === "$" && command[index + 1] === "(") {
|
|
18123
|
+
index = substitutionEnd(command, index + 1, nesting + 1);
|
|
18124
|
+
continue;
|
|
18125
|
+
}
|
|
18126
|
+
if (dialect === "posix" && char === "`") {
|
|
18127
|
+
index = backtickEnd(command, index);
|
|
18128
|
+
continue;
|
|
18129
|
+
}
|
|
18053
18130
|
if (char === '"')
|
|
18054
18131
|
return index;
|
|
18055
18132
|
}
|
|
18056
18133
|
return -1;
|
|
18057
18134
|
};
|
|
18135
|
+
var backtickEnd = (command, start) => {
|
|
18136
|
+
for (let index = start + 1;index < command.length; index++) {
|
|
18137
|
+
if (command[index] === "\\")
|
|
18138
|
+
index++;
|
|
18139
|
+
else if (command[index] === "`")
|
|
18140
|
+
return index;
|
|
18141
|
+
}
|
|
18142
|
+
return command.length;
|
|
18143
|
+
};
|
|
18144
|
+
var heredocDelimiter = (command, start) => {
|
|
18145
|
+
let index = start;
|
|
18146
|
+
if (command[index] === "-")
|
|
18147
|
+
index++;
|
|
18148
|
+
while (command[index] === " " || command[index] === "\t")
|
|
18149
|
+
index++;
|
|
18150
|
+
let delimiter = "";
|
|
18151
|
+
for (;index < command.length && !/[\s;&|<>()]/.test(command[index]); index++) {
|
|
18152
|
+
const char = command[index];
|
|
18153
|
+
if (char === "'" || char === '"') {
|
|
18154
|
+
const end = command.indexOf(char, index + 1);
|
|
18155
|
+
if (end < 0)
|
|
18156
|
+
break;
|
|
18157
|
+
delimiter += command.slice(index + 1, end);
|
|
18158
|
+
index = end;
|
|
18159
|
+
} else if (char === "\\")
|
|
18160
|
+
delimiter += command[++index] ?? "";
|
|
18161
|
+
else
|
|
18162
|
+
delimiter += char;
|
|
18163
|
+
}
|
|
18164
|
+
return { delimiter, end: index - 1 };
|
|
18165
|
+
};
|
|
18166
|
+
var skipHeredocs = (command, newline, delimiters) => {
|
|
18167
|
+
let index = newline;
|
|
18168
|
+
while (delimiters.length) {
|
|
18169
|
+
const delimiter = delimiters.shift();
|
|
18170
|
+
for (;; ) {
|
|
18171
|
+
const lineEnd = command.indexOf(`
|
|
18172
|
+
`, index + 1);
|
|
18173
|
+
const line = command.slice(index + 1, lineEnd < 0 ? undefined : lineEnd);
|
|
18174
|
+
index = lineEnd < 0 ? command.length : lineEnd;
|
|
18175
|
+
if (line.trim() === delimiter || lineEnd < 0)
|
|
18176
|
+
break;
|
|
18177
|
+
}
|
|
18178
|
+
}
|
|
18179
|
+
return index;
|
|
18180
|
+
};
|
|
18181
|
+
var substitutionEnd = (command, start, nesting = 0) => {
|
|
18182
|
+
if (nesting > MAX_NESTING)
|
|
18183
|
+
throw new ShellAnalysisError("substitutions nest too deep");
|
|
18184
|
+
let depth = 0;
|
|
18185
|
+
let wordStart = true;
|
|
18186
|
+
const heredocs = [];
|
|
18187
|
+
for (let index = start;index < command.length; index++) {
|
|
18188
|
+
const char = command[index];
|
|
18189
|
+
const atWordStart = wordStart;
|
|
18190
|
+
wordStart = /[\s;&|()]/.test(char);
|
|
18191
|
+
if (char === "\\")
|
|
18192
|
+
index++;
|
|
18193
|
+
else if (char === `
|
|
18194
|
+
` && heredocs.length) {
|
|
18195
|
+
index = skipHeredocs(command, index, heredocs);
|
|
18196
|
+
wordStart = true;
|
|
18197
|
+
} else if (char === "'" || char === '"') {
|
|
18198
|
+
const end = closingQuote(command, index, "posix", nesting);
|
|
18199
|
+
if (end < 0)
|
|
18200
|
+
return command.length;
|
|
18201
|
+
index = end;
|
|
18202
|
+
} else if (char === "`")
|
|
18203
|
+
index = backtickEnd(command, index);
|
|
18204
|
+
else if (char === "#" && atWordStart) {
|
|
18205
|
+
const newline = command.indexOf(`
|
|
18206
|
+
`, index);
|
|
18207
|
+
index = newline < 0 ? command.length : newline - 1;
|
|
18208
|
+
} else if (char === "<" && command[index + 1] === "<" && command[index + 2] !== "<") {
|
|
18209
|
+
const { delimiter, end } = heredocDelimiter(command, index + 2);
|
|
18210
|
+
if (delimiter)
|
|
18211
|
+
heredocs.push(delimiter);
|
|
18212
|
+
index = end;
|
|
18213
|
+
} else if (char === "<" && command[index + 1] === "<")
|
|
18214
|
+
index += 2;
|
|
18215
|
+
else if (char === "$" && command[index + 1] === "(")
|
|
18216
|
+
index = substitutionEnd(command, index + 1, nesting + 1);
|
|
18217
|
+
else if (char === "(")
|
|
18218
|
+
depth++;
|
|
18219
|
+
else if (char === ")" && --depth === 0)
|
|
18220
|
+
return index;
|
|
18221
|
+
}
|
|
18222
|
+
return command.length;
|
|
18223
|
+
};
|
|
18058
18224
|
var unquote = (body, quote, dialect) => {
|
|
18059
18225
|
if (quote === "'")
|
|
18060
18226
|
return dialect === "powershell" ? body.replaceAll("''", "'") : body;
|
|
18061
|
-
return dialect === "posix" ? body.replace(/\\(["\\$`])/g, "$1") : body.replace(/`(.)/g, "$1");
|
|
18227
|
+
return dialect === "posix" ? body.replace(/\\\n/g, "").replace(/\\(["\\$`])/g, "$1") : body.replace(/`(.)/g, "$1");
|
|
18228
|
+
};
|
|
18229
|
+
var C_ESCAPES = {
|
|
18230
|
+
n: `
|
|
18231
|
+
`,
|
|
18232
|
+
t: "\t",
|
|
18233
|
+
r: "\r",
|
|
18234
|
+
a: "\x07",
|
|
18235
|
+
b: "\b",
|
|
18236
|
+
e: "\x1B",
|
|
18237
|
+
E: "\x1B",
|
|
18238
|
+
f: "\f",
|
|
18239
|
+
v: "\v"
|
|
18240
|
+
};
|
|
18241
|
+
var ansiC = (command, start) => {
|
|
18242
|
+
let text = "";
|
|
18243
|
+
let index = start + 1;
|
|
18244
|
+
for (;index < command.length && command[index] !== "'"; index++) {
|
|
18245
|
+
const char = command[index];
|
|
18246
|
+
if (char !== "\\" || index + 1 >= command.length) {
|
|
18247
|
+
text += char;
|
|
18248
|
+
continue;
|
|
18249
|
+
}
|
|
18250
|
+
const rest = command.slice(++index);
|
|
18251
|
+
const hex = /^x([0-9a-fA-F]{1,2})/.exec(rest);
|
|
18252
|
+
const octal = /^[0-7]{1,3}/.exec(rest);
|
|
18253
|
+
if (hex) {
|
|
18254
|
+
text += String.fromCharCode(Number.parseInt(hex[1], 16));
|
|
18255
|
+
index += hex[0].length - 1;
|
|
18256
|
+
} else if (octal) {
|
|
18257
|
+
text += String.fromCharCode(Number.parseInt(octal[0], 8));
|
|
18258
|
+
index += octal[0].length - 1;
|
|
18259
|
+
} else
|
|
18260
|
+
text += C_ESCAPES[rest[0]] ?? rest[0];
|
|
18261
|
+
}
|
|
18262
|
+
return { text, end: index };
|
|
18263
|
+
};
|
|
18264
|
+
var substitutions = (body) => {
|
|
18265
|
+
const found = [];
|
|
18266
|
+
for (let index = 0;index < body.length; index++) {
|
|
18267
|
+
const char = body[index];
|
|
18268
|
+
if (char === "\\")
|
|
18269
|
+
index++;
|
|
18270
|
+
else if (char === "`") {
|
|
18271
|
+
const end = backtickEnd(body, index);
|
|
18272
|
+
found.push(body.slice(index + 1, end).replace(/\\(.)/g, "$1"));
|
|
18273
|
+
index = end;
|
|
18274
|
+
} else if (char === "$" && body[index + 1] === "(") {
|
|
18275
|
+
const end = substitutionEnd(body, index + 1);
|
|
18276
|
+
found.push(body.slice(index + 2, end));
|
|
18277
|
+
index = end;
|
|
18278
|
+
}
|
|
18279
|
+
}
|
|
18280
|
+
return found;
|
|
18281
|
+
};
|
|
18282
|
+
var PLAIN_POSIX = /[^\s'"\\`$(){},<>|;&#]+/uy;
|
|
18283
|
+
var PLAIN_POWERSHELL = /[^\s'"`(){}<>|;&#]+/uy;
|
|
18284
|
+
var arithmeticEnd = (command, start) => {
|
|
18285
|
+
const end = substitutionEnd(command, start);
|
|
18286
|
+
return command[end - 1] === ")" && end > start + 2 ? end : 0;
|
|
18062
18287
|
};
|
|
18063
18288
|
var segmentsOf = (command, dialect = "posix") => {
|
|
18289
|
+
try {
|
|
18290
|
+
return tokenize(command, dialect);
|
|
18291
|
+
} catch (error) {
|
|
18292
|
+
const why = error instanceof ShellAnalysisError ? error.message : String(error);
|
|
18293
|
+
return [{ words: [], redirects: [], unanalyzable: why }];
|
|
18294
|
+
}
|
|
18295
|
+
};
|
|
18296
|
+
var tokenize = (command, dialect) => {
|
|
18297
|
+
const posix = dialect === "posix";
|
|
18064
18298
|
const segments = [];
|
|
18065
18299
|
let current = { words: [], redirects: [] };
|
|
18066
18300
|
let word = "";
|
|
18067
18301
|
let inWord = false;
|
|
18068
18302
|
let pending = null;
|
|
18069
18303
|
const heredocs = [];
|
|
18070
|
-
const escape =
|
|
18304
|
+
const escape = posix ? "\\" : "`";
|
|
18071
18305
|
const flushWord = () => {
|
|
18072
18306
|
if (!inWord)
|
|
18073
18307
|
return;
|
|
18308
|
+
const text = MARKERS.test(word) ? literal2(word) : word;
|
|
18074
18309
|
if (pending === "redirect") {
|
|
18075
|
-
if (!
|
|
18076
|
-
current.redirects.push(
|
|
18310
|
+
if (!text.startsWith("&"))
|
|
18311
|
+
current.redirects.push(text);
|
|
18077
18312
|
} else if (pending === "heredoc")
|
|
18078
|
-
heredocs.push(
|
|
18313
|
+
heredocs.push({ delimiter: text.replace(/^-/, ""), owner: current });
|
|
18314
|
+
else if (pending === "herestring")
|
|
18315
|
+
(current.stdin ??= []).push(text);
|
|
18079
18316
|
else if (pending !== "input")
|
|
18080
|
-
current.words.push(word);
|
|
18317
|
+
current.words.push(...MARKERS.test(word) ? expandBraces(word) : [word]);
|
|
18081
18318
|
pending = null;
|
|
18082
18319
|
word = "";
|
|
18083
18320
|
inWord = false;
|
|
18084
18321
|
};
|
|
18085
18322
|
const flushSegment = () => {
|
|
18086
18323
|
flushWord();
|
|
18087
|
-
if (current.words.length || current.redirects.length)
|
|
18324
|
+
if (current.words.length || current.redirects.length || current.stdin || current.subs)
|
|
18088
18325
|
segments.push(current);
|
|
18089
18326
|
current = { words: [], redirects: [] };
|
|
18090
18327
|
};
|
|
18328
|
+
const group = (kind) => {
|
|
18329
|
+
flushSegment();
|
|
18330
|
+
pending = null;
|
|
18331
|
+
segments.push({ words: [], redirects: [], group: kind });
|
|
18332
|
+
};
|
|
18333
|
+
const substitution = (inner, text) => {
|
|
18334
|
+
(current.subs ??= []).push(inner);
|
|
18335
|
+
word += text;
|
|
18336
|
+
inWord = true;
|
|
18337
|
+
};
|
|
18338
|
+
const plain = posix ? PLAIN_POSIX : PLAIN_POWERSHELL;
|
|
18091
18339
|
for (let index = 0;index < command.length; index++) {
|
|
18340
|
+
plain.lastIndex = index;
|
|
18341
|
+
const run = plain.exec(command);
|
|
18342
|
+
if (run) {
|
|
18343
|
+
word += run[0];
|
|
18344
|
+
inWord = true;
|
|
18345
|
+
index += run[0].length - 1;
|
|
18346
|
+
continue;
|
|
18347
|
+
}
|
|
18092
18348
|
const char = command[index];
|
|
18093
|
-
|
|
18349
|
+
const next = command[index + 1];
|
|
18350
|
+
if (char === escape && (next === `
|
|
18351
|
+
` || next === "\r" && command[index + 2] === `
|
|
18352
|
+
`))
|
|
18353
|
+
index += next === "\r" ? 2 : 1;
|
|
18354
|
+
else if (char === "#" && !inWord) {
|
|
18355
|
+
const newline = command.indexOf(`
|
|
18356
|
+
`, index);
|
|
18357
|
+
index = (newline < 0 ? command.length : newline) - 1;
|
|
18358
|
+
} else if (!posix && char === "<" && next === "#") {
|
|
18359
|
+
const end = command.indexOf("#>", index + 2);
|
|
18360
|
+
index = end < 0 ? command.length : end + 1;
|
|
18361
|
+
} else if (posix && char === "$" && next === "'") {
|
|
18362
|
+
const { text, end } = ansiC(command, index + 1);
|
|
18363
|
+
word += text;
|
|
18364
|
+
inWord = true;
|
|
18365
|
+
index = end;
|
|
18366
|
+
} else if (posix && char === "$" && next === '"')
|
|
18367
|
+
continue;
|
|
18368
|
+
else if (char === "'" || char === '"') {
|
|
18094
18369
|
const end = closingQuote(command, index, dialect);
|
|
18095
|
-
|
|
18370
|
+
const body = command.slice(index + 1, end < 0 ? undefined : end);
|
|
18371
|
+
if (posix && char === '"' && /\$\(|`/.test(body))
|
|
18372
|
+
(current.subs ??= []).push(...substitutions(body));
|
|
18373
|
+
word += unquote(body, char, dialect);
|
|
18096
18374
|
inWord = true;
|
|
18097
18375
|
index = end < 0 ? command.length : end;
|
|
18376
|
+
} else if (posix && char === "`") {
|
|
18377
|
+
const end = backtickEnd(command, index);
|
|
18378
|
+
const inner = command.slice(index + 1, end);
|
|
18379
|
+
substitution(inner.replace(/\\(.)/g, "$1"), `\`${inner}\``);
|
|
18380
|
+
index = end;
|
|
18098
18381
|
} else if (char === escape && index + 1 < command.length) {
|
|
18099
18382
|
word += command[++index];
|
|
18100
18383
|
inWord = true;
|
|
@@ -18102,26 +18385,56 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
18102
18385
|
`) {
|
|
18103
18386
|
flushSegment();
|
|
18104
18387
|
while (heredocs.length) {
|
|
18105
|
-
const delimiter = heredocs.shift();
|
|
18388
|
+
const { delimiter, owner } = heredocs.shift();
|
|
18106
18389
|
const lines = command.slice(index + 1).split(`
|
|
18107
18390
|
`);
|
|
18108
18391
|
const at = lines.findIndex((line) => line.trim() === delimiter);
|
|
18109
|
-
|
|
18392
|
+
(owner.stdin ??= []).push((at < 0 ? lines : lines.slice(0, at)).join(`
|
|
18393
|
+
`));
|
|
18394
|
+
index += (at < 0 ? lines : lines.slice(0, at + 1)).join(`
|
|
18110
18395
|
`).length + 1;
|
|
18111
|
-
index += skipped;
|
|
18112
18396
|
}
|
|
18113
18397
|
} else if (/\s/.test(char))
|
|
18114
18398
|
flushWord();
|
|
18115
|
-
else if (char === "("
|
|
18399
|
+
else if (posix && char === "(" && inWord && word.endsWith("$")) {
|
|
18400
|
+
const end = substitutionEnd(command, index);
|
|
18401
|
+
const inner = command.slice(index + 1, end);
|
|
18402
|
+
substitution(inner, `(${inner})`);
|
|
18403
|
+
index = end;
|
|
18404
|
+
} else if (posix && char === "(" && (pending === "input" || pending === "redirect")) {
|
|
18405
|
+
const sign = pending === "input" ? "<" : ">";
|
|
18406
|
+
pending = null;
|
|
18407
|
+
const end = substitutionEnd(command, index);
|
|
18408
|
+
const inner = command.slice(index + 1, end);
|
|
18409
|
+
substitution(inner, `${sign}(${inner})`);
|
|
18410
|
+
index = end;
|
|
18411
|
+
} else if (posix && char === "(" && next === "(" && !inWord && arithmeticEnd(command, index)) {
|
|
18412
|
+
flushSegment();
|
|
18413
|
+
index = arithmeticEnd(command, index);
|
|
18414
|
+
} else if (char === "(" || char === ")") {
|
|
18116
18415
|
if (char === "(" && inWord && word.endsWith("$")) {
|
|
18117
18416
|
word = word.slice(0, -1);
|
|
18118
18417
|
inWord = word !== "";
|
|
18119
18418
|
}
|
|
18419
|
+
group(char === "(" ? "open" : "close");
|
|
18420
|
+
} else if (!posix && (char === "{" || char === "}")) {
|
|
18421
|
+
if (char === "{" && inWord && word.endsWith("@")) {
|
|
18422
|
+
word += char;
|
|
18423
|
+
continue;
|
|
18424
|
+
}
|
|
18120
18425
|
flushSegment();
|
|
18121
|
-
segments.push({ words: [], redirects: [], group: char === "(" ? "open" : "close" });
|
|
18122
18426
|
} else if (";&|".includes(char)) {
|
|
18123
|
-
if (char === "&" &&
|
|
18427
|
+
if (char === "&" && next === ">")
|
|
18124
18428
|
continue;
|
|
18429
|
+
if (char === "|" && next === "|")
|
|
18430
|
+
index++;
|
|
18431
|
+
else if (char === "|") {
|
|
18432
|
+
flushWord();
|
|
18433
|
+
if (current.words.length)
|
|
18434
|
+
current.pipe = true;
|
|
18435
|
+
if (next === "&")
|
|
18436
|
+
index++;
|
|
18437
|
+
}
|
|
18125
18438
|
flushSegment();
|
|
18126
18439
|
} else if (char === ">") {
|
|
18127
18440
|
if (inWord && /^\d$/.test(word)) {
|
|
@@ -18137,16 +18450,24 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
18137
18450
|
inWord = true;
|
|
18138
18451
|
}
|
|
18139
18452
|
pending = "redirect";
|
|
18140
|
-
} else if (char === "<" &&
|
|
18453
|
+
} else if (char === "<" && posix) {
|
|
18141
18454
|
flushWord();
|
|
18142
|
-
if (command[index +
|
|
18455
|
+
if (next === "<" && command[index + 2] === "<") {
|
|
18456
|
+
index += 2;
|
|
18457
|
+
pending = "herestring";
|
|
18458
|
+
} else if (next === "<") {
|
|
18143
18459
|
index++;
|
|
18144
|
-
if (command[index + 1] === "<")
|
|
18145
|
-
index++;
|
|
18146
18460
|
pending = "heredoc";
|
|
18147
18461
|
} else
|
|
18148
18462
|
pending = "input";
|
|
18149
|
-
} else {
|
|
18463
|
+
} else if (posix && char === "{" && !word.endsWith("$")) {
|
|
18464
|
+
word += OPEN;
|
|
18465
|
+
inWord = true;
|
|
18466
|
+
} else if (posix && char === "," && word.includes(OPEN))
|
|
18467
|
+
word += COMMA;
|
|
18468
|
+
else if (posix && char === "}" && word.includes(OPEN))
|
|
18469
|
+
word += CLOSE;
|
|
18470
|
+
else {
|
|
18150
18471
|
word += char;
|
|
18151
18472
|
inWord = true;
|
|
18152
18473
|
}
|
|
@@ -18157,8 +18478,35 @@ var segmentsOf = (command, dialect = "posix") => {
|
|
|
18157
18478
|
|
|
18158
18479
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
18159
18480
|
var NONE2 = { kind: "none" };
|
|
18160
|
-
var SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
18161
|
-
var
|
|
18481
|
+
var SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh", "ash", "mksh", "yash", "fish"]);
|
|
18482
|
+
var POWERSHELLS = new Set(["pwsh", "powershell"]);
|
|
18483
|
+
var EVALS = new Set(["eval", "iex", "invoke-expression"]);
|
|
18484
|
+
var WRAPPERS = {
|
|
18485
|
+
sudo: { values: "-u -g -h -p -C -D -R -T -r -t -U --user --group --host --prompt --chdir" },
|
|
18486
|
+
doas: { values: "-u -C" },
|
|
18487
|
+
command: { values: "" },
|
|
18488
|
+
builtin: { values: "" },
|
|
18489
|
+
env: { values: "-u -C --unset --chdir" },
|
|
18490
|
+
nohup: { values: "" },
|
|
18491
|
+
setsid: { values: "" },
|
|
18492
|
+
time: { values: "-f -o --format --output" },
|
|
18493
|
+
exec: { values: "-a" },
|
|
18494
|
+
nice: { values: "-n --adjustment" },
|
|
18495
|
+
ionice: { values: "-c -n -p --class --classdata" },
|
|
18496
|
+
stdbuf: { values: "-i -o -e --input --output --error" },
|
|
18497
|
+
chronic: { values: "" },
|
|
18498
|
+
unbuffer: { values: "" },
|
|
18499
|
+
wsl: { values: "-d -u --cd --distribution --user" },
|
|
18500
|
+
timeout: { values: "-s -k --signal --kill-after", operands: 1 },
|
|
18501
|
+
flock: { values: "-w -E --timeout --conflict-exit-code", operands: 1 },
|
|
18502
|
+
coproc: { values: "" },
|
|
18503
|
+
taskset: { values: "", operands: 1 },
|
|
18504
|
+
watch: { values: "-n -d --interval --differences -q --equexit" },
|
|
18505
|
+
"&": { values: "" }
|
|
18506
|
+
};
|
|
18507
|
+
var WRAPPER_VALUES = new Map(Object.entries(WRAPPERS).map(([name, wrapper]) => [name, new Set(wrapper.values.split(" "))]));
|
|
18508
|
+
var KEYWORDS = new Set(["if", "then", "else", "elif", "while", "until", "do", "!", "{"]);
|
|
18509
|
+
var DECLARATIONS = new Set(["export", "local", "declare", "readonly", "typeset"]);
|
|
18162
18510
|
var SCRIPT_FLAG = /^-[a-zA-Z]*c[a-zA-Z]*$/;
|
|
18163
18511
|
var CD = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
18164
18512
|
var PUSHD = new Set(["pushd", "push-location"]);
|
|
@@ -18172,13 +18520,21 @@ var GIT_VALUE_OPTIONS = new Set([
|
|
|
18172
18520
|
"--config-env",
|
|
18173
18521
|
"--super-prefix"
|
|
18174
18522
|
]);
|
|
18523
|
+
var GIT_CONFIG_OPTIONS = new Set(["-c", "--config-env", "--git-dir"]);
|
|
18524
|
+
var GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
|
|
18525
|
+
var ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
|
|
18526
|
+
var MAX_DEPTH = 4;
|
|
18527
|
+
var MAX_EXPANSIONS = 16;
|
|
18175
18528
|
var isAbsolute = (value) => path20.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
18176
|
-
var
|
|
18529
|
+
var HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
|
|
18530
|
+
var joinDir = (base, raw) => {
|
|
18531
|
+
const next = raw.replace(HERE, ".");
|
|
18177
18532
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
18178
18533
|
return;
|
|
18179
18534
|
const expanded = next === "~" || next.startsWith("~/") ? path20.join(os5.homedir(), next.slice(1)) : next;
|
|
18180
18535
|
return base === null || isAbsolute(expanded) ? expanded : path20.join(base, expanded);
|
|
18181
18536
|
};
|
|
18537
|
+
var rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner);
|
|
18182
18538
|
var cdTarget = (words) => {
|
|
18183
18539
|
const args = words.slice(1);
|
|
18184
18540
|
const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
|
|
@@ -18188,88 +18544,433 @@ var cdTarget = (words) => {
|
|
|
18188
18544
|
};
|
|
18189
18545
|
var stripPrefixes = (input) => {
|
|
18190
18546
|
let words = input;
|
|
18547
|
+
const env = {};
|
|
18191
18548
|
for (;; ) {
|
|
18192
18549
|
const first = words[0];
|
|
18193
18550
|
if (first === undefined)
|
|
18194
|
-
return words;
|
|
18195
|
-
|
|
18551
|
+
return { words, env };
|
|
18552
|
+
const assignment = ASSIGNMENT.exec(first);
|
|
18553
|
+
if (assignment) {
|
|
18554
|
+
if (GIT_CONFIG_ENV.test(assignment[1]))
|
|
18555
|
+
env[assignment[1]] = assignment[2];
|
|
18196
18556
|
words = words.slice(1);
|
|
18197
|
-
else if (
|
|
18557
|
+
} else if (KEYWORDS.has(first))
|
|
18198
18558
|
words = words.slice(1);
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18559
|
+
else if (first === "function")
|
|
18560
|
+
words = words.slice(2);
|
|
18561
|
+
else if (Object.hasOwn(WRAPPERS, commandName(first))) {
|
|
18562
|
+
const name = commandName(first);
|
|
18563
|
+
const values = WRAPPER_VALUES.get(name);
|
|
18202
18564
|
words = words.slice(1);
|
|
18203
|
-
|
|
18565
|
+
const takesValue = (option) => values.has(option) || /^-[a-zA-Z]{2,}$/.test(option) && values.has(`-${option.at(-1)}`);
|
|
18566
|
+
while (words[0]?.startsWith("-") && words[0] !== "--")
|
|
18567
|
+
words = words.slice(takesValue(words[0]) ? 2 : 1);
|
|
18568
|
+
if (words[0] === "--")
|
|
18204
18569
|
words = words.slice(1);
|
|
18205
|
-
words = words.slice(
|
|
18570
|
+
words = words.slice(WRAPPERS[name].operands ?? 0);
|
|
18206
18571
|
} else
|
|
18207
|
-
return words;
|
|
18572
|
+
return { words, env };
|
|
18208
18573
|
}
|
|
18209
18574
|
};
|
|
18210
18575
|
var commandName = (word) => (word?.split(/[\\/]/).at(-1) ?? "").toLowerCase().replace(/\.exe$/, "");
|
|
18576
|
+
var VARIABLE = /\$(?:\{(\w+)\}|(\w+))/g;
|
|
18577
|
+
var expandWord = (word, vars) => {
|
|
18578
|
+
if (!word.includes("$"))
|
|
18579
|
+
return [word];
|
|
18580
|
+
let results = [""];
|
|
18581
|
+
let last = 0;
|
|
18582
|
+
for (const match of word.matchAll(VARIABLE)) {
|
|
18583
|
+
const values = vars.get(match[1] ?? match[2]) ?? [match[0]];
|
|
18584
|
+
const before = word.slice(last, match.index);
|
|
18585
|
+
results = results.flatMap((result) => values.map((value) => result + before + value)).slice(0, MAX_EXPANSIONS);
|
|
18586
|
+
last = match.index + match[0].length;
|
|
18587
|
+
}
|
|
18588
|
+
return results.map((result) => result + word.slice(last));
|
|
18589
|
+
};
|
|
18590
|
+
var substitute = (words, vars) => {
|
|
18591
|
+
if (vars.size === 0)
|
|
18592
|
+
return [words];
|
|
18593
|
+
let lines = [[]];
|
|
18594
|
+
for (const word of words) {
|
|
18595
|
+
const values = expandWord(word, vars);
|
|
18596
|
+
lines = lines.flatMap((line) => values.map((value) => [...line, value])).slice(0, MAX_EXPANSIONS);
|
|
18597
|
+
}
|
|
18598
|
+
return lines;
|
|
18599
|
+
};
|
|
18600
|
+
var assignments = (words, vars) => {
|
|
18601
|
+
if (words[0] === "for" && words[2] === "in" && /^\w+$/.test(words[1] ?? "")) {
|
|
18602
|
+
const values = words.slice(3).flatMap((word) => expandWord(word, vars));
|
|
18603
|
+
return [[words[1], values.slice(0, MAX_EXPANSIONS)]];
|
|
18604
|
+
}
|
|
18605
|
+
let rest = words;
|
|
18606
|
+
if (DECLARATIONS.has(rest[0] ?? "")) {
|
|
18607
|
+
rest = rest.slice(1);
|
|
18608
|
+
while (rest[0]?.startsWith("-"))
|
|
18609
|
+
rest = rest.slice(1);
|
|
18610
|
+
}
|
|
18611
|
+
if (rest.length === 0 || !rest.every((word) => ASSIGNMENT.test(word)))
|
|
18612
|
+
return null;
|
|
18613
|
+
return rest.map((word) => {
|
|
18614
|
+
const [, name, value] = ASSIGNMENT.exec(word);
|
|
18615
|
+
return [name, expandWord(value, vars)];
|
|
18616
|
+
});
|
|
18617
|
+
};
|
|
18618
|
+
var literalOutput = (segment) => {
|
|
18619
|
+
if (!segment?.pipe)
|
|
18620
|
+
return;
|
|
18621
|
+
const { words } = stripPrefixes(segment.words);
|
|
18622
|
+
const name = commandName(words[0]);
|
|
18623
|
+
if (name === "echo") {
|
|
18624
|
+
let args = words.slice(1);
|
|
18625
|
+
while (/^-[neE]+$/.test(args[0] ?? ""))
|
|
18626
|
+
args = args.slice(1);
|
|
18627
|
+
return args.join(" ");
|
|
18628
|
+
}
|
|
18629
|
+
if (name === "printf") {
|
|
18630
|
+
const [format = "", ...args] = words.slice(1);
|
|
18631
|
+
return (args.length ? args.join(`
|
|
18632
|
+
`) : format).replace(/\\n/g, `
|
|
18633
|
+
`);
|
|
18634
|
+
}
|
|
18635
|
+
if (name === "cat" && words.length === 1 && segment.stdin)
|
|
18636
|
+
return segment.stdin.join(`
|
|
18637
|
+
`);
|
|
18638
|
+
return;
|
|
18639
|
+
};
|
|
18640
|
+
var stdinOf = (segment, previous) => segment.stdin ? segment.stdin.join(`
|
|
18641
|
+
`) : literalOutput(previous);
|
|
18642
|
+
var XARGS_VALUES = new Set(["-n", "-L", "-l", "-P", "-d", "-E", "-e", "-s", "-a", "--arg-file", "--delimiter"].concat([
|
|
18643
|
+
"--max-args",
|
|
18644
|
+
"--max-lines",
|
|
18645
|
+
"--max-procs",
|
|
18646
|
+
"--eof",
|
|
18647
|
+
"--max-chars",
|
|
18648
|
+
"--process-slot-var"
|
|
18649
|
+
]));
|
|
18650
|
+
var xargsCommands = (words, input) => {
|
|
18651
|
+
let replace = null;
|
|
18652
|
+
let index = 1;
|
|
18653
|
+
for (;index < words.length; index++) {
|
|
18654
|
+
const word = words[index];
|
|
18655
|
+
if (word === "--") {
|
|
18656
|
+
index++;
|
|
18657
|
+
break;
|
|
18658
|
+
}
|
|
18659
|
+
if (!word.startsWith("-"))
|
|
18660
|
+
break;
|
|
18661
|
+
if (word === "-I")
|
|
18662
|
+
replace = words[++index] ?? "{}";
|
|
18663
|
+
else if (word === "--replace" || word === "-i")
|
|
18664
|
+
replace = "{}";
|
|
18665
|
+
else if (word.startsWith("--replace="))
|
|
18666
|
+
replace = word.slice("--replace=".length);
|
|
18667
|
+
else if (/^-[Ii]./.test(word))
|
|
18668
|
+
replace = word.slice(2);
|
|
18669
|
+
else if (XARGS_VALUES.has(word))
|
|
18670
|
+
index++;
|
|
18671
|
+
}
|
|
18672
|
+
const command = words.slice(index);
|
|
18673
|
+
if (command.length === 0)
|
|
18674
|
+
return [];
|
|
18675
|
+
if (input === undefined)
|
|
18676
|
+
return [command];
|
|
18677
|
+
if (replace === null)
|
|
18678
|
+
return [[...command, ...input.split(/\s+/).filter(Boolean)]];
|
|
18679
|
+
const token = replace;
|
|
18680
|
+
return input.split(`
|
|
18681
|
+
`).map((line) => line.trim()).filter(Boolean).slice(0, MAX_EXPANSIONS).map((line) => command.map((word) => word.replaceAll(token, line)));
|
|
18682
|
+
};
|
|
18683
|
+
var findCommands = (words) => {
|
|
18684
|
+
const found = [];
|
|
18685
|
+
for (let index = 1;index < words.length; index++) {
|
|
18686
|
+
if (!/^-(?:exec|execdir|ok|okdir)$/.test(words[index]))
|
|
18687
|
+
continue;
|
|
18688
|
+
const end = words.findIndex((word, at) => at > index && (word === ";" || word === "+"));
|
|
18689
|
+
found.push(words.slice(index + 1, end < 0 ? undefined : end));
|
|
18690
|
+
if (end < 0)
|
|
18691
|
+
break;
|
|
18692
|
+
index = end;
|
|
18693
|
+
}
|
|
18694
|
+
return found;
|
|
18695
|
+
};
|
|
18696
|
+
var POWERSHELL_VALUES = /^-(?:f|file|ex|executionpolicy|wd|workingdirectory|config|configurationname|o|outputformat|if|inputformat|inp|w|windowstyle|settingsfile|custompipename|psconsolefile)$/;
|
|
18697
|
+
var powershellScript = (words, stdin) => {
|
|
18698
|
+
for (let index = 1;index < words.length; index++) {
|
|
18699
|
+
const word = words[index];
|
|
18700
|
+
if (!/^[-/]/.test(word))
|
|
18701
|
+
return null;
|
|
18702
|
+
const flag = word.replace(/^[-/]+/, "").toLowerCase();
|
|
18703
|
+
if (!flag)
|
|
18704
|
+
return null;
|
|
18705
|
+
if (flag === "e" || flag === "ec" || flag.length >= 2 && "encodedcommand".startsWith(flag)) {
|
|
18706
|
+
try {
|
|
18707
|
+
return Buffer.from(words[index + 1] ?? "", "base64").toString("utf16le");
|
|
18708
|
+
} catch {
|
|
18709
|
+
return null;
|
|
18710
|
+
}
|
|
18711
|
+
}
|
|
18712
|
+
if (flag === "cwa" || flag.length >= 8 && "commandwithargs".startsWith(flag))
|
|
18713
|
+
return words[index + 1] ?? null;
|
|
18714
|
+
if ("command".startsWith(flag))
|
|
18715
|
+
return words[index + 1] === "-" ? stdin ?? null : words.slice(index + 1).join(" ");
|
|
18716
|
+
if (POWERSHELL_VALUES.test(`-${flag}`)) {
|
|
18717
|
+
if (flag === "f" || flag === "file")
|
|
18718
|
+
return null;
|
|
18719
|
+
index++;
|
|
18720
|
+
}
|
|
18721
|
+
}
|
|
18722
|
+
return null;
|
|
18723
|
+
};
|
|
18724
|
+
var cmdScript = (words) => {
|
|
18725
|
+
const at = words.findIndex((word, index) => index > 0 && /^\/[ck]$/i.test(word));
|
|
18726
|
+
if (at > 0)
|
|
18727
|
+
return words.slice(at + 1).join(" ");
|
|
18728
|
+
const attached = words.find((word, index) => index > 0 && /^\/[ck]./i.test(word));
|
|
18729
|
+
return attached ? [attached.slice(2), ...words.slice(words.indexOf(attached) + 1)].join(" ") : null;
|
|
18730
|
+
};
|
|
18731
|
+
var processSubstitutionText = (word) => {
|
|
18732
|
+
const inner = /^<\(([\s\S]*)\)$/.exec(word ?? "")?.[1];
|
|
18733
|
+
if (inner === undefined)
|
|
18734
|
+
return;
|
|
18735
|
+
const segments = segmentsOf(inner);
|
|
18736
|
+
return segments.length === 1 ? literalOutput({ ...segments[0], pipe: true }) : undefined;
|
|
18737
|
+
};
|
|
18738
|
+
var shellScript = (words, stdin) => {
|
|
18739
|
+
const flag = words.findIndex((word, index) => index > 0 && SCRIPT_FLAG.test(word));
|
|
18740
|
+
if (flag > 0)
|
|
18741
|
+
return words[flag + 1] === "--" ? words[flag + 2] : words[flag + 1];
|
|
18742
|
+
const operand = words.slice(1).find((word) => !word.startsWith("-"));
|
|
18743
|
+
if (operand !== undefined)
|
|
18744
|
+
return processSubstitutionText(operand);
|
|
18745
|
+
return stdin;
|
|
18746
|
+
};
|
|
18747
|
+
var scriptCommand = (words) => {
|
|
18748
|
+
for (let index = 1;index < words.length; index++) {
|
|
18749
|
+
const word = words[index];
|
|
18750
|
+
if (word === "--command" || /^-[a-zA-Z]*c$/.test(word))
|
|
18751
|
+
return words[index + 1];
|
|
18752
|
+
if (word.startsWith("--command="))
|
|
18753
|
+
return word.slice("--command=".length);
|
|
18754
|
+
}
|
|
18755
|
+
return;
|
|
18756
|
+
};
|
|
18757
|
+
var PARALLEL_VALUES = new Set(["-j", "--jobs", "-N", "-n", "-S", "--sshlogin", "-P", "--delay"]);
|
|
18758
|
+
var parallelCommands = (words) => {
|
|
18759
|
+
let index = 1;
|
|
18760
|
+
while (index < words.length && words[index].startsWith("-"))
|
|
18761
|
+
index += PARALLEL_VALUES.has(words[index]) ? 2 : 1;
|
|
18762
|
+
const separator = words.indexOf(":::", index);
|
|
18763
|
+
const command = words.slice(index, separator < 0 ? undefined : separator);
|
|
18764
|
+
if (separator < 0)
|
|
18765
|
+
return command.length ? [command] : [];
|
|
18766
|
+
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]);
|
|
18767
|
+
};
|
|
18768
|
+
var START_PROCESS_VALUES = /^-(?:workingdirectory|wd|redirectstandard\w*|verb|windowstyle|credential|environment)$/i;
|
|
18769
|
+
var startProcessCommand = (words) => {
|
|
18770
|
+
let file;
|
|
18771
|
+
let args;
|
|
18772
|
+
const positionals = [];
|
|
18773
|
+
for (let index = 1;index < words.length; index++) {
|
|
18774
|
+
const word = words[index];
|
|
18775
|
+
const flag = word.startsWith("-") ? word.slice(1).toLowerCase() : null;
|
|
18776
|
+
if (flag === null)
|
|
18777
|
+
positionals.push(word);
|
|
18778
|
+
else if (flag && "filepath".startsWith(flag))
|
|
18779
|
+
file = words[++index];
|
|
18780
|
+
else if (flag && (flag === "args" || "argumentlist".startsWith(flag)))
|
|
18781
|
+
args = words[++index];
|
|
18782
|
+
else if (START_PROCESS_VALUES.test(word))
|
|
18783
|
+
index++;
|
|
18784
|
+
}
|
|
18785
|
+
file ??= positionals.shift();
|
|
18786
|
+
args ??= positionals.shift();
|
|
18787
|
+
if (!file)
|
|
18788
|
+
return null;
|
|
18789
|
+
return [file, ...(args ?? "").split(/[\s,]+/).filter(Boolean)];
|
|
18790
|
+
};
|
|
18791
|
+
var splitString = (line) => {
|
|
18792
|
+
if (commandName(line[0]) !== "env")
|
|
18793
|
+
return null;
|
|
18794
|
+
for (let index = 1;index < line.length; index++) {
|
|
18795
|
+
const word = line[index];
|
|
18796
|
+
if (word === "-S" || word === "--split-string")
|
|
18797
|
+
return line.slice(index + 1).join(" ");
|
|
18798
|
+
if (word.startsWith("--split-string="))
|
|
18799
|
+
return line.slice(index).join(" ").slice(15);
|
|
18800
|
+
if (/^-S./.test(word))
|
|
18801
|
+
return [word.slice(2), ...line.slice(index + 1)].join(" ");
|
|
18802
|
+
if (!word.startsWith("-") && !ASSIGNMENT.test(word))
|
|
18803
|
+
return null;
|
|
18804
|
+
}
|
|
18805
|
+
return null;
|
|
18806
|
+
};
|
|
18807
|
+
var CONFIG_READS = /^(?:--get\S*|-l|--list|--unset\S*|--remove-section|--rename-section|-e|--edit|--show-\S+|--name-only)$/;
|
|
18808
|
+
var configSetBy = (args) => {
|
|
18809
|
+
const positionals = args.filter((arg, index) => index > 0 && !arg.startsWith("-"));
|
|
18810
|
+
if (args[0] === "remote" && (positionals[0] === "add" || positionals[0] === "set-url")) {
|
|
18811
|
+
const [, name, url] = positionals;
|
|
18812
|
+
const key = args.includes("--push") ? "pushurl" : "url";
|
|
18813
|
+
return name && url ? ["-c", `remote.${name}.${key}=${url}`] : [];
|
|
18814
|
+
}
|
|
18815
|
+
if (args[0] !== "config" || args.some((arg) => CONFIG_READS.test(arg)))
|
|
18816
|
+
return [];
|
|
18817
|
+
const [key, value] = positionals[0] === "set" ? positionals.slice(1) : positionals;
|
|
18818
|
+
return key?.includes(".") && value !== undefined && positionals.length <= 3 ? ["-c", `${key}=${value}`] : [];
|
|
18819
|
+
};
|
|
18820
|
+
var gitInvocation = (words, dir, env = {}, stdin, inherited = []) => {
|
|
18821
|
+
let here = dir;
|
|
18822
|
+
const config = [...inherited];
|
|
18823
|
+
let gitDir = env.GIT_DIR;
|
|
18824
|
+
let index = 0;
|
|
18825
|
+
for (;index < words.length; index++) {
|
|
18826
|
+
const word = words[index];
|
|
18827
|
+
if (word === "-C")
|
|
18828
|
+
here = words[index + 1] ? joinDir(here, words[++index]) : here;
|
|
18829
|
+
else if (GIT_CONFIG_OPTIONS.has(word)) {
|
|
18830
|
+
if (word === "--git-dir")
|
|
18831
|
+
gitDir = words[index + 1];
|
|
18832
|
+
if (words[index + 1] !== undefined)
|
|
18833
|
+
config.push(word, words[++index]);
|
|
18834
|
+
} else if (/^--(?:config-env|git-dir)=/.test(word)) {
|
|
18835
|
+
if (word.startsWith("--git-dir="))
|
|
18836
|
+
gitDir = word.slice("--git-dir=".length);
|
|
18837
|
+
config.push(word);
|
|
18838
|
+
} else if (GIT_VALUE_OPTIONS.has(word))
|
|
18839
|
+
index++;
|
|
18840
|
+
else if (!word.startsWith("-"))
|
|
18841
|
+
break;
|
|
18842
|
+
}
|
|
18843
|
+
if (gitDir)
|
|
18844
|
+
here = joinDir(here, gitDir.replace(/(?:^|[\\/]+)\.git[\\/]*$/, "") || ".");
|
|
18845
|
+
return {
|
|
18846
|
+
tool: "git",
|
|
18847
|
+
dir: here,
|
|
18848
|
+
args: words.slice(index),
|
|
18849
|
+
...config.length ? { config } : {},
|
|
18850
|
+
...Object.keys(env).length ? { env } : {},
|
|
18851
|
+
...stdin === undefined ? {} : { stdin }
|
|
18852
|
+
};
|
|
18853
|
+
};
|
|
18211
18854
|
function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
18855
|
+
if (depth > 0)
|
|
18856
|
+
return walk2(command, dialect, depth);
|
|
18857
|
+
const key = `${dialect}\x00${command}`;
|
|
18858
|
+
const cached = RECENT.get(key);
|
|
18859
|
+
if (cached)
|
|
18860
|
+
return cached;
|
|
18861
|
+
let found;
|
|
18862
|
+
try {
|
|
18863
|
+
found = walk2(command, dialect, depth);
|
|
18864
|
+
} catch (error) {
|
|
18865
|
+
throw error instanceof ShellAnalysisError ? error : new ShellAnalysisError(error instanceof Error ? error.message : String(error));
|
|
18866
|
+
}
|
|
18867
|
+
RECENT.set(key, found);
|
|
18868
|
+
if (RECENT.size > 8)
|
|
18869
|
+
RECENT.delete(RECENT.keys().next().value);
|
|
18870
|
+
return found;
|
|
18871
|
+
}
|
|
18872
|
+
var RECENT = new Map;
|
|
18873
|
+
function walk2(command, dialect, depth) {
|
|
18212
18874
|
const found = [];
|
|
18213
18875
|
let dir = null;
|
|
18214
18876
|
const groups = [];
|
|
18215
18877
|
let stack = [];
|
|
18216
|
-
|
|
18217
|
-
|
|
18218
|
-
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
|
|
18225
|
-
|
|
18226
|
-
|
|
18227
|
-
const
|
|
18878
|
+
const vars = new Map;
|
|
18879
|
+
const exported = {};
|
|
18880
|
+
const sessionConfig = [];
|
|
18881
|
+
const nested = (script, inner) => {
|
|
18882
|
+
if (!script || depth >= MAX_DEPTH)
|
|
18883
|
+
return;
|
|
18884
|
+
for (const invocation of rawInvocations(script, inner, depth + 1))
|
|
18885
|
+
found.push({ ...invocation, dir: rebase(dir, invocation.dir) });
|
|
18886
|
+
};
|
|
18887
|
+
const visit = (input, stdin, hops) => {
|
|
18888
|
+
const line = /^\$[\w:]+$/.test(input[0] ?? "") && input[1] === "=" ? input.slice(2) : input;
|
|
18889
|
+
const split = splitString(line);
|
|
18890
|
+
if (split !== null)
|
|
18891
|
+
return nested(split, "posix");
|
|
18892
|
+
const { words, env } = stripPrefixes(line);
|
|
18228
18893
|
const name = commandName(words[0]);
|
|
18894
|
+
if (!name)
|
|
18895
|
+
return;
|
|
18896
|
+
const runs = (lines) => {
|
|
18897
|
+
if (hops < MAX_DEPTH)
|
|
18898
|
+
for (const next of lines)
|
|
18899
|
+
visit(next, undefined, hops + 1);
|
|
18900
|
+
};
|
|
18229
18901
|
if (CD.has(name)) {
|
|
18230
18902
|
const target = cdTarget(words);
|
|
18231
18903
|
dir = target === null ? os5.homedir() : joinDir(dir, target);
|
|
18232
|
-
|
|
18233
|
-
}
|
|
18234
|
-
if (PUSHD.has(name)) {
|
|
18904
|
+
} else if (PUSHD.has(name)) {
|
|
18235
18905
|
const target = cdTarget(words);
|
|
18236
18906
|
stack.push(dir);
|
|
18237
18907
|
dir = target === null || target === "-" ? undefined : joinDir(dir, target);
|
|
18238
|
-
|
|
18239
|
-
}
|
|
18240
|
-
if (POPD.has(name)) {
|
|
18908
|
+
} else if (POPD.has(name))
|
|
18241
18909
|
dir = stack.length ? stack.pop() : undefined;
|
|
18242
|
-
|
|
18910
|
+
else if (EVALS.has(name)) {
|
|
18911
|
+
const args = /^-c(?:o(?:m(?:m(?:a(?:n(?:d)?)?)?)?)?)?$/i.test(words[1] ?? "") ? words.slice(2) : words.slice(1);
|
|
18912
|
+
nested(args.join(" "), dialect);
|
|
18913
|
+
} else if (SHELLS.has(name))
|
|
18914
|
+
nested(shellScript(words, stdin), "posix");
|
|
18915
|
+
else if ((name === "source" || name === ".") && dialect === "posix")
|
|
18916
|
+
nested(processSubstitutionText(words[1]), "posix");
|
|
18917
|
+
else if (name === "trap" && dialect === "posix" && !/^-[lp]$/.test(words[1] ?? ""))
|
|
18918
|
+
nested(words[1], "posix");
|
|
18919
|
+
else if (name === "script")
|
|
18920
|
+
nested(scriptCommand(words), "posix");
|
|
18921
|
+
else if (name === "parallel")
|
|
18922
|
+
runs(parallelCommands(words));
|
|
18923
|
+
else if (dialect === "powershell" && /^(?:start-process|saps|start)$/.test(name)) {
|
|
18924
|
+
const started = startProcessCommand(words);
|
|
18925
|
+
if (started)
|
|
18926
|
+
runs([started]);
|
|
18927
|
+
} else if (POWERSHELLS.has(name))
|
|
18928
|
+
nested(powershellScript(words, stdin), "powershell");
|
|
18929
|
+
else if (name === "cmd")
|
|
18930
|
+
nested(cmdScript(words), "powershell");
|
|
18931
|
+
else if (name === "xargs" || name === "find")
|
|
18932
|
+
runs(name === "xargs" ? xargsCommands(words, stdin) : findCommands(words));
|
|
18933
|
+
else if (name === "gh" || name === "glab")
|
|
18934
|
+
found.push({
|
|
18935
|
+
tool: name,
|
|
18936
|
+
dir,
|
|
18937
|
+
args: words.slice(1),
|
|
18938
|
+
...stdin === undefined ? {} : { stdin }
|
|
18939
|
+
});
|
|
18940
|
+
else if (name === "git") {
|
|
18941
|
+
const invocation = gitInvocation(words.slice(1), dir, { ...exported, ...env }, stdin, sessionConfig);
|
|
18942
|
+
found.push(invocation);
|
|
18943
|
+
sessionConfig.push(...configSetBy(invocation.args));
|
|
18243
18944
|
}
|
|
18244
|
-
|
|
18245
|
-
|
|
18246
|
-
|
|
18247
|
-
|
|
18248
|
-
|
|
18249
|
-
found.push({
|
|
18250
|
-
...inner,
|
|
18251
|
-
dir: inner.dir === null ? dir : inner.dir === undefined ? undefined : joinDir(dir, inner.dir)
|
|
18252
|
-
});
|
|
18945
|
+
};
|
|
18946
|
+
const segments = segmentsOf(command, dialect);
|
|
18947
|
+
for (const [index, segment] of segments.entries()) {
|
|
18948
|
+
if (segment.group === "open") {
|
|
18949
|
+
groups.push({ dir, stack: [...stack] });
|
|
18253
18950
|
continue;
|
|
18254
18951
|
}
|
|
18255
|
-
if (
|
|
18256
|
-
|
|
18952
|
+
if (segment.group === "close") {
|
|
18953
|
+
const saved = groups.pop();
|
|
18954
|
+
if (saved)
|
|
18955
|
+
({ dir, stack } = saved);
|
|
18257
18956
|
continue;
|
|
18258
18957
|
}
|
|
18259
|
-
if (
|
|
18958
|
+
if (segment.unanalyzable)
|
|
18959
|
+
throw new ShellAnalysisError(segment.unanalyzable);
|
|
18960
|
+
for (const sub of segment.subs ?? [])
|
|
18961
|
+
nested(sub, "posix");
|
|
18962
|
+
const set = assignments(segment.words, vars);
|
|
18963
|
+
if (set) {
|
|
18964
|
+
for (const [name, values] of set) {
|
|
18965
|
+
vars.set(name, values);
|
|
18966
|
+
if (segment.words[0] === "export" && GIT_CONFIG_ENV.test(name) && values[0] !== undefined)
|
|
18967
|
+
exported[name] = values[0];
|
|
18968
|
+
}
|
|
18260
18969
|
continue;
|
|
18261
|
-
let here = dir;
|
|
18262
|
-
let index = 1;
|
|
18263
|
-
for (;index < words.length; index++) {
|
|
18264
|
-
const word = words[index];
|
|
18265
|
-
if (word === "-C")
|
|
18266
|
-
here = words[index + 1] ? joinDir(here, words[++index]) : here;
|
|
18267
|
-
else if (GIT_VALUE_OPTIONS.has(word))
|
|
18268
|
-
index++;
|
|
18269
|
-
else if (!word.startsWith("-"))
|
|
18270
|
-
break;
|
|
18271
18970
|
}
|
|
18272
|
-
|
|
18971
|
+
const stdin = stdinOf(segment, segments[index - 1]);
|
|
18972
|
+
for (const line of substitute(segment.words, vars))
|
|
18973
|
+
visit(line, stdin, 0);
|
|
18273
18974
|
}
|
|
18274
18975
|
return found;
|
|
18275
18976
|
}
|
|
@@ -18305,6 +19006,55 @@ function workitInvocations(command, dialect = "posix", depth = 0) {
|
|
|
18305
19006
|
return found;
|
|
18306
19007
|
}
|
|
18307
19008
|
var PUSH_VALUE_OPTIONS = new Set(["-o", "--push-option", "--receive-pack", "--exec", "--repo"]);
|
|
19009
|
+
var CURRENT_BRANCH = /^\$\(\s*git\s+(?:branch\s+--show-current|rev-parse\s+--abbrev-ref\s+HEAD|symbolic-ref\s+--short\s+HEAD)\s*\)$/;
|
|
19010
|
+
var pushDestination = (destination) => {
|
|
19011
|
+
if (destination === "HEAD" || destination === "@" || CURRENT_BRANCH.test(destination))
|
|
19012
|
+
return { name: null };
|
|
19013
|
+
if (destination.startsWith("refs/heads/"))
|
|
19014
|
+
return { name: destination.slice(11) };
|
|
19015
|
+
if (destination.startsWith("refs/tags/"))
|
|
19016
|
+
return { name: undefined, tag: destination.slice(10) };
|
|
19017
|
+
if (destination.startsWith("refs/"))
|
|
19018
|
+
return { name: undefined };
|
|
19019
|
+
return { name: destination };
|
|
19020
|
+
};
|
|
19021
|
+
var pushRefspecs = (specs) => {
|
|
19022
|
+
let force = false;
|
|
19023
|
+
let matching = false;
|
|
19024
|
+
const targets = [];
|
|
19025
|
+
const tags = [];
|
|
19026
|
+
const deleted = [];
|
|
19027
|
+
const globs = [];
|
|
19028
|
+
for (const raw of specs) {
|
|
19029
|
+
if (raw.startsWith("+"))
|
|
19030
|
+
force = true;
|
|
19031
|
+
const spec = raw.replace(/^\+/, "");
|
|
19032
|
+
if (spec.startsWith("^"))
|
|
19033
|
+
continue;
|
|
19034
|
+
if (spec === ":") {
|
|
19035
|
+
matching = true;
|
|
19036
|
+
continue;
|
|
19037
|
+
}
|
|
19038
|
+
const colon = spec.indexOf(":");
|
|
19039
|
+
const source = colon >= 0 ? spec.slice(0, colon) : spec;
|
|
19040
|
+
const destination = colon >= 0 ? spec.slice(colon + 1) : spec;
|
|
19041
|
+
if (!destination)
|
|
19042
|
+
continue;
|
|
19043
|
+
if (destination.includes("*")) {
|
|
19044
|
+
globs.push({ source, destination });
|
|
19045
|
+
continue;
|
|
19046
|
+
}
|
|
19047
|
+
const { name, tag } = pushDestination(destination);
|
|
19048
|
+
if (tag !== undefined)
|
|
19049
|
+
tags.push(tag);
|
|
19050
|
+
if (name === undefined)
|
|
19051
|
+
continue;
|
|
19052
|
+
targets.push(name);
|
|
19053
|
+
if (colon === 0 && name !== null)
|
|
19054
|
+
deleted.push(name);
|
|
19055
|
+
}
|
|
19056
|
+
return { force, matching, targets, tags, deleted, globs };
|
|
19057
|
+
};
|
|
18308
19058
|
var pushAction = (args) => {
|
|
18309
19059
|
let force = false;
|
|
18310
19060
|
let lease = false;
|
|
@@ -18314,6 +19064,7 @@ var pushAction = (args) => {
|
|
|
18314
19064
|
let allBranches = false;
|
|
18315
19065
|
let mirror = false;
|
|
18316
19066
|
let remote = null;
|
|
19067
|
+
let dryRun = false;
|
|
18317
19068
|
const positionals = [];
|
|
18318
19069
|
for (let index = 1;index < args.length; index++) {
|
|
18319
19070
|
const arg = args[index];
|
|
@@ -18321,9 +19072,11 @@ var pushAction = (args) => {
|
|
|
18321
19072
|
positionals.push(...args.slice(index + 1));
|
|
18322
19073
|
break;
|
|
18323
19074
|
}
|
|
18324
|
-
if (arg
|
|
18325
|
-
|
|
18326
|
-
if (arg
|
|
19075
|
+
if (/^--dr(?:y(?:-(?:r(?:un?)?)?)?)?$/.test(arg) || /^-[a-zA-Z]*n[a-zA-Z]*$/.test(arg))
|
|
19076
|
+
dryRun = true;
|
|
19077
|
+
else if (/^--no-dr(?:y(?:-(?:r(?:un?)?)?)?)?$/.test(arg))
|
|
19078
|
+
dryRun = false;
|
|
19079
|
+
else if (arg === "--repo")
|
|
18327
19080
|
remote = args[++index] ?? null;
|
|
18328
19081
|
else if (arg.startsWith("--repo="))
|
|
18329
19082
|
remote = arg.slice("--repo=".length);
|
|
@@ -18344,41 +19097,28 @@ var pushAction = (args) => {
|
|
|
18344
19097
|
else if (!arg.startsWith("-"))
|
|
18345
19098
|
positionals.push(arg);
|
|
18346
19099
|
}
|
|
19100
|
+
if (dryRun)
|
|
19101
|
+
return null;
|
|
18347
19102
|
const specs = remote === null ? positionals.slice(1) : positionals;
|
|
18348
19103
|
remote ??= positionals[0] ?? null;
|
|
18349
|
-
const
|
|
18350
|
-
const
|
|
18351
|
-
|
|
18352
|
-
|
|
18353
|
-
if (raw.startsWith("+"))
|
|
18354
|
-
force = true;
|
|
18355
|
-
const spec = raw.replace(/^\+/, "");
|
|
18356
|
-
const colon = spec.indexOf(":");
|
|
18357
|
-
const destination = colon >= 0 ? spec.slice(colon + 1) : spec;
|
|
18358
|
-
if (!destination)
|
|
18359
|
-
continue;
|
|
18360
|
-
const name = destination === "HEAD" ? null : destination.startsWith("refs/heads/") ? destination.slice(11) : destination.startsWith("refs/") ? undefined : destination;
|
|
18361
|
-
if (destination.startsWith("refs/tags/"))
|
|
18362
|
-
tags.push(destination.slice(10));
|
|
18363
|
-
if (name === undefined)
|
|
18364
|
-
continue;
|
|
18365
|
-
targets.push(name);
|
|
18366
|
-
if (colon === 0 && name !== null)
|
|
18367
|
-
deleted.push(name);
|
|
18368
|
-
}
|
|
18369
|
-
if (specs.length === 0 && !wholesale)
|
|
18370
|
-
targets.push(null);
|
|
19104
|
+
const parsed = pushRefspecs(specs);
|
|
19105
|
+
const implicit = specs.length === 0 && !wholesale;
|
|
19106
|
+
if (implicit)
|
|
19107
|
+
parsed.targets.push(null);
|
|
18371
19108
|
return {
|
|
18372
19109
|
kind: "push",
|
|
18373
|
-
targets,
|
|
18374
|
-
blindForce: force && !lease,
|
|
19110
|
+
targets: parsed.targets,
|
|
19111
|
+
blindForce: (force || parsed.force) && !lease,
|
|
18375
19112
|
remote,
|
|
18376
|
-
...tags.length ? { tags } : {},
|
|
19113
|
+
...parsed.tags.length ? { tags: parsed.tags } : {},
|
|
18377
19114
|
...allTags ? { allTags: true } : {},
|
|
18378
19115
|
...deletes ? { deletes: true } : {},
|
|
18379
|
-
...deleted.length ? { deleted } : {},
|
|
19116
|
+
...parsed.deleted.length ? { deleted: parsed.deleted } : {},
|
|
18380
19117
|
...allBranches ? { allBranches: true } : {},
|
|
18381
|
-
...mirror ? { mirror: true } : {}
|
|
19118
|
+
...mirror ? { mirror: true } : {},
|
|
19119
|
+
...implicit ? { implicit: true } : {},
|
|
19120
|
+
...parsed.globs.length ? { globs: parsed.globs } : {},
|
|
19121
|
+
...parsed.matching ? { matching: true } : {}
|
|
18382
19122
|
};
|
|
18383
19123
|
};
|
|
18384
19124
|
var VALUE_OPTIONS = {
|
|
@@ -18424,22 +19164,110 @@ var asksHelp = (invocation) => {
|
|
|
18424
19164
|
}
|
|
18425
19165
|
return false;
|
|
18426
19166
|
};
|
|
19167
|
+
var API_VALUES = new Set(["--method", "--header", "--raw-field", "--field", "--jq", "--template", "--input"].concat([
|
|
19168
|
+
"--hostname",
|
|
19169
|
+
"--preview",
|
|
19170
|
+
"--cache",
|
|
19171
|
+
"--output"
|
|
19172
|
+
]));
|
|
19173
|
+
var API_SHORT_VALUES = "XHfFqtp";
|
|
19174
|
+
var API_FIELDS = new Set(["-f", "-F", "--raw-field", "--field"]);
|
|
19175
|
+
var API_MERGE = {
|
|
19176
|
+
gh: /(?:^|\/)(?:pulls\/[^/?#]+\/merge|merges)\/?(?:[?#]|$)/i,
|
|
19177
|
+
glab: /(?:^|\/)merge_requests\/[^/?#]+\/merge\/?(?:[?#]|$)/i
|
|
19178
|
+
};
|
|
19179
|
+
var GRAPHQL_MERGE = /\b(?:mergePullRequest|enablePullRequestAutoMerge|mergeBranch|mergeRequestAccept)\b/;
|
|
19180
|
+
var apiMerges = (tool, args, stdin) => {
|
|
19181
|
+
const request = { method: null, body: false };
|
|
19182
|
+
let endpoint = null;
|
|
19183
|
+
const values = [];
|
|
19184
|
+
const take = (name, value) => {
|
|
19185
|
+
if (name === "-X" || name === "--method")
|
|
19186
|
+
request.method = value.toUpperCase();
|
|
19187
|
+
if (API_FIELDS.has(name) || name === "--input")
|
|
19188
|
+
request.body = true;
|
|
19189
|
+
values.push(value);
|
|
19190
|
+
const fromStdin = name === "--input" ? value === "-" : /^(?:[^=]*=)?@-$/.test(value);
|
|
19191
|
+
if (fromStdin && stdin !== undefined)
|
|
19192
|
+
values.push(stdin);
|
|
19193
|
+
};
|
|
19194
|
+
for (let index = 1;index < args.length; index++) {
|
|
19195
|
+
const arg = args[index];
|
|
19196
|
+
if (arg === "--") {
|
|
19197
|
+
endpoint ??= args[index + 1] ?? null;
|
|
19198
|
+
break;
|
|
19199
|
+
}
|
|
19200
|
+
if (arg.startsWith("--")) {
|
|
19201
|
+
const eq = arg.indexOf("=");
|
|
19202
|
+
const name = eq > 0 ? arg.slice(0, eq) : arg;
|
|
19203
|
+
if (API_VALUES.has(name))
|
|
19204
|
+
take(name, eq > 0 ? arg.slice(eq + 1) : args[++index] ?? "");
|
|
19205
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
19206
|
+
for (let at = 1;at < arg.length; at++) {
|
|
19207
|
+
if (!API_SHORT_VALUES.includes(arg[at]))
|
|
19208
|
+
continue;
|
|
19209
|
+
take(`-${arg[at]}`, at + 1 < arg.length ? arg.slice(at + 1) : args[++index] ?? "");
|
|
19210
|
+
break;
|
|
19211
|
+
}
|
|
19212
|
+
} else
|
|
19213
|
+
endpoint ??= arg;
|
|
19214
|
+
}
|
|
19215
|
+
if (!endpoint)
|
|
19216
|
+
return false;
|
|
19217
|
+
endpoint = endpoint.replace(/(?<!:)\/{2,}/g, "/");
|
|
19218
|
+
if (/(?:^|\/)graphql\/?$/i.test(endpoint))
|
|
19219
|
+
return values.some((value) => GRAPHQL_MERGE.test(value));
|
|
19220
|
+
const verb = request.method ?? (request.body ? "POST" : "GET");
|
|
19221
|
+
return verb !== "GET" && verb !== "HEAD" && API_MERGE[tool].test(endpoint);
|
|
19222
|
+
};
|
|
19223
|
+
var subtreePush = (args) => {
|
|
19224
|
+
const positionals = [];
|
|
19225
|
+
for (let index = 2;index < args.length; index++) {
|
|
19226
|
+
const arg = args[index];
|
|
19227
|
+
if (arg === "-P" || arg === "--prefix" || arg === "-m" || arg === "--message")
|
|
19228
|
+
index++;
|
|
19229
|
+
else if (!arg.startsWith("-"))
|
|
19230
|
+
positionals.push(arg);
|
|
19231
|
+
}
|
|
19232
|
+
const [remote, branch] = positionals;
|
|
19233
|
+
return remote && branch ? pushAction(["push", remote, `HEAD:refs/heads/${branch}`]) : null;
|
|
19234
|
+
};
|
|
18427
19235
|
function rawAction(invocation) {
|
|
18428
19236
|
const args = invocation.args;
|
|
19237
|
+
if (invocation.tool !== "git" && args[0] === "api")
|
|
19238
|
+
return apiMerges(invocation.tool, args, invocation.stdin) ? { kind: "merge", forge: invocation.tool, via: "api" } : null;
|
|
18429
19239
|
if (asksHelp(invocation))
|
|
18430
19240
|
return null;
|
|
18431
|
-
const [first
|
|
19241
|
+
const [first] = args;
|
|
18432
19242
|
if (invocation.tool === "git") {
|
|
19243
|
+
const second = args[1];
|
|
18433
19244
|
if (first === "commit")
|
|
18434
19245
|
return args.includes("--dry-run") ? null : { kind: "commit", amend: args.includes("--amend") };
|
|
18435
19246
|
if (first === "push")
|
|
18436
19247
|
return pushAction(args);
|
|
19248
|
+
if (first === "send-pack")
|
|
19249
|
+
return pushAction([
|
|
19250
|
+
"push",
|
|
19251
|
+
...args.slice(1).filter((arg) => arg !== "--stdin"),
|
|
19252
|
+
...args.includes("--stdin") ? (invocation.stdin ?? "").split(/\s+/).filter(Boolean) : []
|
|
19253
|
+
]);
|
|
19254
|
+
if (first === "subtree" && second === "push")
|
|
19255
|
+
return subtreePush(args);
|
|
18437
19256
|
return null;
|
|
18438
19257
|
}
|
|
18439
19258
|
const forge = invocation.tool;
|
|
18440
19259
|
const noun = forge === "gh" ? "pr" : "mr";
|
|
18441
19260
|
if (first !== noun)
|
|
18442
19261
|
return null;
|
|
19262
|
+
const values = VALUE_OPTIONS[forge];
|
|
19263
|
+
let second;
|
|
19264
|
+
for (let index = 1;index < args.length && second === undefined; index++) {
|
|
19265
|
+
const arg = args[index];
|
|
19266
|
+
if (values.has(arg))
|
|
19267
|
+
index++;
|
|
19268
|
+
else if (!arg.startsWith("-"))
|
|
19269
|
+
second = arg;
|
|
19270
|
+
}
|
|
18443
19271
|
if (second === "merge")
|
|
18444
19272
|
return { kind: "merge", forge };
|
|
18445
19273
|
if (second === "create")
|
|
@@ -18471,16 +19299,6 @@ var guardedBranch = (dir, branch) => {
|
|
|
18471
19299
|
return false;
|
|
18472
19300
|
}
|
|
18473
19301
|
};
|
|
18474
|
-
var toPushRemote = (repo, remote) => {
|
|
18475
|
-
if (remote === null)
|
|
18476
|
-
return true;
|
|
18477
|
-
try {
|
|
18478
|
-
const pushRemote = pushRemoteName(repo.dir, repo.branch);
|
|
18479
|
-
return pushRemote === null || pushRemote === remote;
|
|
18480
|
-
} catch {
|
|
18481
|
-
return false;
|
|
18482
|
-
}
|
|
18483
|
-
};
|
|
18484
19302
|
var headSha2 = (repo) => {
|
|
18485
19303
|
const git = repo.location.git;
|
|
18486
19304
|
if (!git || git.reftable)
|
|
@@ -18502,10 +19320,169 @@ var headSha2 = (repo) => {
|
|
|
18502
19320
|
return null;
|
|
18503
19321
|
}
|
|
18504
19322
|
};
|
|
19323
|
+
var gitConfig = (dir, invocation, cache) => {
|
|
19324
|
+
const key = JSON.stringify([dir, invocation.config ?? [], invocation.env ?? {}]);
|
|
19325
|
+
const cached = cache.get(key);
|
|
19326
|
+
if (cached)
|
|
19327
|
+
return cached;
|
|
19328
|
+
const config = new Map;
|
|
19329
|
+
const listed = spawnSync11("git", [...invocation.config ?? [], "config", "-z", "--list"], {
|
|
19330
|
+
cwd: dir,
|
|
19331
|
+
encoding: "utf8",
|
|
19332
|
+
timeout: 3000,
|
|
19333
|
+
windowsHide: true,
|
|
19334
|
+
env: { ...process.env, ...invocation.env, GIT_TERMINAL_PROMPT: "0", GIT_OPTIONAL_LOCKS: "0" }
|
|
19335
|
+
});
|
|
19336
|
+
for (const entry of (listed.status === 0 ? listed.stdout : "").split("\x00")) {
|
|
19337
|
+
if (!entry)
|
|
19338
|
+
continue;
|
|
19339
|
+
const newline = entry.indexOf(`
|
|
19340
|
+
`);
|
|
19341
|
+
const name = newline < 0 ? entry : entry.slice(0, newline);
|
|
19342
|
+
config.set(name, [
|
|
19343
|
+
...config.get(name) ?? [],
|
|
19344
|
+
newline < 0 ? "true" : entry.slice(newline + 1)
|
|
19345
|
+
]);
|
|
19346
|
+
}
|
|
19347
|
+
cache.set(key, config);
|
|
19348
|
+
return config;
|
|
19349
|
+
};
|
|
19350
|
+
var configValue = (config, key) => config.get(key)?.at(-1);
|
|
19351
|
+
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(" "));
|
|
19352
|
+
var JUDGED_COMMANDS = [
|
|
19353
|
+
"push",
|
|
19354
|
+
"commit",
|
|
19355
|
+
"switch",
|
|
19356
|
+
"checkout",
|
|
19357
|
+
"branch",
|
|
19358
|
+
"worktree",
|
|
19359
|
+
"stash",
|
|
19360
|
+
"update-ref",
|
|
19361
|
+
"symbolic-ref",
|
|
19362
|
+
"fetch",
|
|
19363
|
+
"pull",
|
|
19364
|
+
"subtree"
|
|
19365
|
+
];
|
|
19366
|
+
var editDistance2 = (a, b) => {
|
|
19367
|
+
let before = [];
|
|
19368
|
+
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
19369
|
+
for (let i = 1;i <= a.length; i++) {
|
|
19370
|
+
const row = [i];
|
|
19371
|
+
for (let j = 1;j <= b.length; j++) {
|
|
19372
|
+
row[j] = Math.min(previous[j] + 1, row[j - 1] + 1, previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
19373
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1])
|
|
19374
|
+
row[j] = Math.min(row[j], before[j - 2] + 1);
|
|
19375
|
+
}
|
|
19376
|
+
[before, previous] = [previous, row];
|
|
19377
|
+
}
|
|
19378
|
+
return previous[b.length];
|
|
19379
|
+
};
|
|
19380
|
+
var autocorrected = (name, config) => {
|
|
19381
|
+
const setting = (configValue(config, "help.autocorrect") ?? "0").toLowerCase();
|
|
19382
|
+
if (setting !== "immediate" && !/^-?[1-9]\d*$/.test(setting))
|
|
19383
|
+
return null;
|
|
19384
|
+
let best = null;
|
|
19385
|
+
let bestDistance = 3;
|
|
19386
|
+
let tie = false;
|
|
19387
|
+
for (const command of JUDGED_COMMANDS) {
|
|
19388
|
+
const distance = editDistance2(name, command);
|
|
19389
|
+
if (distance < bestDistance)
|
|
19390
|
+
[best, bestDistance, tie] = [command, distance, false];
|
|
19391
|
+
else if (distance === bestDistance)
|
|
19392
|
+
tie = true;
|
|
19393
|
+
}
|
|
19394
|
+
return tie ? null : best;
|
|
19395
|
+
};
|
|
19396
|
+
var shellQuote = (word) => `'${word.replaceAll("'", "'\\''")}'`;
|
|
19397
|
+
var positional = (script, args) => {
|
|
19398
|
+
const word = (arg) => /^[\w./@+:=-]+$/.test(arg) ? arg : shellQuote(arg);
|
|
19399
|
+
return script.replace(/\$\{?([1-9])\}?/g, (_, n) => word(args[Number(n) - 1] ?? "")).replace(/\$\{?[@*]\}?/g, args.map(word).join(" "));
|
|
19400
|
+
};
|
|
19401
|
+
var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
19402
|
+
const sub = invocation.args[0];
|
|
19403
|
+
if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
|
|
19404
|
+
return [invocation];
|
|
19405
|
+
const dir = path20.resolve(root, invocation.dir ?? ".");
|
|
19406
|
+
if (!fs16.existsSync(dir))
|
|
19407
|
+
return [invocation];
|
|
19408
|
+
const config = gitConfig(dir, invocation, cache);
|
|
19409
|
+
const alias = configValue(config, `alias.${sub.toLowerCase()}`);
|
|
19410
|
+
if (alias === undefined) {
|
|
19411
|
+
const corrected = autocorrected(sub, config);
|
|
19412
|
+
return corrected ? [{ ...invocation, args: [corrected, ...invocation.args.slice(1)] }] : [invocation];
|
|
19413
|
+
}
|
|
19414
|
+
const rest = invocation.args.slice(1);
|
|
19415
|
+
const expanded = alias.startsWith("!") ? rawInvocations([positional(alias.slice(1), rest), ...rest.map(shellQuote)].join(" ")).map((inner) => ({
|
|
19416
|
+
...inner,
|
|
19417
|
+
dir: rebase(invocation.dir, inner.dir),
|
|
19418
|
+
...inner.tool === "git" && (invocation.config || inner.config) ? { config: [...invocation.config ?? [], ...inner.config ?? []] } : {},
|
|
19419
|
+
...inner.tool === "git" && (invocation.env || inner.env) ? { env: { ...invocation.env, ...inner.env } } : {}
|
|
19420
|
+
})) : [
|
|
19421
|
+
gitInvocation([...segmentsOf(alias)[0]?.words ?? [], ...rest], invocation.dir, invocation.env, invocation.stdin, invocation.config)
|
|
19422
|
+
];
|
|
19423
|
+
return expanded.flatMap((inner) => expandGitAliases(root, inner, cache, depth + 1));
|
|
19424
|
+
};
|
|
19425
|
+
var normalizedUrl = (url, dir) => {
|
|
19426
|
+
const trimmed = url.trim();
|
|
19427
|
+
if (/^file:\/\//i.test(trimmed))
|
|
19428
|
+
return path20.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
19429
|
+
const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
|
|
19430
|
+
const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
|
|
19431
|
+
if (!scheme && !scp)
|
|
19432
|
+
return path20.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
19433
|
+
const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
|
|
19434
|
+
return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
19435
|
+
};
|
|
19436
|
+
var rewrittenUrl = (url, config) => {
|
|
19437
|
+
for (const kind of ["pushinsteadof", "insteadof"]) {
|
|
19438
|
+
let best = null;
|
|
19439
|
+
for (const [key, prefixes] of config) {
|
|
19440
|
+
if (!key.startsWith("url.") || !key.endsWith(`.${kind}`))
|
|
19441
|
+
continue;
|
|
19442
|
+
const base = key.slice(4, -(kind.length + 1));
|
|
19443
|
+
for (const prefix of prefixes)
|
|
19444
|
+
if (url.startsWith(prefix) && prefix.length > (best?.prefix.length ?? -1))
|
|
19445
|
+
best = { base, prefix };
|
|
19446
|
+
}
|
|
19447
|
+
if (best)
|
|
19448
|
+
return best.base + url.slice(best.prefix.length);
|
|
19449
|
+
}
|
|
19450
|
+
return url;
|
|
19451
|
+
};
|
|
19452
|
+
var pushUrl = (config, remote, dir) => {
|
|
19453
|
+
const configured = configValue(config, `remote.${remote}.pushurl`) ?? configValue(config, `remote.${remote}.url`);
|
|
19454
|
+
return normalizedUrl(rewrittenUrl(configured ?? remote, config), dir);
|
|
19455
|
+
};
|
|
19456
|
+
var pushRemoteOf = (config, branch) => {
|
|
19457
|
+
const remotes = new Set;
|
|
19458
|
+
for (const key of config.keys()) {
|
|
19459
|
+
const name = /^remote\.(.+)\.url$/.exec(key)?.[1];
|
|
19460
|
+
if (name)
|
|
19461
|
+
remotes.add(name);
|
|
19462
|
+
}
|
|
19463
|
+
for (const candidate of [
|
|
19464
|
+
branch ? configValue(config, `branch.${branch}.pushremote`) : undefined,
|
|
19465
|
+
configValue(config, "remote.pushdefault"),
|
|
19466
|
+
branch ? configValue(config, `branch.${branch}.remote`) : undefined
|
|
19467
|
+
])
|
|
19468
|
+
if (candidate && candidate !== "." && remotes.has(candidate))
|
|
19469
|
+
return candidate;
|
|
19470
|
+
if (remotes.has("origin"))
|
|
19471
|
+
return "origin";
|
|
19472
|
+
return remotes.size === 1 ? [...remotes][0] : null;
|
|
19473
|
+
};
|
|
19474
|
+
var toPushRemote = (repo, remote, config) => {
|
|
19475
|
+
if (remote === null || /[$`]/.test(remote))
|
|
19476
|
+
return true;
|
|
19477
|
+
const pushRemote = pushRemoteOf(config, repo.branch);
|
|
19478
|
+
if (pushRemote === null || pushRemote === remote)
|
|
19479
|
+
return true;
|
|
19480
|
+
return pushUrl(config, remote, repo.dir) === pushUrl(config, pushRemote, repo.dir);
|
|
19481
|
+
};
|
|
18505
19482
|
var quote = (text) => `\`${text}\``;
|
|
18506
19483
|
var refusal = (action, branch, dir) => {
|
|
18507
19484
|
if (action.kind === "merge")
|
|
18508
|
-
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")}).`;
|
|
19485
|
+
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")}).`;
|
|
18509
19486
|
const plainPush = action.kind === "push" && !action.blindForce && !action.deletes;
|
|
18510
19487
|
if (dir && branch && plainPush && releaseBranch(dir, branch))
|
|
18511
19488
|
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 v<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")}.`;
|
|
@@ -18526,6 +19503,74 @@ var refFacts = (repo, remote) => {
|
|
|
18526
19503
|
}
|
|
18527
19504
|
return facts;
|
|
18528
19505
|
};
|
|
19506
|
+
var globBranches = (repo, glob) => {
|
|
19507
|
+
const source = glob.source.startsWith("refs/") ? glob.source : `refs/heads/${glob.source}`;
|
|
19508
|
+
const [sourcePrefix, sourceSuffix = ""] = source.split("*");
|
|
19509
|
+
const [destinationPrefix, destinationSuffix = ""] = glob.destination.split("*");
|
|
19510
|
+
const listed = spawnSync11("git", [
|
|
19511
|
+
"for-each-ref",
|
|
19512
|
+
"--format=%(refname)",
|
|
19513
|
+
sourcePrefix.slice(0, sourcePrefix.lastIndexOf("/") + 1)
|
|
19514
|
+
], { cwd: repo.dir, encoding: "utf8", timeout: 5000, windowsHide: true });
|
|
19515
|
+
const names = [];
|
|
19516
|
+
for (const ref of (listed.stdout ?? "").split(`
|
|
19517
|
+
`)) {
|
|
19518
|
+
if (!ref.startsWith(sourcePrefix) || !ref.endsWith(sourceSuffix))
|
|
19519
|
+
continue;
|
|
19520
|
+
const middle = ref.slice(sourcePrefix.length, ref.length - sourceSuffix.length);
|
|
19521
|
+
const { name } = pushDestination(destinationPrefix + middle + destinationSuffix);
|
|
19522
|
+
if (name)
|
|
19523
|
+
names.push(name);
|
|
19524
|
+
}
|
|
19525
|
+
return names;
|
|
19526
|
+
};
|
|
19527
|
+
var pushedBranches = (action, repo, config, facts, remote) => {
|
|
19528
|
+
const targets = action.implicit ? [] : [...action.targets];
|
|
19529
|
+
const globs = [...action.globs ?? []];
|
|
19530
|
+
let matching = action.matching === true;
|
|
19531
|
+
const configured = action.implicit ? config.get(`remote.${remote}.push`) : undefined;
|
|
19532
|
+
if (configured?.length) {
|
|
19533
|
+
const parsed = pushRefspecs(configured);
|
|
19534
|
+
targets.push(...parsed.targets);
|
|
19535
|
+
globs.push(...parsed.globs);
|
|
19536
|
+
matching ||= parsed.matching;
|
|
19537
|
+
} else if (action.implicit) {
|
|
19538
|
+
const mode = (configValue(config, "push.default") ?? "simple").toLowerCase();
|
|
19539
|
+
const merge = repo.branch ? configValue(config, `branch.${repo.branch}.merge`) : undefined;
|
|
19540
|
+
if (mode === "matching")
|
|
19541
|
+
matching = true;
|
|
19542
|
+
else if ((mode === "upstream" || mode === "tracking") && merge?.startsWith("refs/heads/"))
|
|
19543
|
+
targets.push(merge.slice(11));
|
|
19544
|
+
else if (mode !== "nothing")
|
|
19545
|
+
targets.push(null);
|
|
19546
|
+
}
|
|
19547
|
+
if (action.allBranches)
|
|
19548
|
+
targets.push(...facts.heads);
|
|
19549
|
+
if (matching) {
|
|
19550
|
+
for (const head of facts.heads)
|
|
19551
|
+
if (facts.remoteHeads.has(head))
|
|
19552
|
+
targets.push(head);
|
|
19553
|
+
}
|
|
19554
|
+
for (const glob of globs)
|
|
19555
|
+
targets.push(...globBranches(repo, glob));
|
|
19556
|
+
return targets;
|
|
19557
|
+
};
|
|
19558
|
+
var literalReadings = (name) => {
|
|
19559
|
+
if (!/[$`]/.test(name))
|
|
19560
|
+
return [name];
|
|
19561
|
+
const withDefaults = name.replace(/\$\{\w+:?[-=]([^}$`]*)\}/g, "$1").replace(/\$\{\w+\}|\$\w+/g, "");
|
|
19562
|
+
return /[$`]/.test(withDefaults) || !withDefaults ? [] : [withDefaults];
|
|
19563
|
+
};
|
|
19564
|
+
var guardedTarget = (dir, target) => {
|
|
19565
|
+
for (const branch of literalReadings(target)) {
|
|
19566
|
+
if (guardedBranch(dir, branch))
|
|
19567
|
+
return branch;
|
|
19568
|
+
const bare = branch.startsWith("heads/") ? branch.slice(6) : null;
|
|
19569
|
+
if (bare && guardedBranch(dir, bare))
|
|
19570
|
+
return bare;
|
|
19571
|
+
}
|
|
19572
|
+
return null;
|
|
19573
|
+
};
|
|
18529
19574
|
var isTag = (facts, name) => facts.tags.has(name) && !facts.heads.has(name);
|
|
18530
19575
|
var tagRefusal = (action, facts) => {
|
|
18531
19576
|
const tags = [
|
|
@@ -18537,24 +19582,32 @@ var tagRefusal = (action, facts) => {
|
|
|
18537
19582
|
const named = tags.length ? tags.join(" --release ") : "v<version>";
|
|
18538
19583
|
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}`)} (v<version> 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")}).`;
|
|
18539
19584
|
};
|
|
18540
|
-
var
|
|
18541
|
-
const listed = spawnSync11("git", ["ls-remote", "--heads", remote
|
|
19585
|
+
var remoteHeads = (repo, remote) => {
|
|
19586
|
+
const listed = spawnSync11("git", ["ls-remote", "--heads", remote], {
|
|
18542
19587
|
cwd: repo.dir,
|
|
18543
19588
|
encoding: "utf8",
|
|
18544
19589
|
timeout: 3000,
|
|
19590
|
+
windowsHide: true,
|
|
18545
19591
|
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
18546
19592
|
});
|
|
18547
|
-
|
|
19593
|
+
if (listed.status !== 0)
|
|
19594
|
+
return null;
|
|
19595
|
+
return new Set((listed.stdout ?? "").split(`
|
|
19596
|
+
`).map((line) => line.split("\t")[1] ?? "").filter((ref) => ref.startsWith("refs/heads/")).map((ref) => ref.slice(11)));
|
|
18548
19597
|
};
|
|
18549
19598
|
var offPolicyPush = (action, repo, facts, remote) => {
|
|
18550
19599
|
const names = action.allBranches ? [...facts.heads] : action.targets.map((target) => target ?? repo.branch);
|
|
19600
|
+
let listed;
|
|
19601
|
+
const remoteHas = (branch) => (listed === undefined ? listed = remoteHeads(repo, remote) : listed)?.has(branch) ?? true;
|
|
18551
19602
|
for (const branch of names) {
|
|
18552
|
-
if (!branch ||
|
|
19603
|
+
if (!branch || /[$`]/.test(branch))
|
|
19604
|
+
continue;
|
|
19605
|
+
if (action.deleted?.includes(branch) || isTag(facts, branch))
|
|
18553
19606
|
continue;
|
|
18554
19607
|
if (facts.remoteHeads.has(branch))
|
|
18555
19608
|
continue;
|
|
18556
19609
|
const check = validateBranchNameFor(repo.dir, branch);
|
|
18557
|
-
if (check.ok || check.rule !== "allowed_pattern" || remoteHas(
|
|
19610
|
+
if (check.ok || check.rule !== "allowed_pattern" || remoteHas(branch))
|
|
18558
19611
|
continue;
|
|
18559
19612
|
return `workit: raw ${quote("git push")} onto ${branch}: ${check.error}`;
|
|
18560
19613
|
}
|
|
@@ -18576,23 +19629,50 @@ var nudgeFor = (action, host, session) => {
|
|
|
18576
19629
|
return null;
|
|
18577
19630
|
}
|
|
18578
19631
|
};
|
|
18579
|
-
var
|
|
19632
|
+
var pushRefusal = (action, repo, config) => {
|
|
19633
|
+
if (!toPushRemote(repo, action.remote, config))
|
|
19634
|
+
return null;
|
|
19635
|
+
if (action.mirror)
|
|
19636
|
+
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")}.`;
|
|
19637
|
+
const remote = action.remote ?? pushRemoteOf(config, repo.branch) ?? "origin";
|
|
19638
|
+
const facts = refFacts(repo, remote);
|
|
19639
|
+
const targets = pushedBranches(action, repo, config, facts, remote);
|
|
19640
|
+
const pushed = { ...action, targets };
|
|
19641
|
+
const offPolicy = action.allBranches ? offPolicyPush(pushed, repo, facts, remote) : null;
|
|
19642
|
+
if (offPolicy)
|
|
19643
|
+
return offPolicy;
|
|
19644
|
+
for (const target of targets) {
|
|
19645
|
+
const guarded = guardedTarget(repo.dir, target ?? repo.branch ?? "");
|
|
19646
|
+
if (guarded)
|
|
19647
|
+
return refusal(action, guarded, repo.dir);
|
|
19648
|
+
}
|
|
19649
|
+
return tagRefusal(pushed, facts) ?? (action.deletes ? null : offPolicyPush(pushed, repo, facts, remote));
|
|
19650
|
+
};
|
|
19651
|
+
var actionsIn = (cwd, command, dialect, cache = new Map) => {
|
|
18580
19652
|
const out = [];
|
|
18581
19653
|
const repos = new Map;
|
|
18582
|
-
|
|
18583
|
-
|
|
18584
|
-
continue;
|
|
18585
|
-
const action = rawAction(invocation);
|
|
18586
|
-
if (!action)
|
|
18587
|
-
continue;
|
|
18588
|
-
const dir = path20.resolve(cwd, invocation.dir ?? ".");
|
|
19654
|
+
const repoFor = (relative) => {
|
|
19655
|
+
const dir = path20.resolve(cwd, relative ?? ".");
|
|
18589
19656
|
if (!repos.has(dir)) {
|
|
18590
19657
|
const repo = repoAt(dir);
|
|
18591
19658
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
18592
19659
|
}
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
|
|
19660
|
+
return repos.get(dir) ?? null;
|
|
19661
|
+
};
|
|
19662
|
+
for (const raw of rawInvocations(command, dialect)) {
|
|
19663
|
+
if (raw.dir === undefined)
|
|
19664
|
+
continue;
|
|
19665
|
+
const known = raw.tool !== "git" || GIT_COMMANDS.has(raw.args[0] ?? "");
|
|
19666
|
+
if (!known && !repoFor(raw.dir))
|
|
19667
|
+
continue;
|
|
19668
|
+
for (const invocation of known ? [raw] : expandGitAliases(cwd, raw, cache)) {
|
|
19669
|
+
if (invocation.dir === undefined)
|
|
19670
|
+
continue;
|
|
19671
|
+
const action = rawAction(invocation);
|
|
19672
|
+
const repo = action ? repoFor(invocation.dir) : null;
|
|
19673
|
+
if (action && repo)
|
|
19674
|
+
out.push({ action, repo, invocation });
|
|
19675
|
+
}
|
|
18596
19676
|
}
|
|
18597
19677
|
return out;
|
|
18598
19678
|
};
|
|
@@ -18621,31 +19701,18 @@ var unseenNudges = (input, nudges, store) => {
|
|
|
18621
19701
|
};
|
|
18622
19702
|
function rawGitPre(input, command, options = {}) {
|
|
18623
19703
|
try {
|
|
18624
|
-
if (!mentionsRawTool(command))
|
|
18625
|
-
return NONE2;
|
|
18626
19704
|
const dialect = dialectOf(input);
|
|
18627
19705
|
const nudges = new Map;
|
|
18628
19706
|
let store = null;
|
|
18629
|
-
|
|
19707
|
+
const cache = new Map;
|
|
19708
|
+
for (const { action, repo, invocation } of actionsIn(input.cwd, command, dialect, cache)) {
|
|
18630
19709
|
store ??= repo.location.dir;
|
|
18631
19710
|
if (action.kind === "merge")
|
|
18632
19711
|
return deny(refusal(action, null));
|
|
18633
|
-
if (action.kind === "push"
|
|
18634
|
-
|
|
18635
|
-
|
|
18636
|
-
|
|
18637
|
-
const branch = target ?? repo.branch;
|
|
18638
|
-
if (branch && guardedBranch(repo.dir, branch))
|
|
18639
|
-
return deny(refusal(action, branch, repo.dir));
|
|
18640
|
-
}
|
|
18641
|
-
const remote = action.remote ?? pushRemoteName(repo.dir, repo.branch) ?? "origin";
|
|
18642
|
-
const facts = refFacts(repo, remote);
|
|
18643
|
-
const tagDeny = tagRefusal(action, facts);
|
|
18644
|
-
if (tagDeny)
|
|
18645
|
-
return deny(tagDeny);
|
|
18646
|
-
const nameDeny = action.deletes ? null : offPolicyPush(action, repo, facts, remote);
|
|
18647
|
-
if (nameDeny)
|
|
18648
|
-
return deny(nameDeny);
|
|
19712
|
+
if (action.kind === "push") {
|
|
19713
|
+
const refused = pushRefusal(action, repo, gitConfig(repo.dir, invocation, cache));
|
|
19714
|
+
if (refused)
|
|
19715
|
+
return deny(refused);
|
|
18649
19716
|
}
|
|
18650
19717
|
const nudge = nudgeFor(action, input.host, input.session.id);
|
|
18651
19718
|
if (nudge && !nudges.has(nudgeKind(action)))
|
|
@@ -18658,11 +19725,17 @@ function rawGitPre(input, command, options = {}) {
|
|
|
18658
19725
|
const shown = unseenNudges(input, nudges, store);
|
|
18659
19726
|
return shown.length ? { kind: "context", text: shown.join(`
|
|
18660
19727
|
`) } : NONE2;
|
|
18661
|
-
} catch {
|
|
18662
|
-
return NONE2;
|
|
19728
|
+
} catch (error) {
|
|
19729
|
+
return error instanceof ShellAnalysisError ? analysisDenial(error) : NONE2;
|
|
18663
19730
|
}
|
|
18664
19731
|
}
|
|
18665
19732
|
var deny = (reason) => ({ kind: "deny", reason, unblock: null });
|
|
19733
|
+
var SPLIT_IT = "Split it into simpler commands (no deeply nested substitutions or huge brace lists) and run them one at a time.";
|
|
19734
|
+
var analysisDenial = (error) => ({
|
|
19735
|
+
kind: "deny",
|
|
19736
|
+
reason: `workit: the shell hook could not analyze this command (${error.message}), so it does not run. ${SPLIT_IT}`,
|
|
19737
|
+
unblock: SPLIT_IT
|
|
19738
|
+
});
|
|
18666
19739
|
var NEXT_COMMAND = "next";
|
|
18667
19740
|
var MARKER_TTL_SECONDS = 3600;
|
|
18668
19741
|
var markerFile = (repo, session, key) => path20.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
|
|
@@ -18763,20 +19836,28 @@ var UNKNOWABLE = /[$`*?[\]{}~]/u;
|
|
|
18763
19836
|
var SWITCH_CREATE = new Set(["-c", "--create", "-C", "--force-create", "--orphan"]);
|
|
18764
19837
|
var CHECKOUT_CREATE = new Set(["-b", "-B", "--orphan"]);
|
|
18765
19838
|
var WORKTREE_CREATE = new Set(["-b", "-B"]);
|
|
19839
|
+
var SUBTREE_CREATE = new Set(["-b", "--branch"]);
|
|
18766
19840
|
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"]));
|
|
18767
19841
|
var BRANCH_RENAME = new Set(["-m", "-M", "--move", "-c", "-C", "--copy"]);
|
|
19842
|
+
var longOption = (name, flags) => flags.has(name) || name.length >= 3 && [...flags].some((flag) => flag.startsWith("--") && flag.startsWith(name));
|
|
19843
|
+
var shortsOf = (flags) => [...flags].filter((flag) => /^-[^-]$/u.test(flag)).join("").replaceAll("-", "");
|
|
18768
19844
|
var flagValue = (args, flags) => {
|
|
19845
|
+
const shorts = shortsOf(flags);
|
|
18769
19846
|
for (let index = 1;index < args.length; index++) {
|
|
18770
19847
|
const arg = args[index];
|
|
18771
19848
|
if (arg === "--")
|
|
18772
19849
|
return null;
|
|
18773
|
-
if (
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
return arg.slice(eq + 1);
|
|
18778
|
-
|
|
18779
|
-
|
|
19850
|
+
if (arg.startsWith("--")) {
|
|
19851
|
+
const eq = arg.indexOf("=");
|
|
19852
|
+
if (!longOption(eq > 0 ? arg.slice(0, eq) : arg, flags))
|
|
19853
|
+
continue;
|
|
19854
|
+
return eq > 0 ? arg.slice(eq + 1) : args[index + 1] ?? null;
|
|
19855
|
+
}
|
|
19856
|
+
if (!arg.startsWith("-") || arg.length < 2)
|
|
19857
|
+
continue;
|
|
19858
|
+
for (let at = 1;at < arg.length; at++)
|
|
19859
|
+
if (shorts.includes(arg[at]))
|
|
19860
|
+
return at + 1 < arg.length ? arg.slice(at + 1) : args[index + 1] ?? null;
|
|
18780
19861
|
}
|
|
18781
19862
|
return null;
|
|
18782
19863
|
};
|
|
@@ -18809,62 +19890,128 @@ var branchCommandTarget = (args) => {
|
|
|
18809
19890
|
positionals.push(...args.slice(index + 1));
|
|
18810
19891
|
break;
|
|
18811
19892
|
}
|
|
18812
|
-
|
|
18813
|
-
|
|
18814
|
-
|
|
18815
|
-
|
|
18816
|
-
|
|
18817
|
-
|
|
19893
|
+
if (arg.startsWith("--")) {
|
|
19894
|
+
const flag = arg.split("=", 1)[0];
|
|
19895
|
+
if (longOption(flag, BRANCH_NO_CREATE))
|
|
19896
|
+
return null;
|
|
19897
|
+
if (longOption(flag, BRANCH_RENAME))
|
|
19898
|
+
rename = true;
|
|
19899
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
19900
|
+
const shorts = arg.slice(1).split("");
|
|
19901
|
+
if (shorts.some((short) => BRANCH_NO_CREATE.has(`-${short}`)))
|
|
19902
|
+
return null;
|
|
19903
|
+
if (shorts.some((short) => BRANCH_RENAME.has(`-${short}`)))
|
|
19904
|
+
rename = true;
|
|
19905
|
+
} else
|
|
18818
19906
|
positionals.push(arg);
|
|
18819
19907
|
}
|
|
18820
19908
|
if (positionals.length < 1 || positionals.length > 2)
|
|
18821
19909
|
return null;
|
|
18822
19910
|
return rename ? positionals.at(-1) ?? null : positionals[0];
|
|
18823
19911
|
};
|
|
18824
|
-
var
|
|
18825
|
-
const
|
|
18826
|
-
|
|
18827
|
-
|
|
19912
|
+
var positionalsOf = (args, skip, values = new Set) => {
|
|
19913
|
+
const found = [];
|
|
19914
|
+
for (let index = skip;index < args.length; index++) {
|
|
19915
|
+
const arg = args[index];
|
|
19916
|
+
if (arg === "--")
|
|
19917
|
+
return [...found, ...args.slice(index + 1)];
|
|
19918
|
+
if (values.has(arg))
|
|
19919
|
+
index++;
|
|
19920
|
+
else if (!arg.startsWith("-") || arg === "-")
|
|
19921
|
+
found.push(arg);
|
|
19922
|
+
}
|
|
19923
|
+
return found;
|
|
18828
19924
|
};
|
|
18829
|
-
var
|
|
18830
|
-
|
|
19925
|
+
var localHead = (ref) => ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : null;
|
|
19926
|
+
var updateRefTargets = (args, stdin) => {
|
|
19927
|
+
if (args.some((arg) => arg === "-d" || arg === "--delete"))
|
|
18831
19928
|
return [];
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
19929
|
+
if (args.includes("--stdin"))
|
|
19930
|
+
return (stdin ?? "").split(/[\n\0]/u).map((line) => /^\s*(?:create|update)\s+(\S+)/u.exec(line)?.[1] ?? "").map(localHead).filter((name) => name !== null);
|
|
19931
|
+
const [ref] = positionalsOf(args, 1, new Set(["-m"]));
|
|
19932
|
+
const name = ref ? localHead(ref) : null;
|
|
19933
|
+
return name ? [name] : [];
|
|
19934
|
+
};
|
|
19935
|
+
var symbolicRefTarget = (args) => {
|
|
19936
|
+
if (args.some((arg) => arg === "-d" || arg === "--delete"))
|
|
19937
|
+
return null;
|
|
19938
|
+
const [, ref] = positionalsOf(args, 1, new Set(["-m"]));
|
|
19939
|
+
return ref ? localHead(ref) : null;
|
|
19940
|
+
};
|
|
19941
|
+
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"]));
|
|
19942
|
+
var fetchTargets = (args, stdin) => {
|
|
19943
|
+
if (args.includes("--all") || args.includes("--multiple"))
|
|
19944
|
+
return [];
|
|
19945
|
+
const specs = args.includes("--stdin") ? (stdin ?? "").split(/\s+/u).filter(Boolean) : positionalsOf(args, 1, FETCH_VALUES).slice(1);
|
|
19946
|
+
const names = [];
|
|
19947
|
+
for (const raw of specs) {
|
|
19948
|
+
const colon = raw.indexOf(":");
|
|
19949
|
+
const destination = colon >= 0 ? raw.slice(colon + 1) : "";
|
|
19950
|
+
if (!destination || destination.includes("*"))
|
|
18835
19951
|
continue;
|
|
18836
|
-
const
|
|
18837
|
-
if (
|
|
18838
|
-
|
|
19952
|
+
const name = destination.startsWith("refs/") ? localHead(destination) : destination;
|
|
19953
|
+
if (name)
|
|
19954
|
+
names.push(name);
|
|
18839
19955
|
}
|
|
18840
|
-
return
|
|
19956
|
+
return names;
|
|
19957
|
+
};
|
|
19958
|
+
var localPushTargets = (args) => {
|
|
19959
|
+
const action = pushAction(args);
|
|
19960
|
+
if (action?.kind !== "push" || action.remote !== "." || action.deletes)
|
|
19961
|
+
return [];
|
|
19962
|
+
return action.targets.filter((name) => name !== null);
|
|
19963
|
+
};
|
|
19964
|
+
var gitBranchCreations = (args, stdin) => {
|
|
19965
|
+
const [sub, second] = args;
|
|
19966
|
+
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)] : [];
|
|
19967
|
+
return targets.filter((target) => target !== null && target !== "" && !target.startsWith("-") && !UNKNOWABLE.test(target));
|
|
18841
19968
|
};
|
|
19969
|
+
var targetsOf = (invocations) => invocations.flatMap((invocation) => invocation.tool === "git" ? gitBranchCreations(invocation.args, invocation.stdin).map((branch) => ({
|
|
19970
|
+
branch,
|
|
19971
|
+
dir: invocation.dir
|
|
19972
|
+
})) : []);
|
|
18842
19973
|
var localBranchExists = (dir, branch) => spawnSync12("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], {
|
|
18843
19974
|
cwd: dir,
|
|
18844
19975
|
stdio: "ignore",
|
|
18845
19976
|
timeout: 5000
|
|
18846
19977
|
}).status === 0;
|
|
19978
|
+
var judgedDir = (root, dir) => {
|
|
19979
|
+
if (dir === undefined)
|
|
19980
|
+
return null;
|
|
19981
|
+
if (dir === null)
|
|
19982
|
+
return root;
|
|
19983
|
+
const resolved = path21.resolve(root, dir);
|
|
19984
|
+
return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
|
|
19985
|
+
};
|
|
18847
19986
|
var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
18848
19987
|
let judged = false;
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
|
|
18852
|
-
const dir = target.dir === null ? root : path21.resolve(root, target.dir);
|
|
18853
|
-
if (target.dir !== null && (!existsSync6(dir) || !inWorkitWorkspace(dir)))
|
|
19988
|
+
const cache = new Map;
|
|
19989
|
+
for (const raw of rawInvocations(command, dialect)) {
|
|
19990
|
+
if (raw.tool !== "git" || judgedDir(root, raw.dir) === null)
|
|
18854
19991
|
continue;
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18860
|
-
|
|
19992
|
+
for (const target of targetsOf(expandGitAliases(root, raw, cache))) {
|
|
19993
|
+
const dir = judgedDir(root, target.dir);
|
|
19994
|
+
if (dir === null || localBranchExists(dir, target.branch))
|
|
19995
|
+
continue;
|
|
19996
|
+
judged = true;
|
|
19997
|
+
const check = validateBranchNameFor(dir, target.branch);
|
|
19998
|
+
if (!check.ok)
|
|
19999
|
+
return check;
|
|
20000
|
+
}
|
|
18861
20001
|
}
|
|
18862
20002
|
return judged ? { ok: true } : null;
|
|
18863
20003
|
};
|
|
18864
20004
|
|
|
18865
20005
|
// packages/workit-core/src/hooks/policy.ts
|
|
18866
20006
|
var shellPolicy = (cwd, command, dialect = "posix") => {
|
|
18867
|
-
|
|
20007
|
+
let policy;
|
|
20008
|
+
try {
|
|
20009
|
+
policy = shellBranchPolicyViolation(cwd, command, dialect);
|
|
20010
|
+
} catch (error) {
|
|
20011
|
+
if (error instanceof ShellAnalysisError)
|
|
20012
|
+
return analysisDenial(error);
|
|
20013
|
+
throw error;
|
|
20014
|
+
}
|
|
18868
20015
|
return policy && !policy.ok ? { kind: "deny", reason: `branch_policy_denied: ${policy.error}`, unblock: null } : { kind: "none" };
|
|
18869
20016
|
};
|
|
18870
20017
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
@@ -18893,11 +20040,11 @@ var exempt = (cwd, root, file, plans) => {
|
|
|
18893
20040
|
const segments = posix.split("/");
|
|
18894
20041
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
18895
20042
|
};
|
|
18896
|
-
var
|
|
20043
|
+
var PREFIXES2 = new Set(["sudo", "command", "env", "nohup", "time", "exec", "xargs"]);
|
|
18897
20044
|
var operands = (words) => words.filter((item) => !item.startsWith("-"));
|
|
18898
20045
|
var editsOf = (input) => {
|
|
18899
20046
|
let words = input;
|
|
18900
|
-
while (words.length && (
|
|
20047
|
+
while (words.length && (PREFIXES2.has(words[0]) || /^\w+=/.test(words[0])))
|
|
18901
20048
|
words = words.slice(1);
|
|
18902
20049
|
const [verb, ...args] = words;
|
|
18903
20050
|
const name = (verb?.split(/[\\/]/).at(-1) ?? "").toLowerCase();
|
|
@@ -20194,7 +21341,7 @@ var CURSOR_DESCRIPTOR = {
|
|
|
20194
21341
|
"compact.pre": { support: "partial", native: "preCompact" },
|
|
20195
21342
|
stop: { support: "native", native: "stop" }
|
|
20196
21343
|
},
|
|
20197
|
-
shellPolicy: { deny: "native", channel: "exit2+json", failClosed:
|
|
21344
|
+
shellPolicy: { deny: "native", channel: "exit2+json", failClosed: false },
|
|
20198
21345
|
context: {
|
|
20199
21346
|
sessionStart: "native",
|
|
20200
21347
|
perTurn: "none",
|