50 lines
1.4 KiB
Go
50 lines
1.4 KiB
Go
package git
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// Remote holds the parsed coordinates of a git remote.
|
|
type Remote struct {
|
|
Host string
|
|
Owner string
|
|
Repo string
|
|
}
|
|
|
|
var (
|
|
httpsRE = regexp.MustCompile(`^https?://(?:[^@]+@)?([^/:]+)(?::\d+)?/([^/]+)/([^/]+?)(?:\.git)?/?$`)
|
|
sshRE = regexp.MustCompile(`^(?:ssh://)?(?:[^@]+@)?([^/:]+)[:/]([^/]+)/([^/]+?)(?:\.git)?/?$`)
|
|
)
|
|
|
|
// ParseRemoteURL parses a git remote URL into its Host, Owner, and Repo parts.
|
|
// Supports https, ssh (git@host:owner/repo), and ssh:// forms.
|
|
func ParseRemoteURL(url string) (*Remote, error) {
|
|
trimmed := strings.TrimSpace(url)
|
|
if trimmed == "" {
|
|
return nil, fmt.Errorf("empty remote URL")
|
|
}
|
|
|
|
if m := httpsRE.FindStringSubmatch(trimmed); m != nil {
|
|
return &Remote{Host: m[1], Owner: m[2], Repo: m[3]}, nil
|
|
}
|
|
|
|
if m := sshRE.FindStringSubmatch(trimmed); m != nil {
|
|
return &Remote{Host: m[1], Owner: m[2], Repo: m[3]}, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("unrecognized remote URL format: %q", trimmed)
|
|
}
|
|
|
|
// DetectRepo resolves the origin remote URL for the given workspace root
|
|
// and parses it into a Remote.
|
|
func DetectRepo(workspaceRoot string) (*Remote, error) {
|
|
out, err := exec.Command("git", "-C", workspaceRoot, "remote", "get-url", "origin").Output()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("git remote get-url origin: %w", err)
|
|
}
|
|
return ParseRemoteURL(strings.TrimSpace(string(out)))
|
|
}
|