this adds recognition of the git_protocol setting when: - creating a repo - cloning a repo - forking a repo - forking/pushing during pr create - checking out a PR additionally, it: - consolidates remote adding to use AddRemote; this introduces a fetch where there previously hadn't been one - changes repo clone to accept an ssh url - changes repo fork to accept an ssh url i just added basic unit tests; adding new test cases for all of the above scenarios seemed like diminishing returns.
102 lines
1.8 KiB
Go
102 lines
1.8 KiB
Go
package git
|
|
|
|
import (
|
|
"net/url"
|
|
"os/exec"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/cli/cli/internal/run"
|
|
)
|
|
|
|
var remoteRE = regexp.MustCompile(`(.+)\s+(.+)\s+\((push|fetch)\)`)
|
|
|
|
// RemoteSet is a slice of git remotes
|
|
type RemoteSet []*Remote
|
|
|
|
// Remote is a parsed git remote
|
|
type Remote struct {
|
|
Name string
|
|
FetchURL *url.URL
|
|
PushURL *url.URL
|
|
}
|
|
|
|
func (r *Remote) String() string {
|
|
return r.Name
|
|
}
|
|
|
|
// Remotes gets the git remotes set for the current repo
|
|
func Remotes() (RemoteSet, error) {
|
|
list, err := listRemotes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return parseRemotes(list), nil
|
|
}
|
|
|
|
func parseRemotes(gitRemotes []string) (remotes RemoteSet) {
|
|
for _, r := range gitRemotes {
|
|
match := remoteRE.FindStringSubmatch(r)
|
|
if match == nil {
|
|
continue
|
|
}
|
|
name := strings.TrimSpace(match[1])
|
|
urlStr := strings.TrimSpace(match[2])
|
|
urlType := strings.TrimSpace(match[3])
|
|
|
|
var rem *Remote
|
|
if len(remotes) > 0 {
|
|
rem = remotes[len(remotes)-1]
|
|
if name != rem.Name {
|
|
rem = nil
|
|
}
|
|
}
|
|
if rem == nil {
|
|
rem = &Remote{Name: name}
|
|
remotes = append(remotes, rem)
|
|
}
|
|
|
|
u, err := ParseURL(urlStr)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
switch urlType {
|
|
case "fetch":
|
|
rem.FetchURL = u
|
|
case "push":
|
|
rem.PushURL = u
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// AddRemote adds a new git remote and auto-fetches objects from it
|
|
func AddRemote(name, u string) (*Remote, error) {
|
|
addCmd := exec.Command("git", "remote", "add", "-f", name, u)
|
|
err := run.PrepareCmd(addCmd).Run()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var urlParsed *url.URL
|
|
if strings.HasPrefix(u, "https") {
|
|
urlParsed, err = url.Parse(u)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
} else {
|
|
urlParsed, err = ParseURL(u)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
}
|
|
|
|
return &Remote{
|
|
Name: name,
|
|
FetchURL: urlParsed,
|
|
PushURL: urlParsed,
|
|
}, nil
|
|
}
|