Blame SOURCES/BZ-1481220-print-disk-usage-on-yum-clean-all.patch

92fe97
diff --git a/cli.py b/cli.py
92fe97
index 5d9791bc..403a92f9 100755
92fe97
--- a/cli.py
92fe97
+++ b/cli.py
92fe97
@@ -29,6 +29,7 @@ import math
92fe97
 from optparse import OptionParser,OptionGroup,SUPPRESS_HELP
92fe97
 import rpm
92fe97
 import ctypes
92fe97
+import glob
92fe97
 
92fe97
 from weakref import proxy as weakref
92fe97
 
92fe97
@@ -1748,26 +1749,10 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
92fe97
         msg = self.fmtKeyValFill(_('Cleaning repos: '), 
92fe97
                         ' '.join([ x.id for x in self.repos.listEnabled()]))
92fe97
         self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
92fe97
+        msg = (_('Operating on %s (see CLEAN OPTIONS in yum(8) for details)')
92fe97
+               % self.conf.cachedir)
92fe97
+        self.verbose_logger.log(yum.logginglevels.DEBUG_3, msg)
92fe97
         if 'all' in userlist:
92fe97
-            self.verbose_logger.log(yum.logginglevels.INFO_2,
92fe97
-                _('Cleaning up everything'))
92fe97
-
92fe97
-            # Print a "maybe you want rm -rf" hint to compensate for the fact
92fe97
-            # that yum clean all is often misunderstood.  Don't do that,
92fe97
-            # however, if cachedir is non-default as we would have to replace
92fe97
-            # arbitrary yum vars with * and that could produce a harmful
92fe97
-            # command, e.g. for /mydata/$myvar we would say rm -rf /mydata/*
92fe97
-            cachedir = self.conf.cachedir
92fe97
-            if cachedir.startswith(('/var/cache/yum', '/var/tmp/yum-')):
92fe97
-                # Take just the first 3 path components
92fe97
-                rmdir = '/'.join(cachedir.split('/')[:4])
92fe97
-                self.verbose_logger.log(
92fe97
-                    yum.logginglevels.INFO_2,
92fe97
-                    _('Maybe you want: rm -rf %s, to also free up space taken '
92fe97
-                      'by orphaned data from disabled or removed repos'
92fe97
-                      % rmdir),
92fe97
-                )
92fe97
-
92fe97
             pkgcode, pkgresults = self.cleanPackages()
92fe97
             hdrcode, hdrresults = self.cleanHeaders()
92fe97
             xmlcode, xmlresults = self.cleanMetadata()
92fe97
@@ -1780,6 +1765,67 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
92fe97
                        rpmresults)
92fe97
             for msg in results:
92fe97
                 self.logger.debug(msg)
92fe97
+
92fe97
+            # Walk the cachedir, look for any leftovers and categorize them
92fe97
+            cacheglob = self.getCachedirGlob(['basearch', 'releasever'])
92fe97
+            paths = glob.glob(cacheglob + '/*')
92fe97
+            table = ([], [], [], [])  # (enabled, disabled, untracked, other)
92fe97
+            repos = self.repos.repos
92fe97
+            for path in paths:
92fe97
+                base = os.path.basename(path)
92fe97
+                if os.path.isdir(path):
92fe97
+                    # Repodir
92fe97
+                    if base not in repos:
92fe97
+                        col = 2
92fe97
+                    elif repos[base].enabled:
92fe97
+                        col = 0
92fe97
+                    else:
92fe97
+                        col = 1
92fe97
+                    # Recursively gather all files in this repodir
92fe97
+                    files = yum.misc.getFileList(path, '', [])
92fe97
+                else:
92fe97
+                    # Ordinary file (such as timedhosts)
92fe97
+                    col = 3
92fe97
+                    files = [path]
92fe97
+                usage = sum(map(os.path.getsize, files))
92fe97
+                if usage > 0:
92fe97
+                    table[col].append((usage, path))
92fe97
+
92fe97
+            # Print the table (verbose mode only)
92fe97
+            lines = [_('Disk usage of %s after cleanup:') % cacheglob]
92fe97
+            headers = ('enabled repos', 'disabled repos', 'untracked repos',
92fe97
+                       'other data')
92fe97
+            totals = [0, 0, 0, 0]
92fe97
+            for col, header in enumerate(headers):
92fe97
+                rows = []
92fe97
+                total = 0
92fe97
+                # Start with the biggest items
92fe97
+                for usage, path in sorted(table[col], key=lambda x:x[0],
92fe97
+                                          reverse=True):
92fe97
+                    rows.append('  %-5s  %s'
92fe97
+                                % (self.format_number(usage), path))
92fe97
+                    total += usage
92fe97
+                colon = ':' if rows else ''
92fe97
+                lines += ['%-5s  %s%s'
92fe97
+                          % (self.format_number(total), _(header), colon)]
92fe97
+                lines += rows
92fe97
+                totals[col] = total
92fe97
+            lines += [_('%-5s  total') % self.format_number(sum(totals))]
92fe97
+            msg = '\n'.join(lines)
92fe97
+            self.verbose_logger.log(yum.logginglevels.DEBUG_3, msg)
92fe97
+
92fe97
+            # Print a short hint for leftover repos specifically (non-verbose
92fe97
+            # mode only)
92fe97
+            total = sum(totals[:3])
92fe97
+            if self.conf.debuglevel == 6 or not total:
92fe97
+                return code, []
92fe97
+            total = self.format_number(total)
92fe97
+            if total[-1] == ' ':
92fe97
+                total = total[:-1] + 'bytes'
92fe97
+            msg = (_('Other repos take up %s of disk space '
92fe97
+                     '(use --verbose for details)') % total)
92fe97
+            self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
92fe97
+
92fe97
             return code, []
92fe97
             
92fe97
         if 'headers' in userlist:
92fe97
diff --git a/docs/yum.8 b/docs/yum.8
92fe97
index e3f1d32a..34a27f53 100644
92fe97
--- a/docs/yum.8
92fe97
+++ b/docs/yum.8
92fe97
@@ -1031,11 +1031,37 @@ Or:          \fByum list available 'foo*'\fP
92fe97
 .IP
92fe97
 .PP 
92fe97
 .SH "CLEAN OPTIONS"
92fe97
-The following are the ways which you can invoke \fByum\fP in clean
92fe97
-mode. Note that "all files" in the commands below means 
92fe97
-"all files in currently enabled repositories". 
92fe97
-If you want to also clean any (temporarily) disabled repositories you need to
92fe97
-use \fB\-\-enablerepo='*'\fP option.
92fe97
+The following are the ways which you can invoke \fByum\fP in clean mode.
92fe97
+
92fe97
+Note that these commands only operate on files in currently enabled
92fe97
+repositories.
92fe97
+If you use substitution variables (such as $releasever) in your \fBcachedir\fP
92fe97
+configuration, the operation is further restricted to the current values of
92fe97
+those variables.
92fe97
+
92fe97
+For fine-grained control over what is being cleaned, you can use
92fe97
+\fB\-\-enablerepo\fP, \fB\-\-disablerepo\fP and \fB\-\-releasever\fP as
92fe97
+desired.
92fe97
+Note, however, that you cannot use \fB\-\-releasever='*'\fP to do the cleaning
92fe97
+for all values previously used.
92fe97
+Also note that untracked (no longer configured) repositories will not be
92fe97
+automatically cleaned.
92fe97
+
92fe97
+To purge the entire cache in one go, the easiest way is to delete the files
92fe97
+manually.
92fe97
+Depending on your \fBcachedir\fP configuration, this usually means treating any
92fe97
+variables as shell wildcards and recursively removing matching directories.
92fe97
+For example, if your \fBcachedir\fP is /var/cache/yum/$basearch/$releasever,
92fe97
+then the whole /var/cache/yum directory has to be removed.
92fe97
+If you do this, \fByum\fP will rebuild the cache as required the next time it
92fe97
+is run (this may take a while).
92fe97
+
92fe97
+As a convenience, when you run \fByum clean all\fP, a recursive lookup will be
92fe97
+done to detect any repositories not cleaned due to the above restrictions.
92fe97
+If some are found, a message will be printed stating how much disk space they
92fe97
+occupy and thus how much you can reclaim by cleaning them.
92fe97
+If you also supply \fB\-\-verbose\fP, a more detailed breakdown will be
92fe97
+printed.
92fe97
 
92fe97
 .IP "\fByum clean expire-cache\fP"
92fe97
 Eliminate the local data saying when the metadata and mirrorlists were downloaded for each repo. This means yum will revalidate the cache for each repo. next time it is used. However if the cache is still valid, nothing significant was deleted.
92fe97
diff --git a/yum/__init__.py b/yum/__init__.py
92fe97
index a156a6a6..c6ced7d5 100644
92fe97
--- a/yum/__init__.py
92fe97
+++ b/yum/__init__.py
92fe97
@@ -2890,6 +2890,16 @@ much more problems).
92fe97
             filelist = misc.getFileList(cachedir, '', [])
92fe97
         return self._cleanFilelist('rpmdb', filelist)
92fe97
 
92fe97
+    def getCachedirGlob(self, dynvar):
92fe97
+        """Return a glob matching all dirs where yum stores cache files, based
92fe97
+        on cachedir and the given list of dynamic vars."""
92fe97
+        yumvar = self.conf.yumvar.copy()
92fe97
+        for d in dynvar:
92fe97
+            yumvar[d] = '*'
92fe97
+        instroot = config.varReplace(self.conf.installroot, self.conf.yumvar)
92fe97
+        cachedir = config.varReplace(self.conf._pristine_cachedir, yumvar)
92fe97
+        return (instroot + cachedir).replace('//', '/')
92fe97
+
92fe97
     def _cleanFiles(self, exts, pathattr, filetype):
92fe97
         filelist = []
92fe97
         for ext in exts:
92fe97
diff --git a/yum/config.py b/yum/config.py
92fe97
index 5eac325e..76128fa5 100644
92fe97
--- a/yum/config.py
92fe97
+++ b/yum/config.py
92fe97
@@ -945,6 +945,9 @@ class YumConf(StartupConf):
92fe97
 
92fe97
     _reposlist = []
92fe97
 
92fe97
+    # cachedir before variable substitutions
92fe97
+    _pristine_cachedir = None
92fe97
+
92fe97
     def dump(self):
92fe97
         """Return a string representing the values of all the
92fe97
         configuration options.
92fe97
@@ -1147,6 +1150,9 @@ def readMainConfig(startupconf):
92fe97
     yumconf = YumConf()
92fe97
     yumconf.populate(startupconf._parser, 'main')
92fe97
 
92fe97
+    # Store the original cachedir (for later reference in clean commands)
92fe97
+    yumconf._pristine_cachedir = yumconf.cachedir
92fe97
+
92fe97
     # Apply the installroot to directory options
92fe97
     def _apply_installroot(yumconf, option):
92fe97
         path = getattr(yumconf, option)