Repository: pypa/pip

Issue:
pip --ignore-installed unexpected behavior
@carljm said this is the expected behavior:

If I have a project that's installed, and if I try to install it in another directory, using -I to ignore the installed version, pip should not uninstall the original one.

But it turns out it does uninstall the original one, see (I had mock installed):

http://tarek.pastebin.mozilla.org/2731680

Also happens with 1.4



Discussion:
from what I can tell, the parameter means to ignore the fact that an existing installation satisfies your requirement, and _uninstall_ it regardless.   I can update the help string for it to be clearer.

an option that truly ignored an installation could be really bad.  the result could be confusing double installs of metadata, when used against the same site-packages

At one point the intended meaning of the `-I` parameter was in fact to fully act as if there were no existing installation; thus not to touch it at all. It seems that at some point that meaning was changed in practice; I don't know if that change was intentional or accidental, but it was a change.

I think the original meaning makes more sense with the name `--ignore-installed` than this new meaning; to uninstall something is clearly not ignoring it.

It's true that this is an advanced feature that can lead to confusing results if used without understanding, but it is very useful in some circumstances and the workarounds for not having it are painful (you have to create a new temporary clean virtualenv just to run a command in it). So I would be in favor of fixing it to the original meaning (and warning of the dangers in its help string.)

let me see if I can track down when the change happened,  and in what context.

looks like this is when the change in behavior occurred (in 2011), and it was not intentional.
https://github.com/pypa/pip/commit/2e1b880d1deff1ec83787a293b4e442820a6c956

An additional unguarded call to `check_if_exists` was added, which sets the `conflicts_with` property, which sets up the unwanted uninstall we're seeing.

I'll fix and try to get this into the next 1.5 beta.
We have one test for this, but it looks broke  


Resolving patch:
diff --git a/pip/req.py b/pip/req.py
--- a/pip/req.py
+++ b/pip/req.py
@@ -1183,7 +1183,8 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
                                 install = False
                         # req_to_install.req is only avail after unpack for URL pkgs
                         # repeat check_if_exists to uninstall-on-upgrade (#14)
-                        req_to_install.check_if_exists()
+                        if not self.ignore_installed:
+                            req_to_install.check_if_exists()
                         if req_to_install.satisfied_by:
                             if self.upgrade or self.ignore_installed:
                                 #don't uninstall conflict if user install and and conflict is not user install


Test patch:
diff --git a/tests/functional/test_install_upgrade.py b/tests/functional/test_install_upgrade.py
--- a/tests/functional/test_install_upgrade.py
+++ b/tests/functional/test_install_upgrade.py
@@ -175,13 +175,14 @@ def test_should_not_install_always_from_cache(script):
 
 def test_install_with_ignoreinstalled_requested(script):
     """
-    It installs package if ignore installed is set.
-
+    Test old conflicting package is completely ignored
     """
-    script.pip('install', 'INITools==0.1', expect_error=True)
-    result = script.pip('install', '-I', 'INITools', expect_error=True)
+    r = script.pip('install', 'INITools==0.1', expect_error=True)
+    result = script.pip('install', '-I', 'INITools==0.3', expect_error=True)
     assert result.files_created, 'pip install -I did not install'
-    assert script.site_packages/'INITools-0.1-py%s.egg-info' % pyversion not in result.files_created
+    # both the old and new metadata should be present.
+    assert os.path.exists(script.site_packages_path/'INITools-0.1-py%s.egg-info' % pyversion)
+    assert os.path.exists(script.site_packages_path/'INITools-0.3-py%s.egg-info' % pyversion)
 
 
 def test_upgrade_vcs_req_with_no_dists_found(script, tmpdir):