resolveWorktreeTarget asks git where path lives, letting git resolve symlinks, "..", case, and trailing slashes for us instead of comparing paths ourselves. It returns whether an existing linked worktree there should be reused, and errors when the path cannot host a new worktree: a path inside a dif
(client *git.Client, path string)
| 67 | // target worktree (e.g. the path does not exist yet), reuse is false so git |
| 68 | // worktree add handles the path. |
| 69 | func resolveWorktreeTarget(client *git.Client, path string) (reuseWorktree bool, err error) { |
| 70 | abs, err := filepath.Abs(path) |
| 71 | if err != nil { |
| 72 | return false, err |
| 73 | } |
| 74 | |
| 75 | // git emits one line per flag, so we expect exactly two lines here. |
| 76 | current, ok := revParseFacts(client, "", "--show-toplevel", "--git-common-dir") |
| 77 | if !ok || len(current) != 2 { |
| 78 | return false, nil |
| 79 | } |
| 80 | currentToplevel, currentCommonDir := current[0], current[1] |
| 81 | |
| 82 | // A non-existent or non-git target fails here: it is a fresh path for a new worktree. |
| 83 | target, ok := revParseFacts(client, abs, "--show-toplevel", "--show-prefix", "--git-common-dir") |
| 84 | if !ok || len(target) != 3 { |
| 85 | return false, nil |
| 86 | } |
| 87 | targetToplevel, targetPrefix, targetCommonDir := target[0], target[1], target[2] |
| 88 | |
| 89 | switch { |
| 90 | case targetCommonDir != currentCommonDir: |
| 91 | return false, fmt.Errorf("--worktree path is inside a different repository") |
| 92 | case targetToplevel == currentToplevel: |
| 93 | return false, fmt.Errorf("--worktree path points to the repository you're already in; omit --worktree to check out here") |
| 94 | case targetPrefix != "": |
| 95 | return false, fmt.Errorf("--worktree path is inside an existing worktree") |
| 96 | } |
| 97 | return true, nil |
| 98 | } |
| 99 | |
| 100 | func revParseFacts(client *git.Client, dir string, flags ...string) (fields []string, ok bool) { |
| 101 | args := append([]string{"rev-parse", "--path-format=absolute"}, flags...) |
no test coverage detected