authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-03 23:26:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-08 16:54:31-07:00
logef8772938811402262060436eb481586c8a81b3e
treee45d2858a59d90aa560282709bb6451ef3158cd4
parent24c8adc6ac40e5b73ae0caee0c559c008467d63a

Manifest: add top-level `paths` field for inclusion rules

See #14311

1 files changed, 30 insertions(+), 0 deletions(-)

src/Manifest.zig+30
......@@ -1,3 +1,4 @@
1pub const max_bytes = 10 * 1024 * 1024;
12pub const basename = "build.zig.zon";
23pub const Hash = std.crypto.hash.sha2.Sha256;
34
......@@ -50,6 +51,7 @@ pub const multihash_len = 1 + 1 + Hash.digest_length;
5051name: []const u8,
5152version: std.SemanticVersion,
5253dependencies: std.StringArrayHashMapUnmanaged(Dependency),
54paths: std.StringArrayHashMapUnmanaged(void),
5355
5456errors: []ErrorMessage,
5557arena_state: std.heap.ArenaAllocator.State,
......@@ -74,11 +76,13 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {
7476 .name = undefined,
7577 .version = undefined,
7678 .dependencies = .{},
79 .paths = .{},
7780 .buf = .{},
7881 };
7982 defer p.buf.deinit(gpa);
8083 defer p.errors.deinit(gpa);
8184 defer p.dependencies.deinit(gpa);
85 defer p.paths.deinit(gpa);
8286
8387 p.parseRoot(main_node_index) catch |err| switch (err) {
8488 error.ParseFailure => assert(p.errors.items.len > 0),
......@@ -89,6 +93,7 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {
8993 .name = p.name,
9094 .version = p.version,
9195 .dependencies = try p.dependencies.clone(p.arena),
96 .paths = try p.paths.clone(p.arena),
9297 .errors = try p.arena.dupe(ErrorMessage, p.errors.items),
9398 .arena_state = arena_instance.state,
9499 };
......@@ -143,6 +148,7 @@ const Parse = struct {
143148 name: []const u8,
144149 version: std.SemanticVersion,
145150 dependencies: std.StringArrayHashMapUnmanaged(Dependency),
151 paths: std.StringArrayHashMapUnmanaged(void),
146152
147153 const InnerError = error{ ParseFailure, OutOfMemory };
148154
......@@ -158,6 +164,7 @@ const Parse = struct {
158164
159165 var have_name = false;
160166 var have_version = false;
167 var have_included_paths = false;
161168
162169 for (struct_init.ast.fields) |field_init| {
163170 const name_token = ast.firstToken(field_init) - 2;
......@@ -167,6 +174,8 @@ const Parse = struct {
167174 // that is desirable on a per-field basis.
168175 if (mem.eql(u8, field_name, "dependencies")) {
169176 try parseDependencies(p, field_init);
177 } else if (mem.eql(u8, field_name, "paths")) {
178 try parseIncludedPaths(p, field_init);
170179 } else if (mem.eql(u8, field_name, "name")) {
171180 p.name = try parseString(p, field_init);
172181 have_name = true;
......@@ -190,6 +199,10 @@ const Parse = struct {
190199 if (!have_version) {
191200 try appendError(p, main_token, "missing top-level 'version' field", .{});
192201 }
202
203 if (!have_included_paths) {
204 try appendError(p, main_token, "missing top-level 'paths' field", .{});
205 }
193206 }
194207
195208 fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void {
......@@ -277,6 +290,23 @@ const Parse = struct {
277290 return dep;
278291 }
279292
293 fn parseIncludedPaths(p: *Parse, node: Ast.Node.Index) !void {
294 const ast = p.ast;
295 const main_tokens = ast.nodes.items(.main_token);
296
297 var buf: [2]Ast.Node.Index = undefined;
298 const array_init = ast.fullArrayInit(&buf, node) orelse {
299 const tok = main_tokens[node];
300 return fail(p, tok, "expected paths expression to be a struct", .{});
301 };
302
303 for (array_init.ast.elements) |elem_node| {
304 const path_string = try parseString(p, elem_node);
305 const normalized = try std.fs.path.resolve(p.arena, &.{path_string});
306 try p.paths.put(p.gpa, normalized, {});
307 }
308 }
309
280310 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {
281311 const ast = p.ast;
282312 const node_tags = ast.nodes.items(.tag);