Commits

Anonymous committed b3e8b20

allow uninstall of develop-installs with source outside venv (fix #12)

Comments (0)

Files changed (2)

             raise UninstallationError("Cannot uninstall requirement %s, not installed" % (self.name,))
         dist = self.satisfied_by or self.conflicts_with
         paths_to_remove = UninstallPathSet(dist, sys.prefix)
-        if not paths_to_remove.can_uninstall():
-            return
 
         pip_egg_info_path = os.path.join(dist.location,
                                          dist.egg_name()) + '.egg-info'
             easy_install_pth = os.path.join(os.path.dirname(develop_egg_link),
                                             'easy-install.pth')
             paths_to_remove.add_pth(easy_install_pth, dist.location)
+            # fix location (so we can uninstall links to sources outside venv)
+            paths_to_remove.location = develop_egg_link
 
         # find distutils scripts= scripts
         if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'):
         self.pth = {}
         self.prefix = os.path.normcase(os.path.realpath(restrict_to_prefix))
         self.dist = dist
+        self.location = dist.location
         self.save_dir = None
         self._moved_paths = []
 
-    def can_uninstall(self):
-        prefix, stripped = strip_prefix(self.dist.location, self.prefix)
+    def _can_uninstall(self):
+        prefix, stripped = strip_prefix(self.location, self.prefix)
         if not stripped:
             logger.notify("Not uninstalling %s at %s, outside environment %s"
                           % (self.dist.project_name, self.dist.location,
     def remove(self, auto_confirm=False):
         """Remove paths in ``self.paths`` with confirmation (unless
         ``auto_confirm`` is True)."""
+        if not self._can_uninstall():
+            return
         logger.notify('Uninstalling %s:' % self.dist.project_name)
         logger.indent += 2
         paths = sorted(self.compact(self.paths))

tests/test_uninstall.txt

 
     >>> from __main__ import here, reset_env, run_pip, pyversion, lib_py, get_env, diff_states, write_file
     >>> from os.path import join
+    >>> from tempfile import mkdtemp
     >>> easy_install_pth = join(lib_py, 'site-packages', 'easy-install.pth')
 
 Simple install and uninstall::
     >>> diff_states(result.files_before, result2.files_after, ignore=['src/initools', 'build']).values()
     [{}, {}, {}]
 
+Editable install from existing source outside the venv::
+
+    >>> reset_env()
+    >>> tmpdir = mkdtemp()
+    >>> result = env.run('hg', 'clone', 'http://bitbucket.org/ianb/virtualenv/', tmpdir)
+    >>> result2 = run_pip('install', '-e', tmpdir)
+    >>> assert (join(lib_py, 'site-packages', 'virtualenv.egg-link') in result2.files_created), result2.files_created.keys()
+    >>> result3 = run_pip('uninstall', '-y', 'virtualenv', expect_error=True)
+    >>> diff_states(result.files_before, result3.files_after, ignore=['build']).values()
+    [{}, {}, {}]
+
 Uninstall from a requirements file::
 
     >>> reset_env()