Repositories

grarr

(mirrored on github)

Modified src/handler/commit.rs

@@ -7,9 +7,8 @@ impl Handler for Commit {
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 = format!("/{}", context.path);
Html {
render: RepositoryWrapper(&context, &render::Commit(&root, &context.repository, &commit)),
render: RepositoryWrapper(&context, &render::Commit(&context, &commit)),
etag: Some(EntityTag::weak(versioned_sha1!())),
req: req,
}.into()

Modified src/handler/commits.rs

@@ -24,7 +24,7 @@ impl Handler for Commits {
};
let commits = itry!(CommitTree::new(&context.repository, &initial_commit, 50), status::InternalServerError);
Html {
render: RepositoryWrapper(&context, render::Commits(&format!("/{}", context.path), &referenced_commit, commits)),
render: RepositoryWrapper(&context, render::Commits(&context, &referenced_commit, commits)),
etag: Some(EntityTag::weak(versioned_sha1!(referenced_commit.commit.id().as_bytes()))),
req: req,
}.into()

Modified src/referenced_commit.rs

@@ -1,6 +1,16 @@
use std::borrow::Cow;
use git2;
pub struct ReferencedCommit<'a> {
pub commit: git2::Commit<'a>,
pub reference: Option<git2::Reference<'a>>,
}
impl<'a> ReferencedCommit<'a> {
pub fn shorthand_or_id(&self) -> Cow<str> {
match self.reference.as_ref().and_then(|r| r.shorthand()) {
Some(reff) => reff.into(),
None => self.commit.id().to_string().into(),
}
}
}

Modified src/render/commit.rs

@@ -5,6 +5,7 @@ use maud_pulldown_cmark::Markdown;
use commit_tree;
use chrono::naive::datetime::NaiveDateTime;
use referenced_commit::ReferencedCommit;
use repository_context::RepositoryContext;
use super::reference;
fn summary<'a>(commit: &'a git2::Commit<'a>) -> Option<&'a str> {
@@ -18,13 +19,13 @@ fn non_summary<'a>(commit: &'a git2::Commit<'a>) -> Option<&'a str> {
}
renderers! {
CommitStub(root: &'a str, commit: &'a git2::Commit<'a>) {
CommitStub(context: &'a RepositoryContext, commit: &'a git2::Commit<'a>) {
div.block {
^CommitHeader(root, commit)
^CommitHeader(context, commit)
}
}
CommitHeader(root: &'a str, commit: &'a git2::Commit<'a>) {
CommitHeader(context: &'a RepositoryContext, commit: &'a git2::Commit<'a>) {
div.block-header {
div.row {
@if commit.author().email() == commit.committer().email() {
@@ -43,7 +44,7 @@ renderers! {
}
div.column {
div {
a href={ ^root "/commit/" ^commit.id() } {
a href={ "/" ^context.path "/commit/" ^commit.id() } {
^(super::reference::Commit(commit))
" "
@match summary(commit) {
@@ -75,9 +76,9 @@ renderers! {
}
}
CommitDetails(root: &'a str, commit: &'a git2::Commit<'a>) {
CommitDetails(context: &'a RepositoryContext, commit: &'a git2::Commit<'a>) {
div.commit.block {
^CommitHeader(root, commit)
^CommitHeader(context, commit)
@if let Some(non_summary) = non_summary(commit) {
@if !non_summary.is_empty() {
div.block-details.message {
@@ -88,21 +89,19 @@ renderers! {
}
}
Commit(root: &'a str, repo: &'a git2::Repository, commit: &'a git2::Commit<'a>) {
^CommitDetails(root, commit)
^super::DiffCommit(repo, commit)
Commit(context: &'a RepositoryContext, commit: &'a git2::Commit<'a>) {
^CommitDetails(context, commit)
^super::DiffCommit(context, commit)
}
NextPage(root: &'a str, commit: &'a ReferencedCommit<'a>, next: &'a Option<&'a git2::Commit<'a>>) {
NextPage(context: &'a RepositoryContext, commit: &'a ReferencedCommit<'a>, next: &'a Option<&'a git2::Commit<'a>>) {
div.block div.block-header.row {
div.column.fixed {
a href={
^root
"/"
^context.path
"/commits/"
@match commit.reference.as_ref().and_then(|r| r.shorthand()) {
Some(ref reff) => ^reff,
None => ^commit.commit.id()
}
^commit.shorthand_or_id()
} {
"Back to beginning (" ^reference::Commit(&commit.commit) ")"
}
@@ -111,12 +110,10 @@ renderers! {
@if let Some(ref next) = *next {
div.column.fixed {
a.float-right href={
^root
"/"
^context.path
"/commits/"
@match commit.reference.as_ref().and_then(|r| r.shorthand()) {
Some(ref reff) => ^reff,
None => ^commit.commit.id()
}
^commit.shorthand_or_id()
"?start=" ^next.id()
} {
"Next page (" ^reference::Commit(next) ")"
@@ -127,10 +124,10 @@ renderers! {
}
}
pub struct Commits<'repo, 'a>(pub &'a str, pub &'a ReferencedCommit<'a>, pub commit_tree::CommitTree<'repo>);
pub struct Commits<'repo, 'a>(pub &'a RepositoryContext, pub &'a ReferencedCommit<'a>, pub commit_tree::CommitTree<'repo>);
impl<'repo, 'a> RenderOnce for Commits<'repo, 'a> {
fn render_once(self, mut w: &mut fmt::Write) -> fmt::Result {
let Commits(root, commit, mut commits) = self;
let Commits(context, commit, mut commits) = self;
let first = commits.next();
let mut id = 0;
html!(w, {
@@ -145,35 +142,35 @@ impl<'repo, 'a> RenderOnce for Commits<'repo, 'a> {
}
}
}
^CommitStub(root, &first)
^CommitStub(context, &first)
@if !sub.is_empty() {
div.subtree {
input.expander disabled?=(sub.len() == 1) id={ "commits-expander-" ^id } type="checkbox" checked? { }
label for={ "commits-expander-" ^id } { i.fa.fa-fw.chevron {} }
^CommitTree(root, &mut sub, &mut id)
^CommitTree(context, &mut sub, &mut id)
}
}
^CommitTree(root, &mut commits, &mut id)
^NextPage(root, commit, &commits.next_after())
^CommitTree(context, &mut commits, &mut id)
^NextPage(context, commit, &commits.next_after())
}
})
}
}
pub struct CommitTree<'a, 'repo: 'a>(pub &'a str, pub &'a mut commit_tree::CommitTree<'repo>, pub &'a mut u32);
pub struct CommitTree<'a, 'repo: 'a>(pub &'a RepositoryContext, pub &'a mut commit_tree::CommitTree<'repo>, pub &'a mut u32);
impl<'repo, 'a> RenderOnce for CommitTree<'repo, 'a> {
fn render_once(self, mut w: &mut fmt::Write) -> fmt::Result {
let CommitTree(root, commits, id) = self;
let CommitTree(context, commits, id) = self;
*id = *id + 1;
html!(w, {
div.commits {
@for (commit, mut sub) in commits {
^CommitStub(root, &commit)
^CommitStub(context, &commit)
@if !sub.is_empty() {
div.subtree {
input.expander disabled?=(sub.len() == 1) id={ "commits-expander-" ^id } type="checkbox" checked? { }
label for={ "commits-expander-" ^id } { i.fa.fa-fw.chevron {} }
^CommitTree(root, &mut sub, id)
^CommitTree(context, &mut sub, id)
}
}
}

Modified src/render/compare.rs

@@ -20,14 +20,14 @@ impl<'r> Render for Compare<'r> {
div.block-header h3 { "Commits" }
div.block-details {
@for commit in &self.commits {
^super::CommitStub(&("/".to_owned() + &self.context.path), commit)
^super::CommitStub(&self.context, commit)
}
}
}
div.block {
div.block-header h3 { "File changes" }
div.block-details {
^super::DiffCommits(&self.context.repository, &Some(&self.base), &self.new.commit)
^super::DiffCommits(&self.context, &Some(&self.base), &self.new.commit)
}
}
})

Modified src/render/diff.rs

@@ -4,41 +4,49 @@ use std::path::PathBuf;
use std::cell::RefCell;
use git2::{ self, Commit, Repository };
use maud::{ RenderOnce };
use repository_context::RepositoryContext;
renderers! {
DiffCommits(repo: &'a Repository, old_commit: &'a Option<&'a Commit<'a>>, new_commit: &'a Commit<'a>) {
@match repo.diff_tree_to_tree(old_commit.map(|commit| commit.tree().unwrap()).as_ref(), Some(&new_commit.tree().unwrap()), None) {
Ok(ref diff) => ^Diff(diff),
DiffCommits(context: &'a RepositoryContext, old_commit: &'a Option<&'a Commit<'a>>, new_commit: &'a git2::Commit<'a>) {
@match context.repository.diff_tree_to_tree(old_commit.map(|commit| commit.tree().unwrap()).as_ref(), Some(&new_commit.tree().unwrap()), None) {
Ok(ref diff) => ^Diff(context, new_commit, diff),
Err(ref error) => ^super::Error(error),
}
}
DiffCommit(repo: &'a Repository, commit: &'a Commit<'a>) {
^DiffCommits(repo, &commit.parents().nth(0).as_ref(), commit)
DiffCommit(context: &'a RepositoryContext, commit: &'a git2::Commit<'a>) {
^DiffCommits(context, &commit.parents().nth(0).as_ref(), commit)
}
DiffHeader(delta: &'a DiffDelta) {
div.block-header {
@match (delta.status.0, delta.new_file.as_ref(), delta.old_file.as_ref()) {
(git2::Delta::Added, Some(ref new_file), _) => {
h3 { span { "Added " span.path ^new_file.to_string_lossy() } }
},
(git2::Delta::Deleted, _, Some(ref old_file)) => {
h3 { span { "Deleted " span.path ^old_file.to_string_lossy() } }
},
(git2::Delta::Modified, Some(ref new_file), Some(ref old_file)) if old_file == new_file => {
h3 { span { "Modified " span.path ^new_file.to_string_lossy() } }
},
(git2::Delta::Modified, Some(ref new_file), Some(ref old_file)) if old_file != new_file => {
h3 { span { "Modified " span.path ^new_file.to_string_lossy() "(Previously " span.path ^old_file.to_string_lossy() ")" } }
},
(git2::Delta::Renamed, Some(ref new_file), Some(ref old_file)) => {
h3 { span { "Renamed " span.path ^old_file.to_string_lossy() " to " span.path ^new_file.to_string_lossy() } }
},
(git2::Delta::Copied, Some(ref new_file), Some(ref old_file)) => {
h3 { span { "Copied " span.path ^old_file.to_string_lossy() " to " span.path ^new_file.to_string_lossy() } }
},
(status, ref new_file, ref old_file) => ^(format!("{:?} ({:?} -> {:?}) (should not happen)", status, old_file, new_file))
DiffHeader(context: &'a RepositoryContext, new_commit: &'a git2::Commit<'a>, delta: &'a DiffDelta) {
div.block-header.row {
div.column {
@match (delta.status.0, delta.new_file.as_ref(), delta.old_file.as_ref()) {
(git2::Delta::Added, Some(ref new_file), _) => {
h3 { span { "Added " span.path ^new_file.to_string_lossy() } }
},
(git2::Delta::Deleted, _, Some(ref old_file)) => {
h3 { span { "Deleted " span.path ^old_file.to_string_lossy() } }
},
(git2::Delta::Modified, Some(ref new_file), Some(ref old_file)) if old_file == new_file => {
h3 { span { "Modified " span.path ^new_file.to_string_lossy() } }
},
(git2::Delta::Modified, Some(ref new_file), Some(ref old_file)) if old_file != new_file => {
h3 { span { "Modified " span.path ^new_file.to_string_lossy() "(Previously " span.path ^old_file.to_string_lossy() ")" } }
},
(git2::Delta::Renamed, Some(ref new_file), Some(ref old_file)) => {
h3 { span { "Renamed " span.path ^old_file.to_string_lossy() " to " span.path ^new_file.to_string_lossy() } }
},
(git2::Delta::Copied, Some(ref new_file), Some(ref old_file)) => {
h3 { span { "Copied " span.path ^old_file.to_string_lossy() " to " span.path ^new_file.to_string_lossy() } }
},
(status, ref new_file, ref old_file) => ^(format!("{:?} ({:?} -> {:?}) (should not happen)", status, old_file, new_file))
}
}
@if let Some(new_file) = delta.new_file.as_ref() {
div.column.fixed {
a href={ "/" ^context.path "/blob/" ^new_commit.id() "/" ^new_file.to_string_lossy() } { "View" }
}
}
}
}
@@ -123,10 +131,10 @@ renderers! {
}
}
Diff(diff: &'a git2::Diff<'a>) {
Diff(context: &'a RepositoryContext, new_commit: &'a git2::Commit<'a>, diff: &'a git2::Diff<'a>) {
@for (delta, hunks) in group(diff).unwrap() {
div.diff.block id=^delta.id() {
^DiffHeader(&delta)
^DiffHeader(context, new_commit, &delta)
^DiffDetails(delta.id(), delta.new_file.or(delta.old_file).and_then(|path| path.extension().map(|s| s.to_string_lossy().into_owned())), hunks)
}
}

Modified src/tree_entry.rs

@@ -44,7 +44,7 @@ pub fn get_tree_entry<'a>(context: &'a RepositoryContext, path: &'a str) -> Iron
};
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).to_owned();
let reff = referenced_commit.shorthand_or_id().into_owned();
Ok(TreeEntryContext {
entry: entry,
repo_path: &context.path,