const std = @import("std"); const assert = std.debug.assert; const fs = @import("fs.zig"); const Env = @import("env.zig"); pub const Tree = struct { name: []const u8, root: fs.Path, pub fn port_path(self: Tree, port_name: []const u8) fs.Path { return .join(.{ self.root.name(), port_name }); } }; pub const Iterator = struct { root: fs.Path, iter: ?fs.Iterator = null, pub fn deinit(self: *Iterator) void { if (self.iter) |*it| it.deinit(); } pub fn next(self: *Iterator) !?Tree { if (self.iter) |*iter| { while (try iter.next()) |entry| { if (entry.type == .dir) { return .{ .name = entry.name, .root = .join(.{ self.root.name(), entry.name }), }; } } } return null; } }; pub inline fn iterate(env: *const Env) !Iterator { const root = tree_root_dir(env); const iter = fs.iterate(&root) catch |err| { if (err == error.FileNotFound) return .{ .root = undefined }; return err; }; return .{ .root = root, .iter = iter, }; } pub fn get(env: *const Env, tree_name: []const u8) !?Tree { var tree_root = tree_root_dir(env); tree_root.append(.{tree_name}); return .{ .name = tree_name, .root = tree_root }; } pub fn remove(env: *const Env, tree: Tree) !void { const tree_path = env.ports_tree_path(tree.name, .{}); const src_path = env.ports_src_path(tree.name, .{}); try fs.rm(&tree.root); fs.rm(&tree_path) catch {}; fs.rm(&src_path) catch {}; } fn tree_root_dir(env: *const Env) fs.Path { return env.etc_path(.{"ports"}); }