@@ -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,16 @@ 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 ) ;
529
+ collect_tests_from_dir (
530
+ config,
531
+ & config. src_base ,
532
+ & PathBuf :: new ( ) ,
533
+ & inputs,
534
+ tests,
535
+ & modified_tests,
536
+ )
537
+ . unwrap_or_else ( |_| panic ! ( "Could not read tests from {}" , config. src_base. display( ) ) ) ;
526
538
}
527
539
528
540
/// Returns a stamp constructed from input files common to all test cases.
@@ -561,12 +573,34 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
561
573
stamp
562
574
}
563
575
576
+ fn modified_tests ( config : & Config , dir : & Path ) -> Vec < PathBuf > {
577
+ if !config. only_modified {
578
+ return vec ! [ ] ;
579
+ }
580
+ let Ok ( Some ( files) ) = get_git_modified_files ( Some ( dir) , & vec ! [ "rs" , "stderr" , "fixed" ] ) else { return vec ! [ ] ; } ;
581
+ // Add new test cases to the list, it will be convenient in daily development.
582
+ let Ok ( Some ( untracked_files) ) = get_git_untracked_files ( None ) else { return vec ! [ ] ; } ;
583
+
584
+ let all_paths = [ & files[ ..] , & untracked_files[ ..] ] . concat ( ) ;
585
+ let full_paths = {
586
+ let mut full_paths: Vec < PathBuf > = all_paths
587
+ . into_iter ( )
588
+ . map ( |f| fs:: canonicalize ( & f) . unwrap ( ) . with_extension ( "" ) . with_extension ( "rs" ) )
589
+ . collect ( ) ;
590
+ full_paths. dedup ( ) ;
591
+ full_paths. sort_unstable ( ) ;
592
+ full_paths
593
+ } ;
594
+ full_paths
595
+ }
596
+
564
597
fn collect_tests_from_dir (
565
598
config : & Config ,
566
599
dir : & Path ,
567
600
relative_dir_path : & Path ,
568
601
inputs : & Stamp ,
569
602
tests : & mut Vec < test:: TestDescAndFn > ,
603
+ only_modified : & Vec < PathBuf > ,
570
604
) -> io:: Result < ( ) > {
571
605
// Ignore directories that contain a file named `compiletest-ignore-dir`.
572
606
if dir. join ( "compiletest-ignore-dir" ) . exists ( ) {
@@ -597,7 +631,7 @@ fn collect_tests_from_dir(
597
631
let file = file?;
598
632
let file_path = file. path ( ) ;
599
633
let file_name = file. file_name ( ) ;
600
- if is_test ( & file_name) {
634
+ if is_test ( & file_name) && ( !config . only_modified || only_modified . contains ( & file_path ) ) {
601
635
debug ! ( "found test file: {:?}" , file_path. display( ) ) ;
602
636
let paths =
603
637
TestPaths { file : file_path, relative_dir : relative_dir_path. to_path_buf ( ) } ;
@@ -607,7 +641,14 @@ fn collect_tests_from_dir(
607
641
let relative_file_path = relative_dir_path. join ( file. file_name ( ) ) ;
608
642
if & file_name != "auxiliary" {
609
643
debug ! ( "found directory: {:?}" , file_path. display( ) ) ;
610
- collect_tests_from_dir ( config, & file_path, & relative_file_path, inputs, tests) ?;
644
+ collect_tests_from_dir (
645
+ config,
646
+ & file_path,
647
+ & relative_file_path,
648
+ inputs,
649
+ tests,
650
+ only_modified,
651
+ ) ?;
611
652
}
612
653
} else {
613
654
debug ! ( "found other file/directory: {:?}" , file_path. display( ) ) ;
0 commit comments