Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

queueJobsForDeps

Fetch.queueJobsForDeps
fn queueJobsForDeps(f: *Fetch) RunError!void

File

lib/compiler/Maker/Fetch.zig:903

Code

fn queueJobsForDeps(f: *Fetch) RunError!void {
    const io = f.job_queue.io;

    assert(f.job_queue.recursive);

    // If the package does not have a build.zig.zon file then there are no dependencies.
    if (!f.have_manifest) return;
    const manifest = &f.manifest;

    const new_fetches, const prog_names = nf: {
        const parent_arena = f.arena.allocator();
        const gpa = f.arena.child_allocator;
        const cache_root = f.job_queue.global_cache;
        const dep_names = manifest.dependencies.keys();
        const deps = manifest.dependencies.values();
        // Grab the new tasks into a temporary buffer so we can unlock that mutex
        // as fast as possible.
        // This overallocates any fetches that get skipped by the `continue` in the
        // loop below.
        const new_fetches = try parent_arena.alloc(Fetch, deps.len);
        const prog_names = try parent_arena.alloc([]const u8, deps.len);
        var new_fetch_index: usize = 0;

        try f.job_queue.mutex.lock(io);
        defer f.job_queue.mutex.unlock(io);

        try f.job_queue.all_fetches.ensureUnusedCapacity(gpa, new_fetches.len);
        try f.job_queue.table.ensureUnusedCapacity(gpa, @intCast(new_fetches.len));

        // There are four cases here:
        // * Correct hash is provided by manifest.
        //   - Hash map already has the entry, no need to add it again.
        // * Incorrect hash is provided by manifest.
        //   - Hash mismatch error emitted; `queueJobsForDeps` is not called.
        // * Hash is not provided by manifest.
        //   - Hash missing error emitted; `queueJobsForDeps` is not called.
        // * path-based location is used without a hash.
        //   - Hash is added to the table based on the path alone before
        //     calling run(); no need to add it again.
        //
        // If we add a dep as lazy and then later try to add the same dep as eager,
        // eagerness takes precedence and the existing entry is updated and re-scheduled
        // for fetching.

        for (dep_names, deps) |dep_name, dep| {
            var promoted_existing_to_eager = false;
            const new_fetch = &new_fetches[new_fetch_index];
            const location: Location = switch (dep.location) {
                .url => |url| .{
                    .remote = .{
                        .url = url,
                        .hash = h: {
                            const h = dep.hash orelse break :h null;
                            const pkg_hash: Package.Hash = .fromSlice(h);
                            if (h.len == 0) break :h pkg_hash;
                            const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash);
                            if (gop.found_existing) {
                                if (!dep.lazy and gop.value_ptr.*.lazy_status != .eager) {
                                    gop.value_ptr.*.lazy_status = .eager;
                                    promoted_existing_to_eager = true;
                                } else {
                                    continue;
                                }
                            }
                            gop.value_ptr.* = new_fetch;
                            break :h pkg_hash;
                        },
                    },
                },
                .path => |rel_path| l: {
                    // This might produce an invalid path, which is checked for
                    // at the beginning of run().
                    const new_root = try f.package_root.resolvePosix(parent_arena, rel_path);
                    const pkg_hash = relativePathDigest(new_root, cache_root);
                    const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash);
                    if (gop.found_existing) {
                        if (!dep.lazy and gop.value_ptr.*.lazy_status != .eager) {
                            gop.value_ptr.*.lazy_status = .eager;
                            promoted_existing_to_eager = true;
                        } else {
                            continue;
                        }
                    }
                    gop.value_ptr.* = new_fetch;
                    break :l .{ .relative_path = new_root };
                },
            };
            prog_names[new_fetch_index] = dep_name;
            new_fetch_index += 1;
            if (!promoted_existing_to_eager) {
                f.job_queue.all_fetches.appendAssumeCapacity(new_fetch);
            }
            new_fetch.* = .{
                .arena = std.heap.ArenaAllocator.init(gpa),
                .location = location,
                .location_tok = dep.location_tok,
                .hash_tok = dep.hash_tok,
                .name_tok = dep.name_tok,
                .lazy_status = switch (f.job_queue.mode) {
                    .needed => if (dep.lazy) .available else .eager,
                    .all => .eager,
                },
                .parent_package_root = f.package_root,
                .remote_package_root = f.remote_package_root,
                .parent_manifest_ast = &f.manifest_ast,
                .prog_node = f.prog_node,
                .job_queue = f.job_queue,
                .omit_missing_hash_error = false,
                .allow_missing_paths_field = true,
                .use_latest_commit = false,

                .package_root = undefined,
                .error_bundle = undefined,
                .manifest = undefined,
                .manifest_ast = undefined,
                .have_manifest = false,
                .computed_hash = undefined,
                .has_build_zig = false,
                .oom_flag = false,
                .latest_commit = null,

                .cli_module = null,
            };
        }

        f.prog_node.increaseEstimatedTotalItems(new_fetch_index);

        break :nf .{ new_fetches[0..new_fetch_index], prog_names[0..new_fetch_index] };
    };

    // Now it's time to dispatch tasks.
    for (new_fetches, prog_names) |*new_fetch, prog_name| {
        f.job_queue.group.async(io, workerRun, .{ new_fetch, prog_name });
    }
}