Skip to content

Commit d124640

Browse files
authored
Merge pull request #10 from tobiase/address-pr9-feedback
fix: address critical PR 9 feedback issues
2 parents da9bae0 + dff7766 commit d124640

3 files changed

Lines changed: 28 additions & 22 deletions

File tree

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,6 @@ wt env-copy feature # Shows: "Consider using 'wt env sync' instead"
582582
- Add new subcommands alongside existing commands
583583
- Extend existing commands with new flags
584584
- Provide multiple interfaces to the same functionality
585-
- Use deprecation warnings before removal
586585
587586
## Claude Code Integration
588587

cmd/wt/main.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import (
1919

2020
// Version information - set by build flags
2121
var (
22-
version = "dev"
23-
buildTime = "unknown"
22+
version = "dev"
23+
date = "unknown"
2424
)
2525

2626
// osExit is a variable for testing - allows overriding os.Exit
@@ -83,6 +83,8 @@ wt() {
8383
if [ -n "$cd_path" ]; then
8484
cd "$cd_path"
8585
elif [ -n "$exec_cmd" ]; then
86+
# Security note: EXEC commands are only used for virtualenv activation
87+
# and paths are quoted by the Go binary to prevent injection
8688
eval "$exec_cmd"
8789
fi
8890
else
@@ -139,6 +141,10 @@ func resolveCommandAlias(cmd string) string {
139141
}
140142

141143
// printErrorAndExit prints an error message and exits with status 1
144+
// NOTE: This function is used throughout the codebase for consistent error handling.
145+
// Future refactoring should move towards returning errors from command handlers
146+
// and handling exits centrally in main(), but this pattern is maintained for
147+
// backward compatibility and to minimize changes.
142148
func printErrorAndExit(format string, args ...interface{}) {
143149
fmt.Fprintf(os.Stderr, "wt: "+format+"\n", args...)
144150
osExit(1)
@@ -230,8 +236,7 @@ func handleListCommand(args []string) {
230236
}
231237

232238
if err := worktree.List(); err != nil {
233-
fmt.Fprintf(os.Stderr, "wt: %v\n", err)
234-
osExit(1)
239+
printErrorAndExit("%v", err)
235240
}
236241
}
237242

@@ -263,21 +268,18 @@ func handleRemoveCommand(args []string) {
263268
// Resolve target with fuzzy matching
264269
branches, branchErr := worktree.GetAvailableBranches()
265270
if branchErr != nil {
266-
fmt.Fprintf(os.Stderr, "wt: %v\n", branchErr)
267-
osExit(1)
271+
printErrorAndExit("%v", branchErr)
268272
}
269273

270274
resolvedTarget, resolveErr := worktree.ResolveBranchName(target, branches)
271275
if resolveErr != nil {
272-
fmt.Fprintf(os.Stderr, "wt: %v\n", resolveErr)
273-
osExit(1)
276+
printErrorAndExit("%v", resolveErr)
274277
}
275278
target = resolvedTarget
276279
}
277280

278281
if err := worktree.Remove(target); err != nil {
279-
fmt.Fprintf(os.Stderr, "wt: %v\n", err)
280-
osExit(1)
282+
printErrorAndExit("%v", err)
281283
}
282284
}
283285

@@ -426,9 +428,6 @@ func handleEnvCopyCommand(args []string) {
426428
return
427429
}
428430

429-
// Show deprecation warning
430-
fmt.Fprintf(os.Stderr, "Warning: 'wt env-copy' is deprecated. Use 'wt env sync' instead.\n")
431-
432431
// Parse flags
433432
var useFuzzy bool
434433
var target string
@@ -635,8 +634,8 @@ func handleVersionCommand(args []string) {
635634
versionStr = "dev"
636635
}
637636

638-
if buildTime != "" && buildTime != "unknown" {
639-
fmt.Printf("wt version %s (built %s)\n", versionStr, buildTime)
637+
if date != "" && date != "unknown" {
638+
fmt.Printf("wt version %s (built %s)\n", versionStr, date)
640639
} else {
641640
fmt.Printf("wt version %s\n", versionStr)
642641
}
@@ -699,6 +698,13 @@ func handleVirtualenvCommand(navCmd *config.NavigationCommand, configMgr *config
699698

700699
venvPath := filepath.Join(repo, venvName)
701700

701+
// Validate that venvPath is within the repository
702+
absRepo, _ := filepath.Abs(repo)
703+
absVenvPath, _ := filepath.Abs(venvPath)
704+
if !strings.HasPrefix(absVenvPath, absRepo) {
705+
printErrorAndExit("invalid virtualenv path: must be within repository")
706+
}
707+
702708
switch navCmd.Target {
703709
case "activate":
704710
// Check if virtualenv exists
@@ -709,7 +715,8 @@ func handleVirtualenvCommand(navCmd *config.NavigationCommand, configMgr *config
709715
osExit(1)
710716
}
711717
// Output EXEC command to activate virtualenv
712-
fmt.Printf("EXEC:source %s", activateScript)
718+
// Use printf with %q to properly quote the path for shell safety
719+
fmt.Printf("EXEC:source %q", activateScript)
713720

714721
case "create":
715722
// Check if virtualenv already exists

cmd/wt/main_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,33 @@ func TestHandleVersionCommand(t *testing.T) {
4343
tests := []struct {
4444
name string
4545
version string
46-
buildTime string
46+
date string
4747
wantContain string
4848
}{
4949
{
5050
name: "with version and build time",
5151
version: "1.2.3",
52-
buildTime: "2024-01-01",
52+
date: "2024-01-01",
5353
wantContain: "wt version 1.2.3 (built 2024-01-01)",
5454
},
5555
{
5656
name: "development version",
5757
version: "dev",
58-
buildTime: "",
58+
date: "",
5959
wantContain: "wt version dev",
6060
},
6161
{
6262
name: "empty version",
6363
version: "",
64-
buildTime: "",
64+
date: "",
6565
wantContain: "wt version dev",
6666
},
6767
}
6868

6969
for _, tt := range tests {
7070
t.Run(tt.name, func(t *testing.T) {
7171
version = tt.version
72-
buildTime = tt.buildTime
72+
date = tt.date
7373

7474
stdout, _, err := captureOutput(func() error {
7575
handleVersionCommand([]string{})

0 commit comments

Comments
 (0)