download patch
commit eefbbb39c047419e11797ce415b8208c5bc67d69
Author: tri <tri@thac.loan>
Date: Mon Sep 29 08:36:59 2025 +0700
more robust git dir detection logic
diff --git a/Makefile b/Makefile
index 2f8c180..d2bc10e 100644
--- a/Makefile
+++ b/Makefile
watch:
zig build run --watch -- demo http://localhost:8000
+watch2:
+ zig build run --watch -- demo2 http://localhost:8000
+
# TODO: write a simple zig server instead
serve:
python -m http.server -b localhost -d demo 8000
+# TODO: write a simple zig server instead
+serve2:
+ python -m http.server -b localhost -d demo2 8000
+
test:
zig build test --watch
diff --git a/src/git.zig b/src/git.zig
index f9fc639..ae16e32 100644
--- a/src/git.zig
+++ b/src/git.zig
const std = @import("std");
const mem = std.mem;
const fs = std.fs;
-pub fn isGitDir(name: []const u8, dir: fs.Dir) !bool {
- if (mem.endsWith(u8, name, ".git")) {
- return true;
- }
- const stat = dir.statFile(".git") catch |err| {
- switch (err) {
- error.FileNotFound => return false,
- else => return err,
- }
- };
- if (stat.kind == .directory) {
- return true;
- }
- return false;
+pub fn findGitDir(arena: mem.Allocator, dir: fs.Dir) ![]const u8 {
+ var proc = try std.process.Child.run(.{
+ .allocator = arena,
+ .cwd_dir = dir,
+ .argv = &.{ "git", "rev-parse", "--git-dir" },
+ });
+ return mem.trimEnd(u8, proc.stdout, "\n");
}
pub fn updateServerInfo(gpa: mem.Allocator, dir: fs.Dir) !void {
diff --git a/src/main.zig b/src/main.zig
index d6ddce8..23bae57 100644
--- a/src/main.zig
+++ b/src/main.zig
const std = @import("std");
const fs = std.fs;
+const mem = std.mem;
const println = @import("utils.zig").println;
const git = @import("git.zig");
pub fn main() !u8 {
var repo_dir = try target_dir.openDir(entry.name, .{});
defer repo_dir.close();
- if (!try git.isGitDir(entry.name, repo_dir)) {
+ const git_dir_path = try git.findGitDir(repo_arena, repo_dir);
+ if (!(
+ // check if entry is actually a git repo
+ mem.eql(u8, git_dir_path, ".") // bare repo
+ or mem.eql(u8, git_dir_path, ".git") // normal repo
+ )) {
+ // Note: git dir could also return a full path, which means the
+ // current dir is NOT a git repo, but one of its ancestors is.
+ // We're not interested in such cases either.
+ println("* {s} is not a git repo", .{entry.name});
continue;
}
pub fn main() !u8 {
.last_commit_time = if (commits.len == 0) "" else try arena.dupe(u8, commits[0].time),
});
- try writeRepoPage(
- repo_arena,
- site_url,
- entry.name,
- target_dir,
- repo_dir,
- commits,
- );
+ try writeRepoPage(.{
+ .arena = repo_arena,
+ .site_url = site_url,
+ .repo_name = entry.name,
+ .target_dir = target_dir,
+ .in_repo_dir = repo_dir,
+ .commits = commits,
+ .git_dir_path = git_dir_path,
+ });
// TODO: write repo's commits
}
pub fn writeHomePage(dir: fs.Dir, repos: []RepoSummary) !void {
try writer.interface.flush();
}
-// TODO: write repo's index
-pub fn writeRepoPage(
+const RepoArgs = struct {
arena: std.mem.Allocator,
site_url: [*:0]const u8,
repo_name: []const u8,
target_dir: fs.Dir,
in_repo_dir: fs.Dir,
commits: []git.Commit,
-) !void {
+ git_dir_path: []const u8,
+};
+
+pub fn writeRepoPage(args: RepoArgs) !void {
+ const arena = args.arena;
+ const site_url = args.site_url;
+ const repo_name = args.repo_name;
+ const target_dir = args.target_dir;
+ const in_repo_dir = args.in_repo_dir;
+ const commits = args.commits;
+ const git_dir_path = args.git_dir_path;
+
var buf: [1024]u8 = undefined;
var out_repo_dir = try target_dir.makeOpenPath(
try std.fmt.bufPrint(&buf, "{s}/{s}", .{ web_prefix, repo_name }),
pub fn writeRepoPage(
// TODO write readme content to repo index page, probably in a <details>
}
+ const git_dir = try git.findGitDir(arena, in_repo_dir);
+ _ = git_dir;
+
var file = try out_repo_dir.createFile("index.html", .{});
defer file.close();
pub fn writeRepoPage(
\\ </header>
\\
\\ <p>
- \\ clone command: <code>git clone {2s}/{3s}/</code><br>
+ \\ clone command: <code>git clone {2s}/{3s}</code><br>
\\ commits: <b>{1d}</b><br>
\\ </p>
\\
pub fn writeRepoPage(
repo_name,
commits.len,
site_url,
- if (std.mem.endsWith(u8, repo_name, ".git"))
+ if (mem.eql(u8, git_dir_path, "."))
repo_name
else
- try std.fmt.bufPrint(&buf, "{s}/.git", .{repo_name}),
+ try std.fmt.bufPrint(&buf, "{s}/{s}", .{ repo_name, git_dir_path }),
});
for (commits) |cmt| {