fix: handle missing/corrupt repos when fetching branches + clearer manual fallback

Backend (git_repositories.py):
- get_repository_branches now checks for .git subdirectory (not just dir existence)
- If local repo is corrupt/missing but has remote_url, falls back to git ls-remote
  to list branches from the remote
- Returns 404 with actionable message instead of 400 with raw git stderr
- Pre-existing test failure in test_git_repository_clone_preflight.py unchanged

Frontend (workspace-create-form.tsx):
- When branch API fails, auto-switches to manual text input (no dropdown selection needed)
- Shows hint text: 'Couldn't load branches — type one manually'
- useGitRepo hook auto-fetches branches when projectId/repoId change

Quality gates: ruff clean, tsc --noEmit clean, 93 passed + 1 pre-existing failure
This commit is contained in:
2026-06-01 19:00:59 +02:00
parent b02cd978c3
commit ee3c5af7a4
3 changed files with 95 additions and 35 deletions
+7 -5
View File
@@ -72,7 +72,11 @@ export interface UseGitRepoResult {
/** Delete a branch. */
deleteBranch: (name: string, force?: boolean) => Promise<void>;
/** Merge source into current (or target) branch. */
merge: (sourceBranch: string, targetBranch?: string, message?: string) => Promise<void>;
merge: (
sourceBranch: string,
targetBranch?: string,
message?: string,
) => Promise<void>;
/** Clear the current error. */
clearError: () => void;
}
@@ -90,7 +94,7 @@ export function useGitRepo(
const [error, setError] = useState<string | null>(null);
const withLoading = useCallback(
async <T,>(fn: () => Promise<T>): Promise<T> => {
async <T>(fn: () => Promise<T>): Promise<T> => {
setLoading(true);
setError(null);
try {
@@ -157,9 +161,7 @@ export function useGitRepo(
const commit = useCallback(
async (message: string, files?: string[]) => {
if (!projectId || !repoId) return;
await withLoading(() =>
commitChanges(projectId, repoId, message, files),
);
await withLoading(() => commitChanges(projectId, repoId, message, files));
await refreshStatus();
},
[projectId, repoId, withLoading, refreshStatus],