fish-shell / fish-shell

The user-friendly command line shell.
https://fishshell.com
Other
26.05k stars 1.91k forks source link

fish_user_paths entries creep into existing shells #2162

Closed languitar closed 9 years ago

languitar commented 9 years ago
fish, version 2.2b1-29-g18d7465

I am using the fish_user_paths variable to extend my PATH environment variable. Starting new fish sessions in parallel to an existing sessions results in the situation that the entries in fish_user_paths are prepended to the PATH of the existing shell again (and deduplicated). This a complete show beaker currently, e.g when using python virtualenvs.

E.g. I have a shell where I activated a virtaulenv. PATH looks as follows:

/homes/jwienke/workspace/git/rsbperfmon-doc/_env/bin /homes/jwienke/.local/bin /usr/local/sbin /homes/jwienke/local/bin /usr/local/bin /homes/jwienke/.gem/ruby/1.9.1/bin /homes/jwienke/local/trusty/x86_64/bin /homes/jwienke/local/trusty/x86_64/bin /homes/jwienke/local/trusty/x86_64/sbin /usr/bin /bin /usr/local/games /usr/games /opt/thinlinc/bin /homes/jwienke/.rvm/bin

After opening a completely unrelated fish sessions, the PATH in the existing shell changes to:

/homes/jwienke/.local/bin /usr/local/sbin /homes/jwienke/local/bin /usr/local/bin /homes/jwienke/.gem/ruby/1.9.1/bin /homes/jwienke/workspace/git/rsbperfmon-doc/_env/bin /homes/jwienke/local/trusty/x86_64/bin /homes/jwienke/local/trusty/x86_64/bin /homes/jwienke/local/trusty/x86_64/sbin /usr/bin /bin /usr/local/games /usr/games /opt/thinlinc/bin /homes/jwienke/.rvm/bin

My fish_user_paths entries are:

/homes/jwienke/.local/bin /usr/local/sbin /homes/jwienke/local/bin /usr/local/bin /homes/jwienke/.gem/ruby/1.9.1/bin
zanchey commented 9 years ago

fish_user_paths is generally made to be a universal variable, but it shouldn't be re-set on every new invocation of the shell. Are you setting fish_user_paths in your config.fish?

languitar commented 9 years ago

Yes. It's set there.

ridiculousfish commented 9 years ago

@languitar I'm confused by "Starting new fish sessions in parallel to an existing sessions results in the situation that the entries in fish_user_paths are prepended to the PATH of the existing shell again". This makes it sound like the new shell somehow inherits the PATH from the existing shell? Is that what you are seeing?

If so, perhaps PATH itself is a universal variable? (That would be crazy!) Does set -U | grep PATH show a value?

The fish_user_paths algorithm is simple: its values are prepended to PATH, with the de-duplication you saw.

languitar commented 9 years ago

@ridiculousfish No, the other way around, an already running sessions changes its environment variable PATH when a new one is started.

No, PATH is not a universal variable.

zanchey commented 9 years ago

@languitar I would say that setting a universal variable in config.fish on every execution mostly defeats the purpose of universal variables. It is getting a lot of people into trouble with appending (see #2005, #2058).

I think what happens is

The workaround is either to use a global variable in config.fish for fish_user_paths and accept that you will not have changes synchronised between running shells, or set -U fish_user_paths once and remove it from your config.fish.

languitar commented 9 years ago

Ok, so is it valid to have fish_user_paths as a non-universal variable? I found this somewhere in the documentation once as the preferred way to set the PATH.

languitar commented 9 years ago

Actually, how do I get rid of fish_users_paths being a universal variable? set -e fish_user_paths doesn't help.

languitar commented 9 years ago

Ok, my own fault. Had another config file manipulating the variable

zanchey commented 9 years ago

You certainly can have fish_user_paths as a global variable, and it will override the universal variable if you want to have different paths in different instances (although in that case futzing with PATH directly is probably saner). If you're happy with this as a solution shall we close this issue? I think the warning with set -U in config.fish as mentioned in other open issues is the long term fix.

languitar commented 9 years ago

This seems to work now with the global variable. However, what is the preferred way to set PATH? The documentation on this was very fuzzy the last time I looked for this. What is the idea of fish_user_paths at all compared to directly changing PATH?

ridiculousfish commented 9 years ago

Here is what the docs say about $PATH:

$PATH is an environment variable containing the directories in which fish searches for commands. Instead of separating entries with a colon, $PATH is a list. You can modify $PATH in a few ways:

  1. By modifying the $fish_user_paths variable, which is automatically appended to $PATH. For example, to permanently add /usr/local/bin to your $PATH, you could write:

    set -U fish_user_paths $fish_user_paths /usr/local/bin

  2. Directly in config.fish (see below).

Reading this, it sure looks easy to interpret it as "run this command in config.fish", which is the exact opposite of what one ought to do. I need to fix that.

ridiculousfish commented 9 years ago

I updated the wording, and fixed the anchor too (d'oh).

languitar commented 9 years ago

Ok, documentation is now clearer. But if I do not want to use a universal variable, because I want to be able to restore my working environment completely from config files, is there any difference between messing with PATH directly or using fish_user_paths as a global variable?

ridiculousfish commented 9 years ago

In that case you should set PATH directly. fish_user_paths is just a convenience and is not directly used by fish. The implementation might shed some light: There's a function __fish_reconstruct_path that watches for changes to fish_user_paths and updates PATH accordingly. I hope that's clear.

languitar commented 9 years ago

Ok. good to know.