@@ -7,11 +7,14 @@ use std::path::{Path, PathBuf};
7
7
use std:: process:: Stdio ;
8
8
use std:: str;
9
9
10
+ use cargo_test_support:: basic_manifest;
11
+ use cargo_test_support:: paths:: CargoPathExt ;
10
12
use cargo_test_support:: registry:: Package ;
11
13
use cargo_test_support:: tools:: echo_subcommand;
12
14
use cargo_test_support:: {
13
15
basic_bin_manifest, cargo_exe, cargo_process, paths, project, project_in_home,
14
16
} ;
17
+ use cargo_util:: paths:: join_paths;
15
18
16
19
fn path ( ) -> Vec < PathBuf > {
17
20
env:: split_paths ( & env:: var_os ( "PATH" ) . unwrap_or_default ( ) ) . collect ( )
@@ -341,6 +344,83 @@ fn cargo_subcommand_env() {
341
344
. run ( ) ;
342
345
}
343
346
347
+ #[ cargo_test]
348
+ fn cargo_cmd_bins_vs_explicit_path ( ) {
349
+ // Set up `cargo-foo` binary in two places: inside `$HOME/.cargo/bin` and outside of it
350
+ //
351
+ // Return paths to both places
352
+ fn set_up_cargo_foo ( ) -> ( PathBuf , PathBuf ) {
353
+ let p = project ( )
354
+ . at ( "cargo-foo" )
355
+ . file ( "Cargo.toml" , & basic_manifest ( "cargo-foo" , "1.0.0" ) )
356
+ . file (
357
+ "src/bin/cargo-foo.rs" ,
358
+ r#"fn main() { println!("INSIDE"); }"# ,
359
+ )
360
+ . file (
361
+ "src/bin/cargo-foo2.rs" ,
362
+ r#"fn main() { println!("OUTSIDE"); }"# ,
363
+ )
364
+ . build ( ) ;
365
+ p. cargo ( "build" ) . run ( ) ;
366
+ let cargo_bin_dir = paths:: home ( ) . join ( ".cargo/bin" ) ;
367
+ cargo_bin_dir. mkdir_p ( ) ;
368
+ let root_bin_dir = paths:: root ( ) . join ( "bin" ) ;
369
+ root_bin_dir. mkdir_p ( ) ;
370
+ let exe_name = format ! ( "cargo-foo{}" , env:: consts:: EXE_SUFFIX ) ;
371
+ fs:: rename ( p. bin ( "cargo-foo" ) , cargo_bin_dir. join ( & exe_name) ) . unwrap ( ) ;
372
+ fs:: rename ( p. bin ( "cargo-foo2" ) , root_bin_dir. join ( & exe_name) ) . unwrap ( ) ;
373
+
374
+ ( root_bin_dir, cargo_bin_dir)
375
+ }
376
+
377
+ let ( outside_dir, inside_dir) = set_up_cargo_foo ( ) ;
378
+
379
+ // If `$CARGO_HOME/bin` is not in a path, prefer it over anything in `$PATH`.
380
+ //
381
+ // This is the historical behavior we don't want to break.
382
+ cargo_process ( "foo" ) . with_stdout_contains ( "INSIDE" ) . run ( ) ;
383
+
384
+ // When `$CARGO_HOME/bin` is in the `$PATH`
385
+ // use only `$PATH` so the user-defined ordering is respected.
386
+ {
387
+ cargo_process ( "foo" )
388
+ . env (
389
+ "PATH" ,
390
+ join_paths ( & [ & inside_dir, & outside_dir] , "PATH" ) . unwrap ( ) ,
391
+ )
392
+ . with_stdout_contains ( "INSIDE" )
393
+ . run ( ) ;
394
+
395
+ cargo_process ( "foo" )
396
+ // Note: trailing slash
397
+ . env (
398
+ "PATH" ,
399
+ join_paths ( & [ inside_dir. join ( "" ) , outside_dir. join ( "" ) ] , "PATH" ) . unwrap ( ) ,
400
+ )
401
+ . with_stdout_contains ( "INSIDE" )
402
+ . run ( ) ;
403
+
404
+ cargo_process ( "foo" )
405
+ . env (
406
+ "PATH" ,
407
+ join_paths ( & [ & outside_dir, & inside_dir] , "PATH" ) . unwrap ( ) ,
408
+ )
409
+ . with_stdout_contains ( "OUTSIDE" )
410
+ . run ( ) ;
411
+
412
+ cargo_process ( "foo" )
413
+ // Note: trailing slash
414
+ . env (
415
+ "PATH" ,
416
+ join_paths ( & [ outside_dir. join ( "" ) , inside_dir. join ( "" ) ] , "PATH" ) . unwrap ( ) ,
417
+ )
418
+ . with_stdout_contains ( "OUTSIDE" )
419
+ . run ( ) ;
420
+ }
421
+ }
422
+
423
+ #[ test]
344
424
#[ cargo_test]
345
425
fn cargo_subcommand_args ( ) {
346
426
let p = echo_subcommand ( ) ;
0 commit comments