Commit 1c0d6f9c00

Andrew Kelley <andrew@ziglang.org>
2023-10-07 02:41:29
require inclusion directives in root manifest but not deps
see #14311
1 parent d0bcc39
Changed files (3)
src/Package/Fetch.zig
@@ -38,6 +38,10 @@ job_queue: *JobQueue,
 /// If true, don't add an error for a missing hash. This flag is not passed
 /// down to recursive dependencies. It's intended to be used only be the CLI.
 omit_missing_hash_error: bool,
+/// If true, don't fail when a manifest file is missing the `paths` field,
+/// which specifies inclusion rules. This is intended to be true for the first
+/// fetch task and false for the recursive dependencies.
+allow_missing_paths_field: bool,
 
 // Above this are fields provided as inputs to `run`.
 // Below this are fields populated by `run`.
@@ -365,7 +369,9 @@ fn loadManifest(f: *Fetch, pkg_root: Package.Path) RunError!void {
         return error.FetchFailed;
     }
 
-    f.manifest = try Manifest.parse(arena, ast.*);
+    f.manifest = try Manifest.parse(arena, ast.*, .{
+        .allow_missing_paths_field = f.allow_missing_paths_field,
+    });
     const manifest = &f.manifest.?;
 
     if (manifest.errors.len > 0) {
@@ -452,6 +458,7 @@ fn queueJobsForDeps(f: *Fetch, hash: Manifest.MultiHashHexDigest) RunError!void
                 .prog_node = f.prog_node,
                 .job_queue = f.job_queue,
                 .omit_missing_hash_error = false,
+                .allow_missing_paths_field = false,
 
                 .package_root = undefined,
                 .error_bundle = undefined,
@@ -481,7 +488,7 @@ fn queueJobsForDeps(f: *Fetch, hash: Manifest.MultiHashHexDigest) RunError!void
     }
 }
 
-fn workerRun(f: *Fetch) void {
+pub fn workerRun(f: *Fetch) void {
     defer f.job_queue.wait_group.finish();
     run(f) catch |err| switch (err) {
         error.OutOfMemory => f.oom_flag = true,
src/main.zig
@@ -6640,7 +6640,6 @@ fn cmdFetch(
         std.process.hasEnvVarConstant("ZIG_BTRFS_WORKAROUND");
     var opt_path_or_url: ?[]const u8 = null;
     var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR");
-    var recursive = false;
 
     {
         var i: usize = 0;
@@ -6656,9 +6655,6 @@ fn cmdFetch(
                     i += 1;
                     override_global_cache_dir = args[i];
                     continue;
-                } else if (mem.eql(u8, arg, "--recursive")) {
-                    recursive = true;
-                    continue;
                 } else {
                     fatal("unrecognized parameter: '{s}'", .{arg});
                 }
@@ -6696,7 +6692,7 @@ fn cmdFetch(
         .http_client = &http_client,
         .thread_pool = &thread_pool,
         .global_cache = global_cache_directory,
-        .recursive = recursive,
+        .recursive = false,
         .work_around_btrfs_bug = work_around_btrfs_bug,
     };
     defer job_queue.deinit();
@@ -6711,6 +6707,7 @@ fn cmdFetch(
         .prog_node = root_prog_node,
         .job_queue = &job_queue,
         .omit_missing_hash_error = true,
+        .allow_missing_paths_field = true,
 
         .package_root = undefined,
         .error_bundle = undefined,
src/Manifest.zig
@@ -59,9 +59,13 @@ paths: std.StringArrayHashMapUnmanaged(void),
 errors: []ErrorMessage,
 arena_state: std.heap.ArenaAllocator.State,
 
+pub const ParseOptions = struct {
+    allow_missing_paths_field: bool = false,
+};
+
 pub const Error = Allocator.Error;
 
-pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {
+pub fn parse(gpa: Allocator, ast: std.zig.Ast, options: ParseOptions) Error!Manifest {
     const node_tags = ast.nodes.items(.tag);
     const node_datas = ast.nodes.items(.data);
     assert(node_tags[0] == .root);
@@ -80,6 +84,7 @@ pub fn parse(gpa: Allocator, ast: std.zig.Ast) Error!Manifest {
         .version = undefined,
         .dependencies = .{},
         .paths = .{},
+        .allow_missing_paths_field = options.allow_missing_paths_field,
         .buf = .{},
     };
     defer p.buf.deinit(gpa);
@@ -152,6 +157,7 @@ const Parse = struct {
     version: std.SemanticVersion,
     dependencies: std.StringArrayHashMapUnmanaged(Dependency),
     paths: std.StringArrayHashMapUnmanaged(void),
+    allow_missing_paths_field: bool,
 
     const InnerError = error{ ParseFailure, OutOfMemory };
 
@@ -178,6 +184,7 @@ const Parse = struct {
             if (mem.eql(u8, field_name, "dependencies")) {
                 try parseDependencies(p, field_init);
             } else if (mem.eql(u8, field_name, "paths")) {
+                have_included_paths = true;
                 try parseIncludedPaths(p, field_init);
             } else if (mem.eql(u8, field_name, "name")) {
                 p.name = try parseString(p, field_init);
@@ -204,7 +211,11 @@ const Parse = struct {
         }
 
         if (!have_included_paths) {
-            try appendError(p, main_token, "missing top-level 'paths' field", .{});
+            if (p.allow_missing_paths_field) {
+                try p.paths.put(p.gpa, "", {});
+            } else {
+                try appendError(p, main_token, "missing top-level 'paths' field", .{});
+            }
         }
     }