Skip to content

Commit ce5c2c0

Browse files
CSCSoftwareclaude
andcommitted
fix: dedup only removes parents with direct children in global-init
Previously, any project containing a sub-project at any depth was removed during deduplication. This incorrectly removed projects like Aidex/ when they only had deeply nested sample projects (e.g. SampleLangProjects/java/). Now only parents with direct (one-level-deep) children are deduplicated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7643fa3 commit ce5c2c0

1 file changed

Lines changed: 26 additions & 13 deletions

File tree

src/commands/global/global-init.ts

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -194,17 +194,21 @@ export async function globalInit(params: GlobalInitParams): Promise<GlobalInitRe
194194

195195
// Remove parent-duplicate projects already in the global DB
196196
// (from previous runs before deduplication was added)
197+
// Only remove parents with DIRECT children (one level deeper)
197198
const allRegistered = globalDb.getProjects();
198199
const allPaths = allRegistered.map(p => ({
199200
id: p.id,
200201
path: p.path.replace(/\\/g, '/').replace(/\/+$/, '') + '/',
201202
}));
202203
for (const project of allPaths) {
203-
const isParent = allPaths.some(other =>
204-
other.id !== project.id &&
205-
other.path.startsWith(project.path)
206-
);
207-
if (isParent) {
204+
const hasDirectChild = allPaths.some(other => {
205+
if (other.id === project.id) return false;
206+
if (!other.path.startsWith(project.path)) return false;
207+
const remainder = other.path.slice(project.path.length);
208+
const segments = remainder.replace(/\/+$/, '').split('/');
209+
return segments.length === 1;
210+
});
211+
if (hasDirectChild) {
208212
globalDb.unregisterProject(project.path.replace(/\/+$/, ''));
209213
removedCount++;
210214
}
@@ -505,11 +509,15 @@ function findUnindexedProjects(searchPath: string, maxDepth: number, indexedPath
505509

506510
/**
507511
* Deduplicate projects: If project A is a parent directory of project B,
508-
* keep only B (the more specific sub-project).
512+
* keep only B (the more specific sub-project) — but only when B is a
513+
* DIRECT child of A (one level deeper).
509514
*
510515
* Example: Given paths [AudioGrabber/, AudioGrabber/AudioGrabber/, AudioGrabber/AudioGrabber2/]
511-
* → Remove AudioGrabber/ because it contains sub-projects.
516+
* → Remove AudioGrabber/ because it has direct sub-projects.
512517
* → Keep AudioGrabber/AudioGrabber/ and AudioGrabber/AudioGrabber2/.
518+
*
519+
* Counter-example: [Aidex/, Aidex/SampleLangProjects/java-minimal-json/]
520+
* → Keep Aidex/ because the sub-project is nested 2+ levels deep (not a direct child).
513521
*/
514522
function deduplicateProjects<T extends { path: string; name: string }>(projects: T[]): T[] {
515523
// Normalize all paths
@@ -521,14 +529,19 @@ function deduplicateProjects<T extends { path: string; name: string }>(projects:
521529
// Sort by path length descending (deepest first)
522530
normalized.sort((a, b) => b._normPath.length - a._normPath.length);
523531

524-
// A project is a "parent" if any other project's path starts with it
532+
// A project is a "parent" only if another project is a DIRECT child (one level deeper)
525533
const result: typeof projects = [];
526534
for (const project of normalized) {
527-
const isParent = normalized.some(other =>
528-
other !== project &&
529-
other._normPath.startsWith(project._normPath)
530-
);
531-
if (!isParent) {
535+
const hasDirectChild = normalized.some(other => {
536+
if (other === project) return false;
537+
if (!other._normPath.startsWith(project._normPath)) return false;
538+
// Check if it's a direct child: the remaining path after the parent
539+
// should contain no additional slashes (only "childName/")
540+
const remainder = other._normPath.slice(project._normPath.length);
541+
const segments = remainder.replace(/\/+$/, '').split('/');
542+
return segments.length === 1;
543+
});
544+
if (!hasDirectChild) {
532545
result.push(project);
533546
}
534547
}

0 commit comments

Comments
 (0)