Skip to content

v0.21.15.0 fix(workspace): sanitize default branch name so spaces don't break worktree create#67

Merged
avinashjoshi merged 2 commits into
mainfrom
fix-branch-name-sanitize
Jun 25, 2026
Merged

v0.21.15.0 fix(workspace): sanitize default branch name so spaces don't break worktree create#67
avinashjoshi merged 2 commits into
mainfrom
fix-branch-name-sanitize

Conversation

@avinashjoshi

Copy link
Copy Markdown
Owner

Summary

Performance / correctness fix. Typing a workspace name with a space in the TUI new-workspace box (e.g. testing codex) fataled creation:

git: git.Add(testing codex -> .../testing-codex): exit status 255
  fatal: 'testing codex' is not a valid branch name

canopy sanitized the name correctly for the on-disk path (testing codextesting-codex) but passed the raw, space-bearing name straight to git worktree add -b as the branch. Git accepts slashes in refs (feature/oauth) but rejects spaces, colons, .., ~ — so any git-invalid name broke creation.

The fix sanitizes the branch on the fallback path only (internal/workspace/lifecycle.go Create): branch := git.Sanitize(name) when no explicit --branch was supplied. An explicit canopy new x --branch feature/y is still passed to git verbatim — the caller knows what they want, and feature/y is a valid ref Sanitize would have mangled to feature-y. This also realigns a latent inconsistency: the on-disk path basename was already git.Sanitize(name), so for any space-bearing name the branch and path had silently diverged. Now branch == path basename == tmux session holds for every input (the v0 "four names match" invariant).

internal/git/worktree.go's Sanitize doc comment was rewritten to drop the now-false "the git branch keeps its original name" claim.

Test Coverage

All new code paths covered (effectively 100%):

  • TestCreate_SanitizesBranchNameWhenNoExplicitBranchtesting codex → branch testing-codex, creates cleanly, verifies the real git branch via rev-parse.
  • TestCreate_PreservesExplicitBranchName--branch feature/y survives intact (not sanitized).
  • TestCreate_AlreadyValidNameUnchanged — guards against over-sanitizing valid names.
  • TestSanitize — +6 table cases (interior space, collapsing spaces, padded interior, multiple spaces, tilde, idempotent).

Both branches of the if opts.Branch != "" conditional are exercised.

Tests: internal/workspace +3 funcs; internal/git TestSanitize 16 → 22 cases.

Pre-Landing Review

No issues. Diff is minimal with no SQL/LLM/security surface. Adversarial note: git.Sanitize could collapse a pathological all-symbol name (e.g. "///") to "", but that's pre-existing (the path basename already used Sanitize), not introduced here, and namegen handles the empty-name case. The dot-sequence gap (.., trailing ., .lock survive Sanitize) is a rarer instance of the same class — captured as a P3 follow-up in TODOS.md rather than expanded here.

Verification

  • go build ./... — OK
  • go vet ./... — clean
  • go test ./... — all packages pass
  • go test -tags=e2e ./internal/git/ ./internal/workspace/ — pass (real git + tmux)

Test plan

  • Full unit suite passes (go test ./...)
  • e2e-tagged worktree + workspace tests pass
  • Build and vet clean

🤖 Generated with Claude Code

avinashjoshi and others added 2 commits June 25, 2026 11:15
…t worktree add

A workspace name with a space (e.g. "testing codex") fataled creation:
`git worktree add -b 'testing codex'` rejects the ref. canopy sanitized
the on-disk path but passed the raw name to git as the branch.

Create now derives the default branch via git.Sanitize(name) on the
fallback path only. An explicit --branch is still passed verbatim
(feature/oauth is a valid ref Sanitize would mangle). This realigns
branch == path basename == tmux session for every input.

Tests cover both conditional branches plus Sanitize edge cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@avinashjoshi avinashjoshi merged commit 0f41a0d into main Jun 25, 2026
2 checks passed
@avinashjoshi avinashjoshi deleted the fix-branch-name-sanitize branch June 25, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant