Skip to content

Refactor worktree.ts — replace 28 try/catch and 24 ignore comments with git helpers #176

@xliry

Description

@xliry

Problem

worktree.ts (316 lines) has 28 try blocks, 28 catch blocks, and 24 /* ignore */ comments. It's the worst offender in the codebase. Most try/catch blocks exist because raw execSync is used for every git operation.

Depends on

What to do

1. createWorktree() (lines 47-86)

Current: 4 nested try/catch, 3 ignore comments.

// BEFORE: try { execSync('git worktree remove...') } catch { /* ignore */ }
// AFTER:  if (worktreeExists(workspace, path)) git.removeWorktree(workspace, path);
  • Use worktreeExists() and branchExists() to check before acting
  • Use git.deleteBranch() instead of try/catch around git branch -D
  • One outer error return if git worktree add itself fails

2. mergeWorktree() (lines 98-200) — the biggest mess

Current: deeply nested try/catch pyramid, didStash flag checked in 5 places.

Refactor to step-based approach:

function mergeWorktree(workspace, branch): MergeResult {
  const didStash = git.stash(workspace);
  const cleanup = () => { if (didStash) git.stashPop(workspace); };

  // Step 1: Pull latest
  git.pull(workspace, "origin", "main");

  // Step 2: Try merge
  const mergeResult = git.merge(workspace, branch);
  if (!mergeResult.ok && mergeResult.hasConflicts) {
    git.mergeAbort(workspace);
    const rebaseResult = tryRebaseThenMerge(workspace, branch);
    if (!rebaseResult) { cleanup(); return { success: false, hasConflicts: true, ... }; }
    cleanup();
    return rebaseResult;
  }
  if (!mergeResult.ok) { cleanup(); return { success: false, ... }; }

  // Step 3: Push with retry
  const pushed = pushWithRetry(workspace, branch, 3);
  cleanup();
  return pushed;
}

3. tryRebaseThenMerge() (lines 206-266)

  • Use git.rebase() and git.rebaseAbort() instead of try/catch
  • Use git.merge() for the ff-only step
  • Use git.push() for the push step

4. cleanupWorktree() (lines 269-286)

Current: 2 try/catch with ignore.

  • Use worktreeExists() check + git.removeWorktree()
  • Use branchExists() check + git.deleteBranch()

5. cleanStaleWorktrees() (lines 292-316)

Current: 3 nested try/catch with ignore.

  • Use git helpers for prune and remove operations

6. isGitRepo() (lines 18-25)

  • DELETE from worktree.ts — it's now in git.ts
  • Update imports

Target metrics

  • try blocks: 28 → 0-2
  • catch blocks: 28 → 0-2
  • /* ignore */: 24 → 0
  • Lines: ~316 → ~150-180

Files

  • src/worktree.ts — major refactor

Acceptance

  • Zero /* ignore */ comments
  • All git operations use git.ts helpers
  • Same external behavior (createWorktree, mergeWorktree, cleanupWorktree APIs unchanged)
  • Code is ~half the current size

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions