fix(workspace-state): keep git-presence flag and branch poll in sync with runtime state

Reconcile the cached is_git_repo flag against the filesystem on every watch flush so `git init` or deletion of .git is reflected immediately: sync the stored flag, drop stale git_snapshot data when the repo goes away, emit a meta delta when presence flips without any data change, and mark the event as requires_resync so the frontend re-fetches the snapshot to pick up the new flag.

Replace the title-bar branch polling interval with a self-adjusting setTimeout chain that backs off to 60s when get_git_branch returns null or throws and drops back to 10s once a branch is detected, so branches created externally recover within one slow tick without hammering the backend on non-git folders.
This commit is contained in:
xintaofei
2026-04-18 17:44:45 +08:00
parent 7ef8d84d44
commit ff48810603
2 changed files with 45 additions and 15 deletions

View File

@@ -678,6 +678,15 @@ async fn flush_watch_batch(
Err(_) => return,
};
// Keep the cached git-presence flag in sync with the filesystem.
// When it flips, the snapshot response carries the new value, and the
// emitted event carries `requires_resync=true` so the frontend re-fetches
// to align its isGitRepo view.
let git_presence_changed = guard.is_git_repo != is_git;
if git_presence_changed {
guard.is_git_repo = is_git;
}
if let Some(tree) = refreshed_tree {
if tree != guard.tree_snapshot {
payload.push(WorkspaceDelta::TreeReplace { nodes: tree });
@@ -689,6 +698,22 @@ async fn flush_watch_batch(
entries: git_snapshot,
});
}
} else if !is_git && !guard.git_snapshot.is_empty() {
// .git vanished (or was never there) and we still hold stale git
// data — emit an empty GitReplace so the UI stops showing tracked
// files that no longer exist from git's perspective.
payload.push(WorkspaceDelta::GitReplace {
entries: Vec::new(),
});
}
// Presence flip with no data delta (e.g. `git init` in a clean folder)
// still needs to wake the frontend, otherwise the snapshot flag never
// propagates until an unrelated change happens.
if git_presence_changed && payload.is_empty() {
payload.push(WorkspaceDelta::Meta {
reason: format!("is_git_repo_changed:{is_git}"),
});
}
if payload.is_empty() {
@@ -709,7 +734,7 @@ async fn flush_watch_batch(
"meta".to_string()
};
guard.append_event(kind, payload, false)
guard.append_event(kind, payload, git_presence_changed)
};
emit_event(emitter, "folder://workspace-state-event", event);