github.com/argoproj/argo-cd/v3@v3.2.1/util/git/git.go (about)

     1  package git
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"regexp"
     7  	"strings"
     8  )
     9  
    10  // EnsurePrefix idempotently ensures that a base string has a given prefix.
    11  func ensurePrefix(s, prefix string) string {
    12  	if !strings.HasPrefix(s, prefix) {
    13  		s = prefix + s
    14  	}
    15  	return s
    16  }
    17  
    18  var (
    19  	commitSHARegex = regexp.MustCompile("^[0-9A-Fa-f]{40}$")
    20  	sshURLRegex    = regexp.MustCompile("^(ssh://)?([^/:]*?)@[^@]+$")
    21  	httpsURLRegex  = regexp.MustCompile("^(https://).*")
    22  	httpURLRegex   = regexp.MustCompile("^(http://).*")
    23  )
    24  
    25  // IsCommitSHA returns whether or not a string is a 40 character SHA-1
    26  func IsCommitSHA(sha string) bool {
    27  	return commitSHARegex.MatchString(sha)
    28  }
    29  
    30  var truncatedCommitSHARegex = regexp.MustCompile("^[0-9A-Fa-f]{7,}$")
    31  
    32  // IsTruncatedCommitSHA returns whether or not a string is a truncated  SHA-1
    33  func IsTruncatedCommitSHA(sha string) bool {
    34  	return truncatedCommitSHARegex.MatchString(sha)
    35  }
    36  
    37  // SameURL returns whether or not the two repository URLs are equivalent in location
    38  func SameURL(leftRepo, rightRepo string) bool {
    39  	normalLeft := NormalizeGitURLAllowInvalid(leftRepo)
    40  	normalRight := NormalizeGitURLAllowInvalid(rightRepo)
    41  	return normalLeft != "" && normalRight != "" && normalLeft == normalRight
    42  }
    43  
    44  // NormalizeGitURLAllowInvalid is similar to NormalizeGitURL, except returning an original url if the url is invalid.
    45  // Needed to allow a deletion of repos with invalid urls. See https://github.com/argoproj/argo-cd/issues/20921.
    46  func NormalizeGitURLAllowInvalid(repo string) string {
    47  	normalized := NormalizeGitURL(repo)
    48  	if normalized == "" {
    49  		return repo
    50  	}
    51  	return normalized
    52  }
    53  
    54  // NormalizeGitURL normalizes a git URL for purposes of comparison, as well as preventing redundant
    55  // local clones (by normalizing various forms of a URL to a consistent location).
    56  // Prefer using SameURL() over this function when possible. This algorithm may change over time
    57  // and should not be considered stable from release to release
    58  func NormalizeGitURL(repo string) string {
    59  	repo = strings.ToLower(strings.TrimSpace(repo))
    60  	if yes, _ := IsSSHURL(repo); yes {
    61  		if !strings.HasPrefix(repo, "ssh://") {
    62  			// We need to replace the first colon in git@server... style SSH URLs with a slash, otherwise
    63  			// net/url.Parse will interpret it incorrectly as the port.
    64  			repo = strings.Replace(repo, ":", "/", 1)
    65  			repo = ensurePrefix(repo, "ssh://")
    66  		}
    67  	}
    68  	repo = strings.TrimSuffix(repo, ".git")
    69  	repoURL, err := url.Parse(repo)
    70  	if err != nil {
    71  		return ""
    72  	}
    73  	normalized := repoURL.String()
    74  	return strings.TrimPrefix(normalized, "ssh://")
    75  }
    76  
    77  // IsSSHURL returns true if supplied URL is SSH URL
    78  func IsSSHURL(url string) (bool, string) {
    79  	matches := sshURLRegex.FindStringSubmatch(url)
    80  	if len(matches) > 2 {
    81  		return true, matches[2]
    82  	}
    83  	return false, ""
    84  }
    85  
    86  // IsHTTPSURL returns true if supplied URL is HTTPS URL
    87  func IsHTTPSURL(url string) bool {
    88  	return httpsURLRegex.MatchString(url)
    89  }
    90  
    91  // IsHTTPURL returns true if supplied URL is HTTP URL
    92  func IsHTTPURL(url string) bool {
    93  	return httpURLRegex.MatchString(url)
    94  }
    95  
    96  // TestRepo tests if a repo exists and is accessible with the given credentials
    97  func TestRepo(repo string, creds Creds, insecure bool, enableLfs bool, proxy string, noProxy string) error {
    98  	client, err := NewClient(repo, creds, insecure, enableLfs, proxy, noProxy)
    99  	if err != nil {
   100  		return fmt.Errorf("unable to initialize git client: %w", err)
   101  	}
   102  	_, err = client.LsRemote("HEAD")
   103  	if err != nil {
   104  		return fmt.Errorf("unable to ls-remote HEAD on repository: %w", err)
   105  	}
   106  	return nil
   107  }