aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Build/Cache/Directory.zig
blob: a105a91ed6ecf292edb1482fd49fa36562c61eaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const Directory = @This();
const std = @import("../../std.zig");
const assert = std.debug.assert;
const fs = std.fs;
const fmt = std.fmt;
const Allocator = std.mem.Allocator;

/// This field is redundant for operations that can act on the open directory handle
/// directly, but it is needed when passing the directory to a child process.
/// `null` means cwd.
path: ?[]const u8,
handle: fs.Dir,

pub fn clone(d: Directory, arena: Allocator) Allocator.Error!Directory {
    return .{
        .path = if (d.path) |p| try arena.dupe(u8, p) else null,
        .handle = d.handle,
    };
}

pub fn cwd() Directory {
    return .{
        .path = null,
        .handle = fs.cwd(),
    };
}

pub fn join(self: Directory, allocator: Allocator, paths: []const []const u8) ![]u8 {
    if (self.path) |p| {
        // TODO clean way to do this with only 1 allocation
        const part2 = try fs.path.join(allocator, paths);
        defer allocator.free(part2);
        return fs.path.join(allocator, &[_][]const u8{ p, part2 });
    } else {
        return fs.path.join(allocator, paths);
    }
}

pub fn joinZ(self: Directory, allocator: Allocator, paths: []const []const u8) ![:0]u8 {
    if (self.path) |p| {
        // TODO clean way to do this with only 1 allocation
        const part2 = try fs.path.join(allocator, paths);
        defer allocator.free(part2);
        return fs.path.joinZ(allocator, &[_][]const u8{ p, part2 });
    } else {
        return fs.path.joinZ(allocator, paths);
    }
}

/// Whether or not the handle should be closed, or the path should be freed
/// is determined by usage, however this function is provided for convenience
/// if it happens to be what the caller needs.
pub fn closeAndFree(self: *Directory, gpa: Allocator) void {
    self.handle.close();
    if (self.path) |p| gpa.free(p);
    self.* = undefined;
}

pub fn format(self: Directory, writer: *std.Io.Writer) std.Io.Writer.Error!void {
    if (self.path) |p| {
        try writer.writeAll(p);
        try writer.writeAll(fs.path.sep_str);
    }
}

pub fn eql(self: Directory, other: Directory) bool {
    return self.handle.fd == other.handle.fd;
}