diff --git a/src/args.rs b/src/args.rs index e4e2b69..9b7a2cc 100644 --- a/src/args.rs +++ b/src/args.rs @@ -124,9 +124,12 @@ pub enum GitOperation { /// /// "main" and "master" can be used interchangeably. #[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 }, + Checkout { + branch: Option, + verbose: bool, + }, } impl SubCommand for GitOperation { @@ -320,18 +323,24 @@ impl HazeArgs { HazeCommand::Checkout => { let branch = args.next().map(S::into); Ok(HazeArgs::Git { - operation: GitOperation::Checkout { branch }, + operation: GitOperation::Checkout { + branch, + verbose: false, + }, }) } HazeCommand::Git => { + let mut args = args.peekable(); let operation = args .next() .ok_or_else(|| Report::msg("No git operation provided"))?; match operation.as_ref() { "checkout" => { + let verbose = args.next_if(|arg| arg.as_ref() == "-v").is_some(); let branch = args.next().map(S::into); + let verbose = verbose | args.next_if(|arg| arg.as_ref() == "-v").is_some(); Ok(HazeArgs::Git { - operation: GitOperation::Checkout { branch }, + operation: GitOperation::Checkout { branch, verbose }, }) } "pull" => Ok(HazeArgs::Git { diff --git a/src/git.rs b/src/git.rs index d08f2f3..3a797c3 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,22 +1,29 @@ +use crate::config::HazeConfig; use crate::Result; use git2::build::CheckoutBuilder; use git2::{Branch, BranchType, Repository, RepositoryState}; use miette::{Context, IntoDiagnostic}; use std::fs::read_dir; -use std::path::{Path, PathBuf}; +use std::iter::once; +use std::path::PathBuf; use std::process::Command; -fn find_app_repos(root: impl AsRef) -> Result> { - let apps_dir = root.as_ref().join("apps"); - Ok(read_dir(apps_dir) - .into_diagnostic()? +fn find_app_repos(config: &HazeConfig) -> Result> { + let apps_dirs = once(config.sources_root.as_path().join("apps")) + .chain(config.app_directories.iter().cloned()); + let dir_handles = apps_dirs + .map(|dir| read_dir(dir).into_diagnostic()) + .collect::>>()?; + Ok(dir_handles + .into_iter() + .flatten() .flatten() .filter(|app| app.path().join(".git").is_dir()) .map(|app| app.path())) } -fn longest_app_branch(root: impl AsRef) -> Result<(usize, usize)> { - Ok(find_app_repos(root)? +fn longest_app_branch(config: &HazeConfig) -> Result<(usize, usize)> { + Ok(find_app_repos(config)? .filter_map(|app_dir| { let app_name = app_dir.file_name()?.to_str()?; let repo = Repository::init(&app_dir).ok()?; @@ -27,27 +34,32 @@ fn longest_app_branch(root: impl AsRef) -> Result<(usize, usize)> { .unwrap_or_default()) } -pub fn checkout_all>(sources_root: P, mut name: &str) -> Result<()> { +pub fn checkout_all(config: &HazeConfig, mut name: &str, verbose: bool) -> Result<()> { // "main" and "master" are interchangeable if name == "main" { 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) .into_diagnostic() .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 !branch.is_head() { 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)) { println!(": {:#} ❌", e); } else { println!(" ✓"); } + } else if verbose { + println!("{app_name} -"); } + } else if verbose { + println!("{app_name} 🛇 Branch not found"); }; } Ok(()) @@ -68,11 +80,10 @@ const GIT_BINARY: &str = match option_env!("GIT_BINARY") { None => "git", }; -pub fn pull_all>(sources_root: P) -> Result<()> { - let sources_root = sources_root.as_ref(); - let (max_app, max_branch) = longest_app_branch(sources_root)?; +pub fn pull_all(config: &HazeConfig) -> Result<()> { + let (max_app, max_branch) = longest_app_branch(config)?; - 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 repo = Repository::init(&app_dir) .into_diagnostic() diff --git a/src/main.rs b/src/main.rs index 5deb172..5eb6e0c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -373,15 +373,16 @@ async fn main() -> Result { proxy(docker, config).await?; } HazeArgs::Git { operation } => match operation { - GitOperation::Checkout { branch } => { + GitOperation::Checkout { branch, verbose } => { let sources = Sources::new(&config.sources_root)?; checkout_all( - &config.sources_root, + &config, &branch.unwrap_or_else(|| sources.get_server_version_branch()), + verbose, )?; } GitOperation::Pull => { - pull_all(&config.sources_root)?; + pull_all(&config)?; } }, HazeArgs::Env {