-
Notifications
You must be signed in to change notification settings - Fork 128
/
git.go
78 lines (72 loc) · 2.21 KB
/
git.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package git
import (
"fmt"
"net/url"
"regexp"
"strings"
)
var scpSyntaxRegex = regexp.MustCompile(`^((?:[\w-]+@)?[\w-]+(?:\.[\w-]+)*)(?::(.*))?$`)
// NormalizeURL normalizes Git URLs of the following forms:
//
// - http[s]://[proxy-user:proxy-pass@]host.xz[:port][/path/to/repo[.git][/]]
// - ssh://[user@]host.xz[:port][/path/to/repo[.git][/]]
// - [user@]host.xz[:path/to/repo[.git][/]]
//
// This is useful for the purposes of comparison and also in cases where a
// canonical representation of a Git URL is needed. Any URL that cannot be
// normalized will be returned as-is.
func NormalizeURL(repo string) string {
origRepo := repo
repo = strings.ToLower(repo)
// HTTP/S URLs
if strings.HasPrefix(repo, "http://") || strings.HasPrefix(repo, "https://") {
repoURL, err := url.Parse(repo)
if err != nil {
return origRepo
}
if len(repoURL.Query()) > 0 {
// Query parameters are not permitted
return origRepo
}
repoURL.User = nil // Remove user info if there is any
repoURL.Path = strings.TrimSuffix(repoURL.Path, "/")
repoURL.Path = strings.TrimSuffix(repoURL.Path, ".git")
return repoURL.String()
}
// URLS of the form ssh://[user@]host.xz[:port][/path/to/repo[.git][/]]
if strings.HasPrefix(repo, "ssh://") {
// repo = strings.TrimPrefix(repo, "ssh://")
repoURL, err := url.Parse(repo)
if err != nil {
return origRepo
}
if len(repoURL.Query()) > 0 {
// Query parameters are not permitted
return origRepo
}
repoURL.Path = strings.TrimSuffix(repoURL.Path, "/")
repoURL.Path = strings.TrimSuffix(repoURL.Path, ".git")
return repoURL.String()
}
// URLS of the form [user@]host.xz[:path/to/repo[.git][/]]
matches := scpSyntaxRegex.FindStringSubmatch(repo)
if len(matches) != 2 && len(matches) != 3 {
// This URL doesn't appear to be in a format we recognize
return origRepo
}
userHost := matches[1]
var path string
if len(matches) == 3 {
path = matches[2]
}
pathURL, err := url.Parse(path)
if err != nil {
return origRepo
}
pathURL.Path = strings.TrimSuffix(pathURL.Path, "/")
pathURL.Path = strings.TrimSuffix(pathURL.Path, ".git")
if pathURL.Path == "" {
return fmt.Sprintf("ssh://%s", userHost)
}
return fmt.Sprintf("ssh://%s/%s", userHost, pathURL.String())
}