From 5b5c421f525b8c54b67357cfcbd5d3bbd3b4ca92 Mon Sep 17 00:00:00 2001 From: Philip Taron Date: Wed, 10 Jun 2026 23:57:18 -0700 Subject: [PATCH] nix-prefetch-git: also disable legacy auto-gc Commit 88cfc54552d5 ("nix-prefetch-git: disable maintenance mode via environment variables") disabled maintenance.auto (git's new auto-maintenance) via GIT_CONFIG_*, which propagates to submodules. But the legacy auto-gc path (gc.auto plus detached gc.autoDetach) is still enabled, and it keeps repacking .git/modules//objects after a nested submodule reports "checked out", racing the later `rm -rf .git`: - rm empties objects/pack, the detached gc drops a fresh pack in, and rmdir fails with "Directory not empty" (exit 123); or - removal partially completes, leaving varying .git remnants, yielding a non-deterministic NAR hash. Disable gc.auto/gc.autoDetach alongside maintenance.auto, using the same GIT_CONFIG_* mechanism so the settings reach every git invocation and its children (including nested submodule fetches). Fold the repeated boilerplate into a small git_config_env helper. The successful output is unchanged (.git is removed either way), so pinned fetchgit hashes stay valid; this only makes removal deterministic. Fixes #524215. Assisted-by: Claude Code (claude-opus-4-8) --- pkgs/build-support/fetchgit/nix-prefetch-git | 24 +++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/pkgs/build-support/fetchgit/nix-prefetch-git b/pkgs/build-support/fetchgit/nix-prefetch-git index 5e78dcc72b84..112593d9d377 100755 --- a/pkgs/build-support/fetchgit/nix-prefetch-git +++ b/pkgs/build-support/fetchgit/nix-prefetch-git @@ -515,13 +515,25 @@ unset XDG_CONFIG_HOME export GIT_CONFIG_NOSYSTEM=1 -# Disable maintenance: it's not useful for a short-lived clone, and -# background maintenance causes non-deterministic builds. +# Append a config entry via the GIT_CONFIG_* environment variables. Unlike +# `git config` (writes a single repo) or `git -c` (one invocation), these +# propagate to every git invocation *and* its children, including (nested) +# submodule fetches. Done additively so it composes with any GIT_CONFIG_* the +# caller passes via `impureEnvVars`. +git_config_env(){ + export GIT_CONFIG_COUNT=$(( ${GIT_CONFIG_COUNT:-0} + 1 )) + export "GIT_CONFIG_KEY_$(( GIT_CONFIG_COUNT - 1 ))=$1" + export "GIT_CONFIG_VALUE_$(( GIT_CONFIG_COUNT - 1 ))=$2" +} + +# Disable maintenance and auto-gc: they're not useful for a short-lived clone, +# and their background/detached processes race the later `.git` removal, +# producing non-deterministic output (and outright failures with nested +# submodules, where the legacy gc.auto path still fires). # https://github.com/NixOS/nixpkgs/issues/524215 -export GIT_CONFIG_COUNT=$(( ${GIT_CONFIG_COUNT:-0} + 1 )) -# Not the best but generic enough that it will work with `impureEnvVars` -export "GIT_CONFIG_KEY_$(( GIT_CONFIG_COUNT - 1 ))=maintenance.auto" -export "GIT_CONFIG_VALUE_$(( GIT_CONFIG_COUNT - 1 ))=false" +git_config_env maintenance.auto false +git_config_env gc.auto 0 +git_config_env gc.autoDetach false if test -n "$builder"; then test -n "$out" -a -n "$url" -a -n "$rev" || usage