Repository: pypa/pip

Issue:
pip ignores --global-option and --install-options when installing from a VCS url
**Environment**

* pip version: 10.0.1
* Python version: 3.6.5
* OS: Linux

**Description**
pip 10.0.1 ignores --install-options installing from git+git://

Likely related to

https://github.com/pypa/pip/issues/5251

```
$ pip install --ignore-installed --no-deps --install-option="--prefix=/tmp/test-install" git+git://github.com/bccp/nbodykit

$ ls /tmp/test-install
ls: cannot access '/tmp/test-install': No such file or directory
```

However, installing from zip works:

```
$ pip install --ignore-installed --no-deps --install-option="--prefix=/tmp/test-install" http://github.com/bccp/nbodykit/archive/master.zip

$ ls /tmp/test-install
lib

```

**Expected behavior**
installing from VCS shall be no different than from a zip file.

**How to Reproduce**
See above.

**Output**

See above.



Discussion:
This looks like a bug to me. I don't have the bandwidth to investigate though. :(
**Environment**
* pip version: 18.0
* Python version: 3.7.0 (installed via Linuxbrew)
* OS: Red Hat Enterprise Linux Server release 6.6 (Santiago)

**Description**
Same thing happens for me using git with ssh. The following installs to Python 3.7.0's site-packages and not to \<path to dir\>/lib/Python3.7/site-packages/ as expected.
```
$ pip3 install --install-option="--prefix=<path to dir>" git+ssh://<host>:<repo>
```
The following does install to \<path to dir>\/lib/Python3.7/site-packages/ as expected
```
$ git clone <host>:<repo>
$ pip3 install --install-option="--prefix=<path to dir>" ./<repo>
```

Both installations give ```UserWarning: Disabling all use of wheels due to the use of --build-options / --global-options / --install-options.```

The former (install from git via ssh) also gives
```
Building wheels for collected packages: cgldb
  Running setup.py bdist_wheel for cgldb ... done
  Stored in directory: /tmp/pip-ephem-wheel-cache-z3m391el/wheels/a8/99/4d/eebf5e88bdd2909e65353b3ccc03761facab89925a55faf3f6
```
Can confirm that this is still an issue with pip `19.0.1` and `git+https`
Someone reported this issue again as #6379 (but for `--global-option` rather than `--install-option`).

I diagnosed it there in [this comment](https://github.com/pypa/pip/issues/6379#issuecomment-480651944) and am copying my findings here since that issue is now closed as a duplicate:

When `--global-option` (or `--install-option`) is passed, pip disallows binaries for that requirement: https://github.com/pypa/pip/blob/78744e80712e32615bc6be293cb9b8c6d8d62a92/src/pip/_internal/cli/cmdoptions.py#L72-L79

However, when pip gets to the point where it needs to decide whether to build a wheel or fall back to using `setup.py`, it looks at whether it's a VCS checkout before checking whether binaries were disallowed: https://github.com/pypa/pip/blob/78744e80712e32615bc6be293cb9b8c6d8d62a92/src/pip/_internal/wheel.py#L766-L776

So the fix should be pretty simple (just reverse those two checks, I believe).


Resolving patch:
diff --git a/src/pip/_internal/wheel.py b/src/pip/_internal/wheel.py
--- a/src/pip/_internal/wheel.py
+++ b/src/pip/_internal/wheel.py
@@ -763,10 +763,6 @@ def should_use_ephemeral_cache(
     if req.editable or not req.source_dir:
         return None
 
-    if req.link and not req.link.is_artifact:
-        # VCS checkout. Build wheel just for this run.
-        return True
-
     if "binary" not in format_control.get_allowed_formats(
             canonicalize_name(req.name)):
         logger.info(
@@ -775,6 +771,10 @@ def should_use_ephemeral_cache(
         )
         return None
 
+    if req.link and not req.link.is_artifact:
+        # VCS checkout. Build wheel just for this run.
+        return True
+
     link = req.link
     base, ext = link.splitext()
     if cache_available and _contains_egg_info(base):


Test patch:
diff --git a/tests/unit/test_wheel.py b/tests/unit/test_wheel.py
--- a/tests/unit/test_wheel.py
+++ b/tests/unit/test_wheel.py
@@ -99,6 +99,49 @@ def test_should_use_ephemeral_cache__issue_6197(
     assert ephem_cache is expected
 
 
+@pytest.mark.parametrize(
+    "disallow_binaries, expected",
+    [
+        # By default (i.e. when binaries are allowed), VCS requirements
+        # should be built.
+        (False, True),
+        # Disallowing binaries, however, should cause them not to be built.
+        (True, None),
+    ],
+)
+def test_should_use_ephemeral_cache__disallow_binaries_and_vcs_checkout(
+    disallow_binaries, expected,
+):
+    """
+    Test that disallowing binaries (e.g. from passing --global-option)
+    causes should_use_ephemeral_cache() to return None for VCS checkouts.
+    """
+    req = Requirement('pendulum')
+    # Passing a VCS url causes link.is_artifact to return False.
+    link = Link(url='git+https://git.example.com/pendulum.git')
+    req = InstallRequirement(
+        req=req,
+        comes_from=None,
+        constraint=False,
+        editable=False,
+        link=link,
+        source_dir='/tmp/pip-install-9py5m2z1/pendulum',
+    )
+    assert not req.is_wheel
+    assert not req.link.is_artifact
+
+    format_control = FormatControl()
+    if disallow_binaries:
+        format_control.disallow_binaries()
+
+    # The cache_available value doesn't matter for this test.
+    ephem_cache = wheel.should_use_ephemeral_cache(
+        req, format_control=format_control, autobuilding=True,
+        cache_available=True,
+    )
+    assert ephem_cache is expected
+
+
 def test_format_command_result__INFO(caplog):
     caplog.set_level(logging.INFO)
     actual = wheel.format_command_result(