From f37549748cefe405d4f0ba1178e2b40def5aada0 Mon Sep 17 00:00:00 2001 From: Bryson Steck Date: Thu, 20 Mar 2025 22:01:50 -0600 Subject: [PATCH] fix formatting, use git2 fork until/if merged in --- .rustfmt.toml | 2 +- Cargo.lock | 10 +- Cargo.toml | 2 +- src/common.rs | 6 +- src/config.rs | 139 +++++++++++++++++++-------- src/main.rs | 50 +++++++--- src/refractr.rs | 248 +++++++++++++++++++++++++++++------------------- 7 files changed, 299 insertions(+), 158 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index a662206..382ae76 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,4 +1,4 @@ edition = "2021" tab_spaces = 2 match_block_trailing_comma = true -wrap_comments = true \ No newline at end of file +#wrap_comments = true \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index d094656..5053f27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,9 +232,8 @@ dependencies = [ [[package]] name = "git2" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" +version = "0.20.1" +source = "git+https://github.com/brysonsteck/git2-rs?branch=certificates#659e318aedf3de9c7be5ce2bf40c8aa850194792" dependencies = [ "bitflags", "libc", @@ -435,9 +434,8 @@ checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libgit2-sys" -version = "0.18.0+1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" +version = "0.18.1+1.9.0" +source = "git+https://github.com/brysonsteck/git2-rs?branch=certificates#659e318aedf3de9c7be5ce2bf40c8aa850194792" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 38dac2a..39ae354 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" clap = { version = "4.5.29", features = ["derive"] } colored = "3.0.0" ctrlc = "3.4.5" -git2 = "0.20.0" +git2 = { git = "https://github.com/brysonsteck/git2-rs", branch = "certificates" } hex = "0.4.3" quit = "2.0.0" serde = "1.0.217" diff --git a/src/common.rs b/src/common.rs index aa5da26..befe619 100644 --- a/src/common.rs +++ b/src/common.rs @@ -15,7 +15,7 @@ pub enum ExitCode { RemoteError = 5, PushError = 6, FetchError = 7, - ConfigError = 8 + ConfigError = 8, } pub struct ReturnData { @@ -33,7 +33,9 @@ pub fn warning(msg: String) { } pub fn verbose(level: u8, msg_lvl: u8, msg: String) { - if level < msg_lvl { return }; + if level < msg_lvl { + return; + }; let mut prefix = String::new(); for _ in 0..msg_lvl { prefix += "="; diff --git a/src/config.rs b/src/config.rs index 747f6e9..fe79d8e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,7 +20,7 @@ use toml; pub struct ConfigFile { pub path: String, pub file: Metadata, - pub config: Config + pub config: Config, } impl fmt::Display for ConfigFile { @@ -40,21 +40,24 @@ impl fmt::Display for ConfigFile { if i < self.config.to.len() - 1 { to_list.push_str(", "); } - }; + } to_list.push(']'); let work_dir_path = match &self.config.work_dir { None => { if cfg!(windows) { - format!("Using default \"{}\\refractr\"", match env::var("TEMP") { - Ok(val) => val, - Err(_) => format!("This shouldn't happen!") - }) + format!( + "Using default \"{}\\refractr\"", + match env::var("TEMP") { + Ok(val) => val, + Err(_) => format!("This shouldn't happen!"), + } + ) } else { format!("Using default: /tmp/refractr") } }, - Some(path) => format!("{}", path) + Some(path) => format!("{}", path), }; let schedule_interval = match self.config.schedule.interval { @@ -65,10 +68,15 @@ impl fmt::Display for ConfigFile { String::from("This shouldn't happen!\n") } }, - Some(int) => format!("\n Scheduled interval in seconds: {}", int.to_string()) + Some(int) => format!( + "\n Scheduled interval in seconds: {}", + int.to_string() + ), }; - write!(f, "Config file: \"{}\"\n \ + write!( + f, + "Config file: \"{}\"\n \ Is a file: {}\n \ Read only: {}\n \ Configuration:\n \ @@ -78,32 +86,37 @@ impl fmt::Display for ConfigFile { Working directory: {}\n \ SSH key for pushing clone: {}\n \ Schedule enabled: {}\ - {}" - , self.path, self.file.is_file(), self.file.permissions().readonly(), self.config.from - , to_list, branches_list, work_dir_path, self.config.git.ssh_identity_file, self.config.schedule.enabled - , schedule_interval) + {}", + self.path, + self.file.is_file(), + self.file.permissions().readonly(), + self.config.from, + to_list, + branches_list, + work_dir_path, + self.config.git.ssh_identity_file, + self.config.schedule.enabled, + schedule_interval + ) } } -#[derive(PartialEq)] -#[derive(Deserialize)] +#[derive(PartialEq, Deserialize)] pub struct Config { pub from: String, pub to: Vec, pub branches: Vec, pub work_dir: Option, pub git: Git, - pub schedule: Schedule + pub schedule: Schedule, } -#[derive(PartialEq)] -#[derive(Deserialize)] +#[derive(PartialEq, Deserialize)] pub struct Git { pub ssh_identity_file: String, } -#[derive(PartialEq)] -#[derive(Deserialize)] +#[derive(PartialEq, Deserialize)] pub struct Schedule { pub enabled: bool, pub interval: Option, @@ -112,48 +125,93 @@ pub struct Schedule { pub fn read_config(paths: Vec, refractr: &Refractr) -> Result, String> { let mut config_files: Vec = vec![]; for path in paths { - common::verbose(refractr.verbose, 1, format!("Reading config file: \"{}\"", String::from(path.to_string_lossy()))); + common::verbose( + refractr.verbose, + 1, + format!( + "Reading config file: \"{}\"", + String::from(path.to_string_lossy()) + ), + ); let mut data = String::new(); let mut file = match File::open(path.as_path()) { - Err(e) => return Err(format!("unable to open {}: {}", path.as_path().display(), e)), - Ok(file) => file + Err(e) => { + return Err(format!( + "unable to open {}: {}", + path.as_path().display(), + e + )) + }, + Ok(file) => file, }; if let Err(e) = file.read_to_string(&mut data) { - return Err(format!("unable to read {}: {}", path.as_path().display(), e)) + return Err(format!( + "unable to read {}: {}", + path.as_path().display(), + e + )); } let config: Config = match toml::from_str(&data) { Ok(c) => c, - Err(e) => return Err(format!("issues parsing toml file {}: {}", path.as_path().display(), e)) + Err(e) => { + return Err(format!( + "issues parsing toml file {}: {}", + path.as_path().display(), + e + )) + }, }; let config_file = ConfigFile { path: match fs::canonicalize(&path) { - Err(_) => return Err(format!("cannot get absolute path of config file: {}", path.as_path().display())), - Ok(abs) => abs.to_string_lossy().to_string() + Err(_) => { + return Err(format!( + "cannot get absolute path of config file: {}", + path.as_path().display() + )) + }, + Ok(abs) => abs.to_string_lossy().to_string(), }, file: match fs::metadata(&path) { - Err(_) => return Err(format!("cannot obtain metadata for config file: {}", path.as_path().display())), - Ok(metadata) => metadata + Err(_) => { + return Err(format!( + "cannot obtain metadata for config file: {}", + path.as_path().display() + )) + }, + Ok(metadata) => metadata, }, config: match verify_config(&config) { - Err(e) => return Err(format!("invalid config {}: {}", path.as_path().display(), e)), - Ok(_) => config - } + Err(e) => { + return Err(format!( + "invalid config {}: {}", + path.as_path().display(), + e + )) + }, + Ok(_) => config, + }, }; let mut dup = false; for i in &config_files { if i.path == config_file.path { - common::warning(format!("skipping config file \"{}\" as it was already read", path.as_path().display())); + common::warning(format!( + "skipping config file \"{}\" as it was already read", + path.as_path().display() + )); dup = true; break; } else if i.config == config_file.config { - common::warning(format!("config files \"{}\" and \"{}\" appear to have the same config", i.path, config_file.path)); + common::warning(format!( + "config files \"{}\" and \"{}\" appear to have the same config", + i.path, config_file.path + )); } } - + if !dup { config_files.push(config_file); } @@ -167,10 +225,10 @@ fn verify_config(config: &Config) -> Result<(), String> { match config.schedule.interval { Some(i) => { if i < 60 { - return Err(format!("schedule is enabled, but less than 60")) + return Err(format!("schedule is enabled, but less than 60")); } }, - None => return Err(format!("schedule is enabled, but no interval was defined")) + None => return Err(format!("schedule is enabled, but no interval was defined")), } } @@ -180,7 +238,7 @@ fn verify_config(config: &Config) -> Result<(), String> { if cfg!(windows) { match env::var("TEMP") { Ok(val) => val, - Err(_) => return Err(format!("cannot determine the default temp dir")) + Err(_) => return Err(format!("cannot determine the default temp dir")), } } else { format!("/tmp/refractr") @@ -190,8 +248,9 @@ fn verify_config(config: &Config) -> Result<(), String> { if !&config.from.starts_with("ssh://") && !&config.from.starts_with("https://") - && !&config.from.starts_with("http://") { - return Err(format!("'from' value does not use a supported protocol")) + && !&config.from.starts_with("http://") + { + return Err(format!("'from' value does not use a supported protocol")); } Ok(()) diff --git a/src/main.rs b/src/main.rs index 9d0048c..0ac23d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,10 +15,10 @@ use crate::refractr::Refractr; use clap::Parser; use std::path::PathBuf; use std::process; -#[cfg(target_family = "unix")] -use users; #[cfg(target_family = "windows")] use username; +#[cfg(target_family = "unix")] +use users; #[derive(Parser)] #[command(name = "refractr")] @@ -32,7 +32,11 @@ struct Args { #[arg(short, long, help = "Specify the level of verbosity", action = clap::ArgAction::Count)] verbose: u8, - #[arg(short = 'e', long, help = "Output a full, commented config file and exit")] + #[arg( + short = 'e', + long, + help = "Output a full, commented config file and exit" + )] create: bool, #[arg(short = 's', long, help = "Exit on push errors instead of ignoring")] @@ -44,7 +48,8 @@ fn get_config_default() -> &'static str { return "C:\\ProgramData\\refractr\\config.toml"; #[cfg(target_os = "linux")] return "/etc/refractr/config.toml"; - #[cfg(any(target_os = "freebsd", + #[cfg(any( + target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "macos" @@ -61,12 +66,12 @@ fn main() -> Result<(), String> { "true" => true, _ => false, }, - None => false + None => false, }, pid: process::id(), strict: args.strict, unix: cfg!(unix), - verbose: args.verbose + verbose: args.verbose, }; // warn to avoid root/admin @@ -86,22 +91,37 @@ fn main() -> Result<(), String> { Err(_) => common::warning(format!("failed to get process username")), } - common::verbose(refractr.verbose, 1, format!("refractr started with level {} verbosity enabled", refractr.verbose.to_string())); + common::verbose( + refractr.verbose, + 1, + format!( + "refractr started with level {} verbosity enabled", + refractr.verbose.to_string() + ), + ); common::verbose(refractr.verbose, 3, format!("Process ID: {}", refractr.pid)); - common::verbose(refractr.verbose, 3, format!("Running in Docker: {}", refractr.docker)); - common::verbose(refractr.verbose, 3, format!("System is UNIX(-like): {}", refractr.unix)); + common::verbose( + refractr.verbose, + 3, + format!("Running in Docker: {}", refractr.docker), + ); + common::verbose( + refractr.verbose, + 3, + format!("System is UNIX(-like): {}", refractr.unix), + ); common::verbose(refractr.verbose, 2, format!("Checking for create flag")); if args.create { common::verbose(refractr.verbose, 3, format!("Printing sample config")); let example = include_str!("example/config.toml"); println!("{}", example); - return Ok(()) + return Ok(()); } let mut cfgs = vec![]; match config::read_config(args.config, &refractr) { Ok(c) => cfgs = c, - Err(e) => common::error(format!("{}", e), common::ExitCode::ConfigError) + Err(e) => common::error(format!("{}", e), common::ExitCode::ConfigError), }; if refractr.verbose >= 2 { @@ -111,10 +131,14 @@ fn main() -> Result<(), String> { } } - common::verbose(refractr.verbose, 1, format!("Config file(s) read successfully")); + common::verbose( + refractr.verbose, + 1, + format!("Config file(s) read successfully"), + ); match refractr.run(cfgs) { Ok(_) => (), - Err(e) => common::error(format!("{}", e.msg), e.code) + Err(e) => common::error(format!("{}", e.msg), e.code), }; Ok(()) diff --git a/src/refractr.rs b/src/refractr.rs index 5851ba7..bafa8b6 100644 --- a/src/refractr.rs +++ b/src/refractr.rs @@ -6,20 +6,20 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::common::{self, ReturnData, ExitCode}; +use crate::common::{self, ExitCode, ReturnData}; use crate::config::{Config, ConfigFile}; -use git2::string_array::StringArray; -use git2::{FetchOptions, CertificateCheckStatus, Cred, PushOptions, RemoteCallbacks, Repository}; -use git2::{Error, ErrorCode}; use git2::build::RepoBuilder; +use git2::string_array::StringArray; +use git2::{CertificateCheckStatus, Cred, FetchOptions, PushOptions, RemoteCallbacks, Repository}; +use git2::{Error, ErrorCode}; use hex; -use sha2::{Sha256, Digest}; +use sha2::{Digest, Sha256}; use std::env; use std::fs; use std::path::{Path, PathBuf, MAIN_SEPARATOR_STR}; -use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; use std::thread; use std::time; @@ -28,7 +28,7 @@ pub struct Refractr { pub pid: u32, pub strict: bool, pub unix: bool, - pub verbose: u8 + pub verbose: u8, } struct OpenedRepository { @@ -41,7 +41,11 @@ struct OpenedRepository { impl Refractr { fn set_up_work_dir(&self, work_dir: PathBuf) -> Result { if let Err(e) = fs::create_dir_all(&work_dir) { - return Err(format!("could not create working directory: {}: {}", work_dir.to_string_lossy().to_string(), e)) + return Err(format!( + "could not create working directory: {}: {}", + work_dir.to_string_lossy().to_string(), + e + )); } Ok(work_dir.to_string_lossy().to_string()) } @@ -72,47 +76,58 @@ impl Refractr { Ok(()) } - fn fetch(&self, repo: &Repository, branches: &Vec, ssh: bool, ssh_key: &String) -> Result<(), Error> { + fn fetch( + &self, + repo: &Repository, + branches: &Vec, + ssh: bool, + ssh_key: &String, + ) -> Result<(), Error> { let mut cb = RemoteCallbacks::new(); let mut fo = FetchOptions::new(); if ssh { let key_string: String = ssh_key.clone(); - cb.credentials(move |_,_,_| Cred::ssh_key( - "git", - None, - Path::new(&key_string), - None)); + cb.credentials(move |_, _, _| Cred::ssh_key("git", None, Path::new(&key_string), None)); cb.certificate_check(|cert, url| { let mut sha256 = String::new(); for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() { sha256.push_str(&hex::encode(i.to_string())); } - common::warning( - format!("implicitly trusting unknown host {} with sha256 host key {}", + common::warning(format!( + "implicitly trusting unknown host {} with sha256 host key {}", url, - hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()))); - common::warning( - format!("to ignore this error in the future, add this host to your known_hosts file")); + hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()) + )); + common::warning(format!( + "to ignore this error in the future, add this host to your known_hosts file" + )); Ok(CertificateCheckStatus::CertificateOk) }); } fo.download_tags(git2::AutotagOption::All); fo.remote_callbacks(cb); - repo.find_remote("origin")?.fetch(&branches, Some(&mut fo), None)?; + repo + .find_remote("origin")? + .fetch(&branches, Some(&mut fo), None)?; Ok(()) } fn set_up_refs(&self, repo: &Repository, branches: &Vec) -> Result<(), Error> { for branch in branches { - let mut fetch_head = repo.find_reference(format!("refs/remotes/origin/{}", branch).as_str())?; + let mut fetch_head = + repo.find_reference(format!("refs/remotes/origin/{}", branch).as_str())?; fetch_head.rename(format!("refs/heads/{}", branch).as_str(), true, "")?; } Ok(()) } - fn make_remotes<'a> (&self, repo: &'a Repository, cfg: &ConfigFile) -> Result, String> { + fn make_remotes<'a>( + &self, + repo: &'a Repository, + cfg: &ConfigFile, + ) -> Result, String> { // create remotes for each "to" repo let mut remote_list = Vec::new(); for to in &cfg.config.to { @@ -122,7 +137,8 @@ impl Refractr { common::verbose( self.verbose, 2, - format!("Attempting to create remote {} for url {}", remote_id, to)); + format!("Attempting to create remote {} for url {}", remote_id, to), + ); match repo.remote(remote_id.as_str(), to) { Ok(_) => remote_list.push(remote_id), Err(e) => { @@ -132,37 +148,43 @@ impl Refractr { } else { return Err(format!("failed to create remote: {}", e)); } - } + }, } } Ok(remote_list) } - fn push_remotes(&self, cfg: &Config, repo: &Repository, remote_list: &Vec) -> Result<(), String> { + fn push_remotes( + &self, + cfg: &Config, + repo: &Repository, + remote_list: &Vec, + ) -> Result<(), String> { for id in remote_list { let mut remote = repo.find_remote(&id).unwrap(); common::verbose( - self.verbose, - 1, - format!("Pushing to remote: {}", remote.url().unwrap())); + self.verbose, + 1, + format!("Pushing to remote: {}", remote.url().unwrap()), + ); let mut callbacks = RemoteCallbacks::new(); - callbacks.credentials(|_,_,_| Cred::ssh_key( - "git", - None, - &Path::new(&cfg.git.ssh_identity_file), - None)); + callbacks.credentials(|_, _, _| { + Cred::ssh_key("git", None, &Path::new(&cfg.git.ssh_identity_file), None) + }); callbacks.certificate_check(|cert, url| { let mut sha256 = String::new(); for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() { sha256.push_str(&hex::encode(i.to_string())); } - common::warning( - format!("implicitly trusting unknown host {} with sha256 host key {}", + common::warning(format!( + "implicitly trusting unknown host {} with sha256 host key {}", url, - hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()))); - common::warning( - format!("to ignore this error in the future, add this host to your known_hosts file")); + hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()) + )); + common::warning(format!( + "to ignore this error in the future, add this host to your known_hosts file" + )); Ok(CertificateCheckStatus::CertificateOk) }); let mut push_options = PushOptions::new(); @@ -182,11 +204,19 @@ impl Refractr { Ok(_) => (), Err(e) => { if self.strict { - return Err(format!("failed to push to remote: {}: {}", remote.url().unwrap(), e)) + return Err(format!( + "failed to push to remote: {}: {}", + remote.url().unwrap(), + e + )); } else { - common::warning(format!("failed to push to remote: {}: {}", remote.url().unwrap(), e)) + common::warning(format!( + "failed to push to remote: {}: {}", + remote.url().unwrap(), + e + )) } - } + }, } } @@ -199,13 +229,16 @@ impl Refractr { let r = running.clone(); let count = repos.len(); for i in 0..repos.len() { - current_ints.push(u64::from(repos[i].cfg.schedule.interval.unwrap().unsigned_abs())); - }; + current_ints.push(u64::from( + repos[i].cfg.schedule.interval.unwrap().unsigned_abs(), + )); + } let original_ints = current_ints.clone(); ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); - }).expect("Failed to set ^C handler"); + }) + .expect("Failed to set ^C handler"); common::verbose(self.verbose, 1, format!("Starting scheduled loop")); let min = *current_ints.iter().min().unwrap(); @@ -218,7 +251,8 @@ impl Refractr { common::verbose( self.verbose, 2, - format!("Sleeping for {} seconds", sleep_int.as_secs())); + format!("Sleeping for {} seconds", sleep_int.as_secs()), + ); while running.load(Ordering::SeqCst) { thread::sleep(time::Duration::from_secs(1)); if now.elapsed().as_secs() >= sleep_int.as_secs() { @@ -230,19 +264,17 @@ impl Refractr { common::verbose( self.verbose, 2, - format!("Interval for {} has arrived, pulling", repos[i].cfg.from)); + format!("Interval for {} has arrived, pulling", repos[i].cfg.from), + ); let _ = self.fast_forward(&repos[i].path, &repos[i].cfg.branches); - if let Err(e) = self.push_remotes( - &repos[i].cfg, - &repos[i].repo, - &repos[i].remotes) { - common::error(e, ExitCode::PushError) + if let Err(e) = self.push_remotes(&repos[i].cfg, &repos[i].repo, &repos[i].remotes) { + common::error(e, ExitCode::PushError) }; } } do_break = false; - break + break; } } } @@ -266,51 +298,54 @@ impl Refractr { PathBuf::from("/tmp/refractr") } }, - Some(path) => PathBuf::from(path) + Some(path) => PathBuf::from(path), }); let path_str = match work_dir { Ok(p) => p, - Err(e) => return Err(ReturnData { - code: ExitCode::FilesystemError, - msg: e - }) + Err(e) => { + return Err(ReturnData { + code: ExitCode::FilesystemError, + msg: e, + }) + }, }; common::verbose( self.verbose, 2, - format!("Created working directory: {}", &path_str)); + format!("Created working directory: {}", &path_str), + ); let repo_name = match &cfg.config.from.split("/").last() { Some(split) => split.to_string(), - None => return Err(ReturnData { - code: ExitCode::ParseError, - msg: format!("failed to parse repository name") - }) + None => { + return Err(ReturnData { + code: ExitCode::ParseError, + msg: format!("failed to parse repository name"), + }) + }, }; let ssh = cfg.config.from.starts_with("ssh://"); let mut builder = RepoBuilder::new(); let mut cb = RemoteCallbacks::new(); let mut fo = FetchOptions::new(); - + // make initial clone if ssh { let key_string = cfg.config.git.ssh_identity_file.clone(); - cb.credentials(move |_,_,_| Cred::ssh_key( - "git", - None, - Path::new(&key_string), - None)); + cb.credentials(move |_, _, _| Cred::ssh_key("git", None, Path::new(&key_string), None)); cb.certificate_check(|cert, url| { let mut sha256 = String::new(); for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() { sha256.push_str(&hex::encode(i.to_string())); } - common::warning( - format!("implicitly trusting unknown host {} with sha256 host key {}", + common::warning(format!( + "implicitly trusting unknown host {} with sha256 host key {}", url, - hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()))); - common::warning( - format!("to ignore this error in the future, add this host to your known_hosts file")); + hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()) + )); + common::warning(format!( + "to ignore this error in the future, add this host to your known_hosts file" + )); Ok(CertificateCheckStatus::CertificateOk) }); } @@ -322,45 +357,63 @@ impl Refractr { common::verbose( self.verbose, 1, - format!("Cloning repository {} to {}", &cfg.config.from, &repo_dir)); + format!("Cloning repository {} to {}", &cfg.config.from, &repo_dir), + ); let repo = match builder.clone(&cfg.config.from, Path::new(&repo_dir)) { Ok(repo) => repo, Err(e) => { if e.code() != ErrorCode::Exists { - common::error(format!("failed to clone repo to {}: {}", repo_dir, e), ExitCode::FilesystemError); + common::error( + format!("failed to clone repo to {}: {}", repo_dir, e), + ExitCode::FilesystemError, + ); } - common::warning(format!("found existing repo at {}, attempting to use", repo_dir)); + common::warning(format!( + "found existing repo at {}, attempting to use", + repo_dir + )); match self.fast_forward(&repo_dir, &cfg.config.branches) { - Ok(_) => if let Ok(repo) = Repository::open(Path::new(&repo_dir)) { - repo - } else { + Ok(_) => { + if let Ok(repo) = Repository::open(Path::new(&repo_dir)) { + repo + } else { + return Err(ReturnData { + code: ExitCode::RepositoryError, + msg: format!("failed to obtain existing repo"), + }); + } + }, + Err(e) => { return Err(ReturnData { code: ExitCode::RepositoryError, - msg: format!("failed to obtain existing repo") + msg: format!("failed to obtain existing repo: {}", e), }) }, - Err(e) => return Err(ReturnData { - code: ExitCode::RepositoryError, - msg: format!("failed to obtain existing repo: {}", e) - }) } - } + }, }; self.set_up_refs(&repo, &cfg.config.branches).unwrap(); - if let Err(e) = self.fetch(&repo, + if let Err(e) = self.fetch( + &repo, &cfg.config.branches, ssh, - &cfg.config.git.ssh_identity_file) { - common::error(format!("failed to fetch repo {}: {}", cfg.config.from, e), ExitCode::FetchError); + &cfg.config.git.ssh_identity_file, + ) { + common::error( + format!("failed to fetch repo {}: {}", cfg.config.from, e), + ExitCode::FetchError, + ); } let remotes = match self.make_remotes(&repo, &cfg) { Ok(v) => v, - Err(e) => return Err(ReturnData { - code: ExitCode::RemoteError, - msg: e - }) + Err(e) => { + return Err(ReturnData { + code: ExitCode::RemoteError, + msg: e, + }) + }, }; if let Err(e) = self.push_remotes(&cfg.config, &repo, &remotes) { common::error(e, ExitCode::PushError); @@ -371,7 +424,7 @@ impl Refractr { repo, path: repo_dir, remotes, - cfg: cfg.config + cfg: cfg.config, }); } } @@ -380,13 +433,18 @@ impl Refractr { common::verbose( self.verbose, 2, - format!("{} configs have schedules enabled, setting up looper", loop_repos.len())); + format!( + "{} configs have schedules enabled, setting up looper", + loop_repos.len() + ), + ); return self.looper(loop_repos); } else { common::verbose( self.verbose, 2, - format!("No scheduled configs found, exiting refractr")); + format!("No scheduled configs found, exiting refractr"), + ); } Ok(())