Skip to content

Commit 7249291

Browse files
committedAug 26, 2024
feat: gix merge-base for the CLI
For now it only supports the standard merge-base, but more derivatives can be added easily on demand.
1 parent 3abf043 commit 7249291

File tree

5 files changed

+61
-6
lines changed

5 files changed

+61
-6
lines changed
 
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use crate::OutputFormat;
2+
use anyhow::bail;
3+
4+
pub fn merge_base(
5+
mut repo: gix::Repository,
6+
first: String,
7+
others: Vec<String>,
8+
mut out: impl std::io::Write,
9+
format: OutputFormat,
10+
) -> anyhow::Result<()> {
11+
if format != OutputFormat::Human {
12+
bail!("Only 'human' format is currently supported");
13+
}
14+
repo.object_cache_size_if_unset(50 * 1024 * 1024);
15+
let first_id = repo.rev_parse_single(first.as_str())?;
16+
let other_ids: Vec<_> = others
17+
.iter()
18+
.cloned()
19+
.map(|other| repo.rev_parse_single(other.as_str()).map(gix::Id::detach))
20+
.collect::<Result<_, _>>()?;
21+
22+
let cache = repo.commit_graph_if_enabled()?;
23+
let bases = repo.merge_bases_many_with_cache(first_id, &other_ids, cache.as_ref())?;
24+
if bases.is_empty() {
25+
bail!("No base found for {first} and {others}", others = others.join(", "))
26+
}
27+
for id in bases {
28+
writeln!(&mut out, "{id}")?;
29+
}
30+
Ok(())
31+
}

‎gitoxide-core/src/repository/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ mod fsck;
4444
pub use fsck::function as fsck;
4545
pub mod index;
4646
pub mod mailmap;
47+
mod merge_base;
48+
pub use merge_base::merge_base;
4749
pub mod odb;
4850
pub mod remote;
4951
pub mod revision;

‎gix/src/repository/revision.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,10 @@ impl crate::Repository {
5252
let two = two.into();
5353
let cache = self.commit_graph_if_enabled()?;
5454
let mut graph = self.revision_graph(cache.as_ref());
55-
let bases =
56-
gix_revision::merge_base(one, &vec![two], &mut graph)?.ok_or(super::merge_base::Error::NotFound {
57-
first: one,
58-
second: two,
59-
})?;
55+
let bases = gix_revision::merge_base(one, &[two], &mut graph)?.ok_or(super::merge_base::Error::NotFound {
56+
first: one,
57+
second: two,
58+
})?;
6059
Ok(bases[0].attach(self))
6160
}
6261

@@ -76,7 +75,7 @@ impl crate::Repository {
7675
let one = one.into();
7776
let two = two.into();
7877
let mut graph = self.revision_graph(cache);
79-
let bases = gix_revision::merge_base(one, &vec![two], &mut graph)?.ok_or(
78+
let bases = gix_revision::merge_base(one, &[two], &mut graph)?.ok_or(
8079
super::merge_base_with_cache::Error::NotFound {
8180
first: one,
8281
second: two,

‎src/plumbing/main.rs

+11
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ pub fn main() -> Result<()> {
141141
}
142142

143143
match cmd {
144+
Subcommands::MergeBase(crate::plumbing::options::merge_base::Command { first, others }) => prepare_and_run(
145+
"merge-base",
146+
trace,
147+
verbose,
148+
progress,
149+
progress_keep_open,
150+
None,
151+
move |_progress, out, _err| {
152+
core::repository::merge_base(repository(Mode::Lenient)?, first, others, out, format)
153+
},
154+
),
144155
Subcommands::Worktree(crate::plumbing::options::worktree::Platform { cmd }) => match cmd {
145156
crate::plumbing::options::worktree::SubCommands::List => prepare_and_run(
146157
"worktree-list",

‎src/plumbing/options/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub enum Subcommands {
138138
Config(config::Platform),
139139
#[cfg(feature = "gitoxide-core-tools-corpus")]
140140
Corpus(corpus::Platform),
141+
MergeBase(merge_base::Command),
141142
Worktree(worktree::Platform),
142143
/// Subcommands that need no git repository to run.
143144
#[clap(subcommand)]
@@ -268,6 +269,17 @@ pub mod status {
268269
}
269270
}
270271

272+
pub mod merge_base {
273+
#[derive(Debug, clap::Parser)]
274+
#[command(about = "A command for calculating all merge-bases")]
275+
pub struct Command {
276+
/// A revspec for the first commit.
277+
pub first: String,
278+
/// Revspecs for the other commits to compute the merge-base with.
279+
pub others: Vec<String>,
280+
}
281+
}
282+
271283
pub mod worktree {
272284
#[derive(Debug, clap::Parser)]
273285
#[command(about = "Commands for handling worktrees")]

0 commit comments

Comments
 (0)
Please sign in to comment.