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

use extra app directories for git operations

This commit is contained in:
Robin Appelman 2026-03-06 00:15:35 +01:00
commit e9cb4f08e3
3 changed files with 42 additions and 21 deletions

View file

@ -124,9 +124,12 @@ pub enum GitOperation {
/// ///
/// "main" and "master" can be used interchangeably. /// "main" and "master" can be used interchangeably.
#[strum(props( #[strum(props(
Args = "[branch] branch to checkout, defaults to the branch matching the current server version" Args = "[branch] branch to checkout, defaults to the branch matching the current server version [-v] verbose"
))] ))]
Checkout { branch: Option<String> }, Checkout {
branch: Option<String>,
verbose: bool,
},
} }
impl SubCommand for GitOperation { impl SubCommand for GitOperation {
@ -320,18 +323,24 @@ impl HazeArgs {
HazeCommand::Checkout => { HazeCommand::Checkout => {
let branch = args.next().map(S::into); let branch = args.next().map(S::into);
Ok(HazeArgs::Git { Ok(HazeArgs::Git {
operation: GitOperation::Checkout { branch }, operation: GitOperation::Checkout {
branch,
verbose: false,
},
}) })
} }
HazeCommand::Git => { HazeCommand::Git => {
let mut args = args.peekable();
let operation = args let operation = args
.next() .next()
.ok_or_else(|| Report::msg("No git operation provided"))?; .ok_or_else(|| Report::msg("No git operation provided"))?;
match operation.as_ref() { match operation.as_ref() {
"checkout" => { "checkout" => {
let verbose = args.next_if(|arg| arg.as_ref() == "-v").is_some();
let branch = args.next().map(S::into); let branch = args.next().map(S::into);
let verbose = verbose | args.next_if(|arg| arg.as_ref() == "-v").is_some();
Ok(HazeArgs::Git { Ok(HazeArgs::Git {
operation: GitOperation::Checkout { branch }, operation: GitOperation::Checkout { branch, verbose },
}) })
} }
"pull" => Ok(HazeArgs::Git { "pull" => Ok(HazeArgs::Git {

View file

@ -1,22 +1,29 @@
use crate::config::HazeConfig;
use crate::Result; use crate::Result;
use git2::build::CheckoutBuilder; use git2::build::CheckoutBuilder;
use git2::{Branch, BranchType, 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::iter::once;
use std::path::PathBuf;
use std::process::Command; use std::process::Command;
fn find_app_repos(root: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>> { fn find_app_repos(config: &HazeConfig) -> Result<impl Iterator<Item = PathBuf>> {
let apps_dir = root.as_ref().join("apps"); let apps_dirs = once(config.sources_root.as_path().join("apps"))
Ok(read_dir(apps_dir) .chain(config.app_directories.iter().cloned());
.into_diagnostic()? let dir_handles = apps_dirs
.map(|dir| read_dir(dir).into_diagnostic())
.collect::<Result<Vec<_>>>()?;
Ok(dir_handles
.into_iter()
.flatten()
.flatten() .flatten()
.filter(|app| app.path().join(".git").is_dir()) .filter(|app| app.path().join(".git").is_dir())
.map(|app| app.path())) .map(|app| app.path()))
} }
fn longest_app_branch(root: impl AsRef<Path>) -> Result<(usize, usize)> { fn longest_app_branch(config: &HazeConfig) -> Result<(usize, usize)> {
Ok(find_app_repos(root)? Ok(find_app_repos(config)?
.filter_map(|app_dir| { .filter_map(|app_dir| {
let app_name = app_dir.file_name()?.to_str()?; let app_name = app_dir.file_name()?.to_str()?;
let repo = Repository::init(&app_dir).ok()?; let repo = Repository::init(&app_dir).ok()?;
@ -27,27 +34,32 @@ fn longest_app_branch(root: impl AsRef<Path>) -> Result<(usize, usize)> {
.unwrap_or_default()) .unwrap_or_default())
} }
pub fn checkout_all<P: AsRef<Path>>(sources_root: P, mut name: &str) -> Result<()> { pub fn checkout_all(config: &HazeConfig, mut name: &str, verbose: bool) -> Result<()> {
// "main" and "master" are interchangeable // "main" and "master" are interchangeable
if name == "main" { if name == "main" {
name = "master"; name = "master";
} }
for app_dir in find_app_repos(sources_root)? { for app_dir in find_app_repos(config)? {
let repo = Repository::init(&app_dir) let repo = Repository::init(&app_dir)
.into_diagnostic() .into_diagnostic()
.wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?; .wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?;
let app_name = app_dir.file_name().unwrap().to_string_lossy();
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(); let is_remote = branch.get().is_remote();
print!("{}", app_dir.file_name().unwrap().to_string_lossy()); print!("{app_name}");
if let Err(e) = checkout(&repo, &branch, is_remote.then_some(name)) { if let Err(e) = checkout(&repo, &branch, is_remote.then_some(name)) {
println!(": {:#}", e); println!(": {:#}", e);
} else { } else {
println!(""); println!("");
} }
} else if verbose {
println!("{app_name} -");
} }
} else if verbose {
println!("{app_name} 🛇 Branch not found");
}; };
} }
Ok(()) Ok(())
@ -68,11 +80,10 @@ const GIT_BINARY: &str = match option_env!("GIT_BINARY") {
None => "git", None => "git",
}; };
pub fn pull_all<P: AsRef<Path>>(sources_root: P) -> Result<()> { pub fn pull_all(config: &HazeConfig) -> Result<()> {
let sources_root = sources_root.as_ref(); let (max_app, max_branch) = longest_app_branch(config)?;
let (max_app, max_branch) = longest_app_branch(sources_root)?;
for app_dir in find_app_repos(sources_root)? { for app_dir in find_app_repos(config)? {
let app_name = app_dir.file_name().unwrap().to_string_lossy(); let app_name = app_dir.file_name().unwrap().to_string_lossy();
let repo = Repository::init(&app_dir) let repo = Repository::init(&app_dir)
.into_diagnostic() .into_diagnostic()

View file

@ -373,15 +373,16 @@ async fn main() -> Result<ExitCode> {
proxy(docker, config).await?; proxy(docker, config).await?;
} }
HazeArgs::Git { operation } => match operation { HazeArgs::Git { operation } => match operation {
GitOperation::Checkout { branch } => { GitOperation::Checkout { branch, verbose } => {
let sources = Sources::new(&config.sources_root)?; let sources = Sources::new(&config.sources_root)?;
checkout_all( checkout_all(
&config.sources_root, &config,
&branch.unwrap_or_else(|| sources.get_server_version_branch()), &branch.unwrap_or_else(|| sources.get_server_version_branch()),
verbose,
)?; )?;
} }
GitOperation::Pull => { GitOperation::Pull => {
pull_all(&config.sources_root)?; pull_all(&config)?;
} }
}, },
HazeArgs::Env { HazeArgs::Env {