diff --git a/src/pip/_internal/commands/cache.py b/src/pip/_internal/commands/cache.py index c3b6c767444..5f53c7eea08 100644 --- a/src/pip/_internal/commands/cache.py +++ b/src/pip/_internal/commands/cache.py @@ -180,7 +180,20 @@ def remove_cache_items(self, options: Values, args: List[Any]) -> None: for filename in files: os.unlink(filename) logger.verbose("Removed %s", filename) + + dirs = filesystem.list_empty_subdirs(self._cache_dir(options, "http")) + \ + filesystem.list_empty_subdirs(self._cache_dir(options, "wheels")) + for dirname in dirs: + os.rmdir(dirname) + + # selfcheck.json is no longer used by pip. + selfcheck_json = self._cache_dir(options, "selfcheck.json") + if os.path.isfile(selfcheck_json): + os.remove(selfcheck_json) + logger.verbose("Removed legacy selfcheck.json file") + logger.info("Files removed: %s", len(files)) + logger.info("Empty directories removed: %s", len(dirs)) def purge_cache(self, options: Values, args: List[Any]) -> None: if args: diff --git a/src/pip/_internal/utils/filesystem.py b/src/pip/_internal/utils/filesystem.py index b7e6191abe6..34dea9b4793 100644 --- a/src/pip/_internal/utils/filesystem.py +++ b/src/pip/_internal/utils/filesystem.py @@ -180,3 +180,21 @@ def directory_size(path: str) -> Union[int, float]: def format_directory_size(path: str) -> str: return format_size(directory_size(path)) + + +def list_empty_subdirs(path): + # type: (str) -> List[str] + """Returns a list of absolute paths of empty directories beneath path. + """ + result = [] # type: List[str] + for root, dirs, _files in os.walk(path, topdown=False): + result.extend(os.path.join(root, d) for d in dirs) + return result + + +def remove_subdirs(path): + # type: (str) -> None + """Removes all subdirectories under path.""" + for entry in os.scandir(path): + if entry.is_dir(): + shutil.rmtree(entry.path)