mirror of
https://codeberg.org/icewind/haze.git
synced 2026-06-03 09:04:12 +02:00
improve git handling
This commit is contained in:
parent
481362921e
commit
4e070fdbd5
3 changed files with 102 additions and 72 deletions
62
Cargo.lock
generated
62
Cargo.lock
generated
|
|
@ -227,6 +227,9 @@ name = "cc"
|
|||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
|
@ -589,6 +592,19 @@ version = "0.27.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
|
||||
[[package]]
|
||||
name = "git2"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"libgit2-sys",
|
||||
"log",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.18"
|
||||
|
|
@ -629,6 +645,7 @@ dependencies = [
|
|||
"enum_dispatch",
|
||||
"flate2",
|
||||
"futures-util",
|
||||
"git2",
|
||||
"hyper",
|
||||
"hyper-reverse-proxy",
|
||||
"maplit",
|
||||
|
|
@ -896,6 +913,15 @@ version = "1.0.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
|
|
@ -917,6 +943,30 @@ version = "0.2.142"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.15.2+1.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.8"
|
||||
|
|
@ -1228,6 +1278,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
|
|
@ -2127,6 +2183,12 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ tracing-subscriber = "0.3.17"
|
|||
hyper-reverse-proxy = { version = "0.5.2-dev", git = "https://github.com/felipenoris/hyper-reverse-proxy" }
|
||||
hyper = "0.14.26"
|
||||
atty = "0.2.14"
|
||||
git2 = { version = "0.17.2", default-features = false }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
|
|
|||
103
src/git.rs
103
src/git.rs
|
|
@ -1,91 +1,58 @@
|
|||
use crate::Result;
|
||||
use miette::{miette, IntoDiagnostic};
|
||||
use git2::build::CheckoutBuilder;
|
||||
use git2::{Branch, BranchType, ObjectType, Repository};
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use std::fs::read_dir;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use tracing::error;
|
||||
|
||||
pub fn checkout_all<P: AsRef<Path>>(sources_root: P, branch: &str) -> Result<()> {
|
||||
pub fn checkout_all<P: AsRef<Path>>(sources_root: P, name: &str) -> Result<()> {
|
||||
let apps_dir = sources_root.as_ref().join("apps");
|
||||
for app in read_dir(apps_dir).into_diagnostic()? {
|
||||
let app = app.into_diagnostic()?;
|
||||
if app.metadata().into_diagnostic()?.is_dir() {
|
||||
if app.metadata().into_diagnostic()?.is_dir() && app.path().join(".git").is_dir() {
|
||||
let app_dir = app.path();
|
||||
if has_branch(&app_dir, branch).unwrap_or_default()
|
||||
&& get_branch(&app_dir).unwrap_or_default().trim() != branch
|
||||
{
|
||||
let repo = Repository::init(&app_dir)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?;
|
||||
if let Some(branch) = get_branch(&repo, name)? {
|
||||
if !branch.is_head() {
|
||||
print!("{}", app.file_name().to_string_lossy());
|
||||
if let Err(e) = checkout(&app_dir, branch) {
|
||||
println!(": {} ❌", e);
|
||||
if let Err(e) = checkout(&repo, branch) {
|
||||
println!(": {:#} ❌", e);
|
||||
} else {
|
||||
println!(" ✓");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn has_branch<P: AsRef<Path>>(repo: P, branch: &str) -> Result<bool> {
|
||||
let output = Command::new("git")
|
||||
.current_dir(repo)
|
||||
.arg("branch")
|
||||
.arg("-a")
|
||||
.output()
|
||||
.into_diagnostic()?;
|
||||
let stdout = String::from_utf8(output.stdout).into_diagnostic()?;
|
||||
let stderr = String::from_utf8(output.stderr).into_diagnostic()?;
|
||||
if output.status.code().unwrap_or_default() != 0 {
|
||||
error!(stdout = stdout, stderr = stderr, "git command failed");
|
||||
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),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
for line in stdout.split('\n') {
|
||||
let line = line.trim();
|
||||
if line == branch {
|
||||
return Ok(true);
|
||||
}
|
||||
if let Some((_, part)) = line.rsplit_once('/') {
|
||||
if part == branch {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
}))
|
||||
}
|
||||
|
||||
fn checkout<P: AsRef<Path>>(repo: P, branch: &str) -> Result<()> {
|
||||
let output = Command::new("git")
|
||||
.current_dir(repo)
|
||||
.arg("checkout")
|
||||
.arg(branch)
|
||||
.output()
|
||||
.into_diagnostic()?;
|
||||
fn checkout(repo: &Repository, branch: Branch) -> Result<()> {
|
||||
let commit = branch.get().peel(ObjectType::Commit).into_diagnostic()?;
|
||||
let name = branch
|
||||
.name()
|
||||
.into_diagnostic()?
|
||||
.expect("we already know the name if utf8");
|
||||
let mut checkout = CheckoutBuilder::default();
|
||||
checkout.update_index(true);
|
||||
|
||||
let stdout = String::from_utf8(output.stdout).into_diagnostic()?;
|
||||
let stderr = String::from_utf8(output.stderr).into_diagnostic()?;
|
||||
let code = output.status.code().unwrap_or_default();
|
||||
if code != 0 {
|
||||
if stderr.contains("would be overwritten") {
|
||||
return Err(miette!("uncommited changes"));
|
||||
}
|
||||
error!(
|
||||
stdout = stdout,
|
||||
stderr = stderr,
|
||||
code = code,
|
||||
"git command failed"
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_branch<P: AsRef<Path>>(repo: P) -> Result<String> {
|
||||
let output = Command::new("git")
|
||||
.current_dir(repo)
|
||||
.arg("rev-parse")
|
||||
.arg("--abbrev-ref")
|
||||
.arg("HEAD")
|
||||
.output()
|
||||
.into_diagnostic()?;
|
||||
String::from_utf8(output.stdout).into_diagnostic()
|
||||
repo.checkout_tree(&commit, Some(&mut checkout))
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to checkout tree")?;
|
||||
repo.set_head(&format!("refs/heads/{name}"))
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to set HEAD")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue