diff --git a/src/Manifest.zig b/src/Manifest.zig index 2ff54e613266783c5716ab67864a5a3203d7bf73..ac384b8fcb64b2e97d334ebd431ecbca21365bc0 100644 --- a/src/Manifest.zig +++ b/src/Manifest.zig @@ -1,3 +1,4 @@ +pub const max_bytes = 10 * 1024 * 1024; pub const basename = "build.zig.zon"; pub const Hash = std.crypto.hash.sha2.Sha256; @@ -50,6 +51,7 @@ pub const multihash_len = 1 + 1 + Hash.digest_length; name: []const u8, version: std.SemanticVersion, dependencies: std.StringArrayHashMapUnmanaged(Dependency), +paths: std.StringArrayHashMapUnmanaged(void), errors: []ErrorMessage, arena_state: std.heap.ArenaAllocator.State, @@ -74,11 +76,13 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest { .name = undefined, .version = undefined, .dependencies = .{}, + .paths = .{}, .buf = .{}, }; defer p.buf.deinit(gpa); defer p.errors.deinit(gpa); defer p.dependencies.deinit(gpa); + defer p.paths.deinit(gpa); p.parseRoot(main_node_index) catch |err| switch (err) { error.ParseFailure => assert(p.errors.items.len > 0), @@ -89,6 +93,7 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest { .name = p.name, .version = p.version, .dependencies = try p.dependencies.clone(p.arena), + .paths = try p.paths.clone(p.arena), .errors = try p.arena.dupe(ErrorMessage, p.errors.items), .arena_state = arena_instance.state, }; @@ -143,6 +148,7 @@ const Parse = struct { name: []const u8, version: std.SemanticVersion, dependencies: std.StringArrayHashMapUnmanaged(Dependency), + paths: std.StringArrayHashMapUnmanaged(void), const InnerError = error{ ParseFailure, OutOfMemory }; @@ -158,6 +164,7 @@ const Parse = struct { var have_name = false; var have_version = false; + var have_included_paths = false; for (struct_init.ast.fields) |field_init| { const name_token = ast.firstToken(field_init) - 2; @@ -167,6 +174,8 @@ const Parse = struct { // that is desirable on a per-field basis. if (mem.eql(u8, field_name, "dependencies")) { try parseDependencies(p, field_init); + } else if (mem.eql(u8, field_name, "paths")) { + try parseIncludedPaths(p, field_init); } else if (mem.eql(u8, field_name, "name")) { p.name = try parseString(p, field_init); have_name = true; @@ -190,6 +199,10 @@ const Parse = struct { if (!have_version) { try appendError(p, main_token, "missing top-level 'version' field", .{}); } + + if (!have_included_paths) { + try appendError(p, main_token, "missing top-level 'paths' field", .{}); + } } fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void { @@ -277,6 +290,23 @@ const Parse = struct { return dep; } + fn parseIncludedPaths(p: *Parse, node: Ast.Node.Index) !void { + const ast = p.ast; + const main_tokens = ast.nodes.items(.main_token); + + var buf: [2]Ast.Node.Index = undefined; + const array_init = ast.fullArrayInit(&buf, node) orelse { + const tok = main_tokens[node]; + return fail(p, tok, "expected paths expression to be a struct", .{}); + }; + + for (array_init.ast.elements) |elem_node| { + const path_string = try parseString(p, elem_node); + const normalized = try std.fs.path.resolve(p.arena, &.{path_string}); + try p.paths.put(p.gpa, normalized, {}); + } + } + fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 { const ast = p.ast; const node_tags = ast.nodes.items(.tag);