Skip to content

Commit

Permalink
Manifest: add top-level paths field for inclusion rules
Browse files Browse the repository at this point in the history
See #14311
  • Loading branch information
andrewrk committed Oct 4, 2023
1 parent 00e98dc commit 2f4bead
Showing 1 changed file with 30 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/Manifest.zig
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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,
Expand All @@ -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),
Expand All @@ -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,
};
Expand Down Expand Up @@ -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 };

Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 2f4bead

Please sign in to comment.