11'use strict'
2- const url = require ( 'url' )
32const gitHosts = require ( './git-host-info.js' )
43const GitHost = module . exports = require ( './git-host.js' )
54const 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' )
146
15- function protocolToRepresentation ( protocol ) {
16- return protocolToRepresentationMap [ protocol ] || protocol . slice ( 0 , - 1 )
17- }
7+ const cache = new LRU ( { max : 1000 } )
188
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+ } , { } ) ,
2521}
2622
27- const knownProtocols = Object . keys ( gitHosts . byShortcut )
28- . concat ( [ 'http:' , 'https:' , 'git:' , 'git+ssh:' , 'git+https:' , 'ssh:' ] )
29-
3023module . exports . fromUrl = function ( giturl , opts ) {
3124 if ( typeof giturl !== 'string' ) {
3225 return
@@ -41,30 +34,34 @@ module.exports.fromUrl = function (giturl, opts) {
4134 return cache . get ( key )
4235}
4336
37+ module . exports . parseUrl = parseUrl
38+
4439function fromUrl ( giturl , opts ) {
4540 if ( ! giturl ) {
4641 return
4742 }
4843
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 )
5146 if ( ! parsed ) {
52- return parsed
47+ return
5348 }
5449
5550 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 ]
6054 const gitHostName = gitHostShortcut || gitHostDomain
6155 if ( ! gitHostName ) {
6256 return
6357 }
6458
6559 const gitHostInfo = gitHosts [ gitHostShortcut || gitHostDomain ]
6660 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+ ) {
6865 auth = `${ parsed . username } ${ parsed . password ? ':' + parsed . password : '' } `
6966 }
7067
@@ -116,7 +113,8 @@ function fromUrl (giturl, opts) {
116113 user = segments . user && decodeURIComponent ( segments . user )
117114 project = decodeURIComponent ( segments . project )
118115 committish = decodeURIComponent ( segments . committish )
119- defaultRepresentation = protocolToRepresentation ( parsed . protocol )
116+ defaultRepresentation = ( protocols [ parsed . protocol ] && protocols [ parsed . protocol ] . name )
117+ || parsed . protocol . slice ( 0 , - 1 )
120118 }
121119 } catch ( err ) {
122120 /* istanbul ignore else */
@@ -130,31 +128,6 @@ function fromUrl (giturl, opts) {
130128 return new GitHost ( gitHostName , user , auth , project , committish , defaultRepresentation , opts )
131129}
132130
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-
158131// look for github shorthand inputs, such as npm/cli
159132const isGitHubShorthand = ( arg ) => {
160133 // it cannot contain whitespace before the first #
@@ -185,64 +158,3 @@ const isGitHubShorthand = (arg) => {
185158 doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash &&
186159 secondSlashOnlyAfterHash
187160}
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