rulesync 36.0.0 → 36.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.cjs +100 -30
- package/dist/cli/index.js +100 -30
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -1691,7 +1691,8 @@ async function listDirectoryRecursive(params) {
|
|
|
1691
1691
|
else if (entry.type === "dir") directories.push(entry);
|
|
1692
1692
|
else dropped = true;
|
|
1693
1693
|
if (dropped) onIncompleteDirectory?.(path);
|
|
1694
|
-
const
|
|
1694
|
+
const failures = [];
|
|
1695
|
+
const settled = await Promise.allSettled(directories.map((dir) => listDirectoryRecursive({
|
|
1695
1696
|
client,
|
|
1696
1697
|
owner,
|
|
1697
1698
|
repo,
|
|
@@ -1700,7 +1701,12 @@ async function listDirectoryRecursive(params) {
|
|
|
1700
1701
|
depth: depth + 1,
|
|
1701
1702
|
semaphore,
|
|
1702
1703
|
onIncompleteDirectory
|
|
1704
|
+
}).catch((error) => {
|
|
1705
|
+
failures.push(error);
|
|
1706
|
+
throw error;
|
|
1703
1707
|
})));
|
|
1708
|
+
if (failures.length > 0) throw failures[0];
|
|
1709
|
+
const subResults = settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
1704
1710
|
return [...files, ...subResults.flat()];
|
|
1705
1711
|
}
|
|
1706
1712
|
/**
|
|
@@ -2411,6 +2417,12 @@ async function resolveAndFetchSources(params) {
|
|
|
2411
2417
|
failedSourceCount
|
|
2412
2418
|
};
|
|
2413
2419
|
}
|
|
2420
|
+
/**
|
|
2421
|
+
* The claim of a source the prefetch does not list -- a git or npm transport
|
|
2422
|
+
* source -- whose selection is a wildcard: it may take any
|
|
2423
|
+
* name, so later sources download nothing a name decides.
|
|
2424
|
+
*/
|
|
2425
|
+
const ANY_NAME = Symbol("any name");
|
|
2414
2426
|
function createNameClaim() {
|
|
2415
2427
|
let settle = () => {};
|
|
2416
2428
|
return {
|
|
@@ -2425,7 +2437,12 @@ function createClaimSlot(params) {
|
|
|
2425
2437
|
return {
|
|
2426
2438
|
earlier: async () => {
|
|
2427
2439
|
const claimed = await Promise.all(earlier.map((claim) => claim.names));
|
|
2428
|
-
|
|
2440
|
+
const mayTakeAny = claimed.includes(ANY_NAME);
|
|
2441
|
+
const names = /* @__PURE__ */ new Set([...reserved, ...claimed.flatMap((claim) => claim === ANY_NAME ? [] : claim)]);
|
|
2442
|
+
return {
|
|
2443
|
+
names,
|
|
2444
|
+
has: (name) => mayTakeAny || names.has(name)
|
|
2445
|
+
};
|
|
2429
2446
|
},
|
|
2430
2447
|
settle: own.settle
|
|
2431
2448
|
};
|
|
@@ -2450,13 +2467,30 @@ async function prefetchGithubSources(params) {
|
|
|
2450
2467
|
...rest,
|
|
2451
2468
|
semaphore: new es_toolkit_promise.Semaphore(10)
|
|
2452
2469
|
};
|
|
2453
|
-
const items = sources.filter((sourceEntry) =>
|
|
2470
|
+
const items = sources.filter((sourceEntry) => !hasEmptySelection(sourceEntry)).map((sourceEntry) => ({
|
|
2454
2471
|
sourceEntry,
|
|
2472
|
+
listedThroughApi: isListedThroughGithubApi(sourceEntry),
|
|
2455
2473
|
skills: createNameClaim(),
|
|
2456
2474
|
rules: createNameClaim()
|
|
2457
2475
|
}));
|
|
2476
|
+
for (const item of items.filter((candidate) => !candidate.listedThroughApi)) {
|
|
2477
|
+
if (isGitlabSource(item.sourceEntry)) {
|
|
2478
|
+
item.skills.settle([]);
|
|
2479
|
+
item.rules.settle([]);
|
|
2480
|
+
continue;
|
|
2481
|
+
}
|
|
2482
|
+
const filters = getSourceFilters(item.sourceEntry);
|
|
2483
|
+
item.skills.settle(getSelectionClaim({
|
|
2484
|
+
selection: filters.skills,
|
|
2485
|
+
normalize: (name) => name
|
|
2486
|
+
}));
|
|
2487
|
+
item.rules.settle(getSelectionClaim({
|
|
2488
|
+
selection: filters.rules,
|
|
2489
|
+
normalize: normalizeRuleFilterName
|
|
2490
|
+
}));
|
|
2491
|
+
}
|
|
2458
2492
|
await require_import.mapWithConcurrency({
|
|
2459
|
-
items,
|
|
2493
|
+
items: items.filter((item) => item.listedThroughApi),
|
|
2460
2494
|
limit: 4,
|
|
2461
2495
|
mapper: async (item) => {
|
|
2462
2496
|
const earlier = items.slice(0, items.indexOf(item));
|
|
@@ -2485,14 +2519,36 @@ async function prefetchGithubSources(params) {
|
|
|
2485
2519
|
}
|
|
2486
2520
|
});
|
|
2487
2521
|
}
|
|
2522
|
+
/** Whether the prefetch lists and downloads this source through the GitHub API. */
|
|
2523
|
+
function isListedThroughGithubApi(sourceEntry) {
|
|
2524
|
+
if ((sourceEntry.transport ?? "github") !== "github") return false;
|
|
2525
|
+
try {
|
|
2526
|
+
return parseSource(sourceEntry.source).provider !== "gitlab";
|
|
2527
|
+
} catch {
|
|
2528
|
+
return true;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
/** Whether this is a GitLab source, which the serial pass does not support yet. */
|
|
2532
|
+
function isGitlabSource(sourceEntry) {
|
|
2533
|
+
if ((sourceEntry.transport ?? "github") !== "github") return false;
|
|
2534
|
+
try {
|
|
2535
|
+
return parseSource(sourceEntry.source).provider === "gitlab";
|
|
2536
|
+
} catch {
|
|
2537
|
+
return false;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
/** What a source the prefetch does not list may take, judged by its selection alone. */
|
|
2541
|
+
function getSelectionClaim(params) {
|
|
2542
|
+
const { selection, normalize } = params;
|
|
2543
|
+
if (selection === void 0) return [];
|
|
2544
|
+
return selection.includes("*") ? ANY_NAME : selection.map(normalize);
|
|
2545
|
+
}
|
|
2488
2546
|
async function prefetchGithubSource(params) {
|
|
2489
2547
|
const { sourceEntry, lock, context, skillClaim, ruleClaim } = params;
|
|
2490
2548
|
const parsedFromSource = parseSource(sourceEntry.source);
|
|
2491
|
-
if (parsedFromSource.provider === "gitlab") return;
|
|
2492
2549
|
const parsed = {
|
|
2493
2550
|
...parsedFromSource,
|
|
2494
|
-
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
2495
|
-
path: sourceEntry.path ?? parsedFromSource.path
|
|
2551
|
+
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
2496
2552
|
};
|
|
2497
2553
|
const locked = getLockedSource(lock, sourceEntry.source);
|
|
2498
2554
|
const ref = await resolvePrefetchRef({
|
|
@@ -2555,7 +2611,7 @@ async function prefetchGithubSkills(params) {
|
|
|
2555
2611
|
}
|
|
2556
2612
|
const skillFilter = sourceEntry.skills ?? ["*"];
|
|
2557
2613
|
const isWildcard = skillFilter.length === 1 && skillFilter[0] === "*";
|
|
2558
|
-
const entries = await withSemaphore(semaphore, () => client.listDirectory(parsed.owner, parsed.repo,
|
|
2614
|
+
const entries = await withSemaphore(semaphore, () => client.listDirectory(parsed.owner, parsed.repo, resolveSkillsSourcePath(sourceEntry), ref));
|
|
2559
2615
|
const skillDirs = entries.filter((entry) => entry.type === "dir" && (isWildcard || skillFilter.includes(entry.name)));
|
|
2560
2616
|
const useRootFallback = shouldUseRootFallback({
|
|
2561
2617
|
skillFilter,
|
|
@@ -2624,13 +2680,13 @@ async function prefetchGithubRules(params) {
|
|
|
2624
2680
|
sourceEntry,
|
|
2625
2681
|
lockedRuleNames: getLockedRuleNames(locked),
|
|
2626
2682
|
localRuleNames: context.localRuleNames,
|
|
2627
|
-
alreadyFetchedRuleNames: claimed,
|
|
2683
|
+
alreadyFetchedRuleNames: claimed.names,
|
|
2628
2684
|
curatedDir: (0, node_path.join)(context.projectRoot, require_import.RULESYNC_CURATED_RULES_RELATIVE_DIR_PATH)
|
|
2629
2685
|
})) {
|
|
2630
2686
|
claim.settle(getLockedRuleNames(locked));
|
|
2631
2687
|
return;
|
|
2632
2688
|
}
|
|
2633
|
-
const entries = await withSemaphore(context.semaphore, () => context.client.listDirectory(parsed.owner, parsed.repo, sourceEntry
|
|
2689
|
+
const entries = await withSemaphore(context.semaphore, () => context.client.listDirectory(parsed.owner, parsed.repo, resolveRulesSourcePath(sourceEntry), ref));
|
|
2634
2690
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
2635
2691
|
const isWildcard = ruleFilter.length === 1 && ruleFilter[0] === "*";
|
|
2636
2692
|
const files = entries.filter((entry) => {
|
|
@@ -3475,16 +3531,31 @@ async function canReuseLockedSkills(params) {
|
|
|
3475
3531
|
}) && await checkLockedSkillsExist(curatedDir, lockedSkillNames);
|
|
3476
3532
|
}
|
|
3477
3533
|
/**
|
|
3478
|
-
* The
|
|
3534
|
+
* The path the skills of a source are read from, as declared: the source's
|
|
3479
3535
|
* `path`, else (for the github transport) the path embedded in the source
|
|
3480
|
-
* spec, else `skills`.
|
|
3536
|
+
* spec, else `skills`. Every transport fetches from this path, and the
|
|
3537
|
+
* lockfile records its normalized form ({@link resolveSkillsPath}), so the
|
|
3538
|
+
* fetch and the lock comparison cannot pick different paths.
|
|
3481
3539
|
*/
|
|
3482
|
-
function
|
|
3540
|
+
function resolveSkillsSourcePath(sourceEntry) {
|
|
3483
3541
|
const embeddedPath = (sourceEntry.transport ?? "github") === "github" ? parseSource(sourceEntry.source).path : void 0;
|
|
3484
|
-
return
|
|
3542
|
+
return sourceEntry.path ?? embeddedPath ?? "skills";
|
|
3485
3543
|
}
|
|
3486
|
-
|
|
3487
|
-
|
|
3544
|
+
/** The skills path of a source in the form the lockfile records and compares. */
|
|
3545
|
+
function resolveSkillsPath(sourceEntry) {
|
|
3546
|
+
return normalizeSourceDirPath(resolveSkillsSourcePath(sourceEntry));
|
|
3547
|
+
}
|
|
3548
|
+
/**
|
|
3549
|
+
* The path the rules of a source are read from, as declared: the source's
|
|
3550
|
+
* `rulesPath`, else `rules`. The rules counterpart of
|
|
3551
|
+
* {@link resolveSkillsSourcePath}.
|
|
3552
|
+
*/
|
|
3553
|
+
function resolveRulesSourcePath(sourceEntry) {
|
|
3554
|
+
return sourceEntry.rulesPath ?? "rules";
|
|
3555
|
+
}
|
|
3556
|
+
/** The rules path of a source in the form the lockfile records and compares. */
|
|
3557
|
+
function resolveRulesPath(sourceEntry) {
|
|
3558
|
+
return normalizeSourceDirPath(resolveRulesSourcePath(sourceEntry));
|
|
3488
3559
|
}
|
|
3489
3560
|
/**
|
|
3490
3561
|
* The form a source directory path is recorded in the lockfile and compared
|
|
@@ -3497,7 +3568,7 @@ function lockedRuleConfigMatches(params) {
|
|
|
3497
3568
|
const rules = getSourceFilters(params.sourceEntry).rules;
|
|
3498
3569
|
if (rules === void 0 || params.locked.ruleSelection === void 0) return false;
|
|
3499
3570
|
const selection = normalizeRuleSelection(rules);
|
|
3500
|
-
return selection.length === params.locked.ruleSelection.length && selection.every((ruleName, index) => ruleName === params.locked.ruleSelection?.[index]) &&
|
|
3571
|
+
return selection.length === params.locked.ruleSelection.length && selection.every((ruleName, index) => ruleName === params.locked.ruleSelection?.[index]) && resolveRulesPath(params.sourceEntry) === params.locked.rulesPath;
|
|
3501
3572
|
}
|
|
3502
3573
|
function assertMatchingRulesFound(params) {
|
|
3503
3574
|
if (params.ruleNames.length === 0) throw new Error(`No matching rules found in ${params.source}.`);
|
|
@@ -3543,7 +3614,7 @@ async function fetchRulesViaGithub(params) {
|
|
|
3543
3614
|
}
|
|
3544
3615
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
3545
3616
|
const isWildcard = ruleFilter.length === 1 && ruleFilter[0] === "*";
|
|
3546
|
-
const rulesPath = sourceEntry
|
|
3617
|
+
const rulesPath = resolveRulesSourcePath(sourceEntry);
|
|
3547
3618
|
let entries;
|
|
3548
3619
|
try {
|
|
3549
3620
|
entries = await client.listDirectory(parsed.owner, parsed.repo, rulesPath, ref);
|
|
@@ -3598,7 +3669,7 @@ async function fetchRulesViaGithub(params) {
|
|
|
3598
3669
|
requestedRef,
|
|
3599
3670
|
resolvedRef: resolvedSha,
|
|
3600
3671
|
ruleSelection: normalizeRuleSelection(sourceEntry.rules ?? []),
|
|
3601
|
-
rulesPath:
|
|
3672
|
+
rulesPath: resolveRulesPath(sourceEntry),
|
|
3602
3673
|
resolvedRuleNames: remoteRuleNames,
|
|
3603
3674
|
logger
|
|
3604
3675
|
});
|
|
@@ -3643,7 +3714,7 @@ async function fetchRulesViaGit(params) {
|
|
|
3643
3714
|
url: sourceKey,
|
|
3644
3715
|
ref: requestedRef,
|
|
3645
3716
|
resolvedRef,
|
|
3646
|
-
skillsPath: sourceEntry
|
|
3717
|
+
skillsPath: resolveRulesSourcePath(sourceEntry),
|
|
3647
3718
|
logger
|
|
3648
3719
|
});
|
|
3649
3720
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
@@ -3676,7 +3747,7 @@ async function fetchRulesViaGit(params) {
|
|
|
3676
3747
|
requestedRef,
|
|
3677
3748
|
resolvedRef,
|
|
3678
3749
|
ruleSelection: normalizeRuleSelection(sourceEntry.rules ?? []),
|
|
3679
|
-
rulesPath:
|
|
3750
|
+
rulesPath: resolveRulesPath(sourceEntry),
|
|
3680
3751
|
resolvedRuleNames: remoteRuleNames,
|
|
3681
3752
|
logger
|
|
3682
3753
|
});
|
|
@@ -3823,8 +3894,7 @@ async function fetchGithubSkillDir(params) {
|
|
|
3823
3894
|
* names already written into `fetchedSkills`.
|
|
3824
3895
|
*/
|
|
3825
3896
|
async function discoverGithubSkillDirs(params) {
|
|
3826
|
-
const { parsed, ref, resolvedSha, skillFilter, isWildcard, curatedDir, locked, sourceKey, localSkillNames, alreadyFetchedSkillNames, client, semaphore, getExecutablePaths, fetchedSkills, logger } = params;
|
|
3827
|
-
const skillsBasePath = parsed.path ?? "skills";
|
|
3897
|
+
const { parsed, skillsBasePath, ref, resolvedSha, skillFilter, isWildcard, curatedDir, locked, sourceKey, localSkillNames, alreadyFetchedSkillNames, client, semaphore, getExecutablePaths, fetchedSkills, logger } = params;
|
|
3828
3898
|
try {
|
|
3829
3899
|
const entries = await client.listDirectory(parsed.owner, parsed.repo, skillsBasePath, ref);
|
|
3830
3900
|
const remoteSkillDirs = entries.filter((e) => e.type === "dir").map((e) => ({
|
|
@@ -3889,8 +3959,7 @@ async function fetchSource(params) {
|
|
|
3889
3959
|
const parsedFromSource = parseSource(sourceEntry.source);
|
|
3890
3960
|
const parsed = {
|
|
3891
3961
|
...parsedFromSource,
|
|
3892
|
-
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
3893
|
-
path: sourceEntry.path ?? parsedFromSource.path
|
|
3962
|
+
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
3894
3963
|
};
|
|
3895
3964
|
if (parsed.provider === "gitlab") throw new Error(`GitLab sources are not yet supported: "${sourceEntry.source}".`);
|
|
3896
3965
|
const sourceKey = sourceEntry.source;
|
|
@@ -3934,6 +4003,7 @@ async function fetchSource(params) {
|
|
|
3934
4003
|
const fetchedSkills = {};
|
|
3935
4004
|
const discovery = await discoverGithubSkillDirs({
|
|
3936
4005
|
parsed,
|
|
4006
|
+
skillsBasePath: resolveSkillsSourcePath(sourceEntry),
|
|
3937
4007
|
ref,
|
|
3938
4008
|
resolvedSha,
|
|
3939
4009
|
skillFilter,
|
|
@@ -4046,7 +4116,7 @@ async function fetchSourceViaGit(params) {
|
|
|
4046
4116
|
url,
|
|
4047
4117
|
ref: requestedRef,
|
|
4048
4118
|
resolvedRef: resolvedSha,
|
|
4049
|
-
skillsPath: sourceEntry
|
|
4119
|
+
skillsPath: resolveSkillsSourcePath(sourceEntry),
|
|
4050
4120
|
logger
|
|
4051
4121
|
}),
|
|
4052
4122
|
skillFilter,
|
|
@@ -4270,7 +4340,7 @@ function buildNpmLockEntry(params) {
|
|
|
4270
4340
|
...sourceEntry.rules !== void 0 && {
|
|
4271
4341
|
rules: mergedRules,
|
|
4272
4342
|
ruleSelection: normalizeRuleSelection(sourceEntry.rules),
|
|
4273
|
-
rulesPath:
|
|
4343
|
+
rulesPath: resolveRulesPath(sourceEntry),
|
|
4274
4344
|
resolvedRuleNames
|
|
4275
4345
|
}
|
|
4276
4346
|
};
|
|
@@ -4285,7 +4355,7 @@ async function fetchNpmSkills(params) {
|
|
|
4285
4355
|
const declaredWildcard = skillFilter.length === 1 && skillFilter[0] === "*";
|
|
4286
4356
|
const selectedFiles = selectNpmSkillFiles({
|
|
4287
4357
|
allFiles,
|
|
4288
|
-
skillsPath: sourceEntry
|
|
4358
|
+
skillsPath: resolveSkillsSourcePath(sourceEntry),
|
|
4289
4359
|
skillFilter,
|
|
4290
4360
|
isWildcard: declaredWildcard,
|
|
4291
4361
|
packageName
|
|
@@ -4333,7 +4403,7 @@ async function fetchNpmRules(params) {
|
|
|
4333
4403
|
resolvedRuleNames: []
|
|
4334
4404
|
};
|
|
4335
4405
|
const { allFiles, sourceEntry, packageName, lockedForIntegrityCheck, lockedRuleNames, curatedRulesDir, localRuleNames, alreadyFetchedRuleNames, resolvedVersion, updateSources, logger } = params;
|
|
4336
|
-
const normalizedRulesPath =
|
|
4406
|
+
const normalizedRulesPath = resolveRulesPath(sourceEntry);
|
|
4337
4407
|
const rulePrefix = normalizedRulesPath === "." ? "" : `${normalizedRulesPath}/`;
|
|
4338
4408
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
4339
4409
|
const isWildcard = ruleFilter.length === 1 && ruleFilter[0] === "*";
|
|
@@ -14033,7 +14103,7 @@ function wrapCommand$1({ name, errorCode, handler, getVersion, loggerFactory = c
|
|
|
14033
14103
|
}
|
|
14034
14104
|
//#endregion
|
|
14035
14105
|
//#region src/cli/program.ts
|
|
14036
|
-
const getVersion = () => "36.0.
|
|
14106
|
+
const getVersion = () => "36.0.2";
|
|
14037
14107
|
const FEATURES_HELP = `${require_import.ALL_FEATURES.join(",")}; ignore is deprecated, use permissions`;
|
|
14038
14108
|
function wrapCommand(name, errorCode, handler) {
|
|
14039
14109
|
return wrapCommand$1({
|
package/dist/cli/index.js
CHANGED
|
@@ -1688,7 +1688,8 @@ async function listDirectoryRecursive(params) {
|
|
|
1688
1688
|
else if (entry.type === "dir") directories.push(entry);
|
|
1689
1689
|
else dropped = true;
|
|
1690
1690
|
if (dropped) onIncompleteDirectory?.(path);
|
|
1691
|
-
const
|
|
1691
|
+
const failures = [];
|
|
1692
|
+
const settled = await Promise.allSettled(directories.map((dir) => listDirectoryRecursive({
|
|
1692
1693
|
client,
|
|
1693
1694
|
owner,
|
|
1694
1695
|
repo,
|
|
@@ -1697,7 +1698,12 @@ async function listDirectoryRecursive(params) {
|
|
|
1697
1698
|
depth: depth + 1,
|
|
1698
1699
|
semaphore,
|
|
1699
1700
|
onIncompleteDirectory
|
|
1701
|
+
}).catch((error) => {
|
|
1702
|
+
failures.push(error);
|
|
1703
|
+
throw error;
|
|
1700
1704
|
})));
|
|
1705
|
+
if (failures.length > 0) throw failures[0];
|
|
1706
|
+
const subResults = settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
1701
1707
|
return [...files, ...subResults.flat()];
|
|
1702
1708
|
}
|
|
1703
1709
|
/**
|
|
@@ -2408,6 +2414,12 @@ async function resolveAndFetchSources(params) {
|
|
|
2408
2414
|
failedSourceCount
|
|
2409
2415
|
};
|
|
2410
2416
|
}
|
|
2417
|
+
/**
|
|
2418
|
+
* The claim of a source the prefetch does not list -- a git or npm transport
|
|
2419
|
+
* source -- whose selection is a wildcard: it may take any
|
|
2420
|
+
* name, so later sources download nothing a name decides.
|
|
2421
|
+
*/
|
|
2422
|
+
const ANY_NAME = Symbol("any name");
|
|
2411
2423
|
function createNameClaim() {
|
|
2412
2424
|
let settle = () => {};
|
|
2413
2425
|
return {
|
|
@@ -2422,7 +2434,12 @@ function createClaimSlot(params) {
|
|
|
2422
2434
|
return {
|
|
2423
2435
|
earlier: async () => {
|
|
2424
2436
|
const claimed = await Promise.all(earlier.map((claim) => claim.names));
|
|
2425
|
-
|
|
2437
|
+
const mayTakeAny = claimed.includes(ANY_NAME);
|
|
2438
|
+
const names = /* @__PURE__ */ new Set([...reserved, ...claimed.flatMap((claim) => claim === ANY_NAME ? [] : claim)]);
|
|
2439
|
+
return {
|
|
2440
|
+
names,
|
|
2441
|
+
has: (name) => mayTakeAny || names.has(name)
|
|
2442
|
+
};
|
|
2426
2443
|
},
|
|
2427
2444
|
settle: own.settle
|
|
2428
2445
|
};
|
|
@@ -2447,13 +2464,30 @@ async function prefetchGithubSources(params) {
|
|
|
2447
2464
|
...rest,
|
|
2448
2465
|
semaphore: new Semaphore(10)
|
|
2449
2466
|
};
|
|
2450
|
-
const items = sources.filter((sourceEntry) =>
|
|
2467
|
+
const items = sources.filter((sourceEntry) => !hasEmptySelection(sourceEntry)).map((sourceEntry) => ({
|
|
2451
2468
|
sourceEntry,
|
|
2469
|
+
listedThroughApi: isListedThroughGithubApi(sourceEntry),
|
|
2452
2470
|
skills: createNameClaim(),
|
|
2453
2471
|
rules: createNameClaim()
|
|
2454
2472
|
}));
|
|
2473
|
+
for (const item of items.filter((candidate) => !candidate.listedThroughApi)) {
|
|
2474
|
+
if (isGitlabSource(item.sourceEntry)) {
|
|
2475
|
+
item.skills.settle([]);
|
|
2476
|
+
item.rules.settle([]);
|
|
2477
|
+
continue;
|
|
2478
|
+
}
|
|
2479
|
+
const filters = getSourceFilters(item.sourceEntry);
|
|
2480
|
+
item.skills.settle(getSelectionClaim({
|
|
2481
|
+
selection: filters.skills,
|
|
2482
|
+
normalize: (name) => name
|
|
2483
|
+
}));
|
|
2484
|
+
item.rules.settle(getSelectionClaim({
|
|
2485
|
+
selection: filters.rules,
|
|
2486
|
+
normalize: normalizeRuleFilterName
|
|
2487
|
+
}));
|
|
2488
|
+
}
|
|
2455
2489
|
await mapWithConcurrency({
|
|
2456
|
-
items,
|
|
2490
|
+
items: items.filter((item) => item.listedThroughApi),
|
|
2457
2491
|
limit: 4,
|
|
2458
2492
|
mapper: async (item) => {
|
|
2459
2493
|
const earlier = items.slice(0, items.indexOf(item));
|
|
@@ -2482,14 +2516,36 @@ async function prefetchGithubSources(params) {
|
|
|
2482
2516
|
}
|
|
2483
2517
|
});
|
|
2484
2518
|
}
|
|
2519
|
+
/** Whether the prefetch lists and downloads this source through the GitHub API. */
|
|
2520
|
+
function isListedThroughGithubApi(sourceEntry) {
|
|
2521
|
+
if ((sourceEntry.transport ?? "github") !== "github") return false;
|
|
2522
|
+
try {
|
|
2523
|
+
return parseSource(sourceEntry.source).provider !== "gitlab";
|
|
2524
|
+
} catch {
|
|
2525
|
+
return true;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
/** Whether this is a GitLab source, which the serial pass does not support yet. */
|
|
2529
|
+
function isGitlabSource(sourceEntry) {
|
|
2530
|
+
if ((sourceEntry.transport ?? "github") !== "github") return false;
|
|
2531
|
+
try {
|
|
2532
|
+
return parseSource(sourceEntry.source).provider === "gitlab";
|
|
2533
|
+
} catch {
|
|
2534
|
+
return false;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
/** What a source the prefetch does not list may take, judged by its selection alone. */
|
|
2538
|
+
function getSelectionClaim(params) {
|
|
2539
|
+
const { selection, normalize } = params;
|
|
2540
|
+
if (selection === void 0) return [];
|
|
2541
|
+
return selection.includes("*") ? ANY_NAME : selection.map(normalize);
|
|
2542
|
+
}
|
|
2485
2543
|
async function prefetchGithubSource(params) {
|
|
2486
2544
|
const { sourceEntry, lock, context, skillClaim, ruleClaim } = params;
|
|
2487
2545
|
const parsedFromSource = parseSource(sourceEntry.source);
|
|
2488
|
-
if (parsedFromSource.provider === "gitlab") return;
|
|
2489
2546
|
const parsed = {
|
|
2490
2547
|
...parsedFromSource,
|
|
2491
|
-
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
2492
|
-
path: sourceEntry.path ?? parsedFromSource.path
|
|
2548
|
+
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
2493
2549
|
};
|
|
2494
2550
|
const locked = getLockedSource(lock, sourceEntry.source);
|
|
2495
2551
|
const ref = await resolvePrefetchRef({
|
|
@@ -2552,7 +2608,7 @@ async function prefetchGithubSkills(params) {
|
|
|
2552
2608
|
}
|
|
2553
2609
|
const skillFilter = sourceEntry.skills ?? ["*"];
|
|
2554
2610
|
const isWildcard = skillFilter.length === 1 && skillFilter[0] === "*";
|
|
2555
|
-
const entries = await withSemaphore(semaphore, () => client.listDirectory(parsed.owner, parsed.repo,
|
|
2611
|
+
const entries = await withSemaphore(semaphore, () => client.listDirectory(parsed.owner, parsed.repo, resolveSkillsSourcePath(sourceEntry), ref));
|
|
2556
2612
|
const skillDirs = entries.filter((entry) => entry.type === "dir" && (isWildcard || skillFilter.includes(entry.name)));
|
|
2557
2613
|
const useRootFallback = shouldUseRootFallback({
|
|
2558
2614
|
skillFilter,
|
|
@@ -2621,13 +2677,13 @@ async function prefetchGithubRules(params) {
|
|
|
2621
2677
|
sourceEntry,
|
|
2622
2678
|
lockedRuleNames: getLockedRuleNames(locked),
|
|
2623
2679
|
localRuleNames: context.localRuleNames,
|
|
2624
|
-
alreadyFetchedRuleNames: claimed,
|
|
2680
|
+
alreadyFetchedRuleNames: claimed.names,
|
|
2625
2681
|
curatedDir: join(context.projectRoot, RULESYNC_CURATED_RULES_RELATIVE_DIR_PATH)
|
|
2626
2682
|
})) {
|
|
2627
2683
|
claim.settle(getLockedRuleNames(locked));
|
|
2628
2684
|
return;
|
|
2629
2685
|
}
|
|
2630
|
-
const entries = await withSemaphore(context.semaphore, () => context.client.listDirectory(parsed.owner, parsed.repo, sourceEntry
|
|
2686
|
+
const entries = await withSemaphore(context.semaphore, () => context.client.listDirectory(parsed.owner, parsed.repo, resolveRulesSourcePath(sourceEntry), ref));
|
|
2631
2687
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
2632
2688
|
const isWildcard = ruleFilter.length === 1 && ruleFilter[0] === "*";
|
|
2633
2689
|
const files = entries.filter((entry) => {
|
|
@@ -3472,16 +3528,31 @@ async function canReuseLockedSkills(params) {
|
|
|
3472
3528
|
}) && await checkLockedSkillsExist(curatedDir, lockedSkillNames);
|
|
3473
3529
|
}
|
|
3474
3530
|
/**
|
|
3475
|
-
* The
|
|
3531
|
+
* The path the skills of a source are read from, as declared: the source's
|
|
3476
3532
|
* `path`, else (for the github transport) the path embedded in the source
|
|
3477
|
-
* spec, else `skills`.
|
|
3533
|
+
* spec, else `skills`. Every transport fetches from this path, and the
|
|
3534
|
+
* lockfile records its normalized form ({@link resolveSkillsPath}), so the
|
|
3535
|
+
* fetch and the lock comparison cannot pick different paths.
|
|
3478
3536
|
*/
|
|
3479
|
-
function
|
|
3537
|
+
function resolveSkillsSourcePath(sourceEntry) {
|
|
3480
3538
|
const embeddedPath = (sourceEntry.transport ?? "github") === "github" ? parseSource(sourceEntry.source).path : void 0;
|
|
3481
|
-
return
|
|
3539
|
+
return sourceEntry.path ?? embeddedPath ?? "skills";
|
|
3482
3540
|
}
|
|
3483
|
-
|
|
3484
|
-
|
|
3541
|
+
/** The skills path of a source in the form the lockfile records and compares. */
|
|
3542
|
+
function resolveSkillsPath(sourceEntry) {
|
|
3543
|
+
return normalizeSourceDirPath(resolveSkillsSourcePath(sourceEntry));
|
|
3544
|
+
}
|
|
3545
|
+
/**
|
|
3546
|
+
* The path the rules of a source are read from, as declared: the source's
|
|
3547
|
+
* `rulesPath`, else `rules`. The rules counterpart of
|
|
3548
|
+
* {@link resolveSkillsSourcePath}.
|
|
3549
|
+
*/
|
|
3550
|
+
function resolveRulesSourcePath(sourceEntry) {
|
|
3551
|
+
return sourceEntry.rulesPath ?? "rules";
|
|
3552
|
+
}
|
|
3553
|
+
/** The rules path of a source in the form the lockfile records and compares. */
|
|
3554
|
+
function resolveRulesPath(sourceEntry) {
|
|
3555
|
+
return normalizeSourceDirPath(resolveRulesSourcePath(sourceEntry));
|
|
3485
3556
|
}
|
|
3486
3557
|
/**
|
|
3487
3558
|
* The form a source directory path is recorded in the lockfile and compared
|
|
@@ -3494,7 +3565,7 @@ function lockedRuleConfigMatches(params) {
|
|
|
3494
3565
|
const rules = getSourceFilters(params.sourceEntry).rules;
|
|
3495
3566
|
if (rules === void 0 || params.locked.ruleSelection === void 0) return false;
|
|
3496
3567
|
const selection = normalizeRuleSelection(rules);
|
|
3497
|
-
return selection.length === params.locked.ruleSelection.length && selection.every((ruleName, index) => ruleName === params.locked.ruleSelection?.[index]) &&
|
|
3568
|
+
return selection.length === params.locked.ruleSelection.length && selection.every((ruleName, index) => ruleName === params.locked.ruleSelection?.[index]) && resolveRulesPath(params.sourceEntry) === params.locked.rulesPath;
|
|
3498
3569
|
}
|
|
3499
3570
|
function assertMatchingRulesFound(params) {
|
|
3500
3571
|
if (params.ruleNames.length === 0) throw new Error(`No matching rules found in ${params.source}.`);
|
|
@@ -3540,7 +3611,7 @@ async function fetchRulesViaGithub(params) {
|
|
|
3540
3611
|
}
|
|
3541
3612
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
3542
3613
|
const isWildcard = ruleFilter.length === 1 && ruleFilter[0] === "*";
|
|
3543
|
-
const rulesPath = sourceEntry
|
|
3614
|
+
const rulesPath = resolveRulesSourcePath(sourceEntry);
|
|
3544
3615
|
let entries;
|
|
3545
3616
|
try {
|
|
3546
3617
|
entries = await client.listDirectory(parsed.owner, parsed.repo, rulesPath, ref);
|
|
@@ -3595,7 +3666,7 @@ async function fetchRulesViaGithub(params) {
|
|
|
3595
3666
|
requestedRef,
|
|
3596
3667
|
resolvedRef: resolvedSha,
|
|
3597
3668
|
ruleSelection: normalizeRuleSelection(sourceEntry.rules ?? []),
|
|
3598
|
-
rulesPath:
|
|
3669
|
+
rulesPath: resolveRulesPath(sourceEntry),
|
|
3599
3670
|
resolvedRuleNames: remoteRuleNames,
|
|
3600
3671
|
logger
|
|
3601
3672
|
});
|
|
@@ -3640,7 +3711,7 @@ async function fetchRulesViaGit(params) {
|
|
|
3640
3711
|
url: sourceKey,
|
|
3641
3712
|
ref: requestedRef,
|
|
3642
3713
|
resolvedRef,
|
|
3643
|
-
skillsPath: sourceEntry
|
|
3714
|
+
skillsPath: resolveRulesSourcePath(sourceEntry),
|
|
3644
3715
|
logger
|
|
3645
3716
|
});
|
|
3646
3717
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
@@ -3673,7 +3744,7 @@ async function fetchRulesViaGit(params) {
|
|
|
3673
3744
|
requestedRef,
|
|
3674
3745
|
resolvedRef,
|
|
3675
3746
|
ruleSelection: normalizeRuleSelection(sourceEntry.rules ?? []),
|
|
3676
|
-
rulesPath:
|
|
3747
|
+
rulesPath: resolveRulesPath(sourceEntry),
|
|
3677
3748
|
resolvedRuleNames: remoteRuleNames,
|
|
3678
3749
|
logger
|
|
3679
3750
|
});
|
|
@@ -3820,8 +3891,7 @@ async function fetchGithubSkillDir(params) {
|
|
|
3820
3891
|
* names already written into `fetchedSkills`.
|
|
3821
3892
|
*/
|
|
3822
3893
|
async function discoverGithubSkillDirs(params) {
|
|
3823
|
-
const { parsed, ref, resolvedSha, skillFilter, isWildcard, curatedDir, locked, sourceKey, localSkillNames, alreadyFetchedSkillNames, client, semaphore, getExecutablePaths, fetchedSkills, logger } = params;
|
|
3824
|
-
const skillsBasePath = parsed.path ?? "skills";
|
|
3894
|
+
const { parsed, skillsBasePath, ref, resolvedSha, skillFilter, isWildcard, curatedDir, locked, sourceKey, localSkillNames, alreadyFetchedSkillNames, client, semaphore, getExecutablePaths, fetchedSkills, logger } = params;
|
|
3825
3895
|
try {
|
|
3826
3896
|
const entries = await client.listDirectory(parsed.owner, parsed.repo, skillsBasePath, ref);
|
|
3827
3897
|
const remoteSkillDirs = entries.filter((e) => e.type === "dir").map((e) => ({
|
|
@@ -3886,8 +3956,7 @@ async function fetchSource(params) {
|
|
|
3886
3956
|
const parsedFromSource = parseSource(sourceEntry.source);
|
|
3887
3957
|
const parsed = {
|
|
3888
3958
|
...parsedFromSource,
|
|
3889
|
-
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
3890
|
-
path: sourceEntry.path ?? parsedFromSource.path
|
|
3959
|
+
ref: sourceEntry.ref ?? parsedFromSource.ref
|
|
3891
3960
|
};
|
|
3892
3961
|
if (parsed.provider === "gitlab") throw new Error(`GitLab sources are not yet supported: "${sourceEntry.source}".`);
|
|
3893
3962
|
const sourceKey = sourceEntry.source;
|
|
@@ -3931,6 +4000,7 @@ async function fetchSource(params) {
|
|
|
3931
4000
|
const fetchedSkills = {};
|
|
3932
4001
|
const discovery = await discoverGithubSkillDirs({
|
|
3933
4002
|
parsed,
|
|
4003
|
+
skillsBasePath: resolveSkillsSourcePath(sourceEntry),
|
|
3934
4004
|
ref,
|
|
3935
4005
|
resolvedSha,
|
|
3936
4006
|
skillFilter,
|
|
@@ -4043,7 +4113,7 @@ async function fetchSourceViaGit(params) {
|
|
|
4043
4113
|
url,
|
|
4044
4114
|
ref: requestedRef,
|
|
4045
4115
|
resolvedRef: resolvedSha,
|
|
4046
|
-
skillsPath: sourceEntry
|
|
4116
|
+
skillsPath: resolveSkillsSourcePath(sourceEntry),
|
|
4047
4117
|
logger
|
|
4048
4118
|
}),
|
|
4049
4119
|
skillFilter,
|
|
@@ -4267,7 +4337,7 @@ function buildNpmLockEntry(params) {
|
|
|
4267
4337
|
...sourceEntry.rules !== void 0 && {
|
|
4268
4338
|
rules: mergedRules,
|
|
4269
4339
|
ruleSelection: normalizeRuleSelection(sourceEntry.rules),
|
|
4270
|
-
rulesPath:
|
|
4340
|
+
rulesPath: resolveRulesPath(sourceEntry),
|
|
4271
4341
|
resolvedRuleNames
|
|
4272
4342
|
}
|
|
4273
4343
|
};
|
|
@@ -4282,7 +4352,7 @@ async function fetchNpmSkills(params) {
|
|
|
4282
4352
|
const declaredWildcard = skillFilter.length === 1 && skillFilter[0] === "*";
|
|
4283
4353
|
const selectedFiles = selectNpmSkillFiles({
|
|
4284
4354
|
allFiles,
|
|
4285
|
-
skillsPath: sourceEntry
|
|
4355
|
+
skillsPath: resolveSkillsSourcePath(sourceEntry),
|
|
4286
4356
|
skillFilter,
|
|
4287
4357
|
isWildcard: declaredWildcard,
|
|
4288
4358
|
packageName
|
|
@@ -4330,7 +4400,7 @@ async function fetchNpmRules(params) {
|
|
|
4330
4400
|
resolvedRuleNames: []
|
|
4331
4401
|
};
|
|
4332
4402
|
const { allFiles, sourceEntry, packageName, lockedForIntegrityCheck, lockedRuleNames, curatedRulesDir, localRuleNames, alreadyFetchedRuleNames, resolvedVersion, updateSources, logger } = params;
|
|
4333
|
-
const normalizedRulesPath =
|
|
4403
|
+
const normalizedRulesPath = resolveRulesPath(sourceEntry);
|
|
4334
4404
|
const rulePrefix = normalizedRulesPath === "." ? "" : `${normalizedRulesPath}/`;
|
|
4335
4405
|
const ruleFilter = (sourceEntry.rules ?? []).map(normalizeRuleFilterName);
|
|
4336
4406
|
const isWildcard = ruleFilter.length === 1 && ruleFilter[0] === "*";
|
|
@@ -14030,7 +14100,7 @@ function wrapCommand$1({ name, errorCode, handler, getVersion, loggerFactory = c
|
|
|
14030
14100
|
}
|
|
14031
14101
|
//#endregion
|
|
14032
14102
|
//#region src/cli/program.ts
|
|
14033
|
-
const getVersion = () => "36.0.
|
|
14103
|
+
const getVersion = () => "36.0.2";
|
|
14034
14104
|
const FEATURES_HELP = `${ALL_FEATURES.join(",")}; ignore is deprecated, use permissions`;
|
|
14035
14105
|
function wrapCommand(name, errorCode, handler) {
|
|
14036
14106
|
return wrapCommand$1({
|