Skip to content

Commit 3c016d7

Browse files
committed
fix: honor config when detecting managed worktrees
1 parent 4b6f91c commit 3c016d7

File tree

5 files changed

+58
-119
lines changed

5 files changed

+58
-119
lines changed

cmd/wtp/cd.go

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,7 @@ import (
2020

2121
// isWorktreeManagedCd determines if a worktree is managed by wtp (for cd command)
2222
func isWorktreeManagedCd(worktreePath string, cfg *config.Config, mainRepoPath string, isMain bool) bool {
23-
// Main worktree is always managed
24-
if isMain {
25-
return true
26-
}
27-
28-
// Get base directory - use default config if config is not available
29-
if cfg == nil {
30-
// Create default config when none is available
31-
defaultCfg := &config.Config{
32-
Defaults: config.Defaults{
33-
BaseDir: "../worktrees",
34-
},
35-
}
36-
cfg = defaultCfg
37-
}
38-
39-
baseDir := cfg.ResolveWorktreePath(mainRepoPath, "")
40-
// Remove trailing slash if it exists
41-
baseDir = strings.TrimSuffix(baseDir, "/")
42-
43-
// Check if worktree path is under base directory
44-
absWorktreePath, err := filepath.Abs(worktreePath)
45-
if err != nil {
46-
return false
47-
}
48-
49-
absBaseDir, err := filepath.Abs(baseDir)
50-
if err != nil {
51-
return false
52-
}
53-
54-
// Check if worktree is within base directory
55-
relPath, err := filepath.Rel(absBaseDir, absWorktreePath)
56-
if err != nil {
57-
return false
58-
}
59-
60-
// If relative path starts with "..", it's outside base directory
61-
return !strings.HasPrefix(relPath, "..")
23+
return isWorktreeManagedCommon(worktreePath, cfg, mainRepoPath, isMain)
6224
}
6325

6426
// NewCdCommand creates the cd command definition

cmd/wtp/list.go

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -162,45 +162,7 @@ func parseWorktreesFromOutput(output string) []git.Worktree {
162162

163163
// isWorktreeManagedList determines if a worktree is managed by wtp (for list command)
164164
func isWorktreeManagedList(worktreePath string, cfg *config.Config, mainRepoPath string, isMain bool) bool {
165-
// Main worktree is always managed
166-
if isMain {
167-
return true
168-
}
169-
170-
// Get base directory - use default config if config is not available
171-
if cfg == nil {
172-
// Create default config when none is available
173-
defaultCfg := &config.Config{
174-
Defaults: config.Defaults{
175-
BaseDir: "../worktrees",
176-
},
177-
}
178-
cfg = defaultCfg
179-
}
180-
181-
baseDir := cfg.ResolveWorktreePath(mainRepoPath, "")
182-
// Remove trailing slash if it exists
183-
baseDir = strings.TrimSuffix(baseDir, "/")
184-
185-
// Check if worktree path is under base directory
186-
absWorktreePath, err := filepath.Abs(worktreePath)
187-
if err != nil {
188-
return false
189-
}
190-
191-
absBaseDir, err := filepath.Abs(baseDir)
192-
if err != nil {
193-
return false
194-
}
195-
196-
// Check if worktree is within base directory
197-
relPath, err := filepath.Rel(absBaseDir, absWorktreePath)
198-
if err != nil {
199-
return false
200-
}
201-
202-
// If relative path starts with "..", it's outside base directory
203-
return !strings.HasPrefix(relPath, "..")
165+
return isWorktreeManagedCommon(worktreePath, cfg, mainRepoPath, isMain)
204166
}
205167

206168
// formatBranchDisplay formats branch name for display, following Git conventions

cmd/wtp/remove.go

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,45 +23,7 @@ var removeGetwd = os.Getwd
2323

2424
// isWorktreeManaged determines if a worktree is managed by wtp
2525
func isWorktreeManaged(worktreePath string, cfg *config.Config, mainRepoPath string, isMain bool) bool {
26-
// Main worktree is always managed
27-
if isMain {
28-
return true
29-
}
30-
31-
// Get base directory - use default config if config is not available
32-
if cfg == nil {
33-
// Create default config when none is available
34-
defaultCfg := &config.Config{
35-
Defaults: config.Defaults{
36-
BaseDir: "../worktrees",
37-
},
38-
}
39-
cfg = defaultCfg
40-
}
41-
42-
baseDir := cfg.ResolveWorktreePath(mainRepoPath, "")
43-
// Remove trailing slash if it exists
44-
baseDir = strings.TrimSuffix(baseDir, "/")
45-
46-
// Check if worktree path is under base directory
47-
absWorktreePath, err := filepath.Abs(worktreePath)
48-
if err != nil {
49-
return false
50-
}
51-
52-
absBaseDir, err := filepath.Abs(baseDir)
53-
if err != nil {
54-
return false
55-
}
56-
57-
// Check if worktree is within base directory
58-
relPath, err := filepath.Rel(absBaseDir, absWorktreePath)
59-
if err != nil {
60-
return false
61-
}
62-
63-
// If relative path starts with "..", it's outside base directory
64-
return !strings.HasPrefix(relPath, "..")
26+
return isWorktreeManagedCommon(worktreePath, cfg, mainRepoPath, isMain)
6527
}
6628

6729
// NewRemoveCommand creates the remove command definition
@@ -163,7 +125,7 @@ func removeCommandWithCommandExecutor(
163125
return errors.DirectoryAccessFailed("access current", cwd, err)
164126
}
165127

166-
if isPathWithin(absCwd, absTargetPath) {
128+
if isPathWithin(absTargetPath, absCwd) {
167129
return errors.CannotRemoveCurrentWorktree(worktreeName, absTargetPath)
168130
}
169131

cmd/wtp/remove_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ func TestRemoveCommand_WorktreeNotFound_ShowsConsistentNames(t *testing.T) {
391391
}
392392

393393
func TestRemoveCommand_FailsWhenRemovingCurrentWorktree(t *testing.T) {
394-
targetPath := "/repo/worktrees/feature/foo"
394+
targetPath := "/worktrees/feature/foo"
395395
mockWorktreeList := fmt.Sprintf(
396396
"worktree /repo\nHEAD abc123\nbranch refs/heads/main\n\n"+
397397
"worktree %s\nHEAD def456\nbranch refs/heads/feature/foo\n\n",

cmd/wtp/worktree_managed.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"path/filepath"
5+
"strings"
6+
7+
"github.com/satococoa/wtp/internal/config"
8+
)
9+
10+
// isWorktreeManagedCommon determines whether a worktree path is considered managed by wtp.
11+
// The logic is shared across multiple commands so that we consistently classify worktrees.
12+
func isWorktreeManagedCommon(worktreePath string, cfg *config.Config, mainRepoPath string, isMain bool) bool {
13+
if isMain {
14+
return true
15+
}
16+
17+
// Fallback to default configuration if none is provided
18+
if cfg == nil {
19+
cfg = &config.Config{
20+
Defaults: config.Defaults{
21+
BaseDir: config.DefaultBaseDir,
22+
},
23+
}
24+
}
25+
26+
baseDir := cfg.ResolveWorktreePath(mainRepoPath, "")
27+
baseDir = strings.TrimSuffix(baseDir, string(filepath.Separator))
28+
29+
absWorktreePath, err := filepath.Abs(worktreePath)
30+
if err != nil {
31+
return false
32+
}
33+
34+
absBaseDir, err := filepath.Abs(baseDir)
35+
if err != nil {
36+
return false
37+
}
38+
39+
relPath, err := filepath.Rel(absBaseDir, absWorktreePath)
40+
if err != nil {
41+
return false
42+
}
43+
44+
if relPath == "." || relPath == "" {
45+
return true
46+
}
47+
48+
if relPath == ".." || strings.HasPrefix(relPath, ".."+string(filepath.Separator)) {
49+
return false
50+
}
51+
52+
return true
53+
}

0 commit comments

Comments
 (0)