a73x

cfa8e4ff

refactor: MUX_KEY_FILE is spelled once, in xdg

a73x   2026-08-27 08:05

Commit message
refactor: MUX_KEY_FILE is spelled once, in xdg

Four binaries each spelled the variable name themselves, two of them
under comments explaining why the copy was tolerable. xdg.pickKey
already owns which of --key and the environment wins; the name of the
environment now sits beside it.

src/cli/main.zig
Old New
@@ -43,7 +43,7 @@ fn pickKey(flag: ?[]const u8, env: ?[]const u8, default_if_present: ?[]const u8)
43 /// MUX_KEY_FILE, with "set but empty" read as unset — an empty path 43 /// MUX_KEY_FILE, with "set but empty" read as unset — an empty path
44 /// could only be a mistake, and Key.load would blame "". 44 /// could only be a mistake, and Key.load would blame "".
45 fn envKey() ?[]const u8 { 45 fn envKey() ?[]const u8 {
46 const v = std.posix.getenv("MUX_KEY_FILE") orelse return null; 46 const v = std.posix.getenv(xdg.key_env) orelse return null;
47 return if (v.len == 0) null else v; 47 return if (v.len == 0) null else v;
48 } 48 }
49 49
src/cli/mux_main.zig
Old New
@@ -140,11 +140,6 @@ fn agentReachable(path: []const u8) bool {
140 return n != 0; 140 return n != 0;
141 } 141 }
142 142
143 /// The environment variable consulted when `--key` is absent. Named rather
144 /// than inlined because the parse cannot read it — the parse stays pure so
145 /// it stays testable — and `main` has to use exactly the same name.
146 pub const key_env = "MUX_KEY_FILE";
147
148 /// Built from `proto.session_env` so the message and the planter cannot 143 /// Built from `proto.session_env` so the message and the planter cannot
149 /// disagree about the spelling. 144 /// disagree about the spelling.
150 const self_attach_refusal = 145 const self_attach_refusal =
@@ -277,7 +272,7 @@ pub fn main() !u8 {
277 if (args.len > 1 and std.mem.eql(u8, args[1], "wall")) 272 if (args.len > 1 and std.mem.eql(u8, args[1], "wall"))
278 return wallMain(alloc, args[2..]); 273 return wallMain(alloc, args[2..]);
279 274
280 const parsed = parseArgs(args, std.posix.getenv(key_env)); 275 const parsed = parseArgs(args, std.posix.getenv(xdg.key_env));
281 276
282 // `-A` is a promise, and a client with no agent behind it cannot keep 277 // `-A` is a promise, and a client with no agent behind it cannot keep
283 // one. Left to attach, it offers anyway — the offer is a declaration, 278 // one. Left to attach, it offers anyway — the offer is a declaration,
@@ -534,7 +529,7 @@ fn wallMain(alloc: std.mem.Allocator, args: []const [:0]const u8) !u8 {
534 const env_sock = std.posix.getenv(proto.sock_env); 529 const env_sock = std.posix.getenv(proto.sock_env);
535 const env_session = std.posix.getenv(proto.session_env); 530 const env_session = std.posix.getenv(proto.session_env);
536 for (resolved, spellings.items) |*r, s| { 531 for (resolved, spellings.items) |*r, s| {
537 r.* = wallview.resolveSpelling(arena, s, xdg.pickKey(key, std.posix.getenv(key_env)), idle_ms) catch |err| { 532 r.* = wallview.resolveSpelling(arena, s, xdg.pickKey(key, std.posix.getenv(xdg.key_env)), idle_ms) catch |err| {
538 std.debug.print("mux: bad wall target '{s}': {s}\n", .{ s, @errorName(err) }); 533 std.debug.print("mux: bad wall target '{s}': {s}\n", .{ s, @errorName(err) });
539 return 2; 534 return 2;
540 }; 535 };
src/cli/muxa.zig
Old New
@@ -1304,7 +1304,7 @@ fn openQuicConn(
1304 // same two functions, and a copy that drifted is how two binaries end 1304 // same two functions, and a copy that drifted is how two binaries end
1305 // up authenticating with different keys. (muxd's pickKey stands apart 1305 // up authenticating with different keys. (muxd's pickKey stands apart
1306 // deliberately: it takes the default only when the file exists.) 1306 // deliberately: it takes the default only when the file exists.)
1307 const res = xdg.resolveKeyPath(alloc, xdg.pickKey(o.key, std.posix.getenv("MUX_KEY_FILE"))) catch |e| 1307 const res = xdg.resolveKeyPath(alloc, xdg.pickKey(o.key, std.posix.getenv(xdg.key_env))) catch |e|
1308 return .{ .exit = fail("quic: cannot resolve a key path", @errorName(e)) }; 1308 return .{ .exit = fail("quic: cannot resolve a key path", @errorName(e)) };
1309 const key_path = switch (res) { 1309 const key_path = switch (res) {
1310 .given, .default => |p| p, 1310 .given, .default => |p| p,
src/cli/webhub_main.zig
Old New
@@ -132,7 +132,7 @@ pub fn main() !u8 {
132 const args = try std.process.argsAlloc(alloc); 132 const args = try std.process.argsAlloc(alloc);
133 defer std.process.argsFree(alloc, args); 133 defer std.process.argsFree(alloc, args);
134 134
135 const result = parseArgs(alloc, args, std.posix.getenv(client_key_env)) catch |err| switch (err) { 135 const result = parseArgs(alloc, args, std.posix.getenv(xdg.key_env)) catch |err| switch (err) {
136 error.Usage => { 136 error.Usage => {
137 std.debug.print("{s}", .{usage}); 137 std.debug.print("{s}", .{usage});
138 return 2; 138 return 2;
@@ -251,13 +251,6 @@ pub fn main() !u8 {
251 } 251 }
252 } 252 }
253 253
254 /// mux_main.key_env's value, spelled again rather than imported: pulling
255 /// an exe root into the module graph for one string constant is not
256 /// worth the tangle. mux_main.key_env is the origin; a drift between
257 /// the two spellings would make the two binaries read different
258 /// variables, so change both or neither.
259 const client_key_env = "MUX_KEY_FILE";
260
261 test "parse: three spellings become three tiles in argv order, port and key bind" { 254 test "parse: three spellings become three tiles in argv order, port and key bind" {
262 const alloc = std.testing.allocator; 255 const alloc = std.testing.allocator;
263 const args = [_][:0]const u8{ 256 const args = [_][:0]const u8{
src/xdg.zig
Old New
@@ -39,6 +39,11 @@ pub fn resolveKeyPath(alloc: std.mem.Allocator, given: ?[]const u8) !KeyResoluti
39 return .{ .default = p }; 39 return .{ .default = p };
40 } 40 }
41 41
42 /// The environment spelling of `--key`, and the ONE place it is spelled:
43 /// two binaries reading different variable names is a drift only a user
44 /// hitting it would ever notice. The parses stay pure by taking its VALUE.
45 pub const key_env = "MUX_KEY_FILE";
46
42 /// `--key` beats `$MUX_KEY_FILE`: the flag is the more specific intent. 47 /// `--key` beats `$MUX_KEY_FILE`: the flag is the more specific intent.
43 /// An empty spelling of either is unset, not a key at the empty path. 48 /// An empty spelling of either is unset, not a key at the empty path.
44 pub fn pickKey(flag: ?[]const u8, env: ?[]const u8) ?[]const u8 { 49 pub fn pickKey(flag: ?[]const u8, env: ?[]const u8) ?[]const u8 {