refactor: simplify manifest registry duplicate detection (#16260)

This commit is contained in:
Peter Steinberger
2026-02-14 16:04:41 +01:00
committed by GitHub
parent a6fbd0393d
commit 497b060e49

View File

@@ -11,17 +11,25 @@ type SeenIdEntry = {
recordIndex: number; recordIndex: number;
}; };
function pluginOriginRank(origin: PluginOrigin): number { // Precedence: config > workspace > global > bundled
// Precedence: config > workspace > global > bundled const PLUGIN_ORIGIN_RANK: Readonly<Record<PluginOrigin, number>> = {
switch (origin) { config: 0,
case "config": workspace: 1,
return 0; global: 2,
case "workspace": bundled: 3,
return 1; };
case "global":
return 2; function safeRealpathSync(rootDir: string, cache: Map<string, string>): string | null {
case "bundled": const cached = cache.get(rootDir);
return 3; if (cached) {
return cached;
}
try {
const resolved = fs.realpathSync(rootDir);
cache.set(rootDir, resolved);
return resolved;
} catch {
return null;
} }
} }
@@ -158,6 +166,7 @@ export function loadPluginManifestRegistry(params: {
const candidates: PluginCandidate[] = discovery.candidates; const candidates: PluginCandidate[] = discovery.candidates;
const records: PluginManifestRecord[] = []; const records: PluginManifestRecord[] = [];
const seenIds = new Map<string, SeenIdEntry>(); const seenIds = new Map<string, SeenIdEntry>();
const realpathCache = new Map<string, string>();
for (const candidate of candidates) { for (const candidate of candidates) {
const manifestRes = loadPluginManifest(candidate.rootDir); const manifestRes = loadPluginManifest(candidate.rootDir);
@@ -191,17 +200,13 @@ export function loadPluginManifestRegistry(params: {
// Check whether both candidates point to the same physical directory // Check whether both candidates point to the same physical directory
// (e.g. via symlinks or different path representations). If so, this // (e.g. via symlinks or different path representations). If so, this
// is a false-positive duplicate and can be silently skipped. // is a false-positive duplicate and can be silently skipped.
let samePlugin = false; const existingReal = safeRealpathSync(existing.candidate.rootDir, realpathCache);
try { const candidateReal = safeRealpathSync(candidate.rootDir, realpathCache);
samePlugin = const samePlugin = Boolean(existingReal && candidateReal && existingReal === candidateReal);
fs.realpathSync(existing.candidate.rootDir) === fs.realpathSync(candidate.rootDir);
} catch {
// If either path is inaccessible, fall through to duplicate warning
}
if (samePlugin) { if (samePlugin) {
// Prefer higher-precedence origins even if candidates are passed in // Prefer higher-precedence origins even if candidates are passed in
// an unexpected order (config > workspace > global > bundled). // an unexpected order (config > workspace > global > bundled).
if (pluginOriginRank(candidate.origin) < pluginOriginRank(existing.candidate.origin)) { if (PLUGIN_ORIGIN_RANK[candidate.origin] < PLUGIN_ORIGIN_RANK[existing.candidate.origin]) {
records[existing.recordIndex] = buildRecord({ records[existing.recordIndex] = buildRecord({
manifest, manifest,
candidate, candidate,