Commit 57cfe0778c
src/Package/Fetch.zig
@@ -44,6 +44,8 @@ omit_missing_hash_error: bool,
/// 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,
+/// If true and URL points to a Git repository, will use the latest commit.
+use_latest_commit: bool,
// Above this are fields provided as inputs to `run`.
// Below this are fields populated by `run`.
@@ -59,6 +61,8 @@ actual_hash: Manifest.Digest,
has_build_zig: bool,
/// Indicates whether the task aborted due to an out-of-memory condition.
oom_flag: bool,
+/// If `use_latest_commit` was true, this will be the commit that was used.
+latest_commit: ?git.Oid,
// This field is used by the CLI only, untouched by this file.
@@ -687,6 +691,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
.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,
@@ -695,6 +700,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
.actual_hash = undefined,
.has_build_zig = false,
.oom_flag = false,
+ .latest_commit = undefined,
.module = null,
};
@@ -987,7 +993,9 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
}
return f.fail(f.location_tok, try eb.printString("ref not found: {s}", .{want_ref}));
};
- if (uri.fragment == null) {
+ 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/main.zig
@@ -5098,6 +5098,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
.job_queue = &job_queue,
.omit_missing_hash_error = true,
.allow_missing_paths_field = false,
+ .use_latest_commit = false,
.package_root = undefined,
.error_bundle = undefined,
@@ -5106,6 +5107,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
.actual_hash = undefined,
.has_build_zig = true,
.oom_flag = false,
+ .latest_commit = undefined,
.module = build_mod,
};
@@ -6757,6 +6759,7 @@ const usage_fetch =
\\ --debug-hash Print verbose hash information to stdout
\\ --save Add the fetched package to build.zig.zon
\\ --save=[name] Add the fetched package to build.zig.zon as name
+ \\ --resolve-commit Before saving, replace the name of a Git branch/tag with its commit SHA
\\
;
@@ -6772,6 +6775,7 @@ fn cmdFetch(
var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
var debug_hash: bool = false;
var save: union(enum) { no, yes, name: []const u8 } = .no;
+ var resolve_commit: bool = false;
{
var i: usize = 0;
@@ -6792,6 +6796,8 @@ fn cmdFetch(
save = .yes;
} else if (mem.startsWith(u8, arg, "--save=")) {
save = .{ .name = arg["--save=".len..] };
+ } else if (mem.eql(u8, arg, "--resolve-commit")) {
+ resolve_commit = true;
} else {
fatal("unrecognized parameter: '{s}'", .{arg});
}
@@ -6803,6 +6809,9 @@ fn cmdFetch(
}
}
+ if (resolve_commit and save == .no)
+ warn("'--resolve-commit' has no effect unless used with '--save'", .{});
+
const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{});
var thread_pool: ThreadPool = undefined;
@@ -6851,6 +6860,7 @@ fn cmdFetch(
.job_queue = &job_queue,
.omit_missing_hash_error = true,
.allow_missing_paths_field = false,
+ .use_latest_commit = resolve_commit,
.package_root = undefined,
.error_bundle = undefined,
@@ -6859,6 +6869,7 @@ fn cmdFetch(
.actual_hash = undefined,
.has_build_zig = false,
.oom_flag = false,
+ .latest_commit = undefined,
.module = null,
};
@@ -6915,13 +6926,22 @@ fn cmdFetch(
var fixups: Ast.Fixups = .{};
defer fixups.deinit(gpa);
+ const saved_path_or_url = if (resolve_commit) blk: {
+ // replace the refspec with the latest commit SHA
+ var uri = try std.Uri.parse(path_or_url);
+ uri.fragment = try std.fmt.allocPrint(arena, "{}", .{
+ std.fmt.fmtSliceHexLower(&fetch.latest_commit.?),
+ });
+ break :blk try std.fmt.allocPrint(arena, "{}", .{uri});
+ } else path_or_url;
+
const new_node_init = try std.fmt.allocPrint(arena,
\\.{{
\\ .url = "{}",
\\ .hash = "{}",
\\ }}
, .{
- std.zig.fmtEscapes(path_or_url),
+ std.zig.fmtEscapes(saved_path_or_url),
std.zig.fmtEscapes(&hex_digest),
});