From 5f414b846780c82b353b0ffeaaf65c90b426b67e Mon Sep 17 00:00:00 2001 From: Arcadiy Ivanov Date: Sat, 25 Sep 2021 18:02:19 -0400 Subject: [PATCH] Restore unintentionally-modified pre-``2186`` cleanup behaviors 1. Do not disturb platdir 2. Do delete a target directory on install if it is present and wasn't a part of the distro that could've been uninstalled fixes #2198 --- docs/changelog/2198.bugfix.rst | 1 + .../embed/via_app_data/pip_install/base.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 docs/changelog/2198.bugfix.rst diff --git a/docs/changelog/2198.bugfix.rst b/docs/changelog/2198.bugfix.rst new file mode 100644 index 000000000..cb1af3c2b --- /dev/null +++ b/docs/changelog/2198.bugfix.rst @@ -0,0 +1 @@ +Restore unintentionally-modified pre-``2186`` cleanup behaviors - by :user:`arcivanov` diff --git a/src/virtualenv/seed/embed/via_app_data/pip_install/base.py b/src/virtualenv/seed/embed/via_app_data/pip_install/base.py index 35e0ccae9..572453598 100644 --- a/src/virtualenv/seed/embed/via_app_data/pip_install/base.py +++ b/src/virtualenv/seed/embed/via_app_data/pip_install/base.py @@ -36,6 +36,8 @@ def install(self, version_info): # sync image for filename in self._image_dir.iterdir(): into = self._creator.purelib / filename.name + # The `into` path may still be dirty due to partial/broken installs - clean it up + self._delete_path(into) self._sync(filename, into) # generate console executables consoles = set() @@ -149,12 +151,21 @@ def _create_console_entry_point(self, name, value, to_folder, version_info): def _uninstall_previous_version(self): dist_name = self._dist_info.stem.split("-")[0] - in_folders = chain.from_iterable([i.iterdir() for i in {self._creator.purelib, self._creator.platlib}]) + # Only uninstall purelib as it's the only one that VirtualEnv installs into + in_folders = chain.from_iterable([i.iterdir() for i in {self._creator.purelib}]) paths = (p for p in in_folders if p.stem.split("-")[0] == dist_name and p.suffix == ".dist-info" and p.is_dir()) existing_dist = next(paths, None) if existing_dist is not None: self._uninstall_dist(existing_dist) + @staticmethod + def _delete_path(path): + if path.exists(): + if path.is_dir() and not path.is_symlink(): + safe_delete(path) + else: + path.unlink() + @staticmethod def _uninstall_dist(dist): dist_base = dist.parent @@ -171,11 +182,7 @@ def _uninstall_dist(dist): paths.add(path) for path in sorted(paths): # actually remove stuff in a stable order - if path.exists(): - if path.is_dir() and not path.is_symlink(): - safe_delete(path) - else: - path.unlink() + PipInstall._delete_path(path) def clear(self): if self._image_dir.exists():