2bd71fb27d78

apply/upgrade: thread ctx.passthrough into nixos-rebuild switch argv

time
2026-07-02 00:54 UTC · 3 months ago
machine
koh2
agent
claude-sonnet-5
session
nina passthrough flag audit
parent
d00f8194f384
3 files src/commands.zig+4 −4src/exec.zig+24 −18src/main.zig+34 −0
src/commands.zig+4 −4
@@ -68,7 +68,7 @@6868 pub fn apply(ctx: Ctx) !void {6969     if (ctx.dry) {7070         output.applyDry(ctx.machine.name);71-        const code = try exec.nixosRebuildDryActivate(ctx.io, &ctx.machine, ctx.gpa);71+        const code = try exec.nixosRebuildDryActivate(ctx.io, &ctx.machine, ctx.gpa, ctx.passthrough);7272         if (code != 0) return error.BuildFailed;7373         output.applyDryDone();7474         return;@@ -87,7 +87,7 @@8787     const start = std.Io.Clock.awake.now(ctx.io);8888 8989     var panel = output.BuildPanel{};90-    const code = exec.nixosRebuildSwitchWithPanel(ctx.io, &ctx.machine, ctx.gpa, &panel) catch |e| {90+    const code = exec.nixosRebuildSwitchWithPanel(ctx.io, &ctx.machine, ctx.gpa, &panel, ctx.passthrough) catch |e| {9191         output.buildPanelClear();9292         exec.markApplyFailed(ctx.io, ctx.environ);9393         return e;@@ -117,7 +117,7 @@117117 118118 pub fn check(ctx: Ctx) !void {119119     output.checkStart(ctx.machine.name);120-    const code = try exec.nixosRebuildBuild(ctx.io, &ctx.machine, ctx.gpa);120+    const code = try exec.nixosRebuildBuild(ctx.io, &ctx.machine, ctx.gpa, ctx.passthrough);121121     if (code != 0) return error.BuildFailed;122122     output.checkOk();123123 }@@ -809,7 +809,7 @@809809     output.buildPanelInit();810810     const start = std.Io.Clock.awake.now(ctx.io);811811     var panel = output.BuildPanel{};812-    const code = exec.nixosRebuildSwitchWithPanel(ctx.io, &ctx.machine, ctx.gpa, &panel) catch |e| {812+    const code = exec.nixosRebuildSwitchWithPanel(ctx.io, &ctx.machine, ctx.gpa, &panel, ctx.passthrough) catch |e| {813813         output.buildPanelClear();814814         return e;815815     };

view file

src/exec.zig+24 −18
@@ -351,27 +351,29 @@351351 // output is suppressed; on failure, reportError() translates stderr via352352 // errors.translateError(). The substep line above the call tells the user what353353 // is running; silence during the build is intentional per the error-wrapping brief.354-fn nixosRebuildRun(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator, verb: []const u8, flake: bool) !u8 {355-    const argv: []const []const u8 = if (flake)356-        &.{ "sudo", "nixos-rebuild", verb, "--flake", machine.config_path }357-    else358-        &.{ "sudo", "nixos-rebuild", verb };354+fn nixosRebuildRun(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator, verb: []const u8, flake: bool, extra_flags: []const []const u8) !u8 {355+    var argv: std.ArrayList([]const u8) = .empty;356+    defer argv.deinit(gpa);357+    try argv.appendSlice(gpa, &.{ "sudo", "nixos-rebuild", verb });358+    if (flake) try argv.appendSlice(gpa, &.{ "--flake", machine.config_path });359+    try argv.appendSlice(gpa, extra_flags);360+359361     output.flush();360-    const r = try capture(gpa, io, machine, argv);362+    const r = try capture(gpa, io, machine, argv.items);361363     defer gpa.free(r.stdout);362364     defer gpa.free(r.stderr);363365     errors.setBuildStderr(r.stderr);364366     return r.exit_code;365367 }366368 367-pub fn nixosRebuildSwitch(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator) !u8 {369+pub fn nixosRebuildSwitch(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator, extra_flags: []const []const u8) !u8 {368370     const flake = useFlakeFlag(gpa, io, machine);369371     if (flake) {370372         output.printSubstep("nixos-rebuild switch --flake {s}", .{machine.config_path});371373     } else {372374         output.printSubstep("nixos-rebuild switch", .{});373375     }374-    return nixosRebuildRun(io, machine, gpa, "switch", flake);376+    return nixosRebuildRun(io, machine, gpa, "switch", flake, extra_flags);375377 }376378 377379 // Live-streaming variant used by `apply` when stdout is a TTY. Each stderr line@@ -383,6 +385,7 @@383385     machine: *const types.Machine,384386     gpa: std.mem.Allocator,385387     panel: *output.BuildPanel,388+    extra_flags: []const []const u8,386389 ) !u8 {387390     const flake = useFlakeFlag(gpa, io, machine);388391     if (flake) {@@ -390,8 +393,8 @@390393     } else {391394         output.printSubstep("nixos-rebuild switch", .{});392395     }393-    if (!output.colorEnabled()) return nixosRebuildRun(io, machine, gpa, "switch", flake);394-    return nixosRebuildRunStreamed(io, machine, gpa, "switch", flake, panel);396+    if (!output.colorEnabled()) return nixosRebuildRun(io, machine, gpa, "switch", flake, extra_flags);397+    return nixosRebuildRunStreamed(io, machine, gpa, "switch", flake, panel, extra_flags);395398 }396399 397400 fn nixosRebuildRunStreamed(@@ -401,11 +404,14 @@401404     verb: []const u8,402405     flake: bool,403406     panel: *output.BuildPanel,407+    extra_flags: []const []const u8,404408 ) !u8 {405-    const argv: []const []const u8 = if (flake)406-        &.{ "sudo", "nixos-rebuild", verb, "--flake", machine.config_path }407-    else408-        &.{ "sudo", "nixos-rebuild", verb };409+    var argv_list: std.ArrayList([]const u8) = .empty;410+    defer argv_list.deinit(gpa);411+    try argv_list.appendSlice(gpa, &.{ "sudo", "nixos-rebuild", verb });412+    if (flake) try argv_list.appendSlice(gpa, &.{ "--flake", machine.config_path });413+    try argv_list.appendSlice(gpa, extra_flags);414+    const argv: []const []const u8 = argv_list.items;409415 410416     output.flush();411417     const built_argv = try buildArgv(gpa, machine, argv);@@ -449,12 +455,12 @@449455     };450456 }451457 452-pub fn nixosRebuildDryActivate(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator) !u8 {453-    return nixosRebuildRun(io, machine, gpa, "dry-activate", useFlakeFlag(gpa, io, machine));458+pub fn nixosRebuildDryActivate(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator, extra_flags: []const []const u8) !u8 {459+    return nixosRebuildRun(io, machine, gpa, "dry-activate", useFlakeFlag(gpa, io, machine), extra_flags);454460 }455461 456-pub fn nixosRebuildBuild(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator) !u8 {457-    return nixosRebuildRun(io, machine, gpa, "build", useFlakeFlag(gpa, io, machine));462+pub fn nixosRebuildBuild(io: std.Io, machine: *const types.Machine, gpa: std.mem.Allocator, extra_flags: []const []const u8) !u8 {463+    return nixosRebuildRun(io, machine, gpa, "build", useFlakeFlag(gpa, io, machine), extra_flags);458464 }459465 460466 // --- Generations ---

view file

src/main.zig+34 −0
@@ -361,6 +361,40 @@361361     try std.testing.expectEqualStrings("--refresh", args.passthrough[0]);362362 }363363 364+test "parse args forwards apply --show-trace" {365+    const gpa = std.testing.allocator;366+    const argv = [_][:0]const u8{ "nina", "apply", "--show-trace" };367+    const args = try parseArgs(gpa, &argv);368+    defer gpa.free(args.rest);369+    defer gpa.free(args.passthrough);370+    try std.testing.expectEqualStrings("apply", args.command);371+    try std.testing.expectEqual(@as(usize, 1), args.passthrough.len);372+    try std.testing.expectEqualStrings("--show-trace", args.passthrough[0]);373+}374+375+test "parse args forwards check --show-trace" {376+    const gpa = std.testing.allocator;377+    const argv = [_][:0]const u8{ "nina", "check", "--show-trace" };378+    const args = try parseArgs(gpa, &argv);379+    defer gpa.free(args.rest);380+    defer gpa.free(args.passthrough);381+    try std.testing.expectEqualStrings("check", args.command);382+    try std.testing.expectEqual(@as(usize, 1), args.passthrough.len);383+    try std.testing.expectEqualStrings("--show-trace", args.passthrough[0]);384+}385+386+test "parse args forwards flake check --all-systems" {387+    const gpa = std.testing.allocator;388+    const argv = [_][:0]const u8{ "nina", "flake", "check", "--all-systems" };389+    const args = try parseArgs(gpa, &argv);390+    defer gpa.free(args.rest);391+    defer gpa.free(args.passthrough);392+    try std.testing.expectEqualStrings("flake", args.command);393+    try std.testing.expectEqualStrings("check", args.sub);394+    try std.testing.expectEqual(@as(usize, 1), args.passthrough.len);395+    try std.testing.expectEqualStrings("--all-systems", args.passthrough[0]);396+}397+364398 test "parse subcommand" {365399     const gpa = std.testing.allocator;366400     const argv = [_][:0]const u8{ "nina", "service", "list" };

view file