@@ -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' )
@@ -183,10 +183,11 @@ Result.prototype.toJSON = function () {
183
183
return result
184
184
}
185
185
186
- function setGitCommittish ( res , committish ) {
186
+ // sets res.gitCommittish, res.gitRange, and res.gitSubdir
187
+ function setGitAttrs ( res , committish ) {
187
188
if ( ! committish ) {
188
189
res . gitCommittish = null
189
- return res
190
+ return
190
191
}
191
192
192
193
// for each :: separated item:
@@ -224,8 +225,6 @@ function setGitCommittish (res, committish) {
224
225
}
225
226
log . warn ( 'npm-package-arg' , `ignoring unknown key "${ name } "` )
226
227
}
227
-
228
- return res
229
228
}
230
229
231
230
function fromFile ( res , where ) {
@@ -245,10 +244,10 @@ function fromFile (res, where) {
245
244
const rawWithPrefix = prefix + res . rawSpec
246
245
let rawNoPrefix = rawWithPrefix . replace ( / ^ f i l e : / , '' )
247
246
try {
248
- resolvedUrl = new url . URL ( rawWithPrefix , `file://${ path . resolve ( where ) } /` )
249
- specUrl = new url . URL ( rawWithPrefix )
247
+ resolvedUrl = new URL ( rawWithPrefix , `file://${ path . resolve ( where ) } /` )
248
+ specUrl = new URL ( rawWithPrefix )
250
249
} catch ( originalError ) {
251
- const er = new Error ( 'Invalid file: URL, must comply with RFC 8909 ' )
250
+ const er = new Error ( 'Invalid file: URL, must comply with RFC 8089 ' )
252
251
throw Object . assign ( er , {
253
252
raw : res . rawSpec ,
254
253
spec : res ,
@@ -257,23 +256,23 @@ function fromFile (res, where) {
257
256
} )
258
257
}
259
258
260
- // XXX backwards compatibility lack of compliance with RFC 8909
259
+ // XXX backwards compatibility lack of compliance with RFC 8089
261
260
if ( resolvedUrl . host && resolvedUrl . host !== 'localhost' ) {
262
261
const rawSpec = res . rawSpec . replace ( / ^ f i l e : \/ \/ / , 'file:///' )
263
- resolvedUrl = new url . URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
264
- specUrl = new url . URL ( rawSpec )
262
+ resolvedUrl = new URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
263
+ specUrl = new URL ( rawSpec )
265
264
rawNoPrefix = rawSpec . replace ( / ^ f i l e : / , '' )
266
265
}
267
266
// turn file:/../foo into file:../foo
268
267
// for 1, 2 or 3 leading slashes since we attempted
269
268
// in the previous step to make it a file protocol url with a leading slash
270
269
if ( / ^ \/ { 1 , 3 } \. \. ? ( \/ | $ ) / . test ( rawNoPrefix ) ) {
271
270
const rawSpec = res . rawSpec . replace ( / ^ f i l e : \/ { 1 , 3 } / , 'file:' )
272
- resolvedUrl = new url . URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
273
- specUrl = new url . URL ( rawSpec )
271
+ resolvedUrl = new URL ( rawSpec , `file://${ path . resolve ( where ) } /` )
272
+ specUrl = new URL ( rawSpec )
274
273
rawNoPrefix = rawSpec . replace ( / ^ f i l e : / , '' )
275
274
}
276
- // XXX end RFC 8909 violation backwards compatibility section
275
+ // XXX end RFC 8089 violation backwards compatibility section
277
276
278
277
// turn /C:/blah into just C:/blah on windows
279
278
let specPath = decodeURIComponent ( specUrl . pathname )
@@ -303,7 +302,8 @@ function fromHostedGit (res, hosted) {
303
302
res . hosted = hosted
304
303
res . saveSpec = hosted . toString ( { noGitPlus : false , noCommittish : false } )
305
304
res . fetchSpec = hosted . getDefaultRepresentation ( ) === 'shortcut' ? null : hosted . toString ( )
306
- return setGitCommittish ( res , hosted . committish )
305
+ setGitAttrs ( res , hosted . committish )
306
+ return res
307
307
}
308
308
309
309
function unsupportedURLType ( protocol , spec ) {
@@ -312,62 +312,59 @@ function unsupportedURLType (protocol, spec) {
312
312
return err
313
313
}
314
314
315
- function matchGitScp ( spec ) {
316
- // git ssh specifiers are overloaded to also use scp-style git
317
- // specifiers, so we have to parse those out and treat them special.
318
- // They are NOT true URIs, so we can't hand them to `url.parse`.
319
- //
320
- // This regex looks for things that look like:
321
- // git+ssh://git@my.custom.git.com:username/project.git#deadbeef
322
- //
323
- // ...and various combinations. The username in the beginning is *required*.
324
- const matched = spec . match ( / ^ g i t \+ s s h : \/ \/ ( [ ^ : # ] + : [ ^ # ] + (?: \. g i t ) ? ) (?: # ( .* ) ) ? $ / i)
325
- return matched && ! matched [ 1 ] . match ( / : [ 0 - 9 ] + \/ ? .* $ / i) && {
326
- fetchSpec : matched [ 1 ] ,
327
- gitCommittish : matched [ 2 ] == null ? null : matched [ 2 ] ,
328
- }
329
- }
330
-
331
315
function fromURL ( res ) {
332
- // eslint-disable-next-line node/no-deprecated-api
333
- const urlparse = url . parse ( res . rawSpec )
334
- res . saveSpec = res . rawSpec
316
+ let rawSpec = res . rawSpec
317
+ res . saveSpec = rawSpec
318
+ if ( rawSpec . startsWith ( 'git+ssh:' ) ) {
319
+ // git ssh specifiers are overloaded to also use scp-style git
320
+ // specifiers, so we have to parse those out and treat them special.
321
+ // They are NOT true URIs, so we can't hand them to URL.
322
+
323
+ // This regex looks for things that look like:
324
+ // git+ssh://git@my.custom.git.com:username/project.git#deadbeef
325
+ // ...and various combinations. The username in the beginning is *required*.
326
+ const matched = rawSpec . match ( / ^ g i t \+ s s h : \/ \/ ( [ ^ : # ] + : [ ^ # ] + (?: \. g i t ) ? ) (?: # ( .* ) ) ? $ / i)
327
+ if ( matched && ! matched [ 1 ] . match ( / : [ 0 - 9 ] + \/ ? .* $ / i) ) {
328
+ res . type = 'git'
329
+ setGitAttrs ( res , matched [ 2 ] )
330
+ res . fetchSpec = matched [ 1 ]
331
+ return res
332
+ }
333
+ } else if ( rawSpec . startsWith ( 'git+file://' ) ) {
334
+ // URL can't handle windows paths
335
+ rawSpec = rawSpec . replace ( / \\ / g, '/' )
336
+ }
337
+ const parsedUrl = new URL ( rawSpec )
335
338
// check the protocol, and then see if it's git or not
336
- switch ( urlparse . protocol ) {
339
+ switch ( parsedUrl . protocol ) {
337
340
case 'git:' :
338
341
case 'git+http:' :
339
342
case 'git+https:' :
340
343
case 'git+rsync:' :
341
344
case 'git+ftp:' :
342
345
case 'git+file:' :
343
- case 'git+ssh:' : {
346
+ case 'git+ssh:' :
344
347
res . type = 'git'
345
- const match = urlparse . protocol === 'git+ssh:' ? matchGitScp ( res . rawSpec )
346
- : null
347
- if ( match ) {
348
- setGitCommittish ( res , match . gitCommittish )
349
- res . fetchSpec = match . fetchSpec
348
+ setGitAttrs ( res , parsedUrl . hash . slice ( 1 ) )
349
+ if ( parsedUrl . protocol === 'git+file:' && / ^ g i t \+ f i l e : \/ \/ [ a - z ] : / i. test ( rawSpec ) ) {
350
+ // URL can't handle drive letters on windows file paths, the host can't contain a :
351
+ res . fetchSpec = `git+file://${ parsedUrl . host . toLowerCase ( ) } :${ parsedUrl . pathname } `
350
352
} else {
351
- setGitCommittish ( res , urlparse . hash != null ? urlparse . hash . slice ( 1 ) : '' )
352
- urlparse . protocol = urlparse . protocol . replace ( / ^ g i t [ + ] / , '' )
353
- if ( urlparse . protocol === 'file:' && / ^ g i t \+ f i l e : \/ \/ [ a - z ] : / i. test ( res . rawSpec ) ) {
354
- // keep the drive letter : on windows file paths
355
- urlparse . host += ':'
356
- urlparse . hostname += ':'
357
- }
358
- delete urlparse . hash
359
- res . fetchSpec = url . format ( urlparse )
353
+ parsedUrl . hash = ''
354
+ res . fetchSpec = parsedUrl . toString ( )
355
+ }
356
+ if ( res . fetchSpec . startsWith ( 'git+' ) ) {
357
+ res . fetchSpec = res . fetchSpec . slice ( 4 )
360
358
}
361
359
break
362
- }
363
360
case 'http:' :
364
361
case 'https:' :
365
362
res . type = 'remote'
366
363
res . fetchSpec = res . saveSpec
367
364
break
368
365
369
366
default :
370
- throw unsupportedURLType ( urlparse . protocol , res . rawSpec )
367
+ throw unsupportedURLType ( parsedUrl . protocol , rawSpec )
371
368
}
372
369
373
370
return res
0 commit comments