@@ -4,7 +4,7 @@ module.exports.resolve = resolve
4
4
module . exports . toPurl = toPurl
5
5
module . exports . Result = Result
6
6
7
- const url = require ( 'url' )
7
+ const { URL } = require ( 'url' )
8
8
const HostedGit = require ( 'hosted-git-info' )
9
9
const semver = require ( 'semver' )
10
10
const path = global . FAKE_WINDOWS ? require ( 'path' ) . win32 : require ( 'path' )
@@ -245,8 +245,8 @@ function fromFile (res, where) {
245
245
const rawWithPrefix = prefix + res . rawSpec
246
246
let rawNoPrefix = rawWithPrefix . replace ( / ^ f i l e : / , '' )
247
247
try {
248
- resolvedUrl = new url . URL ( rawWithPrefix , `file://${ path . resolve ( where ) } /` )
249
- specUrl = new url . URL ( rawWithPrefix )
248
+ resolvedUrl = new URL ( rawWithPrefix , `file://${ path . resolve ( where ) } /` )
249
+ specUrl = new URL ( rawWithPrefix )
250
250
} catch ( originalError ) {
251
251
const er = new Error ( 'Invalid file: URL, must comply with RFC 8909' )
252
252
throw Object . assign ( er , {
@@ -263,17 +263,17 @@ function fromFile (res, where) {
263
263
// Remove when we want a breaking change to come into RFC compliance.
264
264
if ( resolvedUrl . host && resolvedUrl . host !== 'localhost' ) {
265
265
const rawSpec = res . rawSpec . replace ( / ^ f i l e : \/ \/ / , 'file:///' )
266
- resolvedUrl = new url . URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
267
- specUrl = new url . URL ( rawSpec )
266
+ resolvedUrl = new URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
267
+ specUrl = new URL ( rawSpec )
268
268
rawNoPrefix = rawSpec . replace ( / ^ f i l e : / , '' )
269
269
}
270
270
// turn file:/../foo into file:../foo
271
271
// for 1, 2 or 3 leading slashes since we attempted
272
272
// in the previous step to make it a file protocol url with a leading slash
273
273
if ( / ^ \/ { 1 , 3 } \. \. ? ( \/ | $ ) / . test ( rawNoPrefix ) ) {
274
274
const rawSpec = res . rawSpec . replace ( / ^ f i l e : \/ { 1 , 3 } / , 'file:' )
275
- resolvedUrl = new url . URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
276
- specUrl = new url . URL ( rawSpec )
275
+ resolvedUrl = new URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
276
+ specUrl = new URL ( rawSpec )
277
277
rawNoPrefix = rawSpec . replace ( / ^ f i l e : / , '' )
278
278
}
279
279
// XXX end 8909 violation backwards compatibility section
@@ -329,28 +329,29 @@ function unsupportedURLType (protocol, spec) {
329
329
return err
330
330
}
331
331
332
- function matchGitScp ( spec ) {
333
- // git ssh specifiers are overloaded to also use scp-style git
334
- // specifiers, so we have to parse those out and treat them special.
335
- // They are NOT true URIs, so we can't hand them to `url.parse`.
336
- //
337
- // This regex looks for things that look like:
338
- // git+ssh://[email protected] :username/project.git#deadbeef
339
- //
340
- // ...and various combinations. The username in the beginning is *required*.
341
- const matched = spec . match ( / ^ g i t \+ s s h : \/ \/ ( [ ^ : # ] + : [ ^ # ] + (?: \. g i t ) ? ) (?: # ( .* ) ) ? $ / i)
342
- return matched && ! matched [ 1 ] . match ( / : [ 0 - 9 ] + \/ ? .* $ / i) && {
343
- fetchSpec : matched [ 1 ] ,
344
- gitCommittish : matched [ 2 ] == null ? null : matched [ 2 ] ,
345
- }
346
- }
347
-
348
332
function fromURL ( res ) {
333
+ let rawSpec = res . rawSpec
334
+ res . saveSpec = rawSpec
335
+ if ( rawSpec . startsWith ( 'git+ssh:' ) ) {
336
+ // git ssh specifiers are overloaded to also use scp-style git
337
+ // specifiers, so we have to parse those out and treat them special.
338
+ // They are NOT true URIs, so we can't hand them to URL.
339
+ const matched = rawSpec . match ( / ^ g i t \+ s s h : \/ \/ ( [ ^ : # ] + : [ ^ # ] + (?: \. g i t ) ? ) (?: # ( .* ) ) ? $ / i)
340
+ if ( matched && ! matched [ 1 ] . match ( / : [ 0 - 9 ] + \/ ? .* $ / i) ) {
341
+ res . type = 'git'
342
+ setGitCommittish ( res , matched [ 2 ] )
343
+ res . fetchSpec = matched [ 1 ]
344
+ return res
345
+ }
346
+ } else if ( rawSpec . startsWith ( 'git+file://' ) ) {
347
+ // URL can't handle windows paths
348
+ const noProtocol = rawSpec . slice ( 11 ) . replace ( / \\ / g, '/' )
349
+ rawSpec = `git+file://${ noProtocol } `
350
+ }
349
351
// eslint-disable-next-line node/no-deprecated-api
350
- const urlparse = url . parse ( res . rawSpec )
351
- res . saveSpec = res . rawSpec
352
+ const parsedUrl = new URL ( rawSpec )
352
353
// check the protocol, and then see if it's git or not
353
- switch ( urlparse . protocol ) {
354
+ switch ( parsedUrl . protocol ) {
354
355
case 'git:' :
355
356
case 'git+http:' :
356
357
case 'git+https:' :
@@ -359,21 +360,16 @@ function fromURL (res) {
359
360
case 'git+file:' :
360
361
case 'git+ssh:' : {
361
362
res . type = 'git'
362
- const match = urlparse . protocol === 'git+ssh:' ? matchGitScp ( res . rawSpec )
363
- : null
364
- if ( match ) {
365
- setGitCommittish ( res , match . gitCommittish )
366
- res . fetchSpec = match . fetchSpec
363
+ setGitCommittish ( res , parsedUrl . hash . slice ( 1 ) )
364
+ if ( parsedUrl . protocol === 'git+file:' && / ^ g i t \+ f i l e : \/ \/ [ a - z ] : / i. test ( rawSpec ) ) {
365
+ // URL can't handle drive letters on windows file paths, the host can't contain a :
366
+ res . fetchSpec = `git+file://${ parsedUrl . host . toLowerCase ( ) } :${ parsedUrl . pathname } `
367
367
} else {
368
- setGitCommittish ( res , urlparse . hash != null ? urlparse . hash . slice ( 1 ) : '' )
369
- urlparse . protocol = urlparse . protocol . replace ( / ^ g i t [ + ] / , '' )
370
- if ( urlparse . protocol === 'file:' && / ^ g i t \+ f i l e : \/ \/ [ a - z ] : / i. test ( res . rawSpec ) ) {
371
- // keep the drive letter : on windows file paths
372
- urlparse . host += ':'
373
- urlparse . hostname += ':'
374
- }
375
- delete urlparse . hash
376
- res . fetchSpec = url . format ( urlparse )
368
+ parsedUrl . hash = ''
369
+ res . fetchSpec = parsedUrl . toString ( )
370
+ }
371
+ if ( res . fetchSpec . startsWith ( 'git+' ) ) {
372
+ res . fetchSpec = res . fetchSpec . slice ( 4 )
377
373
}
378
374
break
379
375
}
@@ -384,7 +380,7 @@ function fromURL (res) {
384
380
break
385
381
386
382
default :
387
- throw unsupportedURLType ( urlparse . protocol , res . rawSpec )
383
+ throw unsupportedURLType ( parsedUrl . protocol , rawSpec )
388
384
}
389
385
390
386
return res
0 commit comments