Commits

barberj committed 4f5c84c

Update cpvirtualenv utilizing virtualenv-clone and allowing for external virutalenvs to be added to WORKON_HOME.

Comments (0)

Files changed (7)

docs/en/command_ref.rst

 cpvirtualenv
 ------------
 
-Duplicate an environment, in the WORKON_HOME.
+In the WORKON_HOME, duplicate an environment or clone an external environment.
 
 Syntax::
 
-    cpvirtualenv ENVNAME TARGETENVNAME
+    cpvirtualenv ENVNAME [TARGETENVNAME]
+
+
 
 .. note::
 
-   The environment created by the copy operation is made `relocatable
-   <http://virtualenv.openplans.org/#making-environments-relocatable>`__.
+  Target environment name is required for WORKON_HOME duplications. However, target environment name can be ommited for external copies, causing the new environment to have the name of the original within the WORKON_HOME.
 
 ::
 
               'virtualenvwrapper.user_scripts',
               'virtualenvwrapper.project',
               ],
-    install_requires=['virtualenv'],
+    install_requires=['virtualenv',
+                      'virtualenv-clone',
+                      ],
 
     namespace_packages = [ 'virtualenvwrapper' ],
     packages = find_packages(),
     deactivate
 }
 
+test_virtualenvwrapper_verify_virtualenv(){
+    assertTrue "Verified unable to verify virtualenv" virtualenvwrapper_verify_virtualenv
+
+    VIRTUALENVWRAPPER_VIRTUALENV="thiscannotpossiblyexist123"
+    assertFalse "Incorrectly verified virtualenv" virtualenvwrapper_verify_virtualenv
+}
+
+test_virtualenvwrapper_verify_virtualenv_clone(){
+    assertTrue "Verified unable to verify virtualenv_clone" virtualenvwrapper_verify_virtualenv_clone
+
+    VIRTUALENVWRAPPER_VIRTUALENV_CLONE="thiscannotpossiblyexist123"
+    assertFalse "Incorrectly verified virtualenv_clone" virtualenvwrapper_verify_virtualenv_clone
+}
+
 . "$test_dir/shunit2"
 }
 
 test_new_env_activated () {
-    mkvirtualenv "source"
+    mkvirtualenv "source" >/dev/null 2>&1
     (cd tests/testpackage && python setup.py install) >/dev/null 2>&1
-    cpvirtualenv "source" "destination"
-    rmvirtualenv "source"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1
+    rmvirtualenv "source" >/dev/null 2>&1
     testscript="$(which testscript.py)"
     assertTrue "Environment test script not found in path" "[ $WORKON_HOME/destination/bin/testscript.py -ef $testscript ]"
     testscriptcontent="$(cat $testscript)"
 }
 
 test_virtual_env_variable () {
-    mkvirtualenv "source"
-    cpvirtualenv "source" "destination"
+    mkvirtualenv "source" >/dev/null 2>&1
+    cpvirtualenv "source" "destination" >/dev/null 2>&1
     assertSame "Wrong virtualenv name" "destination" $(basename "$VIRTUAL_ENV")
     assertTrue "$WORKON_HOME not in $VIRTUAL_ENV" "echo $VIRTUAL_ENV | grep -q $WORKON_HOME"
 }
 
-fake_virtualenv () {
+fake_venv () {
+    ###
+    # create a silly file to ensure copy happens
+    ###
     typeset envname="$1"
-    touch "$envname/fake_virtualenv_was_here"
     virtualenv $@
+    touch "$WORKON_HOME/$envname/fake_virtualenv_was_here"
+}
+
+fake_venv_clone () {
+    ###
+    # create a silly file to ensure copy happens
+    ###
+    typeset src_path="$1"
+    touch "$src_path/fake_virtualenv_clone_was_here"
+    virtualenv-clone $@
 }
 
 test_virtualenvwrapper_virtualenv_variable () {
-    mkvirtualenv "source"
-    export VIRTUALENVWRAPPER_VIRTUALENV=fake_virtualenv
-    cpvirtualenv "source" "destination"
+
+    eval 'virtualenvwrapper_verify_virtualenv () { 
+        return 0 
+    }'
+
+    VIRTUALENVWRAPPER_VIRTUALENV=fake_venv
+    assertSame "VIRTUALENVWRAPPER_VIRTUALENV is not set correctly" "$VIRTUALENVWRAPPER_VIRTUALENV" "fake_venv"
+
+    mkvirtualenv "source" >/dev/null 2>&1 
+    assertTrue "Fake file not made in fake_venv" "[ -f "$VIRTUAL_ENV/fake_virtualenv_was_here" ]"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
     unset VIRTUALENVWRAPPER_VIRTUALENV
-    assertTrue "wrapper was not run" "[ -f $VIRTUAL_ENV/fake_virtualenv_was_here ]"
+    assertTrue "VIRTUALENVWRAPPER_CLONE did not clone fake file" "[ -f $WORKON_HOME/destination/fake_virtualenv_was_here ]"
+}
+
+test_virtualenvwrapper_virtualenv_clone_variable () {
+
+    eval 'virtualenvwrapper_verify_virtualenv_clone () { 
+        return 0 
+    }'
+
+    VIRTUALENVWRAPPER_VIRTUALENV_CLONE=fake_venv_clone
+    assertSame "VIRTUALENVWRAPPER_VIRTUALENV_CLONE is not set correctly" "$VIRTUALENVWRAPPER_VIRTUALENV_CLONE" "fake_venv_clone"
+
+    mkvirtualenv "source" >/dev/null 2>&1 
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
+    unset VIRTUALENVWRAPPER_VIRTUALENV_CLONE
+    assertTrue "VIRTUALENVWRAPPER_CLONE did not clone fake file" "[ -f $WORKON_HOME/destination/fake_virtualenv_clone_was_here ]"
 }
 
 test_source_relocatable () {
-    mkvirtualenv "source"
+    mkvirtualenv "source" >/dev/null 2>&1 
     (cd tests/testpackage && python setup.py install) >/dev/null 2>&1
     assertTrue "virtualenv --relocatable \"$WORKON_HOME/source\""
-    cpvirtualenv "source" "destination"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
     testscript="$(which testscript.py)"
     assertTrue "Environment test script not the same as copy" "[ $WORKON_HOME/destination/bin/testscript.py -ef $testscript ]"
     assertTrue virtualenvwrapper_verify_active_environment
 }
 
 test_source_does_not_exist () {
-    out="$(cpvirtualenv virtualenvthatdoesntexist foo)"
-    assertSame "$out" "virtualenvthatdoesntexist virtualenv doesn't exist"
+    assertSame "Please provide a valid virtualenv to copy." "$(cpvirtualenv virtualenvthatdoesntexist foo)"
 }
 
 test_hooks () {
-    mkvirtualenv "source"
+    mkvirtualenv "source" >/dev/null 2>&1 
 
     export pre_test_dir=$(cd "$test_dir"; pwd)
 
     echo "#!/bin/sh" > "$WORKON_HOME/postcpvirtualenv"
     echo "echo GLOBAL postcpvirtualenv >> $test_dir/catch_output" > "$WORKON_HOME/postcpvirtualenv"
 
-    cpvirtualenv "source" "destination"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
 
     output=$(cat "$test_dir/catch_output")
     workon_home_as_pwd=$(cd $WORKON_HOME; pwd)
 
-    expected="GLOBAL precpvirtualenv $workon_home_as_pwd source destination
+    expected="GLOBAL precpvirtualenv $workon_home_as_pwd $workon_home_as_pwd/source destination
 GLOBAL premkvirtualenv $workon_home_as_pwd destination
 GLOBAL postmkvirtualenv
 GLOBAL postcpvirtualenv"
 test_no_site_packages () {
     # See issue #102
     mkvirtualenv "source" --no-site-packages >/dev/null 2>&1
-    cpvirtualenv "source" "destination"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
     ngsp_file="`virtualenvwrapper_get_site_packages_dir`/../no-global-site-packages.txt"
     assertTrue "$ngsp_file does not exist in copied env" "[ -f \"$ngsp_file\" ]"
 }
     VIRTUALENVWRAPPER_VIRTUALENV_ARGS="--no-site-packages"
     # With the argument, verify that they are not copied.
     mkvirtualenv "source" >/dev/null 2>&1
-    cpvirtualenv "source" "destination"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
     ngsp_file="`virtualenvwrapper_get_site_packages_dir`/../no-global-site-packages.txt"
     assertTrue "$ngsp_file does not exist" "[ -f \"$ngsp_file\" ]"
     unset VIRTUALENVWRAPPER_VIRTUALENV_ARGS
     # See issue #102
     # virtualenv 1.7 changed to make --no-site-packages the default
     mkvirtualenv "source" >/dev/null 2>&1
-    cpvirtualenv "source" "destination"
+    cpvirtualenv "source" "destination" >/dev/null 2>&1 
     ngsp_file="`virtualenvwrapper_get_site_packages_dir`/../no-global-site-packages.txt"
     assertTrue "$ngsp_file does not exist in copied env" "[ -f \"$ngsp_file\" ]"
 }

tests/test_cpvirtualenv.sh

+#venv!/bin/sh
+
+test_dir=$(cd $(dirname $0) && pwd)
+source "$test_dir/setup.sh"
+
+setUp () {
+    rm -rf "$WORKON_HOME"
+    mkdir -p "$WORKON_HOME"
+    source "$test_dir/../virtualenvwrapper.sh"
+    rm -f "$test_dir/catch_output"
+    echo
+}
+
+tearDown () {
+    if type deactivate >/dev/null 2>&1
+    then 
+        deactivate
+    fi
+    #rm -rf "$WORKON_HOME"
+}
+
+test_no_arguments () {
+    assertSame "Please provide a valid virtualenv to copy." "$(cpvirtualenv)"
+}
+
+test_venv_already_exists_in_workon () {
+    mkvirtualenv "cpvenv_test" >/dev/null 2>&1
+    assertSame  "cpvenv_test virtualenv already exists." "$(cpvirtualenv 'cpvenv_test')"
+}
+
+test_bad_path () {
+    assertSame "Please provide a valid virtualenv to copy." "$(cpvirtualenv '~/cpvenv_test')"
+}
+
+test_copy_venv () {
+    # verify venvs don't exist
+    assertTrue "Virtualenv to copy already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Copied virtualenv already exists" "[ ! -d $WORKON_HOME/copied_venv ]"
+    mkvirtualenv "cpvenv_test" >/dev/null 2>&1
+    touch "$WORKON_HOME/cpvenv_test/mytestpackage"
+
+    assertTrue "Virtualenv to copy didn't get created" "[ -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Copied virtualenv already exists" "[ ! -d $WORKON_HOME/copied_venv ]"
+
+    cpvirtualenv "cpvenv_test" "copied_venv" >/dev/null 2>&1
+
+    # verify copied venv exist
+    assertTrue "Copied virtualenv doesn't exist" "[ -d $WORKON_HOME/copied_venv ]"
+    # verify test package exists
+    assertTrue "Test package is missing" "[ -f $WORKON_HOME/copied_venv/mytestpackage ]"
+}
+
+test_copy_venv_activate () {
+    # verify venvs don't exist
+    assertTrue "Virtualenv to copy already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Copied virtualenv already exists" "[ ! -d $WORKON_HOME/copied_venv ]"
+    mkvirtualenv "cpvenv_test" >/dev/null 2>&1
+
+    assertTrue "Virtualenv to copy didn't get created" "[ -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Copied virtualenv already exists" "[ ! -d $WORKON_HOME/copied_venv ]"
+
+    cpvirtualenv "cpvenv_test" "copied_venv" >/dev/null 2>&1
+
+    # verify copied venv exist
+    assertTrue "Copied virtualenv doesn't exist" "[ -d $WORKON_HOME/copied_venv ]"
+
+    assertSame "copied_venv" "$(basename $VIRTUAL_ENV)"
+    assertTrue "Virtualenv not active" virtualenvwrapper_verify_active_environment
+}
+
+test_copy_venv_is_listed () {
+    # verify venvs don't exist
+    assertTrue "Virtualenv to copy already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Copied virtualenv already exists" "[ ! -d $WORKON_HOME/copied_venv ]"
+    mkvirtualenv "cpvenv_test" >/dev/null 2>&1
+
+    typeset listed=$(lsvirtualenv)
+    [[ "$listed" != *copied_venv* ]]
+    RC=$?
+    assertTrue "Copied virtualenv found in virtualenv list" $RC 
+
+    cpvirtualenv "cpvenv_test" "copied_venv" >/dev/null 2>&1
+
+    listed=$(lsvirtualenv -b)
+    [[ "$listed" == *copied_venv* ]]
+    RC=$?
+    assertTrue "Copied virtualenv not found in virtualenv list" $RC 
+}
+
+test_clone_venv () {
+    typeset tmplocation=$(dirname $WORKON_HOME)
+
+    # verify venvs don't exist
+    assertTrue "Virtualenv to clone already exists" "[ ! -d $tmplocation/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cloned_venv ]"
+
+    $VIRTUALENVWRAPPER_VIRTUALENV "$tmplocation/cpvenv_test" >/dev/null 2>&1
+    touch "$tmplocation/cpvenv_test/mytestpackage"
+
+    assertTrue "Virtualenv to clone didn't get created" "[ -d $tmplocation/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cloned_venv ]"
+
+    cpvirtualenv "$tmplocation/cpvenv_test" "cloned_venv" >/dev/null 2>&1
+
+    # verify cloned venv exist
+    assertTrue "Cloned virtualenv doesn't exist" "[ -d $WORKON_HOME/cloned_venv ]"
+    # verify test package exists
+    assertTrue "Test package is missing" "[ -f $WORKON_HOME/cloned_venv/mytestpackage ]"
+
+    rm -rf "$tmplocation/cpvenv_test"
+}
+
+test_clone_venv_activate () {
+    typeset tmplocation=$(dirname $WORKON_HOME)
+
+    # verify venvs don't exist
+    assertTrue "Virtualenv to clone already exists" "[ ! -d $tmplocation/cpvenv_test ]"
+    assertTrue "Virtualenv with same name as clone source already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cloned_venv ]"
+
+    $VIRTUALENVWRAPPER_VIRTUALENV "$tmplocation/cpvenv_test" >/dev/null 2>&1
+
+    assertTrue "Virtualenv to clone didn't get created" "[ -d $tmplocation/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cloned_venv ]"
+
+    #cpvirtualenv "$tmplocation/cpvenv_test" "cloned_venv" >/dev/null 2>&1
+    cpvirtualenv "$tmplocation/cpvenv_test" "cloned_venv" >/dev/null 2/>&1
+
+    # verify cloned venv exist
+    assertTrue "Cloned virtualenv doesn't exist" "[ -d $WORKON_HOME/cloned_venv ]"
+
+    assertSame "cloned_venv" "$(basename $VIRTUAL_ENV)"
+    assertTrue "Virtualenv not active" virtualenvwrapper_verify_active_environment
+
+    rm -rf "$tmplocation/cpvenv_test"
+}
+
+test_clone_venv_is_listed (){
+    typeset tmplocation=$(dirname $WORKON_HOME)
+
+    # verify venvs don't exist
+    assertTrue "Virtualenv to clone already exists" "[ ! -d $tmplocation/cpvenv_test ]"
+    assertTrue "Virtualenv with same name as clone source already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cloned_venv ]"
+
+    typeset listed=$(lsvirtualenv)
+    [[ "$listed" != *cloned_venv* ]]
+    RC=$?
+    assertTrue "Cloned virtualenv found in virtualenv list" $RC 
+
+    $VIRTUALENVWRAPPER_VIRTUALENV "$tmplocation/cpvenv_test" >/dev/null 2>&1
+    cpvirtualenv "$tmplocation/cpvenv_test" "cloned_venv" >/dev/null 2>&1
+
+    listed=$(lsvirtualenv -b)
+    [[ "$listed" == *cloned_venv* ]]
+    RC=$?
+    assertTrue "Cloned virtualenv not found in virtualenv list" $RC 
+
+    rm -rf "$tmplocation/cpvenv_test"
+
+}
+
+test_clone_venv_using_same_name () {
+    typeset tmplocation=$(dirname $WORKON_HOME)
+
+    # verify venvs don't exist
+    assertTrue "Virtualenv to clone already exists" "[ ! -d $tmplocation/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+
+    $VIRTUALENVWRAPPER_VIRTUALENV "$tmplocation/cpvenv_test" >/dev/null 2>&1
+    touch "$tmplocation/cpvenv_test/mytestpackage"
+
+    assertTrue "Virtualenv to clone didn't get created" "[ -d $tmplocation/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+
+    typeset listed=$(lsvirtualenv)
+    [[ "$listed" != *cpvenv_test* ]]
+    RC=$?
+    assertTrue "Cloned virtualenv found in virtualenv list" $RC 
+
+    cpvirtualenv "$tmplocation/cpvenv_test" >/dev/null 2>&1 >/dev/null 2>&1
+
+    # verify cloned venv exist
+    assertTrue "Cloned virtualenv doesn't exist" "[ -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Test package is missing" "[ -f $WORKON_HOME/cpvenv_test/mytestpackage ]"
+
+    listed=$(lsvirtualenv -b)
+    [[ "$listed" == *cpvenv_test* ]]
+    RC=$?
+    assertTrue "Cloned virtualenv not found in virtualenv list" $RC 
+
+    assertSame "cpvenv_test" "$(basename $VIRTUAL_ENV)"
+    assertTrue "Virtualenv not active" virtualenvwrapper_verify_active_environment
+
+    rm -rf "$tmplocation/cpvenv_test"
+}
+
+test_clone_venv_using_vars () {
+
+    # verify venvs don't exist
+    assertTrue "Virtualenv to clone already exists" "[ ! -d $TMPDIR/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+
+    $VIRTUALENVWRAPPER_VIRTUALENV "$TMPDIR/cpvenv_test" >/dev/null 2>&1
+    touch "$tmplocation/cpvenv_test/mytestpackage"
+
+    assertTrue "Virtualenv to clone didn't get created" "[ -d $TMPDIR/cpvenv_test ]"
+    assertTrue "Cloned virtualenv already exists" "[ ! -d $WORKON_HOME/cpvenv_test ]"
+
+    typeset listed=$(lsvirtualenv)
+    [[ "$listed" != *cpvenv_test* ]]
+    RC=$?
+    assertTrue "Cloned virtualenv found in virtualenv list" $RC 
+
+    cpvirtualenv '$TMPDIR/cpvenv_test' >/dev/null 2>&1 >/dev/null 2>&1
+
+    # verify cloned venv exist
+    assertTrue "Cloned virtualenv doesn't exist" "[ -d $WORKON_HOME/cpvenv_test ]"
+    assertTrue "Test package is missing" "[ -f $WORKON_HOME/cpvenv_test/mytestpackage ]"
+
+    listed=$(lsvirtualenv -b)
+    [[ "$listed" == *cpvenv_test* ]]
+    RC=$?
+    assertTrue "Cloned virtualenv not found in virtualenv list" $RC 
+
+    assertSame "cpvenv_test" "$(basename $VIRTUAL_ENV)"
+    assertTrue "Virtualenv not active" virtualenvwrapper_verify_active_environment
+
+    rm -rf "$TMPDIR/cpvenv_test"
+}
+
+source "$test_dir/shunit2"
 [testenv]
 commands = bash ./tests/run_tests {envdir} []
 deps = virtualenv
+       virtualenv-clone
 setenv =
     TOXIC = true
+isitepackages=True
 
 # Not sure why this is needed, but on my system if it isn't included then
 # the python version picked up for 2.6 is actually 2.7.

virtualenvwrapper.sh

     VIRTUALENVWRAPPER_VIRTUALENV="virtualenv"
 fi
 
+# Set the name of the virtualenv-clone app to use.
+if [ "$VIRTUALENVWRAPPER_VIRTUALENV_CLONE" = "" ]
+then
+    VIRTUALENVWRAPPER_VIRTUALENV_CLONE="virtualenv-clone"
+fi
+
 # Define script folder depending on the platorm (Win32/Unix)
 VIRTUALENVWRAPPER_ENV_BIN_DIR="bin"
 if [ "$OS" = "Windows_NT" ] && [ "$MSYSTEM" = "MINGW32" ]
         if [ "$1" = "" ]; then
             return 1
         else
-            "$VIRTUALENVWRAPPER_PYTHON" -c "import os,sys; sys.stdout.write(os.path.realpath(os.path.expanduser(os.path.expandvars(\"$1\")))+'\n')"
+            "$VIRTUALENVWRAPPER_PYTHON" -c "import os,sys; sys.stdout.write(os.path.normpath(os.path.expanduser(os.path.expandvars(\"$1\")))+'\n')"
             return 0
         fi
 }
     return 0
 }
 
-
-# Verify that virtualenv is installed and visible
-function virtualenvwrapper_verify_virtualenv {
-    typeset venv=$(\which "$VIRTUALENVWRAPPER_VIRTUALENV" | (unset GREP_OPTIONS; \grep -v "not found"))
-    if [ "$venv" = "" ]
+# Verify that the passed resource is in path and exists
+function virtualenvwrapper_verify_resource {
+    typeset exe_path=$(\which "$1" | (unset GREP_OPTIONS; \grep -v "not found"))
+    if [ "$exe_path" = "" ]
     then
-        echo "ERROR: virtualenvwrapper could not find $VIRTUALENVWRAPPER_VIRTUALENV in your path" >&2
+        echo "ERROR: virtualenvwrapper could not find $1 in your path" >&2
         return 1
     fi
-    if [ ! -e "$venv" ]
+    if [ ! -e "$exe_path" ]
     then
-        echo "ERROR: Found $VIRTUALENVWRAPPER_VIRTUALENV in path as \"$venv\" but that does not exist" >&2
+        echo "ERROR: Found $1 in path as \"$exe_path\" but that does not exist" >&2
         return 1
     fi
     return 0
 }
 
+
+# Verify that virtualenv is installed and visible
+function virtualenvwrapper_verify_virtualenv {
+    virtualenvwrapper_verify_resource $VIRTUALENVWRAPPER_VIRTUALENV
+}
+
+
+function virtualenvwrapper_verify_virtualenv_clone {
+    virtualenvwrapper_verify_resource $VIRTUALENVWRAPPER_VIRTUALENV_CLONE
+}
+
+
 # Verify that the requested environment exists
 function virtualenvwrapper_verify_workon_environment {
     typeset env_name="$1"
 
 # Duplicate the named virtualenv to make a new one.
 function cpvirtualenv {
-    typeset env_name="$1"
-    if [ "$env_name" = "" ]
-    then
-        virtualenvwrapper_show_workon_options
-        return 1
-    fi
-    typeset new_env="$2"
-    if [ "$new_env" = "" ]
-    then
-        echo "Please specify target virtualenv"
+    virtualenvwrapper_verify_workon_home || return 1
+    virtualenvwrapper_verify_virtualenv_clone || return 1
+
+    typeset src_name="$1"
+    typeset trg_name="$2"
+    typeset src
+    typeset trg 
+
+    # without a source there is nothing to do
+    if [ "$src_name" = "" ]; then
+        echo "Please provide a valid virtualenv to copy."
         return 1
+    else
+        # see if its already in workon
+        if [ ! -e "$WORKON_HOME/$src_name" ]; then
+            # so its a virtualenv we are importing
+            # make sure we have a full path
+            # and get the name
+            src=$(virtualenvwrapper_expandpath "$src_name")
+            # final verification
+            if [ ! -e "$src" ]; then
+                echo "Please provide a valid virtualenv to copy."
+                return 1
+            fi
+            src_name=$(basename "$src")
+        else
+           src="$WORKON_HOME/$src_name"
+        fi
     fi
-    if echo "$WORKON_HOME" | (unset GREP_OPTIONS; \grep "/$" > /dev/null)
-    then
-        typeset env_home="$WORKON_HOME"
+
+    if [ "$trg_name" = "" ]; then
+        # target not given, assume
+        # same as source
+        trg="$WORKON_HOME/$src_name"
+        trg_name="$src_name"
     else
-        typeset env_home="$WORKON_HOME/"
+        trg="$WORKON_HOME/$trg_name"
     fi
-    typeset source_env="$env_home$env_name"
-    typeset target_env="$env_home$new_env"
+    trg=$(virtualenvwrapper_expandpath "$trg")
 
-    if [ ! -e "$source_env" ]
-    then
-        echo "$env_name virtualenv doesn't exist"
+    # validate trg does not already exist
+    # catch copying virtualenv in workon home
+    # to workon home
+    if [ -e "$trg" ]; then
+        echo "$trg_name virtualenv already exists."
         return 1
     fi
 
-    \cp -r "$source_env" "$target_env"
-    for script in $( \ls $target_env/$VIRTUALENVWRAPPER_ENV_BIN_DIR/* )
-    do
-        newscript="$script-new"
-        \sed "s|$source_env|$target_env|g" < "$script" > "$newscript"
-        \mv "$newscript" "$script"
-        \chmod a+x "$script"
-    done
+    echo "Copying $src_name as $trg_name..."
+    (
+        [ -n "$ZSH_VERSION" ] && setopt SH_WORD_SPLIT 
+        \cd "$WORKON_HOME" &&
+        "$VIRTUALENVWRAPPER_VIRTUALENV_CLONE" "$src" "$trg" 
+        [ -d "$trg" ] && 
+            virtualenvwrapper_run_hook "pre_cpvirtualenv" "$src" "$trg_name" &&
+            virtualenvwrapper_run_hook "pre_mkvirtualenv" "$trg_name"
+    )
+    typeset RC=$?
+    [ $RC -ne 0 ] && return $RC
 
-    "$VIRTUALENVWRAPPER_VIRTUALENV" "$target_env" --relocatable
-    \sed "s/VIRTUAL_ENV\(.*\)$env_name/VIRTUAL_ENV\1$new_env/g" < "$source_env/$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate" > "$target_env/$VIRTUALENVWRAPPER_ENV_BIN_DIR/activate"
+    [ ! -d "$WORKON_HOME/$trg_name" ] && return 0
+
+    # Now activate the new environment
+    workon "$trg_name"
 
-    (\cd "$WORKON_HOME" && (
-        virtualenvwrapper_run_hook "pre_cpvirtualenv" "$env_name" "$new_env";
-        virtualenvwrapper_run_hook "pre_mkvirtualenv" "$new_env"
-        ))
-    workon "$new_env"
     virtualenvwrapper_run_hook "post_mkvirtualenv"
     virtualenvwrapper_run_hook "post_cpvirtualenv"
 }