Handle fetch of updates and push
This commit is contained in:
parent
5484a2742f
commit
db6ba6c6aa
52
src/main.rs
52
src/main.rs
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue