diff options
author | Kipras Melnikovas <kipras@kipras.org> | 2024-02-23 06:30:14 +0200 |
---|---|---|
committer | Kipras Melnikovas <kipras@kipras.org> | 2024-02-23 07:56:11 +0200 |
commit | 1f361115e1c3d0a354209b52f3c973e615b496ea (patch) | |
tree | 104a5b2c888701c11ddc9c6cfda7558241f95913 | |
parent | e063fa885a1e7569b7d22f433be45551d24ea3b3 (diff) |
autostage: enable behavior only if enabled via config
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | src/config.rs | 13 | ||||
-rw-r--r-- | src/lib.rs | 80 |
3 files changed, 88 insertions, 16 deletions
@@ -104,6 +104,17 @@ To always have this behavior, set oneFixupPerCommit = true ``` +### Auto-stage all changes if nothing staged + +By default, git-absorb will only consider files that you've staged to the index via `git add`. However, sometimes one wants to try and absorb from all changes, which would require to stage them first via `git add .`. To avoid this extra step, set + +```ini +[absorb] + autoStageIfNothingStaged = true +``` + +which tells git-absorb, when no changes are staged, to auto-stage them all, create fixup commits where possible, and unstage remaining changes from the index. + ## TODO - implement force flag diff --git a/src/config.rs b/src/config.rs index 84cd601..bc212f0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,6 +4,9 @@ pub const MAX_STACK: usize = 10; pub const ONE_FIXUP_PER_COMMIT_CONFIG_NAME: &str = "absorb.oneFixupPerCommit"; pub const ONE_FIXUP_PER_COMMIT_DEFAULT: bool = false; +pub const AUTO_STAGE_IF_NOTHING_STAGED_CONFIG_NAME: &str = "absorb.autoStageIfNothingStaged"; +pub const AUTO_STAGE_IF_NOTHING_STAGED_DEFAULT: bool = false; + pub fn max_stack(repo: &git2::Repository) -> usize { match repo .config() @@ -23,3 +26,13 @@ pub fn one_fixup_per_commit(repo: &git2::Repository) -> bool { _ => ONE_FIXUP_PER_COMMIT_DEFAULT, } } + +pub fn auto_stage_if_nothing_staged(repo: &git2::Repository) -> bool { + match repo + .config() + .and_then(|config| config.get_bool(AUTO_STAGE_IF_NOTHING_STAGED_CONFIG_NAME)) + { + Ok(val) => val, + _ => AUTO_STAGE_IF_NOTHING_STAGED_DEFAULT, + } +} @@ -45,8 +45,9 @@ fn run_with_repo(config: &Config, repo: &git2::Repository) -> Result<()> { return Ok(()); } + let autostage_enabled = config::auto_stage_if_nothing_staged(repo); let mut we_added_everything_to_index = false; - if nothing_left_in_index(repo)? { + if autostage_enabled && nothing_left_in_index(repo)? { we_added_everything_to_index = true; // no matter from what subdirectory we're executing, @@ -333,7 +334,7 @@ fn run_with_repo(config: &Config, repo: &git2::Repository) -> Result<()> { } } - if we_added_everything_to_index { + if autostage_enabled && we_added_everything_to_index { // now that the fixup commits have been created, // we should unstage the remaining changes from the index. @@ -601,20 +602,33 @@ lines assert!(nothing_left_in_index(&ctx.repo).unwrap()); } - #[test] - fn autostage_if_index_was_empty() { - let (ctx, file_path) = prepare_repo(); - - // 1 modification w/o staging - should get fixup commit created + fn autostage_common(ctx: &Context, file_path: &PathBuf) -> (PathBuf, PathBuf) { + // 1 modification w/o staging let path = ctx.join(&file_path); let contents = std::fs::read_to_string(&path).unwrap(); let modifications = format!("{contents}\nnew_line2"); std::fs::write(&path, &modifications).unwrap(); - // 1 extra file that should get staged & later removed from the index + // 1 extra file let fp2 = PathBuf::from("unrel.txt"); std::fs::write(ctx.join(&fp2), "foo").unwrap(); + (path, fp2) + } + + #[test] + fn autostage_if_index_was_empty() { + let (ctx, file_path) = prepare_repo(); + + // requires enabled config var + ctx.repo + .config() + .unwrap() + .set_bool(config::AUTO_STAGE_IF_NOTHING_STAGED_CONFIG_NAME, true) + .unwrap(); + + autostage_common(&ctx, &file_path); + // run 'git-absorb' let drain = slog::Discard; let logger = slog::Logger::root(drain, o!()); @@ -640,15 +654,15 @@ lines fn do_not_autostage_if_index_was_not_empty() { let (ctx, file_path) = prepare_repo(); - // 1 modification w/o staging - should not get staged nor fixed up - let path = ctx.join(&file_path); - let contents = std::fs::read_to_string(&path).unwrap(); - let modifications = format!("{contents}\nnew_line2"); - std::fs::write(&path, &modifications).unwrap(); + // enable config var + ctx.repo + .config() + .unwrap() + .set_bool(config::AUTO_STAGE_IF_NOTHING_STAGED_CONFIG_NAME, true) + .unwrap(); - // 1 extra file that we'll stage - should stay in index - let fp2 = PathBuf::from("unrel.txt"); - std::fs::write(ctx.join(&fp2), "foo").unwrap(); + let (_, fp2) = autostage_common(&ctx, &file_path); + // we stage the extra file - should stay in index add(&ctx.repo, &fp2); // run 'git-absorb' @@ -671,4 +685,38 @@ lines assert_eq!(index_stats(&ctx.repo).unwrap().files_changed(), 1); } + + #[test] + fn do_not_autostage_if_not_enabled_by_config_var() { + let (ctx, file_path) = prepare_repo(); + + // disable config var + ctx.repo + .config() + .unwrap() + .set_bool(config::AUTO_STAGE_IF_NOTHING_STAGED_CONFIG_NAME, false) + .unwrap(); + + autostage_common(&ctx, &file_path); + + // run 'git-absorb' + let drain = slog::Discard; + let logger = slog::Logger::root(drain, o!()); + let config = Config { + dry_run: false, + force: false, + base: None, + and_rebase: false, + whole_file: false, + one_fixup_per_commit: false, + logger: &logger, + }; + run_with_repo(&config, &ctx.repo).unwrap(); + + let mut revwalk = ctx.repo.revwalk().unwrap(); + revwalk.push_head().unwrap(); + assert_eq!(revwalk.count(), 1); + + assert!(nothing_left_in_index(&ctx.repo).unwrap()); + } } |