mygit

[UNMAINTAINED] A cgit/webgit alternative, written in Rust
Log | Files | Refs | README | LICENSE

commit 8265b607e6d4b6ca45291af2b04dc73fa2c45368
parent a8b7e5f0e1b18522d8ad634576f824fb0265cc53
Author: Johann150 <johann@qwertqwefsday.eu>
Date:   Sun, 18 Jul 2021 16:39:55 +0200

show last commit for files and directories

Diffstat:
Msrc/main.rs | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/commit-tr.html | 7+++++++
Mtemplates/file.html | 1+
Atemplates/last-commit.html | 9+++++++++
Mtemplates/tree.html | 3++-
5 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/main.rs b/src/main.rs @@ -416,6 +416,59 @@ async fn repo_refs(req: Request<()>) -> tide::Result { Ok(tmpl.into()) } +fn last_commit_for<'a, S: git2::IntoCString>( + repo: &'a Repository, + spec: &str, + path: S, +) -> Commit<'a> { + let mut revwalk = repo.revwalk().unwrap(); + revwalk + .push( + repo + // we already know this has to be a commit-ish + .revparse_single(spec) + .unwrap() + .peel_to_commit() + .unwrap() + .id(), + ) + .unwrap(); + revwalk.set_sorting(git2::Sort::TIME).unwrap(); + + let mut options = DiffOptions::new(); + options.pathspec(path); + + revwalk + .filter_map(|oid| repo.find_commit(oid.unwrap()).ok()) // TODO error handling + .filter(|commit| { + let tree = commit.tree().unwrap(); + if commit.parent_count() == 0 { + repo.diff_tree_to_tree(None, Some(&tree), Some(&mut options)) + .unwrap() + .stats() + .unwrap() + .files_changed() + > 0 + } else { + // check that the given file was affected from any of the parents + commit.parents().any(|parent| { + repo.diff_tree_to_tree( + parent.tree().ok().as_ref(), + Some(&tree), + Some(&mut options), + ) + .unwrap() + .stats() + .unwrap() + .files_changed() + > 0 + }) + } + }) + .next() + .expect("file was not part of any commit") +} + #[derive(Template)] #[template(path = "tree.html")] // using the template in this path, relative struct RepoTreeTemplate<'a> { @@ -423,6 +476,7 @@ struct RepoTreeTemplate<'a> { tree: Tree<'a>, path: &'a Path, spec: &'a str, + last_commit: Commit<'a>, } async fn repo_tree(req: Request<()>) -> tide::Result { @@ -443,6 +497,7 @@ async fn repo_tree(req: Request<()>) -> tide::Result { tree, path: Path::new(""), spec, + last_commit: last_commit_for(&repo, spec, ""), }; Ok(tmpl.into()) } @@ -593,6 +648,7 @@ struct RepoFileTemplate<'a> { path: &'a Path, file_text: &'a str, spec: &'a str, + last_commit: Commit<'a>, } async fn repo_file(req: Request<()>) -> tide::Result { @@ -605,6 +661,8 @@ async fn repo_file(req: Request<()>) -> tide::Result { let path = Path::new(req.param("object_name")?); let tree_entry = tree.get_path(path).unwrap(); + let last_commit = last_commit_for(&repo, spec, path); + // TODO make sure I am escaping html properly here // TODO allow disabling of syntax highlighting // TODO -- dont pull in memory, use iterators if possible @@ -622,6 +680,7 @@ async fn repo_file(req: Request<()>) -> tide::Result { tree, path, spec: &spec, + last_commit, } .into(), // this is not a subtree, so it should be a blob i.e. file @@ -691,6 +750,7 @@ async fn repo_file(req: Request<()>) -> tide::Result { path, file_text: &output, spec: &spec, + last_commit, } .into() } diff --git a/templates/commit-tr.html b/templates/commit-tr.html @@ -0,0 +1,7 @@ +<tr> + <td><a href="/{{repo|repo_name|urlencode_strict}}/commit/{{commit.id()}}" class="commit-hash">{{commit|short_id}}</a></td> + {% let summary = commit.summary().unwrap_or("")|truncate(72) %} + <td class="commit-summary">{{summary}}</td> + <td class="commit-author-email">{{commit.author()|signature_email_link|safe}}</td> + <td class="commit-date">{{commit.time()|format_datetime("%Y-%m-%d %H:%M:%S%z")}}</td> +</tr> diff --git a/templates/file.html b/templates/file.html @@ -6,5 +6,6 @@ {% include "repo-navbar.html" %} <a href="/{{repo|repo_name|urlencode_strict}}/tree/{{spec}}/raw/{{path.display()}}" style="float:right;">raw</a> <h3>{{path.display()}}@<a href="/{{repo|repo_name|urlencode_strict}}/tree/{{spec}}">{{spec}}</a></h3> + {% include "last-commit.html" %} {{file_text|safe}} {% endblock %} diff --git a/templates/last-commit.html b/templates/last-commit.html @@ -0,0 +1,9 @@ +<hr class="thin"/> +<table> + {% let commit = last_commit.clone() %} + {% include "commit-tr.html" %} + <tr> + <td colspan="4"><a href="/{{repo|repo_name|urlencode_strict}}/log/{{spec}}/{{path.display()}}">...</a></td> + </tr> +</table> +<hr class="thin"/> diff --git a/templates/tree.html b/templates/tree.html @@ -8,8 +8,9 @@ {% if path.to_string_lossy() != "" %} <h3>{{path.to_string_lossy()}}/@<a href="/{{repo|repo_name|urlencode_strict}}/tree/{{spec}}">{{spec}}</a></h3> {% else %} - <h3>{{ spec }}</h3> + <h3>{{ spec }}</h3> {% endif %} + {% include "last-commit.html" %} <table> {% for entry in tree %} <tr>