@@ -19,7 +19,7 @@ pub enum Error {
1919 Url {
2020 url : String ,
2121 kind : UrlKind ,
22- source : url :: ParseError ,
22+ source : crate :: simple_url :: UrlParseError ,
2323 } ,
2424
2525 #[ error( "The host portion of the following URL is too long ({} bytes, {len} bytes total): {truncated_url:?}" , truncated_url. len( ) ) ]
@@ -99,30 +99,33 @@ pub(crate) fn url(input: &BStr, protocol_end: usize) -> Result<crate::Url, Error
9999 } ) ;
100100 }
101101 let ( input, url) = input_to_utf8_and_url ( input, UrlKind :: Url ) ?;
102- let scheme = url. scheme ( ) . into ( ) ;
102+ let scheme = Scheme :: from ( url. scheme . as_str ( ) ) ;
103103
104- if matches ! ( scheme, Scheme :: Git | Scheme :: Ssh ) && url. path ( ) . is_empty ( ) {
104+ if matches ! ( scheme, Scheme :: Git | Scheme :: Ssh ) && url. path . is_empty ( ) {
105105 return Err ( Error :: MissingRepositoryPath {
106106 url : input. into ( ) ,
107107 kind : UrlKind :: Url ,
108108 } ) ;
109109 }
110110
111- if url. cannot_be_a_base ( ) {
112- return Err ( Error :: RelativeUrl { url : input. to_owned ( ) } ) ;
113- }
111+ // Normalize empty path to "/" for http/https URLs only
112+ let path = if url. path . is_empty ( ) && matches ! ( scheme, Scheme :: Http | Scheme :: Https ) {
113+ "/" . into ( )
114+ } else {
115+ url. path . into ( )
116+ } ;
114117
115118 Ok ( crate :: Url {
116119 serialize_alternative_form : false ,
117120 scheme,
118121 user : url_user ( & url, UrlKind :: Url ) ?,
119122 password : url
120- . password ( )
123+ . password
121124 . map ( |s| percent_decoded_utf8 ( s, UrlKind :: Url ) )
122125 . transpose ( ) ?,
123- host : url. host_str ( ) . map ( Into :: into ) ,
124- port : url. port ( ) ,
125- path : url . path ( ) . into ( ) ,
126+ host : url. host ,
127+ port : url. port ,
128+ path,
126129 } )
127130}
128131
@@ -156,31 +159,32 @@ pub(crate) fn scp(input: &BStr, colon: usize) -> Result<crate::Url, Error> {
156159 // should never differ in any other way (ssh URLs should not contain a query or fragment part).
157160 // To avoid the various off-by-one errors caused by the `/` characters, we keep using the path
158161 // determined above and can therefore skip parsing it here as well.
159- let url = url:: Url :: parse ( & format ! ( "ssh://{host}" ) ) . map_err ( |source| Error :: Url {
162+ let url_string = format ! ( "ssh://{host}" ) ;
163+ let url = crate :: simple_url:: ParsedUrl :: parse ( & url_string) . map_err ( |source| Error :: Url {
160164 url : input. to_owned ( ) ,
161165 kind : UrlKind :: Scp ,
162166 source,
163167 } ) ?;
164168
165169 Ok ( crate :: Url {
166170 serialize_alternative_form : true ,
167- scheme : url. scheme ( ) . into ( ) ,
171+ scheme : Scheme :: from ( url. scheme . as_str ( ) ) ,
168172 user : url_user ( & url, UrlKind :: Scp ) ?,
169173 password : url
170- . password ( )
174+ . password
171175 . map ( |s| percent_decoded_utf8 ( s, UrlKind :: Scp ) )
172176 . transpose ( ) ?,
173- host : url. host_str ( ) . map ( Into :: into ) ,
174- port : url. port ( ) ,
177+ host : url. host ,
178+ port : url. port ,
175179 path : path. into ( ) ,
176180 } )
177181}
178182
179- fn url_user ( url : & url :: Url , kind : UrlKind ) -> Result < Option < String > , Error > {
180- if url. username ( ) . is_empty ( ) && url. password ( ) . is_none ( ) {
183+ fn url_user ( url : & crate :: simple_url :: ParsedUrl < ' _ > , kind : UrlKind ) -> Result < Option < String > , Error > {
184+ if url. username . is_empty ( ) && url. password . is_none ( ) {
181185 Ok ( None )
182186 } else {
183- Ok ( Some ( percent_decoded_utf8 ( url. username ( ) , kind) ?) )
187+ Ok ( Some ( percent_decoded_utf8 ( url. username , kind) ?) )
184188 }
185189}
186190
@@ -269,13 +273,22 @@ fn input_to_utf8(input: &BStr, kind: UrlKind) -> Result<&str, Error> {
269273 } )
270274}
271275
272- fn input_to_utf8_and_url ( input : & BStr , kind : UrlKind ) -> Result < ( & str , url :: Url ) , Error > {
276+ fn input_to_utf8_and_url ( input : & BStr , kind : UrlKind ) -> Result < ( & str , crate :: simple_url :: ParsedUrl < ' _ > ) , Error > {
273277 let input = input_to_utf8 ( input, kind) ?;
274- url :: Url :: parse ( input)
278+ crate :: simple_url :: ParsedUrl :: parse ( input)
275279 . map ( |url| ( input, url) )
276- . map_err ( |source| Error :: Url {
277- url : input. to_owned ( ) ,
278- kind,
279- source,
280+ . map_err ( |source| {
281+ // If the parser rejected it as RelativeUrlWithoutBase, map to Error::RelativeUrl
282+ // to match the expected error type for malformed URLs like "invalid:://"
283+ match source {
284+ crate :: simple_url:: UrlParseError :: RelativeUrlWithoutBase => {
285+ Error :: RelativeUrl { url : input. to_owned ( ) }
286+ }
287+ _ => Error :: Url {
288+ url : input. to_owned ( ) ,
289+ kind,
290+ source,
291+ } ,
292+ }
280293 } )
281294}
0 commit comments