From 9f4a6e28ce83150925d967d7170abd3f9636ed20 Mon Sep 17 00:00:00 2001
From: tri <tri@thac.loan>
Date: Sat, 27 Sep 2025 19:22:35 +0700
Subject: [PATCH] locate git dirs; update-server-info

---
 .gitignore    |  2 ++
 src/git.zig   | 29 +++++++++++++++++++++++++
 src/main.zig  | 60 +++++++++++++++++++++++++++++++++++----------------
 src/utils.zig |  5 +++++
 4 files changed, 77 insertions(+), 19 deletions(-)
 create mode 100644 src/git.zig
 create mode 100644 src/utils.zig

diff --git a/.gitignore b/.gitignore
index d8c8979..15643f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
 .zig-cache
 zig-out
+
+/demo
diff --git a/src/git.zig b/src/git.zig
new file mode 100644
index 0000000..3f83048
--- /dev/null
+++ b/src/git.zig
@@ -0,0 +1,29 @@
+const std = @import("std");
+const mem = std.mem;
+const fs = std.fs;
+
+pub fn isGitDir(gpa: mem.Allocator, dir: fs.Dir) !bool {
+    var proc = try std.process.Child.run(.{
+        .allocator = gpa,
+        .cwd_dir = dir,
+        .argv = &.{
+            "git", "rev-parse", "--is-inside-work-tree",
+        },
+    });
+    defer gpa.free(proc.stderr);
+    defer gpa.free(proc.stdout);
+
+    return mem.startsWith(u8, proc.stdout, "true");
+}
+
+pub fn updateServerInfo(gpa: mem.Allocator, dir: fs.Dir) !void {
+    var proc = try std.process.Child.run(.{
+        .allocator = gpa,
+        .cwd_dir = dir,
+        .argv = &.{ "git", "update-server-info" },
+    });
+    defer gpa.free(proc.stderr);
+    defer gpa.free(proc.stdout);
+
+    std.debug.assert(proc.term.Exited == 0);
+}
diff --git a/src/main.zig b/src/main.zig
index 9c7174e..01fac8a 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,25 +1,47 @@
 const std = @import("std");
+const fs = std.fs;
+const println = @import("utils.zig").println;
+const git = @import("git.zig");
 
-pub fn main() !void {
-    // Prints to stderr, ignoring potential errors.
-    std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
-}
+pub fn main() !u8 {
+    if (std.os.argv.len != 2) {
+        println("Usage: khoe <dir>", .{});
+        return 1;
+    }
 
-test "simple test" {
-    const gpa = std.testing.allocator;
-    var list: std.ArrayList(i32) = .empty;
-    defer list.deinit(gpa); // Try commenting this out and see if zig detects the memory leak!
-    try list.append(gpa, 42);
-    try std.testing.expectEqual(@as(i32, 42), list.pop());
-}
+    var dba_impl: std.heap.DebugAllocator(.{}) = .init;
+    const dba = dba_impl.allocator();
+
+    const target_dir_path = std.os.argv[1];
+    println("Processing dir: {s}", .{target_dir_path});
 
-test "fuzz example" {
-    const Context = struct {
-        fn testOne(context: @This(), input: []const u8) anyerror!void {
-            _ = context;
-            // Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
-            try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
+    var target_dir = try fs.cwd().openDirZ(target_dir_path, .{ .iterate = true });
+    defer target_dir.close();
+
+    var dir_iter = target_dir.iterate();
+    while (try dir_iter.next()) |entry| {
+        if (entry.kind != .directory) {
+            continue;
         }
-    };
-    try std.testing.fuzz(Context{}, Context.testOne, .{});
+
+        var subdir = try target_dir.openDir(entry.name, .{});
+        defer subdir.close();
+
+        if (!try git.isGitDir(dba, subdir)) {
+            continue;
+        }
+
+        // update-server-info generates the necessary files to make our static
+        // dir cloneable: https://git-scm.com/docs/git-update-server-info
+        try git.updateServerInfo(dba, subdir);
+    }
+
+    // Deinit goes here.
+    // It's technically not necessary because the process is ending anyway,
+    // but it lets us know if there's been any memory leak.
+    if (dba_impl.deinit() == .leak) {
+        println(">> memory leak detected", .{});
+        return 1;
+    }
+    return 0;
 }
diff --git a/src/utils.zig b/src/utils.zig
new file mode 100644
index 0000000..dbe8266
--- /dev/null
+++ b/src/utils.zig
@@ -0,0 +1,5 @@
+const std = @import("std");
+
+pub fn println(comptime fmt: []const u8, args: anytype) void {
+    std.debug.print(fmt ++ "\n", args);
+}
-- 
2.47.3

