1
1
'use strict'
2
- const url = require ( 'url' )
3
2
const gitHosts = require ( './git-host-info.js' )
4
3
const GitHost = module . exports = require ( './git-host.js' )
5
4
const LRU = require ( 'lru-cache' )
5
+ const parseUrl = require ( './parse-url.js' )
6
+ const protocols = require ( './protocols' ) ( gitHosts . byShortcut )
6
7
const cache = new LRU ( { max : 1000 } )
7
8
8
- const protocolToRepresentationMap = {
9
- 'git+ssh:' : 'sshurl' ,
10
- 'git+https:' : 'https' ,
11
- 'ssh:' : 'sshurl' ,
12
- 'git:' : 'git' ,
13
- }
14
-
15
- function protocolToRepresentation ( protocol ) {
16
- return protocolToRepresentationMap [ protocol ] || protocol . slice ( 0 , - 1 )
17
- }
18
-
19
- const authProtocols = {
20
- 'git:' : true ,
21
- 'https:' : true ,
22
- 'git+https:' : true ,
23
- 'http:' : true ,
24
- 'git+http:' : true ,
25
- }
26
-
27
- const knownProtocols = Object . keys ( gitHosts . byShortcut )
28
- . concat ( [ 'http:' , 'https:' , 'git:' , 'git+ssh:' , 'git+https:' , 'ssh:' ] )
29
-
30
9
module . exports . fromUrl = function ( giturl , opts ) {
31
10
if ( typeof giturl !== 'string' ) {
32
11
return
@@ -41,30 +20,34 @@ module.exports.fromUrl = function (giturl, opts) {
41
20
return cache . get ( key )
42
21
}
43
22
23
+ module . exports . parseUrl = parseUrl
24
+
44
25
function fromUrl ( giturl , opts ) {
45
26
if ( ! giturl ) {
46
27
return
47
28
}
48
29
49
- const correctedUrl = isGitHubShorthand ( giturl ) ? ' github:' + giturl : correctProtocol ( giturl )
50
- const parsed = parseGitUrl ( correctedUrl )
30
+ const correctedUrl = isGitHubShorthand ( giturl ) ? ` github:${ giturl } ` : giturl
31
+ const parsed = parseUrl ( correctedUrl , protocols )
51
32
if ( ! parsed ) {
52
- return parsed
33
+ return
53
34
}
54
35
55
36
const gitHostShortcut = gitHosts . byShortcut [ parsed . protocol ]
56
- const gitHostDomain =
57
- gitHosts . byDomain [ parsed . hostname . startsWith ( 'www.' ) ?
58
- parsed . hostname . slice ( 4 ) :
59
- parsed . hostname ]
37
+ const gitHostDomain = gitHosts . byDomain [ parsed . hostname . startsWith ( 'www.' )
38
+ ? parsed . hostname . slice ( 4 )
39
+ : parsed . hostname ]
60
40
const gitHostName = gitHostShortcut || gitHostDomain
61
41
if ( ! gitHostName ) {
62
42
return
63
43
}
64
44
65
45
const gitHostInfo = gitHosts [ gitHostShortcut || gitHostDomain ]
66
46
let auth = null
67
- if ( authProtocols [ parsed . protocol ] && ( parsed . username || parsed . password ) ) {
47
+ if ( protocols [ parsed . protocol ] &&
48
+ protocols [ parsed . protocol ] . auth &&
49
+ ( parsed . username || parsed . password )
50
+ ) {
68
51
auth = `${ parsed . username } ${ parsed . password ? ':' + parsed . password : '' } `
69
52
}
70
53
@@ -116,7 +99,8 @@ function fromUrl (giturl, opts) {
116
99
user = segments . user && decodeURIComponent ( segments . user )
117
100
project = decodeURIComponent ( segments . project )
118
101
committish = decodeURIComponent ( segments . committish )
119
- defaultRepresentation = protocolToRepresentation ( parsed . protocol )
102
+ defaultRepresentation = ( protocols [ parsed . protocol ] && protocols [ parsed . protocol ] . name )
103
+ || parsed . protocol . slice ( 0 , - 1 )
120
104
}
121
105
} catch ( err ) {
122
106
/* istanbul ignore else */
@@ -130,31 +114,6 @@ function fromUrl (giturl, opts) {
130
114
return new GitHost ( gitHostName , user , auth , project , committish , defaultRepresentation , opts )
131
115
}
132
116
133
- // accepts input like git:github.com:user/repo and inserts the // after the first :
134
- const correctProtocol = ( arg ) => {
135
- const firstColon = arg . indexOf ( ':' )
136
- const proto = arg . slice ( 0 , firstColon + 1 )
137
- if ( knownProtocols . includes ( proto ) ) {
138
- return arg
139
- }
140
-
141
- const firstAt = arg . indexOf ( '@' )
142
- if ( firstAt > - 1 ) {
143
- if ( firstAt > firstColon ) {
144
- return `git+ssh://${ arg } `
145
- } else {
146
- return arg
147
- }
148
- }
149
-
150
- const doubleSlash = arg . indexOf ( '//' )
151
- if ( doubleSlash === firstColon + 1 ) {
152
- return arg
153
- }
154
-
155
- return arg . slice ( 0 , firstColon + 1 ) + '//' + arg . slice ( firstColon + 1 )
156
- }
157
-
158
117
// look for github shorthand inputs, such as npm/cli
159
118
const isGitHubShorthand = ( arg ) => {
160
119
// it cannot contain whitespace before the first #
@@ -185,64 +144,3 @@ const isGitHubShorthand = (arg) => {
185
144
doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash &&
186
145
secondSlashOnlyAfterHash
187
146
}
188
-
189
- // attempt to correct an scp style url so that it will parse with `new URL()`
190
- const correctUrl = ( giturl ) => {
191
- const firstAt = giturl . indexOf ( '@' )
192
- const lastHash = giturl . lastIndexOf ( '#' )
193
- let firstColon = giturl . indexOf ( ':' )
194
- let lastColon = giturl . lastIndexOf ( ':' , lastHash > - 1 ? lastHash : Infinity )
195
-
196
- let corrected
197
- if ( lastColon > firstAt ) {
198
- // the last : comes after the first @ (or there is no @)
199
- // like it would in:
200
- // proto://hostname.com:user/repo
201
- // username@hostname .com:user/repo
202
- // :password@hostname .com:user/repo
203
- // username:password@hostname .com:user/repo
204
- // proto://username@hostname .com:user/repo
205
- // proto://:password@hostname .com:user/repo
206
- // proto://username:password@hostname .com:user/repo
207
- // then we replace the last : with a / to create a valid path
208
- corrected = giturl . slice ( 0 , lastColon ) + '/' + giturl . slice ( lastColon + 1 )
209
- // // and we find our new : positions
210
- firstColon = corrected . indexOf ( ':' )
211
- lastColon = corrected . lastIndexOf ( ':' )
212
- }
213
-
214
- if ( firstColon === - 1 && giturl . indexOf ( '//' ) === - 1 ) {
215
- // we have no : at all
216
- // as it would be in:
217
- // username@hostname .com/user/repo
218
- // then we prepend a protocol
219
- corrected = `git+ssh://${ corrected } `
220
- }
221
-
222
- return corrected
223
- }
224
-
225
- // try to parse the url as its given to us, if that throws
226
- // then we try to clean the url and parse that result instead
227
- // THIS FUNCTION SHOULD NEVER THROW
228
- const parseGitUrl = ( giturl ) => {
229
- let result
230
- try {
231
- result = new url . URL ( giturl )
232
- } catch {
233
- // this fn should never throw
234
- }
235
-
236
- if ( result ) {
237
- return result
238
- }
239
-
240
- const correctedUrl = correctUrl ( giturl )
241
- try {
242
- result = new url . URL ( correctedUrl )
243
- } catch {
244
- // this fn should never throw
245
- }
246
-
247
- return result
248
- }
0 commit comments