41b75b265eb0
implement registry auto-pin: pin nixpkgs once via ~/.nina-registry-pinned flag, announced before search/install/setup
- time
- 2026-06-04 23:00 UTC · 4 months ago
- machine
- koh2
- agent
- claude-opus-4-8
- session
- registry auto-pin
- parent
- 670b260dac73
↓ nina-41b75b26.tar.gzatlas at this save
files changed3 files
src/api.zig+32 −0src/commands.zig+6 −0src/output.zig+7 −0src/api.zig+32 −0
@@ -3,6 +3,38 @@33 const std = @import("std");44 const types = @import("types.zig");55 const errors = @import("errors.zig");6+const output = @import("output.zig");7+8+// Pin the nixpkgs registry once so `nix search nixpkgs` resolves locally instead9+// of refetching github on every query. Gated by a ~/.nina-registry-pinned flag:10+// absent -> pin + announce + create the flag; present -> no-op, silent. Failure11+// to pin is non-fatal — search still runs (just slower), and the flag is left12+// absent so a later run retries.13+pub fn ensureRegistryPinned(gpa: std.mem.Allocator, io: std.Io, environ: *const std.process.Environ.Map) void {14+ const home = environ.get("HOME") orelse return;15+ const flag_path = std.fmt.allocPrint(gpa, "{s}/.nina-registry-pinned", .{home}) catch return;16+ defer gpa.free(flag_path);17+18+ if (std.Io.Dir.openFile(.cwd(), io, flag_path, .{})) |f| {19+ f.close(io);20+ return; // already pinned21+ } else |_| {}22+23+ output.pinningRegistry();24+25+ const r = std.process.run(gpa, io, .{26+ .argv = &.{ "nix", "registry", "pin", "nixpkgs" },27+ }) catch return;28+ defer gpa.free(r.stdout);29+ defer gpa.free(r.stderr);30+ switch (r.term) {31+ .exited => |code| if (code != 0) return,32+ else => return,33+ }34+35+ const file = std.Io.Dir.createFile(.cwd(), io, flag_path, .{}) catch return;36+ file.close(io);37+}638 739 pub fn searchPackages(gpa: std.mem.Allocator, io: std.Io, query: []const u8) ![]types.NixPackage {840 const result = std.process.run(gpa, io, .{src/commands.zig+6 −0
@@ -443,6 +443,7 @@443443 444444 pub fn searchCmd(ctx: Ctx) !void {445445 const query = if (ctx.args.len > 0) ctx.args[0] else "";446+ api.ensureRegistryPinned(ctx.gpa, ctx.io, ctx.environ);446447 const result = try search_tui.run(ctx.gpa, ctx.io, query, .packages);447448 if (result) |r| {448449 installFromResult(ctx, r) catch |e| return e;@@ -451,12 +452,15 @@451452 452453 pub fn optionCmd(ctx: Ctx) !void {453454 const query = if (ctx.args.len > 0) ctx.args[0] else "";455+ api.ensureRegistryPinned(ctx.gpa, ctx.io, ctx.environ);454456 _ = try search_tui.run(ctx.gpa, ctx.io, query, .options);455457 }456458 457459 pub fn install(ctx: Ctx) !void {458460 const pkg_name = if (ctx.args.len > 0) ctx.args[0] else return error.PackageNotFound;459461 462+ api.ensureRegistryPinned(ctx.gpa, ctx.io, ctx.environ);463+460464 // Search for the package to get the attr461465 const pkgs = api.searchPackages(ctx.gpa, ctx.io, pkg_name) catch {462466 errors.error_info.setMessage("'{s}' not found in nixpkgs", .{pkg_name});@@ -848,6 +852,7 @@848852 849853 if (status.allEnabled()) {850854 output.setupAllSet();855+ api.ensureRegistryPinned(gpa, io, environ);851856 return;852857 }853858 @@ -856,6 +861,7 @@856861 defer gpa.free(path);857862 858863 output.setupDone(path, exec.isNixOS(io));864+ api.ensureRegistryPinned(gpa, io, environ);859865 }860866 861867 // --- Log helper ---src/output.zig+7 −0
@@ -737,6 +737,13 @@737737 p("{s}all set\n", .{hdr()});738738 }739739 740+// Printed once, before the first search, when the nixpkgs registry still points741+// at a remote URL. Flush so it lands before `nix registry pin` and any results.742+pub fn pinningRegistry() void {743+ p("{s}pinning nixpkgs for fast local search...\n", .{hdr()});744+ flush();745+}746+740747 pub fn setupEnabling() void {741748 p("{s}enabling experimental features\n", .{hdr()});742749 }