[yum] Update to latest HEAD.

James Antill james at fedoraproject.org
Wed Aug 28 20:55:02 UTC 2013


commit b4929dc6208ac36dd4f4e7bedd8de8e8e042e880
Author: James Antill <james at and.org>
Date:   Wed Aug 28 16:54:47 2013 -0400

    Update to latest HEAD.
    
    - Use new comps. mock objects to re-integrate group removal. BZ 996866.
    - Add "weak" comps. groups, for installed groups.
    - Add msg. to help users deal with RepoError failures. BZ 867389.
    - Give msgs about install/trans. obsoletes a higher priority. BZ 991080.
    - waitForLock() raises YumBaseError. BZ 1001154.

 yum-HEAD.patch |  694 ++++++++++++++++++++++++++++++++------------------------
 yum.spec       |   10 +-
 2 files changed, 410 insertions(+), 294 deletions(-)
---
diff --git a/yum-HEAD.patch b/yum-HEAD.patch
index d27c35a..0ad3ec7 100644
--- a/yum-HEAD.patch
+++ b/yum-HEAD.patch
@@ -12,7 +12,7 @@ index 911da19..85decd5 100644
  .pydevproject
  asthelper.completions
 diff --git a/Makefile b/Makefile
-index 740b616..9e1d7af 100644
+index 740b616..f203c4d 100644
 --- a/Makefile
 +++ b/Makefile
 @@ -1,4 +1,4 @@
@@ -58,6 +58,14 @@ index 740b616..9e1d7af 100644
  .PHONY: docs test
  
  DOCS = yum rpmUtils callback.py yumcommands.py shell.py output.py cli.py utils.py\
+@@ -63,7 +83,6 @@ doccheck:
+ 
+ test:
+ 	@nosetests -i ".*test" test
+-	- at test/check-po-yes-no.py
+ 	cd po; make test
+ 
+ test-skipbroken:
 diff --git a/callback.py b/callback.py
 index 2f6154e..2e5a052 100644
 --- a/callback.py
@@ -99,7 +107,7 @@ index 2f6154e..2e5a052 100644
 diff --git a/cli.py b/cli.py
 old mode 100644
 new mode 100755
-index 6056d38..7fa638b
+index 6056d38..8358c55
 --- a/cli.py
 +++ b/cli.py
 @@ -25,7 +25,7 @@ import sys
@@ -1124,11 +1132,11 @@ index 6056d38..7fa638b
 +        """Print out a formatted list of dependencies for a list of
 +        packages.  This is a cli wrapper method for
 +        :class:`yum.YumBase.findDeps`.
- 
++
 +        :param args: a list of names or wildcards specifying packages
 +           that should have their dependenices printed
 +        :return: (exit_code, [ errors ])
-+
+ 
 +        exit_code is::
 +
 +            0 = we're done, exit
@@ -1307,10 +1315,10 @@ index 6056d38..7fa638b
 +        :param extcmds: a list of names or wildcards specifying
 +           groups to list
 +        :return: (exit_code, [ errors ])
++
++        exit_code is::
  
 -        uservisible=1
-+        exit_code is::
-+
 +            0 = we're done, exit
 +            1 = we've errored, exit with error string
 +            2 = we've got work yet to do, onto the next stage        
@@ -1645,19 +1653,19 @@ index 6056d38..7fa638b
                  continue
              
          if not pkgs_used:
-@@ -1368,17 +1927,61 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1368,17 +1927,55 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
              return 2, [P_('%d package to Install', '%d packages to Install', len(pkgs_used)) % len(pkgs_used)]
  
      def removeGroups(self, grouplist):
 -        """Remove only packages of the named group(s). Do not recurse."""
 +        """Mark the packages in the given groups for removal.
-+
+ 
 +        :param grouplist: a list of names or wildcards specifying
 +           groups to be removed
 +        :return: (exit_code, [ errors ])
 +
 +        exit_code is::
- 
++
 +            0 = we're done, exit
 +            1 = we've errored, exit with error string
 +            2 = we've got work yet to do, onto the next stage
@@ -1683,10 +1691,7 @@ index 6056d38..7fa638b
 +
 +            groups = []
 +            if grp_grp:
-+                if self.conf.group_command == 'objects':
-+                    groups = self.igroups.return_environments(group_string)
-+                else:
-+                    groups = self.comps.return_environments(group_string)
++                groups = self.comps.return_environments(group_string)
 +                if not groups:
 +                    self.logger.critical(_('No environment named %s exists'), group_string)
 +            for group in groups:
@@ -1699,10 +1704,7 @@ index 6056d38..7fa638b
 +
 +            groups = []
 +            if pkg_grp:
-+                if self.conf.group_command == 'objects':
-+                    groups = self.igroups.return_groups(group_string)
-+                else:
-+                    groups = self.comps.return_groups(group_string)
++                groups = self.comps.return_groups(group_string)
 +                if not groups:
 +                    self.logger.critical(_('No group named %s exists'), group_string)
 +            for group in groups:
@@ -1715,7 +1717,7 @@ index 6056d38..7fa638b
                  
          if not pkgs_used:
              return 0, [_('No packages to remove from groups')]
-@@ -1389,7 +1992,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1389,7 +1986,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
  
      def _promptWanted(self):
          # shortcut for the always-off/always-on options
@@ -1724,7 +1726,7 @@ index 6056d38..7fa638b
              return False
          if self.conf.alwaysprompt:
              return True
-@@ -1397,10 +2000,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1397,10 +1994,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
          # prompt if:
          #  package was added to fill a dependency
          #  package is being removed
@@ -1736,7 +1738,7 @@ index 6056d38..7fa638b
                     txmbr.name not in self.extcmds:
                  return True
          
-@@ -1408,11 +2010,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1408,11 +2004,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
          return False
  
      def usage(self):
@@ -1750,7 +1752,7 @@ index 6056d38..7fa638b
          sys.stdout.write(self.optparser.get_usage())
      
      def _installable(self, pkg, ematch=False):
-@@ -1468,9 +2070,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
+@@ -1468,9 +2064,9 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
          return False
  
  class YumOptionParser(OptionParser):
@@ -1762,7 +1764,7 @@ index 6056d38..7fa638b
  
      def __init__(self,base, **kwargs):
          # check if this is called with a utils=True/False parameter
-@@ -1488,13 +2090,23 @@ class YumOptionParser(OptionParser):
+@@ -1488,13 +2084,23 @@ class YumOptionParser(OptionParser):
          self._addYumBasicOptions()
  
      def error(self, msg):
@@ -1788,7 +1790,7 @@ index 6056d38..7fa638b
          try:
              args = _filtercmdline(
                          ('--noplugins','--version','-q', '-v', "--quiet", "--verbose"), 
-@@ -1521,7 +2133,15 @@ class YumOptionParser(OptionParser):
+@@ -1521,7 +2127,15 @@ class YumOptionParser(OptionParser):
          return ret
          
      def setupYumConfig(self, args=None):
@@ -1805,7 +1807,7 @@ index 6056d38..7fa638b
          if not args:
              (opts, cmds) = self.parse_args()
          else:
-@@ -1533,16 +2153,30 @@ class YumOptionParser(OptionParser):
+@@ -1533,16 +2147,30 @@ class YumOptionParser(OptionParser):
          try:
              # config file is parsed and moving us forward
              # set some things in it.
@@ -1842,7 +1844,7 @@ index 6056d38..7fa638b
                  self.base.conf.cache = 1
  
              if opts.obsoletes:
-@@ -1574,11 +2208,8 @@ class YumOptionParser(OptionParser):
+@@ -1574,11 +2202,8 @@ class YumOptionParser(OptionParser):
                  if opts.color != 'auto':
                      self.base.term.reinit(color=opts.color)
  
@@ -1856,7 +1858,7 @@ index 6056d38..7fa638b
  
              for exclude in self._splitArg(opts.exclude):
                  try:
-@@ -1610,10 +2241,6 @@ class YumOptionParser(OptionParser):
+@@ -1610,10 +2235,6 @@ class YumOptionParser(OptionParser):
                      self.base.usage()
                      sys.exit(1)
  
@@ -1867,7 +1869,7 @@ index 6056d38..7fa638b
              # Disable all gpg key checking, if requested.
              if opts.nogpgcheck:
                  #  Altering the normal configs. doesn't work too well, esp. with
-@@ -1623,7 +2250,7 @@ class YumOptionParser(OptionParser):
+@@ -1623,7 +2244,7 @@ class YumOptionParser(OptionParser):
                      repo._override_sigchecks = True
                              
          except ValueError, e:
@@ -1876,7 +1878,7 @@ index 6056d38..7fa638b
              self.base.usage()
              sys.exit(1)
           
-@@ -1640,10 +2267,18 @@ class YumOptionParser(OptionParser):
+@@ -1640,10 +2261,18 @@ class YumOptionParser(OptionParser):
          sys.exit(1)
  
      def getRoot(self,opts):
@@ -1896,7 +1898,7 @@ index 6056d38..7fa638b
              if os.access(opts.installroot+'/'+opts.conffile, os.R_OK):
                  opts.conffile = opts.installroot+'/'+opts.conffile
              elif opts.conffile == '/etc/yum/yum.conf':
-@@ -1701,6 +2336,9 @@ class YumOptionParser(OptionParser):
+@@ -1701,6 +2330,9 @@ class YumOptionParser(OptionParser):
          group.add_option("--showduplicates", dest="showdupesfromrepos",
                          action="store_true",
                  help=_("show duplicates, in repos, in list/search commands"))
@@ -1906,7 +1908,7 @@ index 6056d38..7fa638b
          group.add_option("-e", "--errorlevel", dest="errorlevel", default=None,
                  help=_("error output level"), type='int',
                  metavar='[error level]')
-@@ -1713,6 +2351,10 @@ class YumOptionParser(OptionParser):
+@@ -1713,6 +2345,10 @@ class YumOptionParser(OptionParser):
                          help=_("verbose operation"))
          group.add_option("-y", "--assumeyes", dest="assumeyes",
                  action="store_true", help=_("answer yes for all questions"))
@@ -1917,7 +1919,7 @@ index 6056d38..7fa638b
          group.add_option("--version", action="store_true", 
                  help=_("show Yum version and exit"))
          group.add_option("--installroot", help=_("set install root"), 
-@@ -1730,6 +2372,9 @@ class YumOptionParser(OptionParser):
+@@ -1730,6 +2366,9 @@ class YumOptionParser(OptionParser):
          group.add_option("", "--disableexcludes", default=[], action="append",
                  help=_("disable exclude from main, for a repo or for everything"),
                          metavar='[repo]')
@@ -1927,7 +1929,7 @@ index 6056d38..7fa638b
          group.add_option("--obsoletes", action="store_true", 
                  help=_("enable obsoletes processing during updates"))
          group.add_option("--noplugins", action="store_true", 
-@@ -1748,9 +2393,29 @@ class YumOptionParser(OptionParser):
+@@ -1748,9 +2387,29 @@ class YumOptionParser(OptionParser):
                  help=_("control whether color is used"))
          group.add_option("", "--releasever", dest="releasever", default=None, 
                  help=_("set value of $releasever in yum config and repo files"))
@@ -2723,7 +2725,7 @@ index 0000000..2af059d
 + the mailing list, yum at lists.baseurl.org, or consult bugzilla.
 +.fi
 diff --git a/docs/yum.8 b/docs/yum.8
-index 1a8202a..1bb756e 100644
+index 1a8202a..1885e15 100644
 --- a/docs/yum.8
 +++ b/docs/yum.8
 @@ -25,6 +25,8 @@ gnome\-packagekit application\&.
@@ -3366,8 +3368,17 @@ index 1a8202a..1bb756e 100644
  .IP "\fByum list obsoletes [glob_exp1] [\&.\&.\&.]\fP"
  List the packages installed on the system that are obsoleted by packages
  in any yum repository listed in the config file.
+@@ -658,7 +1001,7 @@ configuration options.
+ .I yum-complete-transaction (1)
+ .I yumdownloader (1)
+ .I yum-utils (1)
+-.I yum-security (8)
++.I yum-langpacks (1)
+ http://yum.baseurl.org/
+ http://yum.baseurl.org/wiki/Faq
+ yum search yum
 diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
-index 515aa73..4369811 100644
+index 515aa73..8a7de80 100644
 --- a/docs/yum.conf.5
 +++ b/docs/yum.conf.5
 @@ -64,7 +64,7 @@ options are: 'critical', 'emergency', 'error', 'warn' and 'debug'.
@@ -3521,20 +3532,24 @@ index 515aa73..4369811 100644
  
  .IP
  \fBtsflags\fR
-@@ -292,6 +354,12 @@ the maximum available bandwidth.
+@@ -291,6 +353,16 @@ the maximum available bandwidth.
+ 
  Set to `0' to disable bandwidth throttling. This is the default.
  
- .IP
++Note that when multiple downloads run simultaneously the total bandwidth might
++exceed the throttle limit. You may want to also set max_connections=1 or scale
++your throttle option down accordingly.
++
++.IP
 +\fBminrate \fR
 +This sets the low speed threshold in bytes per second. If the server
 +is sending data slower than this for at least `timeout' seconds, Yum
 +aborts the connection. The default is `1000'.
 +
-+.IP
+ .IP
  \fBbandwidth \fR
  Use to specify the maximum available network bandwidth in bytes/second.  Used
- with the \fBthrottle\fR option (above). If \fBthrottle\fR is a percentage and
-@@ -300,6 +368,40 @@ with the \fBthrottle\fR option (above). If \fBthrottle\fR is a percentage and
+@@ -300,6 +372,40 @@ with the \fBthrottle\fR option (above). If \fBthrottle\fR is a percentage and
  ignored. Default is `0' (no bandwidth throttling). 
  
  .IP
@@ -3575,7 +3590,7 @@ index 515aa73..4369811 100644
  \fBsslcacert \fR
  Path to the directory containing the databases of the certificate authorities
  yum should use to verify SSL certificates. Defaults to none - uses system
-@@ -331,6 +433,15 @@ Path to the SSL client key yum should use to connect to repos/remote sites
+@@ -331,6 +437,15 @@ Path to the SSL client key yum should use to connect to repos/remote sites
  Defaults to none.
  
  .IP
@@ -3591,7 +3606,7 @@ index 515aa73..4369811 100644
  \fBhistory_record \fR
  Boolean - should yum record history entries for transactions. This takes some
  disk space, and some extra time in the transactions. But it allows how to know a
-@@ -391,7 +502,9 @@ syslog logging is disabled.  Default is `/dev/log'.
+@@ -391,7 +506,9 @@ syslog logging is disabled.  Default is `/dev/log'.
  
  .IP
  \fBproxy \fR
@@ -3602,7 +3617,7 @@ index 515aa73..4369811 100644
  
  .IP
  \fBproxy_username \fR
-@@ -438,6 +551,31 @@ It's also possible to use the word "never", meaning that the metadata will
+@@ -438,6 +555,31 @@ It's also possible to use the word "never", meaning that the metadata will
  never expire. Note that when using a metalink file the metalink must always
  be newer than the metadata for the repository, due to the validation, so this
  timeout also applies to the metalink file.
@@ -3634,7 +3649,7 @@ index 515aa73..4369811 100644
  
  .IP
  \fBmirrorlist_expire \fR
-@@ -462,12 +600,12 @@ always did, however it now does some checking on the index and reverts if
+@@ -462,12 +604,12 @@ always did, however it now does some checking on the index and reverts if
  it classifies it as bad.
  
  `group:primary' - Download the primary metadata with the index. This contains
@@ -3652,7 +3667,7 @@ index 515aa73..4369811 100644
  
  `group:main' - With the primary and updateinfo download the filelists metadata
  and the group metadata. The filelists data is required for operations like
-@@ -480,6 +618,19 @@ not listed above is the other metadata, which contains the changelog information
+@@ -480,6 +622,19 @@ not listed above is the other metadata, which contains the changelog information
  which is used by yum-changelog. This is what "yum makecache" uses.
  
  .IP
@@ -3672,7 +3687,7 @@ index 515aa73..4369811 100644
  \fBmultilib_policy \fR
  Can be set to 'all' or 'best'. All means install all possible arches for any package you 
  want to install. Therefore yum install foo will install foo.i386 and foo.x86_64 on x86_64, 
-@@ -523,6 +674,13 @@ Default is `normal'.
+@@ -523,6 +678,13 @@ Default is `normal'.
  See color_list_installed_older for possible values.
  
  .IP
@@ -3686,7 +3701,7 @@ index 515aa73..4369811 100644
  \fBcolor_list_installed_extra \fR
  The colorization/highlighting for packages in list/info installed which has
  no available package with the same name and arch.
-@@ -558,6 +716,13 @@ Default is `bold,underline,green.
+@@ -558,6 +720,13 @@ Default is `bold,underline,green.
  See color_list_installed_older for possible values.
  
  .IP
@@ -3700,7 +3715,7 @@ index 515aa73..4369811 100644
  \fBcolor_search_match \fR
  The colorization/highlighting for text matches in search.
  Default is `bold'.
-@@ -587,14 +752,91 @@ be downloaded. The updates list is what is printed when you run "yum update",
+@@ -587,14 +756,91 @@ be downloaded. The updates list is what is printed when you run "yum update",
  Default is `normal'.
  See color_list_installed_older for possible values.
  
@@ -3792,7 +3807,7 @@ index 515aa73..4369811 100644
  
  
  .SH "[repository] OPTIONS"
-@@ -702,12 +944,18 @@ key will be automatically imported without user confirmation.
+@@ -702,12 +948,18 @@ key will be automatically imported without user confirmation.
  Same as the [main] \fBexclude\fR option but only for this repository.
  Substitution variables, described below, are honored here.
  
@@ -3815,7 +3830,7 @@ index 515aa73..4369811 100644
  
  .IP
  \fBenablegroups\fR
-@@ -755,6 +1003,16 @@ repository.
+@@ -755,6 +1007,16 @@ repository.
  Overrides the \fBbandwidth\fR option from the [main] section for this
  repository.
  
@@ -3832,7 +3847,7 @@ index 515aa73..4369811 100644
  
  .IP
  \fBsslcacert \fR
-@@ -776,6 +1034,10 @@ repository.
+@@ -776,6 +1038,10 @@ repository.
  Overrides the \fBsslclientkey\fR option from the [main] section for this
  repository.
  
@@ -3843,7 +3858,7 @@ index 515aa73..4369811 100644
  
  .IP
  \fBmetadata_expire \fR
-@@ -783,6 +1045,11 @@ Overrides the \fBmetadata_expire\fR option from the [main] section for this
+@@ -783,6 +1049,11 @@ Overrides the \fBmetadata_expire\fR option from the [main] section for this
  repository.
  
  .IP
@@ -3855,7 +3870,7 @@ index 515aa73..4369811 100644
  \fBmirrorlist_expire \fR
  Overrides the \fBmirrorlist_expire\fR option from the [main] section for this
  repository.
-@@ -824,7 +1091,16 @@ as greater/less than any other. defaults to 1000
+@@ -824,7 +1095,16 @@ as greater/less than any other. defaults to 1000
  If set to True yum will continue running if this repository cannot be 
  contacted for any reason. This should be set carefully as all repos are consulted
  for any given command. Defaults to False.
@@ -4246,10 +4261,10 @@ index 0000000..3d4392d
 +mdpolicy = group:main
 diff --git a/etc/yum-cron.conf b/etc/yum-cron.conf
 new file mode 100644
-index 0000000..5c59869
+index 0000000..649c326
 --- /dev/null
 +++ b/etc/yum-cron.conf
-@@ -0,0 +1,76 @@
+@@ -0,0 +1,79 @@
 +[commands]
 +#  What kind of update to use:
 +# default                            = yum upgrade
@@ -4316,16 +4331,19 @@ index 0000000..5c59869
 +group_package_types = mandatory, default
 +
 +[base]
++# This section overrides yum.conf
++
 +# Use this to filter Yum core messages
 +# -4: critical
 +# -3: critical+errors
 +# -2: critical+errors+warnings (default)
 +debuglevel = -2
 +
-+# override yum options of the same name
 +# skip_broken = True
-+
 +mdpolicy = group:main
++
++# Uncomment to auto-import new gpg keys (dangerous)
++# assumeyes = True
 diff --git a/etc/yum-cron.sysconf b/etc/yum-cron.sysconf
 deleted file mode 100644
 index 930341c..0000000
@@ -184306,10 +184324,10 @@ index 0000000..28e1964
 +- Check if we're running as root; exit nicely.
 diff --git a/yum-cron/yum-cron.py b/yum-cron/yum-cron.py
 new file mode 100755
-index 0000000..735f496
+index 0000000..d56a1b6
 --- /dev/null
 +++ b/yum-cron/yum-cron.py
-@@ -0,0 +1,1126 @@
+@@ -0,0 +1,1127 @@
 +#!/usr/bin/python -tt
 +import os
 +import sys
@@ -185021,8 +185039,6 @@ index 0000000..735f496
 +    yum_config_file = Option("/etc/yum.conf")
 +    group_list = ListOption([])
 +    group_package_types = ListOption(['mandatory', 'default'])
-+    skip_broken = BoolOption()
-+    debuglevel = IntOption(-2, -4, 10)
 +
 +
 +class YumCronBase(yum.YumBase):
@@ -185077,7 +185093,7 @@ index 0000000..735f496
 +        self.opts.populate(confparser, 'emitters')
 +        self.opts.populate(confparser, 'email')
 +        self.opts.populate(confparser, 'groups')
-+        self.opts.populate(confparser, 'base')
++        self._confparser = confparser
 +
 +        #If the system name is not given, set it by getting the hostname
 +        if self.opts.system_name == 'None' :
@@ -185107,7 +185123,10 @@ index 0000000..735f496
 +        try :
 +            # Set the configuration file
 +            self.preconf.fn = self.opts.yum_config_file
-+            self.preconf.debuglevel = self.opts.debuglevel
++
++            # This needs to be set early, errors are handled later.
++            try: self.preconf.debuglevel = int(self._confparser.get('base', 'debuglevel'))
++            except: pass
 +
 +            # if we are not root do the special subdir thing
 +            if os.geteuid() != 0:
@@ -185116,16 +185135,16 @@ index 0000000..735f496
 +            # Create the configuration
 +            self.conf
 +
++            # override base yum options
++            self.conf.populate(self._confparser, 'base')
++            del self._confparser
++
 +        except Exception, e:
 +            # If there are any exceptions, send a message about them,
 +            # and return False
 +            self.emitSetupFailed('%s' % e)
 +            sys.exit(1)
 +
-+        # override yum options
-+        if self.opts.skip_broken is not None:
-+            self.conf.skip_broken = self.opts.skip_broken
-+
 +    def acquireLock(self):
 +        """ Wrapper method around doLock to emit errors correctly."""
 +
@@ -186608,7 +186627,7 @@ index c1af4ad..70de539 100644
      pass
      
 diff --git a/yum/__init__.py b/yum/__init__.py
-index 99039e0..7a5332b 100644
+index 99039e0..a43f493 100644
 --- a/yum/__init__.py
 +++ b/yum/__init__.py
 @@ -21,6 +21,7 @@ The Yum RPM software updater.
@@ -187137,7 +187156,29 @@ index 99039e0..7a5332b 100644
                      repo.groups_added = False
          self._comps = val
      
-@@ -820,16 +927,14 @@ class YumBase(depsolve.Depsolve):
+@@ -813,6 +920,21 @@ class YumBase(depsolve.Depsolve):
+         overwrite = self.conf.overwrite_groups
+         self._comps = comps.Comps(overwrite_groups = overwrite)
+ 
++        if self.conf.group_command == 'objects':
++            #  Add the ids for installed groups/envs as though sys is a repo.
++            # makes everything easier (comps.return_groups() etc. works)...
++            self._comps.compscount += 1
++            for gid in self.igroups.groups:
++                grp = comps.Group()
++                grp.name = grp.groupid = gid
++                grp._weak = True
++                self._comps.add_group(grp)
++            for evgid in self.igroups.environments:
++                env = comps.Environment()
++                env.name = env.environmentid = evgid
++                env._weak = True
++                self._comps.add_environment(env)
++
+         for repo in reposWithGroups:
+             if repo.groups_added: # already added the groups from this repo
+                 continue
+@@ -820,16 +942,14 @@ class YumBase(depsolve.Depsolve):
              self.verbose_logger.log(logginglevels.DEBUG_4,
                  _('Adding group file from repository: %s'), repo)
              groupfile = repo.getGroups()
@@ -187159,7 +187200,7 @@ index 99039e0..7a5332b 100644
                  self.logger.critical(msg)
              else:
                  repo.groups_added = True
-@@ -837,7 +942,10 @@ class YumBase(depsolve.Depsolve):
+@@ -837,7 +957,10 @@ class YumBase(depsolve.Depsolve):
          if self._comps.compscount == 0:
              raise Errors.GroupsError, _('No Groups Available in any repository')
  
@@ -187171,7 +187212,7 @@ index 99039e0..7a5332b 100644
          self.verbose_logger.debug('group time: %0.3f' % (time.time() - group_st))                
          return self._comps
  
-@@ -868,22 +976,72 @@ class YumBase(depsolve.Depsolve):
+@@ -868,22 +991,72 @@ class YumBase(depsolve.Depsolve):
                      # feed it into _tags.add()
                      self._tags.add(repo.id, tag_sqlite)
                  except (Errors.RepoError, Errors.PkgTagsError), e:
@@ -187246,7 +187287,7 @@ index 99039e0..7a5332b 100644
      # properties so they auto-create themselves with defaults
      repos = property(fget=lambda self: self._getRepos(),
                       fset=lambda self, value: setattr(self, "_repos", value),
-@@ -921,16 +1079,31 @@ class YumBase(depsolve.Depsolve):
+@@ -921,16 +1094,31 @@ class YumBase(depsolve.Depsolve):
                         fdel=lambda self: setattr(self, "_history", None),
                         doc="Yum History Object")
  
@@ -187282,7 +187323,7 @@ index 99039e0..7a5332b 100644
          necessary = False
          
          # I can't think of a nice way of doing this, we have to have the sack here
-@@ -951,8 +1124,12 @@ class YumBase(depsolve.Depsolve):
+@@ -951,8 +1139,12 @@ class YumBase(depsolve.Depsolve):
              self.repos.populateSack(mdtype='filelists')
             
      def yumUtilsMsg(self, func, prog):
@@ -187297,7 +187338,7 @@ index 99039e0..7a5332b 100644
          if self.rpmdb.contains(name="yum-utils"):
              return
  
-@@ -964,12 +1141,24 @@ class YumBase(depsolve.Depsolve):
+@@ -964,12 +1156,24 @@ class YumBase(depsolve.Depsolve):
               (hibeg, prog, hiend))
  
      def buildTransaction(self, unfinished_transactions_check=True):
@@ -187325,7 +187366,7 @@ index 99039e0..7a5332b 100644
              self.logger.critical(msg)
              self.yumUtilsMsg(self.logger.critical, "yum-complete-transaction")
              time.sleep(3)
-@@ -1004,7 +1193,7 @@ class YumBase(depsolve.Depsolve):
+@@ -1004,7 +1208,7 @@ class YumBase(depsolve.Depsolve):
              # If transaction was changed by postresolve plugins then we should run skipbroken again
              (rescode, restring) = self._doSkipBroken(rescode, restring, clear_skipped=False )
  
@@ -187334,7 +187375,7 @@ index 99039e0..7a5332b 100644
              self.tsInfo.pkgSack.dropCachedData()
  
          # FIXME: This is horrible, see below and yummain. Maybe create a real
-@@ -1044,6 +1233,39 @@ class YumBase(depsolve.Depsolve):
+@@ -1044,6 +1248,39 @@ class YumBase(depsolve.Depsolve):
                  if first.verEQ(other):
                      continue
                  msg = _('Protected multilib versions: %s != %s')
@@ -187374,7 +187415,7 @@ index 99039e0..7a5332b 100644
                  xrestring.append(msg % (first, other))
          if xrestring:
              rescode = 1
-@@ -1227,7 +1449,7 @@ class YumBase(depsolve.Depsolve):
+@@ -1227,7 +1464,7 @@ class YumBase(depsolve.Depsolve):
                  self.verbose_logger.info(msg)
              self.skipped_packages.extend(skipped_list)   # make the skipped packages public
          else:
@@ -187383,7 +187424,7 @@ index 99039e0..7a5332b 100644
              self.verbose_logger.info("Skip-broken could not solve problems")
              return 1, orig_restring
          return rescode, restring
-@@ -1242,13 +1464,15 @@ class YumBase(depsolve.Depsolve):
+@@ -1242,13 +1479,15 @@ class YumBase(depsolve.Depsolve):
          if None in pkgtup:
              return None
          return pkgtup
@@ -187403,7 +187444,7 @@ index 99039e0..7a5332b 100644
          if pkgtup is None:
              return
          self._not_found_i[pkgtup] = YumNotFoundPackage(pkgtup)
-@@ -1267,7 +1491,7 @@ class YumBase(depsolve.Depsolve):
+@@ -1267,7 +1506,7 @@ class YumBase(depsolve.Depsolve):
              for pkg in txmbr.obsoleted_by:
                  # check if the obsoleting txmbr is in the transaction
                  # else remove the obsoleted txmbr
@@ -187412,7 +187453,7 @@ index 99039e0..7a5332b 100644
                  if not self.tsInfo.exists(pkg.pkgtup):
                      self.verbose_logger.debug('SKIPBROKEN: Remove extra obsoleted %s (%s)' % (txmbr.po,pkg) )
                      self.tsInfo.remove(txmbr.po.pkgtup)
-@@ -1282,7 +1506,7 @@ class YumBase(depsolve.Depsolve):
+@@ -1282,7 +1521,7 @@ class YumBase(depsolve.Depsolve):
              for pkg in txmbr.updated_by:
                  # check if the updating txmbr is in the transaction
                  # else remove the updated txmbr
@@ -187421,7 +187462,7 @@ index 99039e0..7a5332b 100644
                  if not self.tsInfo.exists(pkg.pkgtup):
                      self.verbose_logger.debug('SKIPBROKEN: Remove extra updated %s (%s)' % (txmbr.po,pkg) )
                      self.tsInfo.remove(txmbr.po.pkgtup)
-@@ -1379,9 +1603,19 @@ class YumBase(depsolve.Depsolve):
+@@ -1379,9 +1618,19 @@ class YumBase(depsolve.Depsolve):
  
      def _getDepsToRemove(self,po, deptree, toRemove):
          for dep in deptree.get(po, []): # Loop trough all deps of po
@@ -187441,7 +187482,7 @@ index 99039e0..7a5332b 100644
              toRemove.add(dep)
              self._getDepsToRemove(dep, deptree, toRemove)
  
-@@ -1454,7 +1688,46 @@ class YumBase(depsolve.Depsolve):
+@@ -1454,7 +1703,46 @@ class YumBase(depsolve.Depsolve):
          return probs
  
      def runTransaction(self, cb):
@@ -187489,7 +187530,7 @@ index 99039e0..7a5332b 100644
  
          self.plugins.run('pretrans')
  
-@@ -1516,10 +1789,23 @@ class YumBase(depsolve.Depsolve):
+@@ -1516,10 +1804,23 @@ class YumBase(depsolve.Depsolve):
                  pass
          self._ts_save_file = None
          
@@ -187513,7 +187554,7 @@ index 99039e0..7a5332b 100644
          
          # make resultobject - just a plain yumgenericholder object
          resultobject = misc.GenericHolder()
-@@ -1567,13 +1853,35 @@ class YumBase(depsolve.Depsolve):
+@@ -1567,13 +1868,35 @@ class YumBase(depsolve.Depsolve):
          self.plugins.run('posttrans')
          # sync up what just happened versus what is in the rpmdb
          if not self.ts.isTsFlagSet(rpm.RPMTRANS_FLAG_TEST):
@@ -187554,7 +187595,7 @@ index 99039e0..7a5332b 100644
          # check to see that the rpmdb and the tsInfo roughly matches
          # push package object metadata outside of rpmdb into yumdb
          # delete old yumdb metadata entries
-@@ -1584,9 +1892,16 @@ class YumBase(depsolve.Depsolve):
+@@ -1584,9 +1907,16 @@ class YumBase(depsolve.Depsolve):
          #    that there is not also an install of this pkg in the tsInfo (reinstall)
          # for any kind of install add from_repo to the yumdb, and the cmdline
          # and the install reason
@@ -187571,7 +187612,7 @@ index 99039e0..7a5332b 100644
          for txmbr in self.tsInfo:
              if txmbr.output_state in TS_INSTALL_STATES:
                  if not self.rpmdb.contains(po=txmbr.po):
-@@ -1596,12 +1911,21 @@ class YumBase(depsolve.Depsolve):
+@@ -1596,12 +1926,21 @@ class YumBase(depsolve.Depsolve):
                                             ' but is not!' % txmbr.po))
                      # Note: Get Panu to do te.Failed() so we don't have to
                      txmbr.output_state = TS_FAILED
@@ -187593,7 +187634,7 @@ index 99039e0..7a5332b 100644
                  if hasattr(self, 'args') and self.args:
                      po.yumdb_info.command_line = ' '.join(self.args)
                  elif hasattr(self, 'cmds') and self.cmds:
-@@ -1630,6 +1954,10 @@ class YumBase(depsolve.Depsolve):
+@@ -1630,6 +1969,10 @@ class YumBase(depsolve.Depsolve):
                      if md:
                          po.yumdb_info.from_repo_timestamp = str(md.timestamp)
  
@@ -187604,7 +187645,7 @@ index 99039e0..7a5332b 100644
                  loginuid = misc.getloginuid()
                  if txmbr.updates or txmbr.downgrades or txmbr.reinstall:
                      if txmbr.updates:
-@@ -1640,11 +1968,16 @@ class YumBase(depsolve.Depsolve):
+@@ -1640,11 +1983,16 @@ class YumBase(depsolve.Depsolve):
                          opo = po
                      if 'installed_by' in opo.yumdb_info:
                          po.yumdb_info.installed_by = opo.yumdb_info.installed_by
@@ -187621,7 +187662,7 @@ index 99039e0..7a5332b 100644
          # Remove old ones after installing new ones, so we can copy values.
          for txmbr in self.tsInfo:
              if txmbr.output_state in TS_INSTALL_STATES:
-@@ -1662,10 +1995,13 @@ class YumBase(depsolve.Depsolve):
+@@ -1662,10 +2010,13 @@ class YumBase(depsolve.Depsolve):
                                                 ' but is not!' % txmbr.po))
                          # Note: Get Panu to do te.Failed() so we don't have to
                          txmbr.output_state = TS_FAILED
@@ -187635,7 +187676,7 @@ index 99039e0..7a5332b 100644
                  self.verbose_logger.log(logginglevels.DEBUG_2, 'What is this? %s' % txmbr.po)
  
          self.plugins.run('postverifytrans')
-@@ -1680,10 +2016,11 @@ class YumBase(depsolve.Depsolve):
+@@ -1680,10 +2031,11 @@ class YumBase(depsolve.Depsolve):
          self.verbose_logger.debug('VerifyTransaction time: %0.3f' % (time.time() - vt_st))
  
      def costExcludePackages(self):
@@ -187651,7 +187692,7 @@ index 99039e0..7a5332b 100644
          # if all the repo.costs are equal then don't bother running things
          costs = {}
          for r in self.repos.listEnabled():
-@@ -1705,10 +2042,12 @@ class YumBase(depsolve.Depsolve):
+@@ -1705,10 +2057,12 @@ class YumBase(depsolve.Depsolve):
              done = True
  
      def excludePackages(self, repo=None):
@@ -187667,7 +187708,7 @@ index 99039e0..7a5332b 100644
          if "all" in self.conf.disable_excludes:
              return
          
-@@ -1735,9 +2074,14 @@ class YumBase(depsolve.Depsolve):
+@@ -1735,9 +2089,14 @@ class YumBase(depsolve.Depsolve):
              self.pkgSack.addPackageExcluder(repoid, exid,'exclude.match', match)
  
      def includePackages(self, repo):
@@ -187685,7 +187726,7 @@ index 99039e0..7a5332b 100644
          includelist = repo.getIncludePkgList()
          
          if len(includelist) == 0:
-@@ -1757,8 +2101,11 @@ class YumBase(depsolve.Depsolve):
+@@ -1757,8 +2116,11 @@ class YumBase(depsolve.Depsolve):
          self.pkgSack.addPackageExcluder(repo.id, exid, 'exclude.marked')
          
      def doLock(self, lockfile = YUM_PID_FILE):
@@ -187699,7 +187740,7 @@ index 99039e0..7a5332b 100644
          if self.conf.uid != 0:
              #  If we are a user, assume we are using the root cache ... so don't
              # bother locking.
-@@ -1774,38 +2121,26 @@ class YumBase(depsolve.Depsolve):
+@@ -1774,38 +2136,26 @@ class YumBase(depsolve.Depsolve):
          
          mypid=str(os.getpid())    
          while not self._lock(lockfile, mypid, 0644):
@@ -187753,7 +187794,7 @@ index 99039e0..7a5332b 100644
          # if we're not root then we don't lock - just return nicely
          #  Note that we can get here from __del__, so if we haven't created
          # YumBase.conf we don't want to do so here as creating stuff inside
-@@ -1830,31 +2165,69 @@ class YumBase(depsolve.Depsolve):
+@@ -1830,31 +2180,69 @@ class YumBase(depsolve.Depsolve):
          self._unlock(lockfile)
          self._lockfile = None
          
@@ -187834,7 +187875,7 @@ index 99039e0..7a5332b 100644
          failed = False
  
          if type(fo) is types.InstanceType:
-@@ -1894,9 +2267,16 @@ class YumBase(depsolve.Depsolve):
+@@ -1894,9 +2282,16 @@ class YumBase(depsolve.Depsolve):
          
          
      def verifyChecksum(self, fo, checksumType, csum):
@@ -187854,7 +187895,7 @@ index 99039e0..7a5332b 100644
          try:
              filesum = misc.checksum(checksumType, fo)
          except Errors.MiscError, e:
-@@ -1908,13 +2288,26 @@ class YumBase(depsolve.Depsolve):
+@@ -1908,13 +2303,26 @@ class YumBase(depsolve.Depsolve):
          return 0
  
      def downloadPkgs(self, pkglist, callback=None, callback_total=None):
@@ -187882,7 +187923,7 @@ index 99039e0..7a5332b 100644
              if a is None:
                  return -1
              if b is None:
-@@ -1925,9 +2318,6 @@ class YumBase(depsolve.Depsolve):
+@@ -1925,9 +2333,6 @@ class YumBase(depsolve.Depsolve):
                  return 1
              return 0
          
@@ -187892,7 +187933,7 @@ index 99039e0..7a5332b 100644
          errors = {}
          def adderror(po, msg):
              errors.setdefault(po, []).append(msg)
-@@ -1943,116 +2333,200 @@ class YumBase(depsolve.Depsolve):
+@@ -1943,116 +2348,200 @@ class YumBase(depsolve.Depsolve):
          self.history.close()
  
          self.plugins.run('predownload', pkglist=pkglist)
@@ -188182,7 +188223,7 @@ index 99039e0..7a5332b 100644
          if type(fo) is types.InstanceType:
              fo = fo.filename
              
-@@ -2076,9 +2550,12 @@ class YumBase(depsolve.Depsolve):
+@@ -2076,9 +2565,12 @@ class YumBase(depsolve.Depsolve):
          return 1
          
      def downloadHeader(self, po):
@@ -188197,7 +188238,7 @@ index 99039e0..7a5332b 100644
          if hasattr(po, 'pkgtype') and po.pkgtype == 'local':
              return
                  
-@@ -2122,15 +2599,17 @@ class YumBase(depsolve.Depsolve):
+@@ -2122,15 +2614,17 @@ class YumBase(depsolve.Depsolve):
              return
  
      def sigCheckPkg(self, po):
@@ -188223,7 +188264,7 @@ index 99039e0..7a5332b 100644
          if self._override_sigchecks:
              check = False
              hasgpgkey = 0
-@@ -2181,6 +2660,9 @@ class YumBase(depsolve.Depsolve):
+@@ -2181,6 +2675,9 @@ class YumBase(depsolve.Depsolve):
          return result, msg
  
      def cleanUsedHeadersPackages(self):
@@ -188233,7 +188274,7 @@ index 99039e0..7a5332b 100644
          filelist = []
          for txmbr in self.tsInfo:
              if txmbr.po.state not in TS_INSTALL_STATES:
-@@ -2218,27 +2700,42 @@ class YumBase(depsolve.Depsolve):
+@@ -2218,27 +2715,42 @@ class YumBase(depsolve.Depsolve):
                      _('%s removed'), fn)
          
      def cleanHeaders(self):
@@ -188278,7 +188319,7 @@ index 99039e0..7a5332b 100644
          cachedir = self.conf.persistdir + "/rpmdb-indexes/"
          if not os.path.exists(cachedir):
              filelist = []
-@@ -2271,9 +2768,31 @@ class YumBase(depsolve.Depsolve):
+@@ -2271,9 +2783,31 @@ class YumBase(depsolve.Depsolve):
          return 0, [msg]
  
      def doPackageLists(self, pkgnarrow='all', patterns=None, showdups=None,
@@ -188313,7 +188354,7 @@ index 99039e0..7a5332b 100644
          if showdups is None:
              showdups = self.conf.showdupesfromrepos
          ygh = misc.GenericHolder(iter=pkgnarrow)
-@@ -2295,6 +2814,8 @@ class YumBase(depsolve.Depsolve):
+@@ -2295,6 +2829,8 @@ class YumBase(depsolve.Depsolve):
              ndinst = {} # Newest versions by name.arch
              for po in self.rpmdb.returnPackages(patterns=patterns,
                                                  ignore_case=ic):
@@ -188322,7 +188363,7 @@ index 99039e0..7a5332b 100644
                  dinst[po.pkgtup] = po
                  if showdups:
                      continue
-@@ -2304,8 +2825,13 @@ class YumBase(depsolve.Depsolve):
+@@ -2304,8 +2840,13 @@ class YumBase(depsolve.Depsolve):
              installed = dinst.values()
                          
              if showdups:
@@ -188337,7 +188378,7 @@ index 99039e0..7a5332b 100644
              else:
                  try:
                      avail = self.pkgSack.returnNewestByNameArch(patterns=patterns,
-@@ -2323,16 +2849,30 @@ class YumBase(depsolve.Depsolve):
+@@ -2323,16 +2864,30 @@ class YumBase(depsolve.Depsolve):
                      key = (pkg.name, pkg.arch)
                      if pkg.pkgtup in dinst:
                          reinstall_available.append(pkg)
@@ -188371,7 +188412,7 @@ index 99039e0..7a5332b 100644
                  if len(matches) > 1:
                      updates.append(matches[0])
                      self.verbose_logger.log(logginglevels.DEBUG_1,
-@@ -2352,13 +2892,19 @@ class YumBase(depsolve.Depsolve):
+@@ -2352,13 +2907,19 @@ class YumBase(depsolve.Depsolve):
          elif pkgnarrow == 'installed':
              installed = self.rpmdb.returnPackages(patterns=patterns,
                                                    ignore_case=ic)
@@ -188392,7 +188433,7 @@ index 99039e0..7a5332b 100644
              else:
                  try:
                      avail = self.pkgSack.returnNewestByNameArch(patterns=patterns,
-@@ -2392,9 +2938,21 @@ class YumBase(depsolve.Depsolve):
+@@ -2392,9 +2953,21 @@ class YumBase(depsolve.Depsolve):
              avail = set(avail)
              for po in self.rpmdb.returnPackages(patterns=patterns,
                                                  ignore_case=ic):
@@ -188414,7 +188455,7 @@ index 99039e0..7a5332b 100644
          # obsoleting packages (and what they obsolete)
          elif pkgnarrow == 'obsoletes':
              self.conf.obsoletes = 1
-@@ -2402,6 +2960,7 @@ class YumBase(depsolve.Depsolve):
+@@ -2402,6 +2975,7 @@ class YumBase(depsolve.Depsolve):
              for (pkgtup, instTup) in self.up.getObsoletesTuples():
                  (n,a,e,v,r) = pkgtup
                  pkgs = self.pkgSack.searchNevra(name=n, arch=a, ver=v, rel=r, epoch=e)
@@ -188422,7 +188463,7 @@ index 99039e0..7a5332b 100644
                  instpo = self.getInstalledPackageObject(instTup)
                  for po in pkgs:
                      obsoletes.append(po)
-@@ -2433,7 +2992,12 @@ class YumBase(depsolve.Depsolve):
+@@ -2433,7 +3007,12 @@ class YumBase(depsolve.Depsolve):
              recentlimit = now-(self.conf.recent*86400)
              if showdups:
                  avail = self.pkgSack.returnPackages(patterns=patterns,
@@ -188436,7 +188477,7 @@ index 99039e0..7a5332b 100644
              else:
                  try:
                      avail = self.pkgSack.returnNewestByNameArch(patterns=patterns,
-@@ -2461,14 +3025,13 @@ class YumBase(depsolve.Depsolve):
+@@ -2461,14 +3040,13 @@ class YumBase(depsolve.Depsolve):
  
          
      def findDeps(self, pkgs):
@@ -188456,7 +188497,7 @@ index 99039e0..7a5332b 100644
          results = {}
  
          for pkg in pkgs:
-@@ -2495,10 +3058,22 @@ class YumBase(depsolve.Depsolve):
+@@ -2495,10 +3073,22 @@ class YumBase(depsolve.Depsolve):
      # pre 3.2.10 API used to always showdups, so that's the default atm.
      def searchGenerator(self, fields, criteria, showdups=True, keys=False, 
                                               searchtags=True, searchrpmdb=True):
@@ -188483,7 +188524,7 @@ index 99039e0..7a5332b 100644
          sql_fields = []
          for f in fields:
              sql_fields.append(RPM_TO_SQLITE.get(f, f))
-@@ -2614,7 +3189,7 @@ class YumBase(depsolve.Depsolve):
+@@ -2614,7 +3204,7 @@ class YumBase(depsolve.Depsolve):
          # ...but without showdups we want to output _just_ #3, which requires
          # we find the newest EVR po for the best "matching value". Without keys
          # it's the same, except we just want the newest EVR.
@@ -188492,7 +188533,7 @@ index 99039e0..7a5332b 100644
          # either, so it's pretty thankless. HTH. HAND.
          # By default just sort using package sorting
          sort_func = operator.itemgetter(0)
-@@ -2661,6 +3236,14 @@ class YumBase(depsolve.Depsolve):
+@@ -2661,6 +3251,14 @@ class YumBase(depsolve.Depsolve):
                      yield (po, vs)
  
      def searchPackageTags(self, criteria):
@@ -188507,7 +188548,7 @@ index 99039e0..7a5332b 100644
          results = {} # name = [(criteria, taglist)]
          for c in criteria:
              c = c.lower()
-@@ -2677,11 +3260,16 @@ class YumBase(depsolve.Depsolve):
+@@ -2677,11 +3275,16 @@ class YumBase(depsolve.Depsolve):
          return results
          
      def searchPackages(self, fields, criteria, callback=None):
@@ -188529,7 +188570,7 @@ index 99039e0..7a5332b 100644
          warnings.warn(_('searchPackages() will go away in a future version of Yum.\
                        Use searchGenerator() instead. \n'),
                  Errors.YumFutureDeprecationWarning, stacklevel=2)           
-@@ -2700,13 +3288,23 @@ class YumBase(depsolve.Depsolve):
+@@ -2700,13 +3303,23 @@ class YumBase(depsolve.Depsolve):
      
      def searchPackageProvides(self, args, callback=None,
                                callback_has_matchfor=False):
@@ -188557,7 +188598,7 @@ index 99039e0..7a5332b 100644
              else:
                  isglob = True
                  canBeFile = misc.re_filename(arg)
-@@ -2723,7 +3321,7 @@ class YumBase(depsolve.Depsolve):
+@@ -2723,7 +3336,7 @@ class YumBase(depsolve.Depsolve):
                  where = self.returnPackagesByDep(arg)
              else:
                  usedDepString = False
@@ -188566,7 +188607,7 @@ index 99039e0..7a5332b 100644
              self.verbose_logger.log(logginglevels.DEBUG_1,
                 P_('Searching %d package', 'Searching %d packages', len(where)), len(where))
              
-@@ -2817,25 +3415,168 @@ class YumBase(depsolve.Depsolve):
+@@ -2817,25 +3430,168 @@ class YumBase(depsolve.Depsolve):
              
          return matches
  
@@ -188747,10 +188788,13 @@ index 99039e0..7a5332b 100644
                  if uservisible:
                      if grp.user_visible:
                          installed.append(grp)
-@@ -2847,34 +3588,98 @@ class YumBase(depsolve.Depsolve):
+@@ -2847,34 +3603,91 @@ class YumBase(depsolve.Depsolve):
                          available.append(grp)
                  else:
                      available.append(grp)
+-            
+-        return sorted(installed), sorted(available)
+-    
 +
 +        for evgrp in evgrps:
 +            if ievgrps is None:
@@ -188764,7 +188808,7 @@ index 99039e0..7a5332b 100644
 +                einstalled.append(evgrp)
 +            else:
 +                eavailable.append(evgrp)
-             
++            
 +        if igrps is None:
 +            igrps = {}
 +        if ievgrps is None:
@@ -188794,9 +188838,8 @@ index 99039e0..7a5332b 100644
 +        if return_evgrps:
 +            return (sorted(installed), sorted(available),
 +                    sorted(einstalled), sorted(eavailable))
-         return sorted(installed), sorted(available)
++        return sorted(installed), sorted(available)
      
--    
      def groupRemove(self, grpid):
 -        """mark all the packages in this group to be removed"""
 -        
@@ -188809,12 +188852,8 @@ index 99039e0..7a5332b 100644
 +        """
          txmbrs_used = []
 -        
--        thesegroups = self.comps.return_groups(grpid)
 +
-+        if self.conf.group_command == 'objects':
-+            thesegroups = self.igroups.return_groups(grpid)
-+        else:
-+            thesegroups = self.comps.return_groups(grpid)
+         thesegroups = self.comps.return_groups(grpid)
          if not thesegroups:
              raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
  
@@ -188822,15 +188861,10 @@ index 99039e0..7a5332b 100644
 +            igroup_data = self._groupInstalledData(thisgroup)
 +
              thisgroup.toremove = True
--            pkgs = thisgroup.packages
--            for pkg in thisgroup.packages:
 +
-+            if self.conf.group_command == 'objects':
-+                pkgs = thisgroup.pkg_names
-+                gid  = thisgroup.gid
-+            else:
-+                pkgs = thisgroup.packages
-+                gid  = thisgroup.groupid
+             pkgs = thisgroup.packages
+-            for pkg in thisgroup.packages:
++            gid  = thisgroup.groupid
 +
 +            for pkg in pkgs:
 +                if pkg in igroup_data and igroup_data[pkg] != 'installed':
@@ -188856,7 +188890,7 @@ index 99039e0..7a5332b 100644
          thesegroups = self.comps.return_groups(grpid)
          if not thesegroups:
              raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
-@@ -2898,13 +3703,58 @@ class YumBase(depsolve.Depsolve):
+@@ -2898,13 +3711,51 @@ class YumBase(depsolve.Depsolve):
                              self.tsInfo.remove(txmbr.po.pkgtup)
          
          
@@ -188877,22 +188911,15 @@ index 99039e0..7a5332b 100644
 +        """
 +        txmbrs_used = []
 +
-+        if self.conf.group_command == 'objects':
-+            thesegroups = self.igroups.return_environments(evgrpid)
-+        else:
-+            thesegroups = self.comps.return_environments(evgrpid)
++        thesegroups = self.comps.return_environments(evgrpid)
 +        if not thesegroups:
 +            raise Errors.GroupsError, _("No Environment named %s exists") % to_unicode(evgrpid)
 +
 +        for thisgroup in thesegroups:
 +            igroup_data = self._groupInstalledEnvData(thisgroup)
 +
-+            if self.conf.group_command == 'objects':
-+                grps  = thisgroup.grp_names
-+                evgid = thisgroup.evgid
-+            else:
-+                grps  = thisgroup.allgroups
-+                evgid = thisgroup.environmentid
++            grps  = thisgroup.allgroups
++            evgid = thisgroup.environmentid
 +
 +            for grp in grps:
 +                if grp in igroup_data and igroup_data[grp] != 'installed':
@@ -188922,7 +188949,7 @@ index 99039e0..7a5332b 100644
          """
  
          if not self.comps.has_group(grpid):
-@@ -2920,12 +3770,18 @@ class YumBase(depsolve.Depsolve):
+@@ -2920,12 +3771,18 @@ class YumBase(depsolve.Depsolve):
          if group_package_types:
              package_types = group_package_types
  
@@ -188941,7 +188968,7 @@ index 99039e0..7a5332b 100644
              pkgs = []
              if 'mandatory' in package_types:
                  pkgs.extend(thisgroup.mandatory_packages)
-@@ -2934,12 +3790,52 @@ class YumBase(depsolve.Depsolve):
+@@ -2934,12 +3791,52 @@ class YumBase(depsolve.Depsolve):
              if 'optional' in package_types:
                  pkgs.extend(thisgroup.optional_packages)
  
@@ -188995,7 +189022,7 @@ index 99039e0..7a5332b 100644
                  except Errors.InstallError, e:
                      self.verbose_logger.debug(_('No package named %s available to be installed'),
                          pkg)
-@@ -2953,7 +3849,9 @@ class YumBase(depsolve.Depsolve):
+@@ -2953,7 +3850,9 @@ class YumBase(depsolve.Depsolve):
                  group_conditionals = enable_group_conditionals
  
              count_cond_test = 0
@@ -189006,7 +189033,7 @@ index 99039e0..7a5332b 100644
                  for condreq, cond in thisgroup.conditional_packages.iteritems():
                      if self.isPackageInstalled(cond):
                          try:
-@@ -2990,17 +3888,23 @@ class YumBase(depsolve.Depsolve):
+@@ -2990,17 +3889,23 @@ class YumBase(depsolve.Depsolve):
                          if cond not in self.tsInfo.conditionals:
                              self.tsInfo.conditionals[cond] = []
                          self.tsInfo.conditionals[cond].extend(pkgs)
@@ -189037,7 +189064,7 @@ index 99039e0..7a5332b 100644
          
          if not self.comps.has_group(grpid):
              raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
-@@ -3008,7 +3912,8 @@ class YumBase(depsolve.Depsolve):
+@@ -3008,7 +3913,8 @@ class YumBase(depsolve.Depsolve):
          thesegroups = self.comps.return_groups(grpid)
          if not thesegroups:
              raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
@@ -189047,7 +189074,7 @@ index 99039e0..7a5332b 100644
          for thisgroup in thesegroups:
              thisgroup.selected = False
              
-@@ -3034,13 +3939,102 @@ class YumBase(depsolve.Depsolve):
+@@ -3034,13 +3940,102 @@ class YumBase(depsolve.Depsolve):
                          for pkg in self.tsInfo.conditionals.get(txmbr.name, []):
                              self.tsInfo.remove(pkg.pkgtup)
          
@@ -189156,7 +189183,7 @@ index 99039e0..7a5332b 100644
          # look it up in the self.localPackages first:
          for po in self.localPackages:
              if po.pkgtup == pkgtup:
-@@ -3049,7 +4043,7 @@ class YumBase(depsolve.Depsolve):
+@@ -3049,7 +4044,7 @@ class YumBase(depsolve.Depsolve):
          pkgs = self.pkgSack.searchPkgTuple(pkgtup)
  
          if len(pkgs) == 0:
@@ -189165,7 +189192,7 @@ index 99039e0..7a5332b 100644
              if allow_missing: #  This can happen due to excludes after .up has
                  return None   # happened.
              raise Errors.DepError, _('Package tuple %s could not be found in packagesack') % str(pkgtup)
-@@ -3065,13 +4059,21 @@ class YumBase(depsolve.Depsolve):
+@@ -3065,13 +4060,21 @@ class YumBase(depsolve.Depsolve):
          return result
  
      def getInstalledPackageObject(self, pkgtup):
@@ -189192,7 +189219,7 @@ index 99039e0..7a5332b 100644
              raise Errors.RpmDBError, _('Package tuple %s could not be found in rpmdb') % str(pkgtup)
  
          # Dito. FIXME from getPackageObject() for len() > 1 ... :)
-@@ -3079,9 +4081,11 @@ class YumBase(depsolve.Depsolve):
+@@ -3079,9 +4082,11 @@ class YumBase(depsolve.Depsolve):
          return po
          
      def gpgKeyCheck(self):
@@ -189206,7 +189233,7 @@ index 99039e0..7a5332b 100644
          gpgkeyschecked = self.conf.cachedir + '/.gpgkeyschecked.yum'
          if os.path.exists(gpgkeyschecked):
              return 1
-@@ -3106,9 +4110,13 @@ class YumBase(depsolve.Depsolve):
+@@ -3106,9 +4111,13 @@ class YumBase(depsolve.Depsolve):
              return 1
  
      def returnPackagesByDep(self, depstring):
@@ -189222,7 +189249,7 @@ index 99039e0..7a5332b 100644
          if not depstring:
              return []
  
-@@ -3132,12 +4140,23 @@ class YumBase(depsolve.Depsolve):
+@@ -3132,12 +4141,23 @@ class YumBase(depsolve.Depsolve):
                          raise Errors.YumBaseError, _('Invalid version flag from: %s') % str(depstring)
                      depflags = SYMBOLFLAGS[flagsymbol]
  
@@ -189249,7 +189276,7 @@ index 99039e0..7a5332b 100644
          # we get all sorts of randomness here
          errstring = depstring
          if type(depstring) not in types.StringTypes:
-@@ -3149,16 +4168,22 @@ class YumBase(depsolve.Depsolve):
+@@ -3149,16 +4169,22 @@ class YumBase(depsolve.Depsolve):
              raise Errors.YumBaseError, _('No Package found for %s') % errstring
          
          ps = ListPackageSack(pkglist)
@@ -189276,7 +189303,7 @@ index 99039e0..7a5332b 100644
          if not depstring:
              return []
  
-@@ -3182,14 +4207,53 @@ class YumBase(depsolve.Depsolve):
+@@ -3182,14 +4208,53 @@ class YumBase(depsolve.Depsolve):
                          raise Errors.YumBaseError, _('Invalid version flag from: %s') % str(depstring)
                      depflags = SYMBOLFLAGS[flagsymbol]
  
@@ -189332,7 +189359,7 @@ index 99039e0..7a5332b 100644
          
          
          if len(pkglist) == 0:
-@@ -3198,14 +4262,23 @@ class YumBase(depsolve.Depsolve):
+@@ -3198,14 +4263,23 @@ class YumBase(depsolve.Depsolve):
          if len(pkglist) == 1:
              return pkglist[0]
  
@@ -189362,7 +189389,7 @@ index 99039e0..7a5332b 100644
          returnlist = []
          compatArchList = self.arch.get_arch_list(arch)
          multiLib = []
-@@ -3222,9 +4295,9 @@ class YumBase(depsolve.Depsolve):
+@@ -3222,9 +4296,9 @@ class YumBase(depsolve.Depsolve):
                  singleLib.append(po)
                  
          # we now have three lists.  find the best package(s) of each
@@ -189375,7 +189402,7 @@ index 99039e0..7a5332b 100644
  
          if single_name and multi and single and multi.name != single.name:
              # Sinlge _must_ match multi, if we want a single package name
-@@ -3238,7 +4311,7 @@ class YumBase(depsolve.Depsolve):
+@@ -3238,7 +4312,7 @@ class YumBase(depsolve.Depsolve):
          # if there's a noarch and it's newer than the multilib, we want
          # just the noarch.  otherwise, we want multi + single
          elif multi:
@@ -189384,7 +189411,7 @@ index 99039e0..7a5332b 100644
              if best.arch == "noarch":
                  returnlist.append(no)
              else:
-@@ -3246,7 +4319,7 @@ class YumBase(depsolve.Depsolve):
+@@ -3246,7 +4320,7 @@ class YumBase(depsolve.Depsolve):
                  if single: returnlist.append(single)
          # similar for the non-multilib case
          elif single:
@@ -189393,7 +189420,7 @@ index 99039e0..7a5332b 100644
              if best.arch == "noarch":
                  returnlist.append(no)
              else:
-@@ -3350,28 +4423,64 @@ class YumBase(depsolve.Depsolve):
+@@ -3350,28 +4424,65 @@ class YumBase(depsolve.Depsolve):
              done = True
  
              slow = next_func(slow)
@@ -189413,6 +189440,7 @@ index 99039e0..7a5332b 100644
 +        try: comps = self.comps
 +        except yum.Errors.GroupsError, e:
 +            # No Groups Available in any repository?
++            # This also means no installed groups, when using objects.
 +            self.logger.warning(e)
 +            return tx_return
 +
@@ -189464,7 +189492,7 @@ index 99039e0..7a5332b 100644
          try:
              txmbrs = self.groupRemove(group_string)
          except yum.Errors.GroupsError:
-@@ -3387,6 +4496,8 @@ class YumBase(depsolve.Depsolve):
+@@ -3387,6 +4498,8 @@ class YumBase(depsolve.Depsolve):
          assert pattern[0] == '@'
          grpid = pattern[1:]
  
@@ -189473,7 +189501,7 @@ index 99039e0..7a5332b 100644
          thesegroups = self.comps.return_groups(grpid)
          if not thesegroups:
              raise Errors.GroupsError, _("No Group named %s exists") % to_unicode(grpid)
-@@ -3398,7 +4509,11 @@ class YumBase(depsolve.Depsolve):
+@@ -3398,7 +4511,11 @@ class YumBase(depsolve.Depsolve):
      def _minus_deselect(self, pattern):
          """ Remove things from the transaction, like kickstart. """
          assert pattern[0] == '-'
@@ -189486,7 +189514,7 @@ index 99039e0..7a5332b 100644
  
          if pat and pat[0] == '@':
              pat = pat[1:]
-@@ -3437,14 +4552,87 @@ class YumBase(depsolve.Depsolve):
+@@ -3437,14 +4554,87 @@ class YumBase(depsolve.Depsolve):
              if flag not in self.tsInfo.probFilterFlags:
                  self.tsInfo.probFilterFlags.append(flag)
  
@@ -189580,7 +189608,7 @@ index 99039e0..7a5332b 100644
          pkgs = []
          was_pattern = False
          if po:
-@@ -3464,9 +4652,14 @@ class YumBase(depsolve.Depsolve):
+@@ -3464,9 +4654,14 @@ class YumBase(depsolve.Depsolve):
                  if kwargs['pattern'] and kwargs['pattern'][0] == '@':
                      return self._at_groupinstall(kwargs['pattern'])
  
@@ -189595,7 +189623,7 @@ index 99039e0..7a5332b 100644
                                                        ignore_case=False)
                  pkgs.extend(mypkgs)
                  # if we have anything left unmatched, let's take a look for it
-@@ -3477,20 +4670,12 @@ class YumBase(depsolve.Depsolve):
+@@ -3477,20 +4672,12 @@ class YumBase(depsolve.Depsolve):
                      self.verbose_logger.debug(_('Checking for virtual provide or file-provide for %s'), 
                          arg)
  
@@ -189622,7 +189650,7 @@ index 99039e0..7a5332b 100644
              else:
                  nevra_dict = self._nevra_kwarg_parse(kwargs)
  
-@@ -3499,6 +4684,8 @@ class YumBase(depsolve.Depsolve):
+@@ -3499,6 +4686,8 @@ class YumBase(depsolve.Depsolve):
                       ver=nevra_dict['version'], rel=nevra_dict['release'])
                  self._add_not_found_a(pkgs, nevra_dict)
                  
@@ -189631,7 +189659,7 @@ index 99039e0..7a5332b 100644
              if pkgs:
                  # if was_pattern or nevra-dict['arch'] is none, take the list
                  # of arches based on our multilib_compat config and 
-@@ -3577,17 +4764,21 @@ class YumBase(depsolve.Depsolve):
+@@ -3577,17 +4766,21 @@ class YumBase(depsolve.Depsolve):
                      continue
              
              # make sure this shouldn't be passed to update:
@@ -189657,7 +189685,7 @@ index 99039e0..7a5332b 100644
                  obsoleting_pkg = self._test_loop(po, self._pkg2obspkg)
              if obsoleting_pkg is not None:
                  # this is not a definitive check but it'll make sure we don't
-@@ -3600,23 +4791,23 @@ class YumBase(depsolve.Depsolve):
+@@ -3600,23 +4793,23 @@ class YumBase(depsolve.Depsolve):
                      already_obs = pkgs[0]
  
                  if already_obs:
@@ -189688,7 +189716,7 @@ index 99039e0..7a5332b 100644
                      continue
  
              # make sure we don't have a name.arch of this already installed
-@@ -3630,8 +4821,8 @@ class YumBase(depsolve.Depsolve):
+@@ -3630,8 +4823,8 @@ class YumBase(depsolve.Depsolve):
                          found = True
                          break
                  if not found:
@@ -189699,7 +189727,7 @@ index 99039e0..7a5332b 100644
                      tx_return.extend(txmbrs)
                      continue
  
-@@ -3719,19 +4910,47 @@ class YumBase(depsolve.Depsolve):
+@@ -3719,19 +4912,47 @@ class YumBase(depsolve.Depsolve):
          return txmbr
  
      def update(self, po=None, requiringPo=None, update_to=False, **kwargs):
@@ -189754,7 +189782,7 @@ index 99039e0..7a5332b 100644
          tx_return = []
          if not po and not kwargs: # update everything (the easy case)
              self.verbose_logger.log(logginglevels.DEBUG_2, _('Updating Everything'))
-@@ -3765,7 +4984,14 @@ class YumBase(depsolve.Depsolve):
+@@ -3765,7 +4986,14 @@ class YumBase(depsolve.Depsolve):
                      if new is None:
                          continue
                      tx_return.extend(self.update(po=new))
@@ -189770,7 +189798,7 @@ index 99039e0..7a5332b 100644
              return tx_return
  
          # complications
-@@ -3787,13 +5013,16 @@ class YumBase(depsolve.Depsolve):
+@@ -3787,13 +5015,16 @@ class YumBase(depsolve.Depsolve):
                  return self._minus_deselect(kwargs['pattern'])
  
              if kwargs['pattern'] and kwargs['pattern'][0] == '@':
@@ -189789,7 +189817,7 @@ index 99039e0..7a5332b 100644
  
              if not instpkgs and not availpkgs:
                  depmatches = []
-@@ -3805,6 +5034,8 @@ class YumBase(depsolve.Depsolve):
+@@ -3805,6 +5036,8 @@ class YumBase(depsolve.Depsolve):
                  except yum.Errors.YumBaseError, e:
                      self.logger.critical(_('%s') % e)
  
@@ -189798,7 +189826,7 @@ index 99039e0..7a5332b 100644
                  if update_to:
                      availpkgs.extend(depmatches)
                  else:
-@@ -3816,9 +5047,12 @@ class YumBase(depsolve.Depsolve):
+@@ -3816,9 +5049,12 @@ class YumBase(depsolve.Depsolve):
              try:
                  if update_to:
                      m = []
@@ -189812,7 +189840,7 @@ index 99039e0..7a5332b 100644
                      m = self.pkgSack.returnNewestByNameArch(patterns=pats)
              except Errors.PackageSackError:
                  m = []
-@@ -3843,7 +5077,7 @@ class YumBase(depsolve.Depsolve):
+@@ -3843,7 +5079,7 @@ class YumBase(depsolve.Depsolve):
                      availpkgs = self._compare_providers(availpkgs, requiringPo)
                      availpkgs = map(lambda x: x[0], availpkgs)
                  elif not availpkgs:
@@ -189821,7 +189849,7 @@ index 99039e0..7a5332b 100644
         
          # for any thing specified
          # get the list of available pkgs matching it (or take the po)
-@@ -3879,6 +5113,7 @@ class YumBase(depsolve.Depsolve):
+@@ -3879,6 +5115,7 @@ class YumBase(depsolve.Depsolve):
                      if obsoleting_pkg is None:
                          continue
                      obs_pkgs.append(obsoleting_pkg)
@@ -189829,7 +189857,7 @@ index 99039e0..7a5332b 100644
                  for obsoleting_pkg in packagesNewestByName(obs_pkgs):
                      tx_return.extend(self.install(po=obsoleting_pkg))
              for available_pkg in availpkgs:
-@@ -3920,11 +5155,29 @@ class YumBase(depsolve.Depsolve):
+@@ -3920,11 +5157,29 @@ class YumBase(depsolve.Depsolve):
                      tx_return.append(txmbr)
                          
          for available_pkg in availpkgs:
@@ -189859,7 +189887,7 @@ index 99039e0..7a5332b 100644
                  self.verbose_logger.log(logginglevels.DEBUG_2, _('Not Updating Package that is obsoleted: %s'), available_pkg)
                  tx_return.extend(self.update(po=obsoleting_pkg))
                  continue
-@@ -3985,11 +5238,18 @@ class YumBase(depsolve.Depsolve):
+@@ -3985,11 +5240,18 @@ class YumBase(depsolve.Depsolve):
          return tx_return
          
      def remove(self, po=None, **kwargs):
@@ -189883,7 +189911,7 @@ index 99039e0..7a5332b 100644
          if not po and not kwargs:
              raise Errors.RemoveError, 'Nothing specified to remove'
          
-@@ -4008,6 +5268,10 @@ class YumBase(depsolve.Depsolve):
+@@ -4008,6 +5270,10 @@ class YumBase(depsolve.Depsolve):
                      return self._at_groupremove(kwargs['pattern'])
  
                  (e,m,u) = self.rpmdb.matchPackageNames([kwargs['pattern']])
@@ -189894,7 +189922,7 @@ index 99039e0..7a5332b 100644
                  pkgs.extend(e)
                  pkgs.extend(m)
                  if u:
-@@ -4018,6 +5282,10 @@ class YumBase(depsolve.Depsolve):
+@@ -4018,6 +5284,10 @@ class YumBase(depsolve.Depsolve):
                      except yum.Errors.YumBaseError, e:
                          self.logger.critical(_('%s') % e)
                      
@@ -189905,7 +189933,7 @@ index 99039e0..7a5332b 100644
                      if not depmatches:
                          arg = to_unicode(arg)
                          self.logger.critical(_('No Match for argument: %s') % to_unicode(arg))
-@@ -4055,17 +5323,19 @@ class YumBase(depsolve.Depsolve):
+@@ -4055,17 +5325,19 @@ class YumBase(depsolve.Depsolve):
          return tx_return
  
      def installLocal(self, pkg, po=None, updateonly=False):
@@ -189935,7 +189963,7 @@ index 99039e0..7a5332b 100644
          # read in the package into a YumLocalPackage Object
          # append it to self.localPackages
          # check if it can be installed or updated based on nevra versus rpmdb
-@@ -4183,16 +5453,15 @@ class YumBase(depsolve.Depsolve):
+@@ -4183,16 +5455,15 @@ class YumBase(depsolve.Depsolve):
          return tx_return
  
      def reinstallLocal(self, pkg, po=None):
@@ -189960,7 +189988,7 @@ index 99039e0..7a5332b 100644
          if not po:
              try:
                  po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg,
-@@ -4215,13 +5484,29 @@ class YumBase(depsolve.Depsolve):
+@@ -4215,13 +5486,29 @@ class YumBase(depsolve.Depsolve):
          return self.reinstall(po=po)
  
      def reinstall(self, po=None, **kwargs):
@@ -189993,7 +190021,7 @@ index 99039e0..7a5332b 100644
          tx_mbrs = []
          if po: # The po, is the "available" po ... we want the installed po
              tx_mbrs.extend(self.remove(pkgtup=po.pkgtup))
-@@ -4240,10 +5525,11 @@ class YumBase(depsolve.Depsolve):
+@@ -4240,10 +5527,11 @@ class YumBase(depsolve.Depsolve):
              # pkgs that are obsolete.
              old_conf_obs = self.conf.obsoletes
              self.conf.obsoletes = False
@@ -190007,7 +190035,7 @@ index 99039e0..7a5332b 100644
              self.conf.obsoletes = old_conf_obs
              if len(members) == 0:
                  self.tsInfo.remove(item.pkgtup)
-@@ -4259,16 +5545,15 @@ class YumBase(depsolve.Depsolve):
+@@ -4259,16 +5547,15 @@ class YumBase(depsolve.Depsolve):
          return tx_mbrs
          
      def downgradeLocal(self, pkg, po=None):
@@ -190032,7 +190060,7 @@ index 99039e0..7a5332b 100644
          if not po:
              try:
                  po = YumUrlPackage(self, ts=self.rpmdb.readOnlyTS(), url=pkg,
-@@ -4309,13 +5594,19 @@ class YumBase(depsolve.Depsolve):
+@@ -4309,13 +5596,19 @@ class YumBase(depsolve.Depsolve):
          return False
          
      def downgrade(self, po=None, **kwargs):
@@ -190059,7 +190087,7 @@ index 99039e0..7a5332b 100644
          if not po and not kwargs:
              raise Errors.DowngradeError, 'Nothing specified to downgrade'
  
-@@ -4397,6 +5688,10 @@ class YumBase(depsolve.Depsolve):
+@@ -4397,6 +5690,10 @@ class YumBase(depsolve.Depsolve):
          # installed version. Indexed fromn the latest installed pkgtup.
          downgrade_apkgs = {}
          for pkg in sorted(apkgs):
@@ -190070,7 +190098,7 @@ index 99039e0..7a5332b 100644
              na  = (pkg.name, pkg.arch)
  
              # Here we allow downgrades from .i386 => .noarch, or .i586 => .i386
-@@ -4421,6 +5716,9 @@ class YumBase(depsolve.Depsolve):
+@@ -4421,6 +5718,9 @@ class YumBase(depsolve.Depsolve):
                  warned_nas.add(na)
                  continue
  
@@ -190080,7 +190108,7 @@ index 99039e0..7a5332b 100644
              if pkg.verGE(lipkg):
                  if na not in warned_nas:
                      msg = _('Only Upgrade available on package: %s') % pkg
-@@ -4457,7 +5755,7 @@ class YumBase(depsolve.Depsolve):
+@@ -4457,7 +5757,7 @@ class YumBase(depsolve.Depsolve):
          if e and v and r:
              evr = '%s:%s-%s' % (e, v, r)
          elif v and r:
@@ -190089,7 +190117,7 @@ index 99039e0..7a5332b 100644
          elif e and v:
              evr = '%s:%s' % (e, v)
          elif v: # e and r etc. is just too weird to print
-@@ -4500,12 +5798,24 @@ class YumBase(depsolve.Depsolve):
+@@ -4500,12 +5800,24 @@ class YumBase(depsolve.Depsolve):
  
          return returndict
  
@@ -190117,7 +190145,7 @@ index 99039e0..7a5332b 100644
          old_conf_obs = self.conf.obsoletes
          self.conf.obsoletes = False
          done = False
-@@ -4515,19 +5825,46 @@ class YumBase(depsolve.Depsolve):
+@@ -4515,19 +5827,46 @@ class YumBase(depsolve.Depsolve):
                      done = True
          for pkg in transaction.trans_data:
              if pkg.state == 'Downgrade':
@@ -190164,7 +190192,7 @@ index 99039e0..7a5332b 100644
                  if self.install(pkgtup=pkg.pkgtup):
                      done = True
          for pkg in transaction.trans_data:
-@@ -4538,8 +5875,14 @@ class YumBase(depsolve.Depsolve):
+@@ -4538,8 +5877,14 @@ class YumBase(depsolve.Depsolve):
          return done
  
      def history_undo(self, transaction):
@@ -190181,7 +190209,7 @@ index 99039e0..7a5332b 100644
          # NOTE: This is somewhat basic atm. ... for instance we don't check
          #       that we are going from the old new version. However it's still
          #       better than the RHN rollback code, and people pay for that :).
-@@ -4616,7 +5959,7 @@ class YumBase(depsolve.Depsolve):
+@@ -4616,7 +5961,7 @@ class YumBase(depsolve.Depsolve):
  
          except urlgrabber.grabber.URLGrabError, e:
              raise Errors.YumBaseError(_('GPG key retrieval failed: ') +
@@ -190190,7 +190218,7 @@ index 99039e0..7a5332b 100644
                                        
          # check for a .asc file accompanying it - that's our gpg sig on the key
          # suck it down and do the check
-@@ -4649,7 +5992,7 @@ class YumBase(depsolve.Depsolve):
+@@ -4649,7 +5994,7 @@ class YumBase(depsolve.Depsolve):
              keys_info = misc.getgpgkeyinfo(rawkey, multiple=True)
          except ValueError, e:
              raise Errors.YumBaseError(_('Invalid GPG Key from %s: %s') % 
@@ -190199,7 +190227,7 @@ index 99039e0..7a5332b 100644
          keys = []
          for keyinfo in keys_info:
              thiskey = {}
-@@ -4674,39 +6017,49 @@ class YumBase(depsolve.Depsolve):
+@@ -4674,39 +6019,49 @@ class YumBase(depsolve.Depsolve):
              if pkgs:
                  pkgs = sorted(pkgs)[-1]
                  msg = (_('Importing %s key 0x%s:\n'
@@ -190267,7 +190295,7 @@ index 99039e0..7a5332b 100644
          user_cb_fail = False
          for keyurl in keyurls:
              keys = self._retrievePublicKey(keyurl, repo)
-@@ -4725,7 +6078,9 @@ class YumBase(depsolve.Depsolve):
+@@ -4725,7 +6080,9 @@ class YumBase(depsolve.Depsolve):
                      # Try installing/updating GPG key
                      self._getKeyImportMessage(info, keyurl)
                      rc = False
@@ -190278,7 +190306,7 @@ index 99039e0..7a5332b 100644
                          rc = True
                          
                      # grab the .sig/.asc for the keyurl, if it exists
-@@ -4751,8 +6106,8 @@ class YumBase(depsolve.Depsolve):
+@@ -4751,8 +6108,8 @@ class YumBase(depsolve.Depsolve):
                  ts = self.rpmdb.readOnlyTS()
                  result = ts.pgpImportPubkey(misc.procgpgkey(info['raw_key']))
                  if result != 0:
@@ -190289,7 +190317,7 @@ index 99039e0..7a5332b 100644
                  self.logger.info(_('Key imported successfully'))
                  key_installed = True
  
-@@ -4760,18 +6115,20 @@ class YumBase(depsolve.Depsolve):
+@@ -4760,18 +6117,20 @@ class YumBase(depsolve.Depsolve):
              raise Errors.YumBaseError, _("Didn't install any keys")
  
          if not key_installed:
@@ -190315,7 +190343,7 @@ index 99039e0..7a5332b 100644
      
      def _getAnyKeyForRepo(self, repo, destdir, keyurl_list, is_cakey=False, callback=None):
          """
-@@ -4788,6 +6145,18 @@ class YumBase(depsolve.Depsolve):
+@@ -4788,6 +6147,18 @@ class YumBase(depsolve.Depsolve):
          """
  
          key_installed = False
@@ -190334,7 +190362,7 @@ index 99039e0..7a5332b 100644
          user_cb_fail = False
          for keyurl in keyurl_list:
              keys = self._retrievePublicKey(keyurl, repo, getSig=not is_cakey)
-@@ -4819,8 +6188,11 @@ class YumBase(depsolve.Depsolve):
+@@ -4819,8 +6190,11 @@ class YumBase(depsolve.Depsolve):
                  if not key_installed:
                      self._getKeyImportMessage(info, keyurl, keytype)
                      rc = False
@@ -190347,7 +190375,7 @@ index 99039e0..7a5332b 100644
                      elif callback:
                          rc = callback({"repo": repo, "userid": info['userid'],
                                          "hexkeyid": info['hexkeyid'], "keyurl": keyurl,
-@@ -4835,7 +6207,8 @@ class YumBase(depsolve.Depsolve):
+@@ -4835,7 +6209,8 @@ class YumBase(depsolve.Depsolve):
                  # Import the key
                  result = misc.import_key_to_pubring(info['raw_key'], info['hexkeyid'], gpgdir=destdir)
                  if not result:
@@ -190357,7 +190385,7 @@ index 99039e0..7a5332b 100644
                  self.logger.info(_('Key imported successfully'))
                  key_installed = True
                  # write out the key id to imported_cakeys in the repos basedir
-@@ -4851,36 +6224,35 @@ class YumBase(depsolve.Depsolve):
+@@ -4851,36 +6226,35 @@ class YumBase(depsolve.Depsolve):
                              pass
  
          if not key_installed and user_cb_fail:
@@ -190410,7 +190438,7 @@ index 99039e0..7a5332b 100644
          self._getAnyKeyForRepo(repo, repo.gpgcadir, repo.gpgcakey, is_cakey=True, callback=callback)
  
      def _limit_installonly_pkgs(self):
-@@ -4889,7 +6261,7 @@ class YumBase(depsolve.Depsolve):
+@@ -4889,7 +6263,7 @@ class YumBase(depsolve.Depsolve):
              New in 3.2.24: Obey yumdb_info.installonly data. """
  
          def _sort_and_filter_installonly(pkgs):
@@ -190419,7 +190447,7 @@ index 99039e0..7a5332b 100644
                  using the yumdb. """
              ret_beg = []
              ret_mid = []
-@@ -4917,6 +6289,10 @@ class YumBase(depsolve.Depsolve):
+@@ -4917,6 +6291,10 @@ class YumBase(depsolve.Depsolve):
  
          if self.conf.installonly_limit < 1 :
              return 
@@ -190430,7 +190458,7 @@ index 99039e0..7a5332b 100644
              
          toremove = []
          #  We "probably" want to use either self.ts or self.rpmdb.ts if either
-@@ -4926,23 +6302,30 @@ class YumBase(depsolve.Depsolve):
+@@ -4926,23 +6304,30 @@ class YumBase(depsolve.Depsolve):
          # so self.rpmdb.ts should be valid.
          ts = self.rpmdb.readOnlyTS()
          (cur_kernel_v, cur_kernel_r) = misc.get_running_kernel_version_release(ts)
@@ -190469,7 +190497,7 @@ index 99039e0..7a5332b 100644
              for po in installed:
                  if (po.version, po.release) == (cur_kernel_v, cur_kernel_r): 
                      # don't remove running
-@@ -4959,19 +6342,22 @@ class YumBase(depsolve.Depsolve):
+@@ -4959,19 +6344,22 @@ class YumBase(depsolve.Depsolve):
              txmbr.depends_on.append(rel)
  
      def processTransaction(self, callback=None,rpmTestDisplay=None, rpmDisplay=None):
@@ -190505,7 +190533,7 @@ index 99039e0..7a5332b 100644
          
          if not callback:
              callback = callbacks.ProcessTransNoOutputCallback()
-@@ -5062,8 +6448,8 @@ class YumBase(depsolve.Depsolve):
+@@ -5062,8 +6450,8 @@ class YumBase(depsolve.Depsolve):
                  raise Errors.YumRPMCheckError, retmsgs
              retmsgs = [_('ERROR with transaction check vs depsolve:')]
              retmsgs.extend(msgs) 
@@ -190516,7 +190544,7 @@ index 99039e0..7a5332b 100644
              raise Errors.YumRPMCheckError,retmsgs
          
          tsConf = {}
-@@ -5114,13 +6500,19 @@ class YumBase(depsolve.Depsolve):
+@@ -5114,13 +6502,19 @@ class YumBase(depsolve.Depsolve):
          return results
  
      def add_enable_repo(self, repoid, baseurls=[], mirrorlist=None, **kwargs):
@@ -190543,7 +190571,7 @@ index 99039e0..7a5332b 100644
          # out of place fixme - maybe we should make this the default repo addition
          # routine and use it from getReposFromConfigFile(), etc.
          newrepo = yumRepo.YumRepository(repoid)
-@@ -5167,9 +6559,15 @@ class YumBase(depsolve.Depsolve):
+@@ -5167,9 +6561,15 @@ class YumBase(depsolve.Depsolve):
  
      def setCacheDir(self, force=False, tmpdir=None, reuse=True,
                      suffix='/$basearch/$releasever'):
@@ -190562,7 +190590,7 @@ index 99039e0..7a5332b 100644
          if not force and os.geteuid() == 0:
              return True # We are root, not forced, so happy with the global dir.
          if tmpdir is None:
-@@ -5179,7 +6577,7 @@ class YumBase(depsolve.Depsolve):
+@@ -5179,7 +6579,7 @@ class YumBase(depsolve.Depsolve):
          try:
              cachedir = misc.getCacheDir(tmpdir, reuse)
          except (IOError, OSError), e:
@@ -190571,7 +190599,7 @@ index 99039e0..7a5332b 100644
              cachedir = None
              
          if cachedir is None:
-@@ -5190,6 +6588,8 @@ class YumBase(depsolve.Depsolve):
+@@ -5190,6 +6590,8 @@ class YumBase(depsolve.Depsolve):
              self.prerepoconf.cachedir = cachedir
          else:
              self.repos.setCacheDir(cachedir)
@@ -190580,7 +190608,7 @@ index 99039e0..7a5332b 100644
          self.conf.cachedir = cachedir
          return True # We got a new cache dir
  
-@@ -5220,13 +6620,24 @@ class YumBase(depsolve.Depsolve):
+@@ -5220,13 +6622,24 @@ class YumBase(depsolve.Depsolve):
          self.history.write_addon_data('config-repos', myrepos)
          
      def verify_plugins_cb(self, verify_package):
@@ -190608,7 +190636,7 @@ index 99039e0..7a5332b 100644
          if self.tsInfo._unresolvedMembers:
              if auto:
                  self.logger.critical(_("Dependencies not solved. Will not save unresolved transaction."))
-@@ -5234,7 +6645,7 @@ class YumBase(depsolve.Depsolve):
+@@ -5234,7 +6647,7 @@ class YumBase(depsolve.Depsolve):
              raise Errors.YumBaseError(_("Dependencies not solved. Will not save unresolved transaction."))
          
          if not filename:
@@ -190617,7 +190645,7 @@ index 99039e0..7a5332b 100644
              fd,filename = tempfile.mkstemp(suffix='.yumtx', prefix=prefix)
              f = os.fdopen(fd, 'w')
          else:
-@@ -5244,13 +6655,17 @@ class YumBase(depsolve.Depsolve):
+@@ -5244,13 +6657,17 @@ class YumBase(depsolve.Depsolve):
          
          msg = "%s\n" % self.rpmdb.simpleVersion(main_only=True)[0]
          msg += "%s\n" % self.ts.getTsFlags()
@@ -190638,7 +190666,7 @@ index 99039e0..7a5332b 100644
          msg += "%s\n" % len(self.tsInfo.getMembers())
          for txmbr in self.tsInfo.getMembers():
              msg += txmbr._dump()
-@@ -5260,42 +6675,84 @@ class YumBase(depsolve.Depsolve):
+@@ -5260,42 +6677,84 @@ class YumBase(depsolve.Depsolve):
          except (IOError, OSError), e:
              self._ts_save_file = None
              if auto:
@@ -190735,7 +190763,7 @@ index 99039e0..7a5332b 100644
              if ignorerpm:
                  msg += _(" ignoring, as requested.")
                  self.logger.critical(_(msg))
-@@ -5318,8 +6775,17 @@ class YumBase(depsolve.Depsolve):
+@@ -5318,8 +6777,17 @@ class YumBase(depsolve.Depsolve):
          numrepos = int(data[2].strip())
          repos = []
          rindex=3+numrepos
@@ -190754,7 +190782,7 @@ index 99039e0..7a5332b 100644
  
          # pkgs/txmbrs
          numpkgs = int(data[rindex].strip())
-@@ -5329,6 +6795,7 @@ class YumBase(depsolve.Depsolve):
+@@ -5329,6 +6797,7 @@ class YumBase(depsolve.Depsolve):
          pkgcount = 0
          pkgprob = False
          curpkg = None
@@ -190762,7 +190790,7 @@ index 99039e0..7a5332b 100644
          for l in data[pkgstart:]:
              l = l.rstrip()
              # our main txmbrs
-@@ -5356,6 +6823,7 @@ class YumBase(depsolve.Depsolve):
+@@ -5356,6 +6825,7 @@ class YumBase(depsolve.Depsolve):
                      if not ignoremissing:
                          raise Errors.YumBaseError(msg)
                      else:
@@ -190770,7 +190798,7 @@ index 99039e0..7a5332b 100644
                          self.logger.critical(msg)
                  else:
                      pkgcount += 1
-@@ -5432,12 +6900,18 @@ class YumBase(depsolve.Depsolve):
+@@ -5432,12 +6902,18 @@ class YumBase(depsolve.Depsolve):
          if pkgprob:
              msg = _("Transaction members, relations are missing or ts has been modified,")
              if ignoremissing:
@@ -190789,7 +190817,7 @@ index 99039e0..7a5332b 100644
          return self.tsInfo.getMembers()
  
      def _remove_old_deps(self):
-@@ -5470,18 +6944,6 @@ class YumBase(depsolve.Depsolve):
+@@ -5470,18 +6946,6 @@ class YumBase(depsolve.Depsolve):
                      if requiring == required: # if they are self-requiring skip them
                          continue
                          
@@ -190808,7 +190836,7 @@ index 99039e0..7a5332b 100644
                      #for tbi_pkg in self.tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
                      #   for reqtuple in tbi_pkg.po.requires:
                      #        if required.provides_for(reqtuple):
-@@ -5533,7 +6995,24 @@ class YumBase(depsolve.Depsolve):
+@@ -5533,7 +6997,24 @@ class YumBase(depsolve.Depsolve):
                      # Debugging output
                      self.verbose_logger.log(logginglevels.DEBUG_2, _("%s has revdep %s which was user-installed."), pkg, curpkg)
                      ok_to_remove[pkg] = False
@@ -190833,7 +190861,7 @@ index 99039e0..7a5332b 100644
                  visited[curpkg] = True
              all_leaves_visited = True
              leaves = curpkg.requiring_packages()
-@@ -5547,4 +7026,3 @@ class YumBase(depsolve.Depsolve):
+@@ -5547,4 +7028,3 @@ class YumBase(depsolve.Depsolve):
          # Debugging output
          self.verbose_logger.log(logginglevels.DEBUG_2, _("%s has no user-installed revdeps."), pkg)
          return False
@@ -190986,7 +191014,7 @@ index 7ad25ce..a9a8e53 100644
          pass
          
 diff --git a/yum/comps.py b/yum/comps.py
-index 65f6d5e..af79a55 100755
+index 65f6d5e..706e2a4 100755
 --- a/yum/comps.py
 +++ b/yum/comps.py
 @@ -16,14 +16,14 @@
@@ -191024,7 +191052,7 @@ index 65f6d5e..af79a55 100755
      def ui_name(self):
          """ Return the "name" of the object for the current locale. """
          return self.nameByLang(get_my_lang_code())
-@@ -108,7 +118,7 @@ class Group(CompsObj):
+@@ -108,12 +118,14 @@ class Group(CompsObj):
          self.optional_packages = {}
          self.default_packages = {}
          self.conditional_packages = {}
@@ -191033,7 +191061,14 @@ index 65f6d5e..af79a55 100755
          self.groupid = None
          self.display_order = 1024
          self.installed = False
-@@ -191,6 +201,10 @@ class Group(CompsObj):
+         self.toremove = False
+ 
++        self._weak = False
++
+         if elem:
+             self.parse(elem)
+ 
+@@ -191,6 +203,10 @@ class Group(CompsObj):
                      continue
  
                  package = child.text
@@ -191044,7 +191079,7 @@ index 65f6d5e..af79a55 100755
                  if genre == 'mandatory':
                      self.mandatory_packages[package] = 1
                  elif genre == 'default':
-@@ -271,6 +285,155 @@ class Group(CompsObj):
+@@ -271,6 +287,157 @@ class Group(CompsObj):
  
          return msg      
  
@@ -191064,6 +191099,8 @@ index 65f6d5e..af79a55 100755
 +        self._options = {}
 +        self._defaultoptions = {}
 +
++        self._weak = False
++
 +        if elem:
 +            self.parse(elem)
 +
@@ -191148,7 +191185,7 @@ index 65f6d5e..af79a55 100755
 +                    self._defaultoptions[optionid] = 1
 +
 +    def add(self, obj):
-+        """Add another category object to this object"""
++        """Add another environment object to this object"""
 +
 +        for grp in obj.groups:
 +            self._groups[grp] = 1
@@ -191200,7 +191237,7 @@ index 65f6d5e..af79a55 100755
  
  class Category(CompsObj):
      """ Category object parsed from group data in each repo. and merged. """
-@@ -371,12 +534,61 @@ class Category(CompsObj):
+@@ -371,12 +538,61 @@ class Category(CompsObj):
          msg += """  </category>\n"""
  
          return msg                
@@ -191263,7 +191300,7 @@ index 65f6d5e..af79a55 100755
          self.compscount = 0
          self.overwrite_groups = overwrite_groups
          self.compiled = False # have groups been compiled into avail/installed 
-@@ -387,14 +599,24 @@ class Comps(object):
+@@ -387,14 +603,24 @@ class Comps(object):
          grps = self._groups.values()
          grps.sort(key=lambda x: (x.display_order, x.name))
          return grps
@@ -191289,7 +191326,7 @@ index 65f6d5e..af79a55 100755
      
      def has_group(self, grpid):
          exists = self.return_groups(grpid)
-@@ -416,6 +638,9 @@ class Comps(object):
+@@ -416,6 +642,9 @@ class Comps(object):
          """return all groups which match either by glob or exact match"""
          returns = {}
  
@@ -191299,7 +191336,7 @@ index 65f6d5e..af79a55 100755
          for item in group_pattern.split(','):
              item = item.strip()
              if item in self._groups:
-@@ -447,6 +672,60 @@ class Comps(object):
+@@ -447,6 +676,60 @@ class Comps(object):
  
          return returns.values()
  
@@ -191360,13 +191397,27 @@ index 65f6d5e..af79a55 100755
      #  This is close to returnPackages() etc. API ... need to std. these names
      # the above return_groups uses different, but equal, API.
      def return_categories(self, pattern, ignore_case=True):
-@@ -490,6 +769,13 @@ class Comps(object):
+@@ -486,10 +769,27 @@ class Comps(object):
+     def add_group(self, group):
+         if group.groupid in self._groups:
+             thatgroup = self._groups[group.groupid]
++            if thatgroup._weak:
++                # If what we had was weak, use this one and merge the weak one.
++                tmp = group
++                group = thatgroup
++                thatgroup = self._groups[group.groupid] = tmp
+             thatgroup.add(group)
          else:
              self._groups[group.groupid] = group
  
 +    def add_environment(self, environment):
 +        if environment.environmentid in self._environments:
 +            env = self._environments[environment.environmentid]
++            if env._weak:
++                # If what we had was weak, use this one and merge the weak one.
++                tmp = environment
++                environment = env
++                env = self._environments[environment.environmentid] = tmp
 +            env.add(environment)
 +        else:
 +            self._environments[environment.environmentid] = environment
@@ -191374,7 +191425,7 @@ index 65f6d5e..af79a55 100755
      def add_category(self, category):
          if category.categoryid in self._categories:
              thatcat = self._categories[category.categoryid]
-@@ -497,6 +783,9 @@ class Comps(object):
+@@ -497,6 +797,9 @@ class Comps(object):
          else:
              self._categories[category.categoryid] = category
  
@@ -191384,7 +191435,7 @@ index 65f6d5e..af79a55 100755
      def add(self, srcfile = None):
          if not srcfile:
              raise CompsException
-@@ -520,9 +809,14 @@ class Comps(object):
+@@ -520,9 +823,14 @@ class Comps(object):
                  if elem.tag == "group":
                      group = Group(elem)
                      self.add_group(group)
@@ -191399,7 +191450,7 @@ index 65f6d5e..af79a55 100755
          except SyntaxError, e:
              raise CompsException, "comps file is empty/damaged"
              
-@@ -557,13 +851,32 @@ class Comps(object):
+@@ -557,13 +865,32 @@ class Comps(object):
                      if pkgname in inst_pkg_names:
                          group.installed = True
                          break
@@ -191433,7 +191484,7 @@ index 65f6d5e..af79a55 100755
              return ""
              
          msg = """<?xml version="1.0" encoding="UTF-8"?>
-@@ -575,7 +888,9 @@ class Comps(object):
+@@ -575,7 +902,9 @@ class Comps(object):
              msg += g.xml()
          for c in self.get_categories():
              msg += c.xml()
@@ -191444,7 +191495,7 @@ index 65f6d5e..af79a55 100755
          msg += """\n</comps>\n"""
          
          return msg
-@@ -590,16 +905,34 @@ def main():
+@@ -590,16 +919,34 @@ def main():
          for srcfile in sys.argv[1:]:
              p.add(srcfile)
  
@@ -191484,7 +191535,7 @@ index 65f6d5e..af79a55 100755
          print >> sys.stderr, "newcomps.py: No such file:\'%s\'" % sys.argv[1]
          sys.exit(1)
 diff --git a/yum/config.py b/yum/config.py
-index d09511f..cd3ef2e 100644
+index d09511f..1d446c0 100644
 --- a/yum/config.py
 +++ b/yum/config.py
 @@ -45,15 +45,18 @@ from misc import get_uuid, read_in_items_from_dot_dir
@@ -192154,7 +192205,7 @@ index d09511f..cd3ef2e 100644
          warnings.warn('setConfigOption() will go away in a future version of Yum.\n'
                  'Please set option values as attributes or using setattr().',
                  DeprecationWarning)
-@@ -603,11 +705,10 @@ class BaseConfig(object):
+@@ -603,13 +705,12 @@ class BaseConfig(object):
              raise Errors.ConfigError, 'No such option %s' % option
  
  class StartupConf(BaseConfig):
@@ -192168,8 +192219,11 @@ index d09511f..cd3ef2e 100644
 +    the other [main] options can be parsed.
 +    """
      # xemacs highlighting hack: '
-     debuglevel = IntOption(2, 0, 10)
+-    debuglevel = IntOption(2, 0, 10)
++    debuglevel = IntOption(2, -4, 10)
      errorlevel = IntOption(2, 0, 10)
+ 
+     distroverpkg = Option('redhat-release')
 @@ -625,13 +726,13 @@ class StartupConf(BaseConfig):
      persistdir = Option('/var/lib/yum')
      
@@ -192567,7 +192621,7 @@ index d09511f..cd3ef2e 100644
  
          if name not in cfgOptions and option.default == value:
 diff --git a/yum/depsolve.py b/yum/depsolve.py
-index 6d744c0..dcfd05a 100644
+index 6d744c0..7002205 100644
 --- a/yum/depsolve.py
 +++ b/yum/depsolve.py
 @@ -31,13 +31,15 @@ from transactioninfo import TransactionMember
@@ -192983,7 +193037,7 @@ index 6d744c0..dcfd05a 100644
  
          todel = []
          for fname in self.installedFileProviders:
-@@ -1149,7 +1312,76 @@ class Depsolve(object):
+@@ -1149,7 +1312,74 @@ class Depsolve(object):
          self.rpmdb.transactionCacheConflictPackages(cpkgs)
          return ret
  
@@ -193018,8 +193072,7 @@ index 6d744c0..dcfd05a 100644
 +                    if po.obsoletedBy([otxmbr.po]): # Loops, hope for rpm.
 +                        continue
 +                    msg = _('Removing %s due to obsoletes from installed %s')
-+                    self.verbose_logger.log(logginglevels.DEBUG_1,
-+                                            msg, otxmbr, po)
++                    self.verbose_logger.warning(msg, otxmbr, po)
 +                    _do_obs(otxmbr)
 +                    ret = True
 +
@@ -193043,8 +193096,7 @@ index 6d744c0..dcfd05a 100644
 +                        # Have to deal with loops! Hope rpm behaves too.
 +                        continue
 +                    msg = _('Removing %s due to obsoletes from %s')
-+                    self.verbose_logger.log(logginglevels.DEBUG_1,
-+                                            msg, otxmbr, txmbr)
++                    self.verbose_logger.warning(msg, otxmbr, txmbr)
 +                    _do_obs(otxmbr)
 +                    ret = True
 +
@@ -193060,7 +193112,7 @@ index 6d744c0..dcfd05a 100644
          lst = self.tsInfo.matchNaevr(name = pkgname)
          for txmbr in lst:
              if txmbr.output_state in TS_INSTALL_STATES:
-@@ -1166,7 +1398,7 @@ class Depsolve(object):
+@@ -1166,7 +1396,7 @@ class Depsolve(object):
          return True
      _isPackageInstalled = isPackageInstalled
  
@@ -193069,7 +193121,7 @@ index 6d744c0..dcfd05a 100644
          """take the list of pkgs and score them based on the requesting package
             return a dictionary of po=score"""
          self.verbose_logger.log(logginglevels.DEBUG_4,
-@@ -1210,6 +1442,24 @@ class Depsolve(object):
+@@ -1210,6 +1440,24 @@ class Depsolve(object):
                  return None
              return x
  
@@ -193094,7 +193146,7 @@ index 6d744c0..dcfd05a 100644
          #  Actual start of _compare_providers().
  
          # Do a NameArch filtering, based on repo. __cmp__
-@@ -1332,6 +1582,29 @@ class Depsolve(object):
+@@ -1332,6 +1580,29 @@ class Depsolve(object):
                          _('common prefix of %s between %s and %s' % (cpl, po, reqpo)))
                  
                      pkgresults[po] += cpl*2
@@ -193124,7 +193176,7 @@ index 6d744c0..dcfd05a 100644
                  
          #  If we have more than one "best", see what would happen if we picked
          # each package ... ie. what things do they require that _aren't_ already
-@@ -1393,42 +1666,52 @@ class Depsolve(object):
+@@ -1393,42 +1664,52 @@ class Depsolve(object):
  
  
  class DepCheck(object):
@@ -193193,10 +193245,10 @@ index 6d744c0..dcfd05a 100644
          self.conflict = conflict # what the conflict was between them
 diff --git a/yum/drpm.py b/yum/drpm.py
 new file mode 100644
-index 0000000..b5bdee3
+index 0000000..2e23241
 --- /dev/null
 +++ b/yum/drpm.py
-@@ -0,0 +1,328 @@
+@@ -0,0 +1,330 @@
 +#  Integrated delta rpm support
 +#  Copyright 2013 Zdenek Pavlas
 +
@@ -193452,7 +193504,9 @@ index 0000000..b5bdee3
 +            elif not po.rpm.verifyLocalPkg():
 +                self.adderror(po, _('Checksum of the delta-rebuilt RPM failed'))
 +            else:
-+                os.unlink(po.localpath)
++                # done with drpm file, unlink when local
++                if po.localpath.startswith(po.repo.pkgdir):
++                    os.unlink(po.localpath)
 +                po.localpath = po.rpm.localpath # for --downloadonly
 +            num += 1
 +
@@ -194917,7 +194971,7 @@ index aaa4f25..a2c5135 100755
                  continue
  
 diff --git a/yum/misc.py b/yum/misc.py
-index 2f6ddfe..3800811 100644
+index 2f6ddfe..7dcd215 100644
 --- a/yum/misc.py
 +++ b/yum/misc.py
 @@ -5,9 +5,11 @@ Assorted utility functions for yum.
@@ -195135,7 +195189,7 @@ index 2f6ddfe..3800811 100644
          os.unlink(filename)
      except OSError, e:
 -        if e.errno != errno.ENOENT:
-+        if e.errno not in (errno.ENOENT, errno.EPERM):
++        if e.errno not in (errno.ENOENT, errno.EPERM, errno.EROFS):
              raise
  
 -def stat_f(filename):
@@ -196494,7 +196548,7 @@ index 31b1080..97e6797 100755
              tags += """ </tags>\n"""
              msg += tags
 diff --git a/yum/repos.py b/yum/repos.py
-index 3793bad..67ef1e4 100644
+index 3793bad..5d6bc99 100644
 --- a/yum/repos.py
 +++ b/yum/repos.py
 @@ -15,13 +15,14 @@
@@ -196522,7 +196576,7 @@ index 3793bad..67ef1e4 100644
          A "better" fix might be to explicitly pass the YumBase instance to
          the callback ... API change! """
      def __init__(self, ayum, ca=False):
-@@ -67,8 +68,57 @@ class RepoStorage:
+@@ -67,8 +68,58 @@ class RepoStorage:
          self._cache_enabled_repos = []
          self.quick_enable_disable = {}
  
@@ -196546,6 +196600,7 @@ index 3793bad..67ef1e4 100644
 +                dl = repo._async and repo._commonLoadRepoXML(repo)
 +            except Errors.RepoError, e:
 +                if not repo.skip_if_unavailable:
++                    e.repo = repo
 +                    raise
 +                self.disableRepo(repo.id)
 +                dl = False
@@ -196580,7 +196635,7 @@ index 3793bad..67ef1e4 100644
          self.ayum.plugins.run('prereposetup')
          
          if thisrepo is None:
-@@ -79,6 +129,17 @@ class RepoStorage:
+@@ -79,6 +130,17 @@ class RepoStorage:
          if len(repos) < 1:
              self.logger.debug('No Repositories Available to Set Up')
  
@@ -196598,7 +196653,7 @@ index 3793bad..67ef1e4 100644
          for repo in repos:
              repo.setup(self.ayum.conf.cache, self.ayum.mediagrabber,
                     gpg_import_func = self.gpg_import_func, confirm_func=self.confirm_func,
-@@ -87,8 +148,13 @@ class RepoStorage:
+@@ -87,8 +149,13 @@ class RepoStorage:
              # so nothing else touches us
              if not repo.enabled:
                  self.disableRepo(repo.id)
@@ -196612,7 +196667,7 @@ index 3793bad..67ef1e4 100644
          self.ayum.plugins.run('postreposetup')
          
      def __str__(self):
-@@ -135,17 +201,25 @@ class RepoStorage:
+@@ -135,17 +202,25 @@ class RepoStorage:
              raise Errors.RepoError, \
                  'Error getting repository data for %s, repository not found' % (repoid)
  
@@ -196641,7 +196696,7 @@ index 3793bad..67ef1e4 100644
          return result
          
      def disableRepo(self, repoid):
-@@ -187,6 +261,10 @@ class RepoStorage:
+@@ -187,6 +262,10 @@ class RepoStorage:
      def listEnabled(self):
          """return list of enabled repo objects"""
  
@@ -196652,7 +196707,7 @@ index 3793bad..67ef1e4 100644
          if (self._cache_enabled_repos is not None and
              not self.quick_enable_disable):
              return self._cache_enabled_repos
-@@ -223,15 +301,16 @@ class RepoStorage:
+@@ -223,15 +302,16 @@ class RepoStorage:
          
          self._cachedir = cachedir
          for repo in self.repos.values():
@@ -196673,7 +196728,7 @@ index 3793bad..67ef1e4 100644
  
      def setFailureCallback(self, obj):
          """sets the failure callback for all repos"""
-@@ -288,6 +367,16 @@ class RepoStorage:
+@@ -288,6 +368,16 @@ class RepoStorage:
          else:
              data = [ mdtype ]
           
@@ -196690,7 +196745,15 @@ index 3793bad..67ef1e4 100644
          for repo in myrepos:
              sack = repo.getPackageSack()
              try:
-@@ -329,6 +418,11 @@ class Repository:
+@@ -296,6 +386,7 @@ class RepoStorage:
+                 if mdtype in ['all', 'metadata'] and repo.skip_if_unavailable:
+                     self.disableRepo(repo.id)
+                 else:
++                    e.repo = repo
+                     raise
+             else:
+                 self.pkgSack.addSack(repo.id, sack)
+@@ -329,6 +420,11 @@ class Repository:
      def __del__(self):
          self.close()
  
@@ -203482,7 +203545,7 @@ index 4dcbea7..03fc58a 100644
 +
 +        return 0, [basecmd + ' ' + subcommand + ' done']
 diff --git a/yummain.py b/yummain.py
-index 9f79f4f..ac94f65 100755
+index 9f79f4f..2535d65 100755
 --- a/yummain.py
 +++ b/yummain.py
 @@ -29,13 +29,13 @@ from yum import Errors
@@ -203502,7 +203565,59 @@ index 9f79f4f..ac94f65 100755
  
      yum.misc.setup_locale(override_time=True)
  
-@@ -89,6 +89,23 @@ def main(args):
+@@ -68,6 +68,51 @@ def main(args):
+         if unlock(): return 200
+         return 1
+ 
++    def exRepoError(e):
++        # For RepoErrors ... help out by forcing new repodata next time.
++        base.cleanExpireCache()
++
++        msg = _("""\
++ One of the configured repositories failed (%(repo)s), and yum doesn't have
++enough cached data to continue. At this point the only safe thing yum can do
++is fail.
++ There are a few ways to work "fix" this:
++
++     1. Contact the upstream for the repository and get them to fix the problem.
++
++     2. Reconfigure the baseurl/etc. for the repository, to point to a working
++        upstream. This is most often useful if you are using a newer
++        distribution release than is supported by the repository (and the
++        packages for the previous distribution release still work).
++
++     3. Disable the repository, so yum won't use it by default. Yum will then
++        just ignore the repository until you permanently enable it again or use
++        --enablerepo for temporary usage:
++
++            yum-config-manager --disable %(repoid)s
++
++     4. Configure the failing repository to be skipped, if it is unavailable.
++        Note that yum will try to contact the repo. when it runs most commands,
++        so will have to try and fail each time (and thus. yum will be be much
++        slower). If it is a very temporary problem though, this is often a nice
++        compromise:
++
++            yum-config-manager --save --setopt=skip_if_unavailable=true %(repoid)s
++""")
++
++        repoui = _('Unknown')
++        repoid = _('<repoid>')
++        if hasattr(e, 'repo'):
++            repoid = e.repo.id
++            repoui = e.repo.name
++
++        msg = msg % {'repoid' : repoid, 'repo' : repoui}
++
++        logger.critical('\n\n%s\n%s', msg, exception2msg(e))
++
++        if unlock(): return 200
++        return 1
++
+     def unlock():
+         try:
+             base.closeRpmDB()
+@@ -89,6 +134,23 @@ def main(args):
      logger = logging.getLogger("yum.main")
      verbose_logger = logging.getLogger("yum.verbose.main")
  
@@ -203526,7 +203641,7 @@ index 9f79f4f..ac94f65 100755
      # our core object for the cli
      base = cli.YumBaseCli()
  
-@@ -100,46 +117,20 @@ def main(args):
+@@ -100,46 +162,20 @@ def main(args):
          return exPluginExit(e)
      except Errors.YumBaseError, e:
          return exFatal(e)
@@ -203535,7 +203650,7 @@ index 9f79f4f..ac94f65 100755
  
 -    # Try to open the current directory to see if we have 
 -    # read and write access. If not, chdir to /
--    try:
+     try:
 -        f = open(".")
 -    except IOError, e:
 -        if e.errno == errno.EACCES:
@@ -203567,21 +203682,20 @@ index 9f79f4f..ac94f65 100755
 -                return 1
 -        else:
 -            break
-+    base.waitForLock()
++        base.waitForLock()
++    except Errors.YumBaseError, e:
++        return exFatal(e)
  
      try:
          result, resultmsgs = base.doCommands()
      except plugins.PluginYumExit, e:
          return exPluginExit(e)
 +    except Errors.RepoError, e:
-+        result = 1
-+        resultmsgs = [exception2msg(e)]
-+        # For RepoErrors ... help out by forcing new repodata next time.
-+        base.cleanExpireCache()
++        return exRepoError(e)
      except Errors.YumBaseError, e:
          result = 1
          resultmsgs = [exception2msg(e)]
-@@ -154,7 +145,7 @@ def main(args):
+@@ -154,7 +190,7 @@ def main(args):
          for msg in resultmsgs:
              verbose_logger.log(logginglevels.INFO_2, '%s', msg)
          if unlock(): return 200
@@ -203590,19 +203704,16 @@ index 9f79f4f..ac94f65 100755
      elif result == 1:
          # Fatal error
          for msg in resultmsgs:
-@@ -181,6 +172,11 @@ def main(args):
+@@ -181,6 +217,8 @@ def main(args):
          (result, resultmsgs) = base.buildTransaction() 
      except plugins.PluginYumExit, e:
          return exPluginExit(e)
 +    except Errors.RepoError, e:
-+        result = 1
-+        resultmsgs = [exception2msg(e)]
-+        # For RepoErrors ... help out by forcing new repodata next time.
-+        base.cleanExpireCache()
++        return exRepoError(e)
      except Errors.YumBaseError, e:
          result = 1
          resultmsgs = [exception2msg(e)]
-@@ -193,7 +189,7 @@ def main(args):
+@@ -193,7 +231,7 @@ def main(args):
      if result == 0:
          # Normal exit
          if unlock(): return 200
@@ -203611,19 +203722,16 @@ index 9f79f4f..ac94f65 100755
      elif result == 1:
          # Fatal error
          for msg in resultmsgs:
-@@ -223,6 +219,11 @@ def main(args):
+@@ -223,6 +261,8 @@ def main(args):
          return_code = base.doTransaction()
      except plugins.PluginYumExit, e:
          return exPluginExit(e)
 +    except Errors.RepoError, e:
-+        result = 1
-+        resultmsgs = [exception2msg(e)]
-+        # For RepoErrors ... help out by forcing new repodata next time.
-+        base.cleanExpireCache()
++        return exRepoError(e)
      except Errors.YumBaseError, e:
          return exFatal(e)
      except KeyboardInterrupt:
-@@ -238,16 +239,27 @@ def main(args):
+@@ -238,16 +278,27 @@ def main(args):
          rpmdb_warn_checks()
          return_code = result
          if base._ts_save_file:
@@ -203653,7 +203761,7 @@ index 9f79f4f..ac94f65 100755
      import hotshot.stats
      fn = os.path.expanduser("~/yum.prof")
      prof = hotshot.Profile(fn)
-@@ -257,6 +269,11 @@ def hotshot(func, *args, **kwargs):
+@@ -257,6 +308,11 @@ def hotshot(func, *args, **kwargs):
      return rc
  
  def cprof(func, *args, **kwargs):
@@ -203665,7 +203773,7 @@ index 9f79f4f..ac94f65 100755
      import cProfile, pstats
      fn = os.path.expanduser("~/yum.prof")
      prof = cProfile.Profile()
-@@ -266,6 +283,10 @@ def cprof(func, *args, **kwargs):
+@@ -266,6 +322,10 @@ def cprof(func, *args, **kwargs):
      return rc
  
  def print_stats(stats):
@@ -203676,7 +203784,7 @@ index 9f79f4f..ac94f65 100755
      stats.strip_dirs()
      stats.sort_stats('time', 'calls')
      stats.print_stats(20)
-@@ -273,7 +294,14 @@ def print_stats(stats):
+@@ -273,7 +333,14 @@ def print_stats(stats):
      stats.print_stats(40)
  
  def user_main(args, exit_code=False):
diff --git a/yum.spec b/yum.spec
index 5aaf5cc..c1385c2 100644
--- a/yum.spec
+++ b/yum.spec
@@ -41,7 +41,7 @@ BuildRequires: bash-completion
 Summary: RPM package installer/updater/manager
 Name: yum
 Version: 3.4.3
-Release: 107%{?dist}
+Release: 108%{?dist}
 License: GPLv2+
 Group: System Environment/Base
 Source0: http://yum.baseurl.org/download/3.4/%{name}-%{version}.tar.gz
@@ -403,6 +403,14 @@ exit 0
 %endif
 
 %changelog
+* Wed Aug 28 2013 James Antill <james at fedoraproject.org> - 3.4.3-108
+- Update to latest HEAD.
+- Use new comps. mock objects to re-integrate group removal. BZ 996866.
+- Add "weak" comps. groups, for installed groups.
+- Add msg. to help users deal with RepoError failures. BZ 867389.
+- Give msgs about install/trans. obsoletes a higher priority. BZ 991080.
+- waitForLock() raises YumBaseError. BZ 1001154.
+
 * Sun Aug 25 2013 James Antill <james at fedoraproject.org> - 3.4.3-107
 - Update to latest HEAD.
 - Pass requirement to compare_proviers so we can use provides version compare.


More information about the scm-commits mailing list