authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-22 12:30:14 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-22 12:30:14 -07:00
log9a91514527a5481ddd1ebeb9707b10808d5eea77
treef7531521979b988d502a2c8f984f0810e2391e34
parent2f002caa03f13fe44701e3bc2d182a0e4f510667
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

Tree: add Walker


1 files changed, 85 insertions(+), 1 deletions(-)

git.zig+85-1
......@@ -1,6 +1,5 @@
11const std = @import("std");
22const string = []const u8;
3const top = @This();
43const time = @import("time");
54const extras = @import("extras");
65const tracer = @import("tracer");
......@@ -1465,6 +1464,91 @@ pub const Tree = struct {
14651464 }
14661465 };
14671466 };
1467
1468 pub fn walk(self: Tree, r: *Repository, arena: std.mem.Allocator) !Walker {
1469 var stack: std.ArrayListUnmanaged(Walker.StackItem) = .empty;
1470
1471 try stack.append(r.gpa, .{
1472 .tree = self,
1473 .idx = 0,
1474 .dirname_len = 0,
1475 });
1476 return .{
1477 .repo = r,
1478 .arena = arena,
1479 .stack = stack,
1480 .name_buffer = .empty,
1481 };
1482 }
1483
1484 pub const Walker = struct {
1485 repo: *Repository,
1486 arena: std.mem.Allocator,
1487 stack: std.ArrayListUnmanaged(StackItem),
1488 name_buffer: std.ArrayListUnmanaged(u8),
1489
1490 pub const Entry = struct {
1491 obj: Object,
1492 path: [:0]const u8,
1493 };
1494
1495 const StackItem = struct {
1496 tree: Tree,
1497 idx: usize,
1498 dirname_len: usize,
1499 };
1500
1501 pub fn next(self: *Walker) !?Walker.Entry {
1502 const gpa = self.repo.gpa;
1503 const arena = self.arena;
1504 while (self.stack.items.len != 0) {
1505 var top = &self.stack.items[self.stack.items.len - 1];
1506 var containing = top;
1507 var dirname_len = top.dirname_len;
1508 if (top.idx < top.tree.children.len()) {
1509 const base = top.tree.children.get(top.idx);
1510 top.idx += 1;
1511 self.name_buffer.shrinkRetainingCapacity(dirname_len);
1512 if (self.name_buffer.items.len != 0) {
1513 try self.name_buffer.append(gpa, '/');
1514 dirname_len += 1;
1515 }
1516 try self.name_buffer.ensureUnusedCapacity(gpa, base.name.len + 1);
1517 self.name_buffer.appendSliceAssumeCapacity(base.name);
1518 self.name_buffer.appendAssumeCapacity(0);
1519 if (base.id == .tree) {
1520 const new_tree = try self.repo.getTreeA(arena, base.id.tree.id);
1521 {
1522 // errdefer new_dir.close();
1523 try self.stack.append(gpa, .{
1524 .tree = new_tree,
1525 .idx = 0,
1526 .dirname_len = self.name_buffer.items.len - 1,
1527 });
1528 top = &self.stack.items[self.stack.items.len - 1];
1529 containing = &self.stack.items[self.stack.items.len - 2];
1530 }
1531 }
1532 return .{
1533 .obj = base,
1534 .path = self.name_buffer.items[0 .. self.name_buffer.items.len - 1 :0],
1535 };
1536 } else {
1537 var item = self.stack.pop().?;
1538 _ = &item;
1539 // if (self.stack.items.len != 0) item.iter.dir.close();
1540 }
1541 }
1542 return null;
1543 }
1544
1545 pub fn deinit(self: *Walker) void {
1546 const gpa = self.repo.gpa;
1547 // for (self.stack.items) |*item| item.iter.dir.close();
1548 self.stack.deinit(gpa);
1549 self.name_buffer.deinit(gpa);
1550 }
1551 };
14681552};
14691553
14701554pub const Commit = struct {