fix(virtualenvwrapper): several changes for checking git directory, including fixes (#5663)

* 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: Robby Russell <robby@planetargon.com>
This commit is contained in:
Dom Sekotill 2021-06-12 04:52:22 +01:00 committed by GitHub
parent 0869a57cb5
commit 94ea7b4516
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -35,27 +35,19 @@ if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
function workon_cwd { function workon_cwd {
if [[ -z "$WORKON_CWD" ]]; then if [[ -z "$WORKON_CWD" ]]; then
local WORKON_CWD=1 local WORKON_CWD=1
# Check if this is a Git repo
local GIT_REPO_ROOT=""
local GIT_TOPLEVEL="$(git rev-parse --show-toplevel 2> /dev/null)"
if [[ $? == 0 ]]; then
GIT_REPO_ROOT="$GIT_TOPLEVEL"
fi
# Get absolute path, resolving symlinks # Get absolute path, resolving symlinks
local PROJECT_ROOT="${PWD:A}" local PROJECT_ROOT="${PWD:A}"
while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" \ while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" \
&& ! -d "$PROJECT_ROOT/.git" && "$PROJECT_ROOT" != "$GIT_REPO_ROOT" ]]; do && ! -d "$PROJECT_ROOT/.git" ]]; do
PROJECT_ROOT="${PROJECT_ROOT:h}" PROJECT_ROOT="${PROJECT_ROOT:h}"
done done
if [[ "$PROJECT_ROOT" == "/" ]]; then
PROJECT_ROOT="."
fi
# Check for virtualenv name override # Check for virtualenv name override
if [[ -f "$PROJECT_ROOT/.venv" ]]; then if [[ -f "$PROJECT_ROOT/.venv" ]]; then
ENV_NAME="$(cat "$PROJECT_ROOT/.venv")" ENV_NAME="$(cat "$PROJECT_ROOT/.venv")"
elif [[ -f "$PROJECT_ROOT/.venv/bin/activate" ]];then elif [[ -f "$PROJECT_ROOT/.venv/bin/activate" ]];then
ENV_NAME="$PROJECT_ROOT/.venv" ENV_NAME="$PROJECT_ROOT/.venv"
elif [[ "$PROJECT_ROOT" != "." ]]; then elif [[ "$PROJECT_ROOT" != "/" ]]; then
ENV_NAME="${PROJECT_ROOT:t}" ENV_NAME="${PROJECT_ROOT:t}"
else else
ENV_NAME="" ENV_NAME=""
@ -68,14 +60,21 @@ if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
fi fi
if [[ "$ENV_NAME" != "" ]]; then if [[ "$ENV_NAME" != "" ]]; then
# Activate the environment only if it is not already active # Activate the environment only if it is not already active
if [[ "$VIRTUAL_ENV" != "$WORKON_HOME/$ENV_NAME" ]]; then if [[ ! "$VIRTUAL_ENV" -ef "$WORKON_HOME/$ENV_NAME" ]]; then
if [[ -e "$WORKON_HOME/$ENV_NAME/bin/activate" ]]; then if [[ -e "$WORKON_HOME/$ENV_NAME/bin/activate" ]]; then
workon "$ENV_NAME" && export CD_VIRTUAL_ENV="$ENV_NAME" workon "$ENV_NAME" && export CD_VIRTUAL_ENV="$ENV_NAME"
elif [[ -e "$ENV_NAME/bin/activate" ]]; then elif [[ -e "$ENV_NAME/bin/activate" ]]; then
source $ENV_NAME/bin/activate && export CD_VIRTUAL_ENV="$ENV_NAME" source $ENV_NAME/bin/activate && export CD_VIRTUAL_ENV="$ENV_NAME"
else
ENV_NAME=""
fi fi
fi 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 fi
} }