From 6a201170a3c9c1af6723d04056331f7ed865b019 Mon Sep 17 00:00:00 2001 From: Tyce Herrman Date: Tue, 9 Jun 2026 00:40:16 -0400 Subject: [PATCH] Fix cask tap materialization --- ci/flake.lock | 32 ++++++++--------- ci/flake.nix | 10 +++--- ci/tests.nix | 83 +++++++++++++++++++++++++++++++++++++++++++-- modules/default.nix | 15 +++++--- 4 files changed, 113 insertions(+), 27 deletions(-) diff --git a/ci/flake.lock b/ci/flake.lock index 80418f3..cbb001f 100644 --- a/ci/flake.lock +++ b/ci/flake.lock @@ -16,21 +16,21 @@ "type": "github" } }, - "nix-darwin_25_11": { + "nix-darwin_26_05": { "inputs": { "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1772129556, - "narHash": "sha256-Utk0zd8STPsUJPyjabhzPc5BpPodLTXrwkpXBHYnpeg=", + "lastModified": 1780789116, + "narHash": "sha256-+/LcDMJGYQVLp3ECZ1jBhj3GcQU+Yt+OTsDsQFz8cMs=", "owner": "nix-darwin", "repo": "nix-darwin", - "rev": "ebec37af18215214173c98cf6356d0aca24a2585", + "rev": "731951a251ca96cbd12a8e1bde63737e21947644", "type": "github" }, "original": { "owner": "nix-darwin", - "ref": "nix-darwin-25.11", + "ref": "nix-darwin-26.05", "repo": "nix-darwin", "type": "github" } @@ -75,16 +75,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1764491476, - "narHash": "sha256-E4rtgPS7fntINb6fVJ5qQdkhfbZn8pzMYNdmiXqZmCo=", + "lastModified": 1779622335, + "narHash": "sha256-ViA62qtL5za7V3d5I8OA9q9JcFhsVAiL5jVHwEclWqk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "54f09efd2ca0dd5bb9c5fafc89573ab3ac44701d", + "rev": "705e9929918b43bd7b715dc0a878ac870449bb03", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-25.11-darwin", + "ref": "nixpkgs-26.05-darwin", "repo": "nixpkgs", "type": "github" } @@ -105,18 +105,18 @@ "type": "github" } }, - "nixpkgs_25_11": { + "nixpkgs_26_05": { "locked": { - "lastModified": 1774388614, - "narHash": "sha256-tFwzTI0DdDzovdE9+Ras6CUss0yn8P9XV4Ja6RjA+nU=", + "lastModified": 1780902259, + "narHash": "sha256-q8yYEC5f1mFlQO9RGna4LTc9QrcvWunX6FYp83munkQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1073dad219cb244572b74da2b20c7fe39cb3fa9e", + "rev": "bd0ff2d3eac24699c3664d5966b9ef36f388e2ca", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-25.11", + "ref": "nixos-26.05", "repo": "nixpkgs", "type": "github" } @@ -140,10 +140,10 @@ "root": { "inputs": { "flake-compat": "flake-compat", - "nix-darwin_25_11": "nix-darwin_25_11", + "nix-darwin_26_05": "nix-darwin_26_05", "nix-darwin_unstable": "nix-darwin_unstable", "nix-github-actions": "nix-github-actions", - "nixpkgs_25_11": "nixpkgs_25_11", + "nixpkgs_26_05": "nixpkgs_26_05", "nixpkgs_unstable": "nixpkgs_unstable" } } diff --git a/ci/flake.nix b/ci/flake.nix index 373e18d..872fb6e 100644 --- a/ci/flake.nix +++ b/ci/flake.nix @@ -2,10 +2,10 @@ { inputs = { nixpkgs_unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; - nixpkgs_25_11.url = "github:NixOS/nixpkgs/nixos-25.11"; + nixpkgs_26_05.url = "github:NixOS/nixpkgs/nixos-26.05"; nix-darwin_unstable.url = "github:nix-darwin/nix-darwin"; - nix-darwin_25_11.url = "github:nix-darwin/nix-darwin/nix-darwin-25.11"; + nix-darwin_26_05.url = "github:nix-darwin/nix-darwin/nix-darwin-26.05"; nix-github-actions = { url = "github:nix-community/nix-github-actions"; @@ -31,9 +31,9 @@ nixpkgs = inputs.nixpkgs_unstable; nix-darwin = inputs.nix-darwin_unstable; }; - "25.11" = { - nixpkgs = inputs.nixpkgs_25_11; - nix-darwin = inputs.nix-darwin_25_11; + "26.05" = { + nixpkgs = inputs.nixpkgs_26_05; + nix-darwin = inputs.nix-darwin_26_05; }; }; diff --git a/ci/tests.nix b/ci/tests.nix index 63a6d68..55a5ad5 100644 --- a/ci/tests.nix +++ b/ci/tests.nix @@ -67,6 +67,67 @@ let ) ]; }; + + makeTapValidationTest = + module: + makeTest ( + { pkgs, config, ... }: + let + prefixName = + if pkgs.stdenv.hostPlatform.isAarch64 then + config.nix-homebrew.defaultArm64Prefix + else + config.nix-homebrew.defaultIntelPrefix; + library = config.nix-homebrew.prefixes.${prefixName}.library; + fakeCaskTap = pkgs.runCommandLocal "homebrew-cask-test-tap" { } '' + mkdir -p "$out/Casks/u" + touch "$out/Casks/u/ungoogled-chromium.rb" + ''; + in + { + imports = [ + module + ]; + + _module.args.library = library; + + nix-homebrew = { + enable = true; + autoMigrate = true; + taps = { + "homebrew/homebrew-cask" = fakeCaskTap; + }; + }; + + ci.preScript = '' + >&2 echo "Removing runner Homebrew taps before declarative tap validation" + if [[ -e "${library}/Taps" || -L "${library}/Taps" ]]; then + sudo rm -rf "${library}/Taps" + fi + ''; + + ci.postScript = '' + >&2 echo "Checking declarative cask tap realpaths" + tap_root="${library}/Taps" + cask_path="$tap_root/homebrew/homebrew-cask/Casks/u/ungoogled-chromium.rb" + + test -f "$cask_path" + + tap_root_real="$(${pkgs.coreutils}/bin/realpath "$tap_root")" + cask_real="$(${pkgs.coreutils}/bin/realpath "$cask_path")" + + case "$cask_real" in + "$tap_root_real"/*) ;; + *) + >&2 echo "Expected cask realpath to stay under managed Taps root" + >&2 echo "Taps realpath: $tap_root_real" + >&2 echo "Cask realpath: $cask_real" + exit 1 + ;; + esac + ''; + } + ); in { migrate = makeTest ( @@ -89,13 +150,15 @@ in ci.postScript = '' >&2 echo "Checking brew" which brew - '' + lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 '' + '' + + lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 '' >&2 echo "Checking that we can still use the unbound package" $(brew --prefix)/sbin/unbound -V >&2 echo "Checking that we can still use the tap we added imperatively" brew install koekeishiya/formulae/yabai - '' + lib.optionalString config.nix-homebrew.enableRosetta '' + '' + + lib.optionalString config.nix-homebrew.enableRosetta '' >&2 echo "Checking we can execute the Intel brew with arch -x86_64" arch -x86_64 /usr/local/bin/brew config | grep "HOMEBREW_PREFIX: /usr/local" @@ -106,6 +169,22 @@ in } ); + tap-validation-mutable = makeTapValidationTest { }; + + tap-validation-declarative = makeTapValidationTest ( + { library, ... }: + { + nix-homebrew.mutableTaps = false; + + ci.preScript = '' + >&2 echo "Removing runner Homebrew taps before declarative tap validation" + if [[ -e "${library}/Taps" || -L "${library}/Taps" ]]; then + sudo rm -rf "${library}/Taps" + fi + ''; + } + ); + nuke-homebrew-repository = makeTest { ci.script = lib.mkForce '' cat "${tools.nuke-homebrew-repository.passthru.tests.test-nuke}" diff --git a/modules/default.nix b/modules/default.nix index 9452d34..9158544 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -268,24 +268,31 @@ let error "$tty_underline${namespaceDir}$tty_reset is in the way and needs to be moved out for $tty_underline${path}$tty_reset" exit 1 fi - if is_occupied "${tapDir}"; then + if [[ -L "${tapDir}" ]]; then + rm "${tapDir}" + elif [[ -d "${tapDir}" ]]; then + : + # directory + elif is_occupied "${tapDir}"; then error "An existing $tty_underline${tapDir}$tty_reset is in the way" exit 1 fi "''${MKDIR[@]}" "${namespaceDir}" "''${CHOWN[@]}" "$NIX_HOMEBREW_UID:$NIX_HOMEBREW_GID" "${namespaceDir}" "''${CHMOD[@]}" "ug=rwx" "${namespaceDir}" - /bin/ln -shf "${target}" "${tapDir}" + /usr/bin/rsync -rL --delete "${target}/" "${tapDir}" '') (builtins.attrNames taps) # Fully declarative taps else let - env = pkgs.runCommandLocal "taps-env" {} (lib.concatMapStrings (path: let + env = pkgs.runCommandLocal "taps-env" { } ('' + mkdir -p "$out" + '' + lib.concatMapStrings (path: let namespace = builtins.head (lib.splitString "/" path); target = taps.${path}; in '' mkdir -p "$out/${namespace}" - ln -s "${target}" "$out/${path}" + cp -RH "${target}" "$out/${path}" '') (builtins.attrNames taps)); in '' if is_occupied "$HOMEBREW_LIBRARY/Taps"; then