@@ -16,6 +16,11 @@ function protocolToRepresentation (protocol) {
16
16
return protocolToRepresentationMap [ protocol ] || protocol . slice ( 0 , - 1 )
17
17
}
18
18
19
+ function lastIndexOfBefore ( str , char , beforeChar ) {
20
+ const startPosition = str . lastIndexOf ( beforeChar )
21
+ return str . lastIndexOf ( char , startPosition > - 1 ? startPosition : Infinity )
22
+ }
23
+
19
24
const authProtocols = {
20
25
'git:' : true ,
21
26
'https:' : true ,
@@ -189,12 +194,11 @@ const isGitHubShorthand = (arg) => {
189
194
// attempt to correct an scp style url so that it will parse with `new URL()`
190
195
const correctUrl = ( giturl ) => {
191
196
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 , ':' , '#' )
195
200
196
- let corrected
197
- if ( lastColon > firstAt ) {
201
+ if ( lastColonBeforeHash > firstAt ) {
198
202
// the last : comes after the first @ (or there is no @)
199
203
// like it would in:
200
204
// proto://hostname.com:user/repo
@@ -205,44 +209,33 @@ const correctUrl = (giturl) => {
205
209
// proto://:password@hostname .com:user/repo
206
210
// proto://username:password@hostname .com:user/repo
207
211
// 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 )
212
213
}
213
214
214
- if ( firstColon === - 1 && giturl . indexOf ( '//' ) === - 1 ) {
215
+ if ( lastIndexOfBefore ( giturl , ':' , '#' ) === - 1 && giturl . indexOf ( '//' ) === - 1 ) {
215
216
// we have no : at all
216
217
// as it would be in:
217
218
// username@hostname .com/user/repo
218
219
// then we prepend a protocol
219
- corrected = `git+ssh://${ corrected } `
220
+ giturl = `git+ssh://${ giturl } `
220
221
}
221
222
222
- return corrected
223
+ return giturl
223
224
}
224
225
225
226
// try to parse the url as its given to us, if that throws
226
227
// then we try to clean the url and parse that result instead
227
228
// THIS FUNCTION SHOULD NEVER THROW
228
229
const parseGitUrl = ( giturl ) => {
229
- let result
230
230
try {
231
- result = new url . URL ( giturl )
231
+ return new url . URL ( giturl )
232
232
} catch {
233
233
// this fn should never throw
234
234
}
235
235
236
- if ( result ) {
237
- return result
238
- }
239
-
240
- const correctedUrl = correctUrl ( giturl )
241
236
try {
242
- result = new url . URL ( correctedUrl )
237
+ return new url . URL ( correctUrl ( giturl ) )
243
238
} catch {
244
239
// this fn should never throw
245
240
}
246
-
247
- return result
248
241
}
0 commit comments