You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.0 KiB
112 lines
3.0 KiB
use std::env;
|
|
use std::fs;
|
|
use std::io;
|
|
use std::io::prelude::*;
|
|
use std::path;
|
|
use std::process;
|
|
|
|
fn main() {
|
|
let config_text = match load_file(&path::Path::new("mira.json")) {
|
|
Ok(content) => content,
|
|
Err(e) => { eprintln!("{:?}", e); process::exit(1) }
|
|
};
|
|
let root_config: RootConfig = match serde_json::from_str(&config_text) {
|
|
Ok(config) => config,
|
|
Err(e) => { eprintln!("{:?}", e); process::exit(1) }
|
|
};
|
|
process_root_config(&root_config);
|
|
}
|
|
|
|
fn load_file(path: &path::Path) -> Result<String, io::Error> {
|
|
let mut file = fs::File::open(path)?;
|
|
let mut contents = String::new();
|
|
file.read_to_string(&mut contents)?;
|
|
Ok(contents)
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
struct RootConfig {
|
|
workdir: Option<String>,
|
|
auth: serde_json::Value,
|
|
configurations: Vec<Configuration>,
|
|
}
|
|
|
|
// #[derive(Debug, serde::Deserialize)]
|
|
// struct Authentication {
|
|
// key: Option<String>,
|
|
// }
|
|
|
|
fn process_root_config(root_config: &RootConfig) {
|
|
// Ensure working directory exists and move to it.
|
|
if let Some(workdir) = &root_config.workdir {
|
|
let workdir = path::Path::new(&workdir);
|
|
if !workdir.is_dir() {
|
|
if let Err(e) = fs::create_dir_all(&workdir) {
|
|
eprintln!("Failed to create working directory: {}.", e);
|
|
return
|
|
}
|
|
}
|
|
if let Err(e) = env::set_current_dir(&workdir) {
|
|
eprintln!("Failed to move to working directory: {}.", e);
|
|
return
|
|
}
|
|
}
|
|
// Process each configuration.
|
|
for config in &root_config.configurations {
|
|
process_config(config);
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
struct Configuration {
|
|
name: String,
|
|
mirrors: Vec<Mirror>,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
struct Mirror {
|
|
src: String,
|
|
dest: String,
|
|
}
|
|
|
|
fn process_config(config: &Configuration) {
|
|
println!("Processing config {}.", config.name);
|
|
// Move into the configuration directory.
|
|
let mut config_path = match env::current_dir() {
|
|
Ok(pb) => pb,
|
|
Err(e) => { eprintln!("Current directory is not available: {}.", e); return }
|
|
};
|
|
config_path.push(&config.name);
|
|
if !config_path.is_dir() {
|
|
if let Err(e) = fs::create_dir_all(&config_path) {
|
|
eprintln!("Failed to create working directory: {}.", e);
|
|
return
|
|
}
|
|
}
|
|
if let Err(e) = env::set_current_dir(&config_path) {
|
|
eprintln!("Failed to move to working directory: {}.", e);
|
|
return
|
|
}
|
|
// Mirror each repository in the configuration.
|
|
for mirror in &config.mirrors {
|
|
mirror_repo(&mirror.src, &mirror.dest);
|
|
}
|
|
}
|
|
|
|
fn mirror_repo(src_url: &str, dest_url: &str) -> bool {
|
|
clone(src_url)
|
|
}
|
|
|
|
fn run_git_command(args: Vec<&str>) -> bool {
|
|
let mut command = process::Command::new("git");
|
|
command.args(&args);
|
|
match command.status() {
|
|
Ok(status) => status.success(),
|
|
Err(e) => { eprintln!("Failed to run Git: {}", e); false }
|
|
}
|
|
}
|
|
|
|
fn clone(url: &str) -> bool {
|
|
run_git_command(vec!("clone", "--mirror", url))
|
|
}
|