Skip to content

Commit 3470da4

Browse files
authored
show worktree locations in av tree output (#675)
branches checked out in worktrees now show the worktree directory name next to them
1 parent 81b826c commit 3470da4

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

cmd/av/tree.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"path/filepath"
67
"strings"
78

89
"github.com/aviator-co/av/internal/git"
@@ -36,6 +37,14 @@ var treeCmd = &cobra.Command{
3637
return err
3738
}
3839

40+
worktrees, _ := repo.WorktreeList(ctx)
41+
worktreesByBranch := make(map[string]string)
42+
for _, wt := range worktrees {
43+
if wt.Branch != "" {
44+
worktreesByBranch[wt.Branch] = filepath.Base(wt.Path)
45+
}
46+
}
47+
3948
var ss []string
4049
currentBranch := status.CurrentBranch
4150
tx := db.ReadTx()
@@ -59,6 +68,7 @@ var treeCmd = &cobra.Command{
5968
currentBranch,
6069
branchName,
6170
isTrunk,
71+
worktreesByBranch,
6272
)
6373
}),
6474
)
@@ -96,6 +106,7 @@ func renderStackTreeBranchInfo(
96106
currentBranchName string,
97107
branchName string,
98108
isTrunk bool,
109+
worktrees map[string]string,
99110
) string {
100111
bi, _ := tx.Branch(branchName)
101112

@@ -104,6 +115,8 @@ func renderStackTreeBranchInfo(
104115
var stats []string
105116
if branchName == currentBranchName {
106117
stats = append(stats, styles.HEAD.Render("HEAD"))
118+
} else if wtName, ok := worktrees[branchName]; ok {
119+
stats = append(stats, colors.Faint("worktree: "+wtName))
107120
}
108121
if bi.ExcludeFromSyncAll {
109122
descendants := meta.SubsequentBranches(tx, branchName)

internal/git/worktree.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package git
2+
3+
import (
4+
"context"
5+
"strings"
6+
)
7+
8+
type WorktreeInfo struct {
9+
Path string
10+
HEAD string
11+
Branch string
12+
}
13+
14+
func (r *Repo) WorktreeList(ctx context.Context) ([]WorktreeInfo, error) {
15+
out, err := r.Git(ctx, "worktree", "list", "--porcelain")
16+
if err != nil {
17+
return nil, err
18+
}
19+
out = strings.TrimSpace(out)
20+
if out == "" {
21+
return nil, nil
22+
}
23+
24+
var worktrees []WorktreeInfo
25+
var current WorktreeInfo
26+
for line := range strings.SplitSeq(out, "\n") {
27+
if line == "" {
28+
if current.Path != "" {
29+
worktrees = append(worktrees, current)
30+
}
31+
current = WorktreeInfo{}
32+
continue
33+
}
34+
if rest, ok := strings.CutPrefix(line, "worktree "); ok {
35+
current.Path = rest
36+
} else if rest, ok := strings.CutPrefix(line, "HEAD "); ok {
37+
current.HEAD = rest
38+
} else if rest, ok := strings.CutPrefix(line, "branch "); ok {
39+
current.Branch = strings.TrimPrefix(rest, "refs/heads/")
40+
}
41+
}
42+
if current.Path != "" {
43+
worktrees = append(worktrees, current)
44+
}
45+
return worktrees, nil
46+
}

0 commit comments

Comments
 (0)