2020-12-08 02:14:48 +00:00
|
|
|
|
# Created by: https://github.com/malob
|
2022-08-24 20:07:19 +00:00
|
|
|
|
{ config, lib, options, pkgs, ... }:
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
|
|
let
|
2020-12-17 21:03:57 +00:00
|
|
|
|
cfg = config.homebrew;
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
brewfileFile = pkgs.writeText "Brewfile" cfg.brewfile;
|
2022-08-23 01:10:46 +00:00
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
# Brewfile creation helper functions -------------------------------------------------------------
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
mkBrewfileSectionString = heading: entries: optionalString (entries != [ ]) ''
|
|
|
|
|
# ${heading}
|
|
|
|
|
${concatMapStringsSep "\n" (v: v.brewfileLine or v) entries}
|
|
|
|
|
|
|
|
|
|
'';
|
2022-08-22 21:49:22 +00:00
|
|
|
|
|
|
|
|
|
mkBrewfileLineValueString = v:
|
|
|
|
|
if isInt v then toString v
|
|
|
|
|
else if isFloat v then strings.floatToString v
|
|
|
|
|
else if isBool v then boolToString v
|
|
|
|
|
else if isString v then ''"${v}"''
|
|
|
|
|
else if isAttrs v then "{ ${concatStringsSep ", " (mapAttrsToList (n: v': "${n}: ${mkBrewfileLineValueString v'}") v)} }"
|
|
|
|
|
else if isList v then "[${concatMapStringsSep ", " mkBrewfileLineValueString v}]"
|
|
|
|
|
else abort "The value: ${generators.toPretty v} is not a valid Brewfile value.";
|
|
|
|
|
|
|
|
|
|
mkBrewfileLineOptionsListString = attrs:
|
2022-08-23 20:32:07 +00:00
|
|
|
|
concatStringsSep ", " (mapAttrsToList (n: v: "${n}: ${v}") attrs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Submodule helper functions ---------------------------------------------------------------------
|
2022-08-22 21:49:22 +00:00
|
|
|
|
|
|
|
|
|
mkNullOrBoolOption = args: mkOption (args // {
|
|
|
|
|
type = types.nullOr types.bool;
|
|
|
|
|
default = null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
mkNullOrStrOption = args: mkOption (args // {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = null;
|
|
|
|
|
});
|
|
|
|
|
|
2022-08-23 01:10:46 +00:00
|
|
|
|
mkBrewfileLineOption = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
visible = false;
|
|
|
|
|
internal = true;
|
|
|
|
|
readOnly = true;
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
mkProcessedSubmodConfig = attrs: mapAttrs (_: mkBrewfileLineValueString)
|
|
|
|
|
(filterAttrsRecursive (n: v: n != "_module" && n != "brewfileLine" && v != null) attrs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Submodules -------------------------------------------------------------------------------------
|
|
|
|
|
# Option values and descriptions of Brewfile entries are sourced/derived from:
|
|
|
|
|
# * `brew` manpage: https://docs.brew.sh/Manpage
|
|
|
|
|
# * `brew bundle` source files (at https://github.com/Homebrew/homebrew-bundle/tree/9fffe077f1a5a722ed5bd26a87ed622e8cb64e0c):
|
|
|
|
|
# * lib/bundle/dsl.rb
|
|
|
|
|
# * lib/bundle/{brew,cask,tap}_installer.rb
|
|
|
|
|
# * spec/bundle/{brew,cask,tap}_installer_spec.rb
|
|
|
|
|
|
2022-08-24 20:07:19 +00:00
|
|
|
|
onActivationOptions = { config, ... }: {
|
|
|
|
|
options = {
|
|
|
|
|
cleanup = mkOption {
|
|
|
|
|
type = types.enum [ "none" "uninstall" "zap" ];
|
|
|
|
|
default = "none";
|
|
|
|
|
example = "uninstall";
|
|
|
|
|
description = ''
|
|
|
|
|
This option manages what happens to formulae installed by Homebrew, that aren't present in
|
|
|
|
|
the Brewfile generated by this module, during <command>nix-darwin</command> activation.
|
|
|
|
|
|
|
|
|
|
When set to <literal>"none"</literal> (the default), formulae not present in the generated
|
|
|
|
|
Brewfile are left installed.
|
|
|
|
|
|
|
|
|
|
When set to <literal>"uninstall"</literal>, <command>nix-darwin</command> invokes
|
|
|
|
|
<command>brew bundle [install]</command> with the <command>--cleanup</command> flag. This
|
|
|
|
|
uninstalls all formulae not listed in generate Brewfile, i.e.,
|
|
|
|
|
<command>brew uninstall</command> is run for those formulae.
|
|
|
|
|
|
|
|
|
|
When set to <literal>"zap"</literal>, <command>nix-darwin</command> invokes
|
|
|
|
|
<command>brew bundle [install]</command> with the <command>--cleanup --zap</command>
|
|
|
|
|
flags. This uninstalls all formulae not listed in the generated Brewfile, and if the
|
|
|
|
|
formula is a cask, removes all files associated with that cask. In other words,
|
|
|
|
|
<command>brew uninstall --zap</command> is run for all those formulae.
|
|
|
|
|
|
|
|
|
|
If you plan on exclusively using <command>nix-darwin</command> to manage formulae
|
|
|
|
|
installed by Homebrew, you probably want to set this option to
|
|
|
|
|
<literal>"uninstall"</literal> or <literal>"zap"</literal>.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
autoUpdate = mkOption {
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = false;
|
|
|
|
|
description = ''
|
|
|
|
|
Whether to enable Homebrew to auto-update itself and all formulae during
|
|
|
|
|
<command>nix-darwin</command> activation. The default is <literal>false</literal> so that
|
|
|
|
|
repeated invocations of <command>darwin-rebuild switch</command> are idempotent.
|
|
|
|
|
|
|
|
|
|
Note that Homebrew auto-updates when it's been more then 5 minutes since it last updated.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
upgrade = mkOption {
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = false;
|
|
|
|
|
description = ''
|
|
|
|
|
Whether to enable Homebrew to upgrade outdated formulae and Mac App Store apps during
|
|
|
|
|
<command>nix-darwin</command> activation. The default is <literal>false</literal> so
|
|
|
|
|
that repeated invocations of <command>darwin-rebuild switch</command> are idempotent.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
brewBundleCmd = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
visible = false;
|
|
|
|
|
internal = true;
|
|
|
|
|
readOnly = true;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config = {
|
|
|
|
|
brewBundleCmd = concatStringsSep " " (
|
|
|
|
|
optional (!config.autoUpdate) "HOMEBREW_NO_AUTO_UPDATE=1"
|
|
|
|
|
++ [ "brew bundle --file='${brewfileFile}' --no-lock" ]
|
|
|
|
|
++ optional (!config.upgrade) "--no-upgrade"
|
|
|
|
|
++ optional (config.cleanup == "uninstall") "--cleanup"
|
|
|
|
|
++ optional (config.cleanup == "zap") "--cleanup --zap"
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 01:10:46 +00:00
|
|
|
|
tapOptions = { config, ... }: {
|
|
|
|
|
options = {
|
|
|
|
|
name = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
example = "homebrew/cask-fonts";
|
|
|
|
|
description = ''
|
|
|
|
|
When <option>clone_target</option> is unspecified, this is the name of a formula
|
2022-08-23 20:32:07 +00:00
|
|
|
|
repository to tap from GitHub using HTTPS. For example, <literal>"user/repo"</literal>
|
|
|
|
|
will tap https://github.com/user/homebrew-repo.
|
2022-08-23 01:10:46 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
clone_target = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
|
|
|
|
Use this option to tap a formula repository from anywhere, using any transport protocol
|
|
|
|
|
that <command>git</command> handles. When <option>clone_target</option> is specified, taps
|
|
|
|
|
can be cloned from places other than GitHub and using protocols other than HTTPS, e.g.,
|
|
|
|
|
SSH, git, HTTP, FTP(S), rsync.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
force_auto_update = mkNullOrBoolOption {
|
|
|
|
|
description = ''
|
|
|
|
|
Whether to auto-update the tap even if it is not hosted on GitHub. By default, only taps
|
|
|
|
|
hosted on GitHub are auto-updated (for performance reasons).
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
brewfileLine = mkBrewfileLineOption;
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
config =
|
|
|
|
|
let
|
|
|
|
|
sCfg = mkProcessedSubmodConfig config;
|
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
brewfileLine =
|
|
|
|
|
"tap ${sCfg.name}"
|
|
|
|
|
+ optionalString (sCfg ? clone_target) ", ${sCfg.clone_target}"
|
|
|
|
|
+ optionalString (sCfg ? force_auto_update)
|
|
|
|
|
", force_auto_update: ${sCfg.force_auto_update}";
|
|
|
|
|
};
|
2022-08-23 01:10:46 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-08-22 21:49:22 +00:00
|
|
|
|
# Sourced from https://docs.brew.sh/Manpage#global-cask-options
|
|
|
|
|
# and valid values for `HOMEBREW_CASK_OPTS`.
|
|
|
|
|
caskArgsOptions = { config, ... }: {
|
|
|
|
|
options = {
|
|
|
|
|
appdir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Applications.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>/Applications</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
colorpickerdir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Color Pickers.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/ColorPickers</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
prefpanedir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Preference Panes.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/PreferencePanes</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
qlplugindir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for QuickLook Plugins.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/QuickLook</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
mdimporterdir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Spotlight Plugins.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Spotlight</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
dictionarydir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Dictionaries.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Dictionaries</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
fontdir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Fonts.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Fonts</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
servicedir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Services.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Services</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
input_methoddir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Input Methods.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Input Methods</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
internet_plugindir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Internet Plugins.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Internet Plug-Ins</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
audio_unit_plugindir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Audio Unit Plugins.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Audio/Plug-Ins/Components</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
vst_plugindir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for VST Plugins.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Audio/Plug-Ins/VST</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
vst3_plugindir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for VST3 Plugins.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Audio/Plug-Ins/VST3</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
screen_saverdir = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Target location for Screen Savers.
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <filename class='directory'>~/Library/Screen Savers</filename>.
|
2022-08-22 21:49:22 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
language = mkNullOrStrOption {
|
|
|
|
|
description = ''
|
|
|
|
|
Comma-separated list of language codes to prefer for cask installation. The first matching
|
|
|
|
|
language is used, otherwise it reverts to the cask’s default language. The default value
|
|
|
|
|
is the language of your system.
|
|
|
|
|
'';
|
|
|
|
|
example = "zh-TW";
|
|
|
|
|
};
|
|
|
|
|
require_sha = mkNullOrBoolOption {
|
|
|
|
|
description = "Whether to require cask(s) to have a checksum.";
|
|
|
|
|
};
|
|
|
|
|
no_quarantine = mkNullOrBoolOption {
|
|
|
|
|
description = "Whether to disable quarantining of downloads.";
|
|
|
|
|
};
|
|
|
|
|
no_binaries = mkNullOrBoolOption {
|
|
|
|
|
description = "Whether to disable linking of helper executables.";
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 01:10:46 +00:00
|
|
|
|
brewfileLine = mkBrewfileLineOption;
|
2022-08-22 21:49:22 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config =
|
|
|
|
|
let
|
2022-08-23 20:32:07 +00:00
|
|
|
|
sCfg = mkProcessedSubmodConfig config;
|
2022-08-22 21:49:22 +00:00
|
|
|
|
in
|
|
|
|
|
{
|
2022-08-23 20:32:07 +00:00
|
|
|
|
brewfileLine = if sCfg == { } then null else "cask_args ${mkBrewfileLineOptionsListString sCfg}";
|
2022-08-22 21:49:22 +00:00
|
|
|
|
};
|
|
|
|
|
};
|
2022-08-23 02:35:01 +00:00
|
|
|
|
|
|
|
|
|
brewOptions = { config, ... }: {
|
|
|
|
|
options = {
|
|
|
|
|
name = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
description = "The name of the formula to install.";
|
|
|
|
|
};
|
|
|
|
|
args = mkOption {
|
|
|
|
|
type = with types; nullOr (listOf str);
|
|
|
|
|
default = null;
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Arguments flags to pass to <command>brew install</command>. Values should not include the
|
|
|
|
|
leading <literal>"--"</literal>.
|
2022-08-23 02:35:01 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
conflicts_with = mkOption {
|
|
|
|
|
type = with types; nullOr (listOf str);
|
|
|
|
|
default = null;
|
|
|
|
|
description = ''
|
|
|
|
|
List of formulae that should be unlinked and their services stopped (if they are
|
|
|
|
|
installed).
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
restart_service = mkOption {
|
|
|
|
|
type = with types; nullOr (either bool (enum [ "changed" ]));
|
|
|
|
|
default = null;
|
|
|
|
|
description = ''
|
|
|
|
|
Whether to run <command>brew services restart</command> for the formula and register it to
|
2022-08-23 20:32:07 +00:00
|
|
|
|
launch at login (or boot). If set to <literal>"changed"</literal>, the service will only
|
|
|
|
|
be restarted on version changes.
|
2022-08-23 02:35:01 +00:00
|
|
|
|
|
|
|
|
|
Homebrew's default is <literal>false</literal>.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
start_service = mkNullOrBoolOption {
|
|
|
|
|
description = ''
|
|
|
|
|
Whether to run <command>brew services start</command> for the formula and register it to
|
|
|
|
|
launch at login (or boot).
|
|
|
|
|
|
|
|
|
|
Homebrew's default is <literal>false</literal>.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
link = mkNullOrBoolOption {
|
|
|
|
|
description = ''
|
|
|
|
|
Whether to link the formula to the Homebrew prefix. When this option is
|
|
|
|
|
<literal>null</literal>, Homebrew will use it's default behavior which is to link the
|
2022-08-23 20:32:07 +00:00
|
|
|
|
formula if it's currently unlinked and not keg-only, and to unlink the formula if it's
|
2022-08-23 02:35:01 +00:00
|
|
|
|
currently linked and keg-only.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
brewfileLine = mkBrewfileLineOption;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config =
|
|
|
|
|
let
|
2022-08-23 20:32:07 +00:00
|
|
|
|
sCfg = mkProcessedSubmodConfig config;
|
|
|
|
|
sCfgSubset = removeAttrs sCfg [ "name" "restart_service" ];
|
2022-08-23 02:35:01 +00:00
|
|
|
|
in
|
|
|
|
|
{
|
2022-08-23 20:32:07 +00:00
|
|
|
|
brewfileLine =
|
|
|
|
|
"brew ${sCfg.name}"
|
|
|
|
|
+ optionalString (sCfgSubset != { }) ", ${mkBrewfileLineOptionsListString sCfgSubset}"
|
|
|
|
|
# We need to handle the `restart_service` option seperately since it can be either bool
|
|
|
|
|
# or the string value "changed".
|
|
|
|
|
+ optionalString (sCfg ? restart_service) (
|
|
|
|
|
", restart_service: " + (
|
|
|
|
|
if isBool config.restart_service then sCfg.restart_service
|
|
|
|
|
else ":${config.restart_service}"
|
|
|
|
|
)
|
2022-08-23 02:35:01 +00:00
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
};
|
2022-08-23 03:04:09 +00:00
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
caskOptions = { config, ... }: {
|
2022-08-23 03:04:09 +00:00
|
|
|
|
options = {
|
|
|
|
|
name = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
description = "The name of the cask to install.";
|
|
|
|
|
};
|
|
|
|
|
args = mkOption {
|
|
|
|
|
type = types.nullOr (types.submodule caskArgsOptions);
|
|
|
|
|
default = null;
|
|
|
|
|
};
|
|
|
|
|
greedy = mkNullOrBoolOption {
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Whether to always upgrade auto-updated or unversioned cask to the latest version even if
|
|
|
|
|
it's already installed.
|
2022-08-23 03:04:09 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
brewfileLine = mkBrewfileLineOption;
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
config =
|
|
|
|
|
let
|
|
|
|
|
sCfg = mkProcessedSubmodConfig config;
|
|
|
|
|
sCfgSubset = removeAttrs sCfg [ "name" ];
|
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
brewfileLine =
|
|
|
|
|
"cask ${sCfg.name}"
|
|
|
|
|
+ optionalString (sCfgSubset != { }) ", ${mkBrewfileLineOptionsListString sCfgSubset}";
|
|
|
|
|
};
|
2022-08-23 03:04:09 +00:00
|
|
|
|
};
|
2020-12-08 02:14:48 +00:00
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
{
|
2022-08-23 20:32:07 +00:00
|
|
|
|
# Interface --------------------------------------------------------------------------------------
|
|
|
|
|
|
2022-08-24 20:07:19 +00:00
|
|
|
|
imports = [
|
|
|
|
|
(mkRenamedOptionModule [ "homebrew" "autoUpdate" ] [ "homebrew" "onActivation" "autoUpdate" ])
|
|
|
|
|
(mkRenamedOptionModule [ "homebrew" "cleanup" ] [ "homebrew" "onActivation" "cleanup" ])
|
|
|
|
|
];
|
|
|
|
|
|
2020-12-17 21:03:57 +00:00
|
|
|
|
options.homebrew = {
|
2020-12-08 02:14:48 +00:00
|
|
|
|
enable = mkEnableOption ''
|
2022-08-24 20:07:19 +00:00
|
|
|
|
configuring your Brewfile, and installing/updating the formulae therein via
|
2020-12-08 02:14:48 +00:00
|
|
|
|
the <command>brew bundle</command> command, using <command>nix-darwin</command>.
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Note that enabling this option does not install Homebrew. See the Homebrew
|
|
|
|
|
<link xlink:href="https://brew.sh">website</link> for installation instructions
|
2020-12-08 02:14:48 +00:00
|
|
|
|
'';
|
|
|
|
|
|
2021-03-06 12:12:19 +00:00
|
|
|
|
brewPrefix = mkOption {
|
|
|
|
|
type = types.str;
|
2022-01-18 00:07:09 +00:00
|
|
|
|
default = if pkgs.stdenv.hostPlatform.isAarch64 then "/opt/homebrew/bin" else "/usr/local/bin";
|
2022-08-23 20:32:07 +00:00
|
|
|
|
defaultText = literalExpression ''
|
|
|
|
|
if pkgs.stdenv.hostPlatform.isAarch64 then "/opt/homebrew/bin"
|
|
|
|
|
else "/usr/local/bin"
|
|
|
|
|
'';
|
2021-03-06 12:12:19 +00:00
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
The path prefix where the <command>brew</command> executable is located. This will be set to
|
|
|
|
|
the correct value based on your system's platform, and should only need to be changed if you
|
|
|
|
|
manually installed Homebrew in a non-standard location.
|
2021-03-06 12:12:19 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-24 20:07:19 +00:00
|
|
|
|
onActivation = mkOption {
|
|
|
|
|
type = types.submodule onActivationOptions;
|
|
|
|
|
default = { };
|
2020-12-08 02:14:48 +00:00
|
|
|
|
description = ''
|
2022-08-24 20:07:19 +00:00
|
|
|
|
Options for configuring the behavior of the <command>brew bundle</command> command that
|
|
|
|
|
<command>nix-darwin</command> runs during system activation.
|
2020-12-08 02:14:48 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2020-12-31 00:42:31 +00:00
|
|
|
|
global.brewfile = mkOption {
|
2021-01-16 20:39:01 +00:00
|
|
|
|
type = types.bool;
|
|
|
|
|
default = false;
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Whether to enable Homebrew to automatically use the Brewfile in the Nix store that this
|
|
|
|
|
module generates, when you manually invoke <command>brew bundle</command>.
|
2021-01-16 20:39:01 +00:00
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Implementation note: when enabled, this option sets the
|
|
|
|
|
<literal>HOMEBREW_BUNDLE_FILE</literal> environment variable to the path of the Brewfile in
|
|
|
|
|
the Nix store that this module generates, by adding it to
|
2021-01-16 23:15:29 +00:00
|
|
|
|
<option>environment.variables</option>.
|
2021-01-16 20:39:01 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
global.noLock = mkOption {
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = false;
|
|
|
|
|
description = ''
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Whether to disable lockfile generation when you manually invoke
|
2021-01-16 23:15:29 +00:00
|
|
|
|
<command>brew bundle [install]</command>. This is often desirable when
|
|
|
|
|
<option>homebrew.global.brewfile</option> is enabled, since
|
|
|
|
|
<command>brew bundle [install]</command> will try to write the lockfile in the Nix store,
|
|
|
|
|
and complain that it can't (though the command will run successfully regardless).
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
Implementation note: when enabled, this option sets the
|
|
|
|
|
<literal>HOMEBREW_BUNDLE_NO_LOCK</literal> environment variable, by adding it to
|
2021-01-16 23:15:29 +00:00
|
|
|
|
<option>environment.variables</option>.
|
2021-01-16 20:39:01 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
2020-12-31 00:42:31 +00:00
|
|
|
|
|
2020-12-08 02:14:48 +00:00
|
|
|
|
taps = mkOption {
|
2022-08-23 01:10:46 +00:00
|
|
|
|
type = with types; listOf (coercedTo str (name: { inherit name; }) (submodule tapOptions));
|
2022-08-23 20:32:07 +00:00
|
|
|
|
default = [ ];
|
2022-08-23 01:10:46 +00:00
|
|
|
|
example = literalExpression ''
|
|
|
|
|
# Adapted examples from https://github.com/Homebrew/homebrew-bundle#usage
|
|
|
|
|
[
|
2022-08-23 20:32:07 +00:00
|
|
|
|
# `brew tap`
|
2022-08-23 01:10:46 +00:00
|
|
|
|
"homebrew/cask"
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
|
|
|
|
# `brew tap` with custom Git URL and arguments
|
2022-08-23 01:10:46 +00:00
|
|
|
|
{
|
|
|
|
|
name = "user/tap-repo";
|
|
|
|
|
clone_target = "https://user@bitbucket.org/user/homebrew-tap-repo.git";
|
|
|
|
|
force_auto_update = true;
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
'';
|
|
|
|
|
description = ''
|
|
|
|
|
Homebrew formula repositories to tap.
|
|
|
|
|
|
|
|
|
|
Taps defined as strings, e.g., <literal>"user/repo"</literal>, are a shorthand for:
|
|
|
|
|
|
|
|
|
|
<code>{ name = "user/repo"; }</code>
|
|
|
|
|
'';
|
2020-12-08 02:14:48 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
caskArgs = mkOption {
|
|
|
|
|
type = types.submodule caskArgsOptions;
|
|
|
|
|
default = { };
|
|
|
|
|
example = literalExpression ''
|
|
|
|
|
{
|
|
|
|
|
appdir = "~/Applications";
|
|
|
|
|
require_sha = true;
|
|
|
|
|
}
|
|
|
|
|
'';
|
|
|
|
|
description = "Arguments to apply to all <option>homebrew.casks</option>.";
|
|
|
|
|
};
|
|
|
|
|
|
2020-12-08 02:14:48 +00:00
|
|
|
|
brews = mkOption {
|
2022-08-23 02:35:01 +00:00
|
|
|
|
type = with types; listOf (coercedTo str (name: { inherit name; }) (submodule brewOptions));
|
2022-08-23 20:32:07 +00:00
|
|
|
|
default = [ ];
|
2022-08-23 02:35:01 +00:00
|
|
|
|
example = literalExpression ''
|
|
|
|
|
# Adapted examples from https://github.com/Homebrew/homebrew-bundle#usage
|
|
|
|
|
[
|
2022-08-23 20:32:07 +00:00
|
|
|
|
# `brew install`
|
2022-08-23 02:35:01 +00:00
|
|
|
|
"imagemagick"
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
|
|
|
|
# `brew install --with-rmtp`, `brew services restart` on version changes
|
2022-08-23 02:35:01 +00:00
|
|
|
|
{
|
|
|
|
|
name = "denji/nginx/nginx-full";
|
|
|
|
|
args = [ "with-rmtp" ];
|
|
|
|
|
restart_service = "changed";
|
|
|
|
|
}
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
|
|
|
|
# `brew install`, always `brew services restart`, `brew link`, `brew unlink mysql` (if it is installed)
|
2022-08-23 02:35:01 +00:00
|
|
|
|
{
|
|
|
|
|
name = "mysql@5.6";
|
|
|
|
|
restart_service = true;
|
|
|
|
|
link = true;
|
|
|
|
|
conflicts_with = [ "mysql" ];
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
'';
|
|
|
|
|
description = ''
|
|
|
|
|
Homebrew brews to install.
|
|
|
|
|
|
|
|
|
|
Brews defined as strings, e.g., <literal>"imagemagick"</literal>, are a shorthand for:
|
|
|
|
|
|
|
|
|
|
<code>{ name = "imagemagick"; }</code>
|
|
|
|
|
'';
|
2020-12-08 02:14:48 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
casks = mkOption {
|
2022-08-23 03:04:09 +00:00
|
|
|
|
type = with types; listOf (coercedTo str (name: { inherit name; }) (submodule caskOptions));
|
2022-08-23 20:32:07 +00:00
|
|
|
|
default = [ ];
|
2022-08-23 03:04:09 +00:00
|
|
|
|
example = literalExpression ''
|
|
|
|
|
# Adapted examples from https://github.com/Homebrew/homebrew-bundle#usage
|
|
|
|
|
[
|
2022-08-23 20:32:07 +00:00
|
|
|
|
# `brew install --cask`
|
2022-08-23 03:04:09 +00:00
|
|
|
|
"google-chrome"
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
|
|
|
|
# `brew install --cask --appdir=~/my-apps/Applications`
|
2022-08-23 03:04:09 +00:00
|
|
|
|
{
|
|
|
|
|
name = "firefox";
|
|
|
|
|
args = { appdir = "~/my-apps/Applications"; };
|
|
|
|
|
}
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
2022-08-23 03:04:09 +00:00
|
|
|
|
# always upgrade auto-updated or unversioned cask to latest version even if already installed
|
|
|
|
|
{
|
|
|
|
|
name = "opera";
|
|
|
|
|
greedy = true;
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
'';
|
|
|
|
|
description = ''
|
|
|
|
|
Homebrew casks to install.
|
|
|
|
|
|
|
|
|
|
Casks defined as strings, e.g., <literal>"google-chrome"</literal>, are a shorthand for:
|
|
|
|
|
|
|
|
|
|
<code>{ name = "google-chrome"; }</code>
|
|
|
|
|
'';
|
2020-12-08 02:14:48 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
masApps = mkOption {
|
2022-08-23 20:32:07 +00:00
|
|
|
|
type = types.attrsOf types.ints.positive;
|
|
|
|
|
default = { };
|
|
|
|
|
example = literalExpression ''
|
|
|
|
|
{
|
|
|
|
|
"1Password for Safari" = 1569813296;
|
|
|
|
|
Xcode = 497799835;
|
|
|
|
|
}
|
|
|
|
|
'';
|
2020-12-08 02:14:48 +00:00
|
|
|
|
description = ''
|
|
|
|
|
Applications to install from Mac App Store using <command>mas</command>.
|
|
|
|
|
|
2020-12-08 20:22:27 +00:00
|
|
|
|
When this option is used, <literal>"mas"</literal> is automatically added to
|
2020-12-17 21:03:57 +00:00
|
|
|
|
<option>homebrew.brews</option>.
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
|
|
|
|
Note that you need to be signed into the Mac App Store for <command>mas</command> to
|
|
|
|
|
successfully install and upgrade applications, and that unfortunately apps removed from this
|
|
|
|
|
option will not be uninstalled automatically even if
|
2022-08-24 20:07:19 +00:00
|
|
|
|
<option>homebrew.onActivation.cleanup</option> is set to <literal>"uninstall"</literal>
|
2020-12-08 02:14:48 +00:00
|
|
|
|
or <literal>"zap"</literal> (this is currently a limitation of Homebrew Bundle).
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
For more information on <command>mas</command> see:
|
|
|
|
|
<link xlink:href="https://github.com/mas-cli/mas">github.com/mas-cli/mas</link>.
|
2020-12-08 02:14:48 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
whalebrews = mkOption {
|
|
|
|
|
type = with types; listOf str;
|
2022-08-23 20:32:07 +00:00
|
|
|
|
default = [ ];
|
2020-12-08 02:14:48 +00:00
|
|
|
|
example = [ "whalebrew/wget" ];
|
|
|
|
|
description = ''
|
|
|
|
|
Docker images to install using <command>whalebrew</command>.
|
|
|
|
|
|
2020-12-08 20:22:27 +00:00
|
|
|
|
When this option is used, <literal>"whalebrew"</literal> is automatically added to
|
2020-12-17 21:03:57 +00:00
|
|
|
|
<option>homebrew.brews</option>.
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
|
|
|
|
For more information on <command>whalebrew</command> see:
|
2022-08-23 20:32:07 +00:00
|
|
|
|
<link xlink:href="https://github.com/whalebrew/whalebrew">github.com/whalebrew/whalebrew</link>.
|
2020-12-08 02:14:48 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extraConfig = mkOption {
|
|
|
|
|
type = types.lines;
|
|
|
|
|
default = "";
|
|
|
|
|
example = ''
|
2020-12-08 19:42:15 +00:00
|
|
|
|
# 'brew cask install' only if '/usr/libexec/java_home --failfast' fails
|
|
|
|
|
cask "java" unless system "/usr/libexec/java_home --failfast"
|
2020-12-08 02:14:48 +00:00
|
|
|
|
'';
|
2022-08-23 03:04:09 +00:00
|
|
|
|
description = "Extra lines to be added verbatim to bottom of the generated Brewfile.";
|
2020-12-08 02:14:48 +00:00
|
|
|
|
};
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
|
|
|
|
brewfile = mkOption {
|
|
|
|
|
type = types.str;
|
|
|
|
|
visible = false;
|
|
|
|
|
internal = true;
|
|
|
|
|
readOnly = true;
|
|
|
|
|
description = "String reprensentation of the generated Brewfile useful for debugging.";
|
|
|
|
|
};
|
2020-12-08 02:14:48 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-08-23 20:32:07 +00:00
|
|
|
|
|
|
|
|
|
# Implementation ---------------------------------------------------------------------------------
|
|
|
|
|
|
2020-12-08 02:14:48 +00:00
|
|
|
|
config = {
|
2022-08-24 20:07:19 +00:00
|
|
|
|
|
|
|
|
|
warnings = [
|
|
|
|
|
(mkIf (options.homebrew.autoUpdate.isDefined || options.homebrew.cleanup.isDefined) "The `homebrew' module no longer upgrades outdated formulae and apps by default during `nix-darwin' activation. To enable upgrading, set `homebrew.onActivation.upgrade = true'.")
|
|
|
|
|
];
|
|
|
|
|
|
2020-12-17 21:03:57 +00:00
|
|
|
|
homebrew.brews =
|
2022-08-23 20:32:07 +00:00
|
|
|
|
optional (cfg.masApps != { }) "mas"
|
|
|
|
|
++ optional (cfg.whalebrews != [ ]) "whalebrew";
|
|
|
|
|
|
|
|
|
|
homebrew.brewfile =
|
|
|
|
|
"# Created by `nix-darwin`'s `homebrew` module\n\n"
|
|
|
|
|
+ mkBrewfileSectionString "Taps" cfg.taps
|
|
|
|
|
+ mkBrewfileSectionString "Arguments for all casks"
|
|
|
|
|
(optional (cfg.caskArgs.brewfileLine != null) cfg.caskArgs)
|
|
|
|
|
+ mkBrewfileSectionString "Brews" cfg.brews
|
|
|
|
|
+ mkBrewfileSectionString "Casks" cfg.casks
|
|
|
|
|
+ mkBrewfileSectionString "Mac App Store apps"
|
|
|
|
|
(mapAttrsToList (n: id: ''mas "${n}", id: ${toString id}'') cfg.masApps)
|
|
|
|
|
+ mkBrewfileSectionString "Docker containers" (map (v: ''whalebrew "${v}"'') cfg.whalebrews)
|
|
|
|
|
+ optionalString (cfg.extraConfig != "") ("# Extra config\n" + cfg.extraConfig);
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
2020-12-31 00:42:31 +00:00
|
|
|
|
environment.variables = mkIf cfg.enable (
|
2022-08-23 20:32:07 +00:00
|
|
|
|
optionalAttrs cfg.global.brewfile { HOMEBREW_BUNDLE_FILE = "${brewfileFile}"; }
|
|
|
|
|
// optionalAttrs cfg.global.noLock { HOMEBREW_BUNDLE_NO_LOCK = "1"; }
|
|
|
|
|
);
|
2020-12-08 02:14:48 +00:00
|
|
|
|
|
2020-12-17 21:03:57 +00:00
|
|
|
|
system.activationScripts.homebrew.text = mkIf cfg.enable ''
|
2020-12-08 02:14:48 +00:00
|
|
|
|
# Homebrew Bundle
|
|
|
|
|
echo >&2 "Homebrew bundle..."
|
2021-03-06 12:12:19 +00:00
|
|
|
|
if [ -f "${cfg.brewPrefix}/brew" ]; then
|
2022-08-24 20:07:19 +00:00
|
|
|
|
PATH="${cfg.brewPrefix}":$PATH ${cfg.onActivation.brewBundleCmd}
|
2020-12-18 00:54:29 +00:00
|
|
|
|
else
|
|
|
|
|
echo -e "\e[1;31merror: Homebrew is not installed, skipping...\e[0m" >&2
|
|
|
|
|
fi
|
2020-12-08 02:14:48 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
}
|