lohr: add default and additional remotes
Co-authored-by: Antoine Martin <antoine@alarsyo.net>
This commit is contained in:
parent
7c21d65920
commit
295a28bab4
5 changed files with 121 additions and 19 deletions
65
src/job.rs
65
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,7 +92,9 @@ impl Job {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_remotes(&self) -> anyhow::Result<String> {
|
||||
/// Can return Ok(None) if the .lohr file didn't exist, but no significant error occured
|
||||
fn read_remotes_from_lohr_file(&self) -> anyhow::Result<Option<Vec<RepoUrl>>> {
|
||||
// try to read .lohr file from bare repo (hence the git show sorcery)
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(format!("{}", self.local_path.as_ref().unwrap().display()))
|
||||
|
|
@ -101,24 +104,56 @@ impl Job {
|
|||
|
||||
if !output.status.success() {
|
||||
let error = str::from_utf8(&output.stderr)?;
|
||||
let code = output
|
||||
.status
|
||||
.code()
|
||||
.unwrap_or_else(|| output.status.signal().unwrap());
|
||||
|
||||
bail!(
|
||||
"couldn't read .lohr file from repo {}: exit code {}, stderr:\n{}",
|
||||
self.repo.full_name,
|
||||
code,
|
||||
error
|
||||
);
|
||||
// this error case is okay, .lohr just doesn't exist
|
||||
if error.contains("does not exist in 'HEAD'") {
|
||||
return Ok(None);
|
||||
} else {
|
||||
let code = output
|
||||
.status
|
||||
.code()
|
||||
.unwrap_or_else(|| output.status.signal().unwrap());
|
||||
|
||||
bail!(
|
||||
"couldn't read .lohr file from repo {}: exit code {}, stderr:\n{}",
|
||||
self.repo.full_name,
|
||||
code,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(String::from_utf8(output.stdout)?)
|
||||
let output = String::from_utf8(output.stdout)?;
|
||||
|
||||
Ok(Some(output.lines().map(String::from).collect()))
|
||||
}
|
||||
|
||||
fn update_mirrors(&self) -> anyhow::Result<()> {
|
||||
for remote in self.get_remotes()?.lines() {
|
||||
fn get_remotes(&self, config: &GlobalSettings) -> anyhow::Result<Vec<RepoUrl>> {
|
||||
let local_path = self.local_path.as_ref().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
|
||||
};
|
||||
|
||||
// use either .lohr file or default remotes from config
|
||||
let mut remotes = match self.read_remotes_from_lohr_file()? {
|
||||
Some(remotes) if !remotes.is_empty() => remotes,
|
||||
_ => config.default_remotes.iter().map(stem_to_repo).collect(),
|
||||
};
|
||||
|
||||
// additional remotes
|
||||
remotes.append(&mut config.additional_remotes.iter().map(stem_to_repo).collect());
|
||||
|
||||
Ok(remotes)
|
||||
}
|
||||
|
||||
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 +183,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);
|
||||
|
|
|
|||
27
src/main.rs
27
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<Sender<Job>>);
|
||||
|
||||
#[post("/", data = "<payload>")]
|
||||
|
|
@ -34,29 +38,44 @@ fn gitea_webhook(payload: Json<GiteaWebHook>, sender: State<JobSender>) -> Statu
|
|||
Status::Ok
|
||||
}
|
||||
|
||||
fn repo_updater(rx: Receiver<Job>, homedir: PathBuf) {
|
||||
fn repo_updater(rx: Receiver<Job>, 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<GlobalSettings> {
|
||||
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(())
|
||||
}
|
||||
|
|
|
|||
13
src/settings.rs
Normal file
13
src/settings.rs
Normal file
|
|
@ -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<RepoUrl>,
|
||||
/// List of remote stems to use for every repository
|
||||
#[serde(default)]
|
||||
pub additional_remotes: Vec<RepoUrl>,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue