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.

initResource

Fetch.initResource
fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u8) RunError!void

File

lib/compiler/Maker/Fetch.zig:1193

Code

fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u8) RunError!void {
    const io = f.job_queue.io;
    const arena = f.arena.allocator();
    const eb = &f.error_bundle;

    if (ascii.eqlIgnoreCase(uri.scheme, "file")) {
        const path = try uri.path.toRawMaybeAlloc(arena);
        const file = f.parent_package_root.openFile(io, path, .{}) catch |err| {
            return f.fail(f.location_tok, try eb.printString("unable to open {f}/{s}: {t}", .{
                f.parent_package_root, path, err,
            }));
        };
        resource.* = .{ .file = file.reader(io, reader_buffer) };
        return;
    }

    const http_client = f.job_queue.http_client;

    if (ascii.eqlIgnoreCase(uri.scheme, "http") or
        ascii.eqlIgnoreCase(uri.scheme, "https"))
    {
        resource.* = .{ .http_request = .{
            .request = http_client.request(.GET, uri, .{}) catch |err|
                return f.fail(f.location_tok, try eb.printString("server connection failed: {t}", .{err})),
            .response = undefined,
            .transfer_buffer = reader_buffer,
            .decompress_buffer = &.{},
            .decompress = undefined,
        } };
        const request = &resource.http_request.request;
        errdefer request.deinit();

        request.sendBodiless() catch |err|
            return f.fail(f.location_tok, try eb.printString("HTTP request failed: {t}", .{err}));

        var redirect_buffer: [8000]u8 = undefined;
        const response = &resource.http_request.response;
        response.* = request.receiveHead(&redirect_buffer) catch |err| switch (err) {
            error.ReadFailed => {
                return f.fail(f.location_tok, try eb.printString("HTTP response read failure: {t}", .{
                    request.connection.?.getReadError().?,
                }));
            },
            else => |e| return f.fail(f.location_tok, try eb.printString("invalid HTTP response: {t}", .{e})),
        };

        if (response.head.status != .ok) return f.fail(f.location_tok, try eb.printString(
            "bad HTTP response code: '{d} {s}'",
            .{ response.head.status, response.head.status.phrase() orelse "" },
        ));

        resource.http_request.decompress_buffer = try arena.alloc(u8, response.head.content_encoding.minBufferCapacity());
        return;
    }

    if (ascii.eqlIgnoreCase(uri.scheme, "git+http") or
        ascii.eqlIgnoreCase(uri.scheme, "git+https"))
    {
        var transport_uri = uri;
        transport_uri.scheme = uri.scheme["git+".len..];
        var session = git.Session.init(arena, http_client, transport_uri, reader_buffer) catch |err| {
            return f.fail(
                f.location_tok,
                try eb.printString("unable to discover remote git server capabilities: {t}", .{err}),
            );
        };

        const want_oid = want_oid: {
            const want_ref =
                if (uri.fragment) |fragment| try fragment.toRawMaybeAlloc(arena) else "HEAD";
            if (git.Oid.parseAny(want_ref)) |oid| break :want_oid oid else |_| {}

            const want_ref_head = try std.fmt.allocPrint(arena, "refs/heads/{s}", .{want_ref});
            const want_ref_tag = try std.fmt.allocPrint(arena, "refs/tags/{s}", .{want_ref});

            var ref_iterator: git.Session.RefIterator = undefined;
            session.listRefs(&ref_iterator, .{
                .ref_prefixes = &.{ want_ref, want_ref_head, want_ref_tag },
                .include_peeled = true,
                .buffer = reader_buffer,
            }) catch |err| return f.fail(f.location_tok, try eb.printString("unable to list refs: {t}", .{err}));
            defer ref_iterator.deinit();
            while (ref_iterator.next() catch |err| {
                return f.fail(f.location_tok, try eb.printString(
                    "unable to iterate refs: {s}",
                    .{@errorName(err)},
                ));
            }) |ref| {
                if (std.mem.eql(u8, ref.name, want_ref) or
                    std.mem.eql(u8, ref.name, want_ref_head) or
                    std.mem.eql(u8, ref.name, want_ref_tag))
                {
                    break :want_oid ref.peeled orelse ref.oid;
                }
            }
            return f.fail(f.location_tok, try eb.printString("ref not found: {s}", .{want_ref}));
        };
        if (f.use_latest_commit) {
            f.latest_commit = want_oid;
        } else if (uri.fragment == null) {
            const notes_len = 1;
            try eb.addRootErrorMessage(.{
                .msg = try eb.addString("url field is missing an explicit ref"),
                .src_loc = try f.srcLoc(f.location_tok),
                .notes_len = notes_len,
            });
            const notes_start = try eb.reserveNotes(notes_len);
            eb.extra.items[notes_start] = @backingInt(try eb.addErrorMessage(.{
                .msg = try eb.printString("try .url = \"{f}#{f}\",", .{
                    uri.fmt(.{ .scheme = true, .authority = true, .path = true }),
                    want_oid,
                }),
            }));
            return error.FetchFailed;
        }

        var want_oid_buf: [git.Oid.max_formatted_length]u8 = undefined;
        _ = std.fmt.bufPrint(&want_oid_buf, "{f}", .{want_oid}) catch unreachable;
        resource.* = .{ .git = .{
            .session = session,
            .fetch_stream = undefined,
            .want_oid = want_oid,
        } };
        const fetch_stream = &resource.git.fetch_stream;
        session.fetch(fetch_stream, &.{&want_oid_buf}, reader_buffer) catch |err| {
            return f.fail(f.location_tok, try eb.printString("unable to create fetch stream: {t}", .{err}));
        };
        errdefer fetch_stream.deinit(fetch_stream);

        return;
    }

    return f.fail(f.location_tok, try eb.printString("unsupported URL scheme: {s}", .{uri.scheme}));
}