• Dom Sekotill's avatar
    fix(virtualenvwrapper): several changes for checking git directory, including fixes (#5663) · 94ea7b45
    Dom Sekotill authored
    * Test only for the presence of a .git directory in virtualenvwrapper
    
    Instead of using both $(git rev-parse --show-toplevel) and a check for
    a .git directory, use just the latter. As well as being redundant
    the former does not work quite so well when using multiple worktrees;
    each worktree will be treated as a separate project.
    
    * Unset ENV_NAME & deactivate if no virtualenv found
    
    This addresses #4603 without breaking current behaviour (where current
    behaviour is correct).
    
    When changing directories, if there is no environment matching
    ENV_NAME, ENV_NAME is emptied and deactivate called if there is a
    current environment active (based on CD_VIRTUAL_ENV).
    
    * Use path comparison not string comparison for paths
    
    This will solve part of issue #4255 where WORKON_HOME is defined with a
    trailing slash or not normalised in some way, as well as instances
    where symlinks are used, and any other instances where constructed
    paths don't exactly match even though they go to the same file.
    Co-authored-by: 's avatarRobby Russell <robby@planetargon.com>
    94ea7b45
virtualenvwrapper.plugin.zsh 3.22 KB
function {
    # search in these locations for the init script:
    for virtualenvwrapper in $commands[virtualenvwrapper_lazy.sh] \
      $commands[virtualenvwrapper.sh] \
      /usr/share/virtualenvwrapper/virtualenvwrapper{_lazy,}.sh \
      /usr/local/bin/virtualenvwrapper{_lazy,}.sh \
      /etc/bash_completion.d/virtualenvwrapper \
      /usr/share/bash-completion/completions/virtualenvwrapper \
      $HOME/.local/bin/virtualenvwrapper.sh
    do
        if [[ -f "$virtualenvwrapper" ]]; then
            source "$virtualenvwrapper"
            return
        fi
    done
    print "[oh-my-zsh] virtualenvwrapper plugin: Cannot find virtualenvwrapper.sh.\n"\
          "Please install with \`pip install virtualenvwrapper\`" >&2
    return 1
}

if [[ $? -eq 0 ]] && ! type workon &>/dev/null; then
  print "[oh-my-zsh] virtualenvwrapper plugin: shell function 'workon' not defined.\n"\
        "Please check ${virtualenvwrapper}" >&2
  return
fi

if [[ -z "$WORKON_HOME" ]]; then
  WORKON_HOME="$HOME/.virtualenvs"
fi

if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
  # Automatically activate Git projects or other customized virtualenvwrapper projects based on the
  # directory name of the project. Virtual environment name can be overridden
  # by placing a .venv file in the project root with a virtualenv name in it.
  function workon_cwd {
    if [[ -z "$WORKON_CWD" ]]; then
      local WORKON_CWD=1
      # Get absolute path, resolving symlinks
      local PROJECT_ROOT="${PWD:A}"
      while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" \
          && ! -d "$PROJECT_ROOT/.git" ]]; do
        PROJECT_ROOT="${PROJECT_ROOT:h}"
      done

      # Check for virtualenv name override
      if [[ -f "$PROJECT_ROOT/.venv" ]]; then
        ENV_NAME="$(cat "$PROJECT_ROOT/.venv")"
      elif [[ -f "$PROJECT_ROOT/.venv/bin/activate" ]];then
        ENV_NAME="$PROJECT_ROOT/.venv"
      elif [[ "$PROJECT_ROOT" != "/" ]]; then
        ENV_NAME="${PROJECT_ROOT:t}"
      else
        ENV_NAME=""
      fi
      
      if [[ -n $CD_VIRTUAL_ENV && "$ENV_NAME" != "$CD_VIRTUAL_ENV" ]]; then
        # We've just left the repo, deactivate the environment
        # Note: this only happens if the virtualenv was activated automatically
        deactivate && unset CD_VIRTUAL_ENV
      fi
      if [[ "$ENV_NAME" != "" ]]; then
        # Activate the environment only if it is not already active
        if [[ ! "$VIRTUAL_ENV" -ef "$WORKON_HOME/$ENV_NAME" ]]; then
          if [[ -e "$WORKON_HOME/$ENV_NAME/bin/activate" ]]; then
            workon "$ENV_NAME" && export CD_VIRTUAL_ENV="$ENV_NAME"
          elif [[ -e "$ENV_NAME/bin/activate" ]]; then
            source $ENV_NAME/bin/activate && export CD_VIRTUAL_ENV="$ENV_NAME"
          else
            ENV_NAME=""
          fi
        fi
      fi
      if [[ "$ENV_NAME" == "" && -n $CD_VIRTUAL_ENV && -n $VIRTUAL_ENV ]]; then
        # We've just left the repo, deactivate the environment
        # Note: this only happens if the virtualenv was activated automatically
        deactivate && unset CD_VIRTUAL_ENV
      fi
    fi
  }

  # Append workon_cwd to the chpwd_functions array, so it will be called on cd
  # http://zsh.sourceforge.net/Doc/Release/Functions.html
  autoload -U add-zsh-hook
  add-zsh-hook chpwd workon_cwd
fi