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' )
6
- const cache = new LRU ( { max : 1000 } )
7
-
8
- const protocolToRepresentationMap = {
9
- 'git+ssh:' : 'sshurl' ,
10
- 'git+https:' : 'https' ,
11
- 'ssh:' : 'sshurl' ,
12
- 'git:' : 'git' ,
13
- }
5
+ const parseUrl = require ( './parse-url.js' )
14
6
15
- function protocolToRepresentation ( protocol ) {
16
- return protocolToRepresentationMap [ protocol ] || protocol . slice ( 0 , - 1 )
17
- }
7
+ const cache = new LRU ( { max : 1000 } )
18
8
19
- const authProtocols = {
20
- 'git:' : true ,
21
- 'https:' : true ,
22
- 'git+https:' : true ,
23
- 'http:' : true ,
24
- 'git+http:' : true ,
9
+ const protocols = {
10
+ 'git+ssh:' : { name : 'sshurl' } ,
11
+ 'ssh:' : { name : 'sshurl' } ,
12
+ 'git+https:' : { name : 'https' , auth : true } ,
13
+ 'git:' : { auth : true } ,
14
+ 'http:' : { auth : true } ,
15
+ 'https:' : { auth : true } ,
16
+ 'git+http:' : { auth : true } ,
17
+ ...Object . keys ( gitHosts . byShortcut ) . reduce ( ( acc , key ) => {
18
+ acc [ key ] = { name : gitHosts . byShortcut [ key ] }
19
+ return acc
20
+ } , { } ) ,
25
21
}
26
22
27
- const knownProtocols = Object . keys ( gitHosts . byShortcut )
28
- . concat ( [ 'http:' , 'https:' , 'git:' , 'git+ssh:' , 'git+https:' , 'ssh:' ] )
29
-
30
23
module . exports . fromUrl = function ( giturl , opts ) {
31
24
if ( typeof giturl !== 'string' ) {
32
25
return
@@ -41,30 +34,34 @@ module.exports.fromUrl = function (giturl, opts) {
41
34
return cache . get ( key )
42
35
}
43
36
37
+ module . exports . parseUrl = parseUrl
38
+
44
39
function fromUrl ( giturl , opts ) {
45
40
if ( ! giturl ) {
46
41
return
47
42
}
48
43
49
- const correctedUrl = isGitHubShorthand ( giturl ) ? ' github:' + giturl : correctProtocol ( giturl )
50
- const parsed = parseGitUrl ( correctedUrl )
44
+ const correctedUrl = isGitHubShorthand ( giturl ) ? ` github:${ giturl } ` : giturl
45
+ const parsed = parseUrl ( correctedUrl , protocols )
51
46
if ( ! parsed ) {
52
- return parsed
47
+ return
53
48
}
54
49
55
50
const gitHostShortcut = gitHosts . byShortcut [ parsed . protocol ]
56
- const gitHostDomain =
57
- gitHosts . byDomain [ parsed . hostname . startsWith ( 'www.' ) ?
58
- parsed . hostname . slice ( 4 ) :
59
- parsed . hostname ]
51
+ const gitHostDomain = gitHosts . byDomain [ parsed . hostname . startsWith ( 'www.' )
52
+ ? parsed . hostname . slice ( 4 )
53
+ : parsed . hostname ]
60
54
const gitHostName = gitHostShortcut || gitHostDomain
61
55
if ( ! gitHostName ) {
62
56
return
63
57
}
64
58
65
59
const gitHostInfo = gitHosts [ gitHostShortcut || gitHostDomain ]
66
60
let auth = null
67
- if ( authProtocols [ parsed . protocol ] && ( parsed . username || parsed . password ) ) {
61
+ if ( protocols [ parsed . protocol ] &&
62
+ protocols [ parsed . protocol ] . auth &&
63
+ ( parsed . username || parsed . password )
64
+ ) {
68
65
auth = `${ parsed . username } ${ parsed . password ? ':' + parsed . password : '' } `
69
66
}
70
67
@@ -116,7 +113,8 @@ function fromUrl (giturl, opts) {
116
113
user = segments . user && decodeURIComponent ( segments . user )
117
114
project = decodeURIComponent ( segments . project )
118
115
committish = decodeURIComponent ( segments . committish )
119
- defaultRepresentation = protocolToRepresentation ( parsed . protocol )
116
+ defaultRepresentation = ( protocols [ parsed . protocol ] && protocols [ parsed . protocol ] . name )
117
+ || parsed . protocol . slice ( 0 , - 1 )
120
118
}
121
119
} catch ( err ) {
122
120
/* istanbul ignore else */
@@ -130,31 +128,6 @@ function fromUrl (giturl, opts) {
130
128
return new GitHost ( gitHostName , user , auth , project , committish , defaultRepresentation , opts )
131
129
}
132
130
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
131
// look for github shorthand inputs, such as npm/cli
159
132
const isGitHubShorthand = ( arg ) => {
160
133
// it cannot contain whitespace before the first #
@@ -185,64 +158,3 @@ const isGitHubShorthand = (arg) => {
185
158
doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash &&
186
159
secondSlashOnlyAfterHash
187
160
}
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