diff --git a/pip/req.py b/pip/req.py index 4242f0c2a..1fd0f07f0 100644 --- a/pip/req.py +++ b/pip/req.py @@ -407,14 +407,24 @@ execfile(__file__) pip_egg_info_path = os.path.join(dist.location, dist.egg_name()) + '.egg-info' + # workaround for http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=618367 + debian_egg_info_path = pip_egg_info_path.replace( + '-py%s' % pkg_resources.PY_MAJOR, '') easy_install_egg = dist.egg_name() + '.egg' develop_egg_link = egg_link_path(dist) - if os.path.exists(pip_egg_info_path): + + pip_egg_info_exists = os.path.exists(pip_egg_info_path) + debian_egg_info_exists = os.path.exists(debian_egg_info_path) + if pip_egg_info_exists or debian_egg_info_exists: # package installed by pip - paths_to_remove.add(pip_egg_info_path) + if pip_egg_info_exists: + egg_info_path = pip_egg_info_path + else: + egg_info_path = debian_egg_info_path + paths_to_remove.add(egg_info_path) if dist.has_metadata('installed-files.txt'): for installed_file in dist.get_metadata('installed-files.txt').splitlines(): - path = os.path.normpath(os.path.join(pip_egg_info_path, installed_file)) + path = os.path.normpath(os.path.join(egg_info_path, installed_file)) paths_to_remove.add(path) if dist.has_metadata('top_level.txt'): if dist.has_metadata('namespace_packages.txt'): diff --git a/tests/test_compat.py b/tests/test_compat.py new file mode 100644 index 000000000..d6062efa4 --- /dev/null +++ b/tests/test_compat.py @@ -0,0 +1,44 @@ +""" +Tests for compatibility workarounds. + +""" +import os +from test_pip import reset_env, run_pip, pyversion, assert_all_changes + + +def test_debian_egg_name_workaround(): + """ + We can uninstall packages installed with the pyversion removed from the + egg-info metadata directory name. + + Refs: + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=618367 + https://bugs.launchpad.net/ubuntu/+source/distribute/+bug/725178 + https://bitbucket.org/ianb/pip/issue/104/pip-uninstall-on-ubuntu-linux + + """ + env = reset_env() + result = run_pip('install', 'INITools==0.2', expect_error=True) + + egg_info = os.path.join( + env.site_packages, "INITools-0.2-py%s.egg-info" % pyversion) + + # Debian only removes pyversion for global installs, not inside a venv + # so even if this test runs on a Debian/Ubuntu system with broken setuptools, + # since our test runs inside a venv we'll still have the normal .egg-info + assert egg_info in result.files_created, "Couldn't find %s" % egg_info + + # The Debian no-pyversion version of the .egg-info + mangled = os.path.join(env.site_packages, "INITools-0.2.egg-info") + assert mangled not in result.files_created, "Found unexpected %s" % mangled + + # Simulate a Debian install by copying the .egg-info to their name for it + full_egg_info = os.path.join(env.root_path, egg_info) + assert os.path.isdir(full_egg_info) + full_mangled = os.path.join(env.root_path, mangled) + os.renames(full_egg_info, full_mangled) + assert os.path.isdir(full_mangled) + + # Try the uninstall and verify that everything is removed. + result2 = run_pip("uninstall", "INITools", "-y") + assert_all_changes(result, result2, [env.venv/'build', 'cache'])