1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 17:14:08 +02:00

git checkout remote branches

This commit is contained in:
Robin Appelman 2025-11-21 21:01:57 +01:00
commit e1de6d6b79

View file

@ -1,6 +1,6 @@
use crate::Result;
use git2::build::CheckoutBuilder;
use git2::{Branch, BranchType, ObjectType, Repository, RepositoryState};
use git2::{Branch, BranchType, Repository, RepositoryState};
use miette::{Context, IntoDiagnostic};
use std::fs::read_dir;
use std::path::{Path, PathBuf};
@ -39,8 +39,10 @@ pub fn checkout_all<P: AsRef<Path>>(sources_root: P, mut name: &str) -> Result<(
.wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?;
if let Some(branch) = get_branch(&repo, name)? {
if !branch.is_head() {
let is_remote = branch.get().is_remote();
print!("{}", app_dir.file_name().unwrap().to_string_lossy());
if let Err(e) = checkout(&repo, branch) {
if let Err(e) = checkout(&repo, &branch, is_remote.then_some(name)) {
println!(": {:#}", e);
} else {
println!("");
@ -106,29 +108,55 @@ pub fn pull_all<P: AsRef<Path>>(sources_root: P) -> Result<()> {
}
fn get_branch<'repo>(repo: &'repo Repository, name: &str) -> Result<Option<Branch<'repo>>> {
let branches = repo.branches(Some(BranchType::Local)).into_diagnostic()?;
Ok(branches.flatten().find_map(|(branch, _)| {
match (branch.name_bytes(), name) {
(Ok(b"main"), "master") => Some(branch), // make "main" synonymous with "master"
(branch_name, _) if branch_name == Ok(name.as_bytes()) => Some(branch),
let local_branches = repo.branches(Some(BranchType::Local)).into_diagnostic()?;
if let Some(local_branch) = local_branches.flatten().find_map(|(branch, _)| {
match (branch.name(), name) {
(Ok(Some("main")), "master") => Some(branch), // make "main" synonymous with "master"
(Ok(Some(branch_name)), _) if branch_name == name => Some(branch),
_ => None,
}
}))
}) {
return Ok(Some(local_branch));
};
let remote_branches = repo.branches(Some(BranchType::Remote)).into_diagnostic()?;
let remote_name = format!("origin/{name}");
Ok(remote_branches
.flatten()
.find_map(|(branch, _)| match branch.name() {
Ok(Some(branch_name)) if branch_name == remote_name => Some(branch),
_ => None,
}))
}
fn checkout(repo: &Repository, branch: Branch) -> Result<()> {
let commit = branch.get().peel(ObjectType::Commit).into_diagnostic()?;
let name = branch
fn checkout(repo: &Repository, branch: &Branch, target_name: Option<&str>) -> Result<()> {
let commit = branch.get().peel_to_commit().into_diagnostic()?;
let mut name = branch
.name()
.into_diagnostic()?
.expect("we already know the name if utf8");
let mut checkout = CheckoutBuilder::default();
checkout.update_index(true);
repo.checkout_tree(&commit, Some(&mut checkout))
repo.checkout_tree(commit.as_object(), Some(&mut checkout))
.into_diagnostic()
.wrap_err("Failed to checkout tree")?;
if let Some(target_name) = target_name {
let mut new_branch = repo
.branch(target_name, &commit, false)
.into_diagnostic()
.wrap_err("Failed to create local branch")?;
new_branch
.set_upstream(Some(name))
.into_diagnostic()
.wrap_err("Failed to set local branch upstream")?;
name = target_name;
}
repo.set_head(&format!("refs/heads/{name}"))
.into_diagnostic()
.wrap_err("Failed to set HEAD")
.wrap_err("Failed to set HEAD")?;
Ok(())
}