11
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
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)))
|
||||
}
|
||||
Reference in New Issue
Block a user