@@ -16,6 +16,11 @@ function protocolToRepresentation (protocol) {
1616 return protocolToRepresentationMap [ protocol ] || protocol . slice ( 0 , - 1 )
1717}
1818
19+ function lastIndexOfBefore ( str , char , beforeChar ) {
20+ const startPosition = str . lastIndexOf ( beforeChar )
21+ return str . lastIndexOf ( char , startPosition > - 1 ? startPosition : Infinity )
22+ }
23+
1924const authProtocols = {
2025 'git:' : true ,
2126 'https:' : true ,
@@ -189,12 +194,11 @@ const isGitHubShorthand = (arg) => {
189194// attempt to correct an scp style url so that it will parse with `new URL()`
190195const correctUrl = ( giturl ) => {
191196 const firstAt = giturl . indexOf ( '@' )
192- const lastHash = giturl . lastIndexOf ( '#' )
193- let firstColon = giturl . indexOf ( ':' )
194- let lastColon = giturl . lastIndexOf ( ':' , lastHash > - 1 ? lastHash : Infinity )
197+ // ignore colons that come after the hash since that could include colons such as:
198+ // git @github .com:user/package-2#semver:^1.0.0
199+ const lastColonBeforeHash = lastIndexOfBefore ( giturl , ':' , '#' )
195200
196- let corrected
197- if ( lastColon > firstAt ) {
201+ if ( lastColonBeforeHash > firstAt ) {
198202 // the last : comes after the first @ (or there is no @)
199203 // like it would in:
200204 // proto://hostname.com:user/repo
@@ -205,44 +209,33 @@ const correctUrl = (giturl) => {
205209 // proto://:password@hostname .com:user/repo
206210 // proto://username:password@hostname .com:user/repo
207211 // 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+ giturl = giturl . slice ( 0 , lastColonBeforeHash ) + '/' + giturl . slice ( lastColonBeforeHash + 1 )
212213 }
213214
214- if ( firstColon === - 1 && giturl . indexOf ( '//' ) === - 1 ) {
215+ if ( lastIndexOfBefore ( giturl , ':' , '#' ) === - 1 && giturl . indexOf ( '//' ) === - 1 ) {
215216 // we have no : at all
216217 // as it would be in:
217218 // username@hostname .com/user/repo
218219 // then we prepend a protocol
219- corrected = `git+ssh://${ corrected } `
220+ giturl = `git+ssh://${ giturl } `
220221 }
221222
222- return corrected
223+ return giturl
223224}
224225
225226// try to parse the url as its given to us, if that throws
226227// then we try to clean the url and parse that result instead
227228// THIS FUNCTION SHOULD NEVER THROW
228229const parseGitUrl = ( giturl ) => {
229- let result
230230 try {
231- result = new url . URL ( giturl )
231+ return new url . URL ( giturl )
232232 } catch {
233233 // this fn should never throw
234234 }
235235
236- if ( result ) {
237- return result
238- }
239-
240- const correctedUrl = correctUrl ( giturl )
241236 try {
242- result = new url . URL ( correctedUrl )
237+ return new url . URL ( correctUrl ( giturl ) )
243238 } catch {
244239 // this fn should never throw
245240 }
246-
247- return result
248241}
0 commit comments