From 274d1cedb6d0b10bfd7dde82296bf108c1006dc1 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Mon, 29 Mar 2021 19:18:00 +0200 Subject: [PATCH] WIP: lohr: add default and additional remotes Test --- Cargo.lock | 34 +++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/job.rs | 54 ++++++++++++++++++++++++++----------------------- src/main.rs | 27 +++++++++++++++++++++---- src/settings.rs | 13 ++++++++++++ 5 files changed, 100 insertions(+), 29 deletions(-) create mode 100644 src/settings.rs diff --git a/Cargo.lock b/Cargo.lock index ce08ffb..8fcd247 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,6 +231,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + [[package]] name = "filetime" version = "0.2.14" @@ -459,6 +465,12 @@ version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + [[package]] name = "log" version = "0.3.9" @@ -486,6 +498,7 @@ dependencies = [ "rocket", "rocket_contrib", "serde", + "serde_yaml", ] [[package]] @@ -851,6 +864,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +dependencies = [ + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", +] + [[package]] name = "sha2" version = "0.9.3" @@ -1104,6 +1129,15 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yansi" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 14d5b4d..6aabd22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ log = "0.4.14" rocket = "0.4.7" rocket_contrib = { version = "0.4.7", features = [ "json" ] } serde = { version = "1.0.125", features = [ "derive" ] } +serde_yaml = "0.8.17" diff --git a/src/job.rs b/src/job.rs index 25697b5..a4436d1 100644 --- a/src/job.rs +++ b/src/job.rs @@ -8,6 +8,7 @@ use anyhow::bail; use log::info; use crate::gitea::Repository; +use crate::settings::{GlobalSettings, RepoUrl}; pub(crate) struct Job { repo: Repository, @@ -91,34 +92,37 @@ impl Job { Ok(()) } - fn get_remotes(&self) -> anyhow::Result { - let output = Command::new("git") - .arg("-C") - .arg(format!("{}", self.local_path.as_ref().unwrap().display())) - .arg("show") - .arg("HEAD:.lohr") - .output()?; + fn get_remotes(&self, config: &GlobalSettings) -> anyhow::Result> { + let local_path = self.local_path.as_ref().unwrap(); - if !output.status.success() { - let error = str::from_utf8(&output.stderr)?; - let code = output - .status - .code() - .unwrap_or_else(|| output.status.signal().unwrap()); + let stem_to_repo = |stem: &RepoUrl| -> RepoUrl { + let mut res = stem.clone(); + if !res.ends_with('/') { + res.push('/'); + }; + res.push_str(local_path.file_name().unwrap().to_str().unwrap()); + res + }; - bail!( - "couldn't read .lohr file from repo {}: exit code {}, stderr:\n{}", - self.repo.full_name, - code, - error - ); - } + let mut remotes: Vec<_> = { + let mut path_to_dot_lohr = local_path.clone(); + path_to_dot_lohr.push(".lohr"); - Ok(String::from_utf8(output.stdout)?) + if let Ok(contents) = std::fs::read(path_to_dot_lohr.as_path()) { + let contents = String::from_utf8(contents)?; + contents.lines().map(String::from).collect() + } else { + config.default_remotes.iter().map(stem_to_repo).collect() + } + }; + + remotes.append(&mut config.additional_remotes.iter().map(stem_to_repo).collect()); + + Ok(remotes) } - fn update_mirrors(&self) -> anyhow::Result<()> { - for remote in self.get_remotes()?.lines() { + fn update_mirrors(&self, config: &GlobalSettings) -> anyhow::Result<()> { + for remote in &self.get_remotes(config)? { info!("Updating mirror {}:{}...", remote, self.repo.full_name); let output = Command::new("git") @@ -148,7 +152,7 @@ impl Job { Ok(()) } - pub(crate) fn run(&mut self, homedir: &Path) -> anyhow::Result<()> { + pub(crate) fn run(&mut self, homedir: &Path, config: &GlobalSettings) -> anyhow::Result<()> { let local_path = homedir.join(&self.repo.full_name); assert!(local_path.is_absolute()); self.local_path = Some(local_path); @@ -159,6 +163,6 @@ impl Job { self.update_repo()?; } - self.update_mirrors() + self.update_mirrors(config) } } diff --git a/src/main.rs b/src/main.rs index 05e8f20..95f9611 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #![feature(proc_macro_hygiene, decl_macro)] use std::env; +use std::fs::File; use std::path::PathBuf; use std::sync::{ mpsc::{channel, Receiver, Sender}, @@ -19,6 +20,9 @@ use gitea::GiteaWebHook; mod job; use job::Job; +mod settings; +use settings::GlobalSettings; + struct JobSender(Mutex>); #[post("/", data = "")] @@ -32,29 +36,44 @@ fn gitea_webhook(payload: Json, sender: State) -> Statu Status::Ok } -fn repo_updater(rx: Receiver, homedir: PathBuf) { +fn repo_updater(rx: Receiver, homedir: PathBuf, config: GlobalSettings) { loop { let mut job = rx.recv().unwrap(); - if let Err(err) = job.run(&homedir) { + if let Err(err) = job.run(&homedir, &config) { error!("couldn't process job: {}", err); } } } -fn main() { +fn parse_config(mut path: PathBuf) -> anyhow::Result { + path.push("lohr-config"); + path.set_extension("yaml"); + let config = if let Ok(file) = File::open(path.as_path()) { + serde_yaml::from_reader(file)? + } else { + Default::default() + }; + Ok(config) +} + +fn main() -> anyhow::Result<()> { let (sender, receiver) = channel(); let homedir = env::var("LOHR_HOME").unwrap_or_else(|_| "./".to_string()); let homedir: PathBuf = homedir.into(); let homedir = homedir.canonicalize().expect("LOHR_HOME isn't valid!"); + let config = parse_config(homedir.clone())?; + thread::spawn(move || { - repo_updater(receiver, homedir); + repo_updater(receiver, homedir, config); }); rocket::ignite() .mount("/", routes![gitea_webhook]) .manage(JobSender(Mutex::new(sender))) .launch(); + + Ok(()) } diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..bfe7744 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,13 @@ +use serde::Deserialize; + +pub(crate) type RepoUrl = String; // FIXME: probably needs a better type than this + +#[derive(Default, Deserialize)] +pub(crate) struct GlobalSettings { + /// List of remote stems to use when no `.lohr` file is found + #[serde(default)] + pub default_remotes: Vec, + /// List of remote stems to use for every repository + #[serde(default)] + pub additional_remotes: Vec, +}