use anyhow::{Result, bail};
use crate::core::graph;
use crate::core::repo::{self, Target};
use crate::git;
use crate::status;
pub fn run(target: Option<String>, git_args: Vec<String>) -> Result<()> {
let repo = repo::open_repo()?;
let revs = show_revs(&repo, target)?;
let workdir = repo::require_workdir(&repo, "show")?;
let mut args = vec!["show".to_string()];
args.extend(revs);
args.extend(git_args);
let refs: Vec<&str> = args.iter().map(String::as_str).collect();
git::run_git_interactive(workdir, &refs)
}
fn show_revs(repo: &git2::Repository, target: Option<String>) -> Result<Vec<String>> {
let Some(target) = target else {
if !repo::has_integration_context(repo) {
return Ok(vec!["HEAD".to_string()]);
}
return Ok(match status::top_commit(repo)? {
Some(oid) => vec![oid.to_string()],
None => vec!["HEAD".to_string()],
});
};
let resolved = repo::resolve_arg(
repo,
&target,
&[repo::TargetKind::Commit, repo::TargetKind::Branch],
)?;
match resolved {
Target::Commit(hash) => Ok(vec![hash]),
Target::Branch(name) => branch_revs(repo, &name),
_ => unreachable!(),
}
}
fn branch_revs(repo: &git2::Repository, branch: &str) -> Result<Vec<String>> {
if !repo::has_integration_context(repo) {
return Ok(vec![branch.to_string()]);
}
let mut info = repo::gather_commit_graph(repo)?;
let commits = if branch == info.branch_name {
status::apply_hidden_branches(repo, &mut info);
graph::loose_commits(&info)
} else if info.branches.iter().any(|b| b.name == branch) {
graph::commits_in_branch(&info, branch)
} else {
return Ok(vec![branch.to_string()]);
};
if commits.is_empty() {
bail!("Branch '{branch}' has no commits of its own");
}
Ok(commits.iter().map(|oid| oid.to_string()).collect())
}
#[cfg(test)]
#[path = "show_test.rs"]
mod tests;