Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support arbitrary references as merge-base targets #38

Merged
merged 1 commit into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,50 @@
# Unreleased

- Support arbitrary refs (i.e. tags like `v0.1.0` and full refspecs
like `ref/pull/ID`) as the merge-base selector.

# Version 0.2.6

* Fix and improve the experience of working with a main-only workflow.
- Fix and improve the experience of working with a main-only workflow.
- Provide a tailored error message if your current branch is the selected upstream branch
- Work correctly with explicitly-defined remote upstream branches.

# Version 0.2.5

* Correctly find git repos in parent dirs of CWD
* Enable experimental github release attestations in cargo-dist
- Correctly find git repos in parent dirs of CWD
- Enable experimental github release attestations in cargo-dist

# Version 0.2.4

* Retarget multiple branches pointing at the same commit, eg:
- Retarget multiple branches pointing at the same commit, eg:
> updated branch my-cool-branch: deadbeef -> c0ffee

# Version 0.2.3

* Allow setting the diff theme
* Read configuration from git config as well as arguments and env vars
* Choose whether to display full diff or just a diffstat based on terminal
- Allow setting the diff theme
- Read configuration from git config as well as arguments and env vars
- Choose whether to display full diff or just a diffstat based on terminal
height instead of a constant
* Add -u alias for --default-upstream-branch
- Add -u alias for --default-upstream-branch

# Version 0.2.2

* Correctly retarget branches if the target of the edit is also a branch (#24)
* Check if main, master, develop, or trunk exist as reasonable default upstream branches
* Leave the repo in a less confusing state if the edit target is a conflict
- Correctly retarget branches if the target of the edit is also a branch (#24)
- Check if main, master, develop, or trunk exist as reasonable default upstream branches
- Leave the repo in a less confusing state if the edit target is a conflict

# Version 0.2.1

* Remove last dependency on external git binary, using libgit2 for all git interactions
* Show backtraces on error if RUST_BACKTRACE=1 is in the environment
* Correctly stash and unstash changes before the rebase
- Remove last dependency on external git binary, using libgit2 for all git interactions
- Show backtraces on error if RUST_BACKTRACE=1 is in the environment
- Correctly stash and unstash changes before the rebase

# Version 0.2.0

* Rename to git-instafix because there are a bunch of existing projects named git-fixup
- Rename to git-instafix because there are a bunch of existing projects named git-fixup

# Version 0.1.9

* CI and doc improvements
* Use libgit2 instead of shelling out for more things.
* Create binaries and install scripts with cargo-dist
- CI and doc improvements
- Use libgit2 instead of shelling out for more things.
- Create binaries and install scripts with cargo-dist
29 changes: 10 additions & 19 deletions src/selecter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ use std::collections::HashMap;
use anyhow::{anyhow, bail};
use console::style;
use dialoguer::Select;
use git2::BranchType;
use git2::Commit;
use git2::Oid;
use git2::{Branch, Repository};
use git2::{Branch, BranchType, Commit, Oid, Reference, Repository};

use crate::config;
use crate::format_ref;

pub(crate) struct CommitSelection<'a> {
pub commit: Commit<'a>,
pub branch: Branch<'a>,
pub reference: Reference<'a>,
}

pub(crate) fn select_commit_to_amend<'a>(
Expand All @@ -38,9 +35,9 @@ pub(crate) fn select_commit_to_amend<'a>(
let head = repo.head()?;
let current_branch_name = head
.shorthand()
.ok_or_else(|| anyhow!("HEAD is not a branch"))?;
.ok_or_else(|| anyhow!("HEAD's name is invalid utf-8"))?;
if repo.head()?.peel_to_commit()?.id() == upstream.commit.id()
&& current_branch_name == upstream.branch.name().unwrap().unwrap()
&& current_branch_name == upstream.reference.name().unwrap()
{
let upstream_setting = config::UPSTREAM_SETTING;
bail!(
Expand Down Expand Up @@ -132,24 +129,18 @@ pub(crate) fn get_merge_base<'a>(
upstream_name: Option<&str>,
) -> Result<Option<CommitSelection<'a>>, anyhow::Error> {
let (upstream, branch) = if let Some(explicit_upstream_name) = upstream_name {
let mut bt = BranchType::Local;
let branch = repo
.find_branch(explicit_upstream_name, BranchType::Local)
.or_else(|_| {
bt = BranchType::Remote;
repo.find_branch(explicit_upstream_name, BranchType::Remote)
})?;
let b2 = repo.find_branch(explicit_upstream_name, bt)?;
(branch.into_reference().peel_to_commit()?, b2)
let reference = repo.resolve_reference_from_short_name(explicit_upstream_name)?;
let r2 = repo.resolve_reference_from_short_name(explicit_upstream_name)?;
(reference.peel_to_commit()?, r2)
} else if let Some(branch) = find_default_upstream_branch(repo) {
(
branch.into_reference().peel_to_commit()?,
find_default_upstream_branch(repo).unwrap(),
find_default_upstream_branch(repo).unwrap().into_reference(),
)
} else if let Ok(upstream) = head_branch.upstream() {
(
upstream.into_reference().peel_to_commit()?,
head_branch.upstream().unwrap(),
head_branch.upstream().unwrap().into_reference(),
)
} else {
return Ok(None);
Expand All @@ -166,7 +157,7 @@ pub(crate) fn get_merge_base<'a>(

Ok(Some(CommitSelection {
commit: commit.peel_to_commit()?,
branch,
reference: branch,
}))
}

Expand Down
123 changes: 122 additions & 1 deletion tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,127 @@ new
);
}

#[test]
fn simple_straightline_tag_and_reference() {
let td = assert_fs::TempDir::new().unwrap();
git_init(&td);

let base = "v0.1.0";

git_commits(&["a", "b"], &td);
git(&["tag", base], &td);
git(&["checkout", "-b", "changes"], &td);
git_commits(&["target", "d"], &td);

let log = git_log(&td);
assert_eq!(
log,
"\
* d HEAD -> changes
* target
* b tag: v0.1.0, main
* a
",
"log:\n{}",
log
);

td.child("new").touch().unwrap();
git(&["add", "new"], &td);

fixup(&td)
.args(["-P", "target", "-u", base])
.assert()
.success();

let (files, err) = git_changed_files("target", &td);

assert_eq!(
files,
"\
file_target
new
",
"out: {} err: {}",
files,
err
);

// also check that we can use the full refspec definition

td.child("new-full-ref").touch().unwrap();
git(&["add", "new-full-ref"], &td);
fixup(&td)
.args(["-P", "target", "-u", &format!("refs/tags/{base}")])
.unwrap();

let (files, err) = git_changed_files("target", &td);
assert_eq!(
files,
"\
file_target
new
new-full-ref
",
"out: {} err: {}",
files,
err
);
}

#[test]
fn simple_straightline_remote_branch() {
let remote_td = assert_fs::TempDir::new().unwrap();
git_init(&remote_td);
git_commits(&["a", "b"], &remote_td);

let td = assert_fs::TempDir::new().unwrap();
git_init(&td);
let remote_path = &remote_td
.path()
.as_os_str()
.to_owned()
.into_string()
.unwrap();
git(&["remote", "add", "origin", remote_path], &td);
git(&["pull", "origin", "main:main"], &td);
git_commits(&["target", "d"], &td);

let log = git_log(&td);
assert_eq!(
log,
"\
* d HEAD -> main
* target
* b origin/main
* a
",
"log:\n{}",
log
);

td.child("new").touch().unwrap();
git(&["add", "new"], &td);

fixup(&td)
.args(["-P", "target", "-u", "origin/main"])
.assert()
.success();

let (files, err) = git_changed_files("target", &td);

assert_eq!(
files,
"\
file_target
new
",
"out: {} err: {}",
files,
err
);
}

#[test]
fn stashes_before_rebase() {
let td = assert_fs::TempDir::new().unwrap();
Expand Down Expand Up @@ -389,7 +510,7 @@ fn git_init_default_branch_name(name: &str, tempdir: &assert_fs::TempDir) {
fn git_file_commit(name: &str, tempdir: &assert_fs::TempDir) {
tempdir.child(format!("file_{}", name)).touch().unwrap();
git(&["add", "-A"], tempdir);
git(&["commit", "-m", &name], tempdir);
git(&["commit", "-m", name], tempdir);
}

/// Get the git shown output for the target commit
Expand Down