Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand zig fetch usage help doc to explain URL #22850

Merged
merged 4 commits into from
Feb 13, 2025

Conversation

mtlynch
Copy link
Contributor

@mtlynch mtlynch commented Feb 11, 2025

The current zig fetch help docs tell the user to specify a package's URL, but it's unclear what the URL should be.

This change expands the help output to explain what URLs the zig fetch command can handle and provides examples of valid URLs.

Related: #20096

The current zig fetch help docs tell the user to specify a package's URL, but it's unclear what the URL should be.

This change expands the help output to explain what URLs the zig fetch command can handle and provides examples of valid URLs.

Related: ziglang#20096
src/main.zig Outdated Show resolved Hide resolved
src/main.zig Outdated Show resolved Hide resolved
@zaddok
Copy link

zaddok commented Feb 11, 2025

What is the format for actual git urls (so not https?) i.e this doesnt work:

% zig fetch --save git://git.server.com:/home/git/praxis
error: 'git://git.server.com:/home/git/praxis' could not be recognized as a file path (FileNotFound) or an URL (InvalidPort)

Is this a documentation issue, or regular non http git is not supported?

@zaddok
Copy link

zaddok commented Feb 11, 2025

Just testing, these dont work either:

% zig fetch --save git+ssh://[email protected]:/home/git/praxis
error: 'git+ssh://[email protected]:/home/git/praxis' could not be recognized as a file path (FileNotFound) or an URL (InvalidPort)

% zig fetch --save git://[email protected]:/home/git/praxis
error: 'git://[email protected]:/home/git/praxis' could not be recognized as a file path (FileNotFound) or an URL (InvalidPort)

% zig fetch --save git+ssh://git.server.com:/home/git/praxis
error: 'git://[email protected]:/home/git/praxis' could not be recognized as a file path (FileNotFound) or an URL (InvalidPort)

Oh, I just found #14295

Should the documentation mention that only https is supported?

@mtlynch
Copy link
Contributor Author

mtlynch commented Feb 11, 2025

Is this a documentation issue, or regular non http git is not supported?

I'm writing the documentation based on inspecting the code and manually testing, as I wasn't involved in the implementation, but I believe that zig fetch only supports http, https, git+http, and git+https protocols:

zig/src/Package/Fetch.zig

Lines 911 to 1047 in 4162f40

fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Resource {
const gpa = f.arena.child_allocator;
const arena = f.arena.allocator();
const eb = &f.error_bundle;
if (ascii.eqlIgnoreCase(uri.scheme, "file")) {
const path = try uri.path.toRawMaybeAlloc(arena);
return .{ .file = f.parent_package_root.openFile(path, .{}) catch |err| {
return f.fail(f.location_tok, try eb.printString("unable to open '{}{s}': {s}", .{
f.parent_package_root, path, @errorName(err),
}));
} };
}
const http_client = f.job_queue.http_client;
if (ascii.eqlIgnoreCase(uri.scheme, "http") or
ascii.eqlIgnoreCase(uri.scheme, "https"))
{
var req = http_client.open(.GET, uri, .{
.server_header_buffer = server_header_buffer,
}) catch |err| {
return f.fail(f.location_tok, try eb.printString(
"unable to connect to server: {s}",
.{@errorName(err)},
));
};
errdefer req.deinit(); // releases more than memory
req.send() catch |err| {
return f.fail(f.location_tok, try eb.printString(
"HTTP request failed: {s}",
.{@errorName(err)},
));
};
req.wait() catch |err| {
return f.fail(f.location_tok, try eb.printString(
"invalid HTTP response: {s}",
.{@errorName(err)},
));
};
if (req.response.status != .ok) {
return f.fail(f.location_tok, try eb.printString(
"bad HTTP response code: '{d} {s}'",
.{ @intFromEnum(req.response.status), req.response.status.phrase() orelse "" },
));
}
return .{ .http_request = req };
}
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(gpa, http_client, transport_uri, server_header_buffer) catch |err| {
return f.fail(f.location_tok, try eb.printString(
"unable to discover remote git server capabilities: {s}",
.{@errorName(err)},
));
};
errdefer session.deinit();
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 = session.listRefs(.{
.ref_prefixes = &.{ want_ref, want_ref_head, want_ref_tag },
.include_peeled = true,
.server_header_buffer = server_header_buffer,
}) catch |err| {
return f.fail(f.location_tok, try eb.printString(
"unable to list refs: {s}",
.{@errorName(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] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("try .url = \"{;+/}#{}\",", .{ uri, want_oid }),
}));
return error.FetchFailed;
}
var want_oid_buf: [git.Oid.max_formatted_length]u8 = undefined;
_ = std.fmt.bufPrint(&want_oid_buf, "{}", .{want_oid}) catch unreachable;
var fetch_stream = session.fetch(&.{&want_oid_buf}, server_header_buffer) catch |err| {
return f.fail(f.location_tok, try eb.printString(
"unable to create fetch stream: {s}",
.{@errorName(err)},
));
};
errdefer fetch_stream.deinit();
return .{ .git = .{
.session = session,
.fetch_stream = fetch_stream,
.want_oid = want_oid,
} };
}
return f.fail(f.location_tok, try eb.printString(
"unsupported URL scheme: {s}",
.{uri.scheme},
));
}

@zaddok
Copy link

zaddok commented Feb 11, 2025

This is definitely an improvement. I am just brainstorming out loud and wondering if making it explicit that git+ssh is not supported might save some people in the future some confusion. I read ‘git+https’ as meaning the url format works, rather than only the http/https versions. Especially since it looks like git+ssh support might be a year away?

@zaddok
Copy link

zaddok commented Feb 12, 2025

I feel a bit bad that my comment might slow down just pushing this forward. I only landed here because of a google search to find out why this stuff is not working. Perhaps at the end of the list a comment could be added.

git+ssh is not yet supported.

A git bundle file seems to be the more accurate term, as it's what git uses in its documentation: https://git-scm.com/docs/git-bundle
@mtlynch
Copy link
Contributor Author

mtlynch commented Feb 12, 2025

Perhaps at the end of the list a comment could be added.

git+ssh is not yet supported.

I don't think we should add that, as there are a lot of protocols zig fetch currently does not support but might in the future. I'd hope that the list of supported URL types should give the user enough information about which URLs zig fetch supports.

@andrewrk andrewrk merged commit cb5547e into ziglang:master Feb 13, 2025
9 checks passed
@andrewrk
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants