git-api 0.1.1

git2-rs based utility library
Documentation
use git2::{build::CheckoutBuilder, Error, Repository};
use macro_log::*;

/// (强制)切换到远程分支(switch -f)
///
/// 不会创建本地分支,HEAD将是分离的
///
/// 缺点:
/// - 分离状态下`repo.head().name()`的值是"HEAD",查询不到分支名
/// - 两个commit相同的远程分支之间无法切换
pub fn repo_switch(
    repo: &Repository,
    remote_name: &str,
    branch_name: &str,
    force_checkout: bool,
) -> Result<(), Error> {
    // 分离HEAD
    repo.set_head(&format!("refs/remotes/{remote_name}/{branch_name}"))?;
    // 强制checkout
    let mut opts = CheckoutBuilder::new();
    if force_checkout {
        opts.force();
    }
    repo.checkout_head(Some(&mut opts))?;
    Ok(())
}

/// (强制)检出远程分支(checkout -f)
///
/// 将创建本地分支,如果已存在,则先删除再更新
pub fn repo_checkout(
    repo: &Repository,
    remote_name: &str,
    branch_name: &str,
    force_checkout: bool,
) -> Result<(), Error> {
    let obj = repo.revparse_single(&format!("refs/remotes/{remote_name}/{branch_name}"))?;
    let Some(commit) = obj.as_commit() else {
        return Err(Error::from_str("Failed revparse_single commit"));
    };

    // 分离HEAD
    repo.set_head(&format!("refs/remotes/{remote_name}/{branch_name}"))?;
    // 删除本地已有的同名分支
    if let Ok(mut branch) = repo.find_branch(branch_name, git2::BranchType::Local) {
        w!("分支 {branch_name} 已存在,更新");
        branch.delete()?;
    }
    // 创建分支
    let _branch = repo.branch(branch_name, commit, false)?;
    // 切换分支
    repo.set_head(&format!("refs/heads/{branch_name}"))?;

    // 强制checkout
    let mut opts = CheckoutBuilder::new();
    if force_checkout {
        opts.force();
    }
    repo.checkout_head(Some(&mut opts))?;

    Ok(())
}