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:
parent
1804a7fd93
commit
e1de6d6b79
1 changed files with 41 additions and 13 deletions
54
src/git.rs
54
src/git.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use git2::build::CheckoutBuilder;
|
use git2::build::CheckoutBuilder;
|
||||||
use git2::{Branch, BranchType, ObjectType, Repository, RepositoryState};
|
use git2::{Branch, BranchType, Repository, RepositoryState};
|
||||||
use miette::{Context, IntoDiagnostic};
|
use miette::{Context, IntoDiagnostic};
|
||||||
use std::fs::read_dir;
|
use std::fs::read_dir;
|
||||||
use std::path::{Path, PathBuf};
|
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()))?;
|
.wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?;
|
||||||
if let Some(branch) = get_branch(&repo, name)? {
|
if let Some(branch) = get_branch(&repo, name)? {
|
||||||
if !branch.is_head() {
|
if !branch.is_head() {
|
||||||
|
let is_remote = branch.get().is_remote();
|
||||||
|
|
||||||
print!("{}", app_dir.file_name().unwrap().to_string_lossy());
|
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);
|
println!(": {:#} ❌", e);
|
||||||
} else {
|
} else {
|
||||||
println!(" ✓");
|
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>>> {
|
fn get_branch<'repo>(repo: &'repo Repository, name: &str) -> Result<Option<Branch<'repo>>> {
|
||||||
let branches = repo.branches(Some(BranchType::Local)).into_diagnostic()?;
|
let local_branches = repo.branches(Some(BranchType::Local)).into_diagnostic()?;
|
||||||
Ok(branches.flatten().find_map(|(branch, _)| {
|
if let Some(local_branch) = local_branches.flatten().find_map(|(branch, _)| {
|
||||||
match (branch.name_bytes(), name) {
|
match (branch.name(), name) {
|
||||||
(Ok(b"main"), "master") => Some(branch), // make "main" synonymous with "master"
|
(Ok(Some("main")), "master") => Some(branch), // make "main" synonymous with "master"
|
||||||
(branch_name, _) if branch_name == Ok(name.as_bytes()) => Some(branch),
|
(Ok(Some(branch_name)), _) if branch_name == name => Some(branch),
|
||||||
_ => None,
|
_ => 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<()> {
|
fn checkout(repo: &Repository, branch: &Branch, target_name: Option<&str>) -> Result<()> {
|
||||||
let commit = branch.get().peel(ObjectType::Commit).into_diagnostic()?;
|
let commit = branch.get().peel_to_commit().into_diagnostic()?;
|
||||||
let name = branch
|
let mut name = branch
|
||||||
.name()
|
.name()
|
||||||
.into_diagnostic()?
|
.into_diagnostic()?
|
||||||
.expect("we already know the name if utf8");
|
.expect("we already know the name if utf8");
|
||||||
let mut checkout = CheckoutBuilder::default();
|
let mut checkout = CheckoutBuilder::default();
|
||||||
checkout.update_index(true);
|
checkout.update_index(true);
|
||||||
|
|
||||||
repo.checkout_tree(&commit, Some(&mut checkout))
|
repo.checkout_tree(commit.as_object(), Some(&mut checkout))
|
||||||
.into_diagnostic()
|
.into_diagnostic()
|
||||||
.wrap_err("Failed to checkout tree")?;
|
.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}"))
|
repo.set_head(&format!("refs/heads/{name}"))
|
||||||
.into_diagnostic()
|
.into_diagnostic()
|
||||||
.wrap_err("Failed to set HEAD")
|
.wrap_err("Failed to set HEAD")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue