diff --git a/src/pip/_internal/commands/cache.py b/src/pip/_internal/commands/cache.py index ec21be68fb5..23a00eea676 100644 --- a/src/pip/_internal/commands/cache.py +++ b/src/pip/_internal/commands/cache.py @@ -181,24 +181,34 @@ def remove_cache_items(self, options, args): files = self._find_wheels(options, args[0]) - # Only fetch http files if no specific pattern given - if args[0] == '*': - files += self._find_http_files(options) - if not files: raise CommandError('No matching packages') for filename in files: os.unlink(filename) logger.debug('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) + logger.info('Files removed: %s', len(files)) + logger.info('Empty directories removed: %s', len(dirs)) def purge_cache(self, options, args): # type: (Values, List[Any]) -> None if args: raise CommandError('Too many arguments') - return self.remove_cache_items(options, ['*']) + # Remove everything in the "http" and "wheels" cache directories. + filesystem.remove_subdirs(self._cache_dir(options, 'http')) + filesystem.remove_subdirs(self._cache_dir(options, 'wheels')) + + # 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) def _cache_dir(self, options, subdir): # type: (Values, str) -> str diff --git a/src/pip/_internal/utils/filesystem.py b/src/pip/_internal/utils/filesystem.py index 303243fd22f..c3fdb9bd01d 100644 --- a/src/pip/_internal/utils/filesystem.py +++ b/src/pip/_internal/utils/filesystem.py @@ -222,3 +222,21 @@ def directory_size(path): def format_directory_size(path): # type: (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)