Skip to content

Commit be73237

Browse files
authored
[fix] Protect worktree operands with separator (#256)
fix(git): protect worktree operands with separator Pass AddWorktree and MoveWorktree positional operands after -- so dash-leading sources or paths stay data instead of being parsed as git options. Keep MoveWorktree force flags before the separator, and cover the exact argv shape with focused mock runner tests. Co-authored-by: lugassawan
1 parent 3d28494 commit be73237

2 files changed

Lines changed: 10 additions & 12 deletions

File tree

internal/git/mock_runner_test.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ func TestRemoveWorktreeForce(t *testing.T) {
325325
}
326326
}
327327

328-
func TestMoveWorktreeNoForce(t *testing.T) {
328+
func TestMoveWorktreeInsertsDashDash(t *testing.T) {
329329
var captured []string
330330
r := &mockRunner{
331331
run: func(args ...string) (string, error) {
@@ -337,8 +337,10 @@ func TestMoveWorktreeNoForce(t *testing.T) {
337337
if err := MoveWorktree(r, "/old/path", "/new/path", false); err != nil {
338338
t.Fatalf("MoveWorktree: %v", err)
339339
}
340-
if slices.Contains(captured, flagForce) {
341-
t.Error("--force should not be present when force=false")
340+
341+
want := []string{cmdWorktree, "move", "--", "/old/path", "/new/path"}
342+
if !slices.Equal(captured, want) {
343+
t.Errorf("args = %v, want %v", captured, want)
342344
}
343345
}
344346

@@ -355,14 +357,9 @@ func TestMoveWorktreeForce(t *testing.T) {
355357
t.Fatalf("MoveWorktree: %v", err)
356358
}
357359
// git worktree move requires --force twice to move locked worktrees
358-
forceCount := 0
359-
for _, a := range captured {
360-
if a == flagForce {
361-
forceCount++
362-
}
363-
}
364-
if forceCount != 2 {
365-
t.Errorf("expected 2 %s flags, got %d in args %v", flagForce, forceCount, captured)
360+
want := []string{cmdWorktree, "move", flagForce, flagForce, "--", "/old/path", "/new/path"}
361+
if !slices.Equal(captured, want) {
362+
t.Errorf("args = %v, want %v", captured, want)
366363
}
367364
}
368365

internal/git/worktree.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ func RemoveWorktree(ctx context.Context, r Runner, path string, force bool) erro
5252
// When force is true, --force is passed twice so that even locked worktrees can be moved.
5353
// Intentionally non-cancellable: rollback moves must complete to avoid stranded worktrees.
5454
func MoveWorktree(r Runner, oldPath, newPath string, force bool) error {
55-
args := []string{cmdWorktree, "move", oldPath, newPath}
55+
args := []string{cmdWorktree, "move"}
5656
if force {
5757
args = append(args, flagForce, flagForce)
5858
}
59+
args = append(args, "--", oldPath, newPath)
5960
_, err := r.Run(context.Background(), args...)
6061
return err
6162
}

0 commit comments

Comments
 (0)