ReviewOS

also looking at this

pantry-pm/pantry

fix(install): a lock pin decides what installs while it satisfies its spec

#263
Merged glennmichael123 wants to merge fix/260-honor-lock-pins into main
3 files +118 -1
packages/zig/src/cli/commands/install/core.zigmodified+25-1
Changes to packages/zig/src/cli/commands/install/core.zig
@@ -972,6 +972,30 @@ pub fn installCommandWithOptions(allocator: std.mem.Allocator, args: []const []c
972972 // ── Parallel pipeline: resolve tree → download → extract ──
973973 const pipeline = ;
974974
975 // A committed lock decides what gets installed. Every declared range
976 // used to be resolved against the registry, so the newest match won
977 // and the pin was rewritten; `--frozen-lockfile` installed that newer
978 // release and only then failed (#260). A spec the pin no longer
979 // satisfies still resolves afresh, so editing a dependency works.
980 //
981 // Checked before anything is installed, which is the other half of
982 // the report: a frozen run must fail without having written to
983 // `pantry/` first.
984 if (options.frozen_lockfile) {
985 for (deps_to_install) |dep| {
986 if (env_only_domains.contains(helpers.resolvePackageAlias(helpers.normalizePackageName(dep.name)))) continue;
987 if (helpers.lockedVersionSatisfying(&lock_file, dep.name, dep.version) != null) continue;
988 // `latest`-style specs are covered by any pin, so reaching
989 // here means the lock does not cover this dependency at all,
990 // or its pin falls outside the declared spec.
991 style.printWarn("Lockfile does not satisfy {s}@{s} but --frozen-lockfile is set\n", .{ dep.name, dep.version });
992 return .{
993 .exit_code = 1,
994 .message = try allocator.dupe(u8, "Error: lockfile is out of date (--frozen-lockfile)"),
995 };
996 }
997 }
998
975999 // Build pipeline dep list
9761000 var pipeline_deps = try allocator.alloc(pipeline.PipelineDep, deps_to_install.len);
9771001 defer allocator.free(pipeline_deps);
@@ -981,7 +1005,7 @@ pub fn installCommandWithOptions(allocator: std.mem.Allocator, args: []const []c
9811005 const is_domain = std.mem.indexOfScalar(u8, clean_name, '.') != null;
9821006 pipeline_deps[di] = .{
9831007 .name = clean_name,
984 .version = dep.version,
1008 .version = helpers.lockedVersionSatisfying(&lock_file, dep.name, dep.version) orelse dep.version,
9851009 .source = if (is_domain) .pantry else switch (dep.source) {
9861010 .registry => .npm,
9871011 .pantry => .pantry,