use std::env::current_dir;
use clap::{Args, Subcommand};
use printable_shell_command::PrintableShellCommand;
use crate::common::{
inference::get_stdout,
vcs::{auto_detect_preferred_vcs_and_repo_root, VcsKind},
};
#[derive(Args, Debug)]
pub(crate) struct VcsArgs {
#[command(subcommand)]
command: VcsCommand,
}
#[derive(Debug, Subcommand)]
enum VcsCommand {
Kind,
Root,
LatestCommit(LatestCommitArgs),
}
#[derive(Args, Debug)]
pub(crate) struct LatestCommitArgs {
#[command(subcommand)]
command: LatestCommitSubcommand,
}
#[derive(Debug, Subcommand)]
enum LatestCommitSubcommand {
Hash,
}
fn jj_get_latest_commmit_hash() -> Result<String, String> {
let mut jj_command = PrintableShellCommand::new("jj");
jj_command.args([
"--no-graph",
"--ignore-working-copy",
"--color=never",
"--limit=1",
]);
jj_command.args([
"--revisions",
"::@ & ((~description(exact:\"\") & ~empty()) | merges())",
]);
jj_command.args(["--template", "commit_id"]);
if let Some(hash) = get_stdout(jj_command) {
return Ok(hash.trim().to_owned());
}
Err("Could not get latest hash from `jj`.".to_owned())
}
fn git_get_latest_commmit_hash() -> Result<String, String> {
let mut git_command = PrintableShellCommand::new("git");
git_command.args(["rev-parse", "HEAD"]);
if let Some(hash) = get_stdout(git_command) {
return Ok(hash.trim().to_owned());
}
Err("Could not get latest hash from `git`.".to_owned())
}
pub(crate) fn vcs_command(vcs_args: VcsArgs) -> Result<(), String> {
match vcs_args.command {
VcsCommand::Kind => {
match auto_detect_preferred_vcs_and_repo_root(¤t_dir().unwrap()) {
Some((vcs, _)) => print!("{}", vcs),
None => return Err("Could not detect a VCS repo.".to_owned()),
}
}
VcsCommand::Root => {
match auto_detect_preferred_vcs_and_repo_root(¤t_dir().unwrap()) {
Some((_, path)) => print!("{}", path),
None => return Err("Could not detect a VCS repo.".to_owned()),
}
}
VcsCommand::LatestCommit(latest_commit_args) => {
match latest_commit_args.command {
LatestCommitSubcommand::Hash => {
match auto_detect_preferred_vcs_and_repo_root(¤t_dir().unwrap()) {
Some((VcsKind::Jj, _)) => print!("{}", jj_get_latest_commmit_hash()?),
Some((VcsKind::Git, _)) => print!("{}", git_get_latest_commmit_hash()?),
Some((VcsKind::Mercurial, _)) => {
return Err("Mercurial is unsupported for this operation.".into());
}
None => return Err("Could not detect a VCS repo.".to_owned()),
}
}
}
}
};
Ok(())
}