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

Q: Do we want shims to automatically execute older binaries after finding them? #249

Open
stevegt opened this issue Oct 3, 2022 · 3 comments

Comments

@stevegt
Copy link
Contributor

stevegt commented Oct 3, 2022

I hope this question hasn't come up before: The closest I can find is the discussion in #30.

Right now, goenv follows the pyenv precedent of saying this:

https://github.com/syndbg/goenv/blob/ece1aba5651a73c891d2beb75d37ea35d1c5fb2a/libexec/goenv-which#L94

That behavior -- not running executables associated with older versions -- makes sense for an interpreted language in which libraries need to match executables at runtime. But one of the whole points of migrating from e.g. Python to Go is to get away from that constraint. By carrying forward that behavior from pyenv we are causing ourselves more work than we need to. Each time we use goenv to upgrade to a new Go version, we either manually update PATH to include older versions of GO binaries, or we run go install for everything we already had installed.

We should be able to simply let the shims run the old binaries instead.

In my own case, I finally wrote a little bash script that walks through all of the older go/*/bin directories in semver order and creates symlinks in a go/basket/bin, which I then put in PATH. That works great except when I want to use goenv to set my local or shell Go version to an earlier version of binaries, in which case I manually edit PATH anyway to remove go/bin/basket. But that means I lose not only the newer binaries but the older binaries as well -- it's not a great solution.

Which of the following options makes more sense?

  1. Instead of displaying the above message, run the most recent semver of the binary that is less than or equal to the currently set version of Go.
  2. Do (1), but only if GOENV_RUNOLD is set. (I'm open to a better env var name.)
  3. Keep things the way they are.

I'm leaning toward submitting a PR for (2) -- any strong opinions, and is there anything I'm missing?

@ChronosMasterOfAllTime
Copy link
Collaborator

ChronosMasterOfAllTime commented Nov 3, 2022

Unsure I understand the ask here.

Are you saying you want to stay on an older patch version of a particular release?

For example, if go 1.15.2 was used, dont use 1.15.15?

@stevegt
Copy link
Contributor Author

stevegt commented Dec 5, 2022

@ChronosMasterOfAllTime When we execute goenv local, goenv global, or goenv shell, that changes the version of Go compiler that will be used to compile binaries in the future. That's all goenv should change, but right now it also changes PATH access to binaries that have already been compiled -- it inherited this behavior from pyenv for reasons that are not valid for compiled binaries.

  • When a binary has already been compiled and placed in ~/go/*/bin, it ordinarily doesn't need to be compiled again, even when we later use goenv to switch to a newer compiler. That's the entire point of compiled languages -- an already compiled binary does not need an installed compiler, and doesn't care about the version of any compiler that is in the PATH.
  • But goenv inherited an assumption from pyenv that says we do care about the version of interpreter that is in the PATH. In the case of pyenv this is important, because older python executables will not necessarily work with newer versions of the python interpreter, might need libraries that are only installed alongside older interpreters, etc. In the case of goenv this is an invalid assumption, because Go executables do not use or need an interpreter.
  • Due to that invalid assumption, every time we use goenv to switch to a new compiler version, we lose access to all of the binaries we already compiled and placed in ~/go/*/bin. When that happens, a goenv user has approximately three choices:
    • Recompile all of the binaries they ever compiled so they get placed in the new ~/go/*/bin directory so the shims will execute them.
    • Manually edit PATH to regain access to the older binaries.
    • Write a symlink hack like the one I describe above.

Do we want to modify the shim code such that, instead of acting like pyenv and displaying the message listing all of the versions of Go a binary was compiled with, we instead simply execute the most recent version of the binary?

This new behavior might be enabled by a feature flag -- I'm suggesting GOENV_RUNOLD above, but am open to other env variable names.

@huyz
Copy link

huyz commented Feb 4, 2023

In the case of pyenv, there are two solutions for retaining access to packages/executables for an older version of pyenv-managed Python:

  1. https://github.com/pyenv/pyenv-pip-migrate
  2. pyenv global 3.11.1 3.10.9 3.9.15. This is how you specify the fallbacks.

Perhaps some of these schemes are relevant to goenv.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants