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 }