Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > e53c27ce7a27944d2cee0a028d0ccfc9 > files > 29

yum-3.2.22-37.sl.src.rpm

commit 19ca16052d295bffb6ece2fc3410e37ffe6336e5
Author: James Antill <james@and.org>
Date:   Tue Apr 7 23:03:25 2009 -0400

    Add clean expire-cache, to the man page

diff --git a/docs/yum.8 b/docs/yum.8
index 0e65dcb..2100c8a 100644
--- a/docs/yum.8
+++ b/docs/yum.8
@@ -356,6 +356,9 @@ mode. Note that "all files" in the commands below means
 If you want to also clean any (temporarily) disabled repositories you need to
 use \fB--enablerepo='*'\fP option.
 
+.IP "\fByum clean expire-cache\fP"
+Eliminate the local data saying when the metadata and mirrorlists were downloaded for each repo. This means yum will revalidate the cache for each repo. next time it is used. However if the cache is still valid, nothing significant was deleted.
+
 .IP "\fByum clean packages\fP"
 Eliminate any cached packages from the system.  Note that packages are not automatically deleted after they are downloaded.
 
commit fccb827e4e63f3e7d30555af1bfa4399504e328c
Author: James Antill <james@and.org>
Date:   Tue Apr 7 23:14:57 2009 -0400

    Add extra "hidden" features documentation for some commands

diff --git a/docs/yum.8 b/docs/yum.8
index 2100c8a..379169a 100644
--- a/docs/yum.8
+++ b/docs/yum.8
@@ -43,7 +43,7 @@ gnome\-packagekit application\&.
 .br
 .I \fR * groupupdate group1 [group2] [\&.\&.\&.]
 .br 
-.I \fR * grouplist [hidden]
+.I \fR * grouplist [hidden] [groupwildcard] [\&.\&.\&.]
 .br
 .I \fR * groupremove group1 [group2] [\&.\&.\&.]
 .br
@@ -81,14 +81,20 @@ group of packages while ensuring that all dependencies are
 satisfied\&.  If no package matches the given package name(s), they are
 assumed to be a shell glob and any matches are then installed\&. If the
 name starts with an @ character the rest of the name is used as though
-passed to the groupinstall command\&.
+passed to the groupinstall command\&. If the name is a file, then install works
+like localinstall\&. If the name doesn't match a package, then package
+"provides" are searched (Eg. "_sqlitecache.so()(64bit)") as are
+filelists (Eg. "/usr/bin/yum"). Also note that for filelists, wildcards will
+match multiple packages\&.
 .IP 
 .IP "\fBupdate\fP"
 If run without any packages, update will update every currently
 installed package.  If one or more packages or package globs are specified, Yum will
 only update the listed packages\&.  While updating packages, \fByum\fP
-will ensure that all dependencies are satisfied\&. If the packages or globs specified
-match to packages which are not currently installed then update will not install them\&.
+will ensure that all dependencies are satisfied\&. If the packages or globs
+specified match to packages which are not currently installed then update will
+not install them\&. update operates on groups, files, provides and filelists
+just like the "install" command\&.
 
 If the main obsoletes configure option is true (default) or the \-\-obsoletes
 flag is present \fByum\fP will include package 
@@ -110,7 +116,8 @@ for more details.
 .IP "\fBremove\fP or \fBerase\fP"
 Are used to remove the specified packages from the system
 as well as removing any packages which depend on the package being
-removed\&.
+removed\&. remove operates on groups, files, provides and filelists just like
+the "install" command\&.
 .IP 
 .IP "\fBlist\fP"
 Is used to list various information about available
@@ -171,7 +178,9 @@ by "groupremove Y" does not do give you the same result as "groupinstall X".
 Is used to give the description and package list of a group (and which type
 those packages are marked as). Note that you can use the yum-filter-data and
 yum-list-data plugins to get/use the data the other way around (Ie. what
-groups own packages need updating).
+groups own packages need updating). If you pass the -v option, to enable verbose
+mode, then the package names are matched against installed/available packages
+similar to the list command.
 .IP 
 .IP "\fBshell\fP"
 Is used to enter the 'yum shell', when a filename is specified the contents of
@@ -183,24 +192,28 @@ package is listed per dependency.
 .IP
 .IP "\fBlocalinstall\fP"
 Is used to install a set of local rpm files. If required the enabled 
-repositories will be used to resolve dependencies. 
+repositories will be used to resolve dependencies. Note that the install command
+will do a local install, if given a filename.
 .IP
 .IP "\fBlocalupdate\fP"
 Is used to update the system by specifying local rpm files. Only the specified 
 rpm files of which an older version is already installed will be installed,
 the remaining specified packages will be ignored.
-If required the enabled repositories will be used to resolve dependencies.
+If required the enabled repositories will be used to resolve dependencies. Note
+that the update command will do a local install, if given a filename.
 .IP
 .IP "\fBreinstall\fP"
 Will reinstall the identically versioned package as is currently installed. 
-This does not work for "installonly" packages, like Kernels.
+This does not work for "installonly" packages, like Kernels. reinstall operates
+on groups, files, provides and filelists just like the "install" command\&.
 .IP
 .IP "\fBdowngrade\fP"
 Will try and downgrade a package from the version currently installed to the
 previously highest version (or the specified version).
 The depsolver will not necessarily work, but if you specify all the packages it
 should work (and thus. all the simple cases will work). Also this does not
-work for "installonly" packages, like Kernels.
+work for "installonly" packages, like Kernels. downgrade operates
+on groups, files, provides and filelists just like the "install" command\&.
 .IP
 .IP "\fBdeplist\fP"
 Produces a list of all dependencies and what packages provide those
@@ -208,7 +221,8 @@ dependencies for the given packages.
 .IP
 .IP "\fBrepolist\fP"
 Produces a list of configured repositories. The default is to list all
-enabled repositories.
+enabled repositories. If you pass -v, for verbose mode, more information is
+listed.
 .IP
 .IP "\fBhelp\fP"
 Produces help, either for all commands or if given a command name then the help
@@ -280,7 +294,8 @@ Configuration Option: \fBexclude\fP
 .br
 .IP "\fB\-\-color=[always|auto|never]\fP"
 Display colorized output automatically, depending on the output terminal,
-always (using ANSI codes) or never.
+always (using ANSI codes) or never. Note that some commands (Eg. list and info)
+will do a little extra work when color is enabled.
 Configuration Option: \fBcolor\fP
 .br
 .IP "\fB\-\-disableexcludes=[all|main|repoid]\fP"

Based on:
commit 52d3779772df8ff8d09299890329499102a8c61e
Author: Seth Vidal <skvidal@fedoraproject.org>
Date:   Wed Apr 8 15:56:41 2009 -0400

    - fix to make local package from file:// urls work, at all. :(

diff --git a/yum/__init__.py b/yum/__init__.py
index 45378e1..7e5e600 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -1200,7 +1211,10 @@ class YumBase(depsolve.Depsolve):
 
         if type(fo) is types.InstanceType:
             fo = fo.filename
-            
+        
+        if fo != po.localPkg():
+            po.localpath = fo
+
         if not po.verifyLocalPkg():
             failed = True
         else:
commit 43f9c7a1febfd75c8cb68bdf34b3688edbc85a52
Author: Seth Vidal <skvidal@fedoraproject.org>
Date:   Mon Apr 13 12:27:21 2009 -0400

    add an exception catch for the traceback posted here:
    https://bugzilla.redhat.com/show_bug.cgi?id=494149
    
    It _shouldn't_ happen to begin with but since it CAN happen we might as well catch it
    and give off a real error

diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 1d3b25c..806fd25 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -408,13 +408,17 @@ class RPMTransaction:
         if h is not None:
             hdr, rpmloc = h[0], h[1]
             handle = self._makeHandle(hdr)
-            fd = os.open(rpmloc, os.O_RDONLY)
-            self.filehandles[handle]=fd
-            if self.trans_running:
-                self.total_installed += 1
-                self.complete_actions += 1
-                self.installed_pkg_names.append(hdr['name'])
-            return fd
+            try:
+                fd = os.open(rpmloc, os.O_RDONLY)
+            except OSError, e:
+                self.displaylog.errorlog("Error: Cannot open file %s: %s" % (rpmloc, e))
+            else:
+                self.filehandles[handle]=fd
+                if self.trans_running:
+                    self.total_installed += 1
+                    self.complete_actions += 1
+                    self.installed_pkg_names.append(hdr['name'])
+                return fd
         else:
             self.display.errorlog("Error: No Header to INST_OPEN_FILE")
             
commit aeb59bee6dfbd551bbd1fda4a0b35bcf1c441282
Author: James Antill <james@and.org>
Date:   Mon Apr 13 11:58:58 2009 -0400

    Fix cost sorting of repos.

diff --git a/yum/yumRepo.py b/yum/yumRepo.py
index 5204523..db3d44b 100644
--- a/yum/yumRepo.py
+++ b/yum/yumRepo.py
@@ -291,7 +291,7 @@ class YumRepository(Repository, config.RepoConf):
             ocost = 1000
         ret = cmp(self.cost, ocost)
         if ret:
-            return 1
+            return ret
         return cmp(self.id, other.id)
 
     def _getSack(self):
diff --git a/yum/packages.py b/yum/packages.py
index bc0f9cb..7ca88f9 100644
--- a/yum/packages.py
+++ b/yum/packages.py
@@ -163,8 +163,26 @@ class FakeSack:
             
 class FakeRepository:
     """Fake repository class for use in rpmsack package objects"""
+
+    def _set_cleanup_repoid(self, repoid):
+        """ Set the repoid, but because it can be random ... clean it up. """
+
+        #  We don't want repoids to contain random bytes that can be
+        # in the FS directories. It's also nice if they aren't "huge". So
+        # just chop to the rpm name.
+        repoid = os.path.basename(repoid)
+        if repoid.endswith(".rpm"):
+            repoid = repoid[:-4]
+
+        bytes = [] # Just in case someone uses mv to be evil:
+        for byte in repoid:
+            if ord(byte) >= 128:
+                byte = '?'
+            bytes.append(byte)
+        self.id = "/" + "".join(bytes)
+
     def __init__(self, repoid):
-        self.id = repoid
+        self._set_cleanup_repoid(repoid)
         self.sack = FakeSack()
 
     def __cmp__(self, other):
commit 0f752404bb13915cea646ea5db8a270bd58d6f47
Author: James Antill <james@and.org>
Date:   Mon Apr 13 12:29:10 2009 -0400

    Fix local repos. to not traceback UpdateMetadata

diff --git a/yum/update_md.py b/yum/update_md.py
index 9b1f07b..b297704 100644
--- a/yum/update_md.py
+++ b/yum/update_md.py
@@ -26,6 +26,7 @@ import gzip
 
 from yum.i18n import utf8_text_wrap, to_utf8
 from yum.yumRepo import YumRepository
+from yum.packages import FakeRepository
 from yum.misc import to_xml
 import Errors
 
@@ -367,6 +368,8 @@ class UpdateMetadata(object):
                 if not md:
                     raise UpdateNoticeException()
                 infile = gzip.open(md)
+        elif isinstance(obj, FakeRepository):
+            raise Errors.RepoMDError, "No updateinfo for local pkg"
         else:   # obj is a file object
             infile = obj
 
commit a46ef6078c843c88f6ecf90c3e1ebd0d8b6d2df4
Author: James Antill <james@and.org>
Date:   Tue Apr 14 02:36:06 2009 -0400

    Don't show duplicates in searchNames, when splitting the query

diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py
index 21c717f..0b194a1 100644
--- a/yum/sqlitesack.py
+++ b/yum/sqlitesack.py
@@ -895,9 +895,10 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack):
         returnList = []
         max_entries = constants.PATTERNS_INDEXED_MAX
         if len(names) > max_entries:
+            returnList = set() # Unique
             for names in seq_max_split(names, max_entries):
-                returnList.extend(self.searchNames(names))
-            return returnList
+                returnList.update(self.searchNames(names))
+            return list(returnList)
 
         pat_sqls = []
         qsql = """select pkgId,pkgKey,name,epoch,version,release,arch
commit ea4746b6ed6e233427850404edbad36f96bf9b71
Author: James Antill <james@and.org>
Date:   Tue Apr 14 02:36:55 2009 -0400

    Speed up searchNames() when we've loaded all the pkg objects

diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py
index 0b194a1..df24fe1 100644
--- a/yum/sqlitesack.py
+++ b/yum/sqlitesack.py
@@ -893,6 +893,16 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack):
             return []
         
         returnList = []
+        if hasattr(self, 'pkgobjlist'):
+            names = set(names)
+            for po in self.pkgobjlist:
+                if po.name not in names:
+                    continue
+                if self._pkgExcluded(po):
+                    continue
+                returnList.append(po)
+            return returnList
+
         max_entries = constants.PATTERNS_INDEXED_MAX
         if len(names) > max_entries:
             returnList = set() # Unique
commit 941b6528ffa974fad2942f37072e9f3cc7c6959b
Author: James Antill <james@and.org>
Date:   Tue Apr 14 03:11:03 2009 -0400

    Don't do stat() for local* if file doesn't end in .rpm. Allow localdowngrade

diff --git a/cli.py b/cli.py
index 9a78e9b..f6ba8d3 100644
--- a/cli.py
+++ b/cli.py
@@ -575,8 +575,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
         oldcount = len(self.tsInfo)
         
         for arg in userlist:
-            if os.path.exists(arg) and arg.endswith('.rpm'): # this is hurky, deal w/it
-                val, msglist = self.localInstall(filelist=[arg])
+            if arg.endswith('.rpm') and os.path.exists(arg): # this is hurky, deal w/it
+                self.localInstall(filelist=[arg])
                 continue # it was something on disk and it ended in rpm 
                          # no matter what we don't go looking at repos
             try:
@@ -608,11 +608,11 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
             # pass them off to localInstall() and then move on
             localupdates = []
             for item in userlist:
-                if os.path.exists(item) and item[-4:] == '.rpm': # this is hurky, deal w/it
+                if item.endswith('.rpm') and os.path.exists(item): # this is hurky, deal w/it
                     localupdates.append(item)
             
             if len(localupdates) > 0:
-                val, msglist = self.localInstall(filelist=localupdates, updateonly=1)
+                self.localInstall(filelist=localupdates, updateonly=1)
                 for item in localupdates:
                     userlist.remove(item)
                 
@@ -652,10 +652,8 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
         oldcount = len(self.tsInfo)
         
         for arg in userlist:
-            # FIXME: We should allow local file downgrades too
-            #        even more important for Fedora.
-            if False and os.path.exists(arg) and arg.endswith('.rpm'):
-                val, msglist = self.localDowngrade(filelist=[arg])
+            if arg.endswith('.rpm') and os.path.exists(arg):
+                self.downgradeLocal(arg)
                 continue # it was something on disk and it ended in rpm 
                          # no matter what we don't go looking at repos
 
@@ -797,7 +795,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
 
         pkgs = []
         for arg in args:
-            if os.path.exists(arg) and arg.endswith('.rpm'): # this is hurky, deal w/it
+            if arg.endswith('.rpm') and os.path.exists(arg): # this is hurky, deal w/it
                 thispkg = yum.packages.YumLocalPackage(self.ts, arg)
                 pkgs.append(thispkg)
             else:                
diff --git a/yum/__init__.py b/yum/__init__.py
index 7e5e600..90a9737 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -3147,6 +3147,44 @@ class YumBase(depsolve.Depsolve):
         tx_mbrs.extend(new_members)
         return tx_mbrs
         
+    def downgradeLocal(self, pkg, po=None):
+        """
+        handles downgrades of rpms provided on the filesystem in a
+        local dir (ie: not from a repo)
+
+        Return the added transaction members.
+
+        @param pkg: a path to an rpm file on disk.
+        @param po: A YumLocalPackage
+        """
+
+        if not po:
+            try:
+                po = YumLocalPackage(ts=self.rpmdb.readOnlyTS(), filename=pkg)
+            except Errors.MiscError:
+                self.logger.critical(_('Cannot open file: %s. Skipping.'), pkg)
+                return []
+            self.verbose_logger.log(logginglevels.INFO_2,
+                _('Examining %s: %s'), po.localpath, po)
+
+        if po.arch not in rpmUtils.arch.getArchList():
+            self.logger.critical(_('Cannot add package %s to transaction. Not a compatible architecture: %s'), pkg, po.arch)
+            return []
+
+        # handle excludes for a local downgrade
+        toexc = []
+        if len(self.conf.exclude) > 0:
+            exactmatch, matched, unmatched = \
+                   parsePackages(installpkgs + map(lambda x: x[0], updatepkgs),
+                                 self.conf.exclude, casematch=1)
+            toexc = exactmatch + matched
+
+        if po in toexc:
+            self.verbose_logger.debug(_('Excluding %s'), po)
+            return []
+
+        return self.downgrade(po=po)
+
     def downgrade(self, po=None, **kwargs):
         """ Try to downgrade a package. Works like:
             % yum shell <<EOL
commit cf5f4c2069be7991f48fdbd3dbfcc23f0b8b2d90
Author: James Antill <james@and.org>
Date:   Tue Apr 14 09:46:59 2009 -0400

    Only put / in front of "local" repoids

diff --git a/yum/packages.py b/yum/packages.py
index 7ca88f9..3dc7a15 100644
--- a/yum/packages.py
+++ b/yum/packages.py
@@ -170,16 +170,24 @@ class FakeRepository:
         #  We don't want repoids to contain random bytes that can be
         # in the FS directories. It's also nice if they aren't "huge". So
         # just chop to the rpm name.
-        repoid = os.path.basename(repoid)
+        pathbased = False
+        if '/' in repoid:
+            repoid = os.path.basename(repoid)
+            pathbased = True
+
         if repoid.endswith(".rpm"):
             repoid = repoid[:-4]
+            pathbased = True
 
         bytes = [] # Just in case someone uses mv to be evil:
+        if pathbased:
+            bytes.append('/')
+
         for byte in repoid:
             if ord(byte) >= 128:
                 byte = '?'
             bytes.append(byte)
-        self.id = "/" + "".join(bytes)
+        self.id = "".join(bytes)
 
     def __init__(self, repoid):
         self._set_cleanup_repoid(repoid)
commit 11dc235690a84aba4f1cf32d2d6846a6a3363297
Author: James Antill <james@and.org>
Date:   Wed Apr 15 16:16:08 2009 -0400

    Likely fix for only old packages providing stuff

diff --git a/yum/depsolve.py b/yum/depsolve.py
index 819adac..0c09a2c 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -1089,6 +1089,16 @@ class Depsolve(object):
             for nextpo in pkgs:
                 if po == nextpo:
                     continue
+
+                #  If this package isn't the latest version of said package,
+                # treat it like it's obsoleted. The problem here is X-1
+                # accidentally provides FOO, so you release X-2 without the
+                # provide, but X-1 is still picked over a real provider.
+                na = (po.name,po.arch)
+                lpos = self.pkgSack.returnNewestByNameArch(naTup=na)
+                if not lpos or po != sorted(lpos)[-1]:
+                    pkgresults[po] -= 1024
+
                 obsoleted = False
                 poprovtup = (po.name, 'EQ', (po.epoch, po.ver, po.release))
                 if nextpo.inPrcoRange('obsoletes', poprovtup):
commit 7dd2634529541c9f4a1b4fd71e9155d294a3ffa3
Author: James Antill <james@and.org>
Date:   Wed Apr 15 15:53:18 2009 -0400

    Magic i18n sprinkles to fix yum provides on pkgs with (R) in them

diff --git a/output.py b/output.py
index 16da351..099f8fc 100755
--- a/output.py
+++ b/output.py
@@ -833,18 +833,19 @@ class YumOutput:
         print _("Repo        : %s") % po.repoid
         print _('Matched from:')
         for item in yum.misc.unique(values):
-            if po.name == item or po.summary == item:
+            item = to_utf8(item)
+            if to_utf8(po.name) == item or to_utf8(po.summary) == item:
                 continue # Skip double name/summary printing
 
             can_overflow = True
             if False: pass
-            elif po.description == item:
+            elif to_utf8(po.description) == item:
                 key = _("Description : ")
                 item = self._enc(item)
-            elif po.url == item:
+            elif to_utf8(po.url) == item:
                 key = _("URL         : %s")
                 can_overflow = False
-            elif po.license == item:
+            elif to_utf8(po.license) == item:
                 key = _("License     : %s")
                 can_overflow = False
             elif item.startswith("/"):
commit 29b4babd76ee79002f37d87a4b4c2df88b78c5fb
Author: James Antill <james@and.org>
Date:   Thu Apr 16 16:30:31 2009 -0400

    Fix returnPackages() with a repoid, and pre-loaded data

diff --git a/yum/sqlitesack.py b/yum/sqlitesack.py
index df24fe1..7d87e0b 100644
--- a/yum/sqlitesack.py
+++ b/yum/sqlitesack.py
@@ -1215,6 +1215,8 @@ class YumSqlitePackageSack(yumRepo.YumPackageSack):
 
         returnList = []
         for po in pkgobjlist:
+            if repoid is not None and repoid != po.repoid:
+                continue
             if self._pkgExcluded(po):
                 continue
             returnList.append(po)
commit 9fbb21beef647848564f1801d07819cd7dc1ca5c
Author: James Antill <james@and.org>
Date:   Thu Apr 16 16:38:23 2009 -0400

    Fix downgrade to work on same arch. pkgs (still not as good as upgrade)

diff --git a/yum/__init__.py b/yum/__init__.py
index 90a9737..e33ab06 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -44,7 +44,7 @@ import Errors
 import rpmsack
 import rpmUtils.updates
 import rpmUtils.arch
-from rpmUtils.arch import getCanonArch, archDifference
+from rpmUtils.arch import getCanonArch, archDifference, canCoinstall
 import rpmUtils.transaction
 import comps
 import config
@@ -3235,15 +3235,15 @@ class YumBase(depsolve.Depsolve):
                 return []
             raise Errors.DowngradeError, _('No package(s) available to downgrade')
 
-        warned_names = set()
+        warned_nas = set()
         # Skip kernel etc.
         tapkgs = []
         for pkg in apkgs:
             if self.allowedMultipleInstalls(pkg):
-                if pkg.name not in warned_names:
+                if (pkg.name, pkg.arch) not in warned_nas:
                     msg = _("Package %s is allowed multiple installs, skipping") % pkg
                     self.verbose_logger.log(logginglevels.INFO_2, msg)
-                warned_names.add(pkg.name)
+                warned_nas.add((pkg.name, pkg.arch))
                 continue
             tapkgs.append(pkg)
         apkgs = tapkgs
@@ -3254,38 +3254,52 @@ class YumBase(depsolve.Depsolve):
             apkg_names.add(pkg.name)
         ipkgs = self.rpmdb.searchNames(list(apkg_names))
 
-        latest_installed = {}
+        latest_installed_na = {}
+        latest_installed_n  = {}
         for pkg in ipkgs:
-            latest_installed[pkg.name] = pkg
+            latest_installed_n[pkg.name] = pkg
+            latest_installed_na[(pkg.name, pkg.arch)] = pkg
 
         #  Find "latest downgrade", ie. latest available pkg before
         # installed version.
         downgrade_apkgs = {}
         for pkg in sorted(apkgs):
-            if pkg.name not in latest_installed:
-                if pkg.name not in warned_names and not doing_group_pkgs:
+            na  = (pkg.name, pkg.arch)
+
+            # Here we allow downgrades from .i386 => .noarch, or .i586 => .i386
+            # but not .i386 => .x86_64 (similar to update).
+            key = na
+            latest_installed = latest_installed_na
+            if pkg.name in latest_installed_n and na not in latest_installed_na:
+                if not canCoinstall(pkg.arch,latest_installed_n[pkg.name].arch):
+                    key = pkg.name
+                    latest_installed = latest_installed_n
+
+            if key not in latest_installed:
+                if na not in warned_nas and not doing_group_pkgs:
                     msg = _('No Match for available package: %s') % pkg
                     self.logger.critical(msg)
-                warned_names.add(pkg.name)
+                warned_nas.add(na)
                 continue
-            if pkg.verGE(latest_installed[pkg.name]):
-                if pkg.name not in warned_names:
+            if pkg.verGE(latest_installed[key]):
+                if na not in warned_nas:
                     msg = _('Only Upgrade available on package: %s') % pkg
                     self.logger.critical(msg)
-                warned_names.add(pkg.name)
+                warned_nas.add(na)
                 continue
-            warned_names.add(pkg.name)
-            if (pkg.name in downgrade_apkgs and
-                pkg.verLE(downgrade_apkgs[pkg.name])):
+            warned_nas.add(na)
+            if (na in downgrade_apkgs and
+                pkg.verLE(downgrade_apkgs[na])):
                 continue # Skip older than "latest downgrade"
-            downgrade_apkgs[pkg.name] = pkg
+            downgrade_apkgs[na] = pkg
 
         tx_return = []
         for po in ipkgs:
-            if po.name not in downgrade_apkgs:
+            na = (po.name, po.arch)
+            if na not in downgrade_apkgs:
                 continue
             itxmbr = self.tsInfo.addErase(po)
-            atxmbr = self.tsInfo.addInstall(downgrade_apkgs[po.name])
+            atxmbr = self.tsInfo.addInstall(downgrade_apkgs[na])
             if not atxmbr: # Fail?
                 self.tsInfo.remove(itxmbr.pkgtup)
                 continue
commit 5b0164cc3f337946568d0d1cc9f22640b95c3f9e
Author: James Antill <james@and.org>
Date:   Tue Apr 28 11:30:58 2009 -0400

    Don't show multiple obsoletes if multiple versions are available

diff --git a/yum/__init__.py b/yum/__init__.py
index ec4429e..fc7945a 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -2863,8 +2863,11 @@ class YumBase(depsolve.Depsolve):
         # check for obsoletes first
         if self.conf.obsoletes:
             for installed_pkg in instpkgs:
-                for obsoleting in self.up.obsoleted_dict.get(installed_pkg.pkgtup, []):
-                    obsoleting_pkg = self.getPackageObject(obsoleting)
+                obs_tups = self.up.obsoleted_dict.get(installed_pkg.pkgtup, [])
+                # This is done so we don't have to returnObsoletes(newest=True)
+                # It's a minor UI problem for RHEL, but might as well dtrt.
+                obs_pkgs = [self.getPackageObject(tup) for tup in obs_tups]
+                for obsoleting_pkg in packagesNewestByNameArch(obs_pkgs):
                     tx_return.extend(self.install(po=obsoleting_pkg))
             for available_pkg in availpkgs:
                 for obsoleted in self.up.obsoleting_dict.get(available_pkg.pkgtup, []):
commit feedba767289c932ba7d591df79b6ee0bd26db40
Author: James Antill <james@and.org>
Date:   Wed May 13 16:59:58 2009 -0400

    Fix downgrade local, when we have excludes

diff --git a/yum/__init__.py b/yum/__init__.py
index e988236..e72216c 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -3222,8 +3222,7 @@ class YumBase(depsolve.Depsolve):
         toexc = []
         if len(self.conf.exclude) > 0:
             exactmatch, matched, unmatched = \
-                   parsePackages(installpkgs + map(lambda x: x[0], updatepkgs),
-                                 self.conf.exclude, casematch=1)
+                   parsePackages([po], self.conf.exclude, casematch=1)
             toexc = exactmatch + matched
 
         if po in toexc:
commit d06e08d7b72ed4446e47ae454233b2e7aef8c6ea
Author: James Antill <james@and.org>
Date:   Wed May 13 17:07:05 2009 -0400

    Add reinstall of local rpms

diff --git a/cli.py b/cli.py
index 772fae5..7c4047a 100644
--- a/cli.py
+++ b/cli.py
@@ -673,6 +673,30 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
             return 2, [_('Package(s) to downgrade')]
         return 0, [_('Nothing to do')]
         
+    def reinstallPkgs(self, userlist):
+        """Attempts to take the user specified list of packages/wildcards
+           and reinstall them. """
+
+        oldcount = len(self.tsInfo)
+
+        for arg in userlist:
+            if arg.endswith('.rpm') and os.path.exists(arg):
+                self.reinstallLocal(arg)
+                continue # it was something on disk and it ended in rpm
+                         # no matter what we don't go looking at repos
+
+            try:
+                self.reinstall(pattern=arg)
+            except yum.Errors.ReinstallError:
+                self.verbose_logger.log(yum.logginglevels.INFO_2,
+                                        _('No package %s%s%s available.'),
+                                        self.term.MODE['bold'], arg,
+                                        self.term.MODE['normal'])
+                self._maybeYouMeant(arg)
+        if len(self.tsInfo) > oldcount:
+            return 2, [_('Package(s) to reinstall')]
+        return 0, [_('Nothing to do')]
+
     def localInstall(self, filelist, updateonly=0):
         """handles installs/updates of rpms provided on the filesystem in a 
            local dir (ie: not from a repo)"""
diff --git a/yum/__init__.py b/yum/__init__.py
index e72216c..b5515f2 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -3151,6 +3151,43 @@ class YumBase(depsolve.Depsolve):
 
         return tx_return
 
+    def reinstallLocal(self, pkg, po=None):
+        """
+        handles reinstall of rpms provided on the filesystem in a
+        local dir (ie: not from a repo)
+
+        Return the added transaction members.
+
+        @param pkg: a path to an rpm file on disk.
+        @param po: A YumLocalPackage
+        """
+
+        if not po:
+            try:
+                po = YumLocalPackage(ts=self.rpmdb.readOnlyTS(), filename=pkg)
+            except Errors.MiscError:
+                self.logger.critical(_('Cannot open file: %s. Skipping.'), pkg)
+                return []
+            self.verbose_logger.log(logginglevels.INFO_2,
+                _('Examining %s: %s'), po.localpath, po)
+
+        if po.arch not in rpmUtils.arch.getArchList():
+            self.logger.critical(_('Cannot add package %s to transaction. Not a compatible architecture: %s'), pkg, po.arch)
+            return []
+
+        # handle excludes for a local reinstall
+        toexc = []
+        if len(self.conf.exclude) > 0:
+            exactmatch, matched, unmatched = \
+                   parsePackages([po], self.conf.exclude, casematch=1)
+            toexc = exactmatch + matched
+
+        if po in toexc:
+            self.verbose_logger.debug(_('Excluding %s'), po)
+            return []
+
+        return self.reinstall(po=po)
+
     def reinstall(self, po=None, **kwargs):
         """Setup the problem filters to allow a reinstall to work, then
            pass everything off to install"""
@@ -3182,8 +3219,12 @@ class YumBase(depsolve.Depsolve):
             # pkgs that are obsolete.
             old_conf_obs = self.conf.obsoletes
             self.conf.obsoletes = False
-            members = self.install(name=item.name, arch=item.arch,
-                           ver=item.version, release=item.release, epoch=item.epoch)
+            if isinstance(po, YumLocalPackage):
+                members = self.install(po=po)
+            else:
+                members = self.install(name=item.name, arch=item.arch,
+                                       ver=item.version, release=item.release,
+                                       epoch=item.epoch)
             self.conf.obsoletes = old_conf_obs
             if len(members) == 0:
                 self.tsInfo.remove(item.pkgtup)
diff --git a/yumcommands.py b/yumcommands.py
index 9d34055..706d908 100644
--- a/yumcommands.py
+++ b/yumcommands.py
@@ -1006,16 +1006,8 @@ class ReInstallCommand(YumCommand):
 
     def doCommand(self, base, basecmd, extcmds):
         self.doneCommand(base, _("Setting up Reinstall Process"))
-        oldcount = len(base.tsInfo)
         try:
-            # FIXME: Due to not having reinstallPkgs() we don't get
-            #        localreinstall and maybe_you_meant features.
-            for item in extcmds:
-                base.reinstall(pattern=item)
-
-            if len(base.tsInfo) > oldcount:
-                return 2, [_('Package(s) to reinstall')]
-            return 0, [_('Nothing to do')]            
+            return base.reinstallPkgs(extcmds)
             
         except yum.Errors.YumBaseError, e:
             return 1, [to_unicode(e)]