@@ -22,6 +22,7 @@ pub struct CredentialHelper {
22
22
pub username : Option < String > ,
23
23
protocol : Option < String > ,
24
24
host : Option < String > ,
25
+ path : Option < String > ,
25
26
url : String ,
26
27
commands : Vec < String > ,
27
28
}
@@ -198,6 +199,7 @@ impl CredentialHelper {
198
199
let mut ret = CredentialHelper {
199
200
protocol : None ,
200
201
host : None ,
202
+ path : None ,
201
203
username : None ,
202
204
url : url. to_string ( ) ,
203
205
commands : Vec :: new ( ) ,
@@ -208,7 +210,7 @@ impl CredentialHelper {
208
210
if let Some ( url:: Host :: Domain ( s) ) = url. host ( ) {
209
211
ret. host = Some ( s. to_string ( ) ) ;
210
212
}
211
- ret. protocol = Some ( url. scheme ( ) . to_string ( ) )
213
+ ret. protocol = Some ( url. scheme ( ) . to_string ( ) ) ;
212
214
}
213
215
ret
214
216
}
@@ -227,12 +229,11 @@ impl CredentialHelper {
227
229
// Figure out the configured username/helper program.
228
230
//
229
231
// see http://git-scm.com/docs/gitcredentials.html#_configuration_options
230
- //
231
- // TODO: implement useHttpPath
232
232
if self . username . is_none ( ) {
233
233
self . config_username ( config) ;
234
234
}
235
235
self . config_helper ( config) ;
236
+ self . config_use_http_path ( config) ;
236
237
self
237
238
}
238
239
@@ -261,6 +262,29 @@ impl CredentialHelper {
261
262
self . add_command ( global. as_ref ( ) . ok ( ) . map ( |s| & s[ ..] ) ) ;
262
263
}
263
264
265
+ // Discover `useHttpPath` from `config`
266
+ fn config_use_http_path ( & mut self , config : & Config ) {
267
+ let mut use_http_path = false ;
268
+ if let Some ( value) = config. get_bool ( & self . exact_key ( "useHttpPath" ) ) . ok ( ) {
269
+ use_http_path = value;
270
+ } else if let Some ( value) = self
271
+ . url_key ( "useHttpPath" )
272
+ . and_then ( |key| config. get_bool ( & key) . ok ( ) )
273
+ {
274
+ use_http_path = value;
275
+ } else if let Some ( value) = config. get_bool ( "credential.useHttpPath" ) . ok ( ) {
276
+ use_http_path = value;
277
+ }
278
+
279
+ if use_http_path {
280
+ if let Ok ( url) = url:: Url :: parse ( & self . url ) {
281
+ let path = url. path ( ) ;
282
+ // Url::parse always includes a leading slash for rooted URLs, while git does not.
283
+ self . path = Some ( path. strip_prefix ( '/' ) . unwrap_or ( path) . to_string ( ) ) ;
284
+ }
285
+ }
286
+ }
287
+
264
288
// Add a `helper` configured command to the list of commands to execute.
265
289
//
266
290
// see https://www.kernel.org/pub/software/scm/git/docs/technical
@@ -386,6 +410,9 @@ impl CredentialHelper {
386
410
if let Some ( ref p) = self . host {
387
411
let _ = writeln ! ( stdin, "host={}" , p) ;
388
412
}
413
+ if let Some ( ref p) = self . path {
414
+ let _ = writeln ! ( stdin, "path={}" , p) ;
415
+ }
389
416
if let Some ( ref p) = * username {
390
417
let _ = writeln ! ( stdin, "username={}" , p) ;
391
418
}
@@ -602,6 +629,16 @@ echo password=$2
602
629
assert_eq ! ( p, "b" ) ;
603
630
}
604
631
632
+ #[ test]
633
+ fn credential_helper8 ( ) {
634
+ let cfg = test_cfg ! {
635
+ "credential.useHttpPath" => "true"
636
+ } ;
637
+ let mut helper = CredentialHelper :: new ( "https://example.com/foo/bar" ) ;
638
+ helper. config ( & cfg) ;
639
+ assert_eq ! ( helper. path. as_deref( ) , Some ( "foo/bar" ) ) ;
640
+ }
641
+
605
642
#[ test]
606
643
#[ cfg( feature = "ssh" ) ]
607
644
fn ssh_key_from_memory ( ) {
0 commit comments