fix(git): surface non-git-repo as a typed error and align all panels via workspace state

Consolidate `.git` presence detection into a shared `git_repo` module used by both the workspace state watcher and the command preflight helper, replacing duplicated local definitions.

Introduce `AppErrorCode::NotAGitRepository` (HTTP 422) and preflight eleven frontend-callable git commands (log, status, list-branches, diff, diff-with-branch, show-diff, show-file, push-info, list-remotes, list-all-branches, commit-branches) so non-git folders short-circuit with a structured error instead of leaking locale-dependent git stderr.

Frontend `isNotAGitRepoError` checks the error code first and falls back to a multi-language regex list centralized in `src/i18n/git-error-patterns.ts`, covering the nine languages git actually translates into.

Wire the git log panel to `workspaceState.isGitRepo` rather than a local cached flag, so running `git init` or deleting `.git` externally propagates through the watcher and refreshes the panel automatically.
This commit is contained in:
xintaofei
2026-04-18 23:07:13 +08:00
parent cf9573c0ce
commit cc79d62b27
9 changed files with 135 additions and 13 deletions

View File

@@ -1,3 +1,4 @@
import { NOT_A_GIT_REPO_PATTERNS } from "@/i18n/git-error-patterns"
import type { AppCommandError } from "@/lib/types"
type ObjectLike = Record<string, unknown>
@@ -46,11 +47,19 @@ export function extractAppCommandError(error: unknown): AppCommandError | null {
}
}
// Must mirror `AppErrorCode::NotAGitRepository` in src-tauri/src/app_error.rs.
// If the backend enum ever renames, both sides must change together.
export const NOT_A_GIT_REPO_CODE = "not_a_git_repository"
export function isNotAGitRepoError(error: unknown): boolean {
const appError = extractAppCommandError(error)
if (appError?.code === NOT_A_GIT_REPO_CODE) return true
const candidates = [appError?.detail, appError?.message]
return candidates.some(
(text) => typeof text === "string" && /not a git repository/i.test(text)
(text) =>
typeof text === "string" &&
NOT_A_GIT_REPO_PATTERNS.some((pattern) => pattern.test(text))
)
}