github.com/chelnak/go-gh@v0.0.2/internal/git/url.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "net/url" 6 "strings" 7 ) 8 9 func isURL(u string) bool { 10 return strings.HasPrefix(u, "git@") || isSupportedProtocol(u) 11 } 12 13 func isSupportedProtocol(u string) bool { 14 return strings.HasPrefix(u, "ssh:") || 15 strings.HasPrefix(u, "git+ssh:") || 16 strings.HasPrefix(u, "git:") || 17 strings.HasPrefix(u, "http:") || 18 strings.HasPrefix(u, "https:") 19 } 20 21 func isPossibleProtocol(u string) bool { 22 return isSupportedProtocol(u) || 23 strings.HasPrefix(u, "ftp:") || 24 strings.HasPrefix(u, "ftps:") || 25 strings.HasPrefix(u, "file:") 26 } 27 28 // Normalize git remote urls. 29 func parseURL(rawURL string) (u *url.URL, err error) { 30 if !isPossibleProtocol(rawURL) && 31 strings.ContainsRune(rawURL, ':') && 32 // Not a Windows path. 33 !strings.ContainsRune(rawURL, '\\') { 34 // Support scp-like syntax for ssh protocol. 35 rawURL = "ssh://" + strings.Replace(rawURL, ":", "/", 1) 36 } 37 38 u, err = url.Parse(rawURL) 39 if err != nil { 40 return 41 } 42 43 if u.Scheme == "git+ssh" { 44 u.Scheme = "ssh" 45 } 46 47 if u.Scheme != "ssh" { 48 return 49 } 50 51 if strings.HasPrefix(u.Path, "//") { 52 u.Path = strings.TrimPrefix(u.Path, "/") 53 } 54 55 if idx := strings.Index(u.Host, ":"); idx >= 0 { 56 u.Host = u.Host[0:idx] 57 } 58 59 return 60 } 61 62 // Extract GitHub repository information from a git remote URL. 63 func repoInfoFromURL(u *url.URL) (host string, owner string, repo string, err error) { 64 if u.Hostname() == "" { 65 return "", "", "", fmt.Errorf("no hostname detected") 66 } 67 68 parts := strings.SplitN(strings.Trim(u.Path, "/"), "/", 3) 69 if len(parts) != 2 { 70 return "", "", "", fmt.Errorf("invalid path: %s", u.Path) 71 } 72 73 return normalizeHostname(u.Hostname()), parts[0], strings.TrimSuffix(parts[1], ".git"), nil 74 } 75 76 func normalizeHostname(h string) string { 77 return strings.ToLower(strings.TrimPrefix(h, "www.")) 78 }