"pulldown-cmark 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"router 0.1.0 (git+https://github.com/Nemo157/router?rev=reverse_priority)",
"rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
source = "registry+https://github.com/rust-lang/crates.io-index"
use std::{ env, ffi, io, fmt };
use std::borrow::ToOwned;
use std::path::{ Path, PathBuf };
use rustc_serialize::{ Decoder, Decodable, Encoder, Encodable };
#[derive(Debug, RustcDecodable, RustcEncodable)]
// Cannot derive decode/encode as PathBuf by default uses a [u8/u16] for storage...
#[derive(Debug, RustcDecodable, RustcEncodable)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
Parse(Vec<toml::ParserError>),
Decode(toml::DecodeError),
pub fn load<S: AsRef<ffi::OsStr> + ?Sized>(from: Option<&S>) -> Result<Config, Error> {
let path = if let Some(path) = from.map(Path::new) {
try!(path.canonicalize())
try!(try!(env::current_dir()).canonicalize())
load_file(&path).and_then(|mut config| { config.repos.root = try!(config.repos.root.canonicalize()); Ok(config) })
fn load_file(path: &Path) -> Result<Config, Error> {
let text = try!(read_file(path));
let value = try!(text.parse::<toml::Value>());
Config::decode(&mut toml::Decoder::new(value)).map_err(From::from)
fn read_file(path: &Path) -> io::Result<String> {
let mut text = String::new();
let mut file = try!(File::open(path));
try!(file.read_to_string(&mut text));
impl<'a> From<&'a str> for Error {
fn from(s: &'a str) -> Error {
impl From<Vec<toml::ParserError>> for Error {
fn from(v: Vec<toml::ParserError>) -> Error {
impl From<toml::DecodeError> for Error {
fn from(error: toml::DecodeError) -> Error {
impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
impl fmt::Display for Error {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
Error::IO(ref error) => write!(w, "IO Error:\n{}", error),
Error::Parse(ref errors) => {
try!(write!(w, "Parse Error:\n"));
try!(write!(w, "{}", error));
Error::Decode(ref error) => write!(w, "Decode Error:\n{}", error),
Error::Str(ref s) => write!(w, "Misc Error:\n{}", s),
impl Decodable for Repos {
fn decode<D: Decoder>(d: &mut D) -> Result<Repos, D::Error> {
d.read_struct("repos", 1, |d| {
root: try!(d.read_struct_field("root", 0, |d| d.read_str().map(From::from))),
impl Encodable for Repos {
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
e.emit_struct("repos", 1, |e| {
e.emit_struct_field("root", 0, |e| e.emit_str(&self.root.to_string_lossy()))
extern crate rustc_serialize;
mod repository_extension;
include!(concat!(env!("OUT_DIR"), "/version.rs"));
let root = env::args().nth(1).unwrap();
let config = match config::load(env::args_os().nth(1).as_ref()) {
println!("Failed to load config:\n{}", err);
println!("Running with config");
println!("===================");
println!("{}", toml::encode_str(&config));
println!("===================");
let mut router = Router::new();
.register(inject_repository_context(Path::new(&root), handler::Review))
.register(inject_repository_context(Path::new(&root), handler::Reviews))
.register(inject_repository_context(Path::new(&root), handler::Commit))
.register(inject_repository_context(Path::new(&root), handler::Commits))
.register(inject_repository_context(Path::new(&root), handler::Repository))
.register(handler::Repositories { root: root.clone().into() })
.register(inject_repository_context(&config.repos.root, handler::Review))
.register(inject_repository_context(&config.repos.root, handler::Reviews))
.register(inject_repository_context(&config.repos.root, handler::Commit))
.register(inject_repository_context(&config.repos.root, handler::Commits))
.register(inject_repository_context(&config.repos.root, handler::Repository))
.register(handler::Repositories { root: config.repos.root.clone() })
.register(handler::Settings)
.register(handler::SettingsPost)
.register(handler::About)
// .register(inject_repository_context(Path::new(&root), handler::Tree))
.register(inject_repository_context(Path::new(&root), handler::TreeEntry))
// .register(inject_repository_context(&config.repos.root, handler::Tree))
.register(inject_repository_context(&config.repos.root, handler::TreeEntry))
"./static/js/highlight.js",
"./static/fonts/fontawesome-webfont.woff2",
.register(handler::Avatars::new(handler::avatar::Options {
cache_time_to_live: Duration::minutes(1),
enable_gravatar: config.avatars.gravatar.enable,
enable_cache: config.avatars.cache.enable,
cache_capacity: config.avatars.cache.capacity,
cache_time_to_live: Duration::seconds(config.avatars.cache.ttl_seconds),
let (logger_before, logger_after) = Logger::new(None);