0

I have a bash script that I'm trying to execute anytime an hg update occurs. The goal of this bash script is to switch to the correct virtualenv. For the sake of simplicity, this script is called .test - shown as follows:

#!/bin/bash
echo 'testing hg update hook'
source ~/.virtualenvs/myvirtualenv/bin/activate

Whenever I call this script from my shell using source .test everythying works properly; I can see the results of echo and my shell changes to reflect the activated virtualenv

However,when I do an hg update, the virtualenv is not being activated. The script is firing as I can see the echo result; however, my shell is not updated to reflect the activated virtualenv. Below is the hook setup in my .hg/hgrc file is below. Any ideas why my virtualenv isn't being activated in this hook?

[hooks]
# Update to the correct virtualenv when switching branches (hg update branchname)
update = source .test

UPDATE 1: Per this answer, I don't believe the hg update hook is firing in my current shell; which is why the virtualenv activates when I run the script manually but fails from the hook

Community
  • 1
  • 1
Anconia
  • 3,888
  • 6
  • 36
  • 65
  • Where do you expect the virtualenv to be activated? It's only going to be active for the duration of the subshell which doesn't seem to do anything. – tdelaney Nov 05 '15 at 04:46
  • Hm, that seems more tricky. Not sure there's a satisfying solution to that. In my answer to your other question I didn't consider that the virtualenv is only transient to the shell it is generated in. Does your IDE have an API which allows to modify / interact with the shell it offers? http://stackoverflow.com/questions/13122137/how-to-source-virtualenv-activate-in-a-bash-script maybe has some half-answer and help – planetmaker Nov 05 '15 at 09:56

1 Answers1

2

Your problem is that when you invoke a shell script, any changes to the environment variables do not get exported to the calling shell (hence why you need to call source activate from the surrounding shell).

The good news is that you don't strictly need to call activate in order to access a virtual environment. What activate will do is:

  1. Add the virtualenv's bin directory to $PATH.
  2. Set the VIRTUAL_ENV environment variable.
  3. Modify your prompt.

None of this is necessary in order to use the virtualenv, and you can execute the python binary in the virtualenv without ever using the script; the prompt is likely not relevant for your use case, you can add the directory (or just the python executable) to your path by symlinking it, and you need the VIRTUAL_ENV environment variable only for software that for some reason needs to be aware of the virtualenv it's running in. If necessary, you can figure it out from sys.executable. For example:

import sys, os

def find_venv():
  python = sys.executable
  for i in xrange(10):
    if not os.path.islink(python):
      break
    python = os.path.realpath(python)
  return os.path.dirname(os.path.dirname(python))

if not os.environ.has_key("VIRTUAL_ENV"):
  os.environ["VIRTUAL_ENV"] = find_venv()
Reimer Behrends
  • 8,600
  • 15
  • 19