diff --git a/.sqlx/query-c8172df79e5000f77a957a648fc12898959bfba8d12f31428b6e582ce2106719.json b/.sqlx/query-c8172df79e5000f77a957a648fc12898959bfba8d12f31428b6e582ce2106719.json new file mode 100644 index 0000000..648a663 --- /dev/null +++ b/.sqlx/query-c8172df79e5000f77a957a648fc12898959bfba8d12f31428b6e582ce2106719.json @@ -0,0 +1,20 @@ +{ + "db_name": "SQLite", + "query": "SELECT child FROM commit_links WHERE parent = ?", + "describe": { + "columns": [ + { + "name": "child", + "ordinal": 0, + "type_info": "Text" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "c8172df79e5000f77a957a648fc12898959bfba8d12f31428b6e582ce2106719" +} diff --git a/src/web.rs b/src/web.rs index df97d77..32516ad 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,4 +1,5 @@ mod commit; +mod commit_hash; mod index; mod r#static; @@ -12,6 +13,7 @@ pub async fn run(state: AppState) -> somehow::Result<()> { let app = Router::new() .route("/", get(index::get)) .route("/commit/", get(commit::get)) + .route("/commit/:hash", get(commit_hash::get)) .fallback(get(r#static::static_handler)) .with_state(state.clone()); diff --git a/src/web/commit_hash.rs b/src/web/commit_hash.rs new file mode 100644 index 0000000..5717a83 --- /dev/null +++ b/src/web/commit_hash.rs @@ -0,0 +1,90 @@ +use std::sync::Arc; + +use askama::Template; +use axum::{ + extract::{Path, State}, + response::IntoResponse, +}; +use futures::TryStreamExt; +use gix::{prelude::ObjectIdExt, Id, ObjectId, ThreadSafeRepository}; +use sqlx::SqlitePool; + +use crate::{config::Config, repo, somehow}; + +struct Commit { + hash: String, + description: String, +} + +impl Commit { + fn new(id: Id<'_>) -> somehow::Result { + let commit = id.object()?.try_into_commit()?; + Ok(Self { + hash: id.to_string(), + description: repo::format_commit_short(&commit)?, + }) + } +} + +#[derive(Template)] +#[template(path = "commit_hash.html")] +struct CommitIdTemplate { + base: String, + repo_name: String, + current: String, + hash: String, + summary: String, + message: String, + author: String, + author_date: String, + commit: String, + commit_date: String, + parents: Vec, + children: Vec, +} + +pub async fn get( + Path(hash): Path, + State(config): State<&'static Config>, + State(db): State, + State(repo): State>, +) -> somehow::Result { + // Do this first because a &Repository can't be kept across awaits. + let child_ids = sqlx::query!("SELECT child FROM commit_links WHERE parent = ?", hash) + .fetch(&db) + .map_ok(|r| r.child) + .try_collect::>() + .await?; + + let repo = repo.to_thread_local(); + let id = hash.parse::()?.attach(&repo); + let commit = id.object()?.try_into_commit()?; + let author_info = commit.author()?; + let committer_info = commit.committer()?; + + let mut parents = vec![]; + for id in commit.parent_ids() { + parents.push(Commit::new(id)?); + } + + let mut children = vec![]; + for hash in child_ids { + let id = hash.parse::()?.attach(&repo); + children.push(Commit::new(id)?); + } + + Ok(CommitIdTemplate { + base: config.web.base(), + repo_name: config.repo.name(), + current: "commit".to_string(), + hash: id.to_string(), + summary: commit.message()?.summary().to_string(), + message: commit.message_raw_sloppy().to_string(), + author: repo::format_actor(author_info.actor())?, + author_date: author_info.time.to_bstring().to_string(), + commit: repo::format_actor(committer_info.actor())?, + commit_date: committer_info.time.to_bstring().to_string(), + parents, + children, + }) +} diff --git a/static/base.css b/static/base.css index 0d2431b..9cbc0f0 100644 --- a/static/base.css +++ b/static/base.css @@ -1,5 +1,7 @@ :root { + --lh: 1.3em; font-family: monospace; + line-height: var(--lh); color-scheme: light dark; } @@ -59,3 +61,24 @@ a:hover { dd { margin-left: 4ch; } + +/* Commit */ + +.commit * { + margin: 0; +} + +.commit .hash { + color: #b70; + font-weight: bold; +} + +.commit .message { + margin: 1em 0ch 1em 4ch; +} + +.commit dl { + display: grid; + grid: auto-flow / min-content max-content; + column-gap: 1ch; +} diff --git a/templates/commit_hash.html b/templates/commit_hash.html new file mode 100644 index 0000000..b5a6297 --- /dev/null +++ b/templates/commit_hash.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} + +{% block title %}{{ summary }}{% endblock %} + +{% block body %} +

Commit

+
+ commit {{ hash }} +
+
Author:
+
{{ author }}
+ +
AuthorDate:
+
{{ author_date }}
+ +
Commit:
+
{{ commit }}
+ +
CommitDate:
+
{{ commit_date }}
+ + {% for commit in parents %} +
Parent:
+
{{ commit.description }}
+ {% endfor %} + + {% for commit in children %} +
Child:
+
{{ commit.description }}
+ {% endfor %} +
+
{{ message }}
+
+{% endblock %}