Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuring Homebrew with .env files #15787

Merged
merged 1 commit into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions Library/Homebrew/dev-cmd/livecheck.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
module Homebrew
module_function

WATCHLIST_PATH = File.expand_path(Homebrew::EnvConfig.livecheck_watchlist).freeze

sig { returns(CLI::Parser) }
def livecheck_args
Homebrew::CLI::Parser.new do
Expand All @@ -19,7 +17,7 @@

If no formula or cask argument is passed, the list of formulae and
casks to check is taken from `HOMEBREW_LIVECHECK_WATCHLIST` or
`~/.brew_livecheck_watchlist`.
`~/.homebrew/livecheck_watchlist.txt`.
EOS
switch "--full-name",
description: "Print formulae and casks with fully-qualified names."
Expand Down Expand Up @@ -50,6 +48,22 @@
end
end

def watchlist_path
@watchlist_path ||= begin
watchlist = File.expand_path(Homebrew::EnvConfig.livecheck_watchlist)

Check warning on line 53 in Library/Homebrew/dev-cmd/livecheck.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/livecheck.rb#L52-L53

Added lines #L52 - L53 were not covered by tests

unless File.exist?(watchlist)
previous_default_watchlist = File.expand_path("~/.brew_livecheck_watchlist")
if File.exist?(previous_default_watchlist)
odeprecated "~/.brew_livecheck_watchlist", "~/.homebrew/livecheck_watchlist.txt"
watchlist = previous_default_watchlist

Check warning on line 59 in Library/Homebrew/dev-cmd/livecheck.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/livecheck.rb#L59

Added line #L59 was not covered by tests
end
end

watchlist

Check warning on line 63 in Library/Homebrew/dev-cmd/livecheck.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/livecheck.rb#L63

Added line #L63 was not covered by tests
end
end

def livecheck
args = livecheck_args.parse

Expand Down Expand Up @@ -82,9 +96,9 @@
else
args.named.to_formulae_and_casks
end
elsif File.exist?(WATCHLIST_PATH)
elsif File.exist?(watchlist_path)
begin
names = Pathname.new(WATCHLIST_PATH).read.lines
names = Pathname.new(watchlist_path).read.lines
.reject { |line| line.start_with?("#") || line.blank? }
.map(&:strip)

Expand Down
10 changes: 8 additions & 2 deletions Library/Homebrew/env_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ module EnvConfig
HOMEBREW_LIVECHECK_WATCHLIST: {
description: "Consult this file for the list of formulae to check by default when no formula argument " \
"is passed to `brew livecheck`.",
default_text: "`$HOME/.brew_livecheck_watchlist`",
default: "~/.brew_livecheck_watchlist",
default_text: "`$XDG_CONFIG_HOME/homebrew/livecheck_watchlist.txt` if `$XDG_CONFIG_HOME` is set " \
"or `$HOME/.homebrew/livecheck_watchlist.txt` otherwise.",
default: "#{ENV.fetch("HOMEBREW_USER_CONFIG_HOME")}/livecheck_watchlist.txt",
},
HOMEBREW_LOGS: {
description: "Use this directory to store log files.",
Expand Down Expand Up @@ -362,6 +363,11 @@ module EnvConfig
description: "Use this as the `svn`(1) binary.",
default_text: "A Homebrew-built Subversion (if installed), or the system-provided binary.",
},
HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY: {
description: "If set in Homebrew's system-wide environment file (`/etc/homebrew/brew.env`), " \
"the system-wide environment file will be loaded last to override any prefix or user settings.",
boolean: true,
},
HOMEBREW_TEMP: {
description: "Use this path as the temporary directory for building packages. Changing " \
"this may be needed if your system temporary directory and Homebrew prefix are on " \
Expand Down
14 changes: 14 additions & 0 deletions Library/Homebrew/manpages/brew.1.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ Note that environment variables must have a value set to be detected. For
example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just
`export HOMEBREW_NO_INSECURE_REDIRECT`.

`HOMEBREW_*` environment variables can also be set in Homebrew's environment
files:

* `/etc/homebrew/brew.env` (system-wide)

* `$HOMEBREW_PREFIX/etc/homebrew/brew.env` (prefix-specific)

* `$XDG_CONFIG_HOME/homebrew/brew.env` if `$XDG_CONFIG_HOME` is set or
`$HOME/.homebrew/brew.env` otherwise (user-specific)

User-specific environment files take precedence over prefix-specific files and
prefix-specific files take precedence over system-wide files (unless
`HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` is set, see below).

<%= environment_variables %>

## USING HOMEBREW BEHIND A PROXY
Expand Down
50 changes: 50 additions & 0 deletions bin/brew
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,61 @@ then
then
HOMEBREW_PREFIX="/usr/local"
fi
unset USR_LOCAL_BREW_FILE_DIRECTORY USR_LOCAL_HOMEBREW_REPOSITORY
fi

unset BREW_FILE_DIRECTORY

# If the location of HOMEBREW_LIBRARY changes
# keg_relocate.rb, formula_cellar_checks.rb, and test/global_spec.rb need to change.
HOMEBREW_LIBRARY="${HOMEBREW_REPOSITORY}/Library"

# Load Homebrew's variable configuration files from disk.
# First, load the system-wide configuration.
if [[ -f "/etc/homebrew/brew.env" ]]
then
unset SYSTEM_ENV_TAKES_PRIORITY
# only load HOMEBREW_*=* lines
SYSTEM_HOMEBREW_ENV="$(grep -E '^HOMEBREW_[A-Z_]+=.*$' "/etc/homebrew/brew.env")"
if [[ -n "${HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY-}" ]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to check for whether this is set in /etc/homebrew/brew.env.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlocab to avoid it being set by the environment or something else? Allowing it to be set from environment makes testing a bunch easier.

Copy link
Member

@carlocab carlocab Jul 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More to allow the administrator of /etc/homebrew/brew.env to decide whether the system env takes priority or not. Otherwise users can just do unset HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY. We can take the value from the environment too if it's not set in the system env.

But I'm not bothered if you'd rather someone who needed it implemented this.

then
SYSTEM_ENV_TAKES_PRIORITY="1"
else
eval "${SYSTEM_HOMEBREW_ENV}"
fi
fi

# Next, load the prefix configuration
if [[ -f "${HOMEBREW_PREFIX}/etc/homebrew/brew.env" ]]
then
# only load HOMEBREW_*=* lines
PREFIX_HOMEBREW_ENV="$(grep -E '^HOMEBREW_[A-Z_]+=.*$' "${HOMEBREW_PREFIX}/etc/homebrew/brew.env")"
eval "${PREFIX_HOMEBREW_ENV}"
unset PREFIX_HOMEBREW_ENV
fi

# Finally, load the user configuration
if [[ -n "${XDG_CONFIG_HOME-}" ]]
then
HOMEBREW_USER_CONFIG_HOME="${XDG_CONFIG_HOME}/homebrew"
Comment on lines +105 to +107
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if [[ -n "${XDG_CONFIG_HOME-}" ]]
then
HOMEBREW_USER_CONFIG_HOME="${XDG_CONFIG_HOME}/homebrew"
if [[ -n "${HOMEBREW_XDG_CONFIG_HOME-}" ]]
then
HOMEBREW_USER_CONFIG_HOME="${HOMEBREW_XDG_CONFIG_HOME}/homebrew"

and XDG_CONFIG_HOME needs to be added to USED_BY_HOMEBREW_VARS in bin/brew.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlocab Can you explain that? I don't think either should be needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Env filtering:

❯ XDG_CONFIG_HOME=foo brew ruby -e 'puts ENV["XDG_CONFIG_HOME"].present?'
false

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlocab We don't rely on XDG_CONFIG_HOME being set anywhere after env filtering is applied (unless I missed something), no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, I thought this was in brew.sh. 😅 That said, don't we want to have the same behaviour for the livecheck watchlist? i.e. check $XDG_CONFIG_HOME/homebrew/livecheck_watchlist.txt if XDG_CONFIG_HOME is set?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlocab that behaviour is already present. We don't pass through XDG_CONFIG_HOME because we don't want/need to. It's documented that we use it if set but that's only needed/used in brew.sh which in turn sets HOMEBREW_USER_CONFIG_HOME accordingly and that is used afterwards.

For an example:

$ export XDG_CONFIG_HOME=fish[~/OSS/Homebrew]
$ brew irb
==> Interactive Homebrew Shell
...
brew(main):001:0> ENV["HOMEBREW_USER_CONFIG_HOME"]
=> "fish/homebrew"

else
HOMEBREW_USER_CONFIG_HOME="${HOME}/.homebrew"
fi
if [[ -f "${HOMEBREW_USER_CONFIG_HOME}/brew.env" ]]
then
# only load HOMEBREW_*=* lines
USER_HOMEBREW_ENV="$(grep -E '^HOMEBREW_[A-Z_]+=.*$' "${HOMEBREW_USER_CONFIG_HOME}/brew.env")"
eval "${USER_HOMEBREW_ENV}"
unset USER_HOMEBREW_ENV
fi

# If the system configuration takes priority, load it last.
if [[ -n "${SYSTEM_ENV_TAKES_PRIORITY-}" ]]
then
eval "${SYSTEM_HOMEBREW_ENV}"
fi
unset SYSTEM_HOMEBREW_ENV

# Copy and export all HOMEBREW_* variables previously mentioned in
# manpage or used elsewhere by Homebrew.

Expand Down Expand Up @@ -121,6 +170,7 @@ export HOMEBREW_BREW_FILE
export HOMEBREW_PREFIX
export HOMEBREW_REPOSITORY
export HOMEBREW_LIBRARY
export HOMEBREW_USER_CONFIG_HOME

# set from user environment
# shellcheck disable=SC2154
Expand Down
21 changes: 19 additions & 2 deletions docs/Manpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ Check for newer versions of formulae and/or casks from upstream.

If no formula or cask argument is passed, the list of formulae and
casks to check is taken from `HOMEBREW_LIVECHECK_WATCHLIST` or
`~/.brew_livecheck_watchlist`.
`~/.homebrew/livecheck_watchlist.txt`.

* `--full-name`:
Print formulae and casks with fully-qualified names.
Expand Down Expand Up @@ -2059,6 +2059,20 @@ Note that environment variables must have a value set to be detected. For
example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just
`export HOMEBREW_NO_INSECURE_REDIRECT`.

`HOMEBREW_*` environment variables can also be set in Homebrew's environment
files:

* `/etc/homebrew/brew.env` (system-wide)

* `$HOMEBREW_PREFIX/etc/homebrew/brew.env` (prefix-specific)

* `$XDG_CONFIG_HOME/homebrew/brew.env` if `$XDG_CONFIG_HOME` is set or
`$HOME/.homebrew/brew.env` otherwise (user-specific)

User-specific environment files take precedence over prefix-specific files and
prefix-specific files take precedence over system-wide files (unless
`HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY` is set, see below).

- `HOMEBREW_API_DOMAIN`
<br>Use this URL as the download mirror for Homebrew JSON API. If metadata files at that URL are temporarily unavailable, the default API domain will be used as a fallback mirror.

Expand Down Expand Up @@ -2243,7 +2257,7 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just
- `HOMEBREW_LIVECHECK_WATCHLIST`
<br>Consult this file for the list of formulae to check by default when no formula argument is passed to `brew livecheck`.

*Default:* `$HOME/.brew_livecheck_watchlist`
*Default:* `$XDG_CONFIG_HOME/homebrew/livecheck_watchlist.txt` if `$XDG_CONFIG_HOME` is set or `$HOME/.homebrew/livecheck_watchlist.txt` otherwise.

- `HOMEBREW_LOGS`
<br>Use this directory to store log files.
Expand Down Expand Up @@ -2328,6 +2342,9 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just

*Default:* A Homebrew-built Subversion (if installed), or the system-provided binary.

- `HOMEBREW_SYSTEM_ENV_TAKES_PRIORITY`
<br>If set in Homebrew's system-wide environment file (`/etc/homebrew/brew.env`), the system-wide environment file will be loaded last to override any prefix or user settings.

- `HOMEBREW_TEMP`
<br>Use this path as the temporary directory for building packages. Changing this may be needed if your system temporary directory and Homebrew prefix are on different volumes, as macOS has trouble moving symlinks across volumes when the target does not yet exist. This issue typically occurs when using FileVault or custom SSD configurations.

Expand Down
27 changes: 25 additions & 2 deletions manpages/brew.1
Original file line number Diff line number Diff line change
Expand Up @@ -1900,7 +1900,7 @@ Print the cached linkage values stored in \fBHOMEBREW_CACHE\fR, set by a previou
Check for newer versions of formulae and/or casks from upstream\.
.
.P
If no formula or cask argument is passed, the list of formulae and casks to check is taken from \fBHOMEBREW_LIVECHECK_WATCHLIST\fR or \fB~/\.brew_livecheck_watchlist\fR\.
If no formula or cask argument is passed, the list of formulae and casks to check is taken from \fBHOMEBREW_LIVECHECK_WATCHLIST\fR or \fB~/\.homebrew/livecheck_watchlist\.txt\fR\.
.
.TP
\fB\-\-full\-name\fR
Expand Down Expand Up @@ -2935,6 +2935,23 @@ Many Homebrew Cask commands accept one or more \fIcask\fR arguments\. These can
.SH "ENVIRONMENT"
Note that environment variables must have a value set to be detected\. For example, run \fBexport HOMEBREW_NO_INSECURE_REDIRECT=1\fR rather than just \fBexport HOMEBREW_NO_INSECURE_REDIRECT\fR\.
.
.P
\fBHOMEBREW_*\fR environment variables can also be set in Homebrew\'s environment files:
.
.IP "\(bu" 4
\fB/etc/homebrew/brew\.env\fR (system\-wide)
.
.IP "\(bu" 4
\fB$HOMEBREW_PREFIX/etc/homebrew/brew\.env\fR (prefix\-specific)
.
.IP "\(bu" 4
\fB$XDG_CONFIG_HOME/homebrew/brew\.env\fR if \fB$XDG_CONFIG_HOME\fR is set or \fB$HOME/\.homebrew/brew\.env\fR otherwise (user\-specific)
.
.IP "" 0
.
.P
User\-specific environment files take precedence over prefix\-specific files and prefix\-specific files take precedence over system\-wide files (unless \fBHOMEBREW_SYSTEM_ENV_TAKES_PRIORITY\fR is set, see below)\.
.
.TP
\fBHOMEBREW_API_DOMAIN\fR
.
Expand Down Expand Up @@ -3281,7 +3298,7 @@ Print this text before the installation summary of each successful build\.
Consult this file for the list of formulae to check by default when no formula argument is passed to \fBbrew livecheck\fR\.
.
.IP
\fIDefault:\fR \fB$HOME/\.brew_livecheck_watchlist\fR
\fIDefault:\fR \fB$XDG_CONFIG_HOME/homebrew/livecheck_watchlist\.txt\fR if \fB$XDG_CONFIG_HOME\fR is set or \fB$HOME/\.homebrew/livecheck_watchlist\.txt\fR otherwise\.
.
.TP
\fBHOMEBREW_LOGS\fR
Expand Down Expand Up @@ -3443,6 +3460,12 @@ Use this as the \fBsvn\fR(1) binary\.
\fIDefault:\fR A Homebrew\-built Subversion (if installed), or the system\-provided binary\.
.
.TP
\fBHOMEBREW_SYSTEM_ENV_TAKES_PRIORITY\fR
.
.br
If set in Homebrew\'s system\-wide environment file (\fB/etc/homebrew/brew\.env\fR), the system\-wide environment file will be loaded last to override any prefix or user settings\.
.
.TP
\fBHOMEBREW_TEMP\fR
.
.br
Expand Down
Loading