gitlink-cli/internal/context/repo.go

70 lines
1.8 KiB
Go

package context
import (
"fmt"
"net/url"
"os/exec"
"strings"
)
// ResolveOwnerRepo auto-detects owner and repo from git remote origin.
// Returns the explicitly provided values if non-empty.
func ResolveOwnerRepo(flagOwner, flagRepo string) (string, string, error) {
if flagOwner != "" && flagRepo != "" {
return flagOwner, flagRepo, nil
}
owner, repo, err := fromGitRemote()
if err != nil {
if flagOwner == "" || flagRepo == "" {
return "", "", fmt.Errorf("无法从 git remote 自动检测 owner/repo: %w\n请使用 --owner 和 --repo 参数手动指定", err)
}
}
if flagOwner != "" {
owner = flagOwner
}
if flagRepo != "" {
repo = flagRepo
}
return owner, repo, nil
}
func fromGitRemote() (string, string, error) {
out, err := exec.Command("git", "remote", "get-url", "origin").Output()
if err != nil {
return "", "", fmt.Errorf("当前目录不是 git 仓库或未配置 remote 'origin'")
}
remote := strings.TrimSpace(string(out))
return parseRemoteURL(remote)
}
func parseRemoteURL(remote string) (string, string, error) {
// SSH format: git@www.gitlink.org.cn:owner/repo.git
if strings.HasPrefix(remote, "git@") {
parts := strings.SplitN(remote, ":", 2)
if len(parts) != 2 {
return "", "", fmt.Errorf("无法解析 SSH 远程地址: %s", remote)
}
return parsePathSegments(parts[1])
}
// HTTPS format: https://www.gitlink.org.cn/owner/repo.git
u, err := url.Parse(remote)
if err != nil {
return "", "", fmt.Errorf("无法解析远程地址 URL: %s", remote)
}
return parsePathSegments(u.Path)
}
func parsePathSegments(path string) (string, string, error) {
path = strings.TrimPrefix(path, "/")
path = strings.TrimSuffix(path, ".git")
parts := strings.SplitN(path, "/", 3)
if len(parts) < 2 {
return "", "", fmt.Errorf("无法从路径提取 owner/repo: %s", path)
}
return parts[0], parts[1], nil
}