Handle fetch of updates and push

This commit is contained in:
dece 2020-12-07 00:09:53 +01:00
parent 5484a2742f
commit db6ba6c6aa

View file

@ -4,6 +4,8 @@ use std::io::prelude::*;
use std::path; use std::path;
use std::process; use std::process;
const MIRROR_REMOTE_NAME: &str = "mirror";
fn main() { fn main() {
let config_text = match load_file(&path::Path::new("mira.json")) { let config_text = match load_file(&path::Path::new("mira.json")) {
Ok(content) => content, Ok(content) => content,
@ -27,16 +29,9 @@ fn load_file(path: &path::Path) -> Result<String, io::Error> {
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]
struct RootConfig { struct RootConfig {
workspace: String, workspace: String,
auth: serde_json::Value,
configurations: Vec<Configuration>, configurations: Vec<Configuration>,
} }
/// Authentication options, unused at the moment.
#[derive(Debug, serde::Deserialize)]
struct Authentication {
key: Option<String>,
}
/// Server configuration. /// Server configuration.
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]
struct Configuration { struct Configuration {
@ -77,6 +72,7 @@ fn process_root_config(root_config: &RootConfig) -> bool {
enum MirrorResult { enum MirrorResult {
Success, Success,
CloneFailed, CloneFailed,
FetchFailed,
RemotesError, RemotesError,
PushFailed, PushFailed,
} }
@ -103,6 +99,10 @@ fn process_config(config: &Configuration, workspace: &path::Path) -> Result<bool
println!("Failed to clone {}.", mirror.name); println!("Failed to clone {}.", mirror.name);
complete_success = false; complete_success = false;
}, },
Ok(MirrorResult::FetchFailed) => {
println!("Failed to fetch changes for {}.", mirror.name);
complete_success = false;
},
Ok(MirrorResult::RemotesError) => { Ok(MirrorResult::RemotesError) => {
println!("Failed to process remotes for {}.", mirror.name); println!("Failed to process remotes for {}.", mirror.name);
complete_success = false; complete_success = false;
@ -132,19 +132,28 @@ fn mirror_repo(
) -> Result<MirrorResult, io::Error> { ) -> Result<MirrorResult, io::Error> {
let mut repo_path = path.to_path_buf(); let mut repo_path = path.to_path_buf();
repo_path.push(name); repo_path.push(name);
// Ensure the repository is cloned. // Ensure the repository is cloned and up to date.
if !repo_path.exists() { if !repo_path.exists() {
if !clone(src_url, path, name) { if !clone(src_url, path, name) {
return Ok(MirrorResult::CloneFailed) return Ok(MirrorResult::CloneFailed)
} }
} else {
if !fetch(&repo_path) {
return Ok(MirrorResult::FetchFailed)
}
} }
// Ensure the mirror remote is available. // Ensure the mirror remote is available.
let remotes = match get_remotes(&repo_path) { let remotes = match get_remotes(&repo_path) {
Some(remotes) => remotes, Some(remotes) => remotes,
None => return Ok(MirrorResult::RemotesError) None => return Ok(MirrorResult::RemotesError)
}; };
if !remotes.contains(&MIRROR_REMOTE_NAME.to_string()) {
if !add_mirror_remote(&repo_path, dest_url) {
return Ok(MirrorResult::RemotesError)
}
}
// Push to the mirror repo. // Push to the mirror repo.
if !push(&repo_path, dest_url) { if !push(&repo_path) {
return Ok(MirrorResult::PushFailed) return Ok(MirrorResult::PushFailed)
} }
Ok(MirrorResult::Success) Ok(MirrorResult::Success)
@ -152,22 +161,37 @@ fn mirror_repo(
/// Run a git mirror clone command. /// Run a git mirror clone command.
fn clone(url: &str, path: &path::Path, name: &str) -> bool { fn clone(url: &str, path: &path::Path, name: &str) -> bool {
let (success, _) = run_git_command_in(vec!("clone", "--mirror", url, name), path); let args = vec!("clone", "--mirror", url, name);
let (success, _) = run_git_command_in(args, path);
success
}
/// Update a local repository.
fn fetch(path: &path::Path) -> bool {
let (success, _) = run_git_command_in(vec!("fetch"), path);
success success
} }
/// Return a vector of remote names on success. /// Return a vector of remote names on success.
fn get_remotes(path: &path::Path) -> Option<Vec<String>> { fn get_remotes(path: &path::Path) -> Option<Vec<String>> {
let (success, stdout) = run_git_command_in(vec!("remote"), path); let (success, stdout) = run_git_command_in(vec!("remote"), path);
if !success || stdout.is_none() { if !success {
return None return None
} }
Some(stdout.unwrap().split_whitespace().map(|s| s.to_string()).collect()) stdout.and_then(|s| Some(s.split_whitespace().map(|ss| ss.to_string()).collect()))
}
/// Set the mirror remote `url` in the repository at `path`.
fn add_mirror_remote(path: &path::Path, url: &str) -> bool {
let args = vec!("remote", "add", MIRROR_REMOTE_NAME, url);
let (success, _) = run_git_command_in(args, path);
success
} }
/// Run a git mirror push command. /// Run a git mirror push command.
fn push(path: &path::Path, url: &str) -> bool { fn push(path: &path::Path) -> bool {
let (success, _) = run_git_command_in(vec!("push", "--mirror", url), path); let args = vec!("push", "--mirror", MIRROR_REMOTE_NAME);
let (success, _) = run_git_command_in(args, path);
success success
} }