authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-10 16:27:30-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-05-10 16:27:30-07:00
log7fa2357d0586cef742bf691d69a6cffdd353b496
tree59c95aa76c03a8a0779446a00cd9a81822330004
parentcb77bd672c3b398e3c5f6be80af03243bf8638e3
parentdcffa7b2990046926aae782819a53dcd505aa4a3
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19349 from nolanderc/save-commit

`zig fetch`: resolve branch/tag names to commit SHA

2 files changed, 51 insertions(+), 3 deletions(-)

src/Package/Fetch.zig+9-1
...@@ -44,6 +44,8 @@ omit_missing_hash_error: bool,...@@ -44,6 +44,8 @@ omit_missing_hash_error: bool,
44/// which specifies inclusion rules. This is intended to be true for the first44/// which specifies inclusion rules. This is intended to be true for the first
45/// fetch task and false for the recursive dependencies.45/// fetch task and false for the recursive dependencies.
46allow_missing_paths_field: bool,46allow_missing_paths_field: bool,
47/// If true and URL points to a Git repository, will use the latest commit.
48use_latest_commit: bool,
4749
48// Above this are fields provided as inputs to `run`.50// Above this are fields provided as inputs to `run`.
49// Below this are fields populated by `run`.51// Below this are fields populated by `run`.
...@@ -59,6 +61,8 @@ actual_hash: Manifest.Digest,...@@ -59,6 +61,8 @@ actual_hash: Manifest.Digest,
59has_build_zig: bool,61has_build_zig: bool,
60/// Indicates whether the task aborted due to an out-of-memory condition.62/// Indicates whether the task aborted due to an out-of-memory condition.
61oom_flag: bool,63oom_flag: bool,
64/// If `use_latest_commit` was true, this will be the commit that was used.
65latest_commit: ?git.Oid,
6266
63// This field is used by the CLI only, untouched by this file.67// This field is used by the CLI only, untouched by this file.
6468
...@@ -699,6 +703,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {...@@ -699,6 +703,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
699 .job_queue = f.job_queue,703 .job_queue = f.job_queue,
700 .omit_missing_hash_error = false,704 .omit_missing_hash_error = false,
701 .allow_missing_paths_field = true,705 .allow_missing_paths_field = true,
706 .use_latest_commit = false,
702707
703 .package_root = undefined,708 .package_root = undefined,
704 .error_bundle = undefined,709 .error_bundle = undefined,
...@@ -707,6 +712,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {...@@ -707,6 +712,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
707 .actual_hash = undefined,712 .actual_hash = undefined,
708 .has_build_zig = false,713 .has_build_zig = false,
709 .oom_flag = false,714 .oom_flag = false,
715 .latest_commit = undefined,
710716
711 .module = null,717 .module = null,
712 };718 };
...@@ -994,7 +1000,9 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re...@@ -994,7 +1000,9 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
994 }1000 }
995 return f.fail(f.location_tok, try eb.printString("ref not found: {s}", .{want_ref}));1001 return f.fail(f.location_tok, try eb.printString("ref not found: {s}", .{want_ref}));
996 };1002 };
997 if (uri.fragment == null) {1003 if (f.use_latest_commit) {
1004 f.latest_commit = want_oid;
1005 } else if (uri.fragment == null) {
998 const notes_len = 1;1006 const notes_len = 1;
999 try eb.addRootErrorMessage(.{1007 try eb.addRootErrorMessage(.{
1000 .msg = try eb.addString("url field is missing an explicit ref"),1008 .msg = try eb.addString("url field is missing an explicit ref"),
src/main.zig+42-2
...@@ -5097,6 +5097,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5097,6 +5097,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5097 .job_queue = &job_queue,5097 .job_queue = &job_queue,
5098 .omit_missing_hash_error = true,5098 .omit_missing_hash_error = true,
5099 .allow_missing_paths_field = false,5099 .allow_missing_paths_field = false,
5100 .use_latest_commit = false,
51005101
5101 .package_root = undefined,5102 .package_root = undefined,
5102 .error_bundle = undefined,5103 .error_bundle = undefined,
...@@ -5105,6 +5106,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5105,6 +5106,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5105 .actual_hash = undefined,5106 .actual_hash = undefined,
5106 .has_build_zig = true,5107 .has_build_zig = true,
5107 .oom_flag = false,5108 .oom_flag = false,
5109 .latest_commit = undefined,
51085110
5109 .module = build_mod,5111 .module = build_mod,
5110 };5112 };
...@@ -6894,6 +6896,7 @@ const usage_fetch =...@@ -6894,6 +6896,7 @@ const usage_fetch =
6894 \\ --debug-hash Print verbose hash information to stdout6896 \\ --debug-hash Print verbose hash information to stdout
6895 \\ --save Add the fetched package to build.zig.zon6897 \\ --save Add the fetched package to build.zig.zon
6896 \\ --save=[name] Add the fetched package to build.zig.zon as name6898 \\ --save=[name] Add the fetched package to build.zig.zon as name
6899 \\ --preserve-url Store a verbatim copy of the URL in build.zig.zon
6897 \\6900 \\
6898;6901;
68996902
...@@ -6909,6 +6912,7 @@ fn cmdFetch(...@@ -6909,6 +6912,7 @@ fn cmdFetch(
6909 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);6912 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
6910 var debug_hash: bool = false;6913 var debug_hash: bool = false;
6911 var save: union(enum) { no, yes, name: []const u8 } = .no;6914 var save: union(enum) { no, yes, name: []const u8 } = .no;
6915 var preserve_url: bool = false;
69126916
6913 {6917 {
6914 var i: usize = 0;6918 var i: usize = 0;
...@@ -6929,6 +6933,8 @@ fn cmdFetch(...@@ -6929,6 +6933,8 @@ fn cmdFetch(
6929 save = .yes;6933 save = .yes;
6930 } else if (mem.startsWith(u8, arg, "--save=")) {6934 } else if (mem.startsWith(u8, arg, "--save=")) {
6931 save = .{ .name = arg["--save=".len..] };6935 save = .{ .name = arg["--save=".len..] };
6936 } else if (mem.startsWith(u8, arg, "--preserve-url")) {
6937 preserve_url = true;
6932 } else {6938 } else {
6933 fatal("unrecognized parameter: '{s}'", .{arg});6939 fatal("unrecognized parameter: '{s}'", .{arg});
6934 }6940 }
...@@ -6940,6 +6946,8 @@ fn cmdFetch(...@@ -6940,6 +6946,8 @@ fn cmdFetch(
6940 }6946 }
6941 }6947 }
69426948
6949 if (preserve_url and save == .no) fatal("use of '--preserve-url' requires '--save'", .{});
6950
6943 const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{});6951 const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{});
69446952
6945 var thread_pool: ThreadPool = undefined;6953 var thread_pool: ThreadPool = undefined;
...@@ -6988,6 +6996,7 @@ fn cmdFetch(...@@ -6988,6 +6996,7 @@ fn cmdFetch(
6988 .job_queue = &job_queue,6996 .job_queue = &job_queue,
6989 .omit_missing_hash_error = true,6997 .omit_missing_hash_error = true,
6990 .allow_missing_paths_field = false,6998 .allow_missing_paths_field = false,
6999 .use_latest_commit = true,
69917000
6992 .package_root = undefined,7001 .package_root = undefined,
6993 .error_bundle = undefined,7002 .error_bundle = undefined,
...@@ -6996,6 +7005,7 @@ fn cmdFetch(...@@ -6996,6 +7005,7 @@ fn cmdFetch(
6996 .actual_hash = undefined,7005 .actual_hash = undefined,
6997 .has_build_zig = false,7006 .has_build_zig = false,
6998 .oom_flag = false,7007 .oom_flag = false,
7008 .latest_commit = undefined,
69997009
7000 .module = null,7010 .module = null,
7001 };7011 };
...@@ -7052,13 +7062,43 @@ fn cmdFetch(...@@ -7052,13 +7062,43 @@ fn cmdFetch(
7052 var fixups: Ast.Fixups = .{};7062 var fixups: Ast.Fixups = .{};
7053 defer fixups.deinit(gpa);7063 defer fixups.deinit(gpa);
70547064
7065 var saved_path_or_url = path_or_url;
7066
7067 if (fetch.latest_commit) |*latest_commit| {
7068 var uri = try std.Uri.parse(path_or_url);
7069 const target_ref = uri.fragment orelse "";
7070 if (!std.mem.eql(u8, target_ref, latest_commit)) {
7071 std.log.info("resolved ref '{s}' to commit {s}", .{
7072 target_ref,
7073 std.fmt.fmtSliceHexLower(latest_commit),
7074 });
7075
7076 if (!preserve_url) {
7077 if (target_ref.len != 0) {
7078 // include the target ref in a query parameter
7079 var query = try std.ArrayList(u8).initCapacity(arena, 4 + target_ref.len);
7080 try std.Uri.writeEscapedQuery(query.writer(), "ref=");
7081 try std.Uri.writeEscapedQuery(query.writer(), target_ref);
7082 uri.query = try query.toOwnedSlice();
7083 }
7084
7085 // replace the refspec with the resolved commit SHA
7086 uri.fragment = try std.fmt.allocPrint(arena, "{}", .{
7087 std.fmt.fmtSliceHexLower(latest_commit),
7088 });
7089
7090 saved_path_or_url = try std.fmt.allocPrint(arena, "{}", .{uri});
7091 }
7092 }
7093 }
7094
7055 const new_node_init = try std.fmt.allocPrint(arena,7095 const new_node_init = try std.fmt.allocPrint(arena,
7056 \\.{{7096 \\.{{
7057 \\ .url = "{}",7097 \\ .url = "{}",
7058 \\ .hash = "{}",7098 \\ .hash = "{}",
7059 \\ }}7099 \\ }}
7060 , .{7100 , .{
7061 std.zig.fmtEscapes(path_or_url),7101 std.zig.fmtEscapes(saved_path_or_url),
7062 std.zig.fmtEscapes(&hex_digest),7102 std.zig.fmtEscapes(&hex_digest),
7063 });7103 });
70647104
...@@ -7078,7 +7118,7 @@ fn cmdFetch(...@@ -7078,7 +7118,7 @@ fn cmdFetch(
7078 if (dep.hash) |h| {7118 if (dep.hash) |h| {
7079 switch (dep.location) {7119 switch (dep.location) {
7080 .url => |u| {7120 .url => |u| {
7081 if (mem.eql(u8, h, &hex_digest) and mem.eql(u8, u, path_or_url)) {7121 if (mem.eql(u8, h, &hex_digest) and mem.eql(u8, u, saved_path_or_url)) {
7082 std.log.info("existing dependency named '{s}' is up-to-date", .{name});7122 std.log.info("existing dependency named '{s}' is up-to-date", .{name});
7083 process.exit(0);7123 process.exit(0);
7084 }7124 }