Repository: pypa/pipenv

Issue:
Installing from git and specifying the platform or os raises an InvalidMarker error
### Issue description

When running `pipenv install` using Python3 and pipenv version 2018.11.14, if I specify a platform for a package from GitHub I get an InvalidMarker error.

```
python3.7/site-packages/pip/_vendor/packaging/markers.py", line 280, in __init__', '    raise InvalidMarker(err_str)', 'pip._vendor.packaging.markers.InvalidMarker: Invalid marker: \'sys_platform == \\\'linux\\\'"\', parse error at \'"\'']
```

The platform specifications work fine on other modules when not using a git repo.

### Expected result

The packages to be able to be installed or ignored from GitHub depending if the platform matched. The same installation behaviour as the packages that are not from GitHub.

### Steps to replicate

Pipfile with the platform matchers.

```
[[source]]
name = "pypi"
verify_ssl = true
url = "https://pypi.org/simple"

[requires]
python_version = "3"

[packages]
tweepy = { git = "https://github.com/tweepy/tweepy", markers="sys_platform == 'linux'" }
picamera = { version = "*", sys_platform = "== 'linux'" }
```

Using this without "markers" produced the same issue.

```
tweepy = { git = "https://github.com/tweepy/tweepy", sys_platform = "== 'linux'" }
```

I am on a Mac and using python 3.7.



Discussion:
Hey @samfrench,

We did a quick check and this issue looks very darn similar to

* [#3248 - Incorrect index in lockfile](3248)
* [#3247 - pipenv --three fails](3247)
* [#3246 - Update manual](3246)

This could be a coincidence, but if any of these issues solves your problem then I did a good job :smile:

If not, the maintainers will get to this issue shortly.

Cheers,
Your Friendly Neighborhood ProBot

Ah, technically VCS repos don't really have this capability when they aren't editable I guess.  I can just turn the validation aspect of this off to fix it I believe

Resolving patch:
diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py
--- a/pipenv/cli/command.py
+++ b/pipenv/cli/command.py
@@ -296,7 +296,6 @@ def uninstall(
     if retcode:
         sys.exit(retcode)
 
-
 @cli.command(short_help="Generates Pipfile.lock.")
 @lock_options
 @pass_state
diff --git a/pipenv/core.py b/pipenv/core.py
--- a/pipenv/core.py
+++ b/pipenv/core.py
@@ -1361,7 +1361,11 @@ def pip_install(
                 ignore_hashes = True
     else:
         ignore_hashes = True if not requirement.hashes else False
-        install_reqs = [escape_cmd(r) for r in requirement.as_line(as_list=True)]
+        install_reqs = requirement.as_line(as_list=True)
+        if not requirement.markers:
+            install_reqs = [escape_cmd(r) for r in install_reqs]
+        elif len(install_reqs) > 1:
+            install_reqs = install_reqs[0] + [escape_cmd(r) for r in install_reqs[1:]]
     pip_command = [which_pip(allow_global=allow_global), "install"]
     if pre:
         pip_command.append("--pre")


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -11,6 +11,7 @@
 from pipenv.vendor import delegator
 from pipenv.vendor import requests
 from pipenv.vendor import toml
+from pipenv.vendor import tomlkit
 from pytest_pypi.app import prepare_packages as prepare_pypi_packages
 from vistir.compat import ResourceWarning, fs_str
 from vistir.path import mkdir_p
@@ -124,6 +125,44 @@ def isolate(pathlib_tmpdir):
 WE_HAVE_GITHUB_SSH_KEYS = check_github_ssh()
 
 
+class _Pipfile(object):
+    def __init__(self, path):
+        self.path = path
+        self.document = tomlkit.document()
+        self.document["sources"] = tomlkit.aot()
+        self.document["requires"] = tomlkit.table()
+        self.document["packages"] = tomlkit.table()
+        self.document["dev_packages"] = tomlkit.table()
+
+    def install(self, package, value, dev=False):
+        section = "packages" if not dev else "dev_packages"
+        if isinstance(value, dict):
+            table = tomlkit.inline_table()
+            table.update(value)
+            self.document[section][package] = table
+        else:
+            self.document[section][package] = value
+        self.write()
+
+    def loads(self):
+        self.document = tomlkit.loads(self.path.read_text())
+
+    def dumps(self):
+        source_table = tomlkit.table()
+        source_table["url"] = os.environ.get("PIPENV_TEST_INDEX")
+        source_table["verify_ssl"] = False
+        source_table["name"] = "pipenv_test_index"
+        self.document["sources"].append(source_table)
+        return tomlkit.dumps(self.document)
+
+    def write(self):
+        self.path.write_text(self.dumps())
+
+    @classmethod
+    def get_fixture_path(cls, path):
+        return Path(__file__).absolute().parent.parent / "test_artifacts" / path
+
+
 class _PipenvInstance(object):
     """An instance of a Pipenv Project..."""
     def __init__(self, pypi=None, pipfile=True, chdir=False, path=None, home_dir=None):
@@ -134,7 +173,7 @@ def __init__(self, pypi=None, pipfile=True, chdir=False, path=None, home_dir=Non
         os.environ["CI"] = fs_str("1")
         warnings.simplefilter("ignore", category=ResourceWarning)
         warnings.filterwarnings("ignore", category=ResourceWarning, message="unclosed.*<ssl.SSLSocket.*>")
-        path = os.environ.get("PIPENV_PROJECT_DIR", None)
+        path = path if path else os.environ.get("PIPENV_PROJECT_DIR", None)
         if not path:
             self._path = TemporaryDirectory(suffix='-project', prefix='pipenv-')
             path = Path(self._path.name)
@@ -143,7 +182,7 @@ def __init__(self, pypi=None, pipfile=True, chdir=False, path=None, home_dir=Non
             except OSError:
                 self.path = str(path.absolute())
         else:
-            self._path = None
+            self._path = path
             self.path = path
         # set file creation perms
         self.pipfile_path = None
@@ -159,6 +198,7 @@ def __init__(self, pypi=None, pipfile=True, chdir=False, path=None, home_dir=Non
 
             self.chdir = False or chdir
             self.pipfile_path = p_path
+            self._pipfile = _Pipfile(Path(p_path))
 
     def __enter__(self):
         os.environ['PIPENV_DONT_USE_PYENV'] = fs_str('1')
diff --git a/tests/integration/test_install_uri.py b/tests/integration/test_install_uri.py
--- a/tests/integration/test_install_uri.py
+++ b/tests/integration/test_install_uri.py
@@ -270,3 +270,17 @@ def test_vcs_entry_supersedes_non_vcs(PipenvInstance, pip_src_dir):
             p.lockfile["default"]["pyinstaller"]["git"]
             == "https://github.com/pyinstaller/pyinstaller.git"
         )
+
+
+@pytest.mark.vcs
+@pytest.mark.install
+@pytest.mark.needs_internet
+def test_vcs_can_use_markers(PipenvInstance, pip_src_dir, pypi):
+    with PipenvInstance(chdir=True, pypi=pypi) as p:
+        path = p._pipfile.get_fixture_path("git/six/.git")
+        p._pipfile.install("six", {"git": "{0}".format(path.as_uri()), "markers": "sys_platform == 'linux'"})
+        assert "six" in p.pipfile["packages"]
+        c = p.pipenv("install")
+        assert c.return_code == 0
+        assert "six" in p.lockfile["default"]
+        assert "git" in p.lockfile["default"]["six"]
diff --git a/tests/test_artifacts/git/dateutil b/tests/test_artifacts/git/dateutil
new file mode 160000
--- /dev/null
+++ b/tests/test_artifacts/git/dateutil
@@ -0,0 +1 @@
+Subproject commit 6618dee970ec1e5f92e0f48ec74584caf13075aa
diff --git a/tests/test_artifacts/git/pinax b/tests/test_artifacts/git/pinax
new file mode 160000
--- /dev/null
+++ b/tests/test_artifacts/git/pinax
@@ -0,0 +1 @@
+Subproject commit 147d854322cc2ab8246b9f52fa3189dfca3cddec
diff --git a/tests/test_artifacts/git/requests b/tests/test_artifacts/git/requests
new file mode 160000
--- /dev/null
+++ b/tests/test_artifacts/git/requests
@@ -0,0 +1 @@
+Subproject commit 57d7284c1a245cf9fbcecb594f50471d86e879f7
diff --git a/tests/test_artifacts/git/six b/tests/test_artifacts/git/six
new file mode 160000
--- /dev/null
+++ b/tests/test_artifacts/git/six
@@ -0,0 +1 @@
+Subproject commit e114efceea962fb143c909c904157ca994246fd2
diff --git a/tests/test_artifacts/git/six-1.9.0 b/tests/test_artifacts/git/six-1.9.0
new file mode 160000
--- /dev/null
+++ b/tests/test_artifacts/git/six-1.9.0
@@ -0,0 +1 @@
+Subproject commit 5efb522b0647f7467248273ec1b893d06b984a59