Linuxbrew / brew

:beer::penguin: The Homebrew package manager for Linux
https://linuxbrew.sh
BSD 2-Clause "Simplified" License
2.66k stars 237 forks source link

Simplify setting PATH, MANPATH, and INFOPATH #812

Closed jamescostian closed 6 years ago

jamescostian commented 6 years ago

Feature

During the installation, at the end ask users if they'd like to update their PATH, MANPATH, and INFOPATH now that Linuxbrew is installed. If they accept, modify their .bash_profile or .profile, and also modify their .zshenvc. While they may not be using zsh, if they ever do decide to use zsh (e.g. maybe they're planning on running brew install zsh right after the installation of brew finishes), it would be nice for brew to not break and require manual intervention.

Motivation

Homebrew on macOS Just Works™ after you run the one-liner involving curl. IMO, #612 should require that Linuxbrew can be used the same way as Homebrew (just run a one-liner). That way eventually, people can all go to brew.sh and there can be a single sh -c "$(curl ... || wget ...)" that will work on Linux distros and macOS.

Relevancy

99% of Homebrew users install Homebrew because it makes things easy[1]. Thus, making it easier to set up PATH, MANPATH, and INFOPATH is a good thing and very relevant to Homebrew users.

Current Situation

The install guide has 3 blocks of code in it. While the second block says "Follow the Next steps instructions ..." I'd argue that many people (especially those of us willing to sh -c "$(curl ...) will skip over those words and just try to copy each code block and paste it into a terminal emulator.

After running the sh -c "$(curl ... a user will see commands they can run to alter PATH but also MANPATH and INFOPATH. But the second code block on the website doesn't mention changing MANPATH or INFOPATH. In addition, what the user sees isn't necessarily correct (e.g. .profile isn't loaded by zsh).

Alternatives

Maybe change the second code block in the directions for installation. Have it say something like brew setenv, which could do all of the things I'm suggesting to be done at install time.

But seriously, brew should be installable the same way on Linux distros as it is on macOS, and it should be a simple one-liner.

Footnotes

[1]: 86% of statistics are made up. But hey, the main reason people install Homebrew is because they want to use brew install and not have to worry about how to install a particular package. That sounds like they want simplicity to me.

sjackman commented 6 years ago

I like the idea of a brew setenv command. Executed as brew setenv it could modify the users config files. That won't however fix the PATH in the user's current active shell. It could be used like this to modify the PATH of their current shell.

eval "$(brew setenv)"

If we changed the current installation instructions from…

sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

to…

eval "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

we could fix the user's current PATH when they install Linuxbrew.

The brew setenv script should be idempotent. If it's run twice, the second invocation has no effect.

Should the install script ask interactively if the user wishes to run brew setenv?

The name of the command should I think reflect that it's effect is permanent and writes files to disk. Perhaps brew configure-shell or brew write-environment?

sjackman commented 6 years ago

As an implementation detail, I think it'd be helpful to have a shell script at $HOMBREW_PREFIX/etc/environment that modifies PATH. Then ~/.profile and friends of different shells can simply source that one file.

jamescostian commented 6 years ago

I agree with all of these ideas. I'm assuming $HOMBREW_PREFIX/etc/environment would also modify MANPATH and INFOPATH, right?

Having a command (btw, good ideas for the command name!) that can be run post-install as well as during the install (interactively) sounds great.

Having a single shell script that modifies PATH, MANPATH, and INFOPATH sounds perfect. And it makes idempotency simple (as long as you also check that the line that sources that file isn't commented out!)

sjackman commented 6 years ago

I'm assuming $HOMBREW_PREFIX/etc/environment would also modify MANPATH and INFOPATH, right?

Yes.

sjackman commented 6 years ago

I'd suggest writing to ~/.profile the following:

PATH="$HOME/.linuxbrew/bin:$PATH" # Added by brew configure-shell

then running brew configure-shell a second time can exit early if it detects this exact line somewhere in the file.

jamescostian commented 6 years ago

Sorry, I'm a little bit confused now. I thought the plan was to simply write to profile

source $HOMBREW_PREFIX/etc/environment

Instead of modifying environment variables directly in each file? Of course, the above line assumes that $HOMEBREW_PREFIX is substituted with it's actual value.

sjackman commented 6 years ago

Yes, sorry. I got confused. I did in fact mean…

source ~/.linuxbrew/etc/environment # Added by brew configure-shell

then running brew configure-shell a second time can exit early if it detects this exact line somewhere in the file.

maxim-belkin commented 6 years ago

Having a single file that would set everything related to Homebrew sounds like a good idea. All the HOMEBREW_VERBOSE, HOMEBREW_DEVELOPER, etc settings could be set in that file. I'm just not sure about the name... I'd suggest something more "actionable", like brew configure or brew setup. And this command would interactively ask the user if they would like to set "standard" settings (and list a few as an example), or do the "detailed" setup and choose them interactively (and give corresponding explanations along the way).

maxim-belkin commented 6 years ago

@jamescostian have you started working on this already? 🙄

jamescostian commented 6 years ago

@maxim-belkin my only concern about brew configure and brew setup is that they are less descriptive than brew configure-shell and brew write-environment

Also, no I have not started working on this. I noticed that @sjackman assigned this to himself so I assumed that he would be working on it. If he becomes unavailable, I'd be willing to volunteer my time for this.

sjackman commented 6 years ago

Ah, by assigning it to myself, I just meant that I'll be discussing the issue (and of course any other maintainers that'd like to comment). You're welcome to take a go at the implementation if you like, James. I'd prefer to keep it simple for now, the "standard" configuration that Maxim describes above. I like brew configure-shell for the name.

jamescostian commented 6 years ago

Sorry @sjackman I misunderstood. I started implementing it in #829 and I'd appreciate it if you or someone else could give me feedback on that implementation. I have a lot of questions, and it's my first time writing Ruby so I'm sure there are parts of the code that could be improved.

jamescostian commented 6 years ago

I just realized I totally misread the first comment by @maxim-belkin and thought it was only asking for the detailed interface and didn't really understand the standard one - whoops! I'll fix that tomorrow.

maxim-belkin commented 6 years ago

The problem with names like configure-shell or configure-environment is that that "script" will not be configuring shell. It will be configuring the behavior of brew (command) in whatever-shell-is-being-used-by-the-user. Configuring shell is like messing around with .inputrc, setting shell-specific env. vars (PAGER, IFS), enabling some features with set -o ... Not to mention brew irb and brew sh, both of which are "shells". With a simpler name (like setup or configure) it's clear that you're trying to do something with the way Homebrew/Linuxbrew is operating - you're configuring them, not "some shell".

sjackman commented 6 years ago

The intention here is to modify the user's shell configuration file ~/.profile (and similar files) by writing a file $HOMEBREW_PREFIX/etc/environment that is ultimately sourced by the user's shell startup script.

jamescostian commented 6 years ago

I'm now realizing that this is getting a bit larger than it should be. The original reason behind this issue was to maintain compatibility with Homebrew for macOS.

Homebrew for macOS does not have an etc/environment file that is sourced and that allows users to set environment variables like HOMEBREW_DEVELOPER, so adding that functionality here would only increase the divide between macOS and Linux, and make #612 harder to merge

Max mentioned having brew read this config, and now I'm realizing that may be a better way to solve problems like setting HOMEBREW_DEVELOPER by default for some users. One could add a YAML or JSON file to macOS and Linux brew that file could contain user-editable "default" values for all of those configuration settings (e.g. a user can make it so that by "default" HOMEBREW_DEVELOPER is turned on for their machine, and all they would have to do is edit a config file that brew would load when it starts up).

That way it's easier to return to making this command do what it was intended to do: make Linuxbrew and macOS Homebrew work the same to users. In other words, have this command be only about writing PATH, MANPATH, and INFOPATH to an environment file that other files source.

Thoughts?

jonchang commented 6 years ago

I’d say it’s an issue for anyone who has installed somewhere other than /usr/local. I haven’t done a nonstandard install on macOS but I imagine that this script would be used in that situation too.

maxim-belkin commented 6 years ago

Max mentioned having brew read this config, and now I'm realizing that may be a better way to solve problems like setting HOMEBREW_DEVELOPER by default for some users. One could add a YAML or JSON file to macOS and Linux brew that file could contain user-editable "default" values for all of those configuration settings (e.g. a user can make it so that by "default" HOMEBREW_DEVELOPER is turned on for their machine, and all they would have to do is edit a config file that brew would load when it starts up).

Indeed, such a file might be a better solution for HOMEBREW_ variables that control the behavior of brew. So, your PR #829 should focus on env-related changes that are outside the scope of Homebrew/Linuxbrew - PATH, MANPATH, etc. In the end, Homebrew/Linuxbrew will simply add a line to .profile (and its analogues) sourcing this file.

Looking a bit further: formulae that suggest making changes to env. could modify this file.

jamescostian commented 6 years ago

@jonchang I haven't done a nonstandard install on macOS either, but the docs strongly suggest against it:

we recommend installing to /usr/local. Pick another prefix at your peril!

That makes me think that this change can safely be made in Linuxbrew, and later be merged into macOS Homebrew in #612 at some point (i.e., this isn't urgent nor is it a big enough change that it would cause a huge delay in the merge).

Would you agree?

sjackman commented 6 years ago

Yes, this script would be useful in non-/usr/local installs of Homebrew. At work I don't have sudo access, and I have Homebrew installed in ~/.homebrew. We can merge the functionality into Linuxbrew first though.