openapi-typesafe-migrate 1.0.0-rc.10 → 1.0.0-rc.11
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/CHANGELOG.md +78 -0
- package/README.md +35 -9
- package/dist/cli/main.mjs +1178 -694
- package/dist/cli/main.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/main.mjs
CHANGED
|
@@ -2203,22 +2203,158 @@ function referencedFiles(path, documents) {
|
|
|
2203
2203
|
});
|
|
2204
2204
|
}
|
|
2205
2205
|
|
|
2206
|
+
const NONE = /* @__PURE__ */ new Set();
|
|
2207
|
+
const PACKAGE_OPTIONS = /* @__PURE__ */ new Set(["-p", "--package"]);
|
|
2208
|
+
const PACKAGE_MANAGER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2209
|
+
"--filter",
|
|
2210
|
+
"-F",
|
|
2211
|
+
"--dir",
|
|
2212
|
+
"-C",
|
|
2213
|
+
"--prefix",
|
|
2214
|
+
"--cwd",
|
|
2215
|
+
"--workspace"
|
|
2216
|
+
]);
|
|
2217
|
+
const launcher = (words, packageOptions = NONE, valueOptions = NONE) => {
|
|
2218
|
+
const allValueOptions = /* @__PURE__ */ new Set([...valueOptions, ...packageOptions]);
|
|
2219
|
+
return { words, packageOptions, valueOptions: allValueOptions, operands: 0 };
|
|
2220
|
+
};
|
|
2221
|
+
const CONTAINER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2222
|
+
"-e",
|
|
2223
|
+
"--env",
|
|
2224
|
+
"--env-file",
|
|
2225
|
+
"-v",
|
|
2226
|
+
"--volume",
|
|
2227
|
+
"--mount",
|
|
2228
|
+
"-p",
|
|
2229
|
+
"--publish",
|
|
2230
|
+
"-w",
|
|
2231
|
+
"--workdir",
|
|
2232
|
+
"-u",
|
|
2233
|
+
"--user",
|
|
2234
|
+
"--name",
|
|
2235
|
+
"--network",
|
|
2236
|
+
"--entrypoint",
|
|
2237
|
+
"--platform",
|
|
2238
|
+
"-l",
|
|
2239
|
+
"--label",
|
|
2240
|
+
"-h",
|
|
2241
|
+
"--hostname",
|
|
2242
|
+
"--add-host"
|
|
2243
|
+
]);
|
|
2244
|
+
const container = (words) => ({
|
|
2245
|
+
...launcher(words, NONE, CONTAINER_OPTIONS),
|
|
2246
|
+
operands: 1
|
|
2247
|
+
});
|
|
2248
|
+
const withOperands = (words, operands, valueOptions = NONE) => ({ ...launcher(words, NONE, valueOptions), operands });
|
|
2249
|
+
const XARGS_OPTIONS = /* @__PURE__ */ new Set([
|
|
2250
|
+
"-I",
|
|
2251
|
+
"-J",
|
|
2252
|
+
"-L",
|
|
2253
|
+
"-n",
|
|
2254
|
+
"-P",
|
|
2255
|
+
"-R",
|
|
2256
|
+
"-S",
|
|
2257
|
+
"-s",
|
|
2258
|
+
"-d",
|
|
2259
|
+
"-E",
|
|
2260
|
+
"-a",
|
|
2261
|
+
"--max-args",
|
|
2262
|
+
"--max-procs",
|
|
2263
|
+
"--max-lines",
|
|
2264
|
+
"--delimiter",
|
|
2265
|
+
"--arg-file"
|
|
2266
|
+
]);
|
|
2267
|
+
const NODE_OPTIONS = /* @__PURE__ */ new Set([
|
|
2268
|
+
"-r",
|
|
2269
|
+
"--require",
|
|
2270
|
+
"--import",
|
|
2271
|
+
"--loader",
|
|
2272
|
+
"--env-file"
|
|
2273
|
+
]);
|
|
2274
|
+
const LAUNCHERS = [
|
|
2275
|
+
launcher(["npm", "exec"], PACKAGE_OPTIONS),
|
|
2276
|
+
launcher(["npm", "x"], PACKAGE_OPTIONS),
|
|
2277
|
+
launcher(["pnpm", "exec"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2278
|
+
launcher(["pnpm", "dlx"], /* @__PURE__ */ new Set(["--package"])),
|
|
2279
|
+
launcher(["yarn", "dlx"], PACKAGE_OPTIONS),
|
|
2280
|
+
launcher(["yarn", "exec"]),
|
|
2281
|
+
launcher(["bun", "x"], PACKAGE_OPTIONS),
|
|
2282
|
+
withOperands(["yarn", "workspace"], 1),
|
|
2283
|
+
launcher(["dotenvx", "run"], NONE, /* @__PURE__ */ new Set(["-f", "--env-file", "-e", "--env", "--convention"])),
|
|
2284
|
+
launcher(
|
|
2285
|
+
["doppler", "run"],
|
|
2286
|
+
NONE,
|
|
2287
|
+
/* @__PURE__ */ new Set(["-p", "--project", "-c", "--config", "--token", "--mount", "--scope"])
|
|
2288
|
+
),
|
|
2289
|
+
launcher(["nx", "exec"], NONE, /* @__PURE__ */ new Set(["--projects", "-p", "--exclude"])),
|
|
2290
|
+
launcher(["deno", "run"], NONE, /* @__PURE__ */ new Set(["--config", "-c", "--import-map", "--location"])),
|
|
2291
|
+
launcher(["deno", "x"]),
|
|
2292
|
+
launcher(["npx"], PACKAGE_OPTIONS, /* @__PURE__ */ new Set(["-c", "--call"])),
|
|
2293
|
+
launcher(["pnpx"], PACKAGE_OPTIONS),
|
|
2294
|
+
launcher(["bunx"], PACKAGE_OPTIONS),
|
|
2295
|
+
// Like a bare `pnpm <name>`, a bare `bun <name>` runs the binary when no script has the name.
|
|
2296
|
+
launcher(["bun"], NONE, /* @__PURE__ */ new Set(["--cwd", "--filter", "-F"])),
|
|
2297
|
+
launcher(["corepack"]),
|
|
2298
|
+
launcher(["pnpm"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2299
|
+
launcher(["yarn"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2300
|
+
launcher(["node"], NONE, NODE_OPTIONS),
|
|
2301
|
+
launcher(["tsx"], NONE, NODE_OPTIONS),
|
|
2302
|
+
launcher(["ts-node"], NONE, /* @__PURE__ */ new Set([...NODE_OPTIONS, "-P", "--project", "-O", "--compiler"])),
|
|
2303
|
+
launcher(["cross-env"]),
|
|
2304
|
+
launcher(["dotenv"], NONE, /* @__PURE__ */ new Set(["-e", "-c", "-v"])),
|
|
2305
|
+
launcher(["env"], NONE, /* @__PURE__ */ new Set(["-u", "--unset", "-C", "--chdir"])),
|
|
2306
|
+
launcher(["exec"], NONE, /* @__PURE__ */ new Set(["-a"])),
|
|
2307
|
+
launcher(["command"]),
|
|
2308
|
+
launcher(["time"]),
|
|
2309
|
+
launcher(["nice"], NONE, /* @__PURE__ */ new Set(["-n", "--adjustment"])),
|
|
2310
|
+
withOperands(["timeout"], 1, /* @__PURE__ */ new Set(["-s", "--signal", "-k", "--kill-after"])),
|
|
2311
|
+
launcher(["xargs"], NONE, XARGS_OPTIONS),
|
|
2312
|
+
launcher(["nohup"]),
|
|
2313
|
+
launcher(["sudo"], NONE, /* @__PURE__ */ new Set(["-u", "-g"])),
|
|
2314
|
+
// The shell form of Dockerfile instructions runs the rest of the line in a shell.
|
|
2315
|
+
launcher(["RUN"], NONE, /* @__PURE__ */ new Set(["--mount", "--network", "--security"])),
|
|
2316
|
+
launcher(["CMD"]),
|
|
2317
|
+
launcher(["ENTRYPOINT"]),
|
|
2318
|
+
container(["docker", "run"]),
|
|
2319
|
+
container(["docker", "exec"]),
|
|
2320
|
+
container(["docker", "compose", "run"]),
|
|
2321
|
+
container(["docker", "compose", "exec"]),
|
|
2322
|
+
container(["podman", "run"]),
|
|
2323
|
+
container(["podman", "exec"])
|
|
2324
|
+
];
|
|
2325
|
+
const installers = (manager, subcommands) => subcommands.map((subcommand) => ({ words: [manager, subcommand] }));
|
|
2326
|
+
const NPM_INSTALL = ["install", "i", "add", "update", "up", "uninstall", "remove", "rm", "un"];
|
|
2327
|
+
const INSTALLERS = [
|
|
2328
|
+
...installers("npm", NPM_INSTALL),
|
|
2329
|
+
...installers("pnpm", ["add", "update", "up", "remove", "rm", "uninstall", "un"]),
|
|
2330
|
+
...installers("yarn", ["add", "upgrade", "up", "remove"]),
|
|
2331
|
+
// Yarn 1 installs global packages with `yarn global add`.
|
|
2332
|
+
{ words: ["yarn", "global", "add"] },
|
|
2333
|
+
{ words: ["yarn", "global", "remove"] },
|
|
2334
|
+
...installers("bun", ["add", "a", "update", "remove", "rm", "install", "i"]),
|
|
2335
|
+
...installers("deno", ["add", "install", "i", "remove", "uninstall"])
|
|
2336
|
+
];
|
|
2337
|
+
const NPM_SPECIFIER_PREFIX = "npm:";
|
|
2338
|
+
|
|
2206
2339
|
const EXPRESSION_OPEN = "${{";
|
|
2207
|
-
const EXPRESSION_CLOSE = "}}";
|
|
2340
|
+
const EXPRESSION_CLOSE$1 = "}}";
|
|
2208
2341
|
const LITERAL_QUOTE = "'";
|
|
2209
2342
|
const SHELL_SINGLE_QUOTE = "'";
|
|
2210
2343
|
const BACKSLASH$3 = "\\";
|
|
2211
2344
|
const DOUBLE_QUOTE$1 = '"';
|
|
2212
2345
|
function expressionEnd(text, start) {
|
|
2213
2346
|
for (let index = start + EXPRESSION_OPEN.length; index < text.length; ) {
|
|
2214
|
-
if (text.startsWith(EXPRESSION_CLOSE, index)) {
|
|
2215
|
-
return index + EXPRESSION_CLOSE.length;
|
|
2347
|
+
if (text.startsWith(EXPRESSION_CLOSE$1, index)) {
|
|
2348
|
+
return index + EXPRESSION_CLOSE$1.length;
|
|
2216
2349
|
}
|
|
2217
2350
|
const close = text[index] === LITERAL_QUOTE ? text.indexOf(LITERAL_QUOTE, index + 1) : index;
|
|
2218
2351
|
index = close === -1 ? text.length : close + 1;
|
|
2219
2352
|
}
|
|
2220
2353
|
return void 0;
|
|
2221
2354
|
}
|
|
2355
|
+
const INDEX_OPEN = "[";
|
|
2356
|
+
const TRAILING_BLANKS_RE = /[ \t]*$/;
|
|
2357
|
+
const isIndexKey = (raw, open) => raw.slice(0, open).replace(TRAILING_BLANKS_RE, "").endsWith(INDEX_OPEN);
|
|
2222
2358
|
function literalsIn(raw, start, end) {
|
|
2223
2359
|
const found = [];
|
|
2224
2360
|
let open = raw.indexOf(LITERAL_QUOTE, start);
|
|
@@ -2232,7 +2368,8 @@ function literalsIn(raw, start, end) {
|
|
|
2232
2368
|
if (close === -1) {
|
|
2233
2369
|
break;
|
|
2234
2370
|
}
|
|
2235
|
-
|
|
2371
|
+
const isValue = !isEscaped && !isIndexKey(raw, open);
|
|
2372
|
+
found.push(...isValue ? [{ text: raw.slice(open + 1, close), start: open + 1 }] : []);
|
|
2236
2373
|
open = raw.indexOf(LITERAL_QUOTE, close + 1);
|
|
2237
2374
|
}
|
|
2238
2375
|
return found;
|
|
@@ -2255,6 +2392,18 @@ function expressionLiterals(raw) {
|
|
|
2255
2392
|
}
|
|
2256
2393
|
return found;
|
|
2257
2394
|
}
|
|
2395
|
+
function mapExpressions(text, map) {
|
|
2396
|
+
const parts = [];
|
|
2397
|
+
let copiedUpTo = 0;
|
|
2398
|
+
for (let open = text.indexOf(EXPRESSION_OPEN); open !== -1; ) {
|
|
2399
|
+
const end = expressionEnd(text, open) ?? text.length;
|
|
2400
|
+
parts.push(text.slice(copiedUpTo, open), map(text.slice(open, end)));
|
|
2401
|
+
copiedUpTo = end;
|
|
2402
|
+
open = text.indexOf(EXPRESSION_OPEN, end);
|
|
2403
|
+
}
|
|
2404
|
+
parts.push(text.slice(copiedUpTo));
|
|
2405
|
+
return parts.join("");
|
|
2406
|
+
}
|
|
2258
2407
|
function isWholeExpression(raw) {
|
|
2259
2408
|
const isQuoted = raw.length > 1 && raw.startsWith(DOUBLE_QUOTE$1) && raw.endsWith(DOUBLE_QUOTE$1);
|
|
2260
2409
|
const inner = isQuoted ? 1 : 0;
|
|
@@ -2360,6 +2509,37 @@ function wordPart(text, index) {
|
|
|
2360
2509
|
}
|
|
2361
2510
|
return { end: index + 1, value: char };
|
|
2362
2511
|
}
|
|
2512
|
+
function doubleQuotedOffsets(text, start, end) {
|
|
2513
|
+
const offsets = [];
|
|
2514
|
+
for (let index = start + 1; index < end && text[index] !== '"'; index++) {
|
|
2515
|
+
const isEscape = text[index] === BACKSLASH$2 && DOUBLE_QUOTE_ESCAPES.has(text[index + 1] ?? "");
|
|
2516
|
+
index += isEscape ? 1 : 0;
|
|
2517
|
+
if (text[index] !== "\n" || !isEscape) {
|
|
2518
|
+
offsets.push(index);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
return offsets;
|
|
2522
|
+
}
|
|
2523
|
+
function partOffsets(text, start, part) {
|
|
2524
|
+
const char = text[start];
|
|
2525
|
+
if (char === '"') {
|
|
2526
|
+
return doubleQuotedOffsets(text, start, part.end);
|
|
2527
|
+
}
|
|
2528
|
+
const isOpened = char === "'" || char === BACKSLASH$2 && part.end - start > 1;
|
|
2529
|
+
const first = isOpened ? start + 1 : start;
|
|
2530
|
+
return Array.from(part.value, (_, index) => first + index);
|
|
2531
|
+
}
|
|
2532
|
+
function unquotedText(text) {
|
|
2533
|
+
let value = "";
|
|
2534
|
+
const offsets = [];
|
|
2535
|
+
for (let index = 0; index < text.length; ) {
|
|
2536
|
+
const part = wordPart(text, index);
|
|
2537
|
+
value += part.value;
|
|
2538
|
+
offsets.push(...partOffsets(text, index, part));
|
|
2539
|
+
index = part.end;
|
|
2540
|
+
}
|
|
2541
|
+
return { value, offsets };
|
|
2542
|
+
}
|
|
2363
2543
|
const ARRAY_HEAD_RE = /^[A-Za-z_][A-Za-z0-9_]*\+?=$/;
|
|
2364
2544
|
function arrayListEnd(text, index) {
|
|
2365
2545
|
let depth = 0;
|
|
@@ -2401,105 +2581,257 @@ const DECLARATION_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
2401
2581
|
"declare",
|
|
2402
2582
|
"typeset"
|
|
2403
2583
|
]);
|
|
2404
|
-
const QUOTES$3 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2405
|
-
const UNPLAIN_RE = /['"\\$`]/;
|
|
2406
2584
|
function leadingAssignments(command) {
|
|
2407
2585
|
const index = command.findIndex((word) => !ASSIGNMENT_RE$2.test(word.raw));
|
|
2408
2586
|
return index === -1 ? command.length : index;
|
|
2409
2587
|
}
|
|
2588
|
+
function assignmentOf(word) {
|
|
2589
|
+
const match = ASSIGNMENT_RE$2.exec(word.raw);
|
|
2590
|
+
const name = match?.[1];
|
|
2591
|
+
if (match === null || name === void 0) {
|
|
2592
|
+
return [];
|
|
2593
|
+
}
|
|
2594
|
+
const head = match[0].length;
|
|
2595
|
+
const isAppend = match[2] === APPEND_OPERATOR$1;
|
|
2596
|
+
return [{ name, value: word.value.slice(head), word, isAppend, head }];
|
|
2597
|
+
}
|
|
2410
2598
|
function shellAssignments(command) {
|
|
2411
2599
|
const count = leadingAssignments(command);
|
|
2412
2600
|
const isDeclaration = DECLARATION_BUILTINS.has(command[count]?.value ?? "");
|
|
2413
2601
|
const words = [...command.slice(0, count), ...isDeclaration ? command.slice(count + 1) : []];
|
|
2414
|
-
return words.flatMap(
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
}
|
|
2420
|
-
const head = match[0].length;
|
|
2421
|
-
const isAppend = match[2] === APPEND_OPERATOR$1;
|
|
2422
|
-
return [{ name, value: word.value.slice(head), word, isAppend, head }];
|
|
2423
|
-
});
|
|
2602
|
+
return words.flatMap(assignmentOf);
|
|
2603
|
+
}
|
|
2604
|
+
function argumentAssignments(command) {
|
|
2605
|
+
const own = new Set(shellAssignments(command).map(({ word }) => word));
|
|
2606
|
+
return command.slice(leadingAssignments(command)).filter((word) => !own.has(word)).flatMap(assignmentOf);
|
|
2424
2607
|
}
|
|
2608
|
+
const COMMAND_LINE_RE = /[\s;&|()`]/;
|
|
2609
|
+
const holdsCommandLine = (assignment) => COMMAND_LINE_RE.test(assignment.value);
|
|
2425
2610
|
const ARRAY_OPEN = "(";
|
|
2426
|
-
const ARRAY_CLOSE = ")";
|
|
2427
2611
|
const isArrayAssignment = (assignment) => assignment.word.raw.startsWith(ARRAY_OPEN, assignment.head);
|
|
2428
|
-
function
|
|
2429
|
-
const
|
|
2430
|
-
const
|
|
2431
|
-
|
|
2432
|
-
|
|
2612
|
+
function arrayValue({ word, head }) {
|
|
2613
|
+
const start = word.start + head + 1;
|
|
2614
|
+
const place = (found) => ({
|
|
2615
|
+
...found,
|
|
2616
|
+
start: found.start + start,
|
|
2617
|
+
end: found.end + start
|
|
2618
|
+
});
|
|
2619
|
+
return { text: word.raw.slice(head + 1, -1), place };
|
|
2620
|
+
}
|
|
2621
|
+
function assignmentValue(assignment) {
|
|
2433
2622
|
if (isArrayAssignment(assignment)) {
|
|
2434
|
-
return
|
|
2435
|
-
}
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2623
|
+
return arrayValue(assignment);
|
|
2624
|
+
}
|
|
2625
|
+
const { word, head } = assignment;
|
|
2626
|
+
const { value, offsets } = unquotedText(word.raw.slice(head));
|
|
2627
|
+
const written = (index) => head + offsets[index];
|
|
2628
|
+
const place = (found) => {
|
|
2629
|
+
const first = written(found.start);
|
|
2630
|
+
const end = written(found.end - 1) + 1;
|
|
2631
|
+
const raw = word.raw.slice(first, end);
|
|
2632
|
+
return { ...found, start: word.start + first, end: word.start + end, raw };
|
|
2633
|
+
};
|
|
2634
|
+
return { text: value, place };
|
|
2441
2635
|
}
|
|
2442
2636
|
|
|
2443
|
-
const
|
|
2444
|
-
const
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
function heredocAt(text, index, where) {
|
|
2450
|
-
if (text.startsWith(HERE_STRING_OPERATOR, index)) {
|
|
2451
|
-
return { end: index + HERE_STRING_OPERATOR.length };
|
|
2452
|
-
}
|
|
2453
|
-
if (!text.startsWith(HEREDOC_OPERATOR, index)) {
|
|
2454
|
-
return void 0;
|
|
2455
|
-
}
|
|
2456
|
-
let start = index + HEREDOC_OPERATOR.length;
|
|
2457
|
-
const isTabStripped = text[start] === STRIP_TABS;
|
|
2458
|
-
start += isTabStripped ? 1 : 0;
|
|
2459
|
-
while (text[start] === " " || text[start] === " ") {
|
|
2460
|
-
start++;
|
|
2637
|
+
const END_OF_OPTIONS = "--";
|
|
2638
|
+
const isOption$1 = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
2639
|
+
function skipAssignments(words, start) {
|
|
2640
|
+
let index = start;
|
|
2641
|
+
while (index < words.length && ASSIGNMENT_RE$2.test(words[index].raw)) {
|
|
2642
|
+
index++;
|
|
2461
2643
|
}
|
|
2462
|
-
|
|
2463
|
-
const pending = { delimiter: word.value, isTabStripped, ...where };
|
|
2464
|
-
return word.value === "" ? void 0 : { pending, end: word.end };
|
|
2644
|
+
return index;
|
|
2465
2645
|
}
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2646
|
+
const WINDOWS_PROGRAM_SUFFIX_RE = /\.(?:cmd|exe|ps1)$/i;
|
|
2647
|
+
const windowsSuffix = (value) => WINDOWS_PROGRAM_SUFFIX_RE.exec(value)?.[0] ?? "";
|
|
2648
|
+
const withoutWindowsSuffix = (value) => value.slice(0, value.length - windowsSuffix(value).length);
|
|
2649
|
+
const entryWord = (word) => word === void 0 ? void 0 : withoutWindowsSuffix(word.value);
|
|
2650
|
+
function matchingPrefix(entries, words, index) {
|
|
2651
|
+
return entries.find(
|
|
2652
|
+
(entry) => entry.words.every((name, offset) => entryWord(words[index + offset]) === name)
|
|
2653
|
+
);
|
|
2474
2654
|
}
|
|
2475
|
-
function
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
const end = lineEnd === -1 ? text.length : lineEnd;
|
|
2480
|
-
if (isDelimiterLine(text, lineStart, end, heredoc)) {
|
|
2481
|
-
const body = { command: heredoc.command, start, text: text.slice(start, lineStart) };
|
|
2482
|
-
return { body, end: Math.min(end + 1, text.length) };
|
|
2483
|
-
}
|
|
2484
|
-
lineStart = end + 1;
|
|
2485
|
-
}
|
|
2486
|
-
return { body: { command: heredoc.command, start, text: text.slice(start) }, end: text.length };
|
|
2655
|
+
function inlineOptionPackage(word, launcher) {
|
|
2656
|
+
const equals = word.value.indexOf("=");
|
|
2657
|
+
const name = word.value.slice(0, equals);
|
|
2658
|
+
return launcher.packageOptions.has(name) ? { word, value: word.value.slice(equals + 1) } : void 0;
|
|
2487
2659
|
}
|
|
2488
|
-
function
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2660
|
+
function launchedProgram(words, start, launcher, packages) {
|
|
2661
|
+
let index = start;
|
|
2662
|
+
while (index < words.length && isOption$1(words[index])) {
|
|
2663
|
+
const option = words[index++];
|
|
2664
|
+
if (option.value === END_OF_OPTIONS) {
|
|
2665
|
+
break;
|
|
2666
|
+
}
|
|
2667
|
+
const inline = option.value.includes("=") ? inlineOptionPackage(option, launcher) : void 0;
|
|
2668
|
+
if (inline !== void 0) {
|
|
2669
|
+
packages.push(inline);
|
|
2670
|
+
}
|
|
2671
|
+
const value = words[index];
|
|
2672
|
+
if (!option.value.includes("=") && launcher.valueOptions.has(option.value) && value) {
|
|
2673
|
+
if (launcher.packageOptions.has(option.value)) {
|
|
2674
|
+
packages.push({ word: value, value: value.value });
|
|
2675
|
+
}
|
|
2676
|
+
index++;
|
|
2677
|
+
}
|
|
2495
2678
|
}
|
|
2496
|
-
return
|
|
2679
|
+
return index;
|
|
2497
2680
|
}
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2681
|
+
const installArguments = (words, start) => words.slice(start).filter((word) => !isOption$1(word)).map((word) => ({ word, value: word.value }));
|
|
2682
|
+
function commandRoles(words) {
|
|
2683
|
+
const packages = [];
|
|
2684
|
+
let index = skipAssignments(words, 0);
|
|
2685
|
+
while (index < words.length) {
|
|
2686
|
+
const installer = matchingPrefix(INSTALLERS, words, index);
|
|
2687
|
+
if (installer !== void 0) {
|
|
2688
|
+
packages.push(...installArguments(words, index + installer.words.length));
|
|
2689
|
+
return { program: void 0, packages };
|
|
2690
|
+
}
|
|
2691
|
+
const launcher = matchingPrefix(LAUNCHERS, words, index);
|
|
2692
|
+
if (launcher === void 0) {
|
|
2693
|
+
return { program: index, packages };
|
|
2694
|
+
}
|
|
2695
|
+
const start = index + launcher.words.length;
|
|
2696
|
+
const afterOptions = launchedProgram(words, start, launcher, packages);
|
|
2697
|
+
index = skipAssignments(words, afterOptions + launcher.operands);
|
|
2698
|
+
}
|
|
2699
|
+
return { program: void 0, packages };
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2702
|
+
function packageReference(value) {
|
|
2703
|
+
const bare = value.startsWith(NPM_SPECIFIER_PREFIX) ? value.slice(NPM_SPECIFIER_PREFIX.length) : value;
|
|
2704
|
+
const at = bare.indexOf("@", 1);
|
|
2705
|
+
return { name: at === -1 ? bare : bare.slice(0, at), isPinned: at !== -1 };
|
|
2706
|
+
}
|
|
2707
|
+
function namesOldPackage(value) {
|
|
2708
|
+
return PACKAGE_RENAMES.has(packageReference(value).name) || oldPackageInNodeModules(value) !== void 0 || value.endsWith(`/${GENERATOR_COMMAND}`);
|
|
2709
|
+
}
|
|
2710
|
+
const unreadArgumentValues = (words) => new Map(
|
|
2711
|
+
argumentAssignments(words).filter((assignment) => !holdsCommandLine(assignment)).map(({ word, value }) => [word, value])
|
|
2712
|
+
);
|
|
2713
|
+
function unmigratedWordFindings(words, handledOffsets, locate) {
|
|
2714
|
+
const values = unreadArgumentValues(words);
|
|
2715
|
+
const namesOld = (word) => namesOldPackage(word.value) || namesOldPackage(values.get(word) ?? "");
|
|
2716
|
+
return words.filter((word) => !handledOffsets.has(word.start) && namesOld(word)).map((word) => ({
|
|
2717
|
+
offset: word.start,
|
|
2718
|
+
manualStep: { kind: "old-name-in-command", location: locate(word.start), word: word.value }
|
|
2719
|
+
}));
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2722
|
+
const RECIPE_PREFIX_RE$1 = /^[@+-]+(?=.)/;
|
|
2723
|
+
function withoutRecipePrefix(words) {
|
|
2724
|
+
const [first, ...rest] = words;
|
|
2725
|
+
if (first === void 0 || !RECIPE_PREFIX_RE$1.test(first.value)) {
|
|
2726
|
+
return words;
|
|
2727
|
+
}
|
|
2728
|
+
return [{ ...first, value: first.value.replace(RECIPE_PREFIX_RE$1, "") }, ...rest];
|
|
2729
|
+
}
|
|
2730
|
+
const NO_VARIABLES = {
|
|
2731
|
+
programAt: () => void 0,
|
|
2732
|
+
referenceAt: () => void 0
|
|
2733
|
+
};
|
|
2734
|
+
function runsGenerator(command) {
|
|
2735
|
+
const words = withoutRecipePrefix(command);
|
|
2736
|
+
const { program } = commandRoles(words);
|
|
2737
|
+
const word = program === void 0 ? void 0 : words[program];
|
|
2738
|
+
return word !== void 0 && packageReference(withoutWindowsSuffix(word.value)).name === GENERATOR_COMMAND;
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
const COMMAND_PREFIX_WORDS = /* @__PURE__ */ new Set([
|
|
2742
|
+
"if",
|
|
2743
|
+
"then",
|
|
2744
|
+
"elif",
|
|
2745
|
+
"else",
|
|
2746
|
+
"fi",
|
|
2747
|
+
"while",
|
|
2748
|
+
"until",
|
|
2749
|
+
"do",
|
|
2750
|
+
"done",
|
|
2751
|
+
"!",
|
|
2752
|
+
"{",
|
|
2753
|
+
"}",
|
|
2754
|
+
"esac"
|
|
2755
|
+
]);
|
|
2756
|
+
const CLAUSE_WORDS = /* @__PURE__ */ new Set(["for", "select", "case", "[["]);
|
|
2757
|
+
const FUNCTION_WORD = "function";
|
|
2758
|
+
const FUNCTION_HEADER_LENGTH = 2;
|
|
2759
|
+
const isReserved = (word, words) => word !== void 0 && word.raw === word.value && words.has(word.value);
|
|
2760
|
+
function prefixLength(words, index) {
|
|
2761
|
+
if (isReserved(words[index], COMMAND_PREFIX_WORDS)) {
|
|
2762
|
+
return 1;
|
|
2763
|
+
}
|
|
2764
|
+
const word = words[index];
|
|
2765
|
+
return word?.raw === FUNCTION_WORD ? FUNCTION_HEADER_LENGTH : 0;
|
|
2766
|
+
}
|
|
2767
|
+
function simpleCommand(words) {
|
|
2768
|
+
let first = 0;
|
|
2769
|
+
for (let length = prefixLength(words, 0); length > 0; length = prefixLength(words, first)) {
|
|
2770
|
+
first += length;
|
|
2771
|
+
}
|
|
2772
|
+
return isReserved(words[first], CLAUSE_WORDS) ? [] : words.slice(first);
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2775
|
+
const HEREDOC_OPERATOR = "<<";
|
|
2776
|
+
const HERE_STRING_OPERATOR = "<<<";
|
|
2777
|
+
const STRIP_TABS = "-";
|
|
2778
|
+
const LINE_BREAK$6 = "\n";
|
|
2779
|
+
const LEADING_TABS_RE = /^\t+/;
|
|
2780
|
+
const CARRIAGE_RETURN_RE = /\r$/;
|
|
2781
|
+
function heredocAt(text, index, where) {
|
|
2782
|
+
if (text.startsWith(HERE_STRING_OPERATOR, index)) {
|
|
2783
|
+
return { end: index + HERE_STRING_OPERATOR.length };
|
|
2784
|
+
}
|
|
2785
|
+
if (!text.startsWith(HEREDOC_OPERATOR, index)) {
|
|
2786
|
+
return void 0;
|
|
2787
|
+
}
|
|
2788
|
+
let start = index + HEREDOC_OPERATOR.length;
|
|
2789
|
+
const isTabStripped = text[start] === STRIP_TABS;
|
|
2790
|
+
start += isTabStripped ? 1 : 0;
|
|
2791
|
+
while (text[start] === " " || text[start] === " ") {
|
|
2792
|
+
start++;
|
|
2793
|
+
}
|
|
2794
|
+
const word = readWord(text, start);
|
|
2795
|
+
const pending = { delimiter: word.value, isTabStripped, ...where };
|
|
2796
|
+
return word.value === "" ? void 0 : { pending, end: word.end };
|
|
2797
|
+
}
|
|
2798
|
+
function isDelimiterLine(text, lineStart, end, heredoc) {
|
|
2799
|
+
let first = lineStart;
|
|
2800
|
+
while (first < lineStart + heredoc.indent && text[first] === " ") {
|
|
2801
|
+
first++;
|
|
2802
|
+
}
|
|
2803
|
+
const line = text.slice(first, end).replace(CARRIAGE_RETURN_RE, "");
|
|
2804
|
+
const compared = heredoc.isTabStripped ? line.replace(LEADING_TABS_RE, "") : line;
|
|
2805
|
+
return compared === heredoc.delimiter;
|
|
2806
|
+
}
|
|
2807
|
+
function readBody(text, start, heredoc) {
|
|
2808
|
+
let lineStart = start;
|
|
2809
|
+
while (lineStart < text.length) {
|
|
2810
|
+
const lineEnd = text.indexOf(LINE_BREAK$6, lineStart);
|
|
2811
|
+
const end = lineEnd === -1 ? text.length : lineEnd;
|
|
2812
|
+
if (isDelimiterLine(text, lineStart, end, heredoc)) {
|
|
2813
|
+
const body = { command: heredoc.command, start, text: text.slice(start, lineStart) };
|
|
2814
|
+
return { body, end: Math.min(end + 1, text.length) };
|
|
2815
|
+
}
|
|
2816
|
+
lineStart = end + 1;
|
|
2817
|
+
}
|
|
2818
|
+
return { body: { command: heredoc.command, start, text: text.slice(start) }, end: text.length };
|
|
2819
|
+
}
|
|
2820
|
+
function readBodies(text, start, pending) {
|
|
2821
|
+
const bodies = [];
|
|
2822
|
+
let end = start;
|
|
2823
|
+
for (const heredoc of pending) {
|
|
2824
|
+
const read = readBody(text, end, heredoc);
|
|
2825
|
+
bodies.push(read.body);
|
|
2826
|
+
end = read.end;
|
|
2827
|
+
}
|
|
2828
|
+
return { bodies, end };
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
const CODE_OPTIONS = /* @__PURE__ */ new Map([
|
|
2832
|
+
["python", /* @__PURE__ */ new Set(["-c"])],
|
|
2833
|
+
["node", /* @__PURE__ */ new Set(["-e", "--eval", "-p", "--print"])],
|
|
2834
|
+
["bun", /* @__PURE__ */ new Set(["-e", "--eval", "-p", "--print"])],
|
|
2503
2835
|
["ruby", /* @__PURE__ */ new Set(["-e"])],
|
|
2504
2836
|
["perl", /* @__PURE__ */ new Set(["-e", "-E"])]
|
|
2505
2837
|
]);
|
|
@@ -2591,7 +2923,7 @@ function wholeWordExpansion(raw) {
|
|
|
2591
2923
|
}
|
|
2592
2924
|
|
|
2593
2925
|
const COMMENT = "#";
|
|
2594
|
-
const LINE_BREAK$
|
|
2926
|
+
const LINE_BREAK$5 = "\n";
|
|
2595
2927
|
function skipTrivia(text, index) {
|
|
2596
2928
|
const char = text[index];
|
|
2597
2929
|
if (WORD_BREAKS.has(char)) {
|
|
@@ -2621,7 +2953,7 @@ function topLevelCommands(text, indent) {
|
|
|
2621
2953
|
index = heredoc.end;
|
|
2622
2954
|
} else if (afterTrivia !== index) {
|
|
2623
2955
|
index = afterTrivia;
|
|
2624
|
-
} else if (text[index] === LINE_BREAK$
|
|
2956
|
+
} else if (text[index] === LINE_BREAK$5 && pending.length > 0) {
|
|
2625
2957
|
const read = readBodies(text, index + 1, pending);
|
|
2626
2958
|
heredocs.push(...read.bodies);
|
|
2627
2959
|
pending = [];
|
|
@@ -2641,39 +2973,6 @@ function topLevelCommands(text, indent) {
|
|
|
2641
2973
|
}
|
|
2642
2974
|
return { commands, heredocs, pipes };
|
|
2643
2975
|
}
|
|
2644
|
-
const COMMAND_PREFIX_WORDS = /* @__PURE__ */ new Set([
|
|
2645
|
-
"if",
|
|
2646
|
-
"then",
|
|
2647
|
-
"elif",
|
|
2648
|
-
"else",
|
|
2649
|
-
"fi",
|
|
2650
|
-
"while",
|
|
2651
|
-
"until",
|
|
2652
|
-
"do",
|
|
2653
|
-
"done",
|
|
2654
|
-
"!",
|
|
2655
|
-
"{",
|
|
2656
|
-
"}",
|
|
2657
|
-
"esac"
|
|
2658
|
-
]);
|
|
2659
|
-
const CLAUSE_WORDS = /* @__PURE__ */ new Set(["for", "select", "case", "[["]);
|
|
2660
|
-
const FUNCTION_WORD = "function";
|
|
2661
|
-
const FUNCTION_HEADER_LENGTH = 2;
|
|
2662
|
-
const isReserved = (word, words) => word !== void 0 && word.raw === word.value && words.has(word.value);
|
|
2663
|
-
function prefixLength(words, index) {
|
|
2664
|
-
if (isReserved(words[index], COMMAND_PREFIX_WORDS)) {
|
|
2665
|
-
return 1;
|
|
2666
|
-
}
|
|
2667
|
-
const word = words[index];
|
|
2668
|
-
return word?.raw === FUNCTION_WORD ? FUNCTION_HEADER_LENGTH : 0;
|
|
2669
|
-
}
|
|
2670
|
-
function simpleCommand(words) {
|
|
2671
|
-
let first = 0;
|
|
2672
|
-
for (let length = prefixLength(words, 0); length > 0; length = prefixLength(words, first)) {
|
|
2673
|
-
first += length;
|
|
2674
|
-
}
|
|
2675
|
-
return isReserved(words[first], CLAUSE_WORDS) ? [] : words.slice(first);
|
|
2676
|
-
}
|
|
2677
2976
|
const QUOTES$2 = /* @__PURE__ */ new Set(["'", '"']);
|
|
2678
2977
|
const NESTED_COMMAND_RE = /[\s;&|()`]/;
|
|
2679
2978
|
function nestedCommandText(word) {
|
|
@@ -2687,17 +2986,17 @@ const PASS_THROUGH = "cat";
|
|
|
2687
2986
|
const PATH_SEPARATOR$9 = "/";
|
|
2688
2987
|
const OPTION_PREFIX$1 = "-";
|
|
2689
2988
|
const programName$1 = (command) => command[0]?.value.split(PATH_SEPARATOR$9).at(-1) ?? "";
|
|
2690
|
-
const isOption
|
|
2691
|
-
const isScriptShell = (command) => SHELLS$1.has(programName$1(command)) && command.slice(1).every(isOption
|
|
2989
|
+
const isOption = (word) => word.value.startsWith(OPTION_PREFIX$1);
|
|
2990
|
+
const isScriptShell = (command) => SHELLS$1.has(programName$1(command)) && command.slice(1).every(isOption);
|
|
2692
2991
|
function readsScript(command) {
|
|
2693
2992
|
if (programName$1(command) !== DOCKER_RUN) {
|
|
2694
2993
|
return isScriptShell(command);
|
|
2695
2994
|
}
|
|
2696
2995
|
const after = command.slice(1);
|
|
2697
|
-
const shell = after.slice(after.findIndex((word) => !isOption
|
|
2698
|
-
return after.every(isOption
|
|
2996
|
+
const shell = after.slice(after.findIndex((word) => !isOption(word)));
|
|
2997
|
+
return after.every(isOption) || isScriptShell(shell);
|
|
2699
2998
|
}
|
|
2700
|
-
const passesThrough = (command) => programName$1(command) === PASS_THROUGH && command.slice(1).every(isOption
|
|
2999
|
+
const passesThrough = (command) => programName$1(command) === PASS_THROUGH && command.slice(1).every(isOption);
|
|
2701
3000
|
function scriptsRunBy(top, index, command) {
|
|
2702
3001
|
const previous = index - 1;
|
|
2703
3002
|
const isPipedScript = top.pipes.has(previous) && isScriptShell(command) && passesThrough(simpleCommand(top.commands[previous] ?? []));
|
|
@@ -2712,288 +3011,148 @@ function shellCommandsAt(text, offset, indent = 0) {
|
|
|
2712
3011
|
function expansionCommands(word) {
|
|
2713
3012
|
const expansions = wordExpansions(word.raw);
|
|
2714
3013
|
const literals = expressionLiterals(word.raw).filter(
|
|
2715
|
-
({ start }) => expansions.every((expansion) => start < expansion.start || start >= expansion.expansionEnd)
|
|
2716
|
-
);
|
|
2717
|
-
return [...expansions, ...literals].flatMap(
|
|
2718
|
-
(part) => shellCommandsAt(part.text, word.start + part.start)
|
|
2719
|
-
);
|
|
2720
|
-
}
|
|
2721
|
-
function
|
|
2722
|
-
const
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
}
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
}
|
|
2759
|
-
function canRunGenerator(definition, generators) {
|
|
2760
|
-
switch (definition.kind) {
|
|
2761
|
-
case "command":
|
|
2762
|
-
return definition.runsGenerator;
|
|
2763
|
-
case "reference":
|
|
2764
|
-
return generators.has(definition.target);
|
|
2765
|
-
case "no-program":
|
|
2766
|
-
return false;
|
|
2767
|
-
case "run-time":
|
|
2768
|
-
return true;
|
|
2769
|
-
default:
|
|
2770
|
-
return assertNever(definition);
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
function canRunOther(definition, others, defined) {
|
|
2774
|
-
switch (definition.kind) {
|
|
2775
|
-
case "command":
|
|
2776
|
-
return !definition.runsGenerator;
|
|
2777
|
-
case "reference":
|
|
2778
|
-
return others.has(definition.target) || !defined.has(definition.target);
|
|
2779
|
-
case "no-program":
|
|
2780
|
-
return false;
|
|
2781
|
-
case "run-time":
|
|
2782
|
-
return true;
|
|
2783
|
-
default:
|
|
2784
|
-
return assertNever(definition);
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
function variablePrograms(definitions) {
|
|
2788
|
-
const defined = new Set(definitions.map((definition) => definition.name));
|
|
2789
|
-
const generators = /* @__PURE__ */ new Set();
|
|
2790
|
-
const others = /* @__PURE__ */ new Set();
|
|
2791
|
-
for (let size = -1; size !== generators.size + others.size; ) {
|
|
2792
|
-
size = generators.size + others.size;
|
|
2793
|
-
for (const definition of definitions) {
|
|
2794
|
-
if (canRunGenerator(definition, generators)) {
|
|
2795
|
-
generators.add(definition.name);
|
|
2796
|
-
}
|
|
2797
|
-
if (canRunOther(definition, others, defined)) {
|
|
2798
|
-
others.add(definition.name);
|
|
2799
|
-
}
|
|
2800
|
-
}
|
|
2801
|
-
}
|
|
2802
|
-
const programOf = (name) => {
|
|
2803
|
-
if (!generators.has(name)) {
|
|
2804
|
-
return "other";
|
|
2805
|
-
}
|
|
2806
|
-
return others.has(name) ? "generator-or-other" : "generator";
|
|
2807
|
-
};
|
|
2808
|
-
return new Map([...defined].map((name) => [name, programOf(name)]));
|
|
2809
|
-
}
|
|
2810
|
-
|
|
2811
|
-
function placedAssignments$1(commands) {
|
|
2812
|
-
const all = commands.flatMap(shellAssignments).sort((left, right) => {
|
|
2813
|
-
return left.word.start - right.word.start;
|
|
2814
|
-
});
|
|
2815
|
-
return all.map((assignment, index) => {
|
|
2816
|
-
if (!assignment.isAppend) {
|
|
2817
|
-
return { assignment, place: void 0 };
|
|
2818
|
-
}
|
|
2819
|
-
const earlier = all.slice(0, index).filter((found) => found.name === assignment.name);
|
|
2820
|
-
return { assignment, place: appendedPlace(earlier.map((found) => found.value)) };
|
|
2821
|
-
});
|
|
2822
|
-
}
|
|
2823
|
-
const isAfterValue = ({ place }) => place === "after-value" || place === "after-outside";
|
|
2824
|
-
function shellAppend(assignment, variables) {
|
|
2825
|
-
const at = assignment.word.start;
|
|
2826
|
-
const written = `$${assignment.name}`;
|
|
2827
|
-
const found = variables.programAt({ raw: written, value: written, start: at, end: at });
|
|
2828
|
-
const program = found ?? { written, program: "generator-or-other" };
|
|
2829
|
-
const text = assignmentValueText(assignment);
|
|
2830
|
-
if (text !== void 0) {
|
|
2831
|
-
const [command] = shellCommandsAt(text.text, text.start);
|
|
2832
|
-
return { value: { words: command ?? [], program }, command };
|
|
2833
|
-
}
|
|
2834
|
-
const words = shellCommands(assignment.value).flat().map((word) => ({ ...word, start: at, end: at }));
|
|
2835
|
-
const isCertain = program.program === "other";
|
|
2836
|
-
const uncertain = { ...program, program: "generator-or-other" };
|
|
2837
|
-
return { value: { words, program: isCertain ? program : uncertain }, command: void 0 };
|
|
2838
|
-
}
|
|
2839
|
-
function shellAppends(commands, variables) {
|
|
2840
|
-
const appends = placedAssignments$1(commands).filter(isAfterValue).map(({ assignment }) => shellAppend(assignment, variables));
|
|
2841
|
-
const taken = new Set(appends.flatMap(({ command }) => command === void 0 ? [] : [command]));
|
|
2842
|
-
const isTaken = (command) => [...taken].some(
|
|
2843
|
-
(found) => found.length === command.length && found[0]?.start === command[0]?.start
|
|
2844
|
-
);
|
|
2845
|
-
return {
|
|
2846
|
-
commands: commands.filter((command) => !isTaken(command)),
|
|
2847
|
-
appended: appends.map(({ value }) => value)
|
|
2848
|
-
};
|
|
2849
|
-
}
|
|
2850
|
-
|
|
2851
|
-
const NONE = /* @__PURE__ */ new Set();
|
|
2852
|
-
const PACKAGE_OPTIONS = /* @__PURE__ */ new Set(["-p", "--package"]);
|
|
2853
|
-
const PACKAGE_MANAGER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2854
|
-
"--filter",
|
|
2855
|
-
"-F",
|
|
2856
|
-
"--dir",
|
|
2857
|
-
"-C",
|
|
2858
|
-
"--prefix",
|
|
2859
|
-
"--cwd",
|
|
2860
|
-
"--workspace"
|
|
2861
|
-
]);
|
|
2862
|
-
const launcher = (words, packageOptions = NONE, valueOptions = NONE) => {
|
|
2863
|
-
const allValueOptions = /* @__PURE__ */ new Set([...valueOptions, ...packageOptions]);
|
|
2864
|
-
return { words, packageOptions, valueOptions: allValueOptions, operands: 0 };
|
|
2865
|
-
};
|
|
2866
|
-
const CONTAINER_OPTIONS = /* @__PURE__ */ new Set([
|
|
2867
|
-
"-e",
|
|
2868
|
-
"--env",
|
|
2869
|
-
"--env-file",
|
|
2870
|
-
"-v",
|
|
2871
|
-
"--volume",
|
|
2872
|
-
"--mount",
|
|
2873
|
-
"-p",
|
|
2874
|
-
"--publish",
|
|
2875
|
-
"-w",
|
|
2876
|
-
"--workdir",
|
|
2877
|
-
"-u",
|
|
2878
|
-
"--user",
|
|
2879
|
-
"--name",
|
|
2880
|
-
"--network",
|
|
2881
|
-
"--entrypoint",
|
|
2882
|
-
"--platform",
|
|
2883
|
-
"-l",
|
|
2884
|
-
"--label",
|
|
2885
|
-
"-h",
|
|
2886
|
-
"--hostname",
|
|
2887
|
-
"--add-host"
|
|
2888
|
-
]);
|
|
2889
|
-
const container = (words) => ({
|
|
2890
|
-
...launcher(words, NONE, CONTAINER_OPTIONS),
|
|
2891
|
-
operands: 1
|
|
2892
|
-
});
|
|
2893
|
-
const withOperands = (words, operands, valueOptions = NONE) => ({ ...launcher(words, NONE, valueOptions), operands });
|
|
2894
|
-
const XARGS_OPTIONS = /* @__PURE__ */ new Set([
|
|
2895
|
-
"-I",
|
|
2896
|
-
"-J",
|
|
2897
|
-
"-L",
|
|
2898
|
-
"-n",
|
|
2899
|
-
"-P",
|
|
2900
|
-
"-R",
|
|
2901
|
-
"-S",
|
|
2902
|
-
"-s",
|
|
2903
|
-
"-d",
|
|
2904
|
-
"-E",
|
|
2905
|
-
"-a",
|
|
2906
|
-
"--max-args",
|
|
2907
|
-
"--max-procs",
|
|
2908
|
-
"--max-lines",
|
|
2909
|
-
"--delimiter",
|
|
2910
|
-
"--arg-file"
|
|
2911
|
-
]);
|
|
2912
|
-
const NODE_OPTIONS = /* @__PURE__ */ new Set([
|
|
2913
|
-
"-r",
|
|
2914
|
-
"--require",
|
|
2915
|
-
"--import",
|
|
2916
|
-
"--loader",
|
|
2917
|
-
"--env-file"
|
|
2918
|
-
]);
|
|
2919
|
-
const LAUNCHERS = [
|
|
2920
|
-
launcher(["npm", "exec"], PACKAGE_OPTIONS),
|
|
2921
|
-
launcher(["npm", "x"], PACKAGE_OPTIONS),
|
|
2922
|
-
launcher(["pnpm", "exec"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2923
|
-
launcher(["pnpm", "dlx"], /* @__PURE__ */ new Set(["--package"])),
|
|
2924
|
-
launcher(["yarn", "dlx"], PACKAGE_OPTIONS),
|
|
2925
|
-
launcher(["yarn", "exec"]),
|
|
2926
|
-
launcher(["bun", "x"], PACKAGE_OPTIONS),
|
|
2927
|
-
withOperands(["yarn", "workspace"], 1),
|
|
2928
|
-
launcher(["dotenvx", "run"], NONE, /* @__PURE__ */ new Set(["-f", "--env-file", "-e", "--env", "--convention"])),
|
|
2929
|
-
launcher(
|
|
2930
|
-
["doppler", "run"],
|
|
2931
|
-
NONE,
|
|
2932
|
-
/* @__PURE__ */ new Set(["-p", "--project", "-c", "--config", "--token", "--mount", "--scope"])
|
|
2933
|
-
),
|
|
2934
|
-
launcher(["nx", "exec"], NONE, /* @__PURE__ */ new Set(["--projects", "-p", "--exclude"])),
|
|
2935
|
-
launcher(["deno", "run"], NONE, /* @__PURE__ */ new Set(["--config", "-c", "--import-map", "--location"])),
|
|
2936
|
-
launcher(["deno", "x"]),
|
|
2937
|
-
launcher(["npx"], PACKAGE_OPTIONS, /* @__PURE__ */ new Set(["-c", "--call"])),
|
|
2938
|
-
launcher(["pnpx"], PACKAGE_OPTIONS),
|
|
2939
|
-
launcher(["bunx"], PACKAGE_OPTIONS),
|
|
2940
|
-
// Like a bare `pnpm <name>`, a bare `bun <name>` runs the binary when no script has the name.
|
|
2941
|
-
launcher(["bun"], NONE, /* @__PURE__ */ new Set(["--cwd", "--filter", "-F"])),
|
|
2942
|
-
launcher(["corepack"]),
|
|
2943
|
-
launcher(["pnpm"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2944
|
-
launcher(["yarn"], NONE, PACKAGE_MANAGER_OPTIONS),
|
|
2945
|
-
launcher(["node"], NONE, NODE_OPTIONS),
|
|
2946
|
-
launcher(["tsx"], NONE, NODE_OPTIONS),
|
|
2947
|
-
launcher(["ts-node"], NONE, /* @__PURE__ */ new Set([...NODE_OPTIONS, "-P", "--project", "-O", "--compiler"])),
|
|
2948
|
-
launcher(["cross-env"]),
|
|
2949
|
-
launcher(["dotenv"], NONE, /* @__PURE__ */ new Set(["-e", "-c", "-v"])),
|
|
2950
|
-
launcher(["env"], NONE, /* @__PURE__ */ new Set(["-u", "--unset", "-C", "--chdir"])),
|
|
2951
|
-
launcher(["exec"], NONE, /* @__PURE__ */ new Set(["-a"])),
|
|
2952
|
-
launcher(["command"]),
|
|
2953
|
-
launcher(["time"]),
|
|
2954
|
-
launcher(["nice"], NONE, /* @__PURE__ */ new Set(["-n", "--adjustment"])),
|
|
2955
|
-
withOperands(["timeout"], 1, /* @__PURE__ */ new Set(["-s", "--signal", "-k", "--kill-after"])),
|
|
2956
|
-
launcher(["xargs"], NONE, XARGS_OPTIONS),
|
|
2957
|
-
launcher(["nohup"]),
|
|
2958
|
-
launcher(["sudo"], NONE, /* @__PURE__ */ new Set(["-u", "-g"])),
|
|
2959
|
-
// The shell form of Dockerfile instructions runs the rest of the line in a shell.
|
|
2960
|
-
launcher(["RUN"], NONE, /* @__PURE__ */ new Set(["--mount", "--network", "--security"])),
|
|
2961
|
-
launcher(["CMD"]),
|
|
2962
|
-
launcher(["ENTRYPOINT"]),
|
|
2963
|
-
container(["docker", "run"]),
|
|
2964
|
-
container(["docker", "exec"]),
|
|
2965
|
-
container(["docker", "compose", "run"]),
|
|
2966
|
-
container(["docker", "compose", "exec"]),
|
|
2967
|
-
container(["podman", "run"]),
|
|
2968
|
-
container(["podman", "exec"])
|
|
2969
|
-
];
|
|
2970
|
-
const installers = (manager, subcommands) => subcommands.map((subcommand) => ({ words: [manager, subcommand] }));
|
|
2971
|
-
const NPM_INSTALL = ["install", "i", "add", "update", "up", "uninstall", "remove", "rm", "un"];
|
|
2972
|
-
const INSTALLERS = [
|
|
2973
|
-
...installers("npm", NPM_INSTALL),
|
|
2974
|
-
...installers("pnpm", ["add", "update", "up", "remove", "rm", "uninstall", "un"]),
|
|
2975
|
-
...installers("yarn", ["add", "upgrade", "up", "remove"]),
|
|
2976
|
-
// Yarn 1 installs global packages with `yarn global add`.
|
|
2977
|
-
{ words: ["yarn", "global", "add"] },
|
|
2978
|
-
{ words: ["yarn", "global", "remove"] },
|
|
2979
|
-
...installers("bun", ["add", "a", "update", "remove", "rm", "install", "i"]),
|
|
2980
|
-
...installers("deno", ["add", "install", "i", "remove", "uninstall"])
|
|
2981
|
-
];
|
|
2982
|
-
const NPM_SPECIFIER_PREFIX = "npm:";
|
|
3014
|
+
({ start }) => expansions.every((expansion) => start < expansion.start || start >= expansion.expansionEnd)
|
|
3015
|
+
);
|
|
3016
|
+
return [...expansions, ...literals].flatMap(
|
|
3017
|
+
(part) => shellCommandsAt(part.text, word.start + part.start)
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
function commandLineAssignments(command) {
|
|
3021
|
+
const read = [
|
|
3022
|
+
...shellAssignments(command),
|
|
3023
|
+
...argumentAssignments(command).filter(holdsCommandLine)
|
|
3024
|
+
];
|
|
3025
|
+
return new Map(read.map((assignment) => [assignment.word, assignment]));
|
|
3026
|
+
}
|
|
3027
|
+
function valueCommands$1(assignment) {
|
|
3028
|
+
const value = assignmentValue(assignment);
|
|
3029
|
+
return shellCommands(value.text).map((words) => words.map(value.place));
|
|
3030
|
+
}
|
|
3031
|
+
function innerCommands(command) {
|
|
3032
|
+
const assignments = commandLineAssignments(command);
|
|
3033
|
+
const code = inlineCode(command)?.code;
|
|
3034
|
+
return command.flatMap((word) => {
|
|
3035
|
+
const inner = word === code ? void 0 : nestedCommandText(word);
|
|
3036
|
+
if (inner !== void 0) {
|
|
3037
|
+
return shellCommandsAt(inner, word.start + 1);
|
|
3038
|
+
}
|
|
3039
|
+
const assignment = assignments.get(word);
|
|
3040
|
+
return assignment === void 0 ? expansionCommands(word) : valueCommands$1(assignment);
|
|
3041
|
+
});
|
|
3042
|
+
}
|
|
3043
|
+
function shellCommands(text, indent = 0) {
|
|
3044
|
+
const top = topLevelCommands(text, indent);
|
|
3045
|
+
const commands = [];
|
|
3046
|
+
for (const [index, words] of top.commands.entries()) {
|
|
3047
|
+
const command = simpleCommand(words);
|
|
3048
|
+
if (command.length > 0) {
|
|
3049
|
+
commands.push(command);
|
|
3050
|
+
}
|
|
3051
|
+
commands.push(...innerCommands(command));
|
|
3052
|
+
const scripts = scriptsRunBy(top, index, command);
|
|
3053
|
+
commands.push(...scripts.flatMap((body) => shellCommandsAt(body.text, body.start, indent)));
|
|
3054
|
+
}
|
|
3055
|
+
return commands;
|
|
3056
|
+
}
|
|
2983
3057
|
|
|
2984
|
-
function
|
|
2985
|
-
|
|
2986
|
-
const at = bare.indexOf("@", 1);
|
|
2987
|
-
return { name: at === -1 ? bare : bare.slice(0, at), isPinned: at !== -1 };
|
|
3058
|
+
function assertNever(value) {
|
|
3059
|
+
throw new Error(`Unexpected variant: ${JSON.stringify(value)}`);
|
|
2988
3060
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
3061
|
+
|
|
3062
|
+
function appendedPlace(earlierValues) {
|
|
3063
|
+
if (earlierValues.length === 0) {
|
|
3064
|
+
return "after-outside";
|
|
3065
|
+
}
|
|
3066
|
+
return earlierValues.every((value) => value.trim() === "") ? "start" : "after-value";
|
|
2991
3067
|
}
|
|
2992
|
-
function
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
3068
|
+
function canRunGenerator(definition, generators) {
|
|
3069
|
+
switch (definition.kind) {
|
|
3070
|
+
case "command":
|
|
3071
|
+
return definition.runsGenerator;
|
|
3072
|
+
case "reference":
|
|
3073
|
+
return generators.has(definition.target);
|
|
3074
|
+
case "no-program":
|
|
3075
|
+
return false;
|
|
3076
|
+
case "run-time":
|
|
3077
|
+
return true;
|
|
3078
|
+
default:
|
|
3079
|
+
return assertNever(definition);
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
function canRunOther(definition, others, defined) {
|
|
3083
|
+
switch (definition.kind) {
|
|
3084
|
+
case "command":
|
|
3085
|
+
return !definition.runsGenerator;
|
|
3086
|
+
case "reference":
|
|
3087
|
+
return others.has(definition.target) || !defined.has(definition.target);
|
|
3088
|
+
case "no-program":
|
|
3089
|
+
return false;
|
|
3090
|
+
case "run-time":
|
|
3091
|
+
return true;
|
|
3092
|
+
default:
|
|
3093
|
+
return assertNever(definition);
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
function variablePrograms(definitions) {
|
|
3097
|
+
const defined = new Set(definitions.map((definition) => definition.name));
|
|
3098
|
+
const generators = /* @__PURE__ */ new Set();
|
|
3099
|
+
const others = /* @__PURE__ */ new Set();
|
|
3100
|
+
for (let size = -1; size !== generators.size + others.size; ) {
|
|
3101
|
+
size = generators.size + others.size;
|
|
3102
|
+
for (const definition of definitions) {
|
|
3103
|
+
if (canRunGenerator(definition, generators)) {
|
|
3104
|
+
generators.add(definition.name);
|
|
3105
|
+
}
|
|
3106
|
+
if (canRunOther(definition, others, defined)) {
|
|
3107
|
+
others.add(definition.name);
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
const programOf = (name) => {
|
|
3112
|
+
if (!generators.has(name)) {
|
|
3113
|
+
return "other";
|
|
3114
|
+
}
|
|
3115
|
+
return others.has(name) ? "generator-or-other" : "generator";
|
|
3116
|
+
};
|
|
3117
|
+
return new Map([...defined].map((name) => [name, programOf(name)]));
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3120
|
+
function placedAssignments$1(commands) {
|
|
3121
|
+
const all = commands.flatMap(shellAssignments).sort((left, right) => {
|
|
3122
|
+
return left.word.start - right.word.start;
|
|
3123
|
+
});
|
|
3124
|
+
return all.map((assignment, index) => {
|
|
3125
|
+
if (!assignment.isAppend) {
|
|
3126
|
+
return { assignment, place: void 0 };
|
|
3127
|
+
}
|
|
3128
|
+
const earlier = all.slice(0, index).filter((found) => found.name === assignment.name);
|
|
3129
|
+
return { assignment, place: appendedPlace(earlier.map((found) => found.value)) };
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
const isAfterValue = ({ place }) => place === "after-value" || place === "after-outside";
|
|
3133
|
+
function shellAppend(assignment, variables) {
|
|
3134
|
+
const at = assignment.word.start;
|
|
3135
|
+
const written = `$${assignment.name}`;
|
|
3136
|
+
const found = variables.programAt({ raw: written, value: written, start: at, end: at });
|
|
3137
|
+
const program = found ?? { written, program: "generator-or-other" };
|
|
3138
|
+
const [command] = appendedText(assignment);
|
|
3139
|
+
return { value: { words: command ?? [], program }, command };
|
|
3140
|
+
}
|
|
3141
|
+
const isOwnGeneratorCommand = (place, command) => place === "after-outside" && command !== void 0 && runsGenerator(command);
|
|
3142
|
+
function appendedText(assignment) {
|
|
3143
|
+
const value = assignmentValue(assignment);
|
|
3144
|
+
return shellCommands(value.text).map((words) => words.map(value.place));
|
|
3145
|
+
}
|
|
3146
|
+
function shellAppends(commands, variables) {
|
|
3147
|
+
const appends = placedAssignments$1(commands).filter(isAfterValue).filter(({ assignment, place }) => !isOwnGeneratorCommand(place, appendedText(assignment)[0])).map(({ assignment }) => shellAppend(assignment, variables));
|
|
3148
|
+
const taken = new Set(appends.flatMap(({ command }) => command === void 0 ? [] : [command]));
|
|
3149
|
+
const isTaken = (command) => [...taken].some(
|
|
3150
|
+
(found) => found.length === command.length && found[0]?.start === command[0]?.start
|
|
3151
|
+
);
|
|
3152
|
+
return {
|
|
3153
|
+
commands: commands.filter((command) => !isTaken(command)),
|
|
3154
|
+
appended: appends.map(({ value }) => value)
|
|
3155
|
+
};
|
|
2997
3156
|
}
|
|
2998
3157
|
|
|
2999
3158
|
function flagFindings(word, locate) {
|
|
@@ -3012,7 +3171,7 @@ function renamedFlags(value) {
|
|
|
3012
3171
|
const flags = shellCommands(value).flat().map((word) => word.raw.split("=", 1)[0]);
|
|
3013
3172
|
return [...new Set(flags.filter((flag) => FLAG_RENAMES.has(flag)))];
|
|
3014
3173
|
}
|
|
3015
|
-
function argumentFindings(word, locate, variables) {
|
|
3174
|
+
function argumentFindings$1(word, locate, variables) {
|
|
3016
3175
|
const reference = variables.referenceAt(word);
|
|
3017
3176
|
if (reference === void 0) {
|
|
3018
3177
|
return flagFindings(word, locate);
|
|
@@ -3036,7 +3195,7 @@ const oldFlagsOf = (findings) => findings.flatMap(({ change, manualStep }) => {
|
|
|
3036
3195
|
return manualStep?.kind === "flags-in-variable" ? [...manualStep.flags] : [];
|
|
3037
3196
|
});
|
|
3038
3197
|
function programArgumentFindings(words, { offset, use }, locate, variables) {
|
|
3039
|
-
const found = words.flatMap((word) => argumentFindings(word, locate, variables));
|
|
3198
|
+
const found = words.flatMap((word) => argumentFindings$1(word, locate, variables));
|
|
3040
3199
|
if (use?.program !== "generator-or-other") {
|
|
3041
3200
|
return found;
|
|
3042
3201
|
}
|
|
@@ -3060,90 +3219,6 @@ function appendedValueFindings({ words, program }, locate, variables) {
|
|
|
3060
3219
|
return [...found, ...unmigratedWordFindings(words, handled, locate)];
|
|
3061
3220
|
}
|
|
3062
3221
|
|
|
3063
|
-
const END_OF_OPTIONS = "--";
|
|
3064
|
-
const isOption = (word) => word.value.startsWith("-") && word.value.length > 1;
|
|
3065
|
-
function skipAssignments(words, start) {
|
|
3066
|
-
let index = start;
|
|
3067
|
-
while (index < words.length && ASSIGNMENT_RE$2.test(words[index].raw)) {
|
|
3068
|
-
index++;
|
|
3069
|
-
}
|
|
3070
|
-
return index;
|
|
3071
|
-
}
|
|
3072
|
-
const WINDOWS_PROGRAM_SUFFIX_RE = /\.(?:cmd|exe|ps1)$/i;
|
|
3073
|
-
const windowsSuffix = (value) => WINDOWS_PROGRAM_SUFFIX_RE.exec(value)?.[0] ?? "";
|
|
3074
|
-
const withoutWindowsSuffix = (value) => value.slice(0, value.length - windowsSuffix(value).length);
|
|
3075
|
-
const entryWord = (word) => word === void 0 ? void 0 : withoutWindowsSuffix(word.value);
|
|
3076
|
-
function matchingPrefix(entries, words, index) {
|
|
3077
|
-
return entries.find(
|
|
3078
|
-
(entry) => entry.words.every((name, offset) => entryWord(words[index + offset]) === name)
|
|
3079
|
-
);
|
|
3080
|
-
}
|
|
3081
|
-
function inlineOptionPackage(word, launcher) {
|
|
3082
|
-
const equals = word.value.indexOf("=");
|
|
3083
|
-
const name = word.value.slice(0, equals);
|
|
3084
|
-
return launcher.packageOptions.has(name) ? { word, value: word.value.slice(equals + 1) } : void 0;
|
|
3085
|
-
}
|
|
3086
|
-
function launchedProgram(words, start, launcher, packages) {
|
|
3087
|
-
let index = start;
|
|
3088
|
-
while (index < words.length && isOption(words[index])) {
|
|
3089
|
-
const option = words[index++];
|
|
3090
|
-
if (option.value === END_OF_OPTIONS) {
|
|
3091
|
-
break;
|
|
3092
|
-
}
|
|
3093
|
-
const inline = option.value.includes("=") ? inlineOptionPackage(option, launcher) : void 0;
|
|
3094
|
-
if (inline !== void 0) {
|
|
3095
|
-
packages.push(inline);
|
|
3096
|
-
}
|
|
3097
|
-
const value = words[index];
|
|
3098
|
-
if (!option.value.includes("=") && launcher.valueOptions.has(option.value) && value) {
|
|
3099
|
-
if (launcher.packageOptions.has(option.value)) {
|
|
3100
|
-
packages.push({ word: value, value: value.value });
|
|
3101
|
-
}
|
|
3102
|
-
index++;
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
return index;
|
|
3106
|
-
}
|
|
3107
|
-
const installArguments = (words, start) => words.slice(start).filter((word) => !isOption(word)).map((word) => ({ word, value: word.value }));
|
|
3108
|
-
function commandRoles(words) {
|
|
3109
|
-
const packages = [];
|
|
3110
|
-
let index = skipAssignments(words, 0);
|
|
3111
|
-
while (index < words.length) {
|
|
3112
|
-
const installer = matchingPrefix(INSTALLERS, words, index);
|
|
3113
|
-
if (installer !== void 0) {
|
|
3114
|
-
packages.push(...installArguments(words, index + installer.words.length));
|
|
3115
|
-
return { program: void 0, packages };
|
|
3116
|
-
}
|
|
3117
|
-
const launcher = matchingPrefix(LAUNCHERS, words, index);
|
|
3118
|
-
if (launcher === void 0) {
|
|
3119
|
-
return { program: index, packages };
|
|
3120
|
-
}
|
|
3121
|
-
const start = index + launcher.words.length;
|
|
3122
|
-
const afterOptions = launchedProgram(words, start, launcher, packages);
|
|
3123
|
-
index = skipAssignments(words, afterOptions + launcher.operands);
|
|
3124
|
-
}
|
|
3125
|
-
return { program: void 0, packages };
|
|
3126
|
-
}
|
|
3127
|
-
|
|
3128
|
-
const RECIPE_PREFIX_RE$1 = /^[@+-]+(?=.)/;
|
|
3129
|
-
function withoutRecipePrefix(words) {
|
|
3130
|
-
const [first, ...rest] = words;
|
|
3131
|
-
if (first === void 0 || !RECIPE_PREFIX_RE$1.test(first.value)) {
|
|
3132
|
-
return words;
|
|
3133
|
-
}
|
|
3134
|
-
return [{ ...first, value: first.value.replace(RECIPE_PREFIX_RE$1, "") }, ...rest];
|
|
3135
|
-
}
|
|
3136
|
-
const NO_VARIABLES = {
|
|
3137
|
-
programAt: () => void 0,
|
|
3138
|
-
referenceAt: () => void 0
|
|
3139
|
-
};
|
|
3140
|
-
function runsGenerator(command) {
|
|
3141
|
-
const words = withoutRecipePrefix(command);
|
|
3142
|
-
const { program } = commandRoles(words);
|
|
3143
|
-
const word = program === void 0 ? void 0 : words[program];
|
|
3144
|
-
return word !== void 0 && packageReference(withoutWindowsSuffix(word.value)).name === GENERATOR_COMMAND;
|
|
3145
|
-
}
|
|
3146
|
-
|
|
3147
3222
|
const PATH_SEPARATOR$8 = "/";
|
|
3148
3223
|
const WINDOWS_SEPARATOR_RE = /\\/g;
|
|
3149
3224
|
const QUOTE_RE = /["']/g;
|
|
@@ -3152,8 +3227,10 @@ function programPath(word) {
|
|
|
3152
3227
|
const suffix = windowsSuffix(word.value);
|
|
3153
3228
|
const written = word.raw.replace(QUOTE_RE, "");
|
|
3154
3229
|
const isWindowsPath = suffix !== "" || WINDOWS_PATH_RE.test(written);
|
|
3155
|
-
|
|
3156
|
-
|
|
3230
|
+
if (!isWindowsPath) {
|
|
3231
|
+
return { path: word.value, suffix, written: word.value };
|
|
3232
|
+
}
|
|
3233
|
+
return { path: written.replace(WINDOWS_SEPARATOR_RE, PATH_SEPARATOR$8), suffix, written };
|
|
3157
3234
|
}
|
|
3158
3235
|
|
|
3159
3236
|
const SHELL_VARIABLE_RE$1 = /^"?\$(?:([A-Za-z_][A-Za-z0-9_]*)|\{([A-Za-z_][A-Za-z0-9_]*)\})"?$/;
|
|
@@ -3301,14 +3378,18 @@ function packageFindings(found, locate) {
|
|
|
3301
3378
|
const change = { kind: "package-name-renamed", location, from: name, to };
|
|
3302
3379
|
return edit === void 0 ? [] : [{ offset, edit, change }];
|
|
3303
3380
|
}
|
|
3304
|
-
function programPathFindings(word,
|
|
3381
|
+
function programPathFindings(word, program, location) {
|
|
3382
|
+
const { path, suffix, written } = program;
|
|
3305
3383
|
const offset = word.start;
|
|
3306
3384
|
if (path.includes(OLD_PACKAGE_FOLDER)) {
|
|
3307
3385
|
return [{ offset, manualStep: { kind: "old-package-file", location, path } }];
|
|
3308
3386
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3387
|
+
if (!path.endsWith(`${BIN_FOLDER}${GENERATOR_COMMAND}${suffix}`)) {
|
|
3388
|
+
const manualStep = { kind: "old-name-in-command", location, word: written };
|
|
3389
|
+
const isGenerator = path.endsWith(`${PATH_SEPARATOR$7}${GENERATOR_COMMAND}${suffix}`);
|
|
3390
|
+
return isGenerator ? [{ offset, manualStep }] : [];
|
|
3391
|
+
}
|
|
3392
|
+
const edit = renameAtEnd(word, GENERATOR_COMMAND, MIGRATED_GENERATOR_COMMAND, suffix);
|
|
3312
3393
|
return edit === void 0 ? [] : [{ offset, edit, change: { kind: "command-renamed", location } }];
|
|
3313
3394
|
}
|
|
3314
3395
|
function programFindings(word, location) {
|
|
@@ -3371,12 +3452,15 @@ function shellTextFindings(text, locate) {
|
|
|
3371
3452
|
function commandWordFindings(commands, locate, variables = NO_VARIABLES, appended = []) {
|
|
3372
3453
|
const known = withUnreadVariables(withWordExpansions(withShellAssignments(commands, variables)));
|
|
3373
3454
|
const shell = shellAppends(commands, known);
|
|
3374
|
-
|
|
3455
|
+
return textFindings([
|
|
3375
3456
|
...shell.commands.flatMap((words) => commandFindings(words, locate, known)),
|
|
3376
3457
|
...[...appended, ...shell.appended].flatMap(
|
|
3377
3458
|
(value) => appendedValueFindings(value, locate, known)
|
|
3378
3459
|
)
|
|
3379
|
-
]
|
|
3460
|
+
]);
|
|
3461
|
+
}
|
|
3462
|
+
function textFindings(found) {
|
|
3463
|
+
const findings = [...found].sort((left, right) => left.offset - right.offset);
|
|
3380
3464
|
return {
|
|
3381
3465
|
edits: findings.flatMap((finding) => finding.edit === void 0 ? [] : [finding.edit]),
|
|
3382
3466
|
changes: findings.flatMap((finding) => finding.change === void 0 ? [] : [finding.change]),
|
|
@@ -3497,15 +3581,17 @@ function rangeStyle(spec) {
|
|
|
3497
3581
|
return isHyphenRange ? "^" : versionStyle(first[2], first[3], first[4]);
|
|
3498
3582
|
}
|
|
3499
3583
|
const isLocalPackageSpec = (spec) => LOCAL_PROTOCOLS.some((protocol) => spec.startsWith(protocol));
|
|
3584
|
+
const NPM_PROTOCOL$1 = "npm:";
|
|
3500
3585
|
function migrateVersionSpec(spec, version) {
|
|
3501
|
-
if (KEPT_PROTOCOLS.some((
|
|
3586
|
+
if (KEPT_PROTOCOLS.some((protocol2) => spec.startsWith(protocol2))) {
|
|
3502
3587
|
return { kind: "kept", spec, isReported: false };
|
|
3503
3588
|
}
|
|
3504
|
-
const
|
|
3589
|
+
const protocol = spec.startsWith(NPM_PROTOCOL$1) ? NPM_PROTOCOL$1 : "";
|
|
3590
|
+
const style = rangeStyle(spec.slice(protocol.length));
|
|
3505
3591
|
if (style === void 0) {
|
|
3506
3592
|
return { kind: "kept", spec, isReported: true };
|
|
3507
3593
|
}
|
|
3508
|
-
return { kind: "replaced", spec: `${style}${version}` };
|
|
3594
|
+
return { kind: "replaced", spec: `${protocol}${style}${version}` };
|
|
3509
3595
|
}
|
|
3510
3596
|
|
|
3511
3597
|
const NO_LONGER_INSTALLED = /* @__PURE__ */ new Map([
|
|
@@ -3544,25 +3630,104 @@ function isDeclaredFor(manifests, filePath, name) {
|
|
|
3544
3630
|
const declares = ({ names }) => names === void 0 || names.has(name) || original !== void 0 && names.has(original);
|
|
3545
3631
|
return containing.length === 0 || containing.some(declares);
|
|
3546
3632
|
}
|
|
3547
|
-
const packageOfSpecifier = (specifier) => {
|
|
3548
|
-
const slash = specifier.indexOf(PATH_SEPARATOR$6);
|
|
3549
|
-
return slash === -1 ? specifier : specifier.slice(0, slash);
|
|
3550
|
-
};
|
|
3551
|
-
function undeclaredImportSteps(imports, filePath, manifests) {
|
|
3552
|
-
return imports.flatMap(({ specifier, line }) => {
|
|
3553
|
-
const name = packageOfSpecifier(specifier);
|
|
3554
|
-
const installers = NO_LONGER_INSTALLED.get(name);
|
|
3555
|
-
return installers === void 0 || isDeclaredFor(manifests, filePath, name) ? [] : [{ kind: "package-not-declared", line, name, installers }];
|
|
3633
|
+
const packageOfSpecifier = (specifier) => {
|
|
3634
|
+
const slash = specifier.indexOf(PATH_SEPARATOR$6);
|
|
3635
|
+
return slash === -1 ? specifier : specifier.slice(0, slash);
|
|
3636
|
+
};
|
|
3637
|
+
function undeclaredImportSteps(imports, filePath, manifests) {
|
|
3638
|
+
return imports.flatMap(({ specifier, line }) => {
|
|
3639
|
+
const name = packageOfSpecifier(specifier);
|
|
3640
|
+
const installers = NO_LONGER_INSTALLED.get(name);
|
|
3641
|
+
return installers === void 0 || isDeclaredFor(manifests, filePath, name) ? [] : [{ kind: "package-not-declared", line, name, installers }];
|
|
3642
|
+
});
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
const SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh"]);
|
|
3646
|
+
const OPTION_PREFIX = "-";
|
|
3647
|
+
const LONG_OPTION_PREFIX = "--";
|
|
3648
|
+
const COMMAND_OPTION = "c";
|
|
3649
|
+
const SET_OPTION = "-o";
|
|
3650
|
+
const PATH_SEPARATOR$5 = "/";
|
|
3651
|
+
function shellScript(words) {
|
|
3652
|
+
const program = words[0]?.value.split(PATH_SEPARATOR$5).at(-1) ?? "";
|
|
3653
|
+
if (!SHELLS.has(program)) {
|
|
3654
|
+
return void 0;
|
|
3655
|
+
}
|
|
3656
|
+
let index = 1;
|
|
3657
|
+
for (let option = words[index]?.value; option !== void 0; option = words[index]?.value) {
|
|
3658
|
+
if (!option.startsWith(OPTION_PREFIX)) {
|
|
3659
|
+
return void 0;
|
|
3660
|
+
}
|
|
3661
|
+
if (!option.startsWith(LONG_OPTION_PREFIX) && option.includes(COMMAND_OPTION)) {
|
|
3662
|
+
return words[index + 1];
|
|
3663
|
+
}
|
|
3664
|
+
index += option === SET_OPTION ? 2 : 1;
|
|
3665
|
+
}
|
|
3666
|
+
return void 0;
|
|
3667
|
+
}
|
|
3668
|
+
function entrypointProgram(entrypoint) {
|
|
3669
|
+
const script = shellScript(entrypoint);
|
|
3670
|
+
if (script !== void 0) {
|
|
3671
|
+
return shellCommands(script.value).some(runsGenerator) ? "generator-or-other" : "other";
|
|
3672
|
+
}
|
|
3673
|
+
const { changes } = commandWordFindings([entrypoint], () => "");
|
|
3674
|
+
return changes.some((change) => change.kind === "command-renamed") ? "generator" : "other";
|
|
3675
|
+
}
|
|
3676
|
+
function entrypointArgumentFindings({ entrypoint, command, written, isPlaced = true }, locate) {
|
|
3677
|
+
const program = entrypointProgram(entrypoint);
|
|
3678
|
+
const first = command[0];
|
|
3679
|
+
if (program === "other" || first === void 0 || entrypointProgram(command) !== "other") {
|
|
3680
|
+
return [];
|
|
3681
|
+
}
|
|
3682
|
+
const use = { written, program: isPlaced ? program : "generator-or-other" };
|
|
3683
|
+
return programArgumentFindings(command, { offset: first.start, use }, locate, NO_VARIABLES);
|
|
3684
|
+
}
|
|
3685
|
+
|
|
3686
|
+
const STAGE_INSTRUCTION_RE = /^[ \t]*(FROM|CMD|ENTRYPOINT)\b(.*)$/gm;
|
|
3687
|
+
const FROM_RE = /^[ \t]+(?:--\S+[ \t]+)*(\S+)(?:[ \t]+AS[ \t]+(\S+))?/i;
|
|
3688
|
+
const FROM = "FROM";
|
|
3689
|
+
const CMD = "CMD";
|
|
3690
|
+
const ENTRYPOINT_WRITTEN = "ENTRYPOINT";
|
|
3691
|
+
function dockerStages(text, forms) {
|
|
3692
|
+
const formAt = new Map(forms.map((form) => [form.lineStart, form]));
|
|
3693
|
+
const stages = [];
|
|
3694
|
+
for (const match of text.matchAll(STAGE_INSTRUCTION_RE)) {
|
|
3695
|
+
const [, keyword, rest] = match;
|
|
3696
|
+
const stage = stages.at(-1);
|
|
3697
|
+
if (keyword === FROM) {
|
|
3698
|
+
const from = FROM_RE.exec(rest ?? "");
|
|
3699
|
+
const name = from?.[2]?.toLowerCase();
|
|
3700
|
+
stages.push({ base: from?.[1] ?? "", name, entrypoint: void 0, command: void 0 });
|
|
3701
|
+
} else if (stage !== void 0) {
|
|
3702
|
+
const instruction = { form: formAt.get(match.index) };
|
|
3703
|
+
stage[keyword === CMD ? "command" : "entrypoint"] = instruction;
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
return stages;
|
|
3707
|
+
}
|
|
3708
|
+
function baseStage(stages, index) {
|
|
3709
|
+
const base = stages[index]?.base.toLowerCase();
|
|
3710
|
+
return stages.findIndex((stage, at) => at < index && (stage.name === base || `${at}` === base));
|
|
3711
|
+
}
|
|
3712
|
+
function entrypointOf(stages, index) {
|
|
3713
|
+
const own = stages[index]?.entrypoint;
|
|
3714
|
+
const base = baseStage(stages, index);
|
|
3715
|
+
return own ?? (base === -1 ? void 0 : entrypointOf(stages, base));
|
|
3716
|
+
}
|
|
3717
|
+
function entrypointCommandFindings(text, forms, locate) {
|
|
3718
|
+
const stages = dockerStages(text, forms);
|
|
3719
|
+
return stages.flatMap((stage, index) => {
|
|
3720
|
+
const entrypoint = entrypointOf(stages, index)?.form;
|
|
3721
|
+
const command = stage.command?.form;
|
|
3722
|
+
if (entrypoint === void 0 || command === void 0) {
|
|
3723
|
+
return [];
|
|
3724
|
+
}
|
|
3725
|
+
const pair = { entrypoint: entrypoint.words, command: command.words };
|
|
3726
|
+
return entrypointArgumentFindings({ ...pair, written: ENTRYPOINT_WRITTEN }, locate);
|
|
3556
3727
|
});
|
|
3557
3728
|
}
|
|
3558
3729
|
|
|
3559
3730
|
const EXEC_FORM_START_RE = /^[ \t]*(?:RUN|CMD|ENTRYPOINT)(?:[ \t]+--\S+)*[ \t]+\[/gm;
|
|
3560
|
-
const SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "dash", "ash", "zsh"]);
|
|
3561
|
-
const OPTION_PREFIX = "-";
|
|
3562
|
-
const LONG_OPTION_PREFIX = "--";
|
|
3563
|
-
const COMMAND_OPTION = "c";
|
|
3564
|
-
const SET_OPTION = "-o";
|
|
3565
|
-
const PATH_SEPARATOR$5 = "/";
|
|
3566
3731
|
const ARRAY_BLANK_RE = /(?:[ \t\r\n]|\\\r?\n)*/y;
|
|
3567
3732
|
const QUOTED_RE = /"(?:[^"\\\n]|\\.)*"/y;
|
|
3568
3733
|
const ITEM_SEPARATOR = ",";
|
|
@@ -3615,26 +3780,9 @@ function execFormAt(text, start) {
|
|
|
3615
3780
|
function execForms(text) {
|
|
3616
3781
|
return [...text.matchAll(EXEC_FORM_START_RE)].flatMap((match) => {
|
|
3617
3782
|
const form = execFormAt(text, match.index + match[0].length - 1);
|
|
3618
|
-
return form === void 0 ? [] : [form];
|
|
3783
|
+
return form === void 0 ? [] : [{ ...form, lineStart: match.index }];
|
|
3619
3784
|
});
|
|
3620
3785
|
}
|
|
3621
|
-
function shellScript(words) {
|
|
3622
|
-
const program = words[0]?.value.split(PATH_SEPARATOR$5).at(-1) ?? "";
|
|
3623
|
-
if (!SHELLS.has(program)) {
|
|
3624
|
-
return void 0;
|
|
3625
|
-
}
|
|
3626
|
-
let index = 1;
|
|
3627
|
-
for (let option = words[index]?.value; option !== void 0; option = words[index]?.value) {
|
|
3628
|
-
if (!option.startsWith(OPTION_PREFIX)) {
|
|
3629
|
-
return void 0;
|
|
3630
|
-
}
|
|
3631
|
-
if (!option.startsWith(LONG_OPTION_PREFIX) && option.includes(COMMAND_OPTION)) {
|
|
3632
|
-
return words[index + 1];
|
|
3633
|
-
}
|
|
3634
|
-
index += option === SET_OPTION ? 2 : 1;
|
|
3635
|
-
}
|
|
3636
|
-
return void 0;
|
|
3637
|
-
}
|
|
3638
3786
|
function execCommands(forms) {
|
|
3639
3787
|
const commands = [];
|
|
3640
3788
|
const escaped = [];
|
|
@@ -3722,10 +3870,16 @@ function migrateDockerfile(text, file) {
|
|
|
3722
3870
|
const values = definitions.flatMap(valueCommands);
|
|
3723
3871
|
const run = withoutVariableInstructions(shellForm, instructions);
|
|
3724
3872
|
const commands = [...run, ...values, ...exec.commands];
|
|
3725
|
-
const
|
|
3726
|
-
const
|
|
3727
|
-
const
|
|
3728
|
-
|
|
3873
|
+
const found = commandWordFindings(commands, locate, shellVariables(definitions));
|
|
3874
|
+
const entry = textFindings(entrypointCommandFindings(text, forms, locate));
|
|
3875
|
+
const edits = [...found.edits, ...entry.edits];
|
|
3876
|
+
const changes = [...found.changes, ...entry.changes];
|
|
3877
|
+
const steps = [...found.manualSteps, ...entry.manualSteps];
|
|
3878
|
+
return {
|
|
3879
|
+
text: applyTextEdits(text, edits),
|
|
3880
|
+
changes,
|
|
3881
|
+
manualSteps: [...steps, ...escapedScriptSteps(exec.escaped, lineOf)]
|
|
3882
|
+
};
|
|
3729
3883
|
}
|
|
3730
3884
|
|
|
3731
3885
|
const CATALOG_PROTOCOL = "catalog:";
|
|
@@ -4291,7 +4445,7 @@ const BACKTICK = "`";
|
|
|
4291
4445
|
const ESCAPING_DELIMITER = '"';
|
|
4292
4446
|
const ESCAPE = "\\";
|
|
4293
4447
|
const COMMENT_START$1 = "#";
|
|
4294
|
-
const LINE_BREAK$
|
|
4448
|
+
const LINE_BREAK$4 = "\n";
|
|
4295
4449
|
function closingOffset(text, delimiter, from) {
|
|
4296
4450
|
if (delimiter !== ESCAPING_DELIMITER) {
|
|
4297
4451
|
const close = text.indexOf(delimiter, from);
|
|
@@ -4301,7 +4455,7 @@ function closingOffset(text, delimiter, from) {
|
|
|
4301
4455
|
const char = text[index];
|
|
4302
4456
|
if (char === ESCAPE) {
|
|
4303
4457
|
index += 1;
|
|
4304
|
-
} else if (char === ESCAPING_DELIMITER || char === LINE_BREAK$
|
|
4458
|
+
} else if (char === ESCAPING_DELIMITER || char === LINE_BREAK$4) {
|
|
4305
4459
|
return char === ESCAPING_DELIMITER ? index : void 0;
|
|
4306
4460
|
}
|
|
4307
4461
|
}
|
|
@@ -4324,7 +4478,7 @@ function literalAt(text, offset) {
|
|
|
4324
4478
|
function expressionAt(text, start) {
|
|
4325
4479
|
const literals = [];
|
|
4326
4480
|
let index = start;
|
|
4327
|
-
while (index < text.length && text[index] !== LINE_BREAK$
|
|
4481
|
+
while (index < text.length && text[index] !== LINE_BREAK$4 && text[index] !== COMMENT_START$1) {
|
|
4328
4482
|
const literal = literalAt(text, index);
|
|
4329
4483
|
literals.push(...literal === void 0 ? [] : [literal]);
|
|
4330
4484
|
index = literal?.end ?? index + 1;
|
|
@@ -4348,7 +4502,7 @@ function interpolationAt(text, start) {
|
|
|
4348
4502
|
if (text.startsWith(INTERPOLATION_CLOSE, index)) {
|
|
4349
4503
|
return { start, end: index + INTERPOLATION_CLOSE.length, literals };
|
|
4350
4504
|
}
|
|
4351
|
-
if (text[index] === LINE_BREAK$
|
|
4505
|
+
if (text[index] === LINE_BREAK$4) {
|
|
4352
4506
|
return void 0;
|
|
4353
4507
|
}
|
|
4354
4508
|
const literal = literalAt(text, index);
|
|
@@ -4377,11 +4531,11 @@ const EQUALS = "=";
|
|
|
4377
4531
|
const OPEN_PAREN = "(";
|
|
4378
4532
|
const CLOSE_PAREN = ")";
|
|
4379
4533
|
const COMMENT_START = "#";
|
|
4380
|
-
const LINE_BREAK$
|
|
4534
|
+
const LINE_BREAK$3 = "\n";
|
|
4381
4535
|
const BLANK_RE = /[ \t]/;
|
|
4382
4536
|
const depthChange = (char) => char === OPEN_PAREN ? 1 : char === CLOSE_PAREN ? -1 : 0;
|
|
4383
4537
|
function headerColon(text, from) {
|
|
4384
|
-
for (let index = from; index < text.length && text[index] !== LINE_BREAK$
|
|
4538
|
+
for (let index = from; index < text.length && text[index] !== LINE_BREAK$3; ) {
|
|
4385
4539
|
const literal = literalAt(text, index);
|
|
4386
4540
|
const char = text[index];
|
|
4387
4541
|
if (literal !== void 0) {
|
|
@@ -4485,7 +4639,7 @@ function shellProgram(shell) {
|
|
|
4485
4639
|
const isCommandLineShell = (shell) => COMMAND_LINE_SHELLS.has(shellProgram(shell));
|
|
4486
4640
|
const endsWith = (path, keys) => keys.every((key, index) => path[path.length - keys.length + index] === key);
|
|
4487
4641
|
const isDefaultShell = (value) => endsWith(value.path, DEFAULT_SHELL_PATH);
|
|
4488
|
-
function scopeOf(value) {
|
|
4642
|
+
function scopeOf$1(value) {
|
|
4489
4643
|
const keys = isDefaultShell(value) ? DEFAULT_SHELL_PATH.length : 1;
|
|
4490
4644
|
return JSON.stringify(value.path.slice(0, -keys));
|
|
4491
4645
|
}
|
|
@@ -4516,7 +4670,7 @@ function stepShells(strings) {
|
|
|
4516
4670
|
const ordered = [...shells.filter(isDefaultShell), ...shells.filter(isOwnShell)];
|
|
4517
4671
|
const byScope = new Map([
|
|
4518
4672
|
...inheritedShells(strings, shells),
|
|
4519
|
-
...ordered.map((value) => [scopeOf(value), value.value])
|
|
4673
|
+
...ordered.map((value) => [scopeOf$1(value), value.value])
|
|
4520
4674
|
]);
|
|
4521
4675
|
return (value) => {
|
|
4522
4676
|
for (let depth = value.path.length - 1; depth >= 0; depth -= 1) {
|
|
@@ -4536,18 +4690,18 @@ function otherShellFindings(values, shellOf, locate) {
|
|
|
4536
4690
|
return { edits: [], changes: [], manualSteps };
|
|
4537
4691
|
}
|
|
4538
4692
|
|
|
4539
|
-
const LINE_BREAK$
|
|
4693
|
+
const LINE_BREAK$2 = "\n";
|
|
4540
4694
|
const SHEBANG = "#!";
|
|
4541
4695
|
const BODY_LINE_RE = /^(?:[ \t][^\n]*|[ \t]*\r?)$/;
|
|
4542
4696
|
function nextLineStart(text, offset) {
|
|
4543
|
-
const lineBreak = text.indexOf(LINE_BREAK$
|
|
4697
|
+
const lineBreak = text.indexOf(LINE_BREAK$2, offset);
|
|
4544
4698
|
return lineBreak === -1 ? text.length : lineBreak + 1;
|
|
4545
4699
|
}
|
|
4546
4700
|
function bodyEnd(text, start) {
|
|
4547
4701
|
let end = start;
|
|
4548
4702
|
while (end < text.length) {
|
|
4549
4703
|
const lineEnd = nextLineStart(text, end);
|
|
4550
|
-
if (!BODY_LINE_RE.test(text.slice(end, lineEnd).replace(LINE_BREAK$
|
|
4704
|
+
if (!BODY_LINE_RE.test(text.slice(end, lineEnd).replace(LINE_BREAK$2, ""))) {
|
|
4551
4705
|
break;
|
|
4552
4706
|
}
|
|
4553
4707
|
end = lineEnd;
|
|
@@ -4557,7 +4711,7 @@ function bodyEnd(text, start) {
|
|
|
4557
4711
|
function shebangRecipe(text, header) {
|
|
4558
4712
|
const start = nextLineStart(text, header.end);
|
|
4559
4713
|
const end = bodyEnd(text, start);
|
|
4560
|
-
const firstLine = text.slice(start, end).split(LINE_BREAK$
|
|
4714
|
+
const firstLine = text.slice(start, end).split(LINE_BREAK$2).map((line) => line.trim()).find((line) => line.length > 0);
|
|
4561
4715
|
if (firstLine === void 0 || !firstLine.startsWith(SHEBANG)) {
|
|
4562
4716
|
return [];
|
|
4563
4717
|
}
|
|
@@ -4760,7 +4914,7 @@ const VALUE_ARGUMENTS = /* @__PURE__ */ new Map([
|
|
|
4760
4914
|
["and", 0]
|
|
4761
4915
|
]);
|
|
4762
4916
|
const WHOLE_TEXT_FUNCTIONS = /* @__PURE__ */ new Set(["strip"]);
|
|
4763
|
-
const FUNCTION_HEAD_RE = /^\$[({]([a-z]+)[ \t]+/;
|
|
4917
|
+
const FUNCTION_HEAD_RE = /^\$[({]([a-z]+(?:-[a-z]+)*)[ \t]+/;
|
|
4764
4918
|
const OPENING = new Set(Object.keys(CLOSING));
|
|
4765
4919
|
const CLOSINGS = new Set(Object.values(CLOSING));
|
|
4766
4920
|
function callArguments(text, start, end) {
|
|
@@ -4824,14 +4978,14 @@ const ASSIGNMENT_RE = new RegExp(
|
|
|
4824
4978
|
const VARIABLE_REFERENCE_RE = /^\$(?:\(([A-Za-z_][A-Za-z0-9_.-]*)\)|\{([A-Za-z_][A-Za-z0-9_.-]*)\}|([A-Za-z_]))$/;
|
|
4825
4979
|
const RECIPE_PREFIX_RE = /^[@+-]+/;
|
|
4826
4980
|
const NOT_LINE_BREAK_RE = /[^\n]/g;
|
|
4827
|
-
const LINE_BREAK = "\n";
|
|
4981
|
+
const LINE_BREAK$1 = "\n";
|
|
4828
4982
|
const BACKSLASH = "\\";
|
|
4829
4983
|
const APPEND_OPERATOR = "+=";
|
|
4830
4984
|
const CONDITIONAL_OPERATOR = "?=";
|
|
4831
4985
|
function logicalLineEnd(text, index) {
|
|
4832
|
-
let end = text.indexOf(LINE_BREAK, index);
|
|
4986
|
+
let end = text.indexOf(LINE_BREAK$1, index);
|
|
4833
4987
|
while (end !== -1 && text[end - 1] === BACKSLASH) {
|
|
4834
|
-
end = text.indexOf(LINE_BREAK, end + 1);
|
|
4988
|
+
end = text.indexOf(LINE_BREAK$1, end + 1);
|
|
4835
4989
|
}
|
|
4836
4990
|
return end === -1 ? text.length : end;
|
|
4837
4991
|
}
|
|
@@ -4911,9 +5065,12 @@ const startsIn = (command, { valueStart, valueEnd }) => {
|
|
|
4911
5065
|
return valueStart <= start && start < valueEnd;
|
|
4912
5066
|
};
|
|
4913
5067
|
function appendedCommands(commands, placed, programs) {
|
|
4914
|
-
const
|
|
5068
|
+
const commandsIn = (assignment) => commands.filter((command) => startsIn(command, assignment)).sort((left, right) => (left[0]?.start ?? 0) - (right[0]?.start ?? 0));
|
|
5069
|
+
const appends = placed.filter(
|
|
5070
|
+
({ assignment, place }) => place !== void 0 && place !== "start" && !isOwnGeneratorCommand(place, commandsIn(assignment)[0])
|
|
5071
|
+
);
|
|
4915
5072
|
const appended = appends.map(({ assignment }) => {
|
|
4916
|
-
const words =
|
|
5073
|
+
const words = commandsIn(assignment).flat().sort((left, right) => left.start - right.start);
|
|
4917
5074
|
const written = `$(${assignment.name})`;
|
|
4918
5075
|
const program = programs.get(assignment.name) ?? "generator-or-other";
|
|
4919
5076
|
return { words, program: { written, program } };
|
|
@@ -5241,12 +5398,18 @@ const PNPM_SETTINGS = {
|
|
|
5241
5398
|
overrideSections: /* @__PURE__ */ new Set(["overrides", "patchedDependencies"]),
|
|
5242
5399
|
prefix: `${PNPM_SETTINGS_FIELD}.`
|
|
5243
5400
|
};
|
|
5401
|
+
const BUN_SETTING_FIELDS = ["trustedDependencies"];
|
|
5244
5402
|
function reportSettings(manifest, findings) {
|
|
5245
5403
|
for (const field of OVERRIDE_FIELDS) {
|
|
5246
5404
|
for (const name of valuesAt(manifest, field).flatMap(overriddenOldPackages)) {
|
|
5247
5405
|
findings.manualSteps.push({ kind: "override-names-package", field, name });
|
|
5248
5406
|
}
|
|
5249
5407
|
}
|
|
5408
|
+
for (const field of BUN_SETTING_FIELDS) {
|
|
5409
|
+
for (const name of valuesAt(manifest, field).flatMap(oldPackagesNamedBy)) {
|
|
5410
|
+
findings.manualSteps.push({ kind: "setting-names-package", field, name });
|
|
5411
|
+
}
|
|
5412
|
+
}
|
|
5250
5413
|
for (const settings of mapsAt(manifest, PNPM_SETTINGS_FIELD)) {
|
|
5251
5414
|
reportSettingSections(settings, PNPM_SETTINGS, findings);
|
|
5252
5415
|
}
|
|
@@ -5308,18 +5471,12 @@ function oldPackagePatchSteps(fileName) {
|
|
|
5308
5471
|
return name === void 0 || to === void 0 ? [] : [{ kind: "old-package-patch", name, to }];
|
|
5309
5472
|
}
|
|
5310
5473
|
|
|
5311
|
-
const INPUTS_KEY = "inputs";
|
|
5312
|
-
const DEFAULT_KEY = "default";
|
|
5313
|
-
const INPUT_DEFAULT_DEPTH = 3;
|
|
5314
|
-
const INPUT_NAME_INDEX = -2;
|
|
5315
5474
|
const BLANK = " ";
|
|
5316
5475
|
const SURROUNDING_QUOTES_RE = /^"(.*)"$/s;
|
|
5317
|
-
const
|
|
5318
|
-
|
|
5319
|
-
function inputDefaults(strings) {
|
|
5476
|
+
const INPUT_REFERENCE_RE = /(?<![\w.-])(?:github\.event\.)?inputs(?:\.([A-Za-z_][A-Za-z0-9_-]*)|\[[ \t]*'([^']*)'[ \t]*\])/g;
|
|
5477
|
+
function inputValues(defaults) {
|
|
5320
5478
|
const values = /* @__PURE__ */ new Map();
|
|
5321
|
-
for (const value of
|
|
5322
|
-
const name = String(value.path.at(INPUT_NAME_INDEX));
|
|
5479
|
+
for (const [value, name] of defaults) {
|
|
5323
5480
|
values.set(
|
|
5324
5481
|
name,
|
|
5325
5482
|
[values.get(name), value.value].filter((part) => part !== void 0).join(BLANK)
|
|
@@ -5329,27 +5486,14 @@ function inputDefaults(strings) {
|
|
|
5329
5486
|
}
|
|
5330
5487
|
function expressionValue(expression, defaults) {
|
|
5331
5488
|
const inputs = [...expression.matchAll(INPUT_REFERENCE_RE)].flatMap((match) => {
|
|
5332
|
-
const value = defaults.get(match[1]);
|
|
5489
|
+
const value = defaults.get(match[1] ?? match[2] ?? "");
|
|
5333
5490
|
return value === void 0 ? [] : [value];
|
|
5334
5491
|
});
|
|
5335
5492
|
const literals = expressionLiterals(expression).map((literal) => literal.text);
|
|
5336
5493
|
return [...inputs, ...literals].join(BLANK);
|
|
5337
5494
|
}
|
|
5338
|
-
function
|
|
5339
|
-
const
|
|
5340
|
-
let copiedUpTo = 0;
|
|
5341
|
-
for (let open = text.indexOf(EXPRESSION_OPEN); open !== -1; ) {
|
|
5342
|
-
const end = expressionEnd(text, open) ?? text.length;
|
|
5343
|
-
parts.push(text.slice(copiedUpTo, open), expressionValue(text.slice(open, end), defaults));
|
|
5344
|
-
copiedUpTo = end;
|
|
5345
|
-
open = text.indexOf(EXPRESSION_OPEN, end);
|
|
5346
|
-
}
|
|
5347
|
-
parts.push(text.slice(copiedUpTo));
|
|
5348
|
-
return parts.join("");
|
|
5349
|
-
}
|
|
5350
|
-
function withInputDefaults(variables, strings) {
|
|
5351
|
-
const defaults = inputDefaults(strings);
|
|
5352
|
-
const expressionsRead = (text) => withExpressionValues(text, defaults);
|
|
5495
|
+
function withInputDefaults(variables, defaults) {
|
|
5496
|
+
const expressionsRead = (text) => mapExpressions(text, (expression) => expressionValue(expression, defaults));
|
|
5353
5497
|
return {
|
|
5354
5498
|
programAt: (program) => variables.programAt(program),
|
|
5355
5499
|
referenceAt: (word) => {
|
|
@@ -5364,6 +5508,113 @@ function withInputDefaults(variables, strings) {
|
|
|
5364
5508
|
};
|
|
5365
5509
|
}
|
|
5366
5510
|
|
|
5511
|
+
const ARGUMENT_KEYS = /* @__PURE__ */ new Map([
|
|
5512
|
+
["entrypoint", "command"],
|
|
5513
|
+
["command", "args"]
|
|
5514
|
+
]);
|
|
5515
|
+
const PAIRED_KEYS = /* @__PURE__ */ new Set([
|
|
5516
|
+
...ARGUMENT_KEYS.keys(),
|
|
5517
|
+
...ARGUMENT_KEYS.values()
|
|
5518
|
+
]);
|
|
5519
|
+
const TRAILING_KEY = "args";
|
|
5520
|
+
const LINE_BREAK = "\n";
|
|
5521
|
+
const isItem = (string) => typeof string.path.at(-1) === "number";
|
|
5522
|
+
const isContainerListItem = (string) => isItem(string) && PAIRED_KEYS.has(String(string.path.at(-2)));
|
|
5523
|
+
const isList = (value) => value.strings[0] !== void 0 && isItem(value.strings[0]);
|
|
5524
|
+
const mapOf = (string) => JSON.stringify(string.path.slice(0, isItem(string) ? -2 : -1));
|
|
5525
|
+
function isNextItem(value, string) {
|
|
5526
|
+
const last = value?.strings.at(-1);
|
|
5527
|
+
return last !== void 0 && isItem(last) && isItem(string) && JSON.stringify(last.path.slice(0, -1)) === JSON.stringify(string.path.slice(0, -1)) && Number(string.path.at(-1)) > Number(last.path.at(-1));
|
|
5528
|
+
}
|
|
5529
|
+
function keyValues(strings) {
|
|
5530
|
+
const values = [];
|
|
5531
|
+
const starts = /* @__PURE__ */ new Set();
|
|
5532
|
+
for (const string of strings) {
|
|
5533
|
+
const key = ownerKey(string.path) ?? "";
|
|
5534
|
+
const isValue = isItem(string) ? string.path.at(-2) === key : string.path.at(-1) === key;
|
|
5535
|
+
if (!PAIRED_KEYS.has(key) || !isValue || starts.has(string.start)) {
|
|
5536
|
+
continue;
|
|
5537
|
+
}
|
|
5538
|
+
starts.add(string.start);
|
|
5539
|
+
const last = values.at(-1);
|
|
5540
|
+
if (last !== void 0 && isNextItem(last, string)) {
|
|
5541
|
+
last.strings.push(string);
|
|
5542
|
+
} else {
|
|
5543
|
+
values.push({ map: mapOf(string), key, strings: [string] });
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
return values;
|
|
5547
|
+
}
|
|
5548
|
+
const isPlaceable = (string, text) => !string.isEscaped && !(string.isFolded && text.slice(string.content.start, string.content.end).includes(LINE_BREAK));
|
|
5549
|
+
function scalarWords(scalar, text) {
|
|
5550
|
+
const { start, end } = scalar.content;
|
|
5551
|
+
const isPlaced = isPlaceable(scalar, text);
|
|
5552
|
+
const [words = []] = shellCommands(isPlaced ? text.slice(start, end) : scalar.value);
|
|
5553
|
+
const at = (word) => isPlaced ? { ...word, start: word.start + start, end: word.end + start } : { ...word, start: scalar.start, end: scalar.start };
|
|
5554
|
+
return { words: words.map(at), isPlaced };
|
|
5555
|
+
}
|
|
5556
|
+
function valueWords(value, text) {
|
|
5557
|
+
const [first] = value.strings;
|
|
5558
|
+
if (first !== void 0 && !isItem(first)) {
|
|
5559
|
+
return scalarWords(first, text);
|
|
5560
|
+
}
|
|
5561
|
+
const words = value.strings.map((item) => {
|
|
5562
|
+
const { start, end } = item.content;
|
|
5563
|
+
return { start, end, value: item.value, raw: text.slice(start, end), item };
|
|
5564
|
+
});
|
|
5565
|
+
return { words, isPlaced: true };
|
|
5566
|
+
}
|
|
5567
|
+
function pairOf(left, right) {
|
|
5568
|
+
if (right === void 0 || left.map !== right.map) {
|
|
5569
|
+
return void 0;
|
|
5570
|
+
}
|
|
5571
|
+
if (ARGUMENT_KEYS.get(left.key) === right.key) {
|
|
5572
|
+
return [left, right];
|
|
5573
|
+
}
|
|
5574
|
+
return ARGUMENT_KEYS.get(right.key) === left.key ? [right, left] : void 0;
|
|
5575
|
+
}
|
|
5576
|
+
function containers(values) {
|
|
5577
|
+
const found = [];
|
|
5578
|
+
for (let index = 0; index < values.length; index++) {
|
|
5579
|
+
const value = values[index];
|
|
5580
|
+
const pair = pairOf(value, values[index + 1]);
|
|
5581
|
+
if (pair !== void 0) {
|
|
5582
|
+
found.push({ entrypoint: pair[0], command: pair[1] });
|
|
5583
|
+
index++;
|
|
5584
|
+
} else if (value.key !== TRAILING_KEY) {
|
|
5585
|
+
found.push({ entrypoint: value, command: void 0 });
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
return found;
|
|
5589
|
+
}
|
|
5590
|
+
function listCommand({ entrypoint, command }, text) {
|
|
5591
|
+
const parts = command === void 0 ? [entrypoint] : [entrypoint, command];
|
|
5592
|
+
return parts.filter(isList).flatMap((part) => valueWords(part, text).words);
|
|
5593
|
+
}
|
|
5594
|
+
function argumentFindings(container, text, locate) {
|
|
5595
|
+
const { entrypoint, command } = container;
|
|
5596
|
+
if (command === void 0) {
|
|
5597
|
+
return [];
|
|
5598
|
+
}
|
|
5599
|
+
const words = valueWords(entrypoint, text).words;
|
|
5600
|
+
if (isList(entrypoint) && isList(command) && shellScript(words) === void 0) {
|
|
5601
|
+
return [];
|
|
5602
|
+
}
|
|
5603
|
+
const args = valueWords(command, text);
|
|
5604
|
+
const pair = { entrypoint: words, command: args.words, written: entrypoint.key };
|
|
5605
|
+
return entrypointArgumentFindings({ ...pair, isPlaced: args.isPlaced }, locate);
|
|
5606
|
+
}
|
|
5607
|
+
function containerCommands(text, strings, locate) {
|
|
5608
|
+
const found = containers(keyValues(strings));
|
|
5609
|
+
const commands = found.map((container) => listCommand(container, text));
|
|
5610
|
+
const scripts = commands.flatMap((words) => shellScript(words)?.item ?? []);
|
|
5611
|
+
const flags = found.flatMap((container) => argumentFindings(container, text, locate));
|
|
5612
|
+
return {
|
|
5613
|
+
findings: [commandWordFindings(commands, locate), textFindings(flags)],
|
|
5614
|
+
scripts: new Set(scripts)
|
|
5615
|
+
};
|
|
5616
|
+
}
|
|
5617
|
+
|
|
5367
5618
|
const YAML_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
5368
5619
|
"run",
|
|
5369
5620
|
"script",
|
|
@@ -5388,34 +5639,161 @@ const TASKFILE_COMMAND_KEYS = /* @__PURE__ */ new Set([
|
|
|
5388
5639
|
"status"
|
|
5389
5640
|
]);
|
|
5390
5641
|
|
|
5642
|
+
const ROOT_PREFIX = "/";
|
|
5643
|
+
const NOT_A_PROJECT_PATH_RE = /\{\{|\$|^[a-z][a-z\d+.-]*:/i;
|
|
5644
|
+
const LEADING_ROOT_RE = /^\/+/;
|
|
5645
|
+
const YAML_FILE_RE = /\.ya?ml$/;
|
|
5646
|
+
const NO_INCLUDES = {
|
|
5647
|
+
isIncludeAt: () => false,
|
|
5648
|
+
isFromRoot: () => false
|
|
5649
|
+
};
|
|
5650
|
+
const TASKFILE_INCLUDES_KEY = "includes";
|
|
5651
|
+
const TASKFILE_KEY = "taskfile";
|
|
5652
|
+
const TASKFILE_INCLUDES = {
|
|
5653
|
+
isIncludeAt: ([key, name, field]) => key === TASKFILE_INCLUDES_KEY && typeof name === "string" && (field === void 0 || field === TASKFILE_KEY),
|
|
5654
|
+
isFromRoot: () => false
|
|
5655
|
+
};
|
|
5656
|
+
const GITLAB_INCLUDE_KEY = "include";
|
|
5657
|
+
const GITLAB_LOCAL_KEY = "local";
|
|
5658
|
+
const GITLAB_INCLUDES = {
|
|
5659
|
+
isIncludeAt: ([key, ...rest]) => {
|
|
5660
|
+
const [first] = typeof rest[0] === "number" ? rest.slice(1) : rest;
|
|
5661
|
+
const isLocal = first === void 0 || first === GITLAB_LOCAL_KEY;
|
|
5662
|
+
return key === GITLAB_INCLUDE_KEY && isLocal;
|
|
5663
|
+
},
|
|
5664
|
+
isFromRoot: () => true
|
|
5665
|
+
};
|
|
5666
|
+
const AZURE_TEMPLATE_KEY = "template";
|
|
5667
|
+
const AZURE_TEMPLATES = {
|
|
5668
|
+
isIncludeAt: (path) => path.at(-1) === AZURE_TEMPLATE_KEY,
|
|
5669
|
+
isFromRoot: (reference) => reference.startsWith(ROOT_PREFIX)
|
|
5670
|
+
};
|
|
5671
|
+
function includedPaths(fromPath, strings, includes) {
|
|
5672
|
+
return strings.flatMap((string) => {
|
|
5673
|
+
const reference = string.value.trim();
|
|
5674
|
+
if (!includes.isIncludeAt(string.path) || NOT_A_PROJECT_PATH_RE.test(reference)) {
|
|
5675
|
+
return [];
|
|
5676
|
+
}
|
|
5677
|
+
const path = includes.isFromRoot(reference) ? referencedProjectPath("", reference.replace(LEADING_ROOT_RE, "")) : referencedProjectPath(fromPath, reference);
|
|
5678
|
+
return path !== void 0 && YAML_FILE_RE.test(path) ? [path] : [];
|
|
5679
|
+
});
|
|
5680
|
+
}
|
|
5681
|
+
|
|
5682
|
+
const NAME_KEY = "name";
|
|
5683
|
+
function itemName(strings, index) {
|
|
5684
|
+
const item = strings[index]?.path.slice(0, -1) ?? [];
|
|
5685
|
+
const isInItem = (string) => string !== void 0 && item.every((part, at) => string.path[at] === part);
|
|
5686
|
+
const isName = (string) => string.path.length === item.length + 1 && string.path.at(-1) === NAME_KEY;
|
|
5687
|
+
let [first, last] = [index, index];
|
|
5688
|
+
while (isInItem(strings[first - 1])) {
|
|
5689
|
+
first -= 1;
|
|
5690
|
+
}
|
|
5691
|
+
while (isInItem(strings[last + 1])) {
|
|
5692
|
+
last += 1;
|
|
5693
|
+
}
|
|
5694
|
+
return strings.slice(first, last + 1).find(isName)?.value;
|
|
5695
|
+
}
|
|
5696
|
+
|
|
5697
|
+
const DEFAULT_KEY = "default";
|
|
5698
|
+
const INPUTS_KEY = "inputs";
|
|
5699
|
+
const PARAMETERS_KEY = "parameters";
|
|
5700
|
+
const SPEC_KEY = "spec";
|
|
5701
|
+
const SPEC_INPUT_DEPTH = 4;
|
|
5702
|
+
const PATH_TAIL$1 = [-1, -2, -3];
|
|
5703
|
+
function defaultUnder(key, value) {
|
|
5704
|
+
const [last, name, owner] = PATH_TAIL$1.map((at) => value?.path.at(at));
|
|
5705
|
+
return last === DEFAULT_KEY && owner === key && typeof name === "string" ? name : void 0;
|
|
5706
|
+
}
|
|
5707
|
+
const NO_PARAMETERS = {
|
|
5708
|
+
defaultOf: () => void 0,
|
|
5709
|
+
asExpressions: (text) => text
|
|
5710
|
+
};
|
|
5711
|
+
const GITHUB_INPUTS = {
|
|
5712
|
+
defaultOf: (strings, index) => defaultUnder(INPUTS_KEY, strings[index]),
|
|
5713
|
+
asExpressions: (text) => text
|
|
5714
|
+
};
|
|
5715
|
+
const GITLAB_INTERPOLATION_RE = /\$\[\[(.*?)\]\]/g;
|
|
5716
|
+
const GITLAB_INPUTS = {
|
|
5717
|
+
defaultOf: (strings, index) => {
|
|
5718
|
+
const value = strings[index];
|
|
5719
|
+
const isSpec = value?.path.length === SPEC_INPUT_DEPTH && value.path[0] === SPEC_KEY;
|
|
5720
|
+
return isSpec ? defaultUnder(INPUTS_KEY, value) : void 0;
|
|
5721
|
+
},
|
|
5722
|
+
asExpressions: (text) => text.replace(GITLAB_INTERPOLATION_RE, "$${{$1}}")
|
|
5723
|
+
};
|
|
5724
|
+
const CIRCLECI_PARAMETER_RE = /<<[ \t]*(?:pipeline\.)?parameters\.([A-Za-z_][A-Za-z0-9_-]*)[ \t]*>>/g;
|
|
5725
|
+
const EXPRESSION_CLOSE = "}}";
|
|
5726
|
+
const asInputExpression = (written, name) => `${EXPRESSION_OPEN} ${INPUTS_KEY}.${name}`.padEnd(written.length - EXPRESSION_CLOSE.length, " ") + EXPRESSION_CLOSE;
|
|
5727
|
+
const CIRCLECI_PARAMETERS = {
|
|
5728
|
+
defaultOf: (strings, index) => defaultUnder(PARAMETERS_KEY, strings[index]),
|
|
5729
|
+
asExpressions: (text) => text.replace(CIRCLECI_PARAMETER_RE, asInputExpression)
|
|
5730
|
+
};
|
|
5731
|
+
const AZURE_PARAMETERS_RE = /(?<![\w.-])parameters(?=\.|\[)/g;
|
|
5732
|
+
const AZURE_AS_INPUTS = INPUTS_KEY.padStart(PARAMETERS_KEY.length, " ");
|
|
5733
|
+
const AZURE_PARAMETERS = {
|
|
5734
|
+
defaultOf: (strings, index) => {
|
|
5735
|
+
const [last, item, owner] = PATH_TAIL$1.map((at) => strings[index]?.path.at(at));
|
|
5736
|
+
const isDefault = last === DEFAULT_KEY && typeof item === "number" && owner === PARAMETERS_KEY;
|
|
5737
|
+
return isDefault ? itemName(strings, index) : void 0;
|
|
5738
|
+
},
|
|
5739
|
+
asExpressions: (text) => mapExpressions(text, (expression) => expression.replace(AZURE_PARAMETERS_RE, AZURE_AS_INPUTS))
|
|
5740
|
+
};
|
|
5741
|
+
function parameterDefaults(strings, parameters) {
|
|
5742
|
+
return new Map(
|
|
5743
|
+
strings.flatMap((value, index) => {
|
|
5744
|
+
const name = parameters.defaultOf(strings, index);
|
|
5745
|
+
return name === void 0 ? [] : [[value, name]];
|
|
5746
|
+
})
|
|
5747
|
+
);
|
|
5748
|
+
}
|
|
5749
|
+
|
|
5391
5750
|
const ENV_KEY = "env";
|
|
5392
5751
|
const ENVIRONMENT_KEY = "environment";
|
|
5393
5752
|
const VARIABLES_KEY = "variables";
|
|
5394
5753
|
const VARS_KEY = "vars";
|
|
5395
|
-
const VALUE_KEY = "value";
|
|
5396
|
-
const NAME_KEY = "name";
|
|
5397
5754
|
const PLAIN = {
|
|
5398
5755
|
hasValueMaps: false,
|
|
5399
5756
|
hasListItems: false,
|
|
5400
5757
|
hasNamedItems: false,
|
|
5401
5758
|
reference: void 0,
|
|
5402
|
-
shellName: (name) => name
|
|
5759
|
+
shellName: (name) => name,
|
|
5760
|
+
hasDollarEscapes: false
|
|
5403
5761
|
};
|
|
5404
5762
|
const DEFAULT_YAML_FILE = {
|
|
5405
5763
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5406
|
-
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY]) }
|
|
5764
|
+
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY]) },
|
|
5765
|
+
parameters: GITHUB_INPUTS,
|
|
5766
|
+
includes: NO_INCLUDES
|
|
5407
5767
|
};
|
|
5408
5768
|
const GITLAB_CI_FILE = {
|
|
5409
5769
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5410
|
-
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY, VARIABLES_KEY]), hasValueMaps: true }
|
|
5770
|
+
environment: { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY, VARIABLES_KEY]), hasValueMaps: true },
|
|
5771
|
+
parameters: GITLAB_INPUTS,
|
|
5772
|
+
includes: GITLAB_INCLUDES
|
|
5411
5773
|
};
|
|
5774
|
+
const CI_ENVIRONMENT = { ...PLAIN, keys: /* @__PURE__ */ new Set([ENV_KEY, ENVIRONMENT_KEY]) };
|
|
5412
5775
|
const CI_ENVIRONMENT_FILE = {
|
|
5413
5776
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5414
|
-
environment:
|
|
5777
|
+
environment: CI_ENVIRONMENT,
|
|
5778
|
+
parameters: NO_PARAMETERS,
|
|
5779
|
+
includes: NO_INCLUDES
|
|
5780
|
+
};
|
|
5781
|
+
const CIRCLECI_FILE = {
|
|
5782
|
+
commandKeys: YAML_COMMAND_KEYS,
|
|
5783
|
+
environment: CI_ENVIRONMENT,
|
|
5784
|
+
parameters: CIRCLECI_PARAMETERS,
|
|
5785
|
+
includes: NO_INCLUDES
|
|
5415
5786
|
};
|
|
5416
5787
|
const COMPOSE_FILE = {
|
|
5417
5788
|
commandKeys: YAML_COMMAND_KEYS,
|
|
5418
|
-
environment: {
|
|
5789
|
+
environment: {
|
|
5790
|
+
...PLAIN,
|
|
5791
|
+
keys: /* @__PURE__ */ new Set([ENV_KEY, ENVIRONMENT_KEY]),
|
|
5792
|
+
hasListItems: true,
|
|
5793
|
+
hasDollarEscapes: true
|
|
5794
|
+
},
|
|
5795
|
+
parameters: NO_PARAMETERS,
|
|
5796
|
+
includes: NO_INCLUDES
|
|
5419
5797
|
};
|
|
5420
5798
|
const TASKFILE = {
|
|
5421
5799
|
commandKeys: TASKFILE_COMMAND_KEYS,
|
|
@@ -5423,7 +5801,9 @@ const TASKFILE = {
|
|
|
5423
5801
|
...PLAIN,
|
|
5424
5802
|
keys: /* @__PURE__ */ new Set([ENV_KEY, VARS_KEY]),
|
|
5425
5803
|
reference: /\{\{-?[ \t]*\.([A-Za-z_][A-Za-z0-9_]*)[ \t]*-?\}\}/g
|
|
5426
|
-
}
|
|
5804
|
+
},
|
|
5805
|
+
parameters: NO_PARAMETERS,
|
|
5806
|
+
includes: TASKFILE_INCLUDES
|
|
5427
5807
|
};
|
|
5428
5808
|
const AZURE_NAME_SEPARATOR_RE = /\./g;
|
|
5429
5809
|
const AZURE_SHELL_SEPARATOR = "_";
|
|
@@ -5435,49 +5815,84 @@ const AZURE_PIPELINES_FILE = {
|
|
|
5435
5815
|
hasNamedItems: true,
|
|
5436
5816
|
reference: /\$\(([A-Za-z_][A-Za-z0-9_.]*)\)|\$\{\{[ \t]*variables\.([A-Za-z_][A-Za-z0-9_.]*)[ \t]*\}\}/g,
|
|
5437
5817
|
shellName: (name, key) => key === VARIABLES_KEY ? name.replace(AZURE_NAME_SEPARATOR_RE, AZURE_SHELL_SEPARATOR).toUpperCase() : name
|
|
5438
|
-
}
|
|
5818
|
+
},
|
|
5819
|
+
parameters: AZURE_PARAMETERS,
|
|
5820
|
+
includes: AZURE_TEMPLATES
|
|
5439
5821
|
};
|
|
5440
|
-
const
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
const
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
while (isInItem(strings[first - 1])) {
|
|
5447
|
-
first -= 1;
|
|
5822
|
+
const ENV_EXPRESSION_RE = /\$\{\{[ \t]*env\.([A-Za-z_][A-Za-z0-9_]*)[ \t]*\}\}/g;
|
|
5823
|
+
const asShellVariable = (reference, name) => `$${name}`.padEnd(reference.length, " ");
|
|
5824
|
+
function withToolReferences(text, { environment, names }) {
|
|
5825
|
+
const { reference, shellName } = environment;
|
|
5826
|
+
if (reference === void 0) {
|
|
5827
|
+
return text;
|
|
5448
5828
|
}
|
|
5449
|
-
|
|
5450
|
-
|
|
5829
|
+
return text.replace(reference, (written, ...groups) => {
|
|
5830
|
+
const group = groups.find((part) => typeof part === "string") ?? "";
|
|
5831
|
+
const name = shellName(group, VARIABLES_KEY);
|
|
5832
|
+
return names.has(name) ? asShellVariable(written, name) : written;
|
|
5833
|
+
});
|
|
5834
|
+
}
|
|
5835
|
+
const DOLLAR_ESCAPE_RE = /\$\$([A-Za-z_][A-Za-z0-9_]*|\{[^}]*\})/g;
|
|
5836
|
+
const withoutDollarEscapes = (text) => text.replace(
|
|
5837
|
+
DOLLAR_ESCAPE_RE,
|
|
5838
|
+
(written, name) => `$${name}`.padEnd(written.length, " ")
|
|
5839
|
+
);
|
|
5840
|
+
function withVariableReferences(text, references) {
|
|
5841
|
+
const parameters = references?.parameters.asExpressions(text) ?? text;
|
|
5842
|
+
const expressions = parameters.replace(ENV_EXPRESSION_RE, asShellVariable);
|
|
5843
|
+
if (references === void 0) {
|
|
5844
|
+
return expressions;
|
|
5451
5845
|
}
|
|
5452
|
-
|
|
5846
|
+
const escaped = references.environment.hasDollarEscapes ? withoutDollarEscapes(expressions) : expressions;
|
|
5847
|
+
return withToolReferences(escaped, references);
|
|
5453
5848
|
}
|
|
5849
|
+
|
|
5850
|
+
const VALUE_KEY = "value";
|
|
5851
|
+
const OPTIONS_KEY = "options";
|
|
5852
|
+
const LIST_ITEM_RE = /^([A-Za-z_][A-Za-z0-9_]*)=/;
|
|
5853
|
+
const PATH_TAIL = [-1, -2, -3, -4];
|
|
5454
5854
|
const isNamedItemValue = (value, keys) => value.path.at(-1) === VALUE_KEY && typeof value.path.at(-2) === "number" && keys.has(String(value.path.at(-3)));
|
|
5455
|
-
function
|
|
5855
|
+
function entryPlace(strings, index, { keys, hasValueMaps, hasListItems, hasNamedItems }) {
|
|
5456
5856
|
const value = strings[index];
|
|
5457
|
-
const
|
|
5458
|
-
const
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
return named(last, owner);
|
|
5857
|
+
const [last, owner, outer, optionOf] = PATH_TAIL.map((at) => value.path.at(at));
|
|
5858
|
+
const isKey = (part) => keys.has(String(part));
|
|
5859
|
+
if (typeof last === "string" && isKey(owner)) {
|
|
5860
|
+
return { name: last, key: owner };
|
|
5462
5861
|
}
|
|
5463
|
-
if (hasValueMaps && last === VALUE_KEY && typeof owner === "string" &&
|
|
5464
|
-
return
|
|
5862
|
+
if (hasValueMaps && last === VALUE_KEY && typeof owner === "string" && isKey(outer)) {
|
|
5863
|
+
return { name: owner, key: outer };
|
|
5864
|
+
}
|
|
5865
|
+
const isOption = typeof last === "number" && owner === OPTIONS_KEY && typeof outer === "string";
|
|
5866
|
+
if (hasValueMaps && isOption && isKey(optionOf)) {
|
|
5867
|
+
return { name: outer, key: optionOf };
|
|
5465
5868
|
}
|
|
5466
5869
|
if (hasNamedItems && isNamedItemValue(value, keys)) {
|
|
5467
|
-
return
|
|
5870
|
+
return { name: itemName(strings, index), key: String(outer) };
|
|
5468
5871
|
}
|
|
5469
|
-
const
|
|
5470
|
-
const name =
|
|
5471
|
-
|
|
5872
|
+
const isItem = hasListItems && typeof last === "number" && isKey(owner);
|
|
5873
|
+
const name = isItem ? LIST_ITEM_RE.exec(value.value)?.[1] : void 0;
|
|
5874
|
+
const head = (name?.length ?? 0) + 1;
|
|
5875
|
+
return name === void 0 ? void 0 : { name, key: String(owner), head };
|
|
5876
|
+
}
|
|
5877
|
+
function scopeOf(path, key) {
|
|
5878
|
+
const owner = path.slice(0, path.lastIndexOf(key));
|
|
5879
|
+
return owner.slice(0, owner.findLastIndex((part) => typeof part === "number") + 1);
|
|
5472
5880
|
}
|
|
5473
5881
|
function environmentEntries(strings, environment) {
|
|
5474
5882
|
return new Map(
|
|
5475
5883
|
strings.flatMap((value, index) => {
|
|
5476
|
-
const
|
|
5477
|
-
|
|
5884
|
+
const place = entryPlace(strings, index, environment);
|
|
5885
|
+
if (place?.name === void 0) {
|
|
5886
|
+
return [];
|
|
5887
|
+
}
|
|
5888
|
+
const name = environment.shellName(place.name, place.key);
|
|
5889
|
+
const head = place.head ?? 0;
|
|
5890
|
+
const scope = scopeOf(value.path, place.key);
|
|
5891
|
+
return [[value, { name, head, scope }]];
|
|
5478
5892
|
})
|
|
5479
5893
|
);
|
|
5480
5894
|
}
|
|
5895
|
+
const isInScope = (path, entry) => entry.scope.every((part, at) => path[at] === part);
|
|
5481
5896
|
const ENV_ITEM_KEYS = /* @__PURE__ */ new Set([ENV_KEY]);
|
|
5482
5897
|
function environmentItemSteps(strings, entries, locate) {
|
|
5483
5898
|
return strings.filter((value) => isNamedItemValue(value, ENV_ITEM_KEYS) && !entries.has(value)).filter((value) => namesOriginalPackage(value.value)).map((value) => ({
|
|
@@ -5486,43 +5901,35 @@ function environmentItemSteps(strings, entries, locate) {
|
|
|
5486
5901
|
word: value.value
|
|
5487
5902
|
}));
|
|
5488
5903
|
}
|
|
5489
|
-
|
|
5490
|
-
const
|
|
5491
|
-
function
|
|
5492
|
-
const
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
}
|
|
5496
|
-
return text.replace(reference, (written, ...groups) => {
|
|
5497
|
-
const group = groups.find((part) => typeof part === "string") ?? "";
|
|
5498
|
-
const name = shellName(group, VARIABLES_KEY);
|
|
5499
|
-
return names.has(name) ? asShellVariable(written, name) : written;
|
|
5500
|
-
});
|
|
5501
|
-
}
|
|
5502
|
-
function withVariableReferences(text, references) {
|
|
5503
|
-
const expressions = text.replace(ENV_EXPRESSION_RE, asShellVariable);
|
|
5504
|
-
return references === void 0 ? expressions : withToolReferences(expressions, references);
|
|
5904
|
+
|
|
5905
|
+
const FOLDED_LINE_BREAK_RE = /(?<=\S[^\S\n]*)\n(?=[^\S\n]*\S)/g;
|
|
5906
|
+
function shellText(text, value, references) {
|
|
5907
|
+
const slice = text.slice(value.content.start, value.content.end);
|
|
5908
|
+
const unfolded = value.isFolded ? slice.replace(FOLDED_LINE_BREAK_RE, " ") : slice;
|
|
5909
|
+
return withVariableReferences(unfolded, references);
|
|
5505
5910
|
}
|
|
5506
5911
|
|
|
5507
|
-
function
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
)
|
|
5912
|
+
function scopedVariables({
|
|
5913
|
+
text,
|
|
5914
|
+
entries,
|
|
5915
|
+
inputs,
|
|
5916
|
+
references
|
|
5917
|
+
}) {
|
|
5918
|
+
const definitions = [...entries].map(([value, entry]) => {
|
|
5919
|
+
const shell = value.isEscaped ? withVariableReferences(value.value, references) : shellText(text, value, references);
|
|
5920
|
+
return { entry, name: entry.name, value: shell.slice(entry.head) };
|
|
5921
|
+
});
|
|
5922
|
+
return (value) => {
|
|
5923
|
+
const reaching = definitions.filter(({ entry }) => isInScope(value.path, entry));
|
|
5924
|
+
return withInputDefaults(shellVariables(reaching), inputs);
|
|
5925
|
+
};
|
|
5514
5926
|
}
|
|
5927
|
+
|
|
5515
5928
|
const DEPENDABOT_NAME_KEYS = /* @__PURE__ */ new Set([
|
|
5516
5929
|
"dependency-name",
|
|
5517
5930
|
"patterns",
|
|
5518
5931
|
"exclude-patterns"
|
|
5519
5932
|
]);
|
|
5520
|
-
const FOLDED_LINE_BREAK_RE = /(?<=\S[^\S\n]*)\n(?=[^\S\n]*\S)/g;
|
|
5521
|
-
function shellText(text, value, references) {
|
|
5522
|
-
const slice = text.slice(value.content.start, value.content.end);
|
|
5523
|
-
const unfolded = value.isFolded ? slice.replace(FOLDED_LINE_BREAK_RE, " ") : slice;
|
|
5524
|
-
return withVariableReferences(unfolded, references);
|
|
5525
|
-
}
|
|
5526
5933
|
const LEADING_SPACES_RE = /^ */;
|
|
5527
5934
|
function blockIndent(shell) {
|
|
5528
5935
|
const lines = shell.split("\n").slice(1).filter((line) => line.trim() !== "");
|
|
@@ -5538,33 +5945,32 @@ function oncePerPlace(strings) {
|
|
|
5538
5945
|
});
|
|
5539
5946
|
}
|
|
5540
5947
|
const valuesOf = (strings, keys) => oncePerPlace(strings.filter((string) => keys.has(ownerKey(string.path) ?? "")));
|
|
5541
|
-
const EXEC_FORM_KEYS = /* @__PURE__ */ new Set(["command", "entrypoint"]);
|
|
5542
|
-
const isExecFormItem = (value) => typeof value.path.at(-1) === "number" && EXEC_FORM_KEYS.has(String(value.path.at(-2)));
|
|
5543
|
-
const listOf = (item) => item.path.slice(0, -1).join(".");
|
|
5544
|
-
const isNextItem = (previous, item) => listOf(previous) === listOf(item) && Number(item.path.at(-1)) > Number(previous.path.at(-1));
|
|
5545
|
-
function execFormCommands(text, items) {
|
|
5546
|
-
const commands = [];
|
|
5547
|
-
let previous;
|
|
5548
|
-
let command = [];
|
|
5549
|
-
for (const item of items) {
|
|
5550
|
-
if (previous === void 0 || !isNextItem(previous, item)) {
|
|
5551
|
-
command = [];
|
|
5552
|
-
commands.push(command);
|
|
5553
|
-
}
|
|
5554
|
-
const { start, end } = item.content;
|
|
5555
|
-
command.push({ start, end, value: item.value, raw: text.slice(start, end) });
|
|
5556
|
-
previous = item;
|
|
5557
|
-
}
|
|
5558
|
-
return commands;
|
|
5559
|
-
}
|
|
5560
5948
|
function escapedValueFindings(value, encode, { locate, variables, references }) {
|
|
5561
|
-
const
|
|
5562
|
-
const
|
|
5949
|
+
const read = withVariableReferences(value.value, references);
|
|
5950
|
+
const commands = shellCommands(read);
|
|
5951
|
+
const findings = commandWordFindings(commands, () => locate(value.start), variables);
|
|
5952
|
+
const found = withWrittenWords(findings, commands, { read, written: value.value });
|
|
5563
5953
|
const migrated = applyTextEdits(value.value, found.edits);
|
|
5564
5954
|
const isChanged = migrated !== value.value;
|
|
5565
5955
|
const edits = isChanged ? [{ start: value.start, end: value.end, text: encode(migrated) }] : [];
|
|
5566
5956
|
return { ...found, edits };
|
|
5567
5957
|
}
|
|
5958
|
+
const PADDING = " ";
|
|
5959
|
+
function writtenWord({ read, written }, word) {
|
|
5960
|
+
let blanks = word.end;
|
|
5961
|
+
while (read[blanks] === PADDING) {
|
|
5962
|
+
blanks += 1;
|
|
5963
|
+
}
|
|
5964
|
+
const covered = written.slice(word.end, blanks).trimEnd();
|
|
5965
|
+
return written.slice(word.start, word.end + covered.length);
|
|
5966
|
+
}
|
|
5967
|
+
function withWrittenWords(found, commands, value) {
|
|
5968
|
+
const words = new Map(commands.flat().map((word) => [word.raw, writtenWord(value, word)]));
|
|
5969
|
+
const manualSteps = found.manualSteps.map(
|
|
5970
|
+
(step) => "variable" in step ? { ...step, variable: words.get(step.variable) ?? step.variable } : step
|
|
5971
|
+
);
|
|
5972
|
+
return { ...found, manualSteps };
|
|
5973
|
+
}
|
|
5568
5974
|
function valueFindings(value, context) {
|
|
5569
5975
|
if (value.isEscaped && value.encode !== void 0) {
|
|
5570
5976
|
return escapedValueFindings(value, value.encode, context);
|
|
@@ -5573,7 +5979,9 @@ function valueFindings(value, context) {
|
|
|
5573
5979
|
const { start } = value.content;
|
|
5574
5980
|
const shell = shellText(text, value, references);
|
|
5575
5981
|
const commands = shellCommands(shell, blockIndent(shell));
|
|
5576
|
-
const
|
|
5982
|
+
const findings = commandWordFindings(commands, (offset) => locate(start + offset), variables);
|
|
5983
|
+
const written = text.slice(start, value.content.end);
|
|
5984
|
+
const found = withWrittenWords(findings, commands, { read: shell, written });
|
|
5577
5985
|
return { ...found, edits: shiftedEdits(found.edits, start) };
|
|
5578
5986
|
}
|
|
5579
5987
|
const shiftedEdits = (edits, offset) => edits.map((edit) => ({ ...edit, start: edit.start + offset, end: edit.end + offset }));
|
|
@@ -5587,27 +5995,28 @@ function appliedFindings(text, found) {
|
|
|
5587
5995
|
manualSteps: found.flatMap((findings) => findings.manualSteps)
|
|
5588
5996
|
};
|
|
5589
5997
|
}
|
|
5590
|
-
function
|
|
5591
|
-
const names = new Set([...entries.values()].map((entry) => entry.name));
|
|
5592
|
-
const references = { environment, names };
|
|
5593
|
-
const fileVariables = environmentVariables(text, entries, references);
|
|
5594
|
-
return { text, locate, variables: withInputDefaults(fileVariables, strings), references };
|
|
5595
|
-
}
|
|
5596
|
-
function migrateYamlCommands(text, file, strings, { commandKeys, environment } = DEFAULT_YAML_FILE) {
|
|
5998
|
+
function migrateYamlCommands(text, file, strings, { commandKeys, environment, parameters } = DEFAULT_YAML_FILE) {
|
|
5597
5999
|
const lineOf = lineLocator(text);
|
|
5598
6000
|
const locate = (offset) => `${file}:${lineOf(offset)}`;
|
|
5599
6001
|
const shellOf = stepShells(strings);
|
|
5600
6002
|
const values = valuesOf(strings, commandKeys).filter((value) => shellOf(value) === void 0);
|
|
5601
|
-
const commandValues = new Set(values.filter((value) => !
|
|
6003
|
+
const commandValues = new Set(values.filter((value) => !isContainerListItem(value)));
|
|
6004
|
+
const { findings, scripts } = containerCommands(text, strings, locate);
|
|
5602
6005
|
const entries = environmentEntries(strings, environment);
|
|
5603
|
-
const
|
|
5604
|
-
const
|
|
5605
|
-
|
|
5606
|
-
);
|
|
5607
|
-
const
|
|
6006
|
+
const defaults = parameterDefaults(strings, parameters);
|
|
6007
|
+
const isShellText = (value) => commandValues.has(value) || scripts.has(value) || entries.has(value) || defaults.has(value);
|
|
6008
|
+
const shellValues = oncePerPlace(strings.filter(isShellText));
|
|
6009
|
+
const names = new Set([...entries.values()].map((entry) => entry.name));
|
|
6010
|
+
const references = { environment, names, parameters };
|
|
6011
|
+
const inputs = inputValues(defaults);
|
|
6012
|
+
const variablesAt = scopedVariables({ text, entries, inputs, references });
|
|
6013
|
+
const contextOf = (value) => ({
|
|
6014
|
+
...{ text, locate, references },
|
|
6015
|
+
variables: variablesAt(value)
|
|
6016
|
+
});
|
|
5608
6017
|
return appliedFindings(text, [
|
|
5609
|
-
...shellValues.map((value) => valueFindings(value,
|
|
5610
|
-
|
|
6018
|
+
...shellValues.map((value) => valueFindings(value, contextOf(value))),
|
|
6019
|
+
...findings,
|
|
5611
6020
|
otherShellFindings(valuesOf(strings, commandKeys), shellOf, locate),
|
|
5612
6021
|
{ edits: [], changes: [], manualSteps: environmentItemSteps(strings, entries, locate) }
|
|
5613
6022
|
]);
|
|
@@ -5760,6 +6169,25 @@ function migrateWorkspaceCatalogs(text, read, target, file) {
|
|
|
5760
6169
|
return { text: applyTextEdits(text, edits), changes, manualSteps };
|
|
5761
6170
|
}
|
|
5762
6171
|
|
|
6172
|
+
function generatorVariables(text, strings, { environment }) {
|
|
6173
|
+
const entries = environmentEntries(strings, environment);
|
|
6174
|
+
return [...entries].flatMap(([value, entry]) => {
|
|
6175
|
+
const shell = value.isEscaped ? value.value : shellText(text, value);
|
|
6176
|
+
return shellCommands(shell.slice(entry.head)).some(runsGenerator) ? [entry.name] : [];
|
|
6177
|
+
});
|
|
6178
|
+
}
|
|
6179
|
+
const NAME_END = "(?![A-Za-z0-9_])";
|
|
6180
|
+
const SPECIAL_CHARACTERS_RE$1 = /[.*+?^${}()|[\]\\]/g;
|
|
6181
|
+
function usesVariable(text, names) {
|
|
6182
|
+
if (names.size === 0) {
|
|
6183
|
+
return false;
|
|
6184
|
+
}
|
|
6185
|
+
const alternatives = [...names].map((name2) => name2.replace(SPECIAL_CHARACTERS_RE$1, "\\$&"));
|
|
6186
|
+
const name = `(?:${alternatives.join("|")})`;
|
|
6187
|
+
const expansion = `\\$(?:\\{|\\(|env:)?${name}${NAME_END}|%${name}%`;
|
|
6188
|
+
return new RegExp(expansion).test(text);
|
|
6189
|
+
}
|
|
6190
|
+
|
|
5763
6191
|
const withSteps = (migration, steps) => ({
|
|
5764
6192
|
...migration,
|
|
5765
6193
|
manualSteps: [...migration.manualSteps, ...steps]
|
|
@@ -5784,7 +6212,7 @@ const stringsStep = (migrate) => (text, read) => read.kind === "unreadable" ? un
|
|
|
5784
6212
|
const usedStringsStep = (migrate) => (text, read) => read.kind === "unreadable" ? unreadableConfig(text, read.offset) : migrate(text, usedDocumentStrings(read.documents));
|
|
5785
6213
|
const jsonConfig = (steps) => (text, path, context) => migrateConfig(text, (current) => context.readers.json.read(current), steps(context, path));
|
|
5786
6214
|
const yamlConfig = (steps) => (text, path, context) => migrateConfig(text, (current) => context.readers.yaml.read(current), steps(context, path));
|
|
5787
|
-
const whenNamed = (migrate) => (text, path, context) => namesOriginalPackage(text) ? migrate(text, path, context) : unchanged(text);
|
|
6215
|
+
const whenNamed = (migrate) => (text, path, context) => namesOriginalPackage(text) || usesVariable(text, context.yamlReach.generatorVariables) ? migrate(text, path, context) : unchanged(text);
|
|
5788
6216
|
|
|
5789
6217
|
const SHELL_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zsh"]);
|
|
5790
6218
|
const MAKEFILE_EXTENSION = ".mk";
|
|
@@ -5909,15 +6337,18 @@ const CI_ENVIRONMENT_FILES = /* @__PURE__ */ new Set([
|
|
|
5909
6337
|
".woodpecker.yml",
|
|
5910
6338
|
".woodpecker.yaml"
|
|
5911
6339
|
]);
|
|
5912
|
-
const
|
|
6340
|
+
const CIRCLECI_FOLDER = ".circleci/";
|
|
6341
|
+
const WOODPECKER_FOLDER = ".woodpecker/";
|
|
5913
6342
|
const COMPOSE_FILE_RE = /^(?:docker-)?compose(?:\.[^/]+)?\.ya?ml$/;
|
|
5914
6343
|
function yamlCommandFileFor(path) {
|
|
5915
6344
|
const name = baseName(path);
|
|
5916
6345
|
if (GITLAB_FILES.has(name) || isInFolder(path, GITLAB_FOLDER)) {
|
|
5917
6346
|
return GITLAB_CI_FILE;
|
|
5918
6347
|
}
|
|
5919
|
-
|
|
5920
|
-
|
|
6348
|
+
if (isInFolder(path, CIRCLECI_FOLDER)) {
|
|
6349
|
+
return CIRCLECI_FILE;
|
|
6350
|
+
}
|
|
6351
|
+
if (CI_ENVIRONMENT_FILES.has(name) || isInFolder(path, WOODPECKER_FOLDER)) {
|
|
5921
6352
|
return CI_ENVIRONMENT_FILE;
|
|
5922
6353
|
}
|
|
5923
6354
|
if (isAzurePipelinesFile(path)) {
|
|
@@ -5926,6 +6357,58 @@ function yamlCommandFileFor(path) {
|
|
|
5926
6357
|
return COMPOSE_FILE_RE.test(name) ? COMPOSE_FILE : DEFAULT_YAML_FILE;
|
|
5927
6358
|
}
|
|
5928
6359
|
|
|
6360
|
+
const yamlKindOf = (reach, path) => reach.kinds.get(path) ?? yamlCommandFileFor(path);
|
|
6361
|
+
const namedKindOf = (path) => TASKFILE_NAMES.has(baseName(path)) ? TASKFILE : yamlCommandFileFor(path);
|
|
6362
|
+
async function textOf$1(path, { files }) {
|
|
6363
|
+
const read = await files.read(path);
|
|
6364
|
+
return read.kind === "read" ? read.text : void 0;
|
|
6365
|
+
}
|
|
6366
|
+
function stringsOf(text, { readers }) {
|
|
6367
|
+
const parsed = text === void 0 ? void 0 : readers.yaml.read(text);
|
|
6368
|
+
return parsed?.kind === "read" ? usedDocumentStrings(parsed.documents) : [];
|
|
6369
|
+
}
|
|
6370
|
+
const ANY_FOLDERS_WILDCARD = "**";
|
|
6371
|
+
const WILDCARD_RE = /\*\*?/g;
|
|
6372
|
+
const SPECIAL_CHARACTERS_RE = /[.+?^${}()|[\]\\]/g;
|
|
6373
|
+
const ANY_FOLDERS = ".*";
|
|
6374
|
+
const ANY_NAME = "[^/]*";
|
|
6375
|
+
function matchingPaths(pattern, listed) {
|
|
6376
|
+
const source = pattern.replace(SPECIAL_CHARACTERS_RE, "\\$&").replace(WILDCARD_RE, (star) => star === ANY_FOLDERS_WILDCARD ? ANY_FOLDERS : ANY_NAME);
|
|
6377
|
+
const matches = new RegExp(`^${source}$`);
|
|
6378
|
+
return listed.filter((path) => matches.test(path));
|
|
6379
|
+
}
|
|
6380
|
+
async function includedKinds(paths, dependencies) {
|
|
6381
|
+
const kinds = /* @__PURE__ */ new Map();
|
|
6382
|
+
const pending = paths.map((path) => ({ path, kind: namedKindOf(path) })).filter(({ kind }) => kind.includes !== NO_INCLUDES);
|
|
6383
|
+
for (let next = pending.pop(); next !== void 0; next = pending.pop()) {
|
|
6384
|
+
const strings = stringsOf(await textOf$1(next.path, dependencies), dependencies);
|
|
6385
|
+
const included = includedPaths(next.path, strings, next.kind.includes);
|
|
6386
|
+
for (const path of included.flatMap((pattern) => matchingPaths(pattern, paths))) {
|
|
6387
|
+
if (!kinds.has(path) && namedKindOf(path) === DEFAULT_YAML_FILE) {
|
|
6388
|
+
kinds.set(path, next.kind);
|
|
6389
|
+
pending.push({ path, kind: next.kind });
|
|
6390
|
+
}
|
|
6391
|
+
}
|
|
6392
|
+
}
|
|
6393
|
+
return kinds;
|
|
6394
|
+
}
|
|
6395
|
+
const isVariableSource = (path, text) => namesOriginalPackage(text) && (isCiConfigFile(path) || !mayBeApiDescription(text));
|
|
6396
|
+
async function planYamlReach(paths, dependencies) {
|
|
6397
|
+
const yamlPaths = paths.filter((path) => YAML_EXTENSIONS.has(extensionOf(path)));
|
|
6398
|
+
const kinds = await includedKinds(yamlPaths, dependencies);
|
|
6399
|
+
const names = /* @__PURE__ */ new Set();
|
|
6400
|
+
for (const path of yamlPaths) {
|
|
6401
|
+
const text = await textOf$1(path, dependencies);
|
|
6402
|
+
if (text !== void 0 && isVariableSource(path, text)) {
|
|
6403
|
+
const kind = kinds.get(path) ?? namedKindOf(path);
|
|
6404
|
+
for (const name of generatorVariables(text, stringsOf(text, dependencies), kind)) {
|
|
6405
|
+
names.add(name);
|
|
6406
|
+
}
|
|
6407
|
+
}
|
|
6408
|
+
}
|
|
6409
|
+
return { kinds, generatorVariables: names };
|
|
6410
|
+
}
|
|
6411
|
+
|
|
5929
6412
|
const isHuskyHook = (path) => (path.startsWith(HUSKY_FOLDER) || path.includes(`/${HUSKY_FOLDER}`)) && !path.includes(HUSKY_INTERNALS);
|
|
5930
6413
|
const isDependabotConfig = (path) => [...DEPENDABOT_FILES].some((file) => path === file || path.endsWith(`/${file}`));
|
|
5931
6414
|
function migrateSource(text, path, context) {
|
|
@@ -5982,9 +6465,13 @@ const COMMAND_CONFIG_KINDS = [
|
|
|
5982
6465
|
)
|
|
5983
6466
|
}
|
|
5984
6467
|
];
|
|
5985
|
-
const yamlCommandsStep = (path,
|
|
5986
|
-
|
|
5987
|
-
|
|
6468
|
+
const yamlCommandsStep = (path, { apiDescriptionParts, yamlReach }) => (text, read) => {
|
|
6469
|
+
const isCiFile = isCiConfigFile(path) || yamlReach.kinds.has(path);
|
|
6470
|
+
const isApi = !isCiFile && read.kind === "read" && isApiDescription(read.documents);
|
|
6471
|
+
return apiDescriptionParts.has(path) || isApi ? unchanged(text) : usedStringsStep(
|
|
6472
|
+
(current, strings) => migrateYamlCommands(current, path, strings, yamlKindOf(yamlReach, path))
|
|
6473
|
+
)(text, read);
|
|
6474
|
+
};
|
|
5988
6475
|
const manifestTarget = ({ version, catalogs, aliases }, path) => ({
|
|
5989
6476
|
version,
|
|
5990
6477
|
catalogs,
|
|
@@ -6060,11 +6547,7 @@ const FILE_KINDS = [
|
|
|
6060
6547
|
},
|
|
6061
6548
|
{
|
|
6062
6549
|
matches: (path) => YAML_EXTENSIONS.has(extensionOf(path)),
|
|
6063
|
-
migrate: whenNamed(
|
|
6064
|
-
yamlConfig((context, path) => [
|
|
6065
|
-
yamlCommandsStep(path, context.apiDescriptionParts.has(path))
|
|
6066
|
-
])
|
|
6067
|
-
)
|
|
6550
|
+
migrate: whenNamed(yamlConfig((context, path) => [yamlCommandsStep(path, context)]))
|
|
6068
6551
|
},
|
|
6069
6552
|
{
|
|
6070
6553
|
matches: (path) => DOCKERFILE_NAMES.has(baseName(path)),
|
|
@@ -6226,9 +6709,10 @@ async function planProjectTarget(paths, dependencies, version) {
|
|
|
6226
6709
|
});
|
|
6227
6710
|
const declarations = withNamedImportMaps(manifests, importMaps);
|
|
6228
6711
|
const parts = await apiDescriptionParts(paths, dependencies);
|
|
6712
|
+
const yamlReach = await planYamlReach(paths, dependencies);
|
|
6229
6713
|
return {
|
|
6230
6714
|
...{ version, catalogs, manifests: declarations, aliases, importMaps },
|
|
6231
|
-
apiDescriptionParts: parts
|
|
6715
|
+
...{ apiDescriptionParts: parts, yamlReach }
|
|
6232
6716
|
};
|
|
6233
6717
|
}
|
|
6234
6718
|
|
|
@@ -6252,9 +6736,9 @@ async function planFile(path, dependencies, target) {
|
|
|
6252
6736
|
return read;
|
|
6253
6737
|
}
|
|
6254
6738
|
const { rewriter, scanner, readers } = dependencies;
|
|
6255
|
-
const { version, catalogs, manifests, aliases, apiDescriptionParts } = target;
|
|
6739
|
+
const { version, catalogs, manifests, aliases, apiDescriptionParts, yamlReach } = target;
|
|
6256
6740
|
const context = {
|
|
6257
|
-
...{ version, catalogs, manifests, aliases, apiDescriptionParts },
|
|
6741
|
+
...{ version, catalogs, manifests, aliases, apiDescriptionParts, yamlReach },
|
|
6258
6742
|
...{ rewriter, scanner, readers }
|
|
6259
6743
|
};
|
|
6260
6744
|
const attempt = attemptMigration(() => migrate(read.text, path, context));
|