Skip to content

Commit

Permalink
feat: gix merge-base for the CLI
Browse files Browse the repository at this point in the history
For now it only supports the standard merge-base, but more derivatives
can be added easily on demand.
  • Loading branch information
Byron committed Aug 26, 2024
1 parent 3abf043 commit 7249291
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 6 deletions.
31 changes: 31 additions & 0 deletions gitoxide-core/src/repository/merge_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::OutputFormat;
use anyhow::bail;

pub fn merge_base(
mut repo: gix::Repository,
first: String,
others: Vec<String>,
mut out: impl std::io::Write,
format: OutputFormat,
) -> anyhow::Result<()> {
if format != OutputFormat::Human {
bail!("Only 'human' format is currently supported");
}
repo.object_cache_size_if_unset(50 * 1024 * 1024);
let first_id = repo.rev_parse_single(first.as_str())?;
let other_ids: Vec<_> = others
.iter()
.cloned()
.map(|other| repo.rev_parse_single(other.as_str()).map(gix::Id::detach))
.collect::<Result<_, _>>()?;

let cache = repo.commit_graph_if_enabled()?;
let bases = repo.merge_bases_many_with_cache(first_id, &other_ids, cache.as_ref())?;
if bases.is_empty() {
bail!("No base found for {first} and {others}", others = others.join(", "))
}
for id in bases {
writeln!(&mut out, "{id}")?;
}
Ok(())
}
2 changes: 2 additions & 0 deletions gitoxide-core/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ mod fsck;
pub use fsck::function as fsck;
pub mod index;
pub mod mailmap;
mod merge_base;
pub use merge_base::merge_base;
pub mod odb;
pub mod remote;
pub mod revision;
Expand Down
11 changes: 5 additions & 6 deletions gix/src/repository/revision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,10 @@ impl crate::Repository {
let two = two.into();
let cache = self.commit_graph_if_enabled()?;
let mut graph = self.revision_graph(cache.as_ref());
let bases =
gix_revision::merge_base(one, &vec![two], &mut graph)?.ok_or(super::merge_base::Error::NotFound {
first: one,
second: two,
})?;
let bases = gix_revision::merge_base(one, &[two], &mut graph)?.ok_or(super::merge_base::Error::NotFound {
first: one,
second: two,
})?;
Ok(bases[0].attach(self))
}

Expand All @@ -76,7 +75,7 @@ impl crate::Repository {
let one = one.into();
let two = two.into();
let mut graph = self.revision_graph(cache);
let bases = gix_revision::merge_base(one, &vec![two], &mut graph)?.ok_or(
let bases = gix_revision::merge_base(one, &[two], &mut graph)?.ok_or(
super::merge_base_with_cache::Error::NotFound {
first: one,
second: two,
Expand Down
11 changes: 11 additions & 0 deletions src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ pub fn main() -> Result<()> {
}

match cmd {
Subcommands::MergeBase(crate::plumbing::options::merge_base::Command { first, others }) => prepare_and_run(
"merge-base",
trace,
verbose,
progress,
progress_keep_open,
None,
move |_progress, out, _err| {
core::repository::merge_base(repository(Mode::Lenient)?, first, others, out, format)
},
),
Subcommands::Worktree(crate::plumbing::options::worktree::Platform { cmd }) => match cmd {
crate::plumbing::options::worktree::SubCommands::List => prepare_and_run(
"worktree-list",
Expand Down
12 changes: 12 additions & 0 deletions src/plumbing/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub enum Subcommands {
Config(config::Platform),
#[cfg(feature = "gitoxide-core-tools-corpus")]
Corpus(corpus::Platform),
MergeBase(merge_base::Command),
Worktree(worktree::Platform),
/// Subcommands that need no git repository to run.
#[clap(subcommand)]
Expand Down Expand Up @@ -268,6 +269,17 @@ pub mod status {
}
}

pub mod merge_base {
#[derive(Debug, clap::Parser)]
#[command(about = "A command for calculating all merge-bases")]
pub struct Command {
/// A revspec for the first commit.
pub first: String,
/// Revspecs for the other commits to compute the merge-base with.
pub others: Vec<String>,
}
}

pub mod worktree {
#[derive(Debug, clap::Parser)]
#[command(about = "Commands for handling worktrees")]
Expand Down

0 comments on commit 7249291

Please sign in to comment.