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 @@...@@ -1,3 +1,4 @@
1pub const max_bytes = 10 * 1024 * 1024;
1pub const basename = "build.zig.zon";2pub const basename = "build.zig.zon";
2pub const Hash = std.crypto.hash.sha2.Sha256;3pub const Hash = std.crypto.hash.sha2.Sha256;
34
...@@ -50,6 +51,7 @@ pub const multihash_len = 1 + 1 + Hash.digest_length;...@@ -50,6 +51,7 @@ pub const multihash_len = 1 + 1 + Hash.digest_length;
50name: []const u8,51name: []const u8,
51version: std.SemanticVersion,52version: std.SemanticVersion,
52dependencies: std.StringArrayHashMapUnmanaged(Dependency),53dependencies: std.StringArrayHashMapUnmanaged(Dependency),
54paths: std.StringArrayHashMapUnmanaged(void),
5355
54errors: []ErrorMessage,56errors: []ErrorMessage,
55arena_state: std.heap.ArenaAllocator.State,57arena_state: std.heap.ArenaAllocator.State,
...@@ -74,11 +76,13 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {...@@ -74,11 +76,13 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {
74 .name = undefined,76 .name = undefined,
75 .version = undefined,77 .version = undefined,
76 .dependencies = .{},78 .dependencies = .{},
79 .paths = .{},
77 .buf = .{},80 .buf = .{},
78 };81 };
79 defer p.buf.deinit(gpa);82 defer p.buf.deinit(gpa);
80 defer p.errors.deinit(gpa);83 defer p.errors.deinit(gpa);
81 defer p.dependencies.deinit(gpa);84 defer p.dependencies.deinit(gpa);
85 defer p.paths.deinit(gpa);
8286
83 p.parseRoot(main_node_index) catch |err| switch (err) {87 p.parseRoot(main_node_index) catch |err| switch (err) {
84 error.ParseFailure => assert(p.errors.items.len > 0),88 error.ParseFailure => assert(p.errors.items.len > 0),
...@@ -89,6 +93,7 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {...@@ -89,6 +93,7 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {
89 .name = p.name,93 .name = p.name,
90 .version = p.version,94 .version = p.version,
91 .dependencies = try p.dependencies.clone(p.arena),95 .dependencies = try p.dependencies.clone(p.arena),
96 .paths = try p.paths.clone(p.arena),
92 .errors = try p.arena.dupe(ErrorMessage, p.errors.items),97 .errors = try p.arena.dupe(ErrorMessage, p.errors.items),
93 .arena_state = arena_instance.state,98 .arena_state = arena_instance.state,
94 };99 };
...@@ -143,6 +148,7 @@ const Parse = struct {...@@ -143,6 +148,7 @@ const Parse = struct {
143 name: []const u8,148 name: []const u8,
144 version: std.SemanticVersion,149 version: std.SemanticVersion,
145 dependencies: std.StringArrayHashMapUnmanaged(Dependency),150 dependencies: std.StringArrayHashMapUnmanaged(Dependency),
151 paths: std.StringArrayHashMapUnmanaged(void),
146152
147 const InnerError = error{ ParseFailure, OutOfMemory };153 const InnerError = error{ ParseFailure, OutOfMemory };
148154
...@@ -158,6 +164,7 @@ const Parse = struct {...@@ -158,6 +164,7 @@ const Parse = struct {
158164
159 var have_name = false;165 var have_name = false;
160 var have_version = false;166 var have_version = false;
167 var have_included_paths = false;
161168
162 for (struct_init.ast.fields) |field_init| {169 for (struct_init.ast.fields) |field_init| {
163 const name_token = ast.firstToken(field_init) - 2;170 const name_token = ast.firstToken(field_init) - 2;
...@@ -167,6 +174,8 @@ const Parse = struct {...@@ -167,6 +174,8 @@ const Parse = struct {
167 // that is desirable on a per-field basis.174 // that is desirable on a per-field basis.
168 if (mem.eql(u8, field_name, "dependencies")) {175 if (mem.eql(u8, field_name, "dependencies")) {
169 try parseDependencies(p, field_init);176 try parseDependencies(p, field_init);
177 } else if (mem.eql(u8, field_name, "paths")) {
178 try parseIncludedPaths(p, field_init);
170 } else if (mem.eql(u8, field_name, "name")) {179 } else if (mem.eql(u8, field_name, "name")) {
171 p.name = try parseString(p, field_init);180 p.name = try parseString(p, field_init);
172 have_name = true;181 have_name = true;
...@@ -190,6 +199,10 @@ const Parse = struct {...@@ -190,6 +199,10 @@ const Parse = struct {
190 if (!have_version) {199 if (!have_version) {
191 try appendError(p, main_token, "missing top-level 'version' field", .{});200 try appendError(p, main_token, "missing top-level 'version' field", .{});
192 }201 }
202
203 if (!have_included_paths) {
204 try appendError(p, main_token, "missing top-level 'paths' field", .{});
205 }
193 }206 }
194207
195 fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void {208 fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void {
...@@ -277,6 +290,23 @@ const Parse = struct {...@@ -277,6 +290,23 @@ const Parse = struct {
277 return dep;290 return dep;
278 }291 }
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
280 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {310 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {
281 const ast = p.ast;311 const ast = p.ast;
282 const node_tags = ast.nodes.items(.tag);312 const node_tags = ast.nodes.items(.tag);