Repositories

grarr

(mirrored on github)

Modified src/error.rs

@@ -1,12 +1,13 @@
use std::error;
use std::fmt;
use std::borrow::{ Cow, Borrow };
use git2;
#[derive(Debug)]
pub enum Error {
MissingExtension,
MissingPathComponent,
String(&'static str),
String(Cow<'static, str>),
Git(git2::Error),
}
@@ -15,7 +16,7 @@ impl error::Error for Error {
match *self {
Error::MissingExtension => "Missing request extension",
Error::MissingPathComponent => "Missing path component",
Error::String(s) => s,
Error::String(ref s) => s.borrow(),
Error::Git(ref e) => e.description(),
}
}
@@ -38,6 +39,12 @@ impl From<git2::Error> for Error {
impl From<&'static str> for Error {
fn from(s: &'static str) -> Error {
Error::String(s)
Error::String(s.into())
}
}
impl From<String> for Error {
fn from(s: String) -> Error {
Error::String(s.into())
}
}

Modified src/handler/base.rs

@@ -1,11 +1,12 @@
pub use std::borrow::Cow;
pub use iron::{ status, IronResult, IronError };
pub use iron::headers::EntityTag;
pub use iron::method::Method;
pub use iron::middleware::Handler;
pub use iron::modifiers::Redirect;
pub use iron::request::Request;
pub use iron::response::Response;
pub use iron::{ status, Url, IronResult, IronError };
pub use router::Router;
pub use error::Error;

Added src/handler/blob.rs

@@ -0,0 +1,54 @@
use super::base::*;
use super::tree_entry;
use git2;
use std::path::Path;
#[derive(Clone)]
pub struct Blob;
impl Handler for Blob {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let router = itry!(req.extensions.get::<Router>().ok_or(Error::MissingExtension), status::InternalServerError);
let context = itry!(req.extensions.get::<RepositoryContext>().ok_or(Error::MissingExtension), status::InternalServerError);
let path = router.find("path").unwrap_or("");
let entry = try!(tree_entry::get_tree_entry(&context, path));
let referenced_commit = itry!(context.referenced_commit(), status::NotFound);
let id = referenced_commit.commit.id();
match entry.entry.kind() {
Some(git2::ObjectType::Blob) => {
Html {
render: RepositoryWrapper(
&context,
&render::Blob(
&entry.parent,
Path::new(path),
itry!(entry.entry.as_blob().ok_or(Error::from("Wat?")), status::InternalServerError),
&referenced_commit)),
etag: Some(EntityTag::weak(versioned_sha1!(&id))),
req: req,
}.into()
},
Some(git2::ObjectType::Tree) => {
let new_url = Url::parse(&*req.url.to_string().replace("blob", "tree")).unwrap();
Ok(Response::with((status::TemporaryRedirect, Redirect(new_url))))
},
other => {
Err(IronError::new(Error::from(format!("Can only handle blobs and trees, not {:?}", other)), status::InternalServerError))
},
}
}
}
impl Route for Blob {
fn method() -> Method {
Method::Get
}
fn routes() -> Vec<Cow<'static, str>> {
vec![
"/blob/:ref".into(),
"/blob/:ref/*path".into(),
]
}
}

Modified src/handler/mod.rs

@@ -18,6 +18,8 @@ pub mod error;
mod tree_entry;
mod settings;
mod about;
mod tree;
mod blob;
pub use self::avatar::Avatars;
pub use self::review::Review;
@@ -26,7 +28,8 @@ pub use self::commit::Commit;
pub use self::commits::Commits;
pub use self::repository::Repository;
pub use self::repositories::Repositories;
pub use self::tree_entry::TreeEntry;
pub use self::tree::Tree;
pub use self::blob::Blob;
pub use self::register::Register;
pub use self::statics::Static;

Modified src/handler/repository.rs

@@ -8,7 +8,7 @@ impl Handler for Repository {
let context = itry!(req.extensions.get::<RepositoryContext>().ok_or(Error::MissingExtension), status::InternalServerError);
let head_ref = itry!(context.repository.head(), status::InternalServerError);
let resolved_head = itry!(head_ref.resolve(), status::InternalServerError);
let head_id = itry!(resolved_head.target().ok_or(Error::String("Couldn't resolve head")), status::InternalServerError);
let head_id = itry!(resolved_head.target().ok_or(Error::from("Couldn't resolve head")), status::InternalServerError);
Html {
render: RepositoryWrapper(&context, &render::Repository(&context.repository, &head_id)),
etag: Some(EntityTag::weak(versioned_sha1!(head_id.as_bytes()))),

Modified src/handler/settings.rs

@@ -1,7 +1,6 @@
use super::base::*;
use settings;
use iron::Plugin;
use iron::modifiers::Redirect;
use params::{ Map, Params, Value };
#[derive(Clone)]

Modified src/handler/statics.rs

@@ -51,7 +51,7 @@ impl Handler for Static {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let router = itry!(req.extensions.get::<Router>().ok_or(Error::MissingExtension), status::InternalServerError);
let path = Path::new(itry!(router.find("path").ok_or(Error::MissingPathComponent), status::InternalServerError));
let File(mime, entity_tag, buffer) = itry!(self.find_file(path).ok_or(Error::String("Static file not found")), status::NotFound);
let File(mime, entity_tag, buffer) = itry!(self.find_file(path).ok_or(Error::from("Static file not found")), status::NotFound);
let cache_headers = utils::cache_headers_for(&entity_tag, Duration::from_secs(86400));
if req.cache_matches(&entity_tag) {
return Ok(Response::with((status::NotModified, cache_headers)));

Added src/handler/tree.rs

@@ -0,0 +1,54 @@
use super::base::*;
use super::tree_entry;
use git2;
use std::path::Path;
#[derive(Clone)]
pub struct Tree;
impl Handler for Tree {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let router = itry!(req.extensions.get::<Router>().ok_or(Error::MissingExtension), status::InternalServerError);
let context = itry!(req.extensions.get::<RepositoryContext>().ok_or(Error::MissingExtension), status::InternalServerError);
let path = router.find("path").unwrap_or("");
let entry = try!(tree_entry::get_tree_entry(&context, path));
let referenced_commit = itry!(context.referenced_commit(), status::NotFound);
let id = referenced_commit.commit.id();
match entry.entry.kind() {
Some(git2::ObjectType::Tree) => {
Html {
render: RepositoryWrapper(
&context,
&render::Tree(
&entry.parent,
Path::new(path),
itry!(entry.entry.as_tree().ok_or(Error::from("Wat?")), status::InternalServerError),
&referenced_commit)),
etag: Some(EntityTag::weak(versioned_sha1!(&id))),
req: req,
}.into()
},
Some(git2::ObjectType::Blob) => {
let new_url = Url::parse(&*req.url.to_string().replace("tree", "blob")).unwrap();
Ok(Response::with((status::TemporaryRedirect, Redirect(new_url))))
},
other => {
Err(IronError::new(Error::from(format!("Can only handle blobs and trees, not {:?}", other)), status::InternalServerError))
},
}
}
}
impl Route for Tree {
fn method() -> Method {
Method::Get
}
fn routes() -> Vec<Cow<'static, str>> {
vec![
"/tree/:ref".into(),
"/tree/:ref/*path".into(),
]
}
}

Modified src/handler/tree_entry.rs

@@ -1,47 +1,28 @@
use super::base::*;
use iron::{ status, IronResult };
use std::path::Path;
use repository_context::RepositoryContext;
use git2;
#[derive(Clone)]
pub struct TreeEntry;
impl Handler for TreeEntry {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let router = itry!(req.extensions.get::<Router>().ok_or(Error::MissingExtension), status::InternalServerError);
let context = itry!(req.extensions.get::<RepositoryContext>().ok_or(Error::MissingExtension), status::InternalServerError);
let entry_path = router.find("path").unwrap_or("");
let referenced_commit = itry!(context.referenced_commit(), status::NotFound);
let tree = itry!(referenced_commit.commit.tree(), status::InternalServerError);
let obj;
let entry;
if entry_path == "" {
entry = tree.as_object();
} else {
let tree_entry = itry!(tree.get_path(Path::new(entry_path)), status::NotFound);
obj = itry!(tree_entry.to_object(&context.repository), status::InternalServerError);
entry = &obj;
}
let id = referenced_commit.commit.id();
let idstr = format!("{}", id);
let reff = referenced_commit.reference.as_ref().and_then(|r| r.shorthand()).unwrap_or(&*idstr);
let parent = "/".to_owned() + &context.requested_path.to_string_lossy() + "/tree/" + reff;
Html {
render: RepositoryWrapper(&context, &render::TreeEntry(&parent, Path::new(entry_path), entry, &referenced_commit)),
etag: Some(EntityTag::weak(versioned_sha1!(&id))),
req: req,
}.into()
}
pub struct TreeEntryContext<'a> {
pub entry: git2::Object<'a>,
pub parent: String,
}
impl Route for TreeEntry {
fn method() -> Method {
Method::Get
}
fn routes() -> Vec<Cow<'static, str>> {
vec![
"/tree/:ref".into(),
"/tree/:ref/*path".into(),
]
}
pub fn get_tree_entry<'a>(context: &'a RepositoryContext, path: &str) -> IronResult<TreeEntryContext<'a>> {
let referenced_commit = itry!(context.referenced_commit(), status::NotFound);
let tree = itry!(referenced_commit.commit.tree(), status::InternalServerError);
let entry = if path == "" {
itry!(context.repository.find_object(tree.id(), Some(git2::ObjectType::Tree)))
} else {
let tree_entry = itry!(tree.get_path(Path::new(path)), status::NotFound);
itry!(tree_entry.to_object(&context.repository), status::InternalServerError)
};
let id = referenced_commit.commit.id();
let idstr = format!("{}", id);
let reff = referenced_commit.reference.as_ref().and_then(|r| r.shorthand()).unwrap_or(&*idstr);
let parent = "/".to_owned() + &context.requested_path.to_string_lossy() + "/tree/" + reff;
Ok(TreeEntryContext {
entry: entry,
parent: parent,
})
}

Modified src/main.rs

@@ -85,8 +85,8 @@ fn main() {
.register(handler::Settings)
.register(handler::SettingsPost)
.register(handler::About)
// .register(inject_repository_context(&config.repos.root, handler::Tree))
.register(inject_repository_context(&config.repos.root, handler::TreeEntry))
.register(inject_repository_context(&config.repos.root, handler::Tree))
.register(inject_repository_context(&config.repos.root, handler::Blob))
.register(statics![
prefix: "./static/";
"./static/js/highlight.js",

Modified src/render/mod.rs

@@ -36,7 +36,7 @@ pub use self::commit::{ Commit, Commits };
pub use self::repository::{ Repository, Repositories, RepositoryHeader };
pub use self::repository_wrapper::{ RepositoryWrapper };
pub use self::error::{ Error };
pub use self::tree::{ TreeEntry };
pub use self::tree::{ TreeEntry, Tree, Blob };
pub use self::wrapper::Wrapper;
pub use self::signature::Signature;
pub use self::diff::DiffCommit;

Modified src/render/tree.rs

@@ -146,3 +146,7 @@ impl<'a> super::repository_wrapper::RepositoryTab for &'a TreeEntry<'a> {
impl<'a> super::repository_wrapper::RepositoryTab for &'a Tree<'a> {
fn tab() -> super::repository_wrapper::Tab { super::repository_wrapper::Tab::Files }
}
impl<'a> super::repository_wrapper::RepositoryTab for &'a Blob<'a> {
fn tab() -> super::repository_wrapper::Tab { super::repository_wrapper::Tab::Files }
}