Blame SOURCES/BZ-1053289-misc-perf+UI+simple-bug+docs-fixes.patch

1f1d7d
commit 1b14f27c1ff77ca3fb0af7dccc890a6c8bf36d42
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Wed Nov 6 14:42:59 2013 +0100
1f1d7d
1f1d7d
    docs: Suggest "--" when using "-<pkg>" to exclude packages. BZ 1026598
1f1d7d
1f1d7d
diff --git a/docs/yum.8 b/docs/yum.8
1f1d7d
index e42bf49..2cbdf72 100644
1f1d7d
--- a/docs/yum.8
1f1d7d
+++ b/docs/yum.8
1f1d7d
@@ -103,9 +103,13 @@ satisfied\&.  (See \fBSpecifying package names\fP for more information)
1f1d7d
 If no package matches the given package name(s), they are assumed to be a shell 
1f1d7d
 glob and any matches are then installed\&. If the name starts with @^ then it
1f1d7d
 is treated as an environment group (group install @^foo), an @ character and
1f1d7d
-it's treated as a group (plain group install)\&. If the name starts with
1f1d7d
-a - character, then a search is done within
1f1d7d
-the transaction and any matches are removed. If the name is a file, then install works
1f1d7d
+it's treated as a group (plain group install)\&.
1f1d7d
+
1f1d7d
+If the name starts with a "-" character, then a search is done within the
1f1d7d
+transaction and any matches are removed. Note that Yum options use the same
1f1d7d
+syntax and it may be necessary to use "--" to resolve any possible conflicts.
1f1d7d
+
1f1d7d
+If the name is a file, then install works
1f1d7d
 like localinstall\&. If the name doesn't match a package, then package
1f1d7d
 "provides" are searched (e.g. "_sqlitecache.so()(64bit)") as are
1f1d7d
 filelists (Eg. "/usr/bin/yum"). Also note that for filelists, wildcards will
1f1d7d
commit d78b1258ec9fd8ed312c4fede9a68db1623bb124
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Mon Nov 11 08:58:52 2013 +0100
1f1d7d
1f1d7d
    docs: exactarch option is removed.
1f1d7d
1f1d7d
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
1f1d7d
index 5d8578d..53cef2e 100644
1f1d7d
--- a/docs/yum.conf.5
1f1d7d
+++ b/docs/yum.conf.5
1f1d7d
@@ -158,12 +158,6 @@ Can be disabled using --disableexcludes.
1f1d7d
 Command-line option: \fB\-x\fP
1f1d7d
 
1f1d7d
 .IP
1f1d7d
-\fBexactarch\fR
1f1d7d
-Either `1' or `0'. Set to `1' to make yum update only update the architectures
1f1d7d
-of packages that you have installed. ie: with this enabled yum will not install
1f1d7d
-an i686 package to update an i386 package. Default is `1'.
1f1d7d
-
1f1d7d
-.IP
1f1d7d
 \fBinstallonlypkgs \fR
1f1d7d
 List of package provides that should only ever be installed, never updated.
1f1d7d
 Kernels in particular fall into this category. Defaults to kernel,
1f1d7d
commit d6378e152ad8751b5d135d7e8aba49e16f8a374a
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Mon Nov 18 15:57:53 2013 -0500
1f1d7d
1f1d7d
    Add distupgrade command as alias for distro-sync, to be compat. with zypper.
1f1d7d
1f1d7d
diff --git a/yumcommands.py b/yumcommands.py
1f1d7d
index 1530161..a542ade 100644
1f1d7d
--- a/yumcommands.py
1f1d7d
+++ b/yumcommands.py
1f1d7d
@@ -506,7 +506,7 @@ class DistroSyncCommand(YumCommand):
1f1d7d
 
1f1d7d
         :return: a list containing the names of this command
1f1d7d
         """
1f1d7d
-        return ['distribution-synchronization', 'distro-sync']
1f1d7d
+        return ['distribution-synchronization', 'distro-sync', 'distupgrade']
1f1d7d
 
1f1d7d
     def getUsage(self):
1f1d7d
         """Return a usage string for this command.
1f1d7d
commit aae263a57b9e1695d54d463df36f191f3facfb48
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Mon Nov 18 15:58:19 2013 -0500
1f1d7d
1f1d7d
    Add upgrade_group_objects_upgrade config. so people can turn it off.
1f1d7d
1f1d7d
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
1f1d7d
index 53cef2e..b93ad32 100644
1f1d7d
--- a/docs/yum.conf.5
1f1d7d
+++ b/docs/yum.conf.5
1f1d7d
@@ -270,6 +270,12 @@ packages for all groups).
1f1d7d
 Default is: compat
1f1d7d
 
1f1d7d
 .IP
1f1d7d
+\fBupgrade_group_objects_upgrade\fR
1f1d7d
+Either `0' or `1'. Set this to `0' to disable the automatic running of
1f1d7d
+"group upgrade" when running the "upgrade" command, and group_command is set to
1f1d7d
+"objects". Default is `1' (perform the check).
1f1d7d
+
1f1d7d
+.IP
1f1d7d
 \fBinstallroot \fR
1f1d7d
 Specifies an alternative installroot, relative to which all packages will be
1f1d7d
 installed. 
1f1d7d
diff --git a/yum/__init__.py b/yum/__init__.py
1f1d7d
index 6a6f1fc..6bd5962 100644
1f1d7d
--- a/yum/__init__.py
1f1d7d
+++ b/yum/__init__.py
1f1d7d
@@ -5000,7 +5000,8 @@ much more problems).
1f1d7d
                     tx_return.extend(self.update(po=new))
1f1d7d
 
1f1d7d
             # Upgrade the installed groups, as part of generic "yum upgrade"
1f1d7d
-            if self.conf.group_command == 'objects':
1f1d7d
+            if (self.conf.group_command == 'objects' and
1f1d7d
+                self.conf.upgrade_group_objects_upgrade):
1f1d7d
                 for ievgrp in self.igroups.environments:
1f1d7d
                     tx_return.extend(self._at_groupupgrade('@^' + ievgrp))
1f1d7d
                 for igrp in self.igroups.groups:
1f1d7d
diff --git a/yum/config.py b/yum/config.py
1f1d7d
index ecb8490..c43c41b 100644
1f1d7d
--- a/yum/config.py
1f1d7d
+++ b/yum/config.py
1f1d7d
@@ -792,6 +792,7 @@ class YumConf(StartupConf):
1f1d7d
     group_package_types = ListOption(['mandatory', 'default'])
1f1d7d
     group_command = SelectionOption(__group_command_default__,
1f1d7d
                                     ('compat', 'objects', 'simple'))
1f1d7d
+    upgrade_group_objects_upgrade = BoolOption(True)
1f1d7d
     
1f1d7d
     timeout = FloatOption(30.0) # FIXME: Should use variation of SecondsOption
1f1d7d
 
1f1d7d
commit 944f42f65e8a2d4bf0928e85850bf81e2876e233
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Mon Nov 18 16:05:33 2013 -0500
1f1d7d
1f1d7d
    Add autocheck_running_kernel config. so people can turn it off.
1f1d7d
1f1d7d
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
1f1d7d
index b93ad32..6fae41d 100644
1f1d7d
--- a/docs/yum.conf.5
1f1d7d
+++ b/docs/yum.conf.5
1f1d7d
@@ -273,7 +273,14 @@ Default is: compat
1f1d7d
 \fBupgrade_group_objects_upgrade\fR
1f1d7d
 Either `0' or `1'. Set this to `0' to disable the automatic running of
1f1d7d
 "group upgrade" when running the "upgrade" command, and group_command is set to
1f1d7d
-"objects". Default is `1' (perform the check).
1f1d7d
+"objects". Default is `1' (perform the operation).
1f1d7d
+
1f1d7d
+.IP
1f1d7d
+\fBautocheck_running_kernel\fR
1f1d7d
+Either `0' or `1'. Set this to `0' to disable the automatic checking of the
1f1d7d
+running kernel against updateinfo ("yum updateinfo check-running-kernel"), in
1f1d7d
+the "check-update" and "updateinfo summary" commands.
1f1d7d
+Default is `1' (perform the check).
1f1d7d
 
1f1d7d
 .IP
1f1d7d
 \fBinstallroot \fR
1f1d7d
diff --git a/yumcommands.py b/yumcommands.py
1f1d7d
index a542ade..2b1c9c0 100644
1f1d7d
--- a/yumcommands.py
1f1d7d
+++ b/yumcommands.py
1f1d7d
@@ -1609,7 +1609,8 @@ class CheckUpdateCommand(YumCommand):
1f1d7d
                 result = 100
1f1d7d
 
1f1d7d
             # Add check_running_kernel call, if updateinfo is available.
1f1d7d
-            if updateinfo._repos_downloaded(base.repos.listEnabled()):
1f1d7d
+            if (base.conf.autocheck_running_kernel and
1f1d7d
+                updateinfo._repos_downloaded(base.repos.listEnabled())):
1f1d7d
                 def _msg(x):
1f1d7d
                     base.verbose_logger.info("%s", x)
1f1d7d
                 updateinfo._check_running_kernel(base, base.upinfo, _msg)
1f1d7d
@@ -3850,7 +3851,8 @@ class UpdateinfoCommand(YumCommand):
1f1d7d
             if maxsize < size:
1f1d7d
                 maxsize = size
1f1d7d
         if not maxsize:
1f1d7d
-            _upi._check_running_kernel(base, md_info, _msg)
1f1d7d
+            if base.conf.autocheck_running_kernel:
1f1d7d
+                _upi._check_running_kernel(base, md_info, _msg)
1f1d7d
             return
1f1d7d
 
1f1d7d
         outT = {'newpackage' : 'New Package',
1f1d7d
@@ -3880,7 +3882,8 @@ class UpdateinfoCommand(YumCommand):
1f1d7d
                 for sn in sorted(sev_counts, key=_sev_sort_key):
1f1d7d
                     args = (maxsize, sev_counts[sn],sn or '?', outT['security'])
1f1d7d
                     print "        %*u %s %s notice(s)" % args
1f1d7d
-        _upi._check_running_kernel(base, md_info, _msg)
1f1d7d
+        if base.conf.autocheck_running_kernel:
1f1d7d
+            _upi._check_running_kernel(base, md_info, _msg)
1f1d7d
         self.show_pkg_info_done = {}
1f1d7d
 
1f1d7d
     def _get_new_pkgs(self, md_info):
1f1d7d
commit ecf31eee67bd3c5668f8b244c086365ebc510c05
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Tue Nov 19 11:57:13 2013 -0500
1f1d7d
1f1d7d
    Actually add the config. for autocheck_running_kernel.
1f1d7d
1f1d7d
diff --git a/yum/config.py b/yum/config.py
1f1d7d
index c43c41b..45abfd6 100644
1f1d7d
--- a/yum/config.py
1f1d7d
+++ b/yum/config.py
1f1d7d
@@ -898,6 +898,8 @@ class YumConf(StartupConf):
1f1d7d
 
1f1d7d
     depsolve_loop_limit = PositiveIntOption(100, names_of_0=["<forever>"])
1f1d7d
 
1f1d7d
+    autocheck_running_kernel = BoolOption(True)
1f1d7d
+
1f1d7d
     _reposlist = []
1f1d7d
 
1f1d7d
     def dump(self):
1f1d7d
commit 977a79be0f79069febde1ad81d8c71d240d08605
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Tue Nov 19 14:28:03 2013 -0500
1f1d7d
1f1d7d
    Add deltarpm_metadata_percentage config. so people can configure MD downloads.
1f1d7d
1f1d7d
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
1f1d7d
index 6fae41d..4e79298 100644
1f1d7d
--- a/docs/yum.conf.5
1f1d7d
+++ b/docs/yum.conf.5
1f1d7d
@@ -420,6 +420,15 @@ Use `0' to turn off delta rpm processing. Local repositories (with file://
1f1d7d
 baseurl) have delta rpms turned off by default.
1f1d7d
 
1f1d7d
 .IP
1f1d7d
+\fBdeltarpm_metadata_percentage\fR
1f1d7d
+When the relative size of deltarpm metadata vs pkgs is larger than this,
1f1d7d
+deltarpm metadata is not downloaded from the repo.
1f1d7d
+Default value is 100 (Deltarpm metadata must be smaller than the packages from
1f1d7d
+the repo). Note that you can give values over 100, so 200 means that the
1f1d7d
+metadata is required to be half the size of the packages.
1f1d7d
+Use `0' to turn off this check, and always download metadata.
1f1d7d
+
1f1d7d
+.IP
1f1d7d
 \fBsslcacert \fR
1f1d7d
 Path to the directory containing the databases of the certificate authorities
1f1d7d
 yum should use to verify SSL certificates. Defaults to none - uses system
1f1d7d
@@ -1043,6 +1052,11 @@ Overrides the \fBdeltarpm_percentage\fR option from the [main] section
1f1d7d
 for this repository.
1f1d7d
 
1f1d7d
 .IP
1f1d7d
+\fBdeltarpm_metadata_percentage\fR
1f1d7d
+Overrides the \fBdeltarpm_metadata_percentage\fR option from the [main] section
1f1d7d
+for this repository.
1f1d7d
+
1f1d7d
+.IP
1f1d7d
 \fBsslcacert \fR
1f1d7d
 Overrides the \fBsslcacert\fR option from the [main] section for this
1f1d7d
 repository.
1f1d7d
diff --git a/yum/config.py b/yum/config.py
1f1d7d
index cdad4bc..b891f82 100644
1f1d7d
--- a/yum/config.py
1f1d7d
+++ b/yum/config.py
1f1d7d
@@ -805,6 +805,7 @@ class YumConf(StartupConf):
1f1d7d
     max_connections = IntOption(0, range_min=0)
1f1d7d
     deltarpm = IntOption(2, range_min=-16, range_max=128)
1f1d7d
     deltarpm_percentage = IntOption(75, range_min=0, range_max=100)
1f1d7d
+    deltarpm_metadata_percentage = IntOption(100, range_min=0)
1f1d7d
 
1f1d7d
     http_caching = SelectionOption('all', ('none', 'packages', 'all'))
1f1d7d
     metadata_expire = SecondsOption(60 * 60 * 6) # Time in seconds (6h).
1f1d7d
@@ -977,7 +978,12 @@ class RepoConf(BaseConfig):
1f1d7d
     throttle = Inherit(YumConf.throttle)
1f1d7d
     timeout = Inherit(YumConf.timeout)
1f1d7d
     ip_resolve = Inherit(YumConf.ip_resolve)
1f1d7d
+    #  This isn't inherited so that we can automatically disable file:// _only_
1f1d7d
+    # repos. if they haven't set an explicit deltarpm_percentage for the repo.
1f1d7d
     deltarpm_percentage = IntOption(None, range_min=0, range_max=100)
1f1d7d
+    #  Rely on the above config. to do automatic disabling, and thus. no hack
1f1d7d
+    # needed here.
1f1d7d
+    deltarpm_metadata_percentage = Inherit(YumConf.deltarpm_metadata_percentage)
1f1d7d
 
1f1d7d
     http_caching = Inherit(YumConf.http_caching)
1f1d7d
     metadata_expire = Inherit(YumConf.metadata_expire)
1f1d7d
diff --git a/yum/drpm.py b/yum/drpm.py
1f1d7d
index 1fd7a11..42bf70e 100644
1f1d7d
--- a/yum/drpm.py
1f1d7d
+++ b/yum/drpm.py
1f1d7d
@@ -168,8 +168,13 @@ class DeltaInfo:
1f1d7d
                 self.verbose_logger.info(_('No Presto metadata available for %s'), repo)
1f1d7d
                 continue
1f1d7d
             path = repo.cachedir +'/'+ os.path.basename(data.location[1])
1f1d7d
-            if not os.path.exists(path) and int(data.size) > reposize[repo]:
1f1d7d
-                self.verbose_logger.info(_('Not downloading Presto metadata for %s'), repo)
1f1d7d
+            perc = repo.deltarpm_metadata_percentage
1f1d7d
+            data_size = int(data.size) * (perc / 100.0)
1f1d7d
+            if perc and not os.path.exists(path) and data_size > reposize[repo]:
1f1d7d
+                msg = _('Not downloading deltainfo for %s, MD is %s and rpms are %s')
1f1d7d
+                self.verbose_logger.info(msg, repo,
1f1d7d
+                                         progress.format_number(data_size),
1f1d7d
+                                         progress.format_number(reposize[repo]))
1f1d7d
                 continue
1f1d7d
 
1f1d7d
             def failfunc(e, name=name, repo=repo):
1f1d7d
commit b70d74e732f360a0a31cfcb9174982fb65369c54
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Wed Nov 27 14:00:32 2013 -0500
1f1d7d
1f1d7d
    Add check_config_file_age, so we can turn that off for rhsm repos. BZ 1035440.
1f1d7d
1f1d7d
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
1f1d7d
index 4e79298..da13dc8 100644
1f1d7d
--- a/docs/yum.conf.5
1f1d7d
+++ b/docs/yum.conf.5
1f1d7d
@@ -290,6 +290,18 @@ installed.
1f1d7d
 Command-line option: \fB\-\-installroot\fP
1f1d7d
 
1f1d7d
 .IP
1f1d7d
+\fBconfig_file_path \fR
1f1d7d
+Specifies the path to main the configuration file.
1f1d7d
+Default is /etc/yum/yum.conf.
1f1d7d
+
1f1d7d
+.IP
1f1d7d
+\fBcheck_config_file_age \fR
1f1d7d
+Either `0' or `1'. Specifies whether yum should auto metadata expire repos. 
1f1d7d
+that are older than any of the configuration files that led to them (usually 
1f1d7d
+the yum.conf file and the foo.repo file).
1f1d7d
+Default is `1' (perform the check).
1f1d7d
+
1f1d7d
+.IP
1f1d7d
 \fBdistroverpkg\fR
1f1d7d
 The package used by yum to determine the "version" of the distribution, this
1f1d7d
 sets $releasever for use in config. files. This
1f1d7d
diff --git a/yum/config.py b/yum/config.py
1f1d7d
index ea6c1ac..c38d574 100644
1f1d7d
--- a/yum/config.py
1f1d7d
+++ b/yum/config.py
1f1d7d
@@ -901,6 +901,8 @@ class YumConf(StartupConf):
1f1d7d
 
1f1d7d
     autocheck_running_kernel = BoolOption(True)
1f1d7d
 
1f1d7d
+    check_config_file_age = BoolOption(True)
1f1d7d
+
1f1d7d
     _reposlist = []
1f1d7d
 
1f1d7d
     def dump(self):
1f1d7d
@@ -1005,6 +1007,9 @@ class RepoConf(BaseConfig):
1f1d7d
     async = BoolOption(True)
1f1d7d
 
1f1d7d
     ui_repoid_vars = Inherit(YumConf.ui_repoid_vars)
1f1d7d
+
1f1d7d
+    check_config_file_age = Inherit(YumConf.check_config_file_age)
1f1d7d
+
1f1d7d
     
1f1d7d
 class VersionGroupConf(BaseConfig):
1f1d7d
     """Option definitions for version groups."""
1f1d7d
diff --git a/yum/yumRepo.py b/yum/yumRepo.py
1f1d7d
index 67bb7c9..35359e2 100644
1f1d7d
--- a/yum/yumRepo.py
1f1d7d
+++ b/yum/yumRepo.py
1f1d7d
@@ -1170,6 +1170,9 @@ Insufficient space in download directory %s
1f1d7d
             elif cookie_info[8] > time.time():
1f1d7d
                 val = False
1f1d7d
 
1f1d7d
+            if not self.check_config_file_age:
1f1d7d
+                return val
1f1d7d
+
1f1d7d
             # make sure none of our config files for this repo are newer than
1f1d7d
             # us
1f1d7d
             if cookie_info[8] < int(self.repo_config_age):
1f1d7d
commit a88b3ee54bd6f3b7c6855e0595d443fa6a453798
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Sun Dec 1 19:41:18 2013 -0500
1f1d7d
1f1d7d
    Better doc. comment for re_primary_filename().
1f1d7d
1f1d7d
diff --git a/yum/misc.py b/yum/misc.py
1f1d7d
index b817cc0..f551102 100644
1f1d7d
--- a/yum/misc.py
1f1d7d
+++ b/yum/misc.py
1f1d7d
@@ -134,8 +134,9 @@ def re_filename(s):
1f1d7d
 
1f1d7d
 def re_primary_filename(filename):
1f1d7d
     """ Tests if a filename string, can be matched against just primary.
1f1d7d
-        Note that this can produce false negatives (but not false
1f1d7d
-        positives). Note that this is a superset of re_primary_dirname(). """
1f1d7d
+        Note that this can produce false negatives (Eg. /b?n/zsh) but not false
1f1d7d
+        positives (because the former is a perf hit, and the later is a
1f1d7d
+        failure). Note that this is a superset of re_primary_dirname(). """
1f1d7d
     if re_primary_dirname(filename):
1f1d7d
         return True
1f1d7d
     if filename == '/usr/lib/sendmail':
1f1d7d
commit 32e2da9c3e068722f82ae346c761a55ac9d969c9
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Thu Dec 5 16:31:02 2013 -0500
1f1d7d
1f1d7d
    Fix needTs check with repo-pkgs list/info.
1f1d7d
1f1d7d
diff --git a/yumcommands.py b/yumcommands.py
1f1d7d
index 2b1c9c0..db1b9d3 100644
1f1d7d
--- a/yumcommands.py
1f1d7d
+++ b/yumcommands.py
1f1d7d
@@ -3712,7 +3712,7 @@ class RepoPkgsCommand(YumCommand):
1f1d7d
         if len(extcmds) > 1:
1f1d7d
             cmd = extcmds[1]
1f1d7d
         if cmd in ('info', 'list'):
1f1d7d
-            return InfoCommand().cacheRequirement(base, cmd, extcmds[2:])
1f1d7d
+            return InfoCommand().needTs(base, cmd, extcmds[2:])
1f1d7d
 
1f1d7d
         return True
1f1d7d
 
1f1d7d
commit 88a93e8de73066a796bbb698c5c6f59b66174448
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Thu Dec 5 16:36:54 2013 -0500
1f1d7d
1f1d7d
    Add command variation aliases to check-update.
1f1d7d
1f1d7d
diff --git a/yumcommands.py b/yumcommands.py
1f1d7d
index db1b9d3..3412a60 100644
1f1d7d
--- a/yumcommands.py
1f1d7d
+++ b/yumcommands.py
1f1d7d
@@ -1531,7 +1531,8 @@ class CheckUpdateCommand(YumCommand):
1f1d7d
 
1f1d7d
         :return: a list containing the names of this command
1f1d7d
         """
1f1d7d
-        return ['check-update']
1f1d7d
+        return ['check-update',  'check-updates',
1f1d7d
+                'check-upgrade', 'check-upgrades']
1f1d7d
 
1f1d7d
     def getUsage(self):
1f1d7d
         """Return a usage string for this command.
1f1d7d
commit ade4e34d1578ad4046b5efe3c3a97ca6bc1791f5
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Thu Dec 5 16:37:07 2013 -0500
1f1d7d
1f1d7d
    Add check-update sub-command to repo-pkgs.
1f1d7d
1f1d7d
diff --git a/docs/yum.8 b/docs/yum.8
1f1d7d
index 0914765..dff88af 100644
1f1d7d
--- a/docs/yum.8
1f1d7d
+++ b/docs/yum.8
1f1d7d
@@ -423,6 +423,9 @@ only shows packages from the given repository.
1f1d7d
 "repository\-packages <repo> info" - Works like the "yum info" command, but
1f1d7d
 only shows packages from the given repository.
1f1d7d
 
1f1d7d
+"repository\-packages <repo> check-update" - Works like the
1f1d7d
+"yum check-update" command, but only shows packages from the given repository.
1f1d7d
+
1f1d7d
 "repository\-packages <repo> install" - Install all of the packages in the
1f1d7d
 repository, basically the same as: yum install $(repoquery --repoid=<repo> -a).
1f1d7d
 Specific packages/wildcards can be specified.
1f1d7d
diff --git a/yumcommands.py b/yumcommands.py
1f1d7d
index 3412a60..b346128 100644
1f1d7d
--- a/yumcommands.py
1f1d7d
+++ b/yumcommands.py
1f1d7d
@@ -1558,7 +1558,7 @@ class CheckUpdateCommand(YumCommand):
1f1d7d
         """
1f1d7d
         checkEnabledRepo(base)
1f1d7d
 
1f1d7d
-    def doCommand(self, base, basecmd, extcmds):
1f1d7d
+    def doCommand(self, base, basecmd, extcmds, repoid=None):
1f1d7d
         """Execute this command.
1f1d7d
 
1f1d7d
         :param base: a :class:`yum.Yumbase` object
1f1d7d
@@ -1577,10 +1577,10 @@ class CheckUpdateCommand(YumCommand):
1f1d7d
         base.extcmds.insert(0, 'updates')
1f1d7d
         result = 0
1f1d7d
         if True:
1f1d7d
-            ypl = base.returnPkgLists(extcmds)
1f1d7d
+            ypl = base.returnPkgLists(extcmds, repoid=repoid)
1f1d7d
             if (base.conf.obsoletes or
1f1d7d
                 base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)):
1f1d7d
-                typl = base.returnPkgLists(obscmds)
1f1d7d
+                typl = base.returnPkgLists(obscmds, repoid=repoid)
1f1d7d
                 ypl.obsoletes = typl.obsoletes
1f1d7d
                 ypl.obsoletesTuples = typl.obsoletesTuples
1f1d7d
 
1f1d7d
@@ -1606,7 +1606,7 @@ class CheckUpdateCommand(YumCommand):
1f1d7d
                 for obtup in sorted(ypl.obsoletesTuples,
1f1d7d
                                     key=operator.itemgetter(0)):
1f1d7d
                     base.updatesObsoletesList(obtup, 'obsoletes',
1f1d7d
-                                              columns=columns)
1f1d7d
+                                              columns=columns, repoid=repoid)
1f1d7d
                 result = 100
1f1d7d
 
1f1d7d
             # Add check_running_kernel call, if updateinfo is available.
1f1d7d
@@ -3516,6 +3516,9 @@ class RepoPkgsCommand(YumCommand):
1f1d7d
                  'remove-or-distribution-synchronization' : 'remove-or-sync',
1f1d7d
                  'upgrade' : 'update', # Hack, but meh.
1f1d7d
                  'upgrade-to' : 'update-to', # Hack, but meh.
1f1d7d
+                 'check-upgrade' : 'check-update', # Hack, but meh.
1f1d7d
+                 'check-upgrades' : 'check-update', # Hack, but meh.
1f1d7d
+                 'check-updates' : 'check-update', # Hack, but meh.
1f1d7d
                  }
1f1d7d
         cmd = remap.get(cmd, cmd)
1f1d7d
 
1f1d7d
@@ -3524,6 +3527,8 @@ class RepoPkgsCommand(YumCommand):
1f1d7d
             return ListCommand().doCommand(base, cmd, args, repoid=repoid)
1f1d7d
         elif cmd == 'info':
1f1d7d
             return InfoCommand().doCommand(base, cmd, args, repoid=repoid)
1f1d7d
+        elif cmd == 'check-update':
1f1d7d
+            return CheckUpdateCommand().doCommand(base, cmd, args,repoid=repoid)
1f1d7d
 
1f1d7d
         elif cmd == 'install': # install is simpler version of installPkgs...
1f1d7d
             for arg in args:
1f1d7d
@@ -3730,6 +3735,9 @@ class RepoPkgsCommand(YumCommand):
1f1d7d
             cmd = extcmds[1]
1f1d7d
         if cmd in ('info', 'list'):
1f1d7d
             return InfoCommand().cacheRequirement(base, cmd, extcmds[2:])
1f1d7d
+        if cmd in ('check-update', 'check-upgrade',
1f1d7d
+                   'check-updates', 'check-upgrades'):
1f1d7d
+            return CheckUpdateCommand().cacheRequirement(base, cmd, extcmds[2:])
1f1d7d
         return 'write'
1f1d7d
 
1f1d7d
 # Using this a lot, so make it easier...
1f1d7d
commit 84876b27c49056a8d86112020a9ec4ec7a13e852
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Fri Dec 6 11:04:31 2013 -0500
1f1d7d
1f1d7d
     Fix cacheReq manipulation. BZ 1039028.
1f1d7d
    
1f1d7d
     Only look at enabled repos. for cacheReq cookie comparisons. BZ 1039028.
1f1d7d
    
1f1d7d
     Move all the cacheReq repo. setting into a function.
1f1d7d
    
1f1d7d
     Use the function everywhere so we don't overwrite the manipulated value with
1f1d7d
    the generic value.
1f1d7d
1f1d7d
diff --git a/cli.py b/cli.py
1f1d7d
index 7f6643f..180ba99 100755
1f1d7d
--- a/cli.py
1f1d7d
+++ b/cli.py
1f1d7d
@@ -390,6 +390,13 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
1f1d7d
                                   self.basecmd, sys.argv[0])
1f1d7d
             raise CliError
1f1d7d
     
1f1d7d
+        self._set_repos_cache_req()
1f1d7d
+
1f1d7d
+        self.yum_cli_commands[self.basecmd].doCheck(self, self.basecmd, self.extcmds)
1f1d7d
+
1f1d7d
+    def _set_repos_cache_req(self, warning=True):
1f1d7d
+        """ Set the cacheReq attribute from the commands to the repos. """
1f1d7d
+
1f1d7d
         cmd = self.yum_cli_commands[self.basecmd]
1f1d7d
         cacheReq = 'write'
1f1d7d
         if hasattr(cmd, 'cacheRequirement'):
1f1d7d
@@ -404,7 +411,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
1f1d7d
         # they are _really_ old.
1f1d7d
         ts_min = None
1f1d7d
         ts_max = None
1f1d7d
-        for repo in self.repos.sort():
1f1d7d
+        for repo in self.repos.listEnabled():
1f1d7d
             if not os.path.exists(repo.metadata_cookie):
1f1d7d
                 ts_min = None
1f1d7d
                 break
1f1d7d
@@ -428,14 +435,12 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
1f1d7d
 
1f1d7d
         if not ts_min:
1f1d7d
             cacheReq = 'write'
1f1d7d
-        elif (time.time() - ts_max) > (60 * 60 * 24 * 14):
1f1d7d
+        elif warning and (time.time() - ts_max) > (60 * 60 * 24 * 14):
1f1d7d
             self.logger.warning(_("Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast"))
1f1d7d
 
1f1d7d
         for repo in self.repos.sort():
1f1d7d
             repo._metadata_cache_req = cacheReq
1f1d7d
 
1f1d7d
-        self.yum_cli_commands[self.basecmd].doCheck(self, self.basecmd, self.extcmds)
1f1d7d
-
1f1d7d
     def _shell_history_write(self):
1f1d7d
         if not hasattr(self, '_shell_history_cmds'):
1f1d7d
             return
1f1d7d
@@ -560,11 +565,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
1f1d7d
 
1f1d7d
         #  This should already have been done at doCheck() time, but just in
1f1d7d
         # case repos. got added or something do it again.
1f1d7d
-        cacheReq = 'write'
1f1d7d
-        if hasattr(cmd, 'cacheRequirement'):
1f1d7d
-            cacheReq = cmd.cacheRequirement(self, self.basecmd, self.extcmds)
1f1d7d
-        for repo in self.repos.sort():
1f1d7d
-            repo._metadata_cache_req = cacheReq
1f1d7d
+        self._set_repos_cache_req(warning=False)
1f1d7d
 
1f1d7d
         return self.yum_cli_commands[self.basecmd].doCommand(self, self.basecmd, self.extcmds)
1f1d7d
 
1f1d7d
commit 8c4c81b8f958ffaf6f3cf710225eee48426ce767
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Fri Dec 6 11:11:05 2013 -0500
1f1d7d
1f1d7d
    Add comment about magic float timestamp compat. problem.
1f1d7d
1f1d7d
diff --git a/yum/repoMDObject.py b/yum/repoMDObject.py
1f1d7d
index 97e6797..c2a349e 100755
1f1d7d
--- a/yum/repoMDObject.py
1f1d7d
+++ b/yum/repoMDObject.py
1f1d7d
@@ -172,6 +172,9 @@ class RepoMD:
1f1d7d
                         thisdata = old
1f1d7d
                     self.repoData[thisdata.type] = thisdata
1f1d7d
                     try:
1f1d7d
+                        # NOTE: This will fail on float timestamps, this is
1f1d7d
+                        # required for compatability. Fix is to not generate
1f1d7d
+                        # float timestamps in repomd.xml.
1f1d7d
                         nts = int(thisdata.timestamp)
1f1d7d
                         if nts > self.timestamp: # max() not in old python
1f1d7d
                             self.timestamp = nts
1f1d7d
commit 833be09639371c9e0c88bc125e40ef682bbc4a30
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Mon Dec 9 17:58:25 2013 +0100
1f1d7d
1f1d7d
    Align the time formatting in the "Total" output with urlgrabber.progress
1f1d7d
1f1d7d
diff --git a/output.py b/output.py
1f1d7d
index e42702e..041910c 100755
1f1d7d
--- a/output.py
1f1d7d
+++ b/output.py
1f1d7d
@@ -1837,7 +1837,7 @@ to exit.
1f1d7d
         if dl_time <= 0: # This stops divide by zero, among other problems
1f1d7d
             dl_time = 0.01
1f1d7d
         ui_size = tl.add(' | %5sB' % self.format_number(remote_size))
1f1d7d
-        ui_time = tl.add(' %9s' % self.format_time(dl_time))
1f1d7d
+        ui_time = tl.add('  %s' % self.format_time(dl_time, tl._llen > 80))
1f1d7d
         ui_end  = tl.add(' ' * 5)
1f1d7d
         ui_bs   = tl.add(' %5sB/s' % self.format_number(remote_size / dl_time))
1f1d7d
         msg = "%s%s%s%s%s" % (utf8_width_fill(_("Total"), tl.rest(), tl.rest()),
1f1d7d
commit e1db5d6a94dee861d1fa0552277bc03f037c6e3a
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Tue Dec 10 08:47:48 2013 +0100
1f1d7d
1f1d7d
    yum-cron: stderr/email: no output if no messages
1f1d7d
1f1d7d
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
1f1d7d
index dd0a4c6..f53fbfb 100755
1f1d7d
--- a/yum-cron/yum-cron.py
1f1d7d
+++ b/yum-cron/yum-cron.py
1f1d7d
@@ -685,6 +685,9 @@ class EmailEmitter(UpdateEmitter):
1f1d7d
         """Combine the stored messages that have been stored into a
1f1d7d
         single email message, and send this message.
1f1d7d
         """
1f1d7d
+        # Don't send empty emails
1f1d7d
+        if not self.output:
1f1d7d
+            return
1f1d7d
         # Build up the email to be sent
1f1d7d
         msg = MIMEText(''.join(self.output))
1f1d7d
         msg['Subject'] = self.subject
1f1d7d
@@ -708,6 +711,9 @@ class StdIOEmitter(UpdateEmitter):
1f1d7d
         """Combine the stored messages that have been stored into a
1f1d7d
         single email message, and send this message to standard output.
1f1d7d
         """
1f1d7d
+        # Don't print blank lines
1f1d7d
+        if not self.output:
1f1d7d
+            return
1f1d7d
         print "".join(self.output)
1f1d7d
 
1f1d7d
 
1f1d7d
commit 78c4435ddbb00d11bf42040e8afb34ee1cf107b5
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Tue Dec 10 10:02:29 2013 +0100
1f1d7d
1f1d7d
    Fix a gettext string (typo).
1f1d7d
1f1d7d
diff --git a/yum/__init__.py b/yum/__init__.py
1f1d7d
index f212884..caafae4 100644
1f1d7d
--- a/yum/__init__.py
1f1d7d
+++ b/yum/__init__.py
1f1d7d
@@ -1929,7 +1929,7 @@ much more problems).
1f1d7d
                     # maybe a file log here, too
1f1d7d
                     # but raising an exception is not going to do any good
1f1d7d
                     self.logger.critical(_('%s was supposed to be installed' \
1f1d7d
-                                           ' but is not!' % txmbr.po))
1f1d7d
+                                           ' but is not!') % txmbr.po)
1f1d7d
                     # Note: Get Panu to do te.Failed() so we don't have to
1f1d7d
                     txmbr.output_state = TS_FAILED
1f1d7d
                     count = _call_txmbr_cb(txmbr, count)
1f1d7d
commit cc0d8d11c90515ead4f3e1018e0f82b2edbc8274
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Tue Dec 10 16:15:57 2013 +0100
1f1d7d
1f1d7d
    completion-helper: No pkg list when len(prefix) < 1. BZ 1040033
1f1d7d
1f1d7d
diff --git a/etc/yum.bash b/etc/yum.bash
1f1d7d
index 40541af..aae8992 100644
1f1d7d
--- a/etc/yum.bash
1f1d7d
+++ b/etc/yum.bash
1f1d7d
@@ -19,6 +19,8 @@ _yum_list()
1f1d7d
 {
1f1d7d
     # Fail fast for things that look like paths or options.
1f1d7d
     [[ $2 == */* || $2 == [.~-]* ]] && return
1f1d7d
+    # Listing all packages takes way too long
1f1d7d
+    [[ ${#2} -lt 1 ]] && return
1f1d7d
     _yum_helper list "$@"
1f1d7d
 }
1f1d7d
 
1f1d7d
commit 7479c24ff5196f740614338247a7c513fe56486b
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Fri Dec 13 09:01:14 2013 +0100
1f1d7d
1f1d7d
    completion-helper: accept empty prefix when listing installed pkgs
1f1d7d
1f1d7d
diff --git a/etc/yum.bash b/etc/yum.bash
1f1d7d
index aae8992..16d096c 100644
1f1d7d
--- a/etc/yum.bash
1f1d7d
+++ b/etc/yum.bash
1f1d7d
@@ -19,8 +19,8 @@ _yum_list()
1f1d7d
 {
1f1d7d
     # Fail fast for things that look like paths or options.
1f1d7d
     [[ $2 == */* || $2 == [.~-]* ]] && return
1f1d7d
-    # Listing all packages takes way too long
1f1d7d
-    [[ ${#2} -lt 1 ]] && return
1f1d7d
+    # Listing all available packages takes way too long
1f1d7d
+    [[ $1 != "installed" && ${#2} -lt 1 ]] && return
1f1d7d
     _yum_helper list "$@"
1f1d7d
 }
1f1d7d
 
1f1d7d
commit 05846f0ce0ec09e6030f18f6e508a75347f529c0
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Mon Nov 18 17:41:17 2013 -0500
1f1d7d
1f1d7d
    Copy/Paste install for group upgrade lists into yum-cron output. BZ 1031374.
1f1d7d
1f1d7d
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
1f1d7d
index 79c1907..dd0a4c6 100755
1f1d7d
--- a/yum-cron/yum-cron.py
1f1d7d
+++ b/yum-cron/yum-cron.py
1f1d7d
@@ -426,10 +426,31 @@ class UpdateEmitter(object):
1f1d7d
 
1f1d7d
             return a_wid
1f1d7d
 
1f1d7d
-        
1f1d7d
+        ninstalled = self.tsInfo.installed
1f1d7d
+        ginstalled = {}
1f1d7d
+        if self.conf.group_command == 'objects' and ninstalled:
1f1d7d
+            # Show new pkgs. that are installed via. a group.
1f1d7d
+            ninstalled = []
1f1d7d
+            for txmbr in self.tsInfo.installed:
1f1d7d
+                if not hasattr(txmbr, '_ugroup_member'):
1f1d7d
+                    ninstalled.append(txmbr)
1f1d7d
+                    continue
1f1d7d
+                if txmbr._ugroup_member not in ginstalled:
1f1d7d
+                    ginstalled[txmbr._ugroup_member] = []
1f1d7d
+                ginstalled[txmbr._ugroup_member].append(txmbr)
1f1d7d
+
1f1d7d
+        for grp in sorted(ginstalled, key=lambda x: x.ui_name):
1f1d7d
+            action = _('Installing for group upgrade "%s"') % grp.ui_name
1f1d7d
+            pkglist = ginstalled[grp]
1f1d7d
+
1f1d7d
+            lines = []
1f1d7d
+            for txmbr in pkglist:
1f1d7d
+                a_wid = _add_line(lines, data, a_wid, txmbr.po, txmbr.obsoletes)
1f1d7d
+
1f1d7d
+            pkglist_lines.append((action, lines))        
1f1d7d
 
1f1d7d
         # Iterate through the different groups of packages
1f1d7d
-        for (action, pkglist) in [(_('Installing'), tsInfo.installed),
1f1d7d
+        for (action, pkglist) in [(_('Installing'), ninstalled),
1f1d7d
                             (_('Updating'), tsInfo.updated),
1f1d7d
                             (_('Removing'), tsInfo.removed),
1f1d7d
                             (_('Reinstalling'), tsInfo.reinstalled),
1f1d7d
commit d0bba60912ec09dd6bbbc1dfbf2b27688bec3e68
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Fri Dec 13 09:39:36 2013 +0100
1f1d7d
1f1d7d
    yum-cron: Inherit YumOutput. BZ 1040109
1f1d7d
    
1f1d7d
    When yum-cron can use bits from output.py, we don't have to
1f1d7d
    duplicate about 450 lines of code.
1f1d7d
1f1d7d
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
1f1d7d
index f53fbfb..5661fbb 100755
1f1d7d
--- a/yum-cron/yum-cron.py
1f1d7d
+++ b/yum-cron/yum-cron.py
1f1d7d
@@ -21,6 +21,7 @@ from yum.misc import setup_locale
1f1d7d
 
1f1d7d
 # FIXME: is it really sane to use this from here?
1f1d7d
 sys.path.append('/usr/share/yum-cli')
1f1d7d
+from output import YumOutput
1f1d7d
 import callback
1f1d7d
 
1f1d7d
 default_config_file = '/etc/yum/yum-cron.conf'
1f1d7d
@@ -155,447 +156,9 @@ class UpdateEmitter(object):
1f1d7d
         """
1f1d7d
         pass
1f1d7d
 
1f1d7d
-    def _format_number(self, number, SI=0, space=' '):
1f1d7d
-        """Return a human-readable metric-like string representation
1f1d7d
-        of a number.
1f1d7d
-
1f1d7d
-        :param number: the number to be converted to a human-readable form
1f1d7d
-        :param SI: If is 0, this function will use the convention
1f1d7d
-           that 1 kilobyte = 1024 bytes, otherwise, the convention
1f1d7d
-           that 1 kilobyte = 1000 bytes will be used
1f1d7d
-        :param space: string that will be placed between the number
1f1d7d
-           and the SI prefix
1f1d7d
-        :return: a human-readable metric-like string representation of
1f1d7d
-           *number*
1f1d7d
-        """
1f1d7d
-        symbols = [ ' ', # (none)
1f1d7d
-                    'k', # kilo
1f1d7d
-                    'M', # mega
1f1d7d
-                    'G', # giga
1f1d7d
-                    'T', # tera
1f1d7d
-                    'P', # peta
1f1d7d
-                    'E', # exa
1f1d7d
-                    'Z', # zetta
1f1d7d
-                    'Y'] # yotta
1f1d7d
-    
1f1d7d
-        if SI: step = 1000.0
1f1d7d
-        else: step = 1024.0
1f1d7d
-    
1f1d7d
-        thresh = 999
1f1d7d
-        depth = 0
1f1d7d
-        max_depth = len(symbols) - 1
1f1d7d
-    
1f1d7d
-        # we want numbers between 0 and thresh, but don't exceed the length
1f1d7d
-        # of our list.  In that event, the formatting will be screwed up,
1f1d7d
-        # but it'll still show the right number.
1f1d7d
-        while number > thresh and depth < max_depth:
1f1d7d
-            depth  = depth + 1
1f1d7d
-            number = number / step
1f1d7d
-    
1f1d7d
-        if type(number) == type(1) or type(number) == type(1L):
1f1d7d
-            format = '%i%s%s'
1f1d7d
-        elif number < 9.95:
1f1d7d
-            # must use 9.95 for proper sizing.  For example, 9.99 will be
1f1d7d
-            # rounded to 10.0 with the .1f format string (which is too long)
1f1d7d
-            format = '%.1f%s%s'
1f1d7d
-        else:
1f1d7d
-            format = '%.0f%s%s'
1f1d7d
-    
1f1d7d
-        return(format % (float(number or 0), space, symbols[depth]))
1f1d7d
-
1f1d7d
-    def _fmtColumns(self, columns, msg=u'', end=u'', text_width=utf8_width):
1f1d7d
-        """Return a row of data formatted into a string for output.
1f1d7d
-        Items can overflow their columns. 
1f1d7d
-
1f1d7d
-        :param columns: a list of tuples containing the data to
1f1d7d
-           output.  Each tuple contains first the item to be output,
1f1d7d
-           then the amount of space allocated for the column, and then
1f1d7d
-           optionally a type of highlighting for the item
1f1d7d
-        :param msg: a string to begin the line of output with
1f1d7d
-        :param end: a string to end the line of output with
1f1d7d
-        :param text_width: a function to find the width of the items
1f1d7d
-           in the columns.  This defaults to utf8 but can be changed
1f1d7d
-           to len() if you know it'll be fine
1f1d7d
-        :return: a row of data formatted into a string for output
1f1d7d
-        """
1f1d7d
-        total_width = len(msg)
1f1d7d
-        data = []
1f1d7d
-        for col_data in columns[:-1]:
1f1d7d
-            (val, width) = col_data
1f1d7d
-
1f1d7d
-            if not width: # Don't count this column, invisible text
1f1d7d
-                msg += u"%s"
1f1d7d
-                data.append(val)
1f1d7d
-                continue
1f1d7d
-
1f1d7d
-            (align, width) = self._fmt_column_align_width(width)
1f1d7d
-            val_width = text_width(val)
1f1d7d
-            if val_width <= width:
1f1d7d
-                #  Don't use utf8_width_fill() because it sucks performance
1f1d7d
-                # wise for 1,000s of rows. Also allows us to use len(), when
1f1d7d
-                # we can.
1f1d7d
-                msg += u"%s%s "
1f1d7d
-                if (align == u'-'):
1f1d7d
-                    data.extend([val, " " * (width - val_width)])
1f1d7d
-                else:
1f1d7d
-                    data.extend([" " * (width - val_width), val])
1f1d7d
-            else:
1f1d7d
-                msg += u"%s\n" + " " * (total_width + width + 1)
1f1d7d
-                data.append(val)
1f1d7d
-            total_width += width
1f1d7d
-            total_width += 1
1f1d7d
-        (val, width) = columns[-1]
1f1d7d
-        (align, width) = self._fmt_column_align_width(width)
1f1d7d
-        val = utf8_width_fill(val, width, left=(align == u'-'))
1f1d7d
-        msg += u"%%s%s" % end
1f1d7d
-        data.append(val)
1f1d7d
-        return msg % tuple(data)
1f1d7d
-
1f1d7d
-    def _calcColumns(self, data, total_width, columns=None, remainder_column=0, indent=''):
1f1d7d
-        """Dynamically calculate the widths of the columns that the
1f1d7d
-        fields in data should be placed into for output.
1f1d7d
-        
1f1d7d
-        :param data: a list of dictionaries that represent the data to
1f1d7d
-           be output.  Each dictionary in the list corresponds to annn
1f1d7d
-           column of output. The keys of the dictionary are the
1f1d7d
-           lengths of the items to be output, and the value associated
1f1d7d
-           with a key is the number of items of that length.
1f1d7d
-        :param total_width: the total width of the output.
1f1d7d
-        :param columns: a list containing the minimum amount of space
1f1d7d
-           that must be allocated for each row. This can be used to
1f1d7d
-           ensure that there is space available in a column if, for
1f1d7d
-           example, the actual lengths of the items being output
1f1d7d
-           cannot be given in *data*
1f1d7d
-        :param remainder_column: number of the column to receive a few
1f1d7d
-           extra spaces that may remain after other allocation has
1f1d7d
-           taken place
1f1d7d
-        :param indent: string that will be prefixed to a line of
1f1d7d
-           output to create e.g. an indent
1f1d7d
-        :return: a list of the widths of the columns that the fields
1f1d7d
-           in data should be placed into for output
1f1d7d
-        """
1f1d7d
-        if total_width is None:
1f1d7d
-            total_width = self.term.columns
1f1d7d
-
1f1d7d
-        cols = len(data)
1f1d7d
-        # Convert the data to ascending list of tuples, (field_length, pkgs)
1f1d7d
-        pdata = data
1f1d7d
-        data  = [None] * cols # Don't modify the passed in data
1f1d7d
-        for d in range(0, cols):
1f1d7d
-            data[d] = sorted(pdata[d].items())
1f1d7d
-
1f1d7d
-        #  We start allocating 1 char to everything but the last column, and a
1f1d7d
-        # space between each (again, except for the last column). Because
1f1d7d
-        # at worst we are better with:
1f1d7d
-        # |one two three|
1f1d7d
-        # | four        |
1f1d7d
-        # ...than:
1f1d7d
-        # |one two three|
1f1d7d
-        # |            f|
1f1d7d
-        # |our          |
1f1d7d
-        # ...the later being what we get if we pre-allocate the last column, and
1f1d7d
-        # thus. the space, due to "three" overflowing it's column by 2 chars.
1f1d7d
-        if columns is None:
1f1d7d
-            columns = [1] * (cols - 1)
1f1d7d
-            columns.append(0)
1f1d7d
-
1f1d7d
-        total_width -= (sum(columns) + (cols - 1) +
1f1d7d
-                        utf8_width(indent))
1f1d7d
-        if not columns[-1]:
1f1d7d
-            total_width += 1
1f1d7d
-        while total_width > 0:
1f1d7d
-            # Find which field all the spaces left will help best
1f1d7d
-            helps = 0
1f1d7d
-            val   = 0
1f1d7d
-            for d in xrange(0, cols):
1f1d7d
-                thelps = self._calc_columns_spaces_helps(columns[d], data[d],
1f1d7d
-                                                         total_width)
1f1d7d
-                if not thelps:
1f1d7d
-                    continue
1f1d7d
-                #  We prefer to overflow: the last column, and then earlier
1f1d7d
-                # columns. This is so that in the best case (just overflow the
1f1d7d
-                # last) ... grep still "works", and then we make it prettier.
1f1d7d
-                if helps and (d == (cols - 1)) and (thelps / 2) < helps:
1f1d7d
-                    continue
1f1d7d
-                if thelps < helps:
1f1d7d
-                    continue
1f1d7d
-                helps = thelps
1f1d7d
-                val   = d
1f1d7d
-
1f1d7d
-            #  If we found a column to expand, move up to the next level with
1f1d7d
-            # that column and start again with any remaining space.
1f1d7d
-            if helps:
1f1d7d
-                diff = data[val].pop(0)[0] - columns[val]
1f1d7d
-                if not columns[val] and (val == (cols - 1)):
1f1d7d
-                    #  If we are going from 0 => N on the last column, take 1
1f1d7d
-                    # for the space before the column.
1f1d7d
-                    total_width  -= 1
1f1d7d
-                columns[val] += diff
1f1d7d
-                total_width  -= diff
1f1d7d
-                continue
1f1d7d
-
1f1d7d
-            overflowed_columns = 0
1f1d7d
-            for d in xrange(0, cols):
1f1d7d
-                if not data[d]:
1f1d7d
-                    continue
1f1d7d
-                overflowed_columns += 1
1f1d7d
-            if overflowed_columns:
1f1d7d
-                #  Split the remaining spaces among each overflowed column
1f1d7d
-                # equally
1f1d7d
-                norm = total_width / overflowed_columns
1f1d7d
-                for d in xrange(0, cols):
1f1d7d
-                    if not data[d]:
1f1d7d
-                        continue
1f1d7d
-                    columns[d] += norm
1f1d7d
-                    total_width -= norm
1f1d7d
-
1f1d7d
-            #  Split the remaining spaces among each column equally, except the
1f1d7d
-            # last one. And put the rest into the remainder column
1f1d7d
-            cols -= 1
1f1d7d
-            norm = total_width / cols
1f1d7d
-            for d in xrange(0, cols):
1f1d7d
-                columns[d] += norm
1f1d7d
-            columns[remainder_column] += total_width - (cols * norm)
1f1d7d
-            total_width = 0
1f1d7d
-
1f1d7d
-        return columns
1f1d7d
-
1f1d7d
-    @staticmethod
1f1d7d
-    def _fmt_column_align_width(width):
1f1d7d
-        if width < 0:
1f1d7d
-            return (u"-", -width)
1f1d7d
-        return (u"", width)
1f1d7d
-
1f1d7d
-    @staticmethod
1f1d7d
-    def _calc_columns_spaces_helps(current, data_tups, left):
1f1d7d
-        """ Spaces left on the current field will help how many pkgs? """
1f1d7d
-        ret = 0
1f1d7d
-        for tup in data_tups:
1f1d7d
-            if left < (tup[0] - current):
1f1d7d
-                break
1f1d7d
-            ret += tup[1]
1f1d7d
-        return ret
1f1d7d
-
1f1d7d
     def _formatTransaction(self, tsInfo):
1f1d7d
-        """Return a string containing a human-readable formatted
1f1d7d
-        summary of the transaction.
1f1d7d
-        
1f1d7d
-        :param tsInfo: :class:`yum.transactioninfo.TransactionData`
1f1d7d
-           instance that contains information about the transaction
1f1d7d
-        :return: a string that contains a formatted summary of the
1f1d7d
-           transaction
1f1d7d
-           """
1f1d7d
-        # Sort the packages in the transaction into different lists,
1f1d7d
-        # e.g. installed, updated etc
1f1d7d
-        tsInfo.makelists(True, True)
1f1d7d
-
1f1d7d
-        # For each package list, pkglist_lines will contain a tuple
1f1d7d
-        # that contains the name of the list, and a list of tuples
1f1d7d
-        # with information about each package in the list
1f1d7d
-        pkglist_lines = []
1f1d7d
-        data  = {'n' : {}, 'v' : {}, 'r' : {}}
1f1d7d
-        a_wid = 0 # Arch can't get "that big" ... so always use the max.
1f1d7d
-
1f1d7d
-
1f1d7d
-        def _add_line(lines, data, a_wid, po, obsoletes=[]):
1f1d7d
-            # Create a tuple of strings that contain the name, arch,
1f1d7d
-            # version, repository, size, and obsoletes of the package
1f1d7d
-            # given in po.  Then, append this tuple to lines.  The
1f1d7d
-            # strings are formatted so that the tuple can be easily
1f1d7d
-            # joined together for output.
1f1d7d
-
1f1d7d
-            
1f1d7d
-            (n,a,e,v,r) = po.pkgtup
1f1d7d
-            
1f1d7d
-            # Retrieve the version, repo id, and size of the package
1f1d7d
-            # in human-readable form
1f1d7d
-            evr = po.printVer()
1f1d7d
-            repoid = po.ui_from_repo
1f1d7d
-            size = self._format_number(float(po.size))
1f1d7d
-
1f1d7d
-            if a is None: # gpgkeys are weird
1f1d7d
-                a = 'noarch'
1f1d7d
-
1f1d7d
-            lines.append((n, a, evr, repoid, size, obsoletes))
1f1d7d
-            #  Create a dict of field_length => number of packages, for
1f1d7d
-            # each field.
1f1d7d
-            for (d, v) in (("n",len(n)), ("v",len(evr)), ("r",len(repoid))):
1f1d7d
-                data[d].setdefault(v, 0)
1f1d7d
-                data[d][v] += 1
1f1d7d
-            a_wid = max(a_wid, len(a))
1f1d7d
-
1f1d7d
-            return a_wid
1f1d7d
-
1f1d7d
-        ninstalled = self.tsInfo.installed
1f1d7d
-        ginstalled = {}
1f1d7d
-        if self.conf.group_command == 'objects' and ninstalled:
1f1d7d
-            # Show new pkgs. that are installed via. a group.
1f1d7d
-            ninstalled = []
1f1d7d
-            for txmbr in self.tsInfo.installed:
1f1d7d
-                if not hasattr(txmbr, '_ugroup_member'):
1f1d7d
-                    ninstalled.append(txmbr)
1f1d7d
-                    continue
1f1d7d
-                if txmbr._ugroup_member not in ginstalled:
1f1d7d
-                    ginstalled[txmbr._ugroup_member] = []
1f1d7d
-                ginstalled[txmbr._ugroup_member].append(txmbr)
1f1d7d
-
1f1d7d
-        for grp in sorted(ginstalled, key=lambda x: x.ui_name):
1f1d7d
-            action = _('Installing for group upgrade "%s"') % grp.ui_name
1f1d7d
-            pkglist = ginstalled[grp]
1f1d7d
-
1f1d7d
-            lines = []
1f1d7d
-            for txmbr in pkglist:
1f1d7d
-                a_wid = _add_line(lines, data, a_wid, txmbr.po, txmbr.obsoletes)
1f1d7d
-
1f1d7d
-            pkglist_lines.append((action, lines))        
1f1d7d
-
1f1d7d
-        # Iterate through the different groups of packages
1f1d7d
-        for (action, pkglist) in [(_('Installing'), ninstalled),
1f1d7d
-                            (_('Updating'), tsInfo.updated),
1f1d7d
-                            (_('Removing'), tsInfo.removed),
1f1d7d
-                            (_('Reinstalling'), tsInfo.reinstalled),
1f1d7d
-                            (_('Downgrading'), tsInfo.downgraded),
1f1d7d
-                            (_('Installing for dependencies'), tsInfo.depinstalled),
1f1d7d
-                            (_('Updating for dependencies'), tsInfo.depupdated),
1f1d7d
-                            (_('Removing for dependencies'), tsInfo.depremoved)]:
1f1d7d
-            # Create a list to hold the tuples of strings for each package
1f1d7d
-            lines = []
1f1d7d
-
1f1d7d
-            # Append the tuple for each package to lines, and update a_wid
1f1d7d
-            for txmbr in pkglist:
1f1d7d
-                a_wid = _add_line(lines, data, a_wid, txmbr.po, txmbr.obsoletes)
1f1d7d
-
1f1d7d
-            # Append the lines instance for this package list to pkglist_lines
1f1d7d
-            pkglist_lines.append((action, lines))
1f1d7d
-
1f1d7d
-        # # Iterate through other package lists
1f1d7d
-        # for (action, pkglist) in [(_('Skipped (dependency problems)'),
1f1d7d
-        #                            self.skipped_packages),
1f1d7d
-        #                           (_('Not installed'), self._not_found_i.values()),
1f1d7d
-        #                           (_('Not available'), self._not_found_a.values())]:
1f1d7d
-        #     lines = []
1f1d7d
-        #     for po in pkglist:
1f1d7d
-        #         a_wid = _add_line(lines, data, a_wid, po)
1f1d7d
-
1f1d7d
-        #     pkglist_lines.append((action, lines))
1f1d7d
-
1f1d7d
-        if not data['n']:
1f1d7d
-            return u''
1f1d7d
-        else:
1f1d7d
-            # Change data to a list with the correct number of
1f1d7d
-            # columns, in the correct order
1f1d7d
-            data    = [data['n'],    {}, data['v'], data['r'], {}]
1f1d7d
-
1f1d7d
-            
1f1d7d
-             
1f1d7d
-            # Calculate the space needed for each column
1f1d7d
-            columns = [1,         a_wid,         1,         1,  5]
1f1d7d
-
1f1d7d
-            columns = self._calcColumns(data, self.opts.output_width,
1f1d7d
-                                        columns, remainder_column = 2, indent="  ")
1f1d7d
-
1f1d7d
-            (n_wid, a_wid, v_wid, r_wid, s_wid) = columns
1f1d7d
-            assert s_wid == 5
1f1d7d
-
1f1d7d
-            # out will contain the output as a list of strings, that
1f1d7d
-            # can be later joined together
1f1d7d
-            out = [u"""
1f1d7d
-%s
1f1d7d
-%s
1f1d7d
-%s
1f1d7d
-""" % ('=' * self.opts.output_width,
1f1d7d
-       self._fmtColumns(((_('Package'), -n_wid), (_('Arch'), -a_wid),
1f1d7d
-                        (_('Version'), -v_wid), (_('Repository'), -r_wid),
1f1d7d
-                        (_('Size'), s_wid)), u" "),
1f1d7d
-       '=' * self.opts.output_width)]
1f1d7d
-
1f1d7d
-        # Add output for each package list in pkglist_lines
1f1d7d
-        for (action, lines) in pkglist_lines:
1f1d7d
-            #If the package list is empty, skip it
1f1d7d
-            if not lines:
1f1d7d
-                continue
1f1d7d
-
1f1d7d
-            # Add the name of the package list
1f1d7d
-            totalmsg = u"%s:\n" % action
1f1d7d
-            # Add a line of output about an individual package
1f1d7d
-            for (n, a, evr, repoid, size, obsoletes) in lines:
1f1d7d
-                columns = ((n,   -n_wid), (a,      -a_wid),
1f1d7d
-                           (evr, -v_wid), (repoid, -r_wid), (size, s_wid))
1f1d7d
-                msg = self._fmtColumns(columns, u" ", u"\n")
1f1d7d
-                for obspo in sorted(obsoletes):
1f1d7d
-                    appended = _('     replacing  %s.%s %s\n')
1f1d7d
-                    appended %= (obspo.name,
1f1d7d
-                                 obspo.arch, obspo.printVer())
1f1d7d
-                    msg = msg+appended
1f1d7d
-                totalmsg = totalmsg + msg
1f1d7d
-
1f1d7d
-            # Append the line about the individual package to out
1f1d7d
-            out.append(totalmsg)
1f1d7d
-
1f1d7d
-        # Add a summary of the transaction
1f1d7d
-        out.append(_("""
1f1d7d
-Transaction Summary
1f1d7d
-%s
1f1d7d
-""") % ('=' * self.opts.output_width))
1f1d7d
-        summary_data =  (
1f1d7d
-            (_('Install'), len(tsInfo.installed),
1f1d7d
-             len(tsInfo.depinstalled)),
1f1d7d
-            (_('Upgrade'), len(tsInfo.updated),
1f1d7d
-             len(tsInfo.depupdated)),
1f1d7d
-            (_('Remove'), len(tsInfo.removed),
1f1d7d
-             len(tsInfo.depremoved)),
1f1d7d
-            (_('Reinstall'), len(tsInfo.reinstalled), 0),
1f1d7d
-            (_('Downgrade'), len(tsInfo.downgraded), 0),
1f1d7d
-            # (_('Skipped (dependency problems)'), len(self.skipped_packages), 0),
1f1d7d
-            # (_('Not installed'), len(self._not_found_i.values()), 0),
1f1d7d
-            # (_('Not available'), len(self._not_found_a.values()), 0),
1f1d7d
-        )
1f1d7d
-        max_msg_action   = 0
1f1d7d
-        max_msg_count    = 0
1f1d7d
-        max_msg_pkgs     = 0
1f1d7d
-        max_msg_depcount = 0
1f1d7d
-        for action, count, depcount in summary_data:
1f1d7d
-            if not count and not depcount:
1f1d7d
-                continue
1f1d7d
-
1f1d7d
-            msg_pkgs = P_('Package', 'Packages', count)
1f1d7d
-            len_msg_action   = utf8_width(action)
1f1d7d
-            len_msg_count    = utf8_width(str(count))
1f1d7d
-            len_msg_pkgs     = utf8_width(msg_pkgs)
1f1d7d
-
1f1d7d
-            if depcount:
1f1d7d
-                len_msg_depcount = utf8_width(str(depcount))
1f1d7d
-            else:
1f1d7d
-                len_msg_depcount = 0
1f1d7d
-
1f1d7d
-            max_msg_action   = max(len_msg_action,   max_msg_action)
1f1d7d
-            max_msg_count    = max(len_msg_count,    max_msg_count)
1f1d7d
-            max_msg_pkgs     = max(len_msg_pkgs,     max_msg_pkgs)
1f1d7d
-            max_msg_depcount = max(len_msg_depcount, max_msg_depcount)
1f1d7d
-
1f1d7d
-        for action, count, depcount in summary_data:
1f1d7d
-            msg_pkgs = P_('Package', 'Packages', count)
1f1d7d
-            if depcount:
1f1d7d
-                msg_deppkgs = P_('Dependent package', 'Dependent packages',
1f1d7d
-                                 depcount)
1f1d7d
-                if count:
1f1d7d
-                    msg = '%s  %*d %s (+%*d %s)\n'
1f1d7d
-                    out.append(msg % (utf8_width_fill(action, max_msg_action),
1f1d7d
-                                      max_msg_count, count,
1f1d7d
-                                      utf8_width_fill(msg_pkgs, max_msg_pkgs),
1f1d7d
-                                      max_msg_depcount, depcount, msg_deppkgs))
1f1d7d
-                else:
1f1d7d
-                    msg = '%s  %*s %s ( %*d %s)\n'
1f1d7d
-                    out.append(msg % (utf8_width_fill(action, max_msg_action),
1f1d7d
-                                      max_msg_count, '',
1f1d7d
-                                      utf8_width_fill('', max_msg_pkgs),
1f1d7d
-                                      max_msg_depcount, depcount, msg_deppkgs))
1f1d7d
-            elif count:
1f1d7d
-                msg = '%s  %*d %s\n'
1f1d7d
-                out.append(msg % (utf8_width_fill(action, max_msg_action),
1f1d7d
-                                  max_msg_count, count, msg_pkgs))
1f1d7d
-
1f1d7d
-        return ''.join(out)
1f1d7d
+        assert self.opts._base.tsInfo == tsInfo
1f1d7d
+        return self.opts._base.listTransaction()
1f1d7d
 
1f1d7d
 
1f1d7d
 class EmailEmitter(UpdateEmitter):
1f1d7d
@@ -738,7 +301,7 @@ class YumCronConfig(BaseConfig):
1f1d7d
     group_package_types = ListOption(['mandatory', 'default'])
1f1d7d
 
1f1d7d
 
1f1d7d
-class YumCronBase(yum.YumBase):
1f1d7d
+class YumCronBase(yum.YumBase, YumOutput):
1f1d7d
     """Main class to check for and apply the updates."""
1f1d7d
 
1f1d7d
     def __init__(self, config_file_name = None):
1f1d7d
@@ -748,9 +311,13 @@ class YumCronBase(yum.YumBase):
1f1d7d
            config file to use.
1f1d7d
         """
1f1d7d
         yum.YumBase.__init__(self)
1f1d7d
+        YumOutput.__init__(self)
1f1d7d
 
1f1d7d
         # Read the config file
1f1d7d
         self.readConfigFile(config_file_name)
1f1d7d
+        self.term.reinit(color='never')
1f1d7d
+        self.term.columns = self.opts.output_width
1f1d7d
+        self.opts._base = self
1f1d7d
 
1f1d7d
 
1f1d7d
         # Create the emitters, and add them to the list
1f1d7d
commit 1f4b4a800516ec56215a4bed36293f62b77e1239
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Fri Dec 13 10:11:34 2013 +0100
1f1d7d
1f1d7d
    yum-cron: remove _formatTransaction()
1f1d7d
    
1f1d7d
    By moving the formatting out of emitters, we loose a bit of flexibility,
1f1d7d
    but at least run the formatting only once, and don't have to pass YumBase
1f1d7d
    references to emitters.
1f1d7d
1f1d7d
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
1f1d7d
index 5661fbb..a1fd10b 100755
1f1d7d
--- a/yum-cron/yum-cron.py
1f1d7d
+++ b/yum-cron/yum-cron.py
1f1d7d
@@ -37,25 +37,23 @@ class UpdateEmitter(object):
1f1d7d
         self.opts  = opts
1f1d7d
         self.output = []
1f1d7d
 
1f1d7d
-    def updatesAvailable(self, tsInfo):
1f1d7d
+    def updatesAvailable(self, summary):
1f1d7d
         """Appends a message to the output list stating that there are
1f1d7d
         updates available.
1f1d7d
 
1f1d7d
-        :param tsInfo: A :class:`yum.transactioninfo.TransactionData`
1f1d7d
-           instance that contains information about the transaction.
1f1d7d
+        :param summary: A human-readable summary of the transaction.
1f1d7d
         """
1f1d7d
         self.output.append('The following updates are available on %s:' % self.opts.system_name)
1f1d7d
-        self.output.append(self._formatTransaction(tsInfo))
1f1d7d
+        self.output.append(summary)
1f1d7d
 
1f1d7d
-    def updatesDownloading(self, tsInfo):
1f1d7d
+    def updatesDownloading(self, summary):
1f1d7d
         """Append a message to the output list stating that
1f1d7d
         downloading updates has started.
1f1d7d
 
1f1d7d
-        :param tsInfo: A :class:`yum.transactioninfo.TransactionData`
1f1d7d
-           instance that contains information about the transaction.
1f1d7d
+        :param summary: A human-readable summary of the transaction.
1f1d7d
         """
1f1d7d
         self.output.append('The following updates will be downloaded on %s:' % self.opts.system_name)
1f1d7d
-        self.output.append(self._formatTransaction(tsInfo))
1f1d7d
+        self.output.append(summary)
1f1d7d
 
1f1d7d
     def updatesDownloaded(self):
1f1d7d
         """Append a message to the output list stating that updates
1f1d7d
@@ -63,15 +61,14 @@ class UpdateEmitter(object):
1f1d7d
         """
1f1d7d
         self.output.append("Updates downloaded successfully.")
1f1d7d
 
1f1d7d
-    def updatesInstalling(self, tsInfo):
1f1d7d
+    def updatesInstalling(self, summary):
1f1d7d
         """Append a message to the output list stating that
1f1d7d
         installing updates has started.
1f1d7d
 
1f1d7d
-        :param tsInfo: A :class:`yum.transactioninfo.TransactionData`
1f1d7d
-           instance that contains information about the transaction.
1f1d7d
+        :param summary: A human-readable summary of the transaction.
1f1d7d
         """
1f1d7d
         self.output.append('The following updates will be applied on %s:' % self.opts.system_name)
1f1d7d
-        self.output.append(self._formatTransaction(tsInfo))
1f1d7d
+        self.output.append(summary)
1f1d7d
 
1f1d7d
     def updatesInstalled(self):
1f1d7d
         """Append a message to the output list stating that updates
1f1d7d
@@ -156,10 +153,6 @@ class UpdateEmitter(object):
1f1d7d
         """
1f1d7d
         pass
1f1d7d
 
1f1d7d
-    def _formatTransaction(self, tsInfo):
1f1d7d
-        assert self.opts._base.tsInfo == tsInfo
1f1d7d
-        return self.opts._base.listTransaction()
1f1d7d
-
1f1d7d
 
1f1d7d
 class EmailEmitter(UpdateEmitter):
1f1d7d
     """Emitter class to send messages via email."""
1f1d7d
@@ -168,14 +161,13 @@ class EmailEmitter(UpdateEmitter):
1f1d7d
         super(EmailEmitter, self).__init__(opts)        
1f1d7d
         self.subject = ""
1f1d7d
 
1f1d7d
-    def updatesAvailable(self, tsInfo):
1f1d7d
+    def updatesAvailable(self, summary):
1f1d7d
         """Appends a message to the output list stating that there are
1f1d7d
         updates available, and set an appropriate subject line.
1f1d7d
 
1f1d7d
-        :param tsInfo: A :class:`yum.transactioninfo.TransactionData`
1f1d7d
-           instance that contains information about the transaction.
1f1d7d
+        :param summary: A human-readable summary of the transaction.
1f1d7d
         """
1f1d7d
-        super(EmailEmitter, self).updatesAvailable(tsInfo)
1f1d7d
+        super(EmailEmitter, self).updatesAvailable(summary)
1f1d7d
         self.subject = "Yum: Updates Available on %s" % self.opts.system_name
1f1d7d
 
1f1d7d
     def updatesDownloaded(self):
1f1d7d
@@ -317,7 +309,6 @@ class YumCronBase(yum.YumBase, YumOutput):
1f1d7d
         self.readConfigFile(config_file_name)
1f1d7d
         self.term.reinit(color='never')
1f1d7d
         self.term.columns = self.opts.output_width
1f1d7d
-        self.opts._base = self
1f1d7d
 
1f1d7d
 
1f1d7d
         # Create the emitters, and add them to the list
1f1d7d
@@ -655,11 +646,13 @@ class YumCronBase(yum.YumBase, YumOutput):
1f1d7d
 
1f1d7d
     def emitAvailable(self):
1f1d7d
         """Emit a notice stating whether updates are available."""
1f1d7d
-        map(lambda x: x.updatesAvailable(self.tsInfo), self.emitters)
1f1d7d
+        summary = self.listTransaction()
1f1d7d
+        map(lambda x: x.updatesAvailable(summary), self.emitters)
1f1d7d
 
1f1d7d
     def emitDownloading(self):
1f1d7d
         """Emit a notice stating that updates are downloading."""
1f1d7d
-        map(lambda x: x.updatesDownloading(self.tsInfo), self.emitters)
1f1d7d
+        summary = self.listTransaction()
1f1d7d
+        map(lambda x: x.updatesDownloading(summary), self.emitters)
1f1d7d
 
1f1d7d
     def emitDownloaded(self):
1f1d7d
         """Emit a notice stating that updates have downloaded."""
1f1d7d
@@ -669,7 +662,8 @@ class YumCronBase(yum.YumBase, YumOutput):
1f1d7d
         """Emit a notice stating that automatic updates are about to
1f1d7d
         be applied.
1f1d7d
         """
1f1d7d
-        map(lambda x: x.updatesInstalling(self.tsInfo), self.emitters)
1f1d7d
+        summary = self.listTransaction()
1f1d7d
+        map(lambda x: x.updatesInstalling(summary), self.emitters)
1f1d7d
 
1f1d7d
     def emitInstalled(self):
1f1d7d
         """Emit a notice stating that automatic updates have been applied."""
1f1d7d
commit f8579cb9c08f5ea962f555d1610bb58449139ed2
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Mon Dec 23 15:29:51 2013 +0100
1f1d7d
1f1d7d
    Skip unavailable repos. BZ 1046076
1f1d7d
    
1f1d7d
    By populating all repos at once we honor skip_if_unavailable,
1f1d7d
    and also download metadata in parallel (although this does not
1f1d7d
    matter that much since yum-cron is not interactive).
1f1d7d
1f1d7d
diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
1f1d7d
index 19436e5..b96dd13 100755
1f1d7d
--- a/yum-cron/yum-cron.py
1f1d7d
+++ b/yum-cron/yum-cron.py
1f1d7d
@@ -414,7 +414,9 @@ class YumCronBase(yum.YumBase, YumOutput):
1f1d7d
 
1f1d7d
         for repo in self.repos.sort():
1f1d7d
             repo.metadata_expire = 0
1f1d7d
+            repo.skip_if_unavailable = True
1f1d7d
 
1f1d7d
+        self.pkgSack # honor skip_if_unavailable
1f1d7d
         self.upinfo
1f1d7d
 
1f1d7d
     def refreshUpdates(self):
1f1d7d
commit a00fcf5e9ce765fd6aba2db327bfb072f23ac465
1f1d7d
Author: Jonathan Wakely <fedoration@kayari.org>
1f1d7d
Date:   Sun Dec 22 11:39:49 2013 +0000
1f1d7d
1f1d7d
    docs: yum.conf.5: Fix typo.
1f1d7d
1f1d7d
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
1f1d7d
index 48ced00..c66eba8 100644
1f1d7d
--- a/docs/yum.conf.5
1f1d7d
+++ b/docs/yum.conf.5
1f1d7d
@@ -148,7 +148,7 @@ Command-line option: \fB\-t\fP
1f1d7d
 .IP
1f1d7d
 \fBexclude\fR
1f1d7d
 List of packages to exclude from all repositories, so yum works
1f1d7d
-as if that package was never in the repositories.. This should be a space
1f1d7d
+as if that package was never in the repositories. This should be a space
1f1d7d
 separated list.
1f1d7d
 This is commonly used so a package isn't upgraded or installed accidentally, but
1f1d7d
 can be used to remove packages in any way that "yum list" will show packages.
1f1d7d
commit c26740594afdf86c503c3406f1370dbb6ad0608b
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Thu Jan 2 10:57:08 2014 -0500
1f1d7d
1f1d7d
    docs: Update --downloadonly section of man page.
1f1d7d
1f1d7d
diff --git a/docs/yum.8 b/docs/yum.8
1f1d7d
index 0e211eb..f7d6ec3 100644
1f1d7d
--- a/docs/yum.8
1f1d7d
+++ b/docs/yum.8
1f1d7d
@@ -871,7 +871,8 @@ This option makes yum go slower, checking for things that shouldn't be possible
1f1d7d
 making it more tolerant of external errors.
1f1d7d
 .br
1f1d7d
 .IP "\fB\-\-downloadonly\fP"
1f1d7d
-Don't update, just download.
1f1d7d
+Don't update, just download. This is done in the background, so the yum lock is released for other operations. This can also be chosen by typing 'd'ownloadonly
1f1d7d
+at the transaction confirmation prompt.
1f1d7d
 .br
1f1d7d
 .IP "\fB\-\-downloaddir=directory\fP"
1f1d7d
 Specifies an alternate directory to store packages.
1f1d7d
commit 6ddb350b207cfa54d96232c23606444cd0b79341
1f1d7d
Author: Zdenek Pavlas <zpavlas@redhat.com>
1f1d7d
Date:   Mon Jan 13 16:12:33 2014 +0100
1f1d7d
1f1d7d
    yum-cron: Enable random_sleep by default.
1f1d7d
1f1d7d
diff --git a/etc/yum-cron-hourly.conf b/etc/yum-cron-hourly.conf
1f1d7d
index 2d52349..7871a46 100644
1f1d7d
--- a/etc/yum-cron-hourly.conf
1f1d7d
+++ b/etc/yum-cron-hourly.conf
1f1d7d
@@ -25,7 +25,7 @@ apply_updates = no
1f1d7d
 # minutes before running.  This is useful for e.g. staggering the
1f1d7d
 # times that multiple systems will access update servers.  If
1f1d7d
 # random_sleep is 0 or negative, the program will run immediately.
1f1d7d
-random_sleep = 0
1f1d7d
+random_sleep = 15
1f1d7d
 
1f1d7d
 
1f1d7d
 [emitters]
1f1d7d
diff --git a/etc/yum-cron.conf b/etc/yum-cron.conf
1f1d7d
index a97d881..f8de068 100644
1f1d7d
--- a/etc/yum-cron.conf
1f1d7d
+++ b/etc/yum-cron.conf
1f1d7d
@@ -24,7 +24,7 @@ apply_updates = no
1f1d7d
 # minutes before running.  This is useful for e.g. staggering the
1f1d7d
 # times that multiple systems will access update servers.  If
1f1d7d
 # random_sleep is 0 or negative, the program will run immediately.
1f1d7d
-random_sleep = 0
1f1d7d
+random_sleep = 6*60
1f1d7d
 
1f1d7d
 
1f1d7d
 [emitters]
1f1d7d
commit 2715047a195b29d6ac7d985166b985954267a0bb
1f1d7d
Author: James Antill <james@and.org>
1f1d7d
Date:   Tue Jan 14 15:29:03 2014 -0500
1f1d7d
1f1d7d
    Fix yum-cron.conf default, as ini parser can't do Math.
1f1d7d
1f1d7d
diff --git a/etc/yum-cron.conf b/etc/yum-cron.conf
1f1d7d
index f8de068..b0f7839 100644
1f1d7d
--- a/etc/yum-cron.conf
1f1d7d
+++ b/etc/yum-cron.conf
1f1d7d
@@ -24,7 +24,8 @@ apply_updates = no
1f1d7d
 # minutes before running.  This is useful for e.g. staggering the
1f1d7d
 # times that multiple systems will access update servers.  If
1f1d7d
 # random_sleep is 0 or negative, the program will run immediately.
1f1d7d
-random_sleep = 6*60
1f1d7d
+# 6*60 = 360
1f1d7d
+random_sleep = 360
1f1d7d
 
1f1d7d
 
1f1d7d
 [emitters]