authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-06-30 21:30:30-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-06-30 21:41:44-04:00
log580135241b9618fdce6f4acca390e41d14e4b937
treecb31abf732ab691af9c4ed80bae44fccc5dc46f7
parentc737c2efe350db5c9b30a2553d294b6642860378

build: update how changing the currently checked out commit is detected

Add support for building from a git worktree. Previously, the compiler configure script was only rerun on changing which branch is currently checked out. Now, any changes to the `HEAD` reflog will be detected, which, happens to contain the commit hash of the currently checked out commit on the last line, so will necessarily have unique contents for any given commit. While there could be false negatives due to the reflog being cleaned after a couple months, this is not only unlikely to actually occur, involving a specific series of steps over the course of a third of a year, the end result is that the compiled compiler reports the wrong version, and can easily be fixed by simply e.g. changing to another commit and back, something which developers already frequently do. Additionally, the alternative of having to hash longer and longer reflogs to detect a change on the last line would hardly be preferable.

1 files changed, 23 insertions(+), 1 deletions(-)

build.zig+23-1
...@@ -268,7 +268,29 @@ pub fn build(b: *std.Build) !void {...@@ -268,7 +268,29 @@ pub fn build(b: *std.Build) !void {
268 }268 }
269269
270 // Ensure git version changes get picked up.270 // Ensure git version changes get picked up.
271 b.dependOnFileContents(b.path(".git/HEAD"));271 git: {
272 const io = b.graph.io;
273 const git_file = b.root.openFile(io, ".git", .{ .allow_directory = false }) catch |err| switch (err) {
274 error.IsDir => {
275 b.dependOnFileContents(b.path(".git/logs/HEAD"));
276 break :git;
277 },
278 else => |e| return e,
279 };
280 defer git_file.close(io);
281 var line_buffer: ["gitdir: ".len + std.Io.Dir.max_path_bytes + 1]u8 = undefined;
282 var git_file_reader = git_file.reader(io, &line_buffer);
283 if (std.mem.cutPrefix(u8, std.mem.trimEnd(u8, try git_file_reader.interface.allocRemaining(
284 arena,
285 .limited("gitdir: ".len + std.Io.Dir.max_path_bytes + "\r\n".len),
286 ), "\r\n"), "gitdir: ")) |git_dir| {
287 const head_file = b.pathJoin(&.{ git_dir, "logs", "HEAD" });
288 b.dependOnFileContents(if (std.Io.Dir.path.isAbsolute(head_file))
289 b.graph.cwdRelativePath(head_file)
290 else
291 b.path(head_file));
292 }
293 }
272294
273 const version_string = b.fmt("{d}.{d}.{d}", .{ zig_version.major, zig_version.minor, zig_version.patch });295 const version_string = b.fmt("{d}.{d}.{d}", .{ zig_version.major, zig_version.minor, zig_version.patch });
274296