download patch
commit 8ce3088849bd8ed3ade94e599409b61ea5a9ecc0
Author: tri <tri@thac.loan>
Date: Sat Oct 4 12:28:32 2025 +0700
generate commit pages
diff --git a/Makefile b/Makefile
index fe38807..a87886d 100644
--- a/Makefile
+++ b/Makefile
deploy: build
regen: deploy
ssh khoe "cd pub/khoe; ~/global-hooks/post-update"
+
+clean:
+ rm -rf zig-out .zig-cache
diff --git a/src/assets/style.css b/src/assets/style.css
index 525e2ef..0920a99 100644
--- a/src/assets/style.css
+++ b/src/assets/style.css
div.readme-content {
border: 1px solid var(--table-border-color);
}
+.commit-content {
+ width: fit-content;
+ max-width: 100%;
+ overflow-x: auto;
+ border: 1px solid var(--fg);
+ padding: 1rem;
+}
+
@media screen and (max-width: 600px) {
- .repo-content {
- padding: 0.5rem;
- }
- .blob-content {
+ .repo-content,
+ .blob-content,
+ .commit-content {
padding: 0.5rem;
}
}
diff --git a/src/git.zig b/src/git.zig
index c8cac10..cb66c0f 100644
--- a/src/git.zig
+++ b/src/git.zig
const std = @import("std");
const mem = std.mem;
const fs = std.fs;
+const Io = std.Io;
const t = std.testing;
pub fn findGitDir(arena: mem.Allocator, dir: fs.Dir) ![]const u8 {
pub fn catFile(arena: mem.Allocator, dir: fs.Dir, object_hash: []const u8) ![]co
std.debug.assert(proc.term.Exited == 0);
return proc.stdout;
}
+
+pub fn show(arena: mem.Allocator, dir: fs.Dir, commit_hash: []const u8) ![]const u8 {
+ // First get git's terminal output with color codes intact
+ var git_proc = try std.process.Child.run(.{
+ .allocator = arena,
+ .cwd_dir = dir,
+ .max_output_bytes = 1024 * 1024 * 64,
+ .argv = &.{ "git", "show", commit_hash },
+ });
+ std.debug.assert(git_proc.term.Exited == 0);
+ return git_proc.stdout;
+}
diff --git a/src/main.zig b/src/main.zig
index 2e7285c..6e8eb32 100644
--- a/src/main.zig
+++ b/src/main.zig
const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const ascii = std.ascii;
+const fmt = std.fmt;
const utils = @import("utils.zig");
const println = utils.println;
const git = @import("git.zig");
pub fn writeCommitsPage(
);
const escaped_author = try html.escapeAlloc(arena, cmt.author_name);
+ const cmt_web_path = try fmt.allocPrint(arena, "../{s}/{s}/", .{
+ constants.web_objects_path,
+ cmt.hash,
+ });
+
try writer.print(
\\<tr>
- \\ <td class="monospace" title="commit diff coming Soon™">{0s}</td>
+ \\ <td class="monospace"><a href="{5s}">{0s}</a></td>
\\ <td>{1s}{2s}</td>
\\ <td>{4s}</td>
\\ <td><time class="relative" datetime="{3s}" title="{3s}">{3s}</time></td>
pub fn writeCommitsPage(
if (cmt.subject.len > 80) "…" else "",
cmt.time,
escaped_author,
+ cmt_web_path,
},
);
+
+ try writeCommitPage(arena, args, out_repo_dir, cmt);
}
try writer.writeAll(
pub fn writeCommitsPage(
try writer.flush();
}
+pub fn writeCommitPage(
+ arena: mem.Allocator,
+ args: *const RepoArgs,
+ out_repo_dir: fs.Dir,
+ commit: git.Commit,
+) !void {
+ var commit_dir = try out_repo_dir.makeOpenPath(
+ try fmt.allocPrint(
+ arena,
+ "{s}/{s}",
+ .{ constants.web_objects_path, commit.hash },
+ ),
+ .{},
+ );
+ defer commit_dir.close();
+
+ const index_html = "index.html";
+
+ const file_exists = blk: {
+ _ = commit_dir.statFile(index_html) catch |err| switch (err) {
+ error.FileNotFound => break :blk false,
+ else => return err,
+ };
+ break :blk true;
+ };
+ if (file_exists) return;
+
+ println(" writing {s} commit {s}", .{ args.repo_name, commit.hash[0..10] });
+
+ var commit_file = try commit_dir.createFile(index_html, .{});
+ errdefer commit_dir.deleteFile(index_html) catch {};
+ defer commit_file.close();
+
+ var buf: [4096]u8 = undefined;
+ var file_writer = commit_file.writer(&buf);
+ const writer = &file_writer.interface;
+
+ const commit_label = try fmt.allocPrint(arena, "{s} (commit)", .{commit.hash[0..10]});
+
+ try templates.base_start(arena, writer, .{
+ .title = commit_label,
+ .breadcrumbs = &.{
+ .{ .href = "/", .text = "repos" },
+ .{
+ .text = args.repo_name,
+ .href = try fmt.allocPrint(arena, "/{s}/{s}/{s}/", .{
+ constants.web_path,
+ args.repo_name,
+ constants.web_commits_path,
+ }),
+ },
+ .{ .text = commit_label },
+ },
+ });
+
+ try writer.writeAll(
+ \\<pre class="commit-content">
+ \\
+ );
+
+ const commit_text = try git.show(arena, args.in_repo_dir, commit.hash);
+ try html.escape(writer, commit_text);
+
+ try writer.writeAll(
+ \\</pre>
+ \\
+ );
+
+ try templates.base_end(writer);
+ try writer.flush();
+}
+
pub fn writeFilePage(
args: *const RepoArgs,
out_dir: fs.Dir,