From fdb5c7a9b3b797909ee11dbb8c6de06243762b54 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 15 Aug 2018 21:26:05 +0000 Subject: [PATCH] wtf --- Cargo.lock | 31 ++++++++++++++ Cargo.toml | 3 ++ src/handlers/builder.rs | 1 + src/handlers/git.rs | 20 --------- src/handlers/mod.rs | 19 +++++---- src/handlers/script.rs | 18 -------- src/hook.rs | 93 ++++++++++++++++++----------------------- src/lib.rs | 64 +++++++++++++++------------- 8 files changed, 124 insertions(+), 125 deletions(-) create mode 100644 src/handlers/builder.rs delete mode 100644 src/handlers/git.rs delete mode 100644 src/handlers/script.rs diff --git a/Cargo.lock b/Cargo.lock index 46b81df..88b8b14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,6 +150,9 @@ dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -554,6 +557,11 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ryu" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "same-file" version = "1.0.2" @@ -585,6 +593,26 @@ name = "serde" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "serde_derive" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.1.3" @@ -975,11 +1003,14 @@ dependencies = [ "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "16aa12da69951804cddf5f74d96abcc414a31b064e610dc81e37c1536082f491" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfad05c8854584e5f72fb859385ecdfa03af69c3fd0572f0da2d4c95f060bdb" +"checksum serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "b719c6d5e9f73fbc37892246d5852333f040caa617b8873c6aced84bcb28e7bb" +"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970" diff --git a/Cargo.toml b/Cargo.toml index 1bd2923..9a23e25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,9 @@ hyper = "0.12" lazy_static = "1.1" notify = "4.0" regex = "1.0" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" structopt = "0.2" toml = "0.4" walkdir = "2.2" diff --git a/src/handlers/builder.rs b/src/handlers/builder.rs new file mode 100644 index 0000000..3fd6436 --- /dev/null +++ b/src/handlers/builder.rs @@ -0,0 +1 @@ +pub struct HandlerBuilder {} diff --git a/src/handlers/git.rs b/src/handlers/git.rs deleted file mode 100644 index ac58d5a..0000000 --- a/src/handlers/git.rs +++ /dev/null @@ -1,20 +0,0 @@ -use toml::Value; -use failure::Error; -use hyper::{Body, Request, Response, Method}; - -use handlers::Handler; - -pub struct GithubHandler {} - -impl GithubHandler { - pub fn new() -> Self { - GithubHandler {} - } -} - -impl Handler for GithubHandler { - fn handle(&self, req: &Request) -> Result, Error> { - if req.method() != Method::POST { bail!("Github webhooks should use the POST method.") } - Ok(Response::new(Body::from("Lol"))) - } -} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index baa22d5..a4d24b7 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,12 +1,17 @@ -mod git; -mod script; +mod builder; use failure::Error; -use hyper::{Body, Request, Response}; +use serde_json::Value as JsonValue; +use toml::Value as TomlValue; -pub use self::git::*; -pub use self::script::*; +pub use self::builder::*; -pub trait Handler: Send + Sync { - fn handle(&self, &Request) -> Result, Error>; +pub struct Handler { + pub handle: fn(Result) -> Result, +} + +impl Handler { + pub fn from(config: &TomlValue) -> Result { + bail!("rip") + } } diff --git a/src/handlers/script.rs b/src/handlers/script.rs deleted file mode 100644 index d8be4d6..0000000 --- a/src/handlers/script.rs +++ /dev/null @@ -1,18 +0,0 @@ -use failure::Error; -use hyper::{Body, Request, Response}; - -use handlers::Handler; - -pub struct ScriptHandler {} - -impl ScriptHandler { - pub fn new() -> Self { - ScriptHandler {} - } -} - -impl Handler for ScriptHandler { - fn handle(&self, req: &Request) -> Result, Error> { - Ok(Response::new(Body::from("Lol"))) - } -} diff --git a/src/hook.rs b/src/hook.rs index 746f047..939d52b 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -1,69 +1,58 @@ -use std::collections::HashMap; -use std::path::Path; use std::fs::File; use std::io::Read; +use std::path::Path; +use std::slice::Iter; use failure::{err_msg, Error}; use hyper::{Body, Request, Response}; use toml::Value; -use walkdir::WalkDir; + +use Handler; pub struct Hook { - handler_type: String, + name: String, + handlers: Vec, } impl Hook { - pub fn from(config: &Value) -> Result { - let handler_type = config - .get("type") - .ok_or(err_msg("Missing field 'type'"))? - .as_str() - .ok_or(err_msg("Field 'type' is not a string"))? + pub fn from(name: impl Into, config: &Value) -> Result { + let name = name.into(); + let handlers = config + .get("handlers") + .ok_or(err_msg("No 'handlers' found."))? + .as_array() + .ok_or(err_msg("'handlers' is not an array."))? + .iter() + .map(|value: &Value| Handler::from(value)) + .collect::, _>>()?; + Ok(Hook { name, handlers }) + } + pub fn from_file

(path: P) -> Result + where + P: AsRef, + { + let filename = path + .as_ref() + .file_name() + .ok_or(err_msg("what the fuck bro"))? + .to_str() + .ok_or(err_msg("???"))? .to_owned(); - Ok(Hook { handler_type }) + let mut file = File::open(path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + + let config = contents.parse::()?; + let hook = Hook::from(filename, &config)?; + Ok(hook) + } + pub fn get_name(&self) -> String { + self.name.clone() + } + pub fn iter(&self) -> Iter { + self.handlers.iter() } pub fn handle(&self, payload: &Request) -> Result, Error> { Ok(Response::new(Body::from("lol"))) } } - -pub fn load_from_config

(path: P, hooks: &mut HashMap) where P: AsRef { - let hooks_dir = { - let mut p = path.as_ref().to_path_buf(); - p.push("hooks"); - p - }; - if hooks_dir.exists() { - for entry in WalkDir::new(hooks_dir) { - let path = match entry.as_ref().map(|e| e.path()) { - Ok(path) => path, - _ => continue, - }; - if !path.is_file() { - continue; - } - match (|path: &Path| -> Result<(), Error> { - let filename = path - .file_name() - .ok_or(err_msg("what the fuck bro"))? - .to_str() - .ok_or(err_msg("???"))? - .to_owned(); - let mut file = File::open(path)?; - let mut contents = String::new(); - file.read_to_string(&mut contents)?; - - let config = contents.parse::()?; - let hook = Hook::from(&config)?; - println!("Added hook '{}'", filename); - hooks.insert(filename, hook); - Ok(()) - })(path) - { - Ok(_) => (), - Err(err) => eprintln!("Failed to read config from {:?}: {}", path, err), - } - } - } - -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 7ab9aa6..d5eab04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,29 +1,11 @@ //! # Dip -//! -//! Set up some kind of directory structure like this: -//! -//! ``` -//! root/ -//! - config.toml -//! - hooks/ -//! - website.com -//! ``` -//! -//! where every file in the `hooks` subdirectory is a TOML document of the following format: -//! -//! ```toml -//! # The handler to use. This must match one of the handlers defined in the -//! # handlers directory or one of the builtins such as "github" -//! type = "github" -//! -//! # wip lol -//! ``` -//! -//! Then run the `dip` binary with the option `-d ` where `root` points to the root directory you made above. #[macro_use] extern crate failure; extern crate hyper; +extern crate serde; +#[macro_use] +extern crate serde_json; #[macro_use] extern crate lazy_static; extern crate notify; @@ -35,8 +17,6 @@ pub mod handlers; pub mod hook; use std::collections::HashMap; -use std::fs::File; -use std::io::Read; use std::path::Path; use std::sync::{mpsc, Mutex}; use std::thread; @@ -48,7 +28,6 @@ use hyper::service::service_fn_ok; use hyper::{Body, Request, Response, Server}; use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use regex::Regex; -use toml::Value; use walkdir::WalkDir; pub use handlers::Handler; @@ -84,10 +63,15 @@ fn service_fn(req: &Request) -> Result, Error> { .ok_or(err_msg("Missing name"))? .as_str(); let hooks = HOOKS.lock().unwrap(); - let handler = hooks + let hook = hooks .get(name) .ok_or(err_msg(format!("Hook '{}' doesn't exist", name)))?; - handler.handle(&req) + let req_obj = json!({ + "method": req.method().as_str(), + }); + hook.iter() + .fold(Ok(req_obj), |prev, handler| (handler.handle)(prev)) + .map(|_| Response::new(Body::from("success"))) } fn service_fn_wrapper(req: Request) -> Response { @@ -109,12 +93,36 @@ where { let mut handlers = HANDLERS.lock().unwrap(); handlers.clear(); - handlers.insert("github".to_owned(), Box::new(handlers::GithubHandler::new())); } { let mut hooks = HOOKS.lock().unwrap(); hooks.clear(); - hook::load_from_config(root, &mut hooks); + let hooks_dir = { + let mut p = root.as_ref().to_path_buf(); + p.push("hooks"); + p + }; + if hooks_dir.exists() { + for entry in WalkDir::new(hooks_dir) { + let path = match entry.as_ref().map(|e| e.path()) { + Ok(path) => path, + _ => continue, + }; + if !path.is_file() { + continue; + } + match (|path: &Path| -> Result<(), Error> { + let hook = Hook::from_file(path)?; + let name = hook.get_name(); + hooks.insert(name, hook); + Ok(()) + })(path) + { + Ok(_) => (), + Err(err) => eprintln!("Failed to read config from {:?}: {}", path, err), + } + } + } } }