pyenv-virtualenv icon indicating copy to clipboard operation
pyenv-virtualenv copied to clipboard

weird cyclic symlink on macos

Open avoidik opened this issue 1 year ago • 3 comments

Too many issues will kill our team's development velocity, drastically. Make sure you have checked all steps below.

Prerequisite

  • [x] Make sure your problem is not listed in the common build problems.
  • [x] Make sure no duplicated issue has already been reported in the pyenv-virtualenv issues. You should look in closed issues, too.
  • [x] Make sure you are not asking us to help solving your specific issue.
    • GitHub issues is opened mainly for development purposes. If you want to ask someone to help solving your problem, go to some community site like Gitter, StackOverflow, etc.
  • [x] Make sure your problem is not derived from packaging (e.g. Homebrew).
    • Please refer to the package documentation for the installation issues, etc.
  • [x] Make sure your problem is not derived from other plugins.
    • This repository is maintaining the pyenv-virtualenv plugin only. Please refrain from reporting issues of other plugins here.

Description

  • [x] Platform information (e.g. Ubuntu Linux 20.04): apple mac m1 pro
  • [x] OS architecture (e.g. amd64): aarch64/arm64
  • [x] pyenv version: 2.4.7
  • [x] pyenv-virtualenv version: 1.2.3
  • [x] Python version: v3.10.14
  • [x] virtualenv version (if installed): 20.26.3
  • [x] Please attach the debug log of a faulty Pyenv invocation as a gist
    • If the problem happens in a Pyenv invocation, you can turn on debug logging by setting PYENV_DEBUG=1, e.g. env PYENV_DEBUG=1 pyenv install -v 3.6.4
    • If the problem happens outside of a Pyenv invocation, get the debug log like this:
      # for Bash
      export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
      # for Zsh
      export PS4='+(%x:%I): %N(%i): '
      
      set -x
      <reproduce the problem>
      set +x
      

Problem description

This line here creates a weird cyclic symlink inside of a virtualenv directory.

For example, this line attempts to create the following symlink:

$ ln -fs /Users/user.name/.pyenv/versions/3.10.14/envs/venvname /Users/user.name/.pyenv/versions/venvname

However the target and the source directory is the same directory:

$ ls -la /Users/user.name/.pyenv/versions/venvname
lrwxr-xr-x  1 user.name  staff  59 Jul  9 17:37 /Users/user.name/.pyenv/versions/venvname -> /Users/user.name/.pyenv/versions/3.10.14/envs/venvname

As a result

$ ls -la /Users/user.name/.pyenv/versions/3.10.14/envs/venvname/
total 8
drwxr-xr-x   7 user.name  staff  224 Jul  9 18:21 .
drwxr-xr-x   4 user.name  staff  128 Jul  9 17:37 ..
drwxr-xr-x  16 user.name  staff  512 Jul  9 17:37 bin
lrwxr-xr-x   1 user.name  staff   59 Jul  9 18:21 venvname -> /Users/user.name/.pyenv/versions/3.10.14/envs/venvname
drwxr-xr-x   2 user.name  staff   64 Jul  9 17:37 include
drwxr-xr-x   3 user.name  staff   96 Jul  9 17:37 lib
-rw-r--r--   1 user.name  staff  117 Jul  9 18:21 pyvenv.cfg

If I'd prepend this line with echo, like this

echo ln -fs "${VIRTUALENV_PATH}" "${COMPAT_VIRTUALENV_PATH}"

There is no weird cyclic symlink getting created.

Is this something expected or a bug?

avoidik avatar Jul 09 '24 17:07 avoidik

Please provide a debug log showcasing the problem (i.e. the link's creation) as per the issue template.

That line is supposed to create a link $PYENV_ROOT/versions/<env_name> -> $PYENV_ROOT/versions/<python_version>/envs/<env_name>.

native-api avatar Jul 09 '24 20:07 native-api

sure, here is the relevant part (line no. 17)

+(/opt/homebrew/Cellar/pyenv/2.4.7/libexec/pyenv-exec:48): exec /Users/user.name/.pyenv/versions/3.10.14/bin/python3.10 -m venv /Users/user.name/.pyenv/versions/3.10.14/envs/venvname
+(/opt/homebrew/bin/pyenv-virtualenv:610): shopt -s nullglob
+(/opt/homebrew/bin/pyenv-virtualenv:611): for extra_binary in "$PREFIX"/bin/python*-config
++(/opt/homebrew/bin/pyenv-virtualenv:612): basename /Users/user.name/.pyenv/versions/3.10.14/bin/python-config
+(/opt/homebrew/bin/pyenv-virtualenv:612): extra_binary_linkname=/Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/python-config
+(/opt/homebrew/bin/pyenv-virtualenv:613): [[ -e /Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/python-config ]]
+(/opt/homebrew/bin/pyenv-virtualenv:611): for extra_binary in "$PREFIX"/bin/python*-config
++(/opt/homebrew/bin/pyenv-virtualenv:612): basename /Users/user.name/.pyenv/versions/3.10.14/bin/python3-config
+(/opt/homebrew/bin/pyenv-virtualenv:612): extra_binary_linkname=/Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/python3-config
+(/opt/homebrew/bin/pyenv-virtualenv:613): [[ -e /Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/python3-config ]]
+(/opt/homebrew/bin/pyenv-virtualenv:611): for extra_binary in "$PREFIX"/bin/python*-config
++(/opt/homebrew/bin/pyenv-virtualenv:612): basename /Users/user.name/.pyenv/versions/3.10.14/bin/python3.10-config
+(/opt/homebrew/bin/pyenv-virtualenv:612): extra_binary_linkname=/Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/python3.10-config
+(/opt/homebrew/bin/pyenv-virtualenv:613): [[ -e /Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/python3.10-config ]]
+(/opt/homebrew/bin/pyenv-virtualenv:619): '[' -d /Users/user.name/.pyenv/versions/3.10.14/envs/venvname ']'
+(/opt/homebrew/bin/pyenv-virtualenv:619): '[' -n /Users/user.name/.pyenv/versions/venvname ']'
+(/opt/homebrew/bin/pyenv-virtualenv:620): ln -fs /Users/user.name/.pyenv/versions/3.10.14/envs/venvname /Users/user.name/.pyenv/versions/venvname
+(/opt/homebrew/bin/pyenv-virtualenv:623): '[' '!' -e /Users/user.name/.pyenv/versions/3.10.14/envs/venvname/bin/pydoc ']'
+(/opt/homebrew/bin/pyenv-virtualenv:634): '[' -z 1 ']'
+(/opt/homebrew/bin/pyenv-virtualenv:646): '[' 0 == 0 ']'
+(/opt/homebrew/bin/pyenv-virtualenv:647): pyenv-rehash
+(/opt/homebrew/Cellar/pyenv/2.4.7/libexec/pyenv-rehash:7): SHIM_PATH=/Users/user.name/.pyenv/shims

just fyi, ln works a little bit different on macos, it creates not only a symlink at the target, but also at the source, for example:

$ ln -fs /Users/user.name/.pyenv/versions/3.10.14/envs/venvname /Users/user.name/.pyenv/versions/venvname
$ ls -la /Users/user.name/.pyenv/versions/venvname
lrwxr-xr-x@ 1 user.name  staff  59 Jul 11 10:10 /Users/user.name/.pyenv/versions/venvname -> /Users/user.name/.pyenv/versions/3.10.14/envs/venvname
$ ls -la /Users/user.name/.pyenv/versions/venvname/venvname
lrwxr-xr-x@ 1 user.name  staff  59 Jul 11 10:14 /Users/user.name/.pyenv/versions/venvname/venvname -> /Users/user.name/.pyenv/versions/3.10.14/envs/venvname

versus

$ ln -fsn /Users/user.name/.pyenv/versions/3.10.14/envs/venvname /Users/user.name/.pyenv/versions/venvname
$ ls -la /Users/user.name/.pyenv/versions/venvname
lrwxr-xr-x@ 1 user.name  staff  59 Jul 11 10:17 /Users/user.name/.pyenv/versions/venvname -> /Users/user.name/.pyenv/versions/3.10.14/envs/venvname
$ ls -la /Users/user.name/.pyenv/versions/venvname/venvname
ls: /Users/user.name/.pyenv/versions/venvname/venvname: No such file or directory

avoidik avatar Jul 11 '24 09:07 avoidik

to sum up, I have to use ln -fsn instead of ln -fs to overcome that

avoidik avatar Sep 13 '24 13:09 avoidik

So, the erroneous behavior happens because the symlink /Users/user.name/.pyenv/versions/venvname already exists. But it shouldn't -- because you've just created the environment!

Are you trying to create an environment with the same name as one that already exists?

native-api avatar Dec 08 '24 18:12 native-api

Okay, I see that this can happen legitimately, if you're overwriting the environment with -f.

native-api avatar Dec 08 '24 19:12 native-api

Already reported and patch suggested here: #453 Finally fixed, thank you.

Vanav avatar Dec 09 '24 09:12 Vanav