@@ -8,6 +8,7 @@ import { CodeIndexServiceFactory } from "./service-factory"
88import { CodeIndexSearchService } from "./search-service"
99import { CodeIndexOrchestrator } from "./orchestrator"
1010import { CacheManager } from "./cache-manager"
11+ import { GitBranchWatcher } from "./git-branch-watcher"
1112import { RooIgnoreController } from "../../core/ignore/RooIgnoreController"
1213import fs from "fs/promises"
1314import ignore from "ignore"
@@ -16,8 +17,6 @@ import { t } from "../../i18n"
1617import { TelemetryService } from "@roo-code/telemetry"
1718import { TelemetryEventName } from "@roo-code/types"
1819
19- import { getCurrentBranch } from "../../utils/git"
20-
2120export class CodeIndexManager {
2221 // --- Singleton Implementation ---
2322 private static instances = new Map < string , CodeIndexManager > ( ) // Map workspace path to instance
@@ -31,13 +30,10 @@ export class CodeIndexManager {
3130 private _cacheManager : CacheManager | undefined
3231
3332 // Flag to prevent race conditions during error recovery
33+ private _isRecoveringFromError = false
3434
3535 // Git branch change watcher for branch isolation
36- private _gitHeadWatcher ?: vscode . FileSystemWatcher
37- private _lastKnownBranch ?: string
38- private _gitHeadDebounce ?: ReturnType < typeof setTimeout >
39-
40- private _isRecoveringFromError = false
36+ private _gitBranchWatcher ?: GitBranchWatcher
4137
4238 public static getInstance ( context : vscode . ExtensionContext , workspacePath ?: string ) : CodeIndexManager | undefined {
4339 // If workspacePath is not provided, try to get it from the active editor or first workspace folder
@@ -247,9 +243,9 @@ export class CodeIndexManager {
247243 // This ensures a clean slate even if state update failed
248244 this . _configManager = undefined
249245 this . _serviceFactory = undefined
250- if ( this . _gitHeadWatcher ) {
251- this . _gitHeadWatcher . dispose ( )
252- this . _gitHeadWatcher = undefined
246+ if ( this . _gitBranchWatcher ) {
247+ this . _gitBranchWatcher . dispose ( )
248+ this . _gitBranchWatcher = undefined
253249 }
254250
255251 this . _orchestrator = undefined
@@ -267,9 +263,9 @@ export class CodeIndexManager {
267263 if ( this . _orchestrator ) {
268264 this . stopWatcher ( )
269265 }
270- if ( this . _gitHeadWatcher ) {
271- this . _gitHeadWatcher . dispose ( )
272- this . _gitHeadWatcher = undefined
266+ if ( this . _gitBranchWatcher ) {
267+ this . _gitBranchWatcher . dispose ( )
268+ this . _gitBranchWatcher = undefined
273269 }
274270
275271 this . _stateManager . dispose ( )
@@ -399,59 +395,55 @@ export class CodeIndexManager {
399395
400396 // --- Git branch watcher (Phase 1: auto branch switch handling) ---
401397 private async _setupGitHeadWatcher ( ) : Promise < void > {
402- const isEnabled = this . _configManager ?. getConfig ( ) . branchIsolationEnabled
403- if ( ! isEnabled ) {
404- if ( this . _gitHeadWatcher ) {
405- this . _gitHeadWatcher . dispose ( )
406- this . _gitHeadWatcher = undefined
407- }
408- this . _lastKnownBranch = undefined
409- return
410- }
411- this . _lastKnownBranch = await getCurrentBranch ( this . workspacePath )
412- if ( ! this . _gitHeadWatcher ) {
413- const pattern = new vscode . RelativePattern ( this . workspacePath , ".git/HEAD" )
414- this . _gitHeadWatcher = vscode . workspace . createFileSystemWatcher ( pattern )
415- const handler = ( ) => this . _onGitHeadChange ( )
416- this . _gitHeadWatcher . onDidChange ( handler )
417-
418- this . _gitHeadWatcher . onDidCreate ( handler )
419- this . _gitHeadWatcher . onDidDelete ( handler )
398+ const isEnabled = this . _configManager ?. getConfig ( ) . branchIsolationEnabled ?? false
399+
400+ // Create watcher if it doesn't exist
401+ if ( ! this . _gitBranchWatcher ) {
402+ this . _gitBranchWatcher = new GitBranchWatcher (
403+ this . workspacePath ,
404+ async ( oldBranch , newBranch ) => this . _onBranchChange ( oldBranch , newBranch ) ,
405+ { enabled : isEnabled , debounceMs : 500 } ,
406+ )
407+ } else {
408+ // Update existing watcher config
409+ await this . _gitBranchWatcher . updateConfig ( { enabled : isEnabled , debounceMs : 500 } )
420410 }
411+
412+ // Initialize the watcher
413+ await this . _gitBranchWatcher . initialize ( )
421414 }
422415
423- private async _onGitHeadChange ( ) : Promise < void > {
424- if ( this . _gitHeadDebounce ) clearTimeout ( this . _gitHeadDebounce )
425- this . _gitHeadDebounce = setTimeout ( async ( ) => {
426- try {
427- if ( ! this . _configManager ?. getConfig ( ) . branchIsolationEnabled ) return
428- const newBranch = await getCurrentBranch ( this . workspacePath )
429- if ( newBranch === this . _lastKnownBranch ) return
430- this . _lastKnownBranch = newBranch
431- await this . _recreateServices ( )
432-
433- // Smart re-indexing: only do full scan if collection doesn't exist or is empty
434- // If collection exists with data, file watcher will handle incremental updates
435- const vectorStore = this . _orchestrator ?. getVectorStore ( )
436- if ( ! vectorStore ) {
437- // No orchestrator yet, just start indexing
438- this . _orchestrator ?. startIndexing ( )
439- return
440- }
416+ /**
417+ * Handles Git branch changes
418+ * @param oldBranch Previous branch name
419+ * @param newBranch New branch name
420+ */
421+ private async _onBranchChange ( oldBranch : string | undefined , newBranch : string | undefined ) : Promise < void > {
422+ try {
423+ // Recreate services with new branch context
424+ await this . _recreateServices ( )
441425
442- const collectionExists = await vectorStore . collectionExists ( )
443- if ( ! collectionExists ) {
444- // New branch or first time indexing this branch - do full scan
445- this . _orchestrator ?. startIndexing ( )
446- } else {
447- // Collection exists - just validate/initialize without full scan
448- // File watcher will detect any file changes from the branch switch
449- await vectorStore . initialize ( )
450- }
451- } catch ( error ) {
452- console . error ( "Failed to handle Git branch change:" , error )
426+ // Smart re-indexing: only do full scan if collection doesn't exist or is empty
427+ // If collection exists with data, file watcher will handle incremental updates
428+ const vectorStore = this . _orchestrator ?. getVectorStore ( )
429+ if ( ! vectorStore ) {
430+ // No orchestrator yet, just start indexing
431+ this . _orchestrator ?. startIndexing ( )
432+ return
453433 }
454- } , 250 )
434+
435+ const collectionExists = await vectorStore . collectionExists ( )
436+ if ( ! collectionExists ) {
437+ // New branch or first time indexing this branch - do full scan
438+ this . _orchestrator ?. startIndexing ( )
439+ } else {
440+ // Collection exists - just validate/initialize without full scan
441+ // File watcher will detect any file changes from the branch switch
442+ await vectorStore . initialize ( )
443+ }
444+ } catch ( error ) {
445+ console . error ( "[CodeIndexManager] Failed to handle Git branch change:" , error )
446+ }
455447 }
456448
457449 /**
0 commit comments