wtf
This commit is contained in:
parent
ea731f78bf
commit
fdb5c7a9b3
8 changed files with 124 additions and 125 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
1
src/handlers/builder.rs
Normal file
1
src/handlers/builder.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub struct HandlerBuilder {}
|
|
@ -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<Body>) -> Result<Response<Body>, Error> {
|
||||
if req.method() != Method::POST { bail!("Github webhooks should use the POST method.") }
|
||||
Ok(Response::new(Body::from("Lol")))
|
||||
}
|
||||
}
|
|
@ -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<Body>) -> Result<Response<Body>, Error>;
|
||||
pub struct Handler {
|
||||
pub handle: fn(Result<JsonValue, Error>) -> Result<JsonValue, Error>,
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub fn from(config: &TomlValue) -> Result<Self, Error> {
|
||||
bail!("rip")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Body>) -> Result<Response<Body>, Error> {
|
||||
Ok(Response::new(Body::from("Lol")))
|
||||
}
|
||||
}
|
93
src/hook.rs
93
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<Handler>,
|
||||
}
|
||||
|
||||
impl Hook {
|
||||
pub fn from(config: &Value) -> Result<Self, Error> {
|
||||
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<String>, config: &Value) -> Result<Self, Error> {
|
||||
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::<Result<Vec<_>, _>>()?;
|
||||
Ok(Hook { name, handlers })
|
||||
}
|
||||
pub fn from_file<P>(path: P) -> Result<Hook, Error>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
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::<Value>()?;
|
||||
let hook = Hook::from(filename, &config)?;
|
||||
Ok(hook)
|
||||
}
|
||||
pub fn get_name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
pub fn iter(&self) -> Iter<Handler> {
|
||||
self.handlers.iter()
|
||||
}
|
||||
pub fn handle(&self, payload: &Request<Body>) -> Result<Response<Body>, Error> {
|
||||
Ok(Response::new(Body::from("lol")))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_from_config<P>(path: P, hooks: &mut HashMap<String, Hook>) where P: AsRef<Path> {
|
||||
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::<Value>()?;
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
64
src/lib.rs
64
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 <root>` 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<Body>) -> Result<Response<Body>, 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<Body>) -> Response<Body> {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue