@@ -296,12 +296,44 @@ impl CredentialHelper {
296
296
}
297
297
) ) ;
298
298
299
- let mut p = my_try ! ( Command :: new( "sh" ) . arg( "-c" )
300
- . arg( & format!( "{} get" , cmd) )
301
- . stdin( Stdio :: piped( ) )
302
- . stdout( Stdio :: piped( ) )
303
- . stderr( Stdio :: piped( ) )
304
- . spawn( ) ) ;
299
+ // It looks like the `cmd` specification is typically bourne-shell-like
300
+ // syntax, so try that first. If that fails, though, we may be on a
301
+ // Windows machine for example where `sh` isn't actually available by
302
+ // default. Most credential helper configurations though are pretty
303
+ // simple (aka one or two space-separated strings) so also try to invoke
304
+ // the process directly.
305
+ //
306
+ // If that fails then it's up to the user to put `sh` in path and make
307
+ // sure it works.
308
+ let mut c = Command :: new ( "sh" ) ;
309
+ c. arg ( "-c" )
310
+ . arg ( & format ! ( "{} get" , cmd) )
311
+ . stdin ( Stdio :: piped ( ) )
312
+ . stdout ( Stdio :: piped ( ) )
313
+ . stderr ( Stdio :: piped ( ) ) ;
314
+ let mut p = match c. spawn ( ) {
315
+ Ok ( p) => p,
316
+ Err ( e) => {
317
+ debug ! ( "`sh` failed to spawn: {}" , e) ;
318
+ let mut parts = cmd. split_whitespace ( ) ;
319
+ let mut c = Command :: new ( parts. next ( ) . unwrap ( ) ) ;
320
+ for arg in parts {
321
+ c. arg ( arg) ;
322
+ }
323
+ c. arg ( "get" )
324
+ . stdin ( Stdio :: piped ( ) )
325
+ . stdout ( Stdio :: piped ( ) )
326
+ . stderr ( Stdio :: piped ( ) ) ;
327
+ match c. spawn ( ) {
328
+ Ok ( p) => p,
329
+ Err ( e) => {
330
+ debug ! ( "fallback of {:?} failed with {}" , cmd, e) ;
331
+ return ( None , None ) ;
332
+ }
333
+ }
334
+ }
335
+ } ;
336
+
305
337
// Ignore write errors as the command may not actually be listening for
306
338
// stdin
307
339
{
0 commit comments