mygit

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

commit 4331f645d1eb6d01eb6df26c349add639c663462
parent 7f8803ad7ed08f3cd77fc4fa1561ba4e62e7495b
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sat, 13 Mar 2021 21:07:22 -0800

Start diff work

Diffstat:
Msrc/main.rs | 46+++++++++++++++++++++++++++++++++++++++++-----
Atemplates/commit.html | 19+++++++++++++++++++
Mtemplates/log.html | 2+-
Mtemplates/static/style.css | 6+++++-
Mtemplates/tree.html | 3+++
5 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -1,6 +1,6 @@ use anyhow::Result; use askama::Template; -use git2::{Commit, Reference, Repository, Tree, TreeEntry}; +use git2::{Commit, Diff, DiffDelta, DiffFormat, Oid, Reference, Repository, Tree, TreeEntry}; use once_cell::sync::OnceCell; use pico_args; use pulldown_cmark::{html, Options, Parser}; @@ -151,9 +151,8 @@ async fn repo_tree(req: Request<()>) -> tide::Result { let config = &Config::global(); let repo = repo_from_request(&req.param("repo_name")?)?; // TODO accept reference or commit id - let commit = match req.param("ref") { - _ => repo.revparse_single("HEAD")?.peel_to_commit()?, - }; + let spec = req.param("ref").unwrap_or("HEAD"); + let commit = repo.revparse_single(spec)?.peel_to_commit()?; let tree = commit.tree()?; let tmpl = RepoTreeTemplate { repo: &repo, @@ -163,6 +162,43 @@ async fn repo_tree(req: Request<()>) -> tide::Result { Ok(tmpl.into()) } +#[derive(Template)] +#[template(path = "commit.html")] // using the template in this path, relative +struct RepoCommitTemplate<'a> { + repo: &'a Repository, + config: &'a Config, + commit: Commit<'a>, + parent: Commit<'a>, + diff: &'a Diff<'a>, + deltas: Vec<DiffDelta<'a>>, +} + +async fn repo_commit(req: Request<()>) -> tide::Result { + let config = &Config::global(); + let repo = repo_from_request(req.param("repo_name")?)?; + let commit = repo + .revparse_single(req.param("commit")?)? + .peel_to_commit()?; + + let parent = repo + .revparse_single(&format!("{}^", commit.id()))? + .peel_to_commit()?; + // TODO root commit + // how to deal w multiple parents? + let diff = repo.diff_tree_to_tree(Some(&commit.tree()?), Some(&parent.tree()?), None)?; + let deltas = diff.deltas().collect(); + + // TODO accept reference or commit id + let tmpl = RepoCommitTemplate { + repo: &repo, + config, + commit, + parent, + diff: &diff, + deltas, + }; + Ok(tmpl.into()) +} mod filters { pub fn iso_date(i: &i64) -> ::askama::Result<String> { // UTC date @@ -234,7 +270,7 @@ async fn main() -> Result<(), std::io::Error> { .serve_file("templates/static/style.css")?; // TODO configurable app.at("/:repo_name").get(repo_home); // ALSO do git pull at this url somehow ^ - // app.at("/:repo_name/commit/:hash").get(repo_log); + app.at("/:repo_name/commit/:commit").get(repo_commit); app.at("/:repo_name/refs").get(repo_refs); app.at("/:repo_name/log").get(repo_log); app.at("/:repo_name/log/:ref").get(repo_log); // ref optional diff --git a/templates/commit.html b/templates/commit.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block content %} + {% let name = repo.workdir().unwrap().file_name().unwrap().to_str().unwrap() %} + {% include "repo-navbar.html" %} + <b>Commit:</b> <div class="commit-hash">{{commit.id()}}</div> (<a href="/{{name}}/tree/{{parent.id()}}">tree</a>) + <br> + <b>Parent:</b> <a href="/{{name}}/commit/{{parent.id()}}"><div class="commit-hash">{{parent.id()}}</div></a> (<a href="/{{name}}/tree/{{parent.id()}}">tree</a>) + <br> + <b>Author:</b> {{commit.author().name().unwrap()}} &lt;<a href="mailto:{{commit.author().email().unwrap()}}">{{commit.author().email().unwrap()}}</a>&gt; + <br> + <b>Date:</b> {{commit.time().seconds()}} + <br> + {% let stats = diff.stats().unwrap() %} + {{stats.files_changed()}} files changed; {{stats.insertions()}} insertions {{stats.deletions()}} deletions + <div class="commit-message"> + {{commit.message().unwrap()}} + </div> +{% endblock %} diff --git a/templates/log.html b/templates/log.html @@ -6,7 +6,7 @@ <table> {% for commit in commits %} <tr> - <td class="commit-hash"><a href="/{{name}}/commits/{{commit.id()}}">{{commit.id().to_string()[..7]}}</td> + <td class="commit-hash"><a href="/{{name}}/commit/{{commit.id()}}">{{commit.id().to_string()[..7]}}</td> {% let summary = commit.summary().unwrap_or("")|truncate(72) %} <td>{{summary}}</td> <td><a href="mailto:{{commit.author().email().unwrap_or("")}}">{{commit.author().name().unwrap_or("")}}</a></td> diff --git a/templates/static/style.css b/templates/static/style.css @@ -12,10 +12,14 @@ body { font-style: italic; } -.repo-link, .git-reference, .permissions { +.repo-link, .git-reference, .permissions, .commit-hash, .commit-message{ font-family: "Roboto Mono", monospace; } +.commit-hash { + display: inline +} + .footer { text-align: center; font-style: italic; diff --git a/templates/tree.html b/templates/tree.html @@ -12,6 +12,9 @@ <td> {{ entry.name().unwrap() }} </td> + <td> + filesize here + </td> </tr> {% endfor %} </table>