Skip to content

Commit

Permalink
fix: ignore colons after hash when correcting scp urls
Browse files Browse the repository at this point in the history
Fixes #148
  • Loading branch information
lukekarrys committed Oct 12, 2022
1 parent 88d450f commit 3cd4a98
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 78 deletions.
37 changes: 15 additions & 22 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ function protocolToRepresentation (protocol) {
return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
}

function lastIndexOfBefore (str, char, beforeChar) {
const startPosition = str.lastIndexOf(beforeChar)
return str.lastIndexOf(char, startPosition > -1 ? startPosition : Infinity)
}

const authProtocols = {
'git:': true,
'https:': true,
Expand Down Expand Up @@ -189,12 +194,11 @@ const isGitHubShorthand = (arg) => {
// attempt to correct an scp style url so that it will parse with `new URL()`
const correctUrl = (giturl) => {
const firstAt = giturl.indexOf('@')
const lastHash = giturl.lastIndexOf('#')
let firstColon = giturl.indexOf(':')
let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity)
// ignore colons that come after the hash since that could include colons such as:
// git@github.com:user/package-2#semver:^1.0.0
const lastColonBeforeHash = lastIndexOfBefore(giturl, ':', '#')

let corrected
if (lastColon > firstAt) {
if (lastColonBeforeHash > firstAt) {
// the last : comes after the first @ (or there is no @)
// like it would in:
// proto://hostname.com:user/repo
Expand All @@ -205,44 +209,33 @@ const correctUrl = (giturl) => {
// proto://:password@hostname.com:user/repo
// proto://username:password@hostname.com:user/repo
// then we replace the last : with a / to create a valid path
corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1)
// // and we find our new : positions
firstColon = corrected.indexOf(':')
lastColon = corrected.lastIndexOf(':')
giturl = giturl.slice(0, lastColonBeforeHash) + '/' + giturl.slice(lastColonBeforeHash + 1)
}

if (firstColon === -1 && giturl.indexOf('//') === -1) {
if (lastIndexOfBefore(giturl, ':', '#') === -1 && giturl.indexOf('//') === -1) {
// we have no : at all
// as it would be in:
// username@hostname.com/user/repo
// then we prepend a protocol
corrected = `git+ssh://${corrected}`
giturl = `git+ssh://${giturl}`
}

return corrected
return giturl
}

// try to parse the url as its given to us, if that throws
// then we try to clean the url and parse that result instead
// THIS FUNCTION SHOULD NEVER THROW
const parseGitUrl = (giturl) => {
let result
try {
result = new url.URL(giturl)
return new url.URL(giturl)
} catch {
// this fn should never throw
}

if (result) {
return result
}

const correctedUrl = correctUrl(giturl)
try {
result = new url.URL(correctedUrl)
return new url.URL(correctUrl(giturl))
} catch {
// this fn should never throw
}

return result
}
Loading

0 comments on commit 3cd4a98

Please sign in to comment.