1 Commits
Author SHA1 Message Date
Zhaofeng Li 6c63d2adcb .github: Try reinstalling homebrew 2023-07-05 23:56:16 -06:00
20 changed files with 379 additions and 1086 deletions
+62 -24
View File
@@ -5,36 +5,74 @@ on:
pull_request:
jobs:
nix-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
check-migrate:
runs-on: macos-13
steps:
- uses: actions/checkout@v4
- uses: samueldr/lix-gha-installer-action@v2025-10-27
- id: set-matrix
name: Generate Nix Matrix
- uses: actions/checkout@v3
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- name: Test nuke-homebrew-repository
run: |
set -Eeu
matrix="$(nix eval --json '.#githubActions.matrix')"
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
check:
name: ${{ matrix.name }} (${{ matrix.system }})
needs: nix-matrix
runs-on: ${{ matrix.os }}
strategy:
matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}}
steps:
- uses: actions/checkout@v4
- uses: samueldr/lix-gha-installer-action@v2025-10-27
nix build .#nuke-homebrew-repository.passthru.tests.test-nuke -L
- name: Install some package with Homebrew
run: |
brew install unbound
- name: Add a third-party tap imperatively
run: |
brew tap koekeishiya/formulae
- name: Set up /run for nix-darwin
run: |
printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf
sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
- name: Run test
- name: Migrate existing Homebrew installation (imperative taps)
run: |
export NIX_HOMEBREW_CI=1
ci_script=$(nix build -L '.#${{ matrix.attr }}' --print-out-paths)
"$ci_script"
sudo rm /etc/bashrc
./ci/activate-example.sh migrate
- name: Check that we can still use the unbound package
run: $(brew --prefix)/sbin/unbound -V
- name: Check that we can still use the tap that we added imperatively
run: brew install koekeishiya/formulae/yabai
#- name: Migrate to fully-declarative tap management
# run: |
# false
check-non-standard-prefix:
runs-on: macos-13
steps:
- uses: actions/checkout@v3
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- name: Set up /run for nix-darwin
run: |
printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf
sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
- name: Install Homebrew
run: |
sudo rm /etc/bashrc
./ci/activate-example.sh non-standard-prefix
- name: Check that we can install packages
run: |
brew_path=$(type -P brew)
if [[ "${brew_path}" != "/run/current-system/sw/bin/brew" ]]; then
>&2 echo "brew is ${brew_path}, not /run/current-system/sw/bin/brew"
exit 1
fi
brew_prefix=$(brew --prefix)
if [[ "${brew_prefix}" != "/opt/nix-homebrew" ]]; then
>&2 echo "brew prefix is ${brew_prefix}, not /opt/nix-homebrew"
exit 1
fi
brew install gmp
-2
View File
@@ -3,8 +3,6 @@
result*
/ci/*.json
*.o
*.out
+2 -58
View File
@@ -1,12 +1,8 @@
# nix-homebrew
# nix-homebrew (WIP)
`nix-homebrew` manages Homebrew installations on macOS using [nix-darwin](https://github.com/LnL7/nix-darwin).
It pins the Homebrew version and optionally allows for declarative specification of taps.
`nix-homebrew` only installs Homebrew itself and does not manage any package installed by it.
For declarative formula/cask management, use the [`homebrew.*` options](https://daiderd.com/nix-darwin/manual/index.html#opt-homebrew.enable) in nix-darwin which work well in tandem with `nix-homebrew`.
## Quick Start
First of all, you must have [nix-darwin](https://github.com/LnL7/nix-darwin) configured already.
@@ -15,7 +11,7 @@ Add the following to your Flake inputs:
```nix
{
inputs = {
nix-homebrew.url = "github:zhaofengli/nix-homebrew";
nix-homebrew.url = "github:zhaofengli-wip/nix-homebrew";
# Optional: Declarative tap management
homebrew-core = {
@@ -64,23 +60,8 @@ If you haven't installed Homebrew before, use the following configuration:
#
# With mutableTaps disabled, taps can no longer be added imperatively with `brew tap`.
mutableTaps = false;
# Optional: Declarative Homebrew tap trust entries.
#
# Note: The trust entries are _not_ removed if you remove them from those lists!
# Use the `brew untrust` command to remove a trust entry.
trust = {
formulae = [ ];
casks = [ ];
commands = [ ];
taps = [ ];
};
};
}
# Optional: Align homebrew taps config with nix-homebrew
({config, ...}: {
homebrew.taps = builtins.attrNames config.nix-homebrew.taps;
})
];
};
};
@@ -92,27 +73,6 @@ Run `arch -x86_64 brew` to install X86-64 packages through Rosetta 2.
With `nix-homebrew.mutableTaps = false`, taps can be removed by deleting the corresponding attribute in `nix-homebrew.taps` and activating the new configuration.
Setting `homebrew.taps` to equal `nix-homebrew.taps` attribute names reduces configuration mismatches.
For non-official taps, Homebrew requires [explicit trust](https://docs.brew.sh/Tap-Trust).
You may use imperative `brew trust`/`brew untrust` commands, or configure `nix-homebrew` to add trust entries during activation:
```nix
nix-homebrew.trust = {
formulae = [ "user/repo/formula" ];
casks = [ "user/repo/cask" ];
commands = [ "user/repo/command" ];
# To quote upstream documentation:
# > Trust a whole tap only when you are comfortable with all current and
# > future formulae, casks and external commands from that tap being loaded
# > by Homebrew.
taps = [ "user/repo" ];
};
```
Note that when you remove items from those lists, the corresponding trust entries are _not_ removed automatically.
Use the `brew untrust` command to remove a trust entry.
### B. Existing Homebrew Installation
If you've already installed Homebrew with the official script, you can let `nix-homebrew` automatically migrate it:
@@ -163,19 +123,3 @@ Extra prefixes may be configured:
```
Note that with a non-standard prefix, you will no longer be able to use most bottles (prebuilt packages).
## Declarative Taps
In Homebrew, the repo part of all taps always have `homebrew-` prepended.
- https://docs.brew.sh/Taps
- https://docs.brew.sh/Interesting-Taps-and-Forks
`brew tap <user>/<repo>` makes a clone of the repository at `https://github.com/<user>/homebrew-<repo>` into `$(brew --repository)/Library/Taps`.
When declaring taps, please ensure to name the key as a unique folder starting with `homebrew-`, e.g.:
```diff
nix-homebrew.taps = {
- "mtslzr/marmaduke-chromium" = inputs.marmaduke-chromium;
+ "mtslzr/homebrew-marmaduke-chromium" = inputs.marmaduke-chromium;
```
The exact GitHub `<user>/<repo>` should almost always work.
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
DIR=$(dirname $0)
if [[ "$#" != "1" ]]; then
>&2 echo "Usage: $0 [example]"
exit 1
fi
example="$1"
nix-instantiate --eval --json -E 'builtins.currentSystem' >"${DIR}/system.json"
systemProfile=$(nix build "./${DIR}/..#darwinConfigurations.ci.${example}.system" -L --no-link --print-out-paths)
>&2 echo "Built $systemProfile"
sudo "$systemProfile/activate"
"$systemProfile/activate-user"
# vim: set et ts=2 sw=2:
+26
View File
@@ -0,0 +1,26 @@
# Activates example configurations on CI
{ self, nix-darwin, nixpkgs, ... }:
let
system = builtins.fromJSON (builtins.readFile ./system.json);
pkgs = nixpkgs.legacyPackages.${system};
inherit (pkgs) lib;
makeProfile = example: nix-darwin.lib.darwinSystem {
inherit system pkgs;
modules = [
self.darwinModules.nix-homebrew
(../examples + "/${example}.nix")
{
documentation.enable = false;
services.nix-daemon.enable = true;
nix-homebrew = {
user = lib.mkForce "runner";
};
}
];
};
in {
migrate = makeProfile "migrate";
non-standard-prefix = makeProfile "non-standard-prefix";
}
-11
View File
@@ -1,11 +0,0 @@
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
flakeCompat = import (fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
});
flake = flakeCompat {
src = ./.;
};
in
flake.defaultNix.outputs
Generated
-153
View File
@@ -1,153 +0,0 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"nix-darwin_26_05": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1780789116,
"narHash": "sha256-+/LcDMJGYQVLp3ECZ1jBhj3GcQU+Yt+OTsDsQFz8cMs=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "731951a251ca96cbd12a8e1bde63737e21947644",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"ref": "nix-darwin-26.05",
"repo": "nix-darwin",
"type": "github"
}
},
"nix-darwin_unstable": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1773000227,
"narHash": "sha256-zm3ftUQw0MPumYi91HovoGhgyZBlM4o3Zy0LhPNwzXE=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "da529ac9e46f25ed5616fd634079a5f3c579135f",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"repo": "nix-darwin",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"nixpkgs_unstable"
]
},
"locked": {
"lastModified": 1737420293,
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1779622335,
"narHash": "sha256-ViA62qtL5za7V3d5I8OA9q9JcFhsVAiL5jVHwEclWqk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "705e9929918b43bd7b715dc0a878ac870449bb03",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-26.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1765934234,
"narHash": "sha256-pJjWUzNnjbIAMIc5gRFUuKCDQ9S1cuh3b2hKgA7Mc4A=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "af84f9d270d404c17699522fab95bbf928a2d92f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_26_05": {
"locked": {
"lastModified": 1780902259,
"narHash": "sha256-q8yYEC5f1mFlQO9RGna4LTc9QrcvWunX6FYp83munkQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bd0ff2d3eac24699c3664d5966b9ef36f388e2ca",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-26.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_unstable": {
"locked": {
"lastModified": 1774386573,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"nix-darwin_26_05": "nix-darwin_26_05",
"nix-darwin_unstable": "nix-darwin_unstable",
"nix-github-actions": "nix-github-actions",
"nixpkgs_26_05": "nixpkgs_26_05",
"nixpkgs_unstable": "nixpkgs_unstable"
}
}
},
"root": "root",
"version": 7
}
-130
View File
@@ -1,130 +0,0 @@
# Only used for development & CI
{
inputs = {
nixpkgs_unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs_26_05.url = "github:NixOS/nixpkgs/nixos-26.05";
nix-darwin_unstable.url = "github:nix-darwin/nix-darwin";
nix-darwin_26_05.url = "github:nix-darwin/nix-darwin/nix-darwin-26.05";
nix-github-actions = {
url = "github:nix-community/nix-github-actions";
inputs.nixpkgs.follows = "nixpkgs_unstable";
};
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs =
inputs:
let
inherit (inputs.nixpkgs_unstable) lib;
supportedSystems = [
"x86_64-darwin"
"aarch64-darwin"
];
releases = {
"unstable" = {
nixpkgs = inputs.nixpkgs_unstable;
nix-darwin = inputs.nix-darwin_unstable;
};
"26.05" = {
nixpkgs = inputs.nixpkgs_26_05;
nix-darwin = inputs.nix-darwin_26_05;
};
};
githubPlatforms = {
"aarch64-darwin" = "macos-26";
"x86_64-darwin" = "macos-26";
};
matrix =
let
names = {
release = builtins.attrNames releases;
test = builtins.attrNames (
import ./tests.nix {
self = null;
pkgs = null;
nix-darwin = null;
}
);
};
in
lib.pipe names [
lib.cartesianProduct
(map (setup: {
name = "${setup.test}-${setup.release}";
value = setup;
}))
lib.listToAttrs
];
forAllSystems =
f: lib.genAttrs supportedSystems (system: f inputs.nixpkgs_unstable.legacyPackages.${system});
makeCi =
{ self, brew-src }:
let
assembleTest =
{
system,
release,
test,
}:
let
inputs' = releases.${release};
pkgs = inputs'.nixpkgs.legacyPackages.${system};
tests = import ./tests.nix {
inherit self pkgs;
inherit (inputs') nix-darwin;
};
in
tests.${test};
ciTests = lib.genAttrs supportedSystems (
system:
lib.mapAttrs (
name:
{ release, test }:
assembleTest {
inherit system release test;
}
) matrix
);
ciScripts = lib.mapAttrs (
system: tests: lib.mapAttrs (name: test: test.config.system.build.ci-script) tests
) ciTests;
in
{
inherit ciTests;
packages = forAllSystems (
pkgs:
pkgs.callPackages (self + "/pkgs") {
inherit brew-src;
}
);
devShell = forAllSystems (
pkgs:
pkgs.mkShell {
nativeBuildInputs = with pkgs; [
nixfmt
];
BREW_SRC = brew-src;
}
);
githubActions = inputs.nix-github-actions.lib.mkGithubMatrix {
checks = ciScripts;
platforms = githubPlatforms;
};
};
in
{
inherit makeCi;
};
}
+1
View File
@@ -0,0 +1 @@
"aarch64-darwin"
-214
View File
@@ -1,214 +0,0 @@
{
self,
pkgs,
nix-darwin,
}:
let
inherit (pkgs) lib system;
tools = self.packages.${pkgs.system};
makeTest =
module:
nix-darwin.lib.darwinSystem {
inherit system pkgs;
modules = [
self.darwinModules.nix-homebrew
module
(
{
pkgs,
lib,
config,
...
}:
{
options = {
ci = {
preScript = lib.mkOption {
type = lib.types.lines;
default = "";
};
script = lib.mkOption {
type = lib.types.lines;
default = ''
sudo rm -f /etc/bashrc /etc/nix/nix.conf /etc/nix/nix.custom.conf
sudo "${config.system.build.toplevel}/activate"
export PATH=/run/current-system/sw/bin:$PATH
'';
};
postScript = lib.mkOption {
type = lib.types.lines;
default = "";
};
};
};
config = {
documentation.enable = false;
system.stateVersion = 6;
nix-homebrew = {
user = lib.mkForce "runner";
};
system.build.ci-script = pkgs.writeShellScript "ci-script.sh" ''
set -euo pipefail
if [[ -z "''${NIX_HOMEBREW_CI:-}" ]]; then
>&2 echo "This script can only be run on nix-homebrew CI."
exit 1
fi
set -x
${config.ci.preScript}
${config.ci.script}
${config.ci.postScript}
'';
};
}
)
];
};
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"
'';
fakeThirdPartyTap = pkgs.runCommandLocal "thirdparty-test-tap" { } ''
mkdir -p "$out/Formula" "$out/Casks" "$out/cmd"
touch "$out/Formula/foo.rb"
touch "$out/Casks/test-cask.rb"
touch "$out/cmd/brew-test-command.rb"
'';
in
{
imports = [
module
];
_module.args.library = library;
nix-homebrew = {
enable = true;
autoMigrate = true;
taps = {
"homebrew/homebrew-cask" = fakeCaskTap;
"thirdparty/homebrew-testtap" = fakeThirdPartyTap;
};
trust = {
formulae = [ "thirdparty/testtap/foo" ];
casks = [ "thirdparty/testtap/test-cask" ];
commands = [ "thirdparty/testtap/test-command" ];
};
};
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"
>&2 echo "Checking declarative Homebrew trust entries"
brew trust --json=v1 --formula | grep '"thirdparty/testtap/foo"'
brew trust --json=v1 --cask | grep '"thirdparty/testtap/test-cask"'
brew trust --json=v1 --command | grep '"thirdparty/testtap/test-command"'
if brew trust --json=v1 --tap | grep '"thirdparty/testtap"'; then
>&2 echo "Expected thirdparty/testtap not to be trusted as a whole tap"
exit 1
fi
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 (
{ pkgs, config, ... }:
{
imports = [
(self + "/examples/migrate.nix")
];
nix-homebrew.enableRosetta = lib.mkForce pkgs.stdenv.hostPlatform.isAarch64;
# We only have Apple Silicon instances - Only test the install steps on native
# Apple Silicon for now
ci.preScript = lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 ''
>&2 echo "Installing some package with Homebrew"
brew install unbound
>&2 echo "Adding a third-party tap imperatively"
brew tap koekeishiya/formulae
'';
ci.postScript = ''
>&2 echo "Checking brew"
which brew
''
+ 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 ''
>&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"
>&2 echo "Checking that the unified brew launcher selects the correct prefix"
arch -arm64 brew config | grep "HOMEBREW_PREFIX: /opt/homebrew"
arch -x86_64 brew config | grep "HOMEBREW_PREFIX: /usr/local"
'';
}
);
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}"
'';
};
}
-1
View File
@@ -4,7 +4,6 @@
{
nix-homebrew = {
enable = true;
enableRosetta = true;
autoMigrate = true;
user = "yourname";
};
+19
View File
@@ -0,0 +1,19 @@
# Use a non-standard prefix
{ pkgs, ... }:
{
nix-homebrew = {
enable = true;
prefixes = {
"/usr/local".enable = true;
"/opt/homebrew".enable = true;
"/opt/nix-homebrew" = {
enable = true;
library = "/opt/nix-homebrew/Library";
};
};
user = "yourname";
defaultIntelPrefix = "/opt/nix-homebrew";
defaultArm64Prefix = "/opt/nix-homebrew";
};
}
Generated
+88 -5
View File
@@ -3,23 +3,106 @@
"brew-src": {
"flake": false,
"locked": {
"lastModified": 1784558651,
"narHash": "sha256-woXJ1ATKpSYRWCy46TQJjmm9XzAeZVEZw9xDfVG9NYI=",
"lastModified": 1687876440,
"narHash": "sha256-4hoGm5PUYmz091Pqrii4rpfsLsE7/gjIThHVBq6Vquk=",
"owner": "Homebrew",
"repo": "brew",
"rev": "b48c7994b5f0eed7bef532efa63cb4e4f763887a",
"rev": "eff45ef570f265e226f14ce91da72d7a6e7d516a",
"type": "github"
},
"original": {
"owner": "Homebrew",
"ref": "6.0.12",
"ref": "4.0.26",
"repo": "brew",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1687709756,
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1688307440,
"narHash": "sha256-7PTjbN+/+b799YN7Tk2SS5Vh8A0L3gBo8hmB7Y0VXug=",
"owner": "LnL7",
"repo": "nix-darwin",
"rev": "b06bab83bdf285ea0ae3c8e145a081eb95959047",
"type": "github"
},
"original": {
"owner": "LnL7",
"repo": "nix-darwin",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1687274257,
"narHash": "sha256-TutzPriQcZ8FghDhEolnHcYU2oHIG5XWF+/SUBNnAOE=",
"path": "/nix/store/22qgs3skscd9bmrxv9xv4q5d4wwm5ppx-source",
"rev": "2c9ecd1f0400076a4d6b2193ad468ff0a7e7fdc5",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1688049487,
"narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"brew-src": "brew-src"
"brew-src": "brew-src",
"flake-utils": "flake-utils",
"nix-darwin": "nix-darwin",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
+22 -17
View File
@@ -2,34 +2,39 @@
description = "Homebrew installation manager for nix-darwin";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nix-darwin.url = "github:LnL7/nix-darwin";
flake-utils.url = "github:numtide/flake-utils";
brew-src = {
url = "github:Homebrew/brew/6.0.12";
url = "github:Homebrew/brew/4.0.26";
flake = false;
};
};
outputs = { self, brew-src }: let
flakeLock = builtins.fromJSON (builtins.readFile ./flake.lock);
brewVersion = flakeLock.nodes.brew-src.original.ref;
ci = (import ./ci/flake-compat.nix).makeCi {
inherit self brew-src;
};
outputs = { self, nixpkgs, nix-darwin, flake-utils, brew-src, ... } @ inputs: let
# System types to support.
supportedSystems = [ "x86_64-darwin" "aarch64-darwin" ];
in flake-utils.lib.eachSystem supportedSystems (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
darwinModules = rec {
packages = pkgs.callPackage ./pkgs {
inherit inputs;
};
devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
];
};
}) // {
darwinModules = {
nix-homebrew = { lib, ... }: {
imports = [
./modules
];
nix-homebrew.package = lib.mkOptionDefault (brew-src // {
name = "brew-${brewVersion}";
version = brewVersion;
});
nix-homebrew.package = lib.mkOptionDefault brew-src.outPath;
};
default = nix-homebrew;
};
inherit (ci) packages devShell ciTests githubActions;
darwinConfigurations = {
ci = import ./ci inputs;
};
};
}
-233
View File
@@ -1,233 +0,0 @@
# -----
# The following is copied from upstream bin/brew
# Copyright (c) 2009-present, Homebrew contributors
# -----
# nix-homebrew:
# Run scripts/update-brew-tail.sh to update this
# These variables are exported in this file and are not allowed to be overridden by the user.
BIN_BREW_EXPORTED_VARS=(
HOMEBREW_BREW_FILE
HOMEBREW_PREFIX
HOMEBREW_REPOSITORY
HOMEBREW_LIBRARY
HOMEBREW_USER_CONFIG_HOME
HOMEBREW_ORIGINAL_BREW_FILE
)
BIN_BREW_EXPORTED_VARS_REGEX="^($(
IFS='|'
echo "${BIN_BREW_EXPORTED_VARS[*]}"
))(=|$)"
# Load Homebrew's variable configuration files from disk.
export_homebrew_env_file() {
local env_file
env_file="${1}"
[[ -r "${env_file}" ]] || return 0
while read -r line
do
# only load variables defined in env_config.rb
[[ "${line}" =~ ^(HOMEBREW_|SUDO_ASKPASS=|(all|no|ftp|https?)_proxy=) ]] || continue
# forbid overriding variables that are set in this file
[[ "${line}" =~ ${BIN_BREW_EXPORTED_VARS_REGEX} ]] && continue
if [[ "${line}" == HOMEBREW_EXPERIMENTAL_RUST_FRONTEND=* ]]
then
echo "Warning: Ignoring HOMEBREW_EXPERIMENTAL_RUST_FRONTEND. This cannot be set in an env file." >&2
continue
fi
export "${line?}"
done <"${env_file}"
}
# We only want to be able to set this in `brew.env` files.
unset HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER
# First, load the system-wide configuration.
export_homebrew_env_file "/etc/homebrew/brew.env"
unset SYSTEM_ENV_TAKES_PRIORITY
if [[ -n "${HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY-}" ]]
then
SYSTEM_ENV_TAKES_PRIORITY="1"
fi
# Next, load the prefix configuration
export_homebrew_env_file "${HOMEBREW_PREFIX}/etc/homebrew/brew.env"
# Finally, load the user configuration
if [[ -n "${XDG_CONFIG_HOME-}" ]]
then
HOMEBREW_USER_CONFIG_HOME="${XDG_CONFIG_HOME}/homebrew"
elif [[ -n "${HOMEBREW_XDG_CONFIG_HOME-}" ]]
then
HOMEBREW_USER_CONFIG_HOME="${HOMEBREW_XDG_CONFIG_HOME}/homebrew"
else
HOMEBREW_USER_CONFIG_HOME="${HOME}/.homebrew"
fi
export_homebrew_env_file "${HOMEBREW_USER_CONFIG_HOME}/brew.env"
# If the system configuration takes priority, load it again to override any previous settings.
if [[ -n "${SYSTEM_ENV_TAKES_PRIORITY-}" ]]
then
export_homebrew_env_file "/etc/homebrew/brew.env"
fi
# Use HOMEBREW_FORCE_BREW_WRAPPER if set.
export HOMEBREW_ORIGINAL_BREW_FILE="${HOMEBREW_BREW_FILE}"
if [[ -n "${HOMEBREW_FORCE_BREW_WRAPPER:-}" ]]
then
HOMEBREW_BREW_FILE="${HOMEBREW_FORCE_BREW_WRAPPER}"
fi
# Copy and export all HOMEBREW_* variables previously mentioned in
# manpage or used elsewhere by Homebrew.
# These variables are allowed to be set by the user as, e.g., `HOMEBREW_BROWSER`.
MANPAGE_VARS=(
BAT_CONFIG_PATH
BAT_THEME
BROWSER
BUNDLE_USER_CACHE
DISPLAY
EDITOR
NO_COLOR
)
for VAR in "${MANPAGE_VARS[@]}"
do
# Skip if variable value is empty or set to 0.
[[ -z "${!VAR:-}" || "${!VAR:-}" = "0" ]] && continue
VAR_NEW="HOMEBREW_${VAR}"
# Skip if existing HOMEBREW_* variable is set.
[[ -n "${!VAR_NEW:-}" ]] && continue
export "${VAR_NEW}"="${!VAR}"
done
# We don't want to take the user's value for, e.g., `HOMEBREW_PATH` here!
USED_BY_HOMEBREW_VARS=(
CARGO_HOME
CARGO_INSTALL_ROOT
CODESPACES
COLORTERM
DBUS_SESSION_BUS_ADDRESS
GOBIN
GOPATH
LANG
NODENV_ROOT
PATH
PYENV_ROOT
RBENV_ROOT
RUSTUP_HOME
SSH_TTY
SUDO_USER
TMPDIR
TMUX
VSCODE_IPC_HOOK_CLI
WSL_DISTRO_NAME
XDG_CACHE_HOME
XDG_CONFIG_HOME
XDG_DATA_DIRS
XDG_DATA_HOME
XDG_RUNTIME_DIR
ZDOTDIR
)
for VAR in "${USED_BY_HOMEBREW_VARS[@]}"
do
# Skip if variable value is empty.
[[ -z "${!VAR:-}" ]] && continue
# We unconditionally override `HOMEBREW_*` here.
VAR_NEW="HOMEBREW_${VAR}"
export "${VAR_NEW}"="${!VAR}"
done
unset VAR VAR_NEW MANPAGE_VARS USED_BY_HOMEBREW_VARS
for VAR in "${BIN_BREW_EXPORTED_VARS[@]}"
do
export "${VAR?}"
done
# set from user environment
# shellcheck disable=SC2154
# Use VISUAL if HOMEBREW_EDITOR and EDITOR are unset.
if [[ -z "${HOMEBREW_EDITOR:-}" && -n "${VISUAL:-}" ]]
then
export HOMEBREW_EDITOR="${VISUAL}"
fi
# set from user environment
# shellcheck disable=SC2154
# Set CI variable for Azure Pipelines and Jenkins
# (Set by default on GitHub Actions, Circle and Travis CI)
if [[ -z "${CI:-}" ]] && [[ -n "${TF_BUILD:-}" || -n "${JENKINS_HOME:-}" ]]
then
export CI="1"
fi
if [[ -n "${GITHUB_ACTIONS:-}" && -n "${ImageOS:-}" && -n "${ImageVersion:-}" ]]
then
export HOMEBREW_GITHUB_HOSTED_RUNNER=1
fi
# don't filter the environment for `brew bundle (exec|env|sh)`
if [[ "${1:-}" == "bundle" ]]
then
if [[ "${2:-}" == "exec" || "${2:-}" == "env" || "${2:-}" == "sh" ]]
then
exec /bin/bash -p "${HOMEBREW_LIBRARY}/Homebrew/brew.sh" "$@"
exit $?
fi
fi
# filter the user environment
PATH="@runtimePath@:/usr/bin:/bin:/usr/sbin:/sbin"
FILTERED_ENV=()
ENV_VAR_NAMES=(
HOME SHELL PATH TERM TERMINFO TERMINFO_DIRS COLUMNS DISPLAY LOGNAME USER CI SSH_AUTH_SOCK SUDO_ASKPASS
http_proxy https_proxy ftp_proxy no_proxy all_proxy HTTPS_PROXY FTP_PROXY ALL_PROXY
)
# Filter all but the specific variables.
for VAR in "${ENV_VAR_NAMES[@]}" "${!HOMEBREW_@}"
do
# Skip if variable value is empty.
[[ -z "${!VAR:-}" ]] && continue
FILTERED_ENV+=("${VAR}=${!VAR}")
done
if [[ -n "${CI:-}" ]]
then
for VAR in "${!GITHUB_@}"
do
# Skip if variable value is empty.
[[ -z "${!VAR:-}" ]] && continue
# Skip variables that look like tokens.
[[ "${VAR}" = *TOKEN* ]] && continue
FILTERED_ENV+=("${VAR}=${!VAR}")
done
fi
if [[ -n "${HOMEBREW_RDBG:-}" ]]
then
for VAR in "${!RUBY_DEBUG_@}"
do
# Skip if variable value is empty.
[[ -z "${!VAR:-}" ]] && continue
FILTERED_ENV+=("${VAR}=${!VAR}")
done
fi
unset VAR ENV_VAR_NAMES
exec /usr/bin/env -i "${FILTERED_ENV[@]}" /bin/bash -p "${HOMEBREW_LIBRARY}/Homebrew/brew.sh" "$@"
+128 -192
View File
@@ -22,7 +22,7 @@
# that automatically selects the correct prefix based on the architecture.
# Use `arch -x86_64 brew` to install X86-64 packages.
{ pkgs, lib, config, options, ... }:
{ pkgs, lib, config, ... }:
let
inherit (lib) types;
@@ -35,21 +35,16 @@ let
tools = pkgs.callPackage ../pkgs { };
brew = if cfg.patchBrew then patchBrew cfg.package else cfg.package;
ruby = pkgs.ruby_4_0;
# Sadly, we cannot replace coreutils since the GNU implementations
# behave differently.
runtimePath = lib.makeBinPath [ pkgs.gitMinimal ];
prefixType = types.submodule ({ name, ... }: {
options = {
enable = lib.mkOption {
description = ''
description = lib.mdDoc ''
Whether to set up this Homebrew prefix.
'';
};
prefix = lib.mkOption {
description = ''
description = lib.mdDoc ''
The Homebrew prefix.
By default, it's `/opt/homebrew` for Apple Silicon Macs and
@@ -59,7 +54,7 @@ let
default = name;
};
library = lib.mkOption {
description = ''
description = lib.mdDoc ''
The Homebrew library.
By default, it's `/opt/homebrew/Library` for Apple Silicon Macs and
@@ -68,7 +63,7 @@ let
type = types.str;
};
taps = lib.mkOption {
description = ''
description = lib.mdDoc ''
A set of Nix-managed taps.
'';
type = types.attrsOf types.package;
@@ -90,7 +85,7 @@ let
# Our unified brew launcher script.
#
# We use `/bin/bash` (Bash 3.2 :/) instead of `${runtimeShell}`
# for compatibility with `arch -x86_64`.
# for compatibility with `arch -x86_64`.
brewLauncher = pkgs.writeScriptBin "brew" (''
#!/bin/bash
set -euo pipefail
@@ -129,23 +124,111 @@ let
'' + lib.optionalString (prefix.taps ? "homebrew/homebrew-core") ''
# Disable API to use pinned homebrew-core
export HOMEBREW_NO_INSTALL_FROM_API=1
'' + (lib.optionalString (cfg.extraEnv != {})
(lib.concatLines (lib.mapAttrsToList (name: value: "export ${name}=${lib.escapeShellArg value}") cfg.extraEnv)))
+ (builtins.readFile ./brew.tail.sh));
in pkgs.replaceVarsWith {
'' + ''
# -----
# The following is copied from upstream bin/brew
# Copyright (c) 2009-present, Homebrew contributors
# -----
# Copy and export all HOMEBREW_* variables previously mentioned in
# manpage or used elsewhere by Homebrew.
# These variables are allowed to be set by the user as, e.g., `HOMEBREW_BROWSER`.
MANPAGE_VARS=(
BAT_CONFIG_PATH
BAT_THEME
BROWSER
DISPLAY
EDITOR
NO_COLOR
)
for VAR in "''${MANPAGE_VARS[@]}"
do
# Skip if variable value is empty.
[[ -z "''${!VAR:-}" ]] && continue
VAR_NEW="HOMEBREW_''${VAR}"
# Skip if existing HOMEBREW_* variable is set.
[[ -n "''${!VAR_NEW:-}" ]] && continue
export "''${VAR_NEW}"="''${!VAR}"
done
# We don't want to take the user's value for, e.g., `HOMEBREW_PATH` here!
USED_BY_HOMEBREW_VARS=(
CODESPACES
DBUS_SESSION_BUS_ADDRESS
PATH
TMUX
XDG_RUNTIME_DIR
)
for VAR in "''${USED_BY_HOMEBREW_VARS[@]}"
do
# Skip if variable value is empty.
[[ -z "''${!VAR:-}" ]] && continue
# We unconditionally override `HOMEBREW_*` here.
VAR_NEW="HOMEBREW_''${VAR}"
export "''${VAR_NEW}"="''${!VAR}"
done
unset VAR VAR_NEW MANPAGE_VARS USED_BY_HOMEBREW_VARS
# set from user environment
# shellcheck disable=SC2154
# Use VISUAL if HOMEBREW_EDITOR and EDITOR are unset.
if [[ -z "''${HOMEBREW_EDITOR:-}" && -n "''${VISUAL:-}" ]]
then
export HOMEBREW_EDITOR="''${VISUAL}"
fi
# set from user environment
# shellcheck disable=SC2154
# Set CI variable for Azure Pipelines and Jenkins
# (Set by default on GitHub Actions, Circle and Travis CI)
if [[ -z "''${CI:-}" ]] && [[ -n "''${TF_BUILD:-}" || -n "''${JENKINS_HOME:-}" ]]
then
export CI="1"
fi
# filter the user environment
PATH="/usr/bin:/bin:/usr/sbin:/sbin"
FILTERED_ENV=()
ENV_VAR_NAMES=(
HOME SHELL PATH TERM TERMINFO TERMINFO_DIRS COLUMNS DISPLAY LOGNAME USER CI SSH_AUTH_SOCK SUDO_ASKPASS
http_proxy https_proxy ftp_proxy no_proxy all_proxy HTTPS_PROXY FTP_PROXY ALL_PROXY
)
# Filter all but the specific variables.
for VAR in "''${ENV_VAR_NAMES[@]}" "''${!HOMEBREW_@}"
do
# Skip if variable value is empty.
[[ -z "''${!VAR:-}" ]] && continue
FILTERED_ENV+=("''${VAR}=''${!VAR}")
done
if [[ -n "''${CI:-}" ]]
then
for VAR in "''${!GITHUB_@}"
do
# Skip if variable value is empty.
[[ -z "''${!VAR:-}" ]] && continue
# Skip variables that look like tokens.
[[ "''${VAR}" = *TOKEN* ]] && continue
FILTERED_ENV+=("''${VAR}=''${!VAR}")
done
fi
unset VAR ENV_VAR_NAMES
exec /usr/bin/env -i "''${FILTERED_ENV[@]}" /bin/bash "''${HOMEBREW_LIBRARY}/Homebrew/brew.sh" "$@"
'');
in pkgs.substituteAll {
name = "brew";
src = template;
isExecutable = true;
# Must retain #!/bin/bash, otherwise `arch -x86_64 /usr/local/bin/brew`
# on Apple Silicon will not work.
dontPatchShebangs = true;
replacements = {
out = placeholder "out";
inherit runtimePath;
inherit (prefix) prefix library;
};
inherit (prefix) prefix library;
};
setupHomebrew = let
@@ -187,7 +270,7 @@ let
if test -n "${toString cfg.enableRosetta}" && ! pgrep -q oahd; then
warn "The Intel Homebrew prefix has been set up, but Rosetta isn't installed yet."
ohai "Run ''${tty_bold}softwareupdate --install-rosetta''${tty_reset} to install it."
ohai 'Run ''${tty_bold}softwareupdate --install-rosetta''${tty_reset} to install it.'
fi
'';
@@ -243,7 +326,6 @@ let
"''${MKDIR[@]}" "$HOMEBREW_LIBRARY/.homebrew-is-managed-by-nix/.git"
"''${CHOWN[@]}" "$NIX_HOMEBREW_UID:$NIX_HOMEBREW_GID" "$HOMEBREW_LIBRARY/.homebrew-is-managed-by-nix"
"''${CHMOD[@]}" 775 "$HOMEBREW_LIBRARY/.homebrew-is-managed-by-nix/"{,.git}
"''${TOUCH[@]}" "$HOMEBREW_LIBRARY/.homebrew-is-managed-by-nix/.git/HEAD"
# Link generated bin/brew
BIN_BREW="$HOMEBREW_PREFIX/bin/brew"
@@ -252,19 +334,6 @@ let
exit 1
fi
/bin/ln -shf "${makeBinBrew prefix}" "$BIN_BREW"
${setupTrust}
'';
setupTrust = let
trustEntries = flag: entries: lib.concatMapStrings (entry: ''
/usr/bin/sudo -n -u ${lib.escapeShellArg cfg.user} -H "$BIN_BREW" trust ${flag} ${lib.escapeShellArg entry} >/dev/null
'') entries;
in ''
${trustEntries "--tap" cfg.trust.taps}
${trustEntries "--formula" cfg.trust.formulae}
${trustEntries "--cask" cfg.trust.casks}
${trustEntries "--command" cfg.trust.commands}
'';
setupTaps = taps:
@@ -281,31 +350,24 @@ 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 [[ -L "${tapDir}" ]]; then
rm "${tapDir}"
elif [[ -d "${tapDir}" ]]; then
:
# directory
elif is_occupied "${tapDir}"; then
if 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}"
/usr/bin/rsync -rL --delete "${target}/" "${tapDir}"
/bin/ln -shf "${target}" "${tapDir}"
'') (builtins.attrNames taps)
# Fully declarative taps
else let
env = pkgs.runCommandLocal "taps-env" { } (''
mkdir -p "$out"
'' + lib.concatMapStrings (path: let
env = pkgs.runCommandLocal "taps-env" {} (lib.concatMapStrings (path: let
namespace = builtins.head (lib.splitString "/" path);
target = taps.${path};
in ''
mkdir -p "$out/${namespace}"
cp -RH "${target}" "$out/${path}"
ln -s "${target}" "$out/${path}"
'') (builtins.attrNames taps));
in ''
if is_occupied "$HOMEBREW_LIBRARY/Taps"; then
@@ -316,41 +378,19 @@ let
/bin/ln -shf "${env}" "$HOMEBREW_LIBRARY/Taps"
'';
patchBrew = brew: pkgs.runCommandLocal "${brew.name or "brew"}-patched" {} (''
# Patch Homebrew to disable self-update behavior
patchBrew = brew: pkgs.runCommandLocal "${brew.name or "brew"}-patched" {} ''
cp -r "${brew}" "$out"
chmod u+w "$out" "$out/Library/Homebrew/cmd"
# Disable self-update behavior
substituteInPlace "$out/Library/Homebrew/cmd/update.sh" \
--replace-fail 'for DIR in "''${HOMEBREW_REPOSITORY}"' "for DIR in "
# Disable vendored Ruby
#
# Homebrew passes --disable=gems,rubyopt ($HOMEBREW_RUBY_DISABLE_OPTIONS)
# and inserts vendored libraries into LOAD_PATH (vendor/bundle/bundler/setup.rb, standalone/init.rb).
# Instead of re-enabling gems, we add in additional required gems into LOAD_PATH.
ruby_sh="$out/Library/Homebrew/utils/ruby.sh"
bundler_setup_rb="$out/Library/Homebrew/vendor/bundle/bundler/setup.rb"
if [[ -e "$ruby_sh" ]] && grep "setup-ruby-path" "$ruby_sh" >/dev/null; then
>&2 echo "Patching vendored Ruby..."
chmod u+w "$ruby_sh" "$bundler_setup_rb"
echo -e "setup-ruby-path() { export HOMEBREW_RUBY_PATH=\"${ruby}/bin/ruby\"; }" >>"$ruby_sh"
echo -e "$:.unshift \"${ruby.gems.fiddle}/${ruby.gemPath}/gems/fiddle-${ruby.gems.fiddle.version}/lib\"" >>"$bundler_setup_rb"
fi
'' + lib.optionalString (brew ? version) ''
# Embed version number instead of checking with git
brew_sh="$out/Library/Homebrew/brew.sh"
chmod u+w "$out/Library/Homebrew" "$brew_sh"
sed -i -e 's/^HOMEBREW_VERSION=.*/HOMEBREW_VERSION="${brew.version}"/g' "$brew_sh"
# 4.3.5: Clear GIT_REVISION to bypass caching mechanism
sed -i -e 's/^GIT_REVISION=.*/GIT_REVISION=""; HOMEBREW_VERSION="${brew.version}"/g' "$brew_sh"
'');
--replace 'for DIR in "''${HOMEBREW_REPOSITORY}"' "for DIR in "
'';
in {
options = {
nix-homebrew = {
enable = lib.mkOption {
description = ''
description = lib.mdDoc ''
Whether to install Homebrew.
'';
type = types.bool;
@@ -366,13 +406,13 @@ in {
default = false;
};
package = lib.mkOption {
description = ''
description = lib.mdDoc ''
The homebrew package itself.
'';
type = types.package;
};
taps = lib.mkOption {
description = ''
description = lib.mdDoc ''
A set of Nix-managed taps.
These are applied to the default prefixes.
@@ -391,7 +431,7 @@ in {
'';
};
mutableTaps = lib.mkOption {
description = ''
description = lib.mdDoc ''
Whether to allow imperative management of taps.
When enabled, taps can be managed via `brew tap` and
@@ -403,68 +443,6 @@ in {
type = types.bool;
default = true;
};
trust = lib.mkOption {
description = ''
Tap trust entries to be added during activation.
Note: The trust entries are _not_ removed if you remove them from
those lists! Use the `brew untrust` command to remove a trust entry.
Refer to upstream documentations for more information:
<https://docs.brew.sh/Tap-Trust>
'';
type = types.submodule {
options = {
taps = lib.mkOption {
description = ''
Taps to trust in their entirety.
This should be used with caution. To quote upstream documentation:
> Trust a whole tap only when you are comfortable with all current and
> future formulae, casks and external commands from that tap being loaded
> by Homebrew.
'';
type = types.listOf types.str;
default = [];
example = [
"user/repo"
];
};
formulae = lib.mkOption {
description = ''
Fully-qualified formulae to trust.
'';
type = types.listOf types.str;
default = [];
example = [
"user/repo/formula"
];
};
casks = lib.mkOption {
description = ''
Fully-qualified casks to trust.
'';
type = types.listOf types.str;
default = [];
example = [
"user/repo/cask"
];
};
commands = lib.mkOption {
description = ''
Fully-qualified external commands to trust.
'';
type = types.listOf types.str;
default = [];
example = [
"user/repo/command"
];
};
};
};
default = {};
};
autoMigrate = lib.mkOption {
description = ''
Whether to allow nix-homebrew to automatically migrate existing Homebrew installations.
@@ -476,13 +454,13 @@ in {
default = false;
};
user = lib.mkOption {
description = ''
description = lib.mdDoc ''
The user owning the Homebrew directories.
'';
type = types.str;
};
group = lib.mkOption {
description = ''
description = lib.mdDoc ''
The group owning the Homebrew directories.
'';
type = types.str;
@@ -501,7 +479,7 @@ in {
type = types.attrsOf prefixType;
};
defaultArm64Prefix = lib.mkOption {
description = ''
description = lib.mdDoc ''
Key of the default Homebrew prefix for ARM64 macOS.
'';
internal = true;
@@ -509,7 +487,7 @@ in {
default = "/opt/homebrew";
};
defaultIntelPrefix = lib.mkOption {
description = ''
description = lib.mdDoc ''
Key of the default Homebrew prefix for Intel macOS or Rosetta 2.
'';
internal = true;
@@ -517,7 +495,7 @@ in {
default = "/usr/local";
};
extraEnv = lib.mkOption {
description = ''
description = lib.mdDoc ''
Extra environment variables to set for Homebrew.
'';
type = types.attrsOf types.str;
@@ -535,19 +513,6 @@ in {
type = types.bool;
default = true;
};
# Shell integrations
enableBashIntegration = lib.mkEnableOption "homebrew bash integration" // {
default = true;
};
enableFishIntegration = lib.mkEnableOption "homebrew fish integration" // {
default = true;
};
enableZshIntegration = lib.mkEnableOption "homebrew zsh integration" // {
default = true;
};
};
};
@@ -557,12 +522,6 @@ in {
assertion = cfg.enableRosetta -> pkgs.stdenv.hostPlatform.isAarch64;
message = "nix-homebrew.enableRosetta is set to true but this isn't an Apple Silicon Mac";
}
{
# nix-darwin has migrated away from user activation in
# <https://github.com/LnL7/nix-darwin/pull/1341>.
assertion = options.system ? primaryUser;
message = "Please update your nix-darwin version to use system-wide activation";
}
];
nix-homebrew = {
@@ -580,38 +539,15 @@ in {
};
};
# Shell integrations
programs.bash.interactiveShellInit = lib.mkIf cfg.enableBashIntegration ''
eval "$(brew shellenv 2>/dev/null || true)"
'';
programs.zsh.interactiveShellInit = lib.mkIf cfg.enableZshIntegration ''
eval "$(brew shellenv 2>/dev/null || true)"
'';
programs.fish.interactiveShellInit = lib.mkIf cfg.enableFishIntegration ''
brew shellenv 2>/dev/null | source || true
'';
environment.systemPackages = [ brewLauncher ];
system.activationScripts = {
# Set up the Homebrew prefixes before nix-darwin's homebrew
# activation takes place.
homebrew.text = lib.mkBefore ''
# We set up a new system activation step that sets up Homebrew
extraUserActivation.text = lib.mkAfter ''
${config.system.activationScripts.setup-homebrew.text}
'';
setup-homebrew.text = ''
>&2 echo "setting up Homebrew prefixes..."
${setupHomebrew}
sudo ${setupHomebrew}
'';
};
# disable the install homebrew check
# see https://github.com/LnL7/nix-darwin/pull/1178 and https://github.com/zhaofengli/nix-homebrew/issues/45
system.checks.text = lib.mkIf config.homebrew.enable (lib.mkBefore ''
# Ignore unused variable in nix-darwin versions without it
# shellcheck disable=SC2034
INSTALLING_HOMEBREW=1
'');
};
}
+2 -2
View File
@@ -1,6 +1,6 @@
{ callPackage, brew-src ? null }:
{ callPackage, inputs ? {} }:
{
nuke-homebrew-repository = callPackage ./nuke-homebrew-repository {
inherit brew-src;
inherit inputs;
};
}
+8 -10
View File
@@ -1,6 +1,6 @@
{ lib
, pkgs
, replaceVarsWith
, substituteAll
, runtimeShell
, coreutils
, findutils
@@ -8,25 +8,23 @@
, gnused
, gitMinimal
, brew-src ? null
, inputs
, runCommandLocal
}:
let
script = replaceVarsWith {
script = substituteAll {
name = "nuke-homebrew-repository";
src = ./nuke-homebrew-repository.sh.in;
isExecutable = true;
replacements = {
inherit runtimeShell;
path = lib.makeBinPath [ coreutils findutils gnugrep gnused gitMinimal ];
};
inherit runtimeShell;
path = lib.makeBinPath [ coreutils findutils gnugrep gnused gitMinimal ];
};
test-nuke =
assert (lib.assertMsg (brew-src != null) "brew-src must be provided");
runCommandLocal "test-nuke" {
brew-src = inputs.brew-src or (throw "The tests can only be run with flakes");
test-nuke = runCommandLocal "test-nuke" {
nativeBuildInputs = [ gitMinimal ];
} ''
must_exist() {
@@ -30,7 +30,7 @@ if [[ ! -e ".git" ]]; then
exit 1
fi
if ! grep -E "^#.*Homebrew" "README.md" >/dev/null; then
if ! grep -E "^# Homebrew" "README.md" >/dev/null; then
>&2 echo "${PWD} does not looks like a Homebrew checkout"
exit 1
fi
@@ -45,11 +45,6 @@ done < <(git ls-files)
printf "%s\0" "${files_to_delete[@]}" | xargs -0 rm
if [[ -e "Library/Homebrew/vendor" ]]; then
>&2 echo "Removing stray vendor directory"
rm -rf --one-file-system "Library/Homebrew/vendor"
fi
# Next, delete all directories
while read -r dir; do
if [[ -d "$dir" ]]; then
-28
View File
@@ -1,28 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
: "${BREW_SRC:=}"
root="$(dirname $0)/.."
brew_tail="$root/modules/brew.tail.sh"
brew_upstream="${BREW_SRC}/bin/brew"
if [[ -z "${BREW_SRC}" ]]; then
>&2 echo "\$BREW_SRC must be set"
exit 1
fi
>&2 echo "Updating ${brew_tail} using ${brew_upstream}"
cat >"${brew_tail}" <<EOF
# -----
# The following is copied from upstream bin/brew
# Copyright (c) 2009-present, Homebrew contributors
# -----
# nix-homebrew:
# Run scripts/update-brew-tail.sh to update this
EOF
sed \
-e '1,/^HOMEBREW_LIBRARY=/d' \
-e 's/^PATH="/PATH="@runtimePath@:/' \
"${brew_upstream}" >>"${brew_tail}"