diff --git a/internal/storage/commits.go b/internal/storage/commits.go index 1a94cc4..5487370 100644 --- a/internal/storage/commits.go +++ b/internal/storage/commits.go @@ -108,25 +108,34 @@ func (r *Repository) ReadBranch(name string) (string, error) { // WriteBranch writes a branch reference func (r *Repository) WriteBranch(name string, commitID string) error { path := filepath.Join(r.TinPath, RefsDir, HeadsDir, name) + // Create parent directories if they don't exist (for branches like "feature/foo") + if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { + return err + } return os.WriteFile(path, []byte(commitID), 0644) } // ListBranches returns all branch names func (r *Repository) ListBranches() ([]string, error) { headsPath := filepath.Join(r.TinPath, RefsDir, HeadsDir) - entries, err := os.ReadDir(headsPath) - if err != nil { - if os.IsNotExist(err) { - return []string{}, nil - } - return nil, err + if _, err := os.Stat(headsPath); os.IsNotExist(err) { + return []string{}, nil } var branches []string - for _, entry := range entries { - if !entry.IsDir() { - branches = append(branches, entry.Name()) + err := filepath.WalkDir(headsPath, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + // Get branch name relative to heads directory + relPath, _ := filepath.Rel(headsPath, path) + branches = append(branches, relPath) } + return nil + }) + if err != nil { + return nil, err } sort.Strings(branches) diff --git a/internal/storage/commits_test.go b/internal/storage/commits_test.go index dce5869..3488f18 100644 --- a/internal/storage/commits_test.go +++ b/internal/storage/commits_test.go @@ -112,21 +112,21 @@ func TestRepository_BranchOperations(t *testing.T) { t.Errorf("expected 0 branches initially, got %d", len(branches)) } - // Create new branch - if err := repo.WriteBranch("feature", "commit-123"); err != nil { + // Create new branch (with slash to test nested directory creation) + if err := repo.WriteBranch("feature/test", "commit-123"); err != nil { t.Fatalf("WriteBranch failed: %v", err) } // Verify branch exists - if !repo.BranchExists("feature") { - t.Error("expected 'feature' branch to exist") + if !repo.BranchExists("feature/test") { + t.Error("expected 'feature/test' branch to exist") } if repo.BranchExists("nonexistent") { t.Error("expected 'nonexistent' branch to not exist") } // Read branch - commitID, err := repo.ReadBranch("feature") + commitID, err := repo.ReadBranch("feature/test") if err != nil { t.Fatalf("ReadBranch failed: %v", err) } @@ -152,17 +152,17 @@ func TestRepository_DeleteBranch(t *testing.T) { t.Fatalf("Init failed: %v", err) } - // Create branch - repo.WriteBranch("feature", "commit-123") + // Create branch (with slash to test nested directory creation) + repo.WriteBranch("feature/test", "commit-123") // Delete it - if err := repo.DeleteBranch("feature"); err != nil { + if err := repo.DeleteBranch("feature/test"); err != nil { t.Fatalf("DeleteBranch failed: %v", err) } // Verify deleted - if repo.BranchExists("feature") { - t.Error("expected 'feature' branch to be deleted") + if repo.BranchExists("feature/test") { + t.Error("expected 'feature/test' branch to be deleted") } }