@@ -8,15 +8,17 @@ extern crate test;
8
8
use crate :: common:: { expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS } ;
9
9
use crate :: common:: { CompareMode , Config , Debugger , Mode , PassMode , TestPaths } ;
10
10
use crate :: util:: logv;
11
+ use build_helper:: git:: { get_git_modified_files, get_git_untracked_files} ;
12
+ use core:: panic;
11
13
use getopts:: Options ;
12
14
use lazycell:: LazyCell ;
13
- use std:: env;
14
15
use std:: ffi:: OsString ;
15
16
use std:: fs;
16
17
use std:: io:: { self , ErrorKind } ;
17
18
use std:: path:: { Path , PathBuf } ;
18
19
use std:: process:: { Command , Stdio } ;
19
20
use std:: time:: SystemTime ;
21
+ use std:: { env, vec} ;
20
22
use test:: ColorConfig ;
21
23
use tracing:: * ;
22
24
use walkdir:: WalkDir ;
@@ -145,9 +147,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
145
147
"" ,
146
148
"rustfix-coverage" ,
147
149
"enable this to generate a Rustfix coverage file, which is saved in \
148
- `./<build_base>/rustfix_missing_coverage.txt`",
150
+ `./<build_base>/rustfix_missing_coverage.txt`",
149
151
)
150
152
. optflag ( "" , "force-rerun" , "rerun tests even if the inputs are unchanged" )
153
+ . optflag ( "" , "only-modified" , "only run tests that result been modified" )
151
154
. optflag ( "h" , "help" , "show this message" )
152
155
. reqopt ( "" , "channel" , "current Rust channel" , "CHANNEL" )
153
156
. optopt ( "" , "edition" , "default Rust edition" , "EDITION" ) ;
@@ -279,6 +282,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
279
282
lldb_python_dir : matches. opt_str ( "lldb-python-dir" ) ,
280
283
verbose : matches. opt_present ( "verbose" ) ,
281
284
quiet : matches. opt_present ( "quiet" ) ,
285
+ only_modified : matches. opt_present ( "only-modified" ) ,
282
286
color,
283
287
remote_test_client : matches. opt_str ( "remote-test-client" ) . map ( PathBuf :: from) ,
284
288
compare_mode : matches. opt_str ( "compare-mode" ) . map ( CompareMode :: parse) ,
@@ -521,8 +525,18 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
521
525
pub fn make_tests ( config : & Config , tests : & mut Vec < test:: TestDescAndFn > ) {
522
526
debug ! ( "making tests from {:?}" , config. src_base. display( ) ) ;
523
527
let inputs = common_inputs_stamp ( config) ;
524
- collect_tests_from_dir ( config, & config. src_base , & PathBuf :: new ( ) , & inputs, tests)
525
- . unwrap_or_else ( |_| panic ! ( "Could not read tests from {}" , config. src_base. display( ) ) ) ;
528
+ let modified_tests = modified_tests ( config, & config. src_base ) . unwrap_or_else ( |err| {
529
+ panic ! ( "modified_tests got error from dir: {}, error: {}" , config. src_base. display( ) , err)
530
+ } ) ;
531
+ collect_tests_from_dir (
532
+ config,
533
+ & config. src_base ,
534
+ & PathBuf :: new ( ) ,
535
+ & inputs,
536
+ tests,
537
+ & modified_tests,
538
+ )
539
+ . unwrap_or_else ( |_| panic ! ( "Could not read tests from {}" , config. src_base. display( ) ) ) ;
526
540
}
527
541
528
542
/// Returns a stamp constructed from input files common to all test cases.
@@ -561,12 +575,35 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
561
575
stamp
562
576
}
563
577
578
+ fn modified_tests ( config : & Config , dir : & Path ) -> Result < Vec < PathBuf > , String > {
579
+ if !config. only_modified {
580
+ return Ok ( vec ! [ ] ) ;
581
+ }
582
+ let files =
583
+ get_git_modified_files ( Some ( dir) , & vec ! [ "rs" , "stderr" , "fixed" ] ) ?. unwrap_or ( vec ! [ ] ) ;
584
+ // Add new test cases to the list, it will be convenient in daily development.
585
+ let untracked_files = get_git_untracked_files ( None ) ?. unwrap_or ( vec ! [ ] ) ;
586
+
587
+ let all_paths = [ & files[ ..] , & untracked_files[ ..] ] . concat ( ) ;
588
+ let full_paths = {
589
+ let mut full_paths: Vec < PathBuf > = all_paths
590
+ . into_iter ( )
591
+ . map ( |f| fs:: canonicalize ( & f) . unwrap ( ) . with_extension ( "" ) . with_extension ( "rs" ) )
592
+ . collect ( ) ;
593
+ full_paths. dedup ( ) ;
594
+ full_paths. sort_unstable ( ) ;
595
+ full_paths
596
+ } ;
597
+ Ok ( full_paths)
598
+ }
599
+
564
600
fn collect_tests_from_dir (
565
601
config : & Config ,
566
602
dir : & Path ,
567
603
relative_dir_path : & Path ,
568
604
inputs : & Stamp ,
569
605
tests : & mut Vec < test:: TestDescAndFn > ,
606
+ modified_tests : & Vec < PathBuf > ,
570
607
) -> io:: Result < ( ) > {
571
608
// Ignore directories that contain a file named `compiletest-ignore-dir`.
572
609
if dir. join ( "compiletest-ignore-dir" ) . exists ( ) {
@@ -597,7 +634,7 @@ fn collect_tests_from_dir(
597
634
let file = file?;
598
635
let file_path = file. path ( ) ;
599
636
let file_name = file. file_name ( ) ;
600
- if is_test ( & file_name) {
637
+ if is_test ( & file_name) && ( !config . only_modified || modified_tests . contains ( & file_path ) ) {
601
638
debug ! ( "found test file: {:?}" , file_path. display( ) ) ;
602
639
let paths =
603
640
TestPaths { file : file_path, relative_dir : relative_dir_path. to_path_buf ( ) } ;
@@ -607,7 +644,14 @@ fn collect_tests_from_dir(
607
644
let relative_file_path = relative_dir_path. join ( file. file_name ( ) ) ;
608
645
if & file_name != "auxiliary" {
609
646
debug ! ( "found directory: {:?}" , file_path. display( ) ) ;
610
- collect_tests_from_dir ( config, & file_path, & relative_file_path, inputs, tests) ?;
647
+ collect_tests_from_dir (
648
+ config,
649
+ & file_path,
650
+ & relative_file_path,
651
+ inputs,
652
+ tests,
653
+ modified_tests,
654
+ ) ?;
611
655
}
612
656
} else {
613
657
debug ! ( "found other file/directory: {:?}" , file_path. display( ) ) ;
0 commit comments