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