1const Directory = @This();
2
3const std = @import("../../std.zig");
4const Io = std.Io;
5const fs = std.fs;
6const assert = std.debug.assert;
7const fmt = std.fmt;
8const Allocator = std.mem.Allocator;
9
10/// This field is redundant for operations that can act on the open directory handle
11/// directly, but it is needed when passing the directory to a child process.
12/// `null` means cwd.
13path: ?[]const u8,
14handle: Io.Dir,
15
16pub fn clone(d: Directory, arena: Allocator) Allocator.Error!Directory {
17 return .{
18 .path = if (d.path) |p| try arena.dupe(u8, p) else null,
19 .handle = d.handle,
20 };
21}
22
23pub fn cwd() Directory {
24 return .{
25 .path = null,
26 .handle = .cwd(),
27 };
28}
29
30pub fn join(self: Directory, allocator: Allocator, paths: []const []const u8) ![]u8 {
31 if (self.path) |p| {
32 // TODO clean way to do this with only 1 allocation
33 const part2 = try fs.path.join(allocator, paths);
34 defer allocator.free(part2);
35 return fs.path.join(allocator, &[_][]const u8{ p, part2 });
36 } else {
37 return fs.path.join(allocator, paths);
38 }
39}
40
41pub fn joinZ(self: Directory, allocator: Allocator, paths: []const []const u8) ![:0]u8 {
42 if (self.path) |p| {
43 // TODO clean way to do this with only 1 allocation
44 const part2 = try fs.path.join(allocator, paths);
45 defer allocator.free(part2);
46 return fs.path.joinZ(allocator, &[_][]const u8{ p, part2 });
47 } else {
48 return fs.path.joinZ(allocator, paths);
49 }
50}
51
52/// Whether or not the handle should be closed, or the path should be freed
53/// is determined by usage, however this function is provided for convenience
54/// if it happens to be what the caller needs.
55pub fn closeAndFree(self: *Directory, gpa: Allocator, io: Io) void {
56 self.handle.close(io);
57 if (self.path) |p| gpa.free(p);
58 self.* = undefined;
59}
60
61pub fn format(self: Directory, writer: *std.Io.Writer) std.Io.Writer.Error!void {
62 if (self.path) |p| {
63 try writer.writeAll(p);
64 try writer.writeAll(fs.path.sep_str);
65 }
66}
67
68pub fn eql(self: Directory, other: Directory) bool {
69 return self.handle.handle == other.handle.handle;
70}