use async_trait::async_trait;
use clap::{Arg, Command, arg};
use liboxen::model::LocalRepository;
use liboxen::repositories;
use crate::helpers::check_repo_migration_needed;
use crate::cmd::RunCmd;
pub const NAME: &str = "merge";
pub struct MergeCmd;
#[async_trait]
impl RunCmd for MergeCmd {
fn name(&self) -> &str {
NAME
}
fn args(&self) -> Command {
Command::new(NAME)
.about("Merges a branch into the current checked out branch.")
.arg(
arg!([BRANCH] "The name of the branch you want to merge in.")
.required_unless_present("abort"),
)
.arg(
Arg::new("abort")
.long("abort")
.help("Abandon an interrupted or in-conflict merge and restore HEAD.")
.action(clap::ArgAction::SetTrue)
.conflicts_with("BRANCH"),
)
}
async fn run(&self, args: &clap::ArgMatches) -> Result<(), anyhow::Error> {
let repository = LocalRepository::from_current_dir()?;
if repository.is_remote_mode() {
return Err(anyhow::anyhow!(
"Error: Command 'oxen merge' not implemented for remote mode repositories",
));
}
check_repo_migration_needed(&repository)?;
if args.get_flag("abort") {
repositories::merge::abort_merge(&repository).await?;
return Ok(());
}
let branch = args.get_one::<String>("BRANCH").expect("required");
let current = if let Some(current) = repositories::branches::current_branch(&repository)? {
current
} else {
return Err(anyhow::anyhow!(
"Error: Cannot use 'oxen merge' in an empty repository",
));
};
if current.name == *branch {
return Err(anyhow::anyhow!("Error: Cannot merge into current branch",));
}
repositories::merge::merge(&repository, branch).await?;
Ok(())
}
}