fix: improve worktree branch handling in list route

- Updated the logic in the createListHandler to ensure that the branch name is correctly assigned, especially for the main worktree when it may be missing.
- Added checks to handle cases where the worktree directory might not exist, ensuring that removed worktrees are accurately tracked.
- Enhanced the final worktree entry handling to account for scenarios where the output does not end with a blank line, improving robustness.
This commit is contained in:
webdevcody
2026-01-08 00:13:12 -05:00
parent 959467de90
commit fd5f7b873a
2 changed files with 67 additions and 5 deletions

View File

@@ -74,8 +74,23 @@ export function createListHandler() {
} else if (line.startsWith('branch ')) { } else if (line.startsWith('branch ')) {
current.branch = line.slice(7).replace('refs/heads/', ''); current.branch = line.slice(7).replace('refs/heads/', '');
} else if (line === '') { } else if (line === '') {
if (current.path && current.branch) { if (current.path) {
const isMainWorktree = isFirst; const isMainWorktree = isFirst;
// If branch is missing (can happen for main worktree in some git states),
// fall back to getCurrentBranch() for the main worktree
let branchName = current.branch;
if (!branchName && isMainWorktree) {
// For main worktree, use the current branch we already fetched
branchName = currentBranch || '';
}
// Skip if we still don't have a branch name (shouldn't happen, but be safe)
if (!branchName) {
current = {};
continue;
}
// Check if the worktree directory actually exists // Check if the worktree directory actually exists
// Skip checking/pruning the main worktree (projectPath itself) // Skip checking/pruning the main worktree (projectPath itself)
let worktreeExists = false; let worktreeExists = false;
@@ -89,15 +104,15 @@ export function createListHandler() {
// Worktree directory doesn't exist - it was manually deleted // Worktree directory doesn't exist - it was manually deleted
removedWorktrees.push({ removedWorktrees.push({
path: current.path, path: current.path,
branch: current.branch, branch: branchName,
}); });
} else { } else {
// Worktree exists (or is main worktree), add it to the list // Worktree exists (or is main worktree), add it to the list
worktrees.push({ worktrees.push({
path: current.path, path: current.path,
branch: current.branch, branch: branchName,
isMain: isMainWorktree, isMain: isMainWorktree,
isCurrent: current.branch === currentBranch, isCurrent: branchName === currentBranch,
hasWorktree: true, hasWorktree: true,
}); });
isFirst = false; isFirst = false;
@@ -107,6 +122,48 @@ export function createListHandler() {
} }
} }
// Handle the last worktree entry if output doesn't end with blank line
if (current.path) {
const isMainWorktree = isFirst;
// If branch is missing (can happen for main worktree in some git states),
// fall back to getCurrentBranch() for the main worktree
let branchName = current.branch;
if (!branchName && isMainWorktree) {
// For main worktree, use the current branch we already fetched
branchName = currentBranch || '';
}
// Only add if we have a branch name
if (branchName) {
// Check if the worktree directory actually exists
// Skip checking/pruning the main worktree (projectPath itself)
let worktreeExists = false;
try {
await secureFs.access(current.path);
worktreeExists = true;
} catch {
worktreeExists = false;
}
if (!isMainWorktree && !worktreeExists) {
// Worktree directory doesn't exist - it was manually deleted
removedWorktrees.push({
path: current.path,
branch: branchName,
});
} else {
// Worktree exists (or is main worktree), add it to the list
worktrees.push({
path: current.path,
branch: branchName,
isMain: isMainWorktree,
isCurrent: branchName === currentBranch,
hasWorktree: true,
});
}
}
}
// Prune removed worktrees from git (only if any were detected) // Prune removed worktrees from git (only if any were detected)
if (removedWorktrees.length > 0) { if (removedWorktrees.length > 0) {
try { try {

View File

@@ -14,7 +14,6 @@ import {
setupProjectWithPath, setupProjectWithPath,
waitForBoardView, waitForBoardView,
authenticateForTests, authenticateForTests,
handleLoginScreenIfPresent,
} from '../utils'; } from '../utils';
const TEST_TEMP_DIR = createTempDirPath('worktree-tests'); const TEST_TEMP_DIR = createTempDirPath('worktree-tests');
@@ -55,10 +54,16 @@ test.describe('Worktree Integration', () => {
await waitForNetworkIdle(page); await waitForNetworkIdle(page);
await waitForBoardView(page); await waitForBoardView(page);
// Wait for the worktree selector to appear (indicates API call completed)
const branchLabel = page.getByText('Branch:'); const branchLabel = page.getByText('Branch:');
await expect(branchLabel).toBeVisible({ timeout: 10000 }); await expect(branchLabel).toBeVisible({ timeout: 10000 });
// Wait for the main branch button to appear
// This ensures the worktree API has returned data with the main branch
const mainBranchButton = page.locator('[data-testid="worktree-branch-main"]'); const mainBranchButton = page.locator('[data-testid="worktree-branch-main"]');
await expect(mainBranchButton).toBeVisible({ timeout: 15000 }); await expect(mainBranchButton).toBeVisible({ timeout: 15000 });
// Verify the branch name is displayed
await expect(mainBranchButton).toContainText('main');
}); });
}); });