Something went wrong. Try again.
Mirror your Git repositories
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101mod config;mod git;mod s3;mod sync;
use std::path::PathBuf;use std::process::ExitCode;
use anyhow::Result;use clap::{Parser, Subcommand};
use crate::config::Config;
/// Mirror your Git repositories.#[derive(Parser)]#[command(name = "kalandra", version)]struct Cli { /// The path to the config file. #[arg(long, short, global = true, default_value = "kalandra.toml")] config: PathBuf, #[command(subcommand)] command: Command,}
#[derive(Subcommand)]enum Command { /// Syncs repositories to their configured destinations. Sync { /// The names of the repositories to sync. Syncs all repositories if /// none are specified. repos: Vec<String>, }, /// Lists the configured repositories and their destinations. List,}
#[tokio::main]async fn main() -> ExitCode { match run().await { Ok(exit_code) => exit_code, Err(err) => { eprintln!("error: {err:#}"); ExitCode::FAILURE } }}
async fn run() -> Result<ExitCode> { let cli = Cli::parse(); let config = Config::load(&cli.config)?;
match cli.command { Command::Sync { repos } => sync(&config, &repos).await, Command::List => { for repo in &config.repos { println!( "{} <- {} -> [{}]", repo.name, repo.source, repo.destinations.join(", ") ); } Ok(ExitCode::SUCCESS) } }}
async fn sync(config: &Config, repo_names: &[String]) -> Result<ExitCode> { let repos = if repo_names.is_empty() { config.repos.iter().collect::<Vec<_>>() } else { let mut repos = Vec::new(); for name in repo_names { let repo = config .repos .iter() .find(|repo| &repo.name == name) .ok_or_else(|| anyhow::anyhow!("unknown repo: {name:?}"))?; repos.push(repo); } repos };
let cache_dir = config.cache_dir()?;
let mut failures = Vec::new(); for repo in repos { if let Err(err) = crate::sync::sync_repo(config, repo, &cache_dir).await { eprintln!("[{}] error: {err:#}", repo.name); failures.push(repo.name.clone()); } }
if !failures.is_empty() { eprintln!("failed to sync: {}", failures.join(", ")); return Ok(ExitCode::FAILURE); }
Ok(ExitCode::SUCCESS)}