MCPcopy
hub / github.com/colbymchenry/codegraph / sync

Method sync

src/extraction/index.ts:1938–2074  ·  view source on GitHub ↗

* Sync the index with the current file state. * * Change detection is filesystem-based, never git: a (size, mtime) stat * pre-filter skips unchanged files, then a content-hash compare confirms real * changes. This works in non-git projects and catches committed changes from * `git pul

(onProgress?: (progress: IndexProgress) => void)

Source from the content-addressed store, hash-verified

1936 * `git pull`/`checkout`/`merge`/`rebase` that `git status` cannot see.
1937 */
1938 async sync(onProgress?: (progress: IndexProgress) => void): Promise<SyncResult> {
1939 await initGrammars(); // Initialize WASM runtime (grammars loaded lazily below)
1940 const startTime = Date.now();
1941 let filesChecked = 0;
1942 let filesAdded = 0;
1943 let filesModified = 0;
1944 let filesRemoved = 0;
1945 let nodesUpdated = 0;
1946 const changedFilePaths: string[] = [];
1947
1948 onProgress?.({
1949 phase: 'scanning',
1950 current: 0,
1951 total: 0,
1952 });
1953
1954 const filesToIndex: string[] = [];
1955 // === Filesystem reconcile (git-independent) ===
1956 // The source of truth for "what changed" is the filesystem vs the indexed
1957 // state — never git. We enumerate the current source files and reconcile
1958 // each against the DB. A cheap (size, mtime) stat pre-filter skips unchanged
1959 // files without reading or hashing them, so the expensive read+hash+parse
1960 // only runs for files that actually changed. This catches edits/adds/deletes
1961 // whether or not the project uses git, and crucially also catches committed
1962 // changes from `git pull`/`checkout`/`merge`/`rebase` — which `git status`
1963 // cannot see, because the working tree is clean afterward.
1964 const currentFiles = await scanDirectoryAsync(this.rootDir);
1965 filesChecked = currentFiles.length;
1966 const currentSet = new Set(currentFiles);
1967
1968 const trackedFiles = this.queries.getAllFiles();
1969 const trackedMap = new Map<string, FileRecord>();
1970 for (const f of trackedFiles) {
1971 trackedMap.set(f.path, f);
1972 }
1973
1974 // Removals: tracked in the DB but no longer a present source file. Check the
1975 // filesystem directly — `scanDirectory` (via `git ls-files`) still lists a
1976 // file deleted from disk but not yet staged, so set membership alone misses it.
1977 // `reconcileChecks` drives the cooperative yield shared with the adds/mods loop
1978 // below (see SYNC_RECONCILE_YIELD_INTERVAL / issue #905).
1979 let reconcileChecks = 0;
1980 for (const tracked of trackedFiles) {
1981 if (!currentSet.has(tracked.path) || !fs.existsSync(path.join(this.rootDir, tracked.path))) {
1982 this.queries.deleteFile(tracked.path);
1983 filesRemoved++;
1984 }
1985 if (++reconcileChecks % SYNC_RECONCILE_YIELD_INTERVAL === 0) {
1986 await new Promise<void>((resolve) => setImmediate(resolve));
1987 }
1988 }
1989
1990 // Adds / modifications.
1991 for (const filePath of currentFiles) {
1992 // Same cooperative yield as the removals loop — this is the other O(files)
1993 // synchronous-stat loop that wedges the main thread on a large repo (#905).
1994 // Yield at the top of the body so the `continue` fast-paths below still hit it.
1995 if (++reconcileChecks % SYNC_RECONCILE_YIELD_INTERVAL === 0) {

Callers 2

catchUpSyncMethod · 0.45
mainFunction · 0.45

Calls 15

indexFileMethod · 0.95
initGrammarsFunction · 0.90
logDebugFunction · 0.90
loadExtensionOverridesFunction · 0.90
detectLanguageFunction · 0.90
loadGrammarsForLanguagesFunction · 0.90
onProgressFunction · 0.85
scanDirectoryAsyncFunction · 0.85
hashContentFunction · 0.85
setMethod · 0.80
hasMethod · 0.80
joinMethod · 0.80

Tested by

no test coverage detected