@@ -8,6 +8,7 @@ mod owned;
8
8
mod stack;
9
9
10
10
use std:: io:: Write ;
11
+ use std:: path:: Path ;
11
12
12
13
pub struct Config < ' a > {
13
14
pub dry_run : bool ,
@@ -372,6 +373,25 @@ fn run_with_repo(logger: &slog::Logger, config: &Config, repo: &git2::Repository
372
373
assert ! ( number_of_parents <= 1 ) ;
373
374
374
375
let mut command = Command :: new ( "git" ) ;
376
+
377
+ // We'd generally expect to be run from within the repository, but just in case,
378
+ // try to have git run rebase from the repository root.
379
+ // This simplifies writing tests that execute from within git-absorb's source directory
380
+ // but operate on temporary repositories created elsewhere.
381
+ // (The tests could explicitly change directories, but then must be serialized.)
382
+ let repo_path = repo. path ( ) . parent ( ) . map ( Path :: to_str) . flatten ( ) ;
383
+ match repo_path {
384
+ Some ( path) => {
385
+ command. args ( [ "-C" , path] ) ;
386
+ }
387
+ _ => {
388
+ warn ! (
389
+ logger,
390
+ "Could not determine repository path for rebase. Running in current directory."
391
+ ) ;
392
+ }
393
+ }
394
+
375
395
command. args ( [ "rebase" , "--interactive" , "--autosquash" , "--autostash" ] ) ;
376
396
377
397
for arg in config. rebase_options {
@@ -387,9 +407,14 @@ fn run_with_repo(logger: &slog::Logger, config: &Config, repo: &git2::Repository
387
407
command. arg ( & base_commit_sha) ;
388
408
}
389
409
390
- // Don't check that we have successfully absorbed everything, nor git's
391
- // exit code -- as git will print helpful messages on its own.
392
- command. status ( ) . expect ( "could not run git rebase" ) ;
410
+ if config. dry_run {
411
+ info ! ( logger, "would have run git rebase" ; "command" => format!( "{:?}" , command) ) ;
412
+ } else {
413
+ debug ! ( logger, "running git rebase" ; "command" => format!( "{:?}" , command) ) ;
414
+ // Don't check that we have successfully absorbed everything, nor git's
415
+ // exit code -- as git will print helpful messages on its own.
416
+ command. status ( ) . expect ( "could not run git rebase" ) ;
417
+ }
393
418
}
394
419
395
420
Ok ( ( ) )
@@ -687,7 +712,7 @@ mod tests {
687
712
and_rebase : true ,
688
713
..DEFAULT_CONFIG
689
714
} ;
690
- repo_utils :: run_in_repo ( & ctx , || run_with_repo ( & logger, & config, & ctx. repo ) ) . unwrap ( ) ;
715
+ run_with_repo ( & logger, & config, & ctx. repo ) . unwrap ( ) ;
691
716
692
717
let mut revwalk = ctx. repo . revwalk ( ) . unwrap ( ) ;
693
718
revwalk. push_head ( ) . unwrap ( ) ;
@@ -709,7 +734,7 @@ mod tests {
709
734
rebase_options : & vec ! [ "--signoff" ] ,
710
735
..DEFAULT_CONFIG
711
736
} ;
712
- repo_utils :: run_in_repo ( & ctx , || run_with_repo ( & logger, & config, & ctx. repo ) ) . unwrap ( ) ;
737
+ run_with_repo ( & logger, & config, & ctx. repo ) . unwrap ( ) ;
713
738
714
739
let mut revwalk = ctx. repo . revwalk ( ) . unwrap ( ) ;
715
740
revwalk. push_head ( ) . unwrap ( ) ;
@@ -761,6 +786,66 @@ mod tests {
761
786
assert ! ( is_something_in_index) ;
762
787
}
763
788
789
+ #[ test]
790
+ fn dry_run_flag ( ) {
791
+ let ctx = repo_utils:: prepare_and_stage ( ) ;
792
+
793
+ // run 'git-absorb'
794
+ let drain = slog:: Discard ;
795
+ let logger = slog:: Logger :: root ( drain, o ! ( ) ) ;
796
+ let config = Config {
797
+ dry_run : true ,
798
+ ..DEFAULT_CONFIG
799
+ } ;
800
+ run_with_repo ( & logger, & config, & ctx. repo ) . unwrap ( ) ;
801
+
802
+ let mut revwalk = ctx. repo . revwalk ( ) . unwrap ( ) ;
803
+ revwalk. push_head ( ) . unwrap ( ) ;
804
+ assert_eq ! ( revwalk. count( ) , 1 ) ;
805
+ let is_something_in_index = !nothing_left_in_index ( & ctx. repo ) . unwrap ( ) ;
806
+ assert ! ( is_something_in_index) ;
807
+ }
808
+
809
+ #[ test]
810
+ fn dry_run_flag_with_and_rebase_flag ( ) {
811
+ let ( ctx, path) = repo_utils:: prepare_repo ( ) ;
812
+ repo_utils:: set_config_option ( & ctx. repo , "core.editor" , "true" ) ;
813
+
814
+ // create a fixup commit that 'git rebase' will act on if called
815
+ let tree = repo_utils:: stage_file_changes ( & ctx, & path) ;
816
+ let signature = ctx. repo . signature ( ) . unwrap ( ) ;
817
+ let head_commit = ctx. repo . head ( ) . unwrap ( ) . peel_to_commit ( ) . unwrap ( ) ;
818
+ ctx. repo
819
+ . commit (
820
+ Some ( "HEAD" ) ,
821
+ & signature,
822
+ & signature,
823
+ & format ! ( "fixup! {}\n " , head_commit. id( ) ) ,
824
+ & tree,
825
+ & [ & head_commit] ,
826
+ )
827
+ . unwrap ( ) ;
828
+
829
+ // stage one more change so 'git-absorb' won't exit early
830
+ repo_utils:: stage_file_changes ( & ctx, & path) ;
831
+
832
+ // run 'git-absorb'
833
+ let drain = slog:: Discard ;
834
+ let logger = slog:: Logger :: root ( drain, o ! ( ) ) ;
835
+ let config = Config {
836
+ and_rebase : true ,
837
+ dry_run : true ,
838
+ ..DEFAULT_CONFIG
839
+ } ;
840
+ run_with_repo ( & logger, & config, & ctx. repo ) . unwrap ( ) ;
841
+
842
+ let mut revwalk = ctx. repo . revwalk ( ) . unwrap ( ) ;
843
+ revwalk. push_head ( ) . unwrap ( ) ;
844
+ assert_eq ! ( revwalk. count( ) , 2 ) ; // git rebase wasn't called so both commits persist
845
+ let is_something_in_index = !nothing_left_in_index ( & ctx. repo ) . unwrap ( ) ;
846
+ assert ! ( is_something_in_index) ;
847
+ }
848
+
764
849
fn autostage_common ( ctx : & repo_utils:: Context , file_path : & PathBuf ) -> ( PathBuf , PathBuf ) {
765
850
// 1 modification w/o staging
766
851
let path = ctx. join ( & file_path) ;
0 commit comments