download patch
commit cdcc684516342490378dcb0561260847181eb1ea
Author: tri <tri@thac.loan>
Date: Tue Sep 30 22:50:07 2025 +0700
remove gratuitous dependency on du
diff --git a/README.md b/README.md
index 9f8c49b..76ed89b 100644
--- a/README.md
+++ b/README.md
zig build -Doptimize=ReleaseSafe
Runtime dependencies (khoe shells out to these commands at runtime):
- git
-- [cmark][7]
-- [du][6]
+- [cmark][6]
## Use
You should have received a copy of the GNU Affero General Public License along w
[3]: https://github.com/theZiz/aha
[4]: https://manpages.debian.org/trixie/util-linux/flock.1.en.html
[5]: https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/git-no-forge/#submissions
-[6]: https://manpages.debian.org/trixie/coreutils/du.1.en.html
-[7]: https://github.com/commonmark/cmark
+[6]: https://github.com/commonmark/cmark
diff --git a/src/git.zig b/src/git.zig
index e422aa7..24ee54a 100644
--- a/src/git.zig
+++ b/src/git.zig
pub fn readFileAlloc(arena: mem.Allocator, dir: fs.Dir, file_name: []const u8) !
return proc.stdout;
}
-
-pub fn repoSize(arena: mem.Allocator, git_dir: fs.Dir) ![]const u8 {
- var proc = try std.process.Child.run(.{
- .allocator = arena,
- .cwd_dir = git_dir,
- .argv = &.{ "du", "-h", "-d0", "." },
- });
- return proc.stdout[0..std.mem.indexOfAny(u8, proc.stdout, " \t").?];
-}
diff --git a/src/main.zig b/src/main.zig
index 1ed5562..5c8aca4 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 println = @import("utils.zig").println;
+const utils = @import("utils.zig");
+const println = utils.println;
const git = @import("git.zig");
const html = @import("html.zig");
const markdown = @import("markdown.zig");
pub fn main() !u8 {
const commits = try git.getCommits(repo_arena, repo_dir);
println("Found repo {s}: {d} commits", .{ entry.name, commits.len });
- var git_dir = try repo_dir.openDir(git_dir_path, .{});
+ var git_dir = try repo_dir.openDir(git_dir_path, .{ .iterate = true });
defer git_dir.close();
const repo_description = try git.getDescription(arena, git_dir);
pub fn writeRepoPage(args: RepoArgs) !void {
else
try std.fmt.bufPrint(&buf, "{s}/{s}", .{ repo_name, args.git_dir_path }),
try html.escapeAlloc(arena, args.description),
- try git.repoSize(arena, args.git_dir),
+ try utils.humanReadableSize(arena, try utils.dirSize(arena, args.git_dir)),
});
// If there's a readme file, include it in repo index:
diff --git a/src/utils.zig b/src/utils.zig
index dbe8266..e6a5508 100644
--- a/src/utils.zig
+++ b/src/utils.zig
const std = @import("std");
+const fs = std.fs;
+const mem = std.mem;
+const t = std.testing;
pub fn println(comptime fmt: []const u8, args: anytype) void {
std.debug.print(fmt ++ "\n", args);
}
+
+pub fn dirSize(gpa: mem.Allocator, dir: fs.Dir) !u64 {
+ var walker = try dir.walk(gpa);
+ defer walker.deinit();
+
+ var size: u64 = 0;
+ while (try walker.next()) |entry| {
+ if (entry.kind != .sym_link) {
+ size += (try dir.statFile(entry.path)).size;
+ }
+ }
+ return size;
+}
+
+/// Not ideal because it truncates instead of rounding to the nearest value.
+pub fn humanReadableSize(arena: mem.Allocator, n_bytes: u64) ![]const u8 {
+ const units: []const []const u8 = &.{ "B", "KiB", "MiB", "GiB", "TiB" };
+ const multiplier: u64 = 1024;
+ var threshold: u64 = multiplier;
+ var unitIdx: usize = 0;
+
+ for (units, 0..) |_, i| {
+ unitIdx = i;
+ if (n_bytes < threshold) {
+ break;
+ }
+ threshold *= multiplier;
+ }
+
+ return std.fmt.allocPrint(
+ arena,
+ "{d} {s}",
+ .{
+ n_bytes / std.math.pow(u64, 1024, unitIdx),
+ units[unitIdx],
+ },
+ );
+}
+
+test "humanReadableSize" {
+ var arena_impl = std.heap.ArenaAllocator.init(t.allocator_instance.allocator());
+ defer arena_impl.deinit();
+ const arena = arena_impl.allocator();
+
+ try t.expectEqualStrings("12 B", try humanReadableSize(arena, 12));
+ try t.expectEqualStrings("1023 B", try humanReadableSize(arena, 1023));
+ try t.expectEqualStrings("1 KiB", try humanReadableSize(arena, 1024));
+ try t.expectEqualStrings("1 KiB", try humanReadableSize(arena, 1024 + 1023));
+ try t.expectEqualStrings("2 KiB", try humanReadableSize(arena, 1024 + 1024));
+ try t.expectEqualStrings("2 MiB", try humanReadableSize(arena, 1024 * 1024 * 2));
+ try t.expectEqualStrings("3 GiB", try humanReadableSize(arena, 1024 * 1024 * 1024 * 3));
+ try t.expectEqualStrings("4 TiB", try humanReadableSize(arena, 1024 * 1024 * 1024 * 1024 * 4));
+ try t.expectEqualStrings("1024 TiB", try humanReadableSize(arena, 1024 * 1024 * 1024 * 1024 * 1024));
+}