Repository: pypa/pipenv

Issue:
pipenv does not install gitlint
`gitlint` is not installed when using `--dev --deploy` flags.

Here's my `Pipfile`:

```
[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true


[requires]

python_version = '3.6'


[dev-packages]

django-debug-toolbar = "*"
"pep8-naming" = "*"
"flake8-builtins" = "*"
"flake8-commas" = "*"
"flake8-quotes" = "*"
"flake8-blind-except" = "*"
"flake8-bugbear" = "*"
"flake8-comprehensions" = "*"
"flake8-pep3101" = "*"
pytest = "*"
"pytest-flake8" = "*"
pytest-isort = "*"
pytest-django = "*"
pytest-cov = "*"
gitlint = "*"
pre-commit = "*"
xenon = "*"
radon = "*"
pylint = "*"
pytest-xdist = "*"


[packages]

django = "<1.12"
django-split-settings = "*"
django-axes = "*"
"psycopg2" = "*"
gunicorn = "*"
unipath = "*"
python-decouple = "*"
djangorestframework = "*"
djangorestframework-jwt = "*"
```

Here's the command I am using: `pipenv install --dev --deploy`. The same happens with just `--dev`.

It was working some versions ago.

##### Describe your environment

1. OS Type: macos
1. Python version: `Python 3.6.2` 
1. Pipenv version: `pipenv, version 8.3.1`

##### Expected result

I expect every dependency from `Pipfile` to be installed.

##### Actual result

Here's my `pip freeze`:
```
» pip freeze
apipkg==1.4
aspy.yaml==1.0.0
astroid==1.5.3
attrs==17.2.0
cached-property==1.3.1
certifi==2017.7.27.1
chardet==3.0.4
colorama==0.3.9
coverage==4.4.1
Django==1.11.7
django-axes==2.3.3
django-debug-toolbar==1.8
django-split-settings==0.2.5
djangorestframework==3.7.1
djangorestframework-jwt==1.11.0
execnet==1.5.0
flake8==3.5.0
flake8-blind-except==0.1.1
flake8-bugbear==17.4.0
flake8-builtins==1.0
flake8-commas==0.4.3
flake8-comprehensions==1.4.1
flake8-pep3101==1.1
flake8-polyfill==1.0.1
flake8-quotes==0.12.0
gunicorn==19.7.1
identify==1.0.6
idna==2.6
isort==4.2.15
lazy-object-proxy==1.3.1
mando==0.6.4
mccabe==0.6.1
nodeenv==1.2.0
pep8-naming==0.4.1
pre-commit==1.3.0
psycopg2==2.7.3.2
py==1.4.34
pycodestyle==2.3.1
pyflakes==1.6.0
PyJWT==1.5.3
pylint==1.7.4
pytest==3.2.3
pytest-cache==1.0
pytest-cov==2.5.1
pytest-django==3.1.2
pytest-flake8==0.9.1
pytest-forked==0.2
pytest-isort==0.1.0
pytest-xdist==1.20.1
python-decouple==3.1
pytz==2017.3
PyYAML==3.12
radon==2.1.1
requests==2.18.4
six==1.11.0
sqlparse==0.2.4
Unipath==1.1
urllib3==1.22
virtualenv==15.1.0
wrapt==1.10.11
xenon==0.5.4
```

##### Steps to replicate

1. Copy `Pipfile`
2. `pipenv install --dev`
3. Check for `gitlint` in `pip freeze` and `Pipfile.lock`


Discussion:
@sobolevn can you please provide the output of the attempted `pipenv install`? It's hard to know what is happening without seeing the actual result of the command.

Can you please provide as well the output of `which pip && which python && which pipenv && pip --version && python --version && pipenv --version && env`

I would also strongly caution against passing `--deploy` with `--dev`, these two arguments are inherently oppositional in nature and the first argument demands an existing, unchanging lockfile.  They are named this way for a reason, you should not deploy your development environment.
@sobolevn I went ahead and tested this myself by installing your `Pipfile`.  I was able to reproduce the issue, so I ran `pipenv install --dev gitlint` from the command line to see what was going on.

```console
 ◰³ tempenv-0d5a258467e40  /t/new  pipenv install --dev gitlint
Courtesy Notice: Pipenv found itself running within a virtual environment, so it will automatically use that environment, instead of creating its own for any project.
Installing gitlint…
⠦Warning: You installed a VCS dependency in non–editable mode. This will work fine, but sub-dependencies will not be resolved by $ pipenv lock.
  To enable this sub–dependency functionality, specify that this dependency is editable.
Requirement already satisfied: gitlint in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages
Requirement already satisfied: arrow==0.10.0 in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages (from gitlint)
Requirement already satisfied: Click==6.6 in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages (from gitlint)
Requirement already satisfied: ordereddict==1.1 in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages (from gitlint)
Requirement already satisfied: sh==1.11; sys_platform != "win32" in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages (from gitlint)
Requirement already satisfied: python-dateutil in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages (from arrow==0.10.0->gitlint)
Requirement already satisfied: six>=1.5 in /home/hawk/.virtualenvs/tempenv-0d5a258467e40/lib/python3.6/site-packages (from python-dateutil->arrow==0.10.0->gitlint)

Adding gitlint to Pipfile's [dev-packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (d4d49d)!
```

Note that pipenv issues a warning because this is a VCS dependency and advises you to install it in editable mode.  You should follow the instructions it gives you in order to have this appear in your lockfile because it can't resolve dependencies otherwise.  This appears to be some kind of issue with the way `gitlint` is being distributed, although I have actually never seen it before (/cc @erinxocon @nateprewitt ??).  I was able to resolve it by doing as instructed and just modifying the `Pipfile` as follows:

```toml
[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true


[requires]

python_version = '3.6'


[dev-packages]

django-debug-toolbar = "*"
"pep8-naming" = "*"
"flake8-builtins" = "*"
"flake8-commas" = "*"
"flake8-quotes" = "*"
"flake8-blind-except" = "*"
"flake8-bugbear" = "*"
"flake8-comprehensions" = "*"
"flake8-pep3101" = "*"
pytest = "*"
"pytest-flake8" = "*"
pytest-isort = "*"
pytest-django = "*"
pytest-cov = "*"
pre-commit = "*"
xenon = "*"
radon = "*"
pylint = "*"
pytest-xdist = "*"
gitlint = {version = "*", editable = "True"}


[packages]

django = "<1.12"
django-split-settings = "*"
django-axes = "*"
"psycopg2" = "*"
gunicorn = "*"
unipath = "*"
python-decouple = "*"
djangorestframework = "*"
djangorestframework-jwt = "*"
```

We don't currently have a CLI syntax for telling pip to install packages from PyPI in editable mode, and I'm not sure we will ever support this... this is an odd one, to be sure.
@techalchemy, took a quick peek and figured it out. The dependency starts with "git", and so it's being detected as a VCS. This is a bug introduced in #807.
@nateprewitt ok simple fix is to add a + to the VCS list or start using the same requirements parser we use elsewhere
@techalchemy + alone won't work, git:// is also valid. We could use requirements if needed, it's just a time intensive module to load when we don't use it very often. Last time I checked it was 150-200ms of pipenvs load time.

Resolving patch:
diff --git a/pipenv/utils.py b/pipenv/utils.py
--- a/pipenv/utils.py
+++ b/pipenv/utils.py
@@ -771,7 +771,10 @@ def is_vcs(pipfile_entry):
     if hasattr(pipfile_entry, 'keys'):
         return any(key for key in pipfile_entry.keys() if key in VCS_LIST)
     elif isinstance(pipfile_entry, six.string_types):
-        return pipfile_entry.startswith(VCS_LIST)
+        # This syntax is only valid with git
+        if pipfile_entry.startswith('git+git@'):
+            pipfile_entry = pipfile_entry.replace('git+git@', 'git+git://')
+        return bool(requirements.requirement.VCS_REGEX.match(pipfile_entry))
     return False
 
 


Test patch:
diff --git a/tests/test_pipenv.py b/tests/test_pipenv.py
--- a/tests/test_pipenv.py
+++ b/tests/test_pipenv.py
@@ -326,9 +326,13 @@ def test_basic_vcs_install(self):
         with PipenvInstance() as p:
             c = p.pipenv('install git+https://github.com/requests/requests.git#egg=requests')
             assert c.return_code == 0
-            assert 'requests' in p.pipfile['packages']
+            # edge case where normal package starts with VCS name shouldn't be flagged as vcs
+            c = p.pipenv('install gitdb2')
+            assert c.return_code == 0
+            assert all(package in p.pipfile['packages'] for package in ['requests', 'gitdb2'])
             assert 'git' in p.pipfile['packages']['requests']
             assert p.lockfile['default']['requests'] == {"git": "https://github.com/requests/requests.git"}
+            assert 'gitdb2' in p.lockfile['default']
 
     @pytest.mark.e
     @pytest.mark.vcs
diff --git a/tests/test_utils.py b/tests/test_utils.py
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -124,8 +124,10 @@ def test_is_required_version(self, version, specified_ver, expected):
         ({'some_value': 5, 'other_value': object()}, False),
         ('package', False),
         ('git+https://github.com/requests/requests.git#egg=requests', True),
-        ('git+git@github.com:requests/requests.git#egg=requests', True)
+        ('git+git@github.com:requests/requests.git#egg=requests', True),
+        ('gitdb2', False)
     ])
+    @pytest.mark.vcs
     def test_is_vcs(self, entry, expected):
         assert pipenv.utils.is_vcs(entry) is expected