mirror of
https://codeberg.org/icewind/haze.git
synced 2026-06-03 17:14:08 +02:00
git pull command
This commit is contained in:
parent
d86ee53f66
commit
1804a7fd93
7 changed files with 121 additions and 37 deletions
110
src/git.rs
110
src/git.rs
|
|
@ -1,33 +1,105 @@
|
|||
use crate::Result;
|
||||
use git2::build::CheckoutBuilder;
|
||||
use git2::{Branch, BranchType, ObjectType, Repository};
|
||||
use git2::{Branch, BranchType, ObjectType, Repository, RepositoryState};
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use std::fs::read_dir;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
fn find_app_repos(root: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>> {
|
||||
let apps_dir = root.as_ref().join("apps");
|
||||
Ok(read_dir(apps_dir)
|
||||
.into_diagnostic()?
|
||||
.flatten()
|
||||
.filter(|app| app.path().join(".git").is_dir())
|
||||
.map(|app| app.path()))
|
||||
}
|
||||
|
||||
fn longest_app_branch(root: impl AsRef<Path>) -> Result<(usize, usize)> {
|
||||
Ok(find_app_repos(root)?
|
||||
.filter_map(|app_dir| {
|
||||
let app_name = app_dir.file_name()?.to_str()?;
|
||||
let repo = Repository::init(&app_dir).ok()?;
|
||||
let branch_name = current_branch_name(&repo)?;
|
||||
Some((app_name.len(), branch_name.len()))
|
||||
})
|
||||
.max()
|
||||
.unwrap_or_default())
|
||||
}
|
||||
|
||||
pub fn checkout_all<P: AsRef<Path>>(sources_root: P, mut name: &str) -> Result<()> {
|
||||
// "main" and "master" are interchangeable
|
||||
if name == "main" {
|
||||
name = "master";
|
||||
}
|
||||
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() && app.path().join(".git").is_dir() {
|
||||
let app_dir = app.path();
|
||||
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(&repo, branch) {
|
||||
println!(": {:#} ❌", e);
|
||||
} else {
|
||||
println!(" ✓");
|
||||
}
|
||||
|
||||
for app_dir in find_app_repos(sources_root)? {
|
||||
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_dir.file_name().unwrap().to_string_lossy());
|
||||
if let Err(e) = checkout(&repo, branch) {
|
||||
println!(": {:#} ❌", e);
|
||||
} else {
|
||||
println!(" ✓");
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn current_branch_name(repo: &Repository) -> Option<String> {
|
||||
let (branch, _) = repo
|
||||
.branches(None)
|
||||
.ok()?
|
||||
.flatten()
|
||||
.find(|(b, _)| b.is_head())?;
|
||||
|
||||
branch.name().ok().flatten().map(String::from)
|
||||
}
|
||||
|
||||
const GIT_BINARY: &str = match option_env!("GIT_BINARY") {
|
||||
Some(git) => git,
|
||||
None => "git",
|
||||
};
|
||||
|
||||
pub fn pull_all<P: AsRef<Path>>(sources_root: P) -> Result<()> {
|
||||
let sources_root = sources_root.as_ref();
|
||||
let (max_app, max_branch) = longest_app_branch(sources_root)?;
|
||||
|
||||
for app_dir in find_app_repos(sources_root)? {
|
||||
let app_name = app_dir.file_name().unwrap().to_string_lossy();
|
||||
let repo = Repository::init(&app_dir)
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?;
|
||||
let branch_name = current_branch_name(&repo).unwrap_or("unknown".into());
|
||||
|
||||
print!(
|
||||
"{app_name:<app_width$} - {branch_name:<branch_width$}",
|
||||
app_width = max_app,
|
||||
branch_width = max_branch
|
||||
);
|
||||
|
||||
if repo.state() != RepositoryState::Clean {
|
||||
println!(": repository not clean ❌");
|
||||
continue;
|
||||
}
|
||||
|
||||
let output = Command::new(GIT_BINARY)
|
||||
.arg("pull")
|
||||
.current_dir(&app_dir)
|
||||
.output()
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to run git pull for {}", app_dir.display()))?;
|
||||
|
||||
if output.status.success() {
|
||||
println!(" ✓");
|
||||
} else {
|
||||
println!(" ❌");
|
||||
eprintln!("{}", String::from_utf8_lossy(&output.stderr))
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue