GetAllWorktrees returns the refs that all worktrees are using as HEADs plus the worktree's path. This returns all worktrees plus the main working copy, and works even if working dir is actually in a worktree right now Pass in the git storage dir (parent of 'objects') to work from, in case we need t
(storageDir string)
| 916 | // Pass in the git storage dir (parent of 'objects') to work from, in case |
| 917 | // we need to fall back to reading the worktree files directly. |
| 918 | func GetAllWorktrees(storageDir string) ([]*Worktree, error) { |
| 919 | // Versions before 2.7.0 don't support "git-worktree list", and |
| 920 | // those before 2.36.0 don't support the "-z" option, so in these |
| 921 | // cases we fall back to reading the .git/worktrees directory entries |
| 922 | // and then reading the current worktree's HEAD ref. This requires |
| 923 | // the contents of .git/worktrees/*/gitdir files to be absolute paths, |
| 924 | // which is only true for Git versions prior to 2.48.0. |
| 925 | if !IsGitVersionAtLeast("2.36.0") { |
| 926 | return getAllWorktreesFromGitDir(storageDir) |
| 927 | } |
| 928 | |
| 929 | cmd, err := gitNoLFS( |
| 930 | "worktree", |
| 931 | "list", |
| 932 | "--porcelain", |
| 933 | "-z", // handle special chars in filenames |
| 934 | ) |
| 935 | if err != nil { |
| 936 | return nil, errors.New(tr.Tr.Get("failed to find `git worktree`: %v", err)) |
| 937 | } |
| 938 | |
| 939 | stdout, err := cmd.StdoutPipe() |
| 940 | if err != nil { |
| 941 | return nil, errors.New(tr.Tr.Get("failed to open output pipe to `git worktree`: %v", err)) |
| 942 | } |
| 943 | stderr, err := cmd.StderrPipe() |
| 944 | if err != nil { |
| 945 | return nil, errors.New(tr.Tr.Get("failed to open error pipe to `git worktree`: %v", err)) |
| 946 | } |
| 947 | |
| 948 | if err := cmd.Start(); err != nil { |
| 949 | return nil, errors.New(tr.Tr.Get("failed to start `git worktree`: %v", err)) |
| 950 | } |
| 951 | |
| 952 | scanner := bufio.NewScanner(stdout) |
| 953 | scanner.Split(tools.SplitOnNul) |
| 954 | var dir string |
| 955 | var ref *Ref |
| 956 | var prunable bool |
| 957 | var worktrees []*Worktree |
| 958 | for scanner.Scan() { |
| 959 | line := scanner.Text() |
| 960 | |
| 961 | if len(line) == 0 { |
| 962 | if len(dir) > 0 && ref != nil && len(ref.Sha) > 0 { |
| 963 | worktrees = append(worktrees, &Worktree{ |
| 964 | Ref: *ref, |
| 965 | Dir: dir, |
| 966 | Prunable: prunable, |
| 967 | }) |
| 968 | } |
| 969 | dir = "" |
| 970 | ref = nil |
| 971 | continue |
| 972 | } |
| 973 | |
| 974 | parts := strings.SplitN(scanner.Text(), " ", 2) |
| 975 |