clean up work dirs
This commit is contained in:
parent
b98a3beec4
commit
fb8ed1ae8c
4 changed files with 90 additions and 52 deletions
|
@ -16,6 +16,7 @@ pub enum ExitCode {
|
|||
PushError = 6,
|
||||
FetchError = 7,
|
||||
ConfigError = 8,
|
||||
HaltError = 130,
|
||||
}
|
||||
|
||||
pub struct ReturnData {
|
||||
|
@ -23,11 +24,15 @@ pub struct ReturnData {
|
|||
pub msg: String,
|
||||
}
|
||||
|
||||
pub fn error(msg: String, code: ExitCode) {
|
||||
pub fn error_quit(msg: String, code: ExitCode) {
|
||||
eprintln!("{} {}", "error:".red().bold(), msg);
|
||||
quit::with_code(code as u8)
|
||||
}
|
||||
|
||||
pub fn error(msg: String) {
|
||||
eprintln!("{} {}", "error:".red().bold(), msg);
|
||||
}
|
||||
|
||||
pub fn warning(msg: String) {
|
||||
eprintln!("{} {}", "warning:".yellow().bold(), msg)
|
||||
}
|
||||
|
|
|
@ -123,6 +123,19 @@ pub struct Schedule {
|
|||
pub interval: Option<i32>,
|
||||
}
|
||||
|
||||
pub fn get_work_dir(work_dir: &Option<String>) -> String {
|
||||
match work_dir {
|
||||
None => {
|
||||
if cfg!(windows) {
|
||||
format!("{}\\refractr", env::var("TEMP").unwrap())
|
||||
} else {
|
||||
format!("/tmp/refractr")
|
||||
}
|
||||
},
|
||||
Some(path) => path.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_config(paths: Vec<PathBuf>, refractr: &Refractr) -> Result<Vec<ConfigFile>, String> {
|
||||
let mut config_files: Vec<ConfigFile> = vec![];
|
||||
for path in paths {
|
||||
|
@ -233,18 +246,12 @@ fn verify_config(config: &Config) -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
|
||||
match &config.work_dir {
|
||||
Some(path) => format!("{}", path),
|
||||
None => {
|
||||
if let None = &config.work_dir {
|
||||
if cfg!(windows) {
|
||||
match env::var("TEMP") {
|
||||
Ok(val) => val,
|
||||
Err(_) => return Err(format!("cannot determine the default temp dir")),
|
||||
if let Err(e) = env::var("TEMP") {
|
||||
return Err(format!("cannot determine the default temp dir: {}", e));
|
||||
}
|
||||
} else {
|
||||
format!("/tmp/refractr")
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if !&config.from.starts_with("ssh://")
|
||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -45,6 +45,13 @@ struct Args {
|
|||
help = "Exit on push and unknown host errors instead of ignoring them"
|
||||
)]
|
||||
strict: bool,
|
||||
|
||||
#[arg(
|
||||
short = 'p',
|
||||
long,
|
||||
help = "Do not clean the working directories specified in config(s)"
|
||||
)]
|
||||
persist: bool,
|
||||
}
|
||||
|
||||
fn get_config_default() -> &'static str {
|
||||
|
@ -72,6 +79,7 @@ fn main() -> Result<(), String> {
|
|||
},
|
||||
None => false,
|
||||
},
|
||||
persist: args.persist,
|
||||
pid: process::id(),
|
||||
strict: args.strict,
|
||||
unix: cfg!(unix),
|
||||
|
@ -125,7 +133,7 @@ fn main() -> Result<(), String> {
|
|||
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_quit(format!("{}", e), common::ExitCode::ConfigError),
|
||||
};
|
||||
|
||||
if refractr.verbose >= 2 {
|
||||
|
@ -142,7 +150,7 @@ fn main() -> Result<(), String> {
|
|||
);
|
||||
match refractr.run(cfgs) {
|
||||
Ok(_) => (),
|
||||
Err(e) => common::error(format!("{}", e.msg), e.code),
|
||||
Err(e) => common::error_quit(format!("{}", e.msg), e.code),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
use crate::common::{self, ExitCode, ReturnData};
|
||||
use crate::config::{Config, ConfigFile};
|
||||
use crate::config::{self, Config, ConfigFile};
|
||||
|
||||
use git2::build::RepoBuilder;
|
||||
use git2::string_array::StringArray;
|
||||
|
@ -15,8 +15,7 @@ use git2::{CertificateCheckStatus, Cred, FetchOptions, PushOptions, RemoteCallba
|
|||
use git2::{Error, ErrorCode};
|
||||
use hex;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::{self, remove_dir_all};
|
||||
use std::path::{Path, PathBuf, MAIN_SEPARATOR_STR};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
@ -25,6 +24,7 @@ use std::time;
|
|||
|
||||
pub struct Refractr {
|
||||
pub docker: bool,
|
||||
pub persist: bool,
|
||||
pub pid: u32,
|
||||
pub strict: bool,
|
||||
pub unix: bool,
|
||||
|
@ -39,7 +39,7 @@ struct OpenedRepository {
|
|||
}
|
||||
|
||||
impl Refractr {
|
||||
fn set_up_work_dir(&self, work_dir: PathBuf) -> Result<String, String> {
|
||||
fn set_up_work_dir(&self, work_dir: PathBuf) -> Result<(), String> {
|
||||
if let Err(e) = fs::create_dir_all(&work_dir) {
|
||||
return Err(format!(
|
||||
"could not create working directory: {}: {}",
|
||||
|
@ -47,7 +47,7 @@ impl Refractr {
|
|||
e
|
||||
));
|
||||
}
|
||||
Ok(work_dir.to_string_lossy().to_string())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_up_ssh(&self, key_path: String, strict: bool) -> Result<RemoteCallbacks, String> {
|
||||
|
@ -56,7 +56,7 @@ impl Refractr {
|
|||
cb.certificate_check(move |cert, url| {
|
||||
let sha256 = hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec());
|
||||
if strict {
|
||||
common::error(
|
||||
common::error_quit(
|
||||
format!(
|
||||
"unknown host {} with sha256 host key {}, exiting",
|
||||
url, sha256
|
||||
|
@ -120,7 +120,7 @@ impl Refractr {
|
|||
fo.remote_callbacks(cb);
|
||||
()
|
||||
},
|
||||
Err(e) => common::error(
|
||||
Err(e) => common::error_quit(
|
||||
format!("error setting up ssh: {}", e),
|
||||
ExitCode::ConfigError,
|
||||
),
|
||||
|
@ -195,7 +195,7 @@ impl Refractr {
|
|||
po.remote_callbacks(cb);
|
||||
()
|
||||
},
|
||||
Err(e) => common::error(
|
||||
Err(e) => common::error_quit(
|
||||
format!("error setting up ssh: {}", e),
|
||||
ExitCode::ConfigError,
|
||||
),
|
||||
|
@ -294,7 +294,7 @@ impl Refractr {
|
|||
&repos[i].cfg.git.ssh_identity_file,
|
||||
self.strict.clone(),
|
||||
) {
|
||||
common::error(
|
||||
common::error_quit(
|
||||
format!("failed to fetch repo {}: {}", repos[i].cfg.from, e),
|
||||
ExitCode::FetchError,
|
||||
);
|
||||
|
@ -302,7 +302,7 @@ impl Refractr {
|
|||
|
||||
let _ = self.fast_forward(&repos[i].repo, &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)
|
||||
common::error_quit(e, ExitCode::PushError)
|
||||
};
|
||||
current_ints[i] = original_ints[i].clone();
|
||||
}
|
||||
|
@ -322,37 +322,38 @@ impl Refractr {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn clean(&self, dirs: Vec<String>) -> Result<(), ReturnData> {
|
||||
for dir in dirs {
|
||||
common::verbose(self.verbose, 1, format!("removing working dir {}", dir));
|
||||
if let Err(e) = remove_dir_all(&dir) {
|
||||
common::warning(format!("could not clean up working dir: {}: {}", dir, e));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(&self, cfgs: Vec<ConfigFile>) -> Result<(), ReturnData> {
|
||||
common::verbose(self.verbose, 3, format!("Starting main refractr loop"));
|
||||
let mut loop_repos = Vec::new();
|
||||
let mut work_dirs = Vec::new();
|
||||
|
||||
for cfg in cfgs {
|
||||
// set up the working directory
|
||||
common::verbose(self.verbose, 3, format!("Loading config: {}", cfg.path));
|
||||
let work_dir = self.set_up_work_dir(match &cfg.config.work_dir {
|
||||
None => {
|
||||
if cfg!(windows) {
|
||||
PathBuf::from(format!("{}\\refractr", env::var("TEMP").unwrap()))
|
||||
} else {
|
||||
PathBuf::from("/tmp/refractr")
|
||||
}
|
||||
},
|
||||
Some(path) => PathBuf::from(path),
|
||||
});
|
||||
let path_str = match work_dir {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
let work_dir = config::get_work_dir(&cfg.config.work_dir);
|
||||
if let Err(e) = self.set_up_work_dir(PathBuf::from(&work_dir)) {
|
||||
return Err(ReturnData {
|
||||
code: ExitCode::FilesystemError,
|
||||
msg: e,
|
||||
})
|
||||
},
|
||||
};
|
||||
code: ExitCode::FilesystemError,
|
||||
});
|
||||
}
|
||||
common::verbose(
|
||||
self.verbose,
|
||||
2,
|
||||
format!("Created working directory: {}", &path_str),
|
||||
format!("Created working directory: {}", work_dir),
|
||||
);
|
||||
|
||||
let repo_name = match &cfg.config.from.split("/").last() {
|
||||
Some(split) => split.to_string(),
|
||||
None => {
|
||||
|
@ -377,7 +378,7 @@ impl Refractr {
|
|||
fo.remote_callbacks(cb);
|
||||
()
|
||||
},
|
||||
Err(e) => common::error(
|
||||
Err(e) => common::error_quit(
|
||||
format!("error setting up ssh: {}", e),
|
||||
ExitCode::ConfigError,
|
||||
),
|
||||
|
@ -386,7 +387,7 @@ impl Refractr {
|
|||
fo.download_tags(git2::AutotagOption::All);
|
||||
builder.fetch_options(fo);
|
||||
|
||||
let repo_dir = format!("{}{}{}", &path_str, MAIN_SEPARATOR_STR, repo_name);
|
||||
let repo_dir = format!("{}{}{}", &work_dir, MAIN_SEPARATOR_STR, repo_name);
|
||||
common::verbose(
|
||||
self.verbose,
|
||||
1,
|
||||
|
@ -396,7 +397,7 @@ impl Refractr {
|
|||
Ok(repo) => repo,
|
||||
Err(e) => {
|
||||
if e.code() != ErrorCode::Exists {
|
||||
common::error(
|
||||
common::error_quit(
|
||||
format!("failed to clone repo to {}: {}", repo_dir, e),
|
||||
ExitCode::FilesystemError,
|
||||
);
|
||||
|
@ -436,7 +437,7 @@ impl Refractr {
|
|||
&cfg.config.git.ssh_identity_file,
|
||||
self.strict.clone(),
|
||||
) {
|
||||
common::error(
|
||||
common::error_quit(
|
||||
format!("failed to fetch repo {}: {}", cfg.config.from, e),
|
||||
ExitCode::FetchError,
|
||||
);
|
||||
|
@ -463,7 +464,7 @@ impl Refractr {
|
|||
};
|
||||
|
||||
if let Err(e) = self.set_up_refs(&repo, &cfg.config.branches) {
|
||||
common::error(
|
||||
common::error_quit(
|
||||
format!("failed to set up refs: {}", e),
|
||||
ExitCode::RepositoryError,
|
||||
);
|
||||
|
@ -478,8 +479,9 @@ impl Refractr {
|
|||
})
|
||||
},
|
||||
};
|
||||
|
||||
if let Err(e) = self.push_remotes(&cfg.config, &repo, &remotes) {
|
||||
common::error(e, ExitCode::PushError);
|
||||
common::error_quit(e, ExitCode::PushError);
|
||||
}
|
||||
|
||||
if cfg.config.schedule.enabled {
|
||||
|
@ -489,9 +491,18 @@ impl Refractr {
|
|||
cfg: cfg.config,
|
||||
ssh,
|
||||
});
|
||||
if !work_dirs.contains(&work_dir) {
|
||||
work_dirs.push(work_dir);
|
||||
}
|
||||
} else {
|
||||
if let Err(e) = self.clean(vec![work_dir]) {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// end for
|
||||
|
||||
let mut result = Ok(());
|
||||
if loop_repos.len() >= 1 {
|
||||
common::verbose(
|
||||
self.verbose,
|
||||
|
@ -501,7 +512,7 @@ impl Refractr {
|
|||
loop_repos.len()
|
||||
),
|
||||
);
|
||||
return self.looper(loop_repos);
|
||||
result = self.looper(loop_repos);
|
||||
} else {
|
||||
common::verbose(
|
||||
self.verbose,
|
||||
|
@ -510,6 +521,13 @@ impl Refractr {
|
|||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if !self.persist {
|
||||
match result {
|
||||
Ok(()) => return self.clean(work_dirs),
|
||||
Err(_) => result = self.clean(work_dirs),
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue