Skip to content

Commit

Permalink
autostage: enable behavior only if enabled via config
Browse files Browse the repository at this point in the history
  • Loading branch information
kiprasmel committed Feb 23, 2024
1 parent f7db265 commit 9be0498
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 17 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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,
}
}
70 changes: 53 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ fn run_with_repo(config: &Config, repo: &git2::Repository) -> Result<()> {
return Ok(());
}

let autostage_enabled: bool = 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,
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -601,20 +602,33 @@ lines
assert!(nothing_left_in_index(&ctx.repo).unwrap());
}

#[test]
fn auto_add_everything_to_index_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 auto_add_everything_to_index_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!());
Expand All @@ -637,18 +651,40 @@ lines
}

#[test]
fn do_not_add_anything_extra_if_index_was_not_empty() {
fn do_not_auto_add_anything_to_index_if_not_enabled_by_config_var() {
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();
assert_eq!(config::auto_stage_if_nothing_staged(&ctx.repo), false);

// 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();
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_eq!(index_stats(&ctx.repo).unwrap().files_changed(), 0);
}

#[test]
fn do_not_add_anything_extra_if_index_was_not_empty() {
let (ctx, file_path) = prepare_repo();

let (_, fp2) = autostage_common(&ctx, &file_path);
// we stage the extra file - should stay in index
add(&ctx.repo, &fp2);

// run 'git-absorb'
Expand Down

0 comments on commit 9be0498

Please sign in to comment.