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  }