ExtractRemotes extracts all Git remotes from the Git repository at projectPath. If detectDotGit is true, it will look for a .git directory in parent directories. Shells out to the `git` CLI so it works inside linked worktrees, where `.git` is a file pointing to the main repo's worktree dir and the r
(projectPath string, detectDotGit bool)
| 124 | // file pointing to the main repo's worktree dir and the remote config is reachable |
| 125 | // only via `commondir` (which go-git's PlainOpen does not resolve). |
| 126 | func ExtractRemotes(projectPath string, detectDotGit bool) ([]Remote, error) { |
| 127 | if !detectDotGit { |
| 128 | // require a .git entry at exactly this path: a directory in a regular |
| 129 | // checkout, or a file in a linked worktree. |
| 130 | if _, err := os.Stat(filepath.Join(projectPath, ".git")); err != nil { |
| 131 | if os.IsNotExist(err) { |
| 132 | return nil, ErrNotAGitRepository |
| 133 | } |
| 134 | return nil, err |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | out, err := exec.Command("git", "-C", projectPath, "remote").Output() |
| 139 | if err != nil { |
| 140 | var execErr *exec.ExitError |
| 141 | if errors.As(err, &execErr) { |
| 142 | stderr := strings.TrimSpace(string(execErr.Stderr)) |
| 143 | if strings.Contains(stderr, "not a git repository") { |
| 144 | return nil, ErrNotAGitRepository |
| 145 | } |
| 146 | return nil, fmt.Errorf("git remote: %s", stderr) |
| 147 | } |
| 148 | return nil, err |
| 149 | } |
| 150 | |
| 151 | names := strings.Fields(string(out)) |
| 152 | res := make([]Remote, 0, len(names)) |
| 153 | for _, name := range names { |
| 154 | urlOut, err := exec.Command("git", "-C", projectPath, "remote", "get-url", name).Output() |
| 155 | if err != nil { |
| 156 | return nil, fmt.Errorf("failed to get URL for git remote %q: %w", name, err) |
| 157 | } |
| 158 | u := strings.TrimSpace(string(urlOut)) |
| 159 | if u == "" { |
| 160 | return nil, fmt.Errorf("no URL found for git remote %q", name) |
| 161 | } |
| 162 | res = append(res, Remote{Name: name, URL: u}) |
| 163 | } |
| 164 | |
| 165 | return res, nil |
| 166 | } |
| 167 | |
| 168 | func CommitAndPush(ctx context.Context, projectPath string, config *Config, commitMsg string, author *object.Signature) error { |
| 169 | // init git repo |
no test coverage detected