Merge pull request #5264 from psoukie/fix/wsl-mntc-footer-branch-refresh
fix(coding-agent): refresh branch in footer on WSL /mnt repos
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { type ExecFileException, execFile, spawnSync } from "child_process";
|
import { type ExecFileException, execFile, spawnSync } from "child_process";
|
||||||
import { existsSync, type FSWatcher, readFileSync, statSync, unwatchFile, watchFile } from "fs";
|
import { existsSync, type FSWatcher, readFileSync, type Stats, statSync, unwatchFile, watchFile } from "fs";
|
||||||
import { dirname, join, resolve } from "path";
|
import { dirname, join, resolve } from "path";
|
||||||
import { closeWatcher, FS_WATCH_RETRY_DELAY_MS, watchWithErrorHandler } from "../utils/fs-watch.ts";
|
import { closeWatcher, FS_WATCH_RETRY_DELAY_MS, watchWithErrorHandler } from "../utils/fs-watch.ts";
|
||||||
|
|
||||||
@@ -80,6 +80,18 @@ function resolveBranchWithGitAsync(repoDir: string): Promise<string | null> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isWslEnvironment(): boolean {
|
||||||
|
return process.platform === "linux" && !!(process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWindowsMountedRepoPath(repoDir: string): boolean {
|
||||||
|
return /^\/mnt\/[a-z](?:\/|$)/i.test(repoDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldPollGitHead(repoDir: string): boolean {
|
||||||
|
return isWslEnvironment() && isWindowsMountedRepoPath(repoDir);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides git branch and extension statuses - data not otherwise accessible to extensions.
|
* Provides git branch and extension statuses - data not otherwise accessible to extensions.
|
||||||
* Token stats, model info available via ctx.sessionManager and ctx.model.
|
* Token stats, model info available via ctx.sessionManager and ctx.model.
|
||||||
@@ -92,6 +104,8 @@ export class FooterDataProvider {
|
|||||||
private cachedBranch: string | null | undefined = undefined;
|
private cachedBranch: string | null | undefined = undefined;
|
||||||
private gitPaths: GitPaths | null | undefined = undefined;
|
private gitPaths: GitPaths | null | undefined = undefined;
|
||||||
private headWatcher: FSWatcher | null = null;
|
private headWatcher: FSWatcher | null = null;
|
||||||
|
private headWatchFilePath: string | null = null;
|
||||||
|
private headWatchFileListener: ((current: Stats, previous: Stats) => void) | null = null;
|
||||||
private reftableWatcher: FSWatcher | null = null;
|
private reftableWatcher: FSWatcher | null = null;
|
||||||
private reftableTablesListWatcher: FSWatcher | null = null;
|
private reftableTablesListWatcher: FSWatcher | null = null;
|
||||||
private reftableTablesListPath: string | null = null;
|
private reftableTablesListPath: string | null = null;
|
||||||
@@ -255,6 +269,11 @@ export class FooterDataProvider {
|
|||||||
private clearGitWatchers(): void {
|
private clearGitWatchers(): void {
|
||||||
closeWatcher(this.headWatcher);
|
closeWatcher(this.headWatcher);
|
||||||
this.headWatcher = null;
|
this.headWatcher = null;
|
||||||
|
if (this.headWatchFilePath && this.headWatchFileListener) {
|
||||||
|
unwatchFile(this.headWatchFilePath, this.headWatchFileListener);
|
||||||
|
this.headWatchFilePath = null;
|
||||||
|
this.headWatchFileListener = null;
|
||||||
|
}
|
||||||
closeWatcher(this.reftableWatcher);
|
closeWatcher(this.reftableWatcher);
|
||||||
this.reftableWatcher = null;
|
this.reftableWatcher = null;
|
||||||
closeWatcher(this.reftableTablesListWatcher);
|
closeWatcher(this.reftableTablesListWatcher);
|
||||||
@@ -289,6 +308,8 @@ export class FooterDataProvider {
|
|||||||
this.clearGitWatchers();
|
this.clearGitWatchers();
|
||||||
if (!this.gitPaths) return;
|
if (!this.gitPaths) return;
|
||||||
|
|
||||||
|
const pollGitHead = shouldPollGitHead(this.gitPaths.repoDir);
|
||||||
|
|
||||||
// Watch the directory containing HEAD, not HEAD itself.
|
// Watch the directory containing HEAD, not HEAD itself.
|
||||||
// Git uses atomic writes (write temp, rename over HEAD), which changes the inode.
|
// Git uses atomic writes (write temp, rename over HEAD), which changes the inode.
|
||||||
// fs.watch on a file stops working after the inode changes.
|
// fs.watch on a file stops working after the inode changes.
|
||||||
@@ -301,7 +322,20 @@ export class FooterDataProvider {
|
|||||||
},
|
},
|
||||||
() => this.handleGitWatcherError(),
|
() => this.handleGitWatcherError(),
|
||||||
);
|
);
|
||||||
if (!this.headWatcher) {
|
if (pollGitHead) {
|
||||||
|
this.headWatchFilePath = this.gitPaths.headPath;
|
||||||
|
this.headWatchFileListener = (current, previous) => {
|
||||||
|
if (
|
||||||
|
current.mtimeMs !== previous.mtimeMs ||
|
||||||
|
current.ctimeMs !== previous.ctimeMs ||
|
||||||
|
current.size !== previous.size
|
||||||
|
) {
|
||||||
|
this.scheduleRefresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
watchFile(this.headWatchFilePath, { interval: 1000 }, this.headWatchFileListener);
|
||||||
|
}
|
||||||
|
if (!this.headWatcher && !pollGitHead) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user