-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
37 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ module.exports.resolve = resolve | |
module.exports.toPurl = toPurl | ||
module.exports.Result = Result | ||
|
||
const url = require('url') | ||
const { URL } = require('url') | ||
const HostedGit = require('hosted-git-info') | ||
const semver = require('semver') | ||
const path = global.FAKE_WINDOWS ? require('path').win32 : require('path') | ||
|
@@ -245,8 +245,8 @@ function fromFile (res, where) { | |
const rawWithPrefix = prefix + res.rawSpec | ||
let rawNoPrefix = rawWithPrefix.replace(/^file:/, '') | ||
try { | ||
resolvedUrl = new url.URL(rawWithPrefix, `file://${path.resolve(where)}/`) | ||
specUrl = new url.URL(rawWithPrefix) | ||
resolvedUrl = new URL(rawWithPrefix, `file://${path.resolve(where)}/`) | ||
specUrl = new URL(rawWithPrefix) | ||
} catch (originalError) { | ||
const er = new Error('Invalid file: URL, must comply with RFC 8909') | ||
throw Object.assign(er, { | ||
|
@@ -263,17 +263,17 @@ function fromFile (res, where) { | |
// Remove when we want a breaking change to come into RFC compliance. | ||
if (resolvedUrl.host && resolvedUrl.host !== 'localhost') { | ||
const rawSpec = res.rawSpec.replace(/^file:\/\//, 'file:///') | ||
resolvedUrl = new url.URL(rawSpec, `file://${path.resolve(where)}/`) | ||
specUrl = new url.URL(rawSpec) | ||
resolvedUrl = new URL(rawSpec, `file://${path.resolve(where)}/`) | ||
specUrl = new URL(rawSpec) | ||
rawNoPrefix = rawSpec.replace(/^file:/, '') | ||
} | ||
// turn file:/../foo into file:../foo | ||
// for 1, 2 or 3 leading slashes since we attempted | ||
// in the previous step to make it a file protocol url with a leading slash | ||
if (/^\/{1,3}\.\.?(\/|$)/.test(rawNoPrefix)) { | ||
const rawSpec = res.rawSpec.replace(/^file:\/{1,3}/, 'file:') | ||
resolvedUrl = new url.URL(rawSpec, `file://${path.resolve(where)}/`) | ||
specUrl = new url.URL(rawSpec) | ||
resolvedUrl = new URL(rawSpec, `file://${path.resolve(where)}/`) | ||
specUrl = new URL(rawSpec) | ||
rawNoPrefix = rawSpec.replace(/^file:/, '') | ||
} | ||
// XXX end 8909 violation backwards compatibility section | ||
|
@@ -329,28 +329,29 @@ function unsupportedURLType (protocol, spec) { | |
return err | ||
} | ||
|
||
function matchGitScp (spec) { | ||
// git ssh specifiers are overloaded to also use scp-style git | ||
// specifiers, so we have to parse those out and treat them special. | ||
// They are NOT true URIs, so we can't hand them to `url.parse`. | ||
// | ||
// This regex looks for things that look like: | ||
// git+ssh://[email protected]:username/project.git#deadbeef | ||
// | ||
// ...and various combinations. The username in the beginning is *required*. | ||
const matched = spec.match(/^git\+ssh:\/\/([^:#]+:[^#]+(?:\.git)?)(?:#(.*))?$/i) | ||
return matched && !matched[1].match(/:[0-9]+\/?.*$/i) && { | ||
fetchSpec: matched[1], | ||
gitCommittish: matched[2] == null ? null : matched[2], | ||
} | ||
} | ||
|
||
function fromURL (res) { | ||
let rawSpec = res.rawSpec | ||
res.saveSpec = rawSpec | ||
if (rawSpec.startsWith('git+ssh:')) { | ||
// git ssh specifiers are overloaded to also use scp-style git | ||
// specifiers, so we have to parse those out and treat them special. | ||
// They are NOT true URIs, so we can't hand them to URL. | ||
const matched = rawSpec.match(/^git\+ssh:\/\/([^:#]+:[^#]+(?:\.git)?)(?:#(.*))?$/i) | ||
if (matched && !matched[1].match(/:[0-9]+\/?.*$/i)) { | ||
res.type = 'git' | ||
setGitCommittish(res, matched[2]) | ||
res.fetchSpec = matched[1] | ||
return res | ||
} | ||
} else if (rawSpec.startsWith('git+file://')) { | ||
// URL can't handle windows paths | ||
const noProtocol = rawSpec.slice(11).replace(/\\/g, '/') | ||
rawSpec = `git+file://${noProtocol}` | ||
} | ||
// eslint-disable-next-line node/no-deprecated-api | ||
const urlparse = url.parse(res.rawSpec) | ||
res.saveSpec = res.rawSpec | ||
const parsedUrl = new URL(rawSpec) | ||
// check the protocol, and then see if it's git or not | ||
switch (urlparse.protocol) { | ||
switch (parsedUrl.protocol) { | ||
case 'git:': | ||
case 'git+http:': | ||
case 'git+https:': | ||
|
@@ -359,21 +360,16 @@ function fromURL (res) { | |
case 'git+file:': | ||
case 'git+ssh:': { | ||
res.type = 'git' | ||
const match = urlparse.protocol === 'git+ssh:' ? matchGitScp(res.rawSpec) | ||
: null | ||
if (match) { | ||
setGitCommittish(res, match.gitCommittish) | ||
res.fetchSpec = match.fetchSpec | ||
setGitCommittish(res, parsedUrl.hash.slice(1)) | ||
if (parsedUrl.protocol === 'git+file:' && /^git\+file:\/\/[a-z]:/i.test(rawSpec)) { | ||
// URL can't handle drive letters on windows file paths, the host can't contain a : | ||
res.fetchSpec = `git+file://${parsedUrl.host.toLowerCase()}:${parsedUrl.pathname}` | ||
} else { | ||
setGitCommittish(res, urlparse.hash != null ? urlparse.hash.slice(1) : '') | ||
urlparse.protocol = urlparse.protocol.replace(/^git[+]/, '') | ||
if (urlparse.protocol === 'file:' && /^git\+file:\/\/[a-z]:/i.test(res.rawSpec)) { | ||
// keep the drive letter : on windows file paths | ||
urlparse.host += ':' | ||
urlparse.hostname += ':' | ||
} | ||
delete urlparse.hash | ||
res.fetchSpec = url.format(urlparse) | ||
parsedUrl.hash = '' | ||
res.fetchSpec = parsedUrl.toString() | ||
} | ||
if (res.fetchSpec.startsWith('git+')) { | ||
res.fetchSpec = res.fetchSpec.slice(4) | ||
} | ||
break | ||
} | ||
|
@@ -384,7 +380,7 @@ function fromURL (res) { | |
break | ||
|
||
default: | ||
throw unsupportedURLType(urlparse.protocol, res.rawSpec) | ||
throw unsupportedURLType(parsedUrl.protocol, rawSpec) | ||
} | ||
|
||
return res | ||
|