diff --git a/pipenv/cli.py b/pipenv/cli.py index 7aa4d2e0..847f987d 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -321,7 +321,7 @@ def do_create_virtualenv(three=None, python=None): cmd = ['virtualenv', project.virtualenv_location, '--prompt=({0})'.format(project.name)] else: # Default: use pew. - cmd = ['pew', 'new', project.name, '-d'] + cmd = ['pew', 'new', project.virtualenv_name, '-d'] # Pass a Python version to virtualenv, if needed. if python: @@ -891,7 +891,7 @@ def shell(three=None, python=False, compat=False, shell_args=None): # Standard (properly configured shell) mode: else: cmd = 'pew' - args = ["workon", project.name] + args = ["workon", project.virtualenv_name] # Grab current terminal dimensions to replace the hardcoded default # dimensions of pexpect diff --git a/pipenv/project.py b/pipenv/project.py index b11d031e..e2b8de9b 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- import json import os +import re +import base64 +import hashlib import pipfile import toml @@ -37,6 +40,23 @@ class Project(object): def virtualenv_exists(self): return os.path.isdir(self.virtualenv_location) + @property + def virtualenv_name(self): + # Replace dangerous characters into '_' + # + # References: + # https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html + # http://www.tldp.org/LDP/abs/html/special-chars.html#FIELDREF + sanitized = re.sub(r'[ $`!*@"\\\r\n\t]', '_', self.name) + + # Hash the full path of the pipfile + hash = hashlib.sha256(self.pipfile_location.encode()).digest()[:6] + encoded_hash = base64.urlsafe_b64encode(hash).decode() + + # If the pipfile was located at '/home/user/MY_PROJECT/Pipfile', + # the name of its virtualenv will be 'my-project-wyUfYPqE' + return sanitized + '-' + encoded_hash + @property def virtualenv_location(self): @@ -46,7 +66,7 @@ class Project(object): # The user wants the virtualenv in the project. if not PIPENV_VENV_IN_PROJECT: - c = delegator.run('pew dir "{0}"'.format(self.name)) + c = delegator.run('pew dir "{0}"'.format(self.virtualenv_name)) loc = c.out.strip() # Default mode. else: diff --git a/tests/test_project.py b/tests/test_project.py index fa4ede12..1c73d688 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -1,3 +1,6 @@ +from hashlib import sha256 +from base64 import urlsafe_b64encode + import delegator import pipenv.project @@ -6,9 +9,13 @@ class TestProject(): def test_project(self): proj = pipenv.project.Project() + hash = urlsafe_b64encode( + sha256(proj.pipfile_location.encode()).digest()[:6]).decode() + assert proj.name == 'pipenv' assert proj.pipfile_exists assert proj.virtualenv_exists + assert proj.virtualenv_name == 'pipenv-' + hash def test_proper_names(self): proj = pipenv.project.Project()