fn handle(&self, req: &mut Request) -> IronResult<Response> {
let context = itry!(req.extensions.get::<RepositoryContext>().ok_or(Error::MissingExtension), status::InternalServerError);
let commit = itry!(context.commit(), status::NotFound);
let root = "/".to_owned() + &context.requested_path.to_string_lossy();
let root = format!("/{}", context.path);
render: RepositoryWrapper(&context, &render::Commit(&root, &context.repository, &commit)),
etag: Some(EntityTag::weak(versioned_sha1!())),
let commits = itry!(CommitTree::new(&context.repository, &initial_commit, 50), status::InternalServerError);
render: RepositoryWrapper(&context, render::Commits(&("/".to_owned() + context.requested_path.to_str().unwrap()), &referenced_commit, commits)),
render: RepositoryWrapper(&context, render::Commits(&format!("/{}", context.path), &referenced_commit, commits)),
etag: Some(EntityTag::weak(versioned_sha1!(referenced_commit.commit.id().as_bytes()))),
let commit = itry!(router.find("ref").ok_or(Error::MissingPathComponent), status::InternalServerError);
let id = itry!(Oid::from_str(commit), status::BadRequest);
let review = itry!(context.repository.review_for(id), status::NotFound);
let root = "/".to_owned() + &context.requested_path.to_string_lossy();
let root = format!("/{}", context.path);
render: RepositoryWrapper(&context, &render::Review(&root, &review)),
let mut reviews: Vec<_> = context.repository.all_reviews().and_then(|revs| revs.collect()).ok().unwrap_or_default();
reviews.sort_by(|a, b| a.request().timestamp().cmp(&b.request().timestamp()));
let root = "/".to_owned() + &context.requested_path.to_string_lossy();
let root = format!("/{}", context.path);
render: RepositoryWrapper(&context, &render::Reviews(&root, &reviews)),
fn render_once(self, mut w: &mut fmt::Write) -> fmt::Result {
let RepositoryWrapper(context, content) = self;
let path = context.requested_path.to_string_lossy().into_owned();
^super::RepositoryHeader(&path, &context.repository)
^RepositoryWrapperTabs(tab, path, context.repository.head().unwrap().shorthand().unwrap().to_owned())
^super::RepositoryHeader(&context.path, &context.repository)
^RepositoryWrapperTabs(&tab, &context.path, context.repository.head().unwrap().shorthand().unwrap())
RepositoryWrapperTabs(tab: Tab, requested_path: String, head: String) {
RepositoryWrapperTabs(tab: &'a Tab, path: &'a str, head: &'a str) {
div class={ "overview" @if tab == Tab::Overview { " selected" } } { a href={ "/" ^requested_path } { "Overview" } }
div class={ "files" @if tab == Tab::Files { " selected" } } { a href={ "/" ^requested_path "/tree/" ^head } { "Files" } }
div class={ "commits" @if tab == Tab::Commits { " selected" } } { a href={ "/" ^requested_path "/commits/" ^head } { "Commits" } }
div class={ "reviews" @if tab == Tab::Reviews { " selected" } } { a href={ "/" ^requested_path "/reviews" } { "Reviews" } }
div class={ "overview" @if *tab == Tab::Overview { " selected" } } { a href={ "/" ^path } { "Overview" } }
div class={ "files" @if *tab == Tab::Files { " selected" } } { a href={ "/" ^path "/tree/" ^head } { "Files" } }
div class={ "commits" @if *tab == Tab::Commits { " selected" } } { a href={ "/" ^path "/commits/" ^head } { "Commits" } }
div class={ "reviews" @if *tab == Tab::Reviews { " selected" } } { a href={ "/" ^path "/reviews" } { "Reviews" } }
use referenced_commit::ReferencedCommit;
pub struct RepositoryContext {
pub requested_path: PathBuf,
pub repository: git2::Repository,
reference: Option<String>,
impl<H: Handler> Handler for RepositoryContextHandler<H> {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let (requested_path, reference) = {
let (path, reference) = {
let router = itry!(req.extensions.get::<Router>().ok_or(Error::MissingExtension), status::InternalServerError);
(router.find("repo").map(ToOwned::to_owned), router.find("ref").map(ToOwned::to_owned))
let requested_path = PathBuf::from(itry!(requested_path.ok_or(Error::MissingPathComponent), status::InternalServerError));
let full_path = self.canonical_root.join(&requested_path);
let path = itry!(path.ok_or(Error::MissingPathComponent), status::InternalServerError);
let full_path = self.canonical_root.join(&path);
let full_canonical_path = itry!(fs::canonicalize(&full_path), status::NotFound);
if full_path == full_canonical_path {
let repository = itry!(git2::Repository::open(full_canonical_path), status::NotFound);
req.extensions.insert::<RepositoryContext>(RepositoryContext {
requested_path: requested_path,
let canonical_path = itry!(full_canonical_path.strip_prefix(&self.canonical_root), status::InternalServerError).to_owned();
let old_path = requested_path.to_string_lossy();
let new_path = canonical_path.to_string_lossy();
let new_url = Url::parse(&*req.url.to_string().replace(&*old_path, &*new_path)).unwrap();
let new_url = Url::parse(&*req.url.to_string().replace(&*path, &*new_path)).unwrap();
Ok(Response::with((status::TemporaryRedirect, Redirect(new_url))))
use iron::{ status, IronResult };
use repository_context::RepositoryContext;
pub struct TreeEntryContext<'a> {
pub entry: git2::Object<'a>,
pub repo_path: Cow<'a, str>,
pub commit: ReferencedCommit<'a>,
let reff = referenced_commit.reference.as_ref().and_then(|r| r.shorthand()).unwrap_or(&*idstr).to_owned();
repo_path: context.requested_path.to_string_lossy(),
repo_path: &context.path,
entry_path: "/".to_owned() + path,
commit: referenced_commit,