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.

operate

WriteFile.operate
fn operate(
    maker: *Maker,
    step_index: Configuration.Step.Index,
    open_dir_cache: []const Io.Dir,
    root_path: std.Build.Cache.Path,
    progress_node: std.Progress.Node,
) !void

File

lib/compiler/Maker/Step/WriteFile.zig:154

Code

fn operate(
    maker: *Maker,
    step_index: Configuration.Step.Index,
    open_dir_cache: []const Io.Dir,
    root_path: std.Build.Cache.Path,
    progress_node: std.Progress.Node,
) !void {
    const graph = maker.graph;
    const gpa = maker.gpa;
    const arena = maker.graph.arena; // TODO don't leak into process arena
    const io = graph.io;
    const step = maker.stepByIndex(step_index);
    const conf = &maker.scanned_config.configuration;
    const conf_step = step_index.ptr(conf);
    const conf_wf = conf_step.extended.get(conf.extra).write_file;

    const root_directory: std.Build.Cache.Directory = .{
        .handle = root_path.root_dir.handle.createDirPathOpen(io, root_path.sub_path, .{}) catch |err|
            return step.fail(maker, "failed creating path {f}: {t}", .{ root_path, err }),
        .path = try root_path.toString(arena),
    };
    defer root_directory.handle.close(io);

    for (conf_wf.embeds.slice) |*embed| {
        const dest_path: Path = .{
            .root_dir = root_directory,
            .sub_path = embed.sub_path.slice(conf),
        };
        if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| {
            const dirname_path: Path = .{
                .root_dir = root_directory,
                .sub_path = dirname,
            };
            dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err|
                return step.fail(maker, "failed creating path {f}: {t}", .{ dirname_path, err });
        }
        dest_path.root_dir.handle.writeFile(io, .{
            .sub_path = dest_path.sub_path,
            .data = embed.contents.slice(conf),
        }) catch |err| return step.fail(maker, "failed writing contents to file {f}: {t}", .{ dest_path, err });
        progress_node.completeOne();
    }

    for (conf_wf.copies.slice) |*copy| {
        const dest_path: Path = .{
            .root_dir = root_directory,
            .sub_path = copy.sub_path.slice(conf),
        };
        // Rather than passing make_path = true below, this optimizes for the
        // more common case where the directory does not exist.
        if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| {
            const dirname_path: Path = .{
                .root_dir = root_directory,
                .sub_path = dirname,
            };
            dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err|
                return step.fail(maker, "failed creating path {f}: {t}", .{ dirname_path, err });
        }
        const source_path = try maker.resolveLazyPathIndex(arena, copy.src_file, step_index);
        Io.Dir.copyFile(
            source_path.root_dir.handle,
            source_path.sub_path,
            dest_path.root_dir.handle,
            dest_path.sub_path,
            io,
            .{},
        ) catch |err| return step.fail(maker, "failed copying file from {f} to {f}: {t}", .{
            source_path, dest_path, err,
        });
        progress_node.completeOne();
    }

    for (conf_wf.directories.slice, open_dir_cache) |conf_dir, already_open_dir| {
        const exclude_extensions = conf_dir.exclude_extensions.slice(conf) orelse &.{};
        const include_extensions = conf_dir.include_extensions.slice(conf);

        const src_dir_path = try maker.resolveLazyPathIndex(arena, conf_dir.src_path, step_index);
        const dest_dir_path: Path = .{
            .root_dir = root_directory,
            .sub_path = conf_dir.sub_path.slice(conf),
        };

        if (dest_dir_path.sub_path.len != 0) {
            dest_dir_path.root_dir.handle.createDirPath(io, dest_dir_path.sub_path) catch |err|
                return step.fail(maker, "failed creating path {f}: {t}", .{ dest_dir_path, err });
        }

        var it = try already_open_dir.walk(gpa);
        defer it.deinit();
        while (it.next(io) catch |err| switch (err) {
            error.Canceled, error.OutOfMemory => |e| return e,
            else => |e| return step.fail(maker, "failed iterating dir {f}: {t}", .{ src_dir_path, e }),
        }) |entry| {
            if (!pathIncluded(conf, exclude_extensions, include_extensions, entry.path)) continue;

            const src_entry_path = try src_dir_path.join(arena, entry.path);
            const dest_path = try dest_dir_path.join(arena, entry.path);
            switch (entry.kind) {
                .directory => dest_path.root_dir.handle.createDirPath(io, dest_path.sub_path) catch |err| {
                    return step.fail(maker, "failed creating path {f}: {t}", .{ dest_path, err });
                },
                .file => {
                    Io.Dir.copyFile(
                        src_entry_path.root_dir.handle,
                        src_entry_path.sub_path,
                        dest_path.root_dir.handle,
                        dest_path.sub_path,
                        io,
                        .{ .make_path = true }, // Directory entry may be filtered out above.
                    ) catch |err| return step.fail(maker, "failed copying file from {f} to {f}: {t}", .{
                        src_entry_path, dest_path, err,
                    });
                    progress_node.completeOne();
                },
                else => continue,
            }
        }
    }
}