pub const Diagnostics = struct fn findRoot(d: *Diagnostics, kind: FileKind, path: []const u8) !voidfn rootDir(path: []const u8, kind: FileKind) []const u8Returns root dir of the path, assumes non empty path.
pub fn deinit(d: *Diagnostics) void30
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121pub const Diagnostics = struct {
allocator: std.mem.Allocator,
errors: std.ArrayList(Error) = .empty,
entries: usize = 0,
root_dir: []const u8 = "",
pub const Error = union(enum) {
unable_to_create_sym_link: struct {
code: anyerror,
file_name: []const u8,
link_name: []const u8,
},
unable_to_create_file: struct {
code: anyerror,
file_name: []const u8,
},
unsupported_file_type: struct {
file_name: []const u8,
file_type: Header.Kind,
},
components_outside_stripped_prefix: struct {
file_name: []const u8,
},
};
fn findRoot(d: *Diagnostics, kind: FileKind, path: []const u8) !void {
if (path.len == 0) return;
d.entries += 1;
const root_dir = rootDir(path, kind);
if (d.entries == 1) {
d.root_dir = try d.allocator.dupe(u8, root_dir);
return;
}
if (d.root_dir.len == 0 or std.mem.eql(u8, root_dir, d.root_dir))
return;
d.allocator.free(d.root_dir);
d.root_dir = "";
}
// Returns root dir of the path, assumes non empty path.
fn rootDir(path: []const u8, kind: FileKind) []const u8 {
const start_index: usize = if (path[0] == '/') 1 else 0;
const end_index: usize = if (path[path.len - 1] == '/') path.len - 1 else path.len;
const buf = path[start_index..end_index];
if (std.mem.findScalarPos(u8, buf, 0, '/')) |idx| {
return buf[0..idx];
}
return switch (kind) {
.file => "",
.sym_link => "",
.directory => buf,
};
}
test rootDir {
const expectEqualStrings = testing.expectEqualStrings;
try expectEqualStrings("", rootDir("a", .file));
try expectEqualStrings("a", rootDir("a", .directory));
try expectEqualStrings("b", rootDir("b", .directory));
try expectEqualStrings("c", rootDir("/c", .directory));
try expectEqualStrings("d", rootDir("/d/", .directory));
try expectEqualStrings("a", rootDir("a/b", .directory));
try expectEqualStrings("a", rootDir("a/b", .file));
try expectEqualStrings("a", rootDir("a/b/c", .directory));
}
pub fn deinit(d: *Diagnostics) void {
for (d.errors.items) |item| {
switch (item) {
.unable_to_create_sym_link => |info| {
d.allocator.free(info.file_name);
d.allocator.free(info.link_name);
},
.unable_to_create_file => |info| {
d.allocator.free(info.file_name);
},
.unsupported_file_type => |info| {
d.allocator.free(info.file_name);
},
.components_outside_stripped_prefix => |info| {
d.allocator.free(info.file_name);
},
}
}
d.errors.deinit(d.allocator);
d.allocator.free(d.root_dir);
d.* = undefined;
}
}
Provide this to receive detailed error messages. When this is provided, some errors which would otherwise be returned immediately will instead be added to this structure. The API user must check the errors in diagnostics to know whether the operation succeeded or failed.