This repository was archived by the owner on May 29, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathvcsurl.go
160 lines (143 loc) · 4.33 KB
/
vcsurl.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package vcsurl
import (
"fmt"
"net/url"
"path/filepath"
"regexp"
"strings"
)
type RepoHost string
const (
GitHub RepoHost = "github.com"
Bitbucket RepoHost = "bitbucket.org"
GoogleCode RepoHost = "code.google.com"
PythonOrg RepoHost = "hg.python.org"
Launchpad RepoHost = "launchpad.net"
)
type VCS string
const (
Git VCS = "git"
Mercurial VCS = "hg"
Bazaar VCS = "bzr"
)
// RepoInfo describes a VCS repository.
type RepoInfo struct {
CloneURL string // clone URL
VCS VCS // VCS type
RepoHost RepoHost // repo hosting site
Username string // username of repo owner on repo hosting site
Name string // base name of repo on repo hosting site
FullName string // full name of repo on repo hosting site
Rev string // a specific revision (commit ID, branch, etc.)
}
// Link returns the URL to the repository that is intended for access by humans
// using a Web browser (i.e., not the URL to the API resource).
func (r *RepoInfo) Link() string {
switch r.RepoHost {
case GoogleCode:
return fmt.Sprintf("https://code.google.com/p/%s", r.FullName)
default:
return (&url.URL{Scheme: "https", Host: string(r.RepoHost), Path: "/" + r.FullName}).String()
}
}
var (
removeDotGit = regexp.MustCompile(`\.git$`)
gitPreprocessRE = regexp.MustCompile("^git@([a-zA-Z0-9-_\\.]+)\\:(.*)$")
)
// Parses a string that resembles a VCS repository URL. See TestParse for a list of supported URL
// formats.
func Parse(spec string) (info *RepoInfo, err error) {
if parts := gitPreprocessRE.FindStringSubmatch(spec); len(parts) == 3 {
spec = fmt.Sprintf("git://%s/%s", parts[1], parts[2])
}
var parsedURL *url.URL
if parsedURL, err = url.Parse(spec); err == nil {
if parsedURL.Scheme == "" {
spec = "https://" + spec
if parsedURL, err = url.Parse(spec); err != nil {
return nil, err
}
}
info = new(RepoInfo)
info.CloneURL = parsedURL.String()
info.RepoHost = RepoHost(parsedURL.Host)
info.Rev = parsedURL.Fragment
if info.RepoHost == GitHub || parsedURL.Scheme == "git" {
info.VCS = Git
} else if info.RepoHost == GoogleCode && parsedURL.Scheme == "https" {
info.VCS = Mercurial
} else if info.RepoHost == Bitbucket && (parsedURL.Scheme == "https" || parsedURL.Scheme == "http") {
if !strings.HasSuffix(parsedURL.Path, ".git") {
info.VCS = Mercurial
}
} else if info.RepoHost == Launchpad {
info.VCS = Bazaar
}
path := parsedURL.Path
switch info.RepoHost {
case GitHub:
parts := strings.Split(path, "/")
if len(parts) >= 3 {
info.Username = parts[1]
parts[2] = removeDotGit.ReplaceAllLiteralString(parts[2], "")
info.Name = parts[2]
info.FullName = parts[1] + "/" + parts[2]
info.CloneURL = "git://github.com/" + info.FullName + ".git"
}
case GoogleCode:
parts := strings.Split(path, "/")
if len(parts) >= 3 {
if parts[1] == "p" {
info.Name = parts[2]
info.FullName = info.Name
info.CloneURL = "https://code.google.com/p/" + info.FullName
}
}
case PythonOrg:
parts := strings.Split(path, "/")
if len(parts) >= 2 {
info.CloneURL = "http://hg.python.org" + path
info.VCS = Mercurial
info.Name = parts[len(parts)-1]
info.FullName = strings.Join(parts[1:], "/")
}
case Bitbucket:
parts := strings.Split(path, "/")
if len(parts) >= 3 {
info.Username = parts[1]
if strings.HasSuffix(parts[2], ".git") {
info.VCS = Git
parts[2] = strings.TrimSuffix(parts[2], ".git")
}
info.Name = parts[2]
info.FullName = parts[1] + "/" + parts[2]
info.CloneURL = "https://bitbucket.org/" + info.FullName
if info.VCS == Git {
info.CloneURL += ".git"
}
}
default:
if len(path) == 0 {
return nil, fmt.Errorf("empty path in repo spec: %q", spec)
}
path = path[1:] // remove leading slash
path = removeDotGit.ReplaceAllLiteralString(path, "")
info.FullName = path
info.Name = filepath.Base(path)
if strings.Contains(spec, "git") {
info.VCS = Git
} else if strings.Contains(spec, "hg") || strings.Contains(spec, "mercurial") {
info.VCS = Mercurial
}
}
if info.RepoHost == Launchpad {
parsedURL.Scheme = "bzr"
info.CloneURL = parsedURL.String()
}
if info.Name == "" || info.FullName == "" {
return nil, fmt.Errorf("unable to determine name or full name for repo spec %q", spec)
}
return info, nil
}
return nil, err
}