Skip to content

Support Zig 0.16 alongside 0.15.2 via compat layer#5

Open
fielding wants to merge 3 commits into
mainfrom
fable/fresh-eyes
Open

Support Zig 0.16 alongside 0.15.2 via compat layer#5
fielding wants to merge 3 commits into
mainfrom
fable/fresh-eyes

Conversation

@fielding

@fielding fielding commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Why

The repo built on neither toolchain available on a current Mac: zig 0.15.2 fails at link against the macOS 26 SDK (same failure now on GitHub's macos-latest runners, so main is unbuildable in CI macOS too), and zig 0.16 changed the std I/O and process APIs the code relies on. This PR makes nit build and pass its full conformance suite on 0.16.0 while keeping 0.15.2 working where it still can (Linux).

What

  • src/compat.zig — new, ~55 lines: everything version-sensitive lives here. The command modules already target the shared std.Io.Writer interface, which is identical across both versions, so they're untouched.
    • main convention: comptime-select a std.process.Init main (0.16) vs zero-arg main (0.15)
    • stdout: writerStreaming on 0.16 — positional mode (the writer() default) pwrites from offset 0 and silently overwrites earlier output when stdout is redirected to a file
    • getenv / isatty / execvp: go through libc directly; one code path for both versions since nit always links libc
  • src/git.zig — dropped the realpath + dupeZ dance; libgit2 resolves "." and discovers upward itself
  • Version-claim accuracy — README said "zig 0.14+", but the code has required 0.15 APIs since the writer rework. Now says 0.15.2 or 0.16.0 (0.16 required on macOS 26+); build.zig.zon minimum_zig_version bumped to 0.15.2.
  • CI now runs the 143-test conformance suite (previously smoke-test only), on a matrix of ubuntu 0.15.2 / ubuntu 0.16.0 / macos 0.16.0. First-ever Linux run of the suite flushed out two latent portability bugs, fixed here:
    • git init without -b main broke the merge-commit tests on hosts without init.defaultBranch=main
    • the NIT_COLORS TTY tests used BSD script(1) syntax; util-linux needs -c (plus %q quoting, since color values contain semicolons)

Verification

  • CI green on all three matrix jobs (this was red on the first push — the conformance suite caught real portability bugs on Linux)
  • Local (macOS, zig 0.16.0 release binary and 0.16.0-dev.3128): zig build Debug + ReleaseFast, zig build test, conformance 143/143, also 143/143 with GIT_CONFIG_GLOBAL=/dev/null
  • Manual: compact status/log/show/branch, --stat, flag passthrough (diff --name-only), command passthrough (rev-parse), non-repo error path (exit 128)
  • Benchmark claim spot-check: README claims 87% token savings for log -20; measured 90% and 93% on two real repos — the claim is conservative

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xan5eRiAXvcnAVvXHejdTz

fielding and others added 3 commits July 2, 2026 12:01
Zig 0.16-dev reshaped the std I/O and process APIs (std.fs.File ->
std.Io.File behind an Io instance, std.process.Init main convention,
std.posix.getenv/execvpeZ removed). Isolate everything version-sensitive
in src/compat.zig so the command modules stay on the shared std.Io.Writer
interface, which is identical across both versions.

- main: comptime-select a std.process.Init main (0.16) or zero-arg main
  (0.15); cli.run threads compat.ProcessInit through
- stdout: writerStreaming on 0.16 - positional mode pwrites from offset 0
  and overwrites earlier output when stdout is a redirected file
- getenv/isatty/execvp: go through libc directly, one code path for both
- git.zig: drop the realpath dance; libgit2 resolves "." and discovers
  upward itself

Also correct the version claims (README said zig 0.14+, but the code has
required 0.15 APIs since the writer rework; build.zig.zon now says
0.15.2), run the 143-test conformance suite in CI, and add informational
zig-master CI jobs so 0.16 support stays honest.

Verified: zig 0.16.0-dev.3128 build (Debug + ReleaseFast), zig build
test, conformance 143/143, passthrough and non-repo error paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xan5eRiAXvcnAVvXHejdTz
First CI run of the conformance suite exposed that it only passed on
hosts with init.defaultBranch=main: the merge-commit tests checkout main
by name but the repo was created with bare git init. Use git init -b main.
Verified locally with GIT_CONFIG_GLOBAL=/dev/null (143/143).

Zig 0.16.0 is released (master is now 0.17-dev with further Build API
breaks), so pin the matrix to 0.16.0 instead of chasing master, and drop
the macos+0.15.2 job: the current runner images carry the macOS 26 SDK,
which zig 0.15.2 cannot link against - main is equally unbuildable there.
Verified against the real 0.16.0 release binary locally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xan5eRiAXvcnAVvXHejdTz
The NIT_COLORS tests invoked script(1) with BSD/macOS positional-command
syntax; util-linux script wants -c, so the suite died at the first TTY
test on ubuntu runners. Add a run_tty helper that probes for -c support
and %q-quotes args (color values contain semicolons that sh -c would
otherwise interpret).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xan5eRiAXvcnAVvXHejdTz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant