From 69d53c99f42e506178d31cabb5e5a951fffc4b33 Mon Sep 17 00:00:00 2001 From: Christofer Nolander Date: Sat, 11 May 2024 12:37:40 +0200 Subject: [PATCH 1/3] Revert "Revert "Merge pull request #19349 from nolanderc/save-commit"" This reverts commit 6ca4ed5948d8eaab28fc5e3706aeb1b113a210af. --- src/Package/Fetch.zig | 10 +++++++++- src/main.zig | 44 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 5a3fd4298d44..f2da66af5702 100644 --- a/src/Package/Fetch.zig +++ b/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. @@ -699,6 +703,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, @@ -707,6 +712,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { .actual_hash = undefined, .has_build_zig = false, .oom_flag = false, + .latest_commit = undefined, .module = null, }; @@ -994,7 +1000,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"), diff --git a/src/main.zig b/src/main.zig index 3ec27ceb4e7a..156334be562d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5097,6 +5097,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, @@ -5105,6 +5106,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, }; @@ -6894,6 +6896,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 + \\ --preserve-url Store a verbatim copy of the URL in build.zig.zon \\ ; @@ -6909,6 +6912,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 preserve_url: bool = false; { var i: usize = 0; @@ -6929,6 +6933,8 @@ fn cmdFetch( save = .yes; } else if (mem.startsWith(u8, arg, "--save=")) { save = .{ .name = arg["--save=".len..] }; + } else if (mem.startsWith(u8, arg, "--preserve-url")) { + preserve_url = true; } else { fatal("unrecognized parameter: '{s}'", .{arg}); } @@ -6940,6 +6946,8 @@ fn cmdFetch( } } + if (preserve_url and save == .no) fatal("use of '--preserve-url' requires '--save'", .{}); + const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{}); var thread_pool: ThreadPool = undefined; @@ -6988,6 +6996,7 @@ fn cmdFetch( .job_queue = &job_queue, .omit_missing_hash_error = true, .allow_missing_paths_field = false, + .use_latest_commit = true, .package_root = undefined, .error_bundle = undefined, @@ -6996,6 +7005,7 @@ fn cmdFetch( .actual_hash = undefined, .has_build_zig = false, .oom_flag = false, + .latest_commit = undefined, .module = null, }; @@ -7052,13 +7062,43 @@ fn cmdFetch( var fixups: Ast.Fixups = .{}; defer fixups.deinit(gpa); + var saved_path_or_url = path_or_url; + + if (fetch.latest_commit) |*latest_commit| { + var uri = try std.Uri.parse(path_or_url); + const target_ref = uri.fragment orelse ""; + if (!std.mem.eql(u8, target_ref, latest_commit)) { + std.log.info("resolved ref '{s}' to commit {s}", .{ + target_ref, + std.fmt.fmtSliceHexLower(latest_commit), + }); + + if (!preserve_url) { + if (target_ref.len != 0) { + // include the target ref in a query parameter + var query = try std.ArrayList(u8).initCapacity(arena, 4 + target_ref.len); + try std.Uri.writeEscapedQuery(query.writer(), "ref="); + try std.Uri.writeEscapedQuery(query.writer(), target_ref); + uri.query = try query.toOwnedSlice(); + } + + // replace the refspec with the resolved commit SHA + uri.fragment = try std.fmt.allocPrint(arena, "{}", .{ + std.fmt.fmtSliceHexLower(latest_commit), + }); + + saved_path_or_url = try std.fmt.allocPrint(arena, "{}", .{uri}); + } + } + } + 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), }); @@ -7078,7 +7118,7 @@ fn cmdFetch( if (dep.hash) |h| { switch (dep.location) { .url => |u| { - if (mem.eql(u8, h, &hex_digest) and mem.eql(u8, u, path_or_url)) { + if (mem.eql(u8, h, &hex_digest) and mem.eql(u8, u, saved_path_or_url)) { std.log.info("existing dependency named '{s}' is up-to-date", .{name}); process.exit(0); } From d1f0a3424ef6f69fa29adb9bf03d07950fab750f Mon Sep 17 00:00:00 2001 From: Christofer Nolander Date: Sat, 11 May 2024 12:32:02 +0200 Subject: [PATCH 2/3] update to new URI changes, rework `--save` type --- src/main.zig | 70 +++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/main.zig b/src/main.zig index 156334be562d..45f24bda5d41 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6896,7 +6896,8 @@ 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 - \\ --preserve-url Store a verbatim copy of the URL in build.zig.zon + \\ --save-exact Add the fetched package to build.zig.zon, storing the URL verbatim + \\ --save-exact=[name] Add the fetched package to build.zig.zon as name, storing the URL verbatim \\ ; @@ -6911,8 +6912,11 @@ fn cmdFetch( var opt_path_or_url: ?[]const u8 = null; 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 preserve_url: bool = false; + var save: union(enum) { + no, + yes: ?[]const u8, + exact: ?[]const u8, + } = .no; { var i: usize = 0; @@ -6930,11 +6934,13 @@ fn cmdFetch( } else if (mem.eql(u8, arg, "--debug-hash")) { debug_hash = true; } else if (mem.eql(u8, arg, "--save")) { - save = .yes; + save = .{ .yes = null }; } else if (mem.startsWith(u8, arg, "--save=")) { - save = .{ .name = arg["--save=".len..] }; - } else if (mem.startsWith(u8, arg, "--preserve-url")) { - preserve_url = true; + save = .{ .yes = arg["--save=".len..] }; + } else if (mem.eql(u8, arg, "--save-exact")) { + save = .{ .exact = null }; + } else if (mem.startsWith(u8, arg, "--save-exact=")) { + save = .{ .exact = arg["--save=".len..] }; } else { fatal("unrecognized parameter: '{s}'", .{arg}); } @@ -6946,8 +6952,6 @@ fn cmdFetch( } } - if (preserve_url and save == .no) fatal("use of '--preserve-url' requires '--save'", .{}); - const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{}); var thread_pool: ThreadPool = undefined; @@ -7032,12 +7036,12 @@ fn cmdFetch( try io.getStdOut().writeAll(hex_digest ++ "\n"); return cleanExit(); }, - .yes => n: { + .yes, .exact => |name| name: { + if (name) |n| break :name n; const fetched_manifest = fetch.manifest orelse fatal("unable to determine name; fetched package has no build.zig.zon file", .{}); - break :n fetched_manifest.name; + break :name fetched_manifest.name; }, - .name => |n| n, }; const cwd_path = try process.getCwdAlloc(arena); @@ -7064,31 +7068,31 @@ fn cmdFetch( var saved_path_or_url = path_or_url; - if (fetch.latest_commit) |*latest_commit| { + if (fetch.latest_commit) |*latest_commit| resolved: { + const latest_commit_hex = try std.fmt.allocPrint(arena, "{}", .{std.fmt.fmtSliceHexLower(latest_commit)}); + var uri = try std.Uri.parse(path_or_url); - const target_ref = uri.fragment orelse ""; - if (!std.mem.eql(u8, target_ref, latest_commit)) { - std.log.info("resolved ref '{s}' to commit {s}", .{ - target_ref, - std.fmt.fmtSliceHexLower(latest_commit), - }); - if (!preserve_url) { - if (target_ref.len != 0) { - // include the target ref in a query parameter - var query = try std.ArrayList(u8).initCapacity(arena, 4 + target_ref.len); - try std.Uri.writeEscapedQuery(query.writer(), "ref="); - try std.Uri.writeEscapedQuery(query.writer(), target_ref); - uri.query = try query.toOwnedSlice(); - } + if (uri.fragment) |fragment| { + const target_ref = try fragment.toRawMaybeAlloc(arena); - // replace the refspec with the resolved commit SHA - uri.fragment = try std.fmt.allocPrint(arena, "{}", .{ - std.fmt.fmtSliceHexLower(latest_commit), - }); + // the refspec may already be fully resolved + if (std.mem.eql(u8, target_ref, latest_commit_hex)) break :resolved; - saved_path_or_url = try std.fmt.allocPrint(arena, "{}", .{uri}); - } + std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex }); + + // include the original refspec in a query parameter, could be used to check for updates + uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={%}", .{fragment}) }; + } else { + std.log.info("resolved to commit {s}", .{latest_commit_hex}); + } + + // replace the refspec with the resolved commit SHA + uri.fragment = .{ .raw = latest_commit_hex }; + + switch (save) { + .yes => saved_path_or_url = try std.fmt.allocPrint(arena, "{}", .{uri}), + .no, .exact => {}, // keep the original URL } } From 19dfc5ccf986bf729eeb38a3b9ca38b0427025e6 Mon Sep 17 00:00:00 2001 From: Christofer Nolander Date: Sat, 11 May 2024 16:09:25 +0200 Subject: [PATCH 3/3] initialize `latest_commit` to null everywhere --- src/Package/Fetch.zig | 6 ++++-- src/main.zig | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index f2da66af5702..97cbd36bd0b5 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -61,7 +61,9 @@ 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. +/// If `use_latest_commit` was true, this will be set to the commit that was used. +/// If the resource pointed to by the location is not a Git-repository, this +/// will be left unchanged. latest_commit: ?git.Oid, // This field is used by the CLI only, untouched by this file. @@ -712,7 +714,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { .actual_hash = undefined, .has_build_zig = false, .oom_flag = false, - .latest_commit = undefined, + .latest_commit = null, .module = null, }; diff --git a/src/main.zig b/src/main.zig index 45f24bda5d41..61a97de3f54d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5106,7 +5106,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, + .latest_commit = null, .module = build_mod, }; @@ -7009,7 +7009,7 @@ fn cmdFetch( .actual_hash = undefined, .has_build_zig = false, .oom_flag = false, - .latest_commit = undefined, + .latest_commit = null, .module = null, };