@@ -18,6 +18,7 @@ import (
18
18
"io"
19
19
"net/url"
20
20
"regexp"
21
+ "strconv"
21
22
22
23
"gopkg.in/src-d/go-git.v4/plumbing"
23
24
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
28
29
ErrRepositoryNotFound = errors .New ("repository not found" )
29
30
ErrEmptyRemoteRepository = errors .New ("remote repository is empty" )
30
31
ErrAuthenticationRequired = errors .New ("authentication required" )
31
- ErrAuthorizationFailed = errors .New ("authorization failed" )
32
+ ErrAuthorizationFailed = errors .New ("authorization failed" )
32
33
ErrEmptyUploadPackRequest = errors .New ("empty git-upload-pack given" )
33
34
ErrInvalidAuthMethod = errors .New ("invalid auth method" )
34
35
ErrAlreadyConnected = errors .New ("session already established" )
@@ -88,42 +89,134 @@ type ReceivePackSession interface {
88
89
ReceivePack (* packp.ReferenceUpdateRequest ) (* packp.ReportStatus , error )
89
90
}
90
91
91
- type Endpoint url.URL
92
-
93
- var (
94
- isSchemeRegExp = regexp .MustCompile ("^[^:]+://" )
95
- scpLikeUrlRegExp = regexp .MustCompile ("^(?P<user>[^@]+@)?(?P<host>[^:]+):/?(?P<path>.+)$" )
96
- )
92
+ // Endpoint represents a Git URL in any supported protocol.
93
+ type Endpoint interface {
94
+ // Protocol returns the protocol (e.g. git, https, file). It should never
95
+ // return the empty string.
96
+ Protocol () string
97
+ // User returns the user or an empty string if none is given.
98
+ User () string
99
+ // Password returns the password or an empty string if none is given.
100
+ Password () string
101
+ // Host returns the host or an empty string if none is given.
102
+ Host () string
103
+ // Port returns the port or 0 if there is no port or a default should be
104
+ // used.
105
+ Port () int
106
+ // Path returns the repository path.
107
+ Path () string
108
+ // String returns a string representation of the Git URL.
109
+ String () string
110
+ }
97
111
98
112
func NewEndpoint (endpoint string ) (Endpoint , error ) {
99
- endpoint = transformSCPLikeIfNeeded (endpoint )
113
+ if e , ok := parseSCPLike (endpoint ); ok {
114
+ return e , nil
115
+ }
100
116
101
117
u , err := url .Parse (endpoint )
102
118
if err != nil {
103
- return Endpoint {} , plumbing .NewPermanentError (err )
119
+ return nil , plumbing .NewPermanentError (err )
104
120
}
105
121
106
122
if ! u .IsAbs () {
107
- return Endpoint {} , plumbing .NewPermanentError (fmt .Errorf (
123
+ return nil , plumbing .NewPermanentError (fmt .Errorf (
108
124
"invalid endpoint: %s" , endpoint ,
109
125
))
110
126
}
111
127
112
- return Endpoint (* u ), nil
128
+ return urlEndpoint {u }, nil
129
+ }
130
+
131
+ type urlEndpoint struct {
132
+ * url.URL
133
+ }
134
+
135
+ func (e urlEndpoint ) Protocol () string { return e .URL .Scheme }
136
+ func (e urlEndpoint ) Host () string { return e .URL .Hostname () }
137
+
138
+ func (e urlEndpoint ) User () string {
139
+ if e .URL .User == nil {
140
+ return ""
141
+ }
142
+
143
+ return e .URL .User .Username ()
144
+ }
145
+
146
+ func (e urlEndpoint ) Password () string {
147
+ if e .URL .User == nil {
148
+ return ""
149
+ }
150
+
151
+ p , _ := e .URL .User .Password ()
152
+ return p
153
+ }
154
+
155
+ func (e urlEndpoint ) Port () int {
156
+ p := e .URL .Port ()
157
+ if p == "" {
158
+ return 0
159
+ }
160
+
161
+ i , err := strconv .Atoi (e .URL .Port ())
162
+ if err != nil {
163
+ return 0
164
+ }
165
+
166
+ return i
113
167
}
114
168
115
- func (e * Endpoint ) String () string {
116
- u := url .URL (* e )
117
- return u .String ()
169
+ func (e urlEndpoint ) Path () string {
170
+ var res string = e .URL .Path
171
+ if e .URL .RawQuery != "" {
172
+ res += "?" + e .URL .RawQuery
173
+ }
174
+
175
+ if e .URL .Fragment != "" {
176
+ res += "#" + e .URL .Fragment
177
+ }
178
+
179
+ return res
118
180
}
119
181
120
- func transformSCPLikeIfNeeded (endpoint string ) string {
121
- if ! isSchemeRegExp .MatchString (endpoint ) && scpLikeUrlRegExp .MatchString (endpoint ) {
122
- m := scpLikeUrlRegExp .FindStringSubmatch (endpoint )
123
- return fmt .Sprintf ("ssh://%s%s/%s" , m [1 ], m [2 ], m [3 ])
182
+ type scpEndpoint struct {
183
+ user string
184
+ host string
185
+ path string
186
+ }
187
+
188
+ func (e * scpEndpoint ) Protocol () string { return "ssh" }
189
+ func (e * scpEndpoint ) User () string { return e .user }
190
+ func (e * scpEndpoint ) Password () string { return "" }
191
+ func (e * scpEndpoint ) Host () string { return e .host }
192
+ func (e * scpEndpoint ) Port () int { return 22 }
193
+ func (e * scpEndpoint ) Path () string { return e .path }
194
+
195
+ func (e * scpEndpoint ) String () string {
196
+ var user string
197
+ if e .user != "" {
198
+ user = fmt .Sprintf ("%s@" , e .user )
199
+ }
200
+
201
+ return fmt .Sprintf ("%s%s:%s" , user , e .host , e .path )
202
+ }
203
+
204
+ var (
205
+ isSchemeRegExp = regexp .MustCompile ("^[^:]+://" )
206
+ scpLikeUrlRegExp = regexp .MustCompile ("^(?:(?P<user>[^@]+)@)?(?P<host>[^:]+):/?(?P<path>.+)$" )
207
+ )
208
+
209
+ func parseSCPLike (endpoint string ) (Endpoint , bool ) {
210
+ if isSchemeRegExp .MatchString (endpoint ) || ! scpLikeUrlRegExp .MatchString (endpoint ) {
211
+ return nil , false
124
212
}
125
213
126
- return endpoint
214
+ m := scpLikeUrlRegExp .FindStringSubmatch (endpoint )
215
+ return & scpEndpoint {
216
+ user : m [1 ],
217
+ host : m [2 ],
218
+ path : m [3 ],
219
+ }, true
127
220
}
128
221
129
222
// UnsupportedCapabilities are the capabilities not supported by any client
0 commit comments