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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -585,6 +593,26 @@ name = "serde"
|
||||||
version = "1.0.71"
|
version = "1.0.71"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.1.3"
|
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 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-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 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 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 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 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 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 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.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 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"
|
"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"
|
lazy_static = "1.1"
|
||||||
notify = "4.0"
|
notify = "4.0"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
serde_json = "1.0"
|
||||||
structopt = "0.2"
|
structopt = "0.2"
|
||||||
toml = "0.4"
|
toml = "0.4"
|
||||||
walkdir = "2.2"
|
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 builder;
|
||||||
mod script;
|
|
||||||
|
|
||||||
use failure::Error;
|
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::builder::*;
|
||||||
pub use self::script::*;
|
|
||||||
|
|
||||||
pub trait Handler: Send + Sync {
|
pub struct Handler {
|
||||||
fn handle(&self, &Request<Body>) -> Result<Response<Body>, Error>;
|
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::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::slice::Iter;
|
||||||
|
|
||||||
use failure::{err_msg, Error};
|
use failure::{err_msg, Error};
|
||||||
use hyper::{Body, Request, Response};
|
use hyper::{Body, Request, Response};
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
use Handler;
|
||||||
|
|
||||||
pub struct Hook {
|
pub struct Hook {
|
||||||
handler_type: String,
|
name: String,
|
||||||
|
handlers: Vec<Handler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hook {
|
impl Hook {
|
||||||
pub fn from(config: &Value) -> Result<Self, Error> {
|
pub fn from(name: impl Into<String>, config: &Value) -> Result<Self, Error> {
|
||||||
let handler_type = config
|
let name = name.into();
|
||||||
.get("type")
|
let handlers = config
|
||||||
.ok_or(err_msg("Missing field 'type'"))?
|
.get("handlers")
|
||||||
.as_str()
|
.ok_or(err_msg("No 'handlers' found."))?
|
||||||
.ok_or(err_msg("Field 'type' is not a string"))?
|
.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();
|
.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> {
|
pub fn handle(&self, payload: &Request<Body>) -> Result<Response<Body>, Error> {
|
||||||
Ok(Response::new(Body::from("lol")))
|
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
|
//! # 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]
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_json;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate notify;
|
extern crate notify;
|
||||||
|
@ -35,8 +17,6 @@ pub mod handlers;
|
||||||
pub mod hook;
|
pub mod hook;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{mpsc, Mutex};
|
use std::sync::{mpsc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
@ -48,7 +28,6 @@ use hyper::service::service_fn_ok;
|
||||||
use hyper::{Body, Request, Response, Server};
|
use hyper::{Body, Request, Response, Server};
|
||||||
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use toml::Value;
|
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub use handlers::Handler;
|
pub use handlers::Handler;
|
||||||
|
@ -84,10 +63,15 @@ fn service_fn(req: &Request<Body>) -> Result<Response<Body>, Error> {
|
||||||
.ok_or(err_msg("Missing name"))?
|
.ok_or(err_msg("Missing name"))?
|
||||||
.as_str();
|
.as_str();
|
||||||
let hooks = HOOKS.lock().unwrap();
|
let hooks = HOOKS.lock().unwrap();
|
||||||
let handler = hooks
|
let hook = hooks
|
||||||
.get(name)
|
.get(name)
|
||||||
.ok_or(err_msg(format!("Hook '{}' doesn't exist", 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> {
|
fn service_fn_wrapper(req: Request<Body>) -> Response<Body> {
|
||||||
|
@ -109,12 +93,36 @@ where
|
||||||
{
|
{
|
||||||
let mut handlers = HANDLERS.lock().unwrap();
|
let mut handlers = HANDLERS.lock().unwrap();
|
||||||
handlers.clear();
|
handlers.clear();
|
||||||
handlers.insert("github".to_owned(), Box::new(handlers::GithubHandler::new()));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut hooks = HOOKS.lock().unwrap();
|
let mut hooks = HOOKS.lock().unwrap();
|
||||||
hooks.clear();
|
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