Blob Blame History Raw
diff --git a/docs/yum.conf.5 b/docs/yum.conf.5
index 49d98c6..25b2c7d 100644
--- a/docs/yum.conf.5
+++ b/docs/yum.conf.5
@@ -134,9 +134,13 @@ an i686 package to update an i386 package. Default is `1'.
 
 .IP
 \fBinstallonlypkgs \fR
-List of packages that should only ever be installed, never updated. Kernels
-in particular fall into this category. Defaults to kernel, kernel-smp,
-kernel-bigmem, kernel-enterprise, kernel-debug, kernel-unsupported.
+List of package provides that should only ever be installed, never updated.
+Kernels in particular fall into this category. Defaults to kernel,
+kernel-bigmem, kernel-enterprise, kernel-smp, kernel-modules, kernel-debug, 
+kernel-unsupported, kernel-source, kernel-devel, kernel-PAE, kernel-PAE-debug.
+
+Note that because these are provides, and not just package names, kernel-devel
+will also apply to kernel-debug-devel, etc.
 
 .IP
 \fBinstallonly_limit \fR
diff --git a/output.py b/output.py
index 3a90995..10c7442 100755
--- a/output.py
+++ b/output.py
@@ -1882,10 +1882,12 @@ class DepSolveProgressCallBack:
                 msg += _('\n        Not found')
             return msg
 
-        ipkgs = set()
-        for pkg in sorted(yb.rpmdb.getProvides(needname)):
+        def _run_inst_pkg(pkg, msg):
             nevr = (pkg.name, pkg.epoch, pkg.version, pkg.release)
-            ipkgs.add(nevr)
+            if nevr in seen_pkgs or (pkg.verEQ(last) and pkg.arch == last.arch):
+                return msg
+
+            seen_pkgs.add(nevr)
             action = _('Installed')
             rmed = yb.tsInfo.getMembersWithState(pkg.pkgtup, TS_REMOVE_STATES)
             if rmed:
@@ -1901,21 +1903,40 @@ class DepSolveProgressCallBack:
                     if rtype not in relmap:
                         continue
                     nevr = (rpkg.name, rpkg.epoch, rpkg.version, rpkg.release)
-                    ipkgs.add(nevr)
+                    seen_pkgs.add(nevr)
                     msg += _msg_pkg(relmap[rtype], rpkg, needname)
+            return msg
 
-        last = None
-        for pkg in sorted(yb.pkgSack.getProvides(needname)):
+        def _run_avail_pkg(pkg, msg):
             #  We don't want to see installed packages, or N packages of the
             # same version, from different repos.
             nevr = (pkg.name, pkg.epoch, pkg.version, pkg.release)
-            if nevr in ipkgs or (pkg.verEQ(last) and pkg.arch == last.arch):
-                continue
-            last = pkg
+            if nevr in seen_pkgs or (pkg.verEQ(last) and pkg.arch == last.arch):
+                return False, last, msg
+            seen_pkgs.add(nevr)
             action = _('Available')
             if yb.tsInfo.getMembersWithState(pkg.pkgtup, TS_INSTALL_STATES):
                 action = _('Installing')
             msg += _msg_pkg(action, pkg, needname)
+            return True, pkg, msg
+
+        last = None
+        seen_pkgs = set()
+        for pkg in sorted(yb.rpmdb.getProvides(needname)):
+            msg = _run_inst_pkg(pkg, msg)
+
+        available_names = set()
+        for pkg in sorted(yb.pkgSack.getProvides(needname)):
+            tst, last, msg = _run_avail_pkg(pkg, msg)
+            if tst:
+                available_names.add(pkg.name)
+
+        last = None
+        for pkg in sorted(yb.rpmdb.searchNames(available_names)):
+            msg = _run_inst_pkg(pkg, msg)
+        last = None
+        for pkg in sorted(yb.pkgSack.searchNames(available_names)):
+            tst, last, msg = _run_avail_pkg(pkg, msg)
         return msg
     
     def procConflict(self, name, confname):
diff --git a/yum/__init__.py b/yum/__init__.py
index 2ea9f20..3a9ef88 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -294,6 +294,11 @@ class YumBase(depsolve.Depsolve):
             startupconf.syslog_facility = syslog_facility
         if syslog_device != None:
             startupconf.syslog_device = syslog_device
+        if releasever == '/':
+            if startupconf.installroot == '/':
+                releasever = None
+            else:
+                releasever = yum.config._getsysver("/",startupconf.distroverpkg)
         if releasever != None:
             startupconf.releasever = releasever
 
@@ -442,7 +447,11 @@ class YumBase(depsolve.Depsolve):
         @return: YumRepository instance.
         '''
         repo = yumRepo.YumRepository(section)
-        repo.populate(parser, section, self.conf)
+        try:
+            repo.populate(parser, section, self.conf)
+        except ValueError, e:
+            msg = _('Repository %r: Error parsing config: %s' % (section,e))
+            raise Errors.ConfigError, msg
 
         # Ensure that the repo name is set
         if not repo.name:
@@ -1403,7 +1412,8 @@ 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
-
+        
+        vt_st = time.time()
         self.rpmdb.dropCachedData()
         self.plugins.run('preverifytrans')
         for txmbr in self.tsInfo:
@@ -1489,6 +1499,7 @@ class YumBase(depsolve.Depsolve):
             self.plugins.run('historyend')
             self.history.end(self.rpmdb.simpleVersion(main_only=True)[0], ret)
         self.rpmdb.dropCachedData()
+        self.verbose_logger.debug('VerifyTransaction time: %0.3f' % (time.time() - vt_st))
 
     def costExcludePackages(self):
         """ Create an excluder for repos. with higher cost. Eg.
@@ -3669,6 +3680,7 @@ class YumBase(depsolve.Depsolve):
                         self.logger.critical(_('%s') % e)
                     
                     if not depmatches:
+                        arg = to_unicode(arg)
                         self.logger.critical(_('No Match for argument: %s') % arg)
                     else:
                         pkgs.extend(depmatches)
@@ -3690,6 +3702,14 @@ class YumBase(depsolve.Depsolve):
             if self.conf.protected_packages and po.pkgtup == kern_pkgtup:
                 self.logger.warning(_("Skipping the running kernel: %s") % po)
                 continue
+
+            if self.tsInfo.getMembers(po.pkgtup):
+                # This allows multiple reinstalls and update/downgrade "cancel"
+                for txmbr in self.tsInfo.matchNaevr(po.name):
+                    self.logger.warning(_("Removing %s from the transaction") %
+                                        txmbr)
+                    self.tsInfo.remove(txmbr.pkgtup)
+                # Now start the remove/reinstall
             txmbr = self.tsInfo.addErase(po)
             tx_return.append(txmbr)
         
diff --git a/yum/history.py b/yum/history.py
index 502b908..014bdab 100644
--- a/yum/history.py
+++ b/yum/history.py
@@ -27,7 +27,7 @@ import yum.misc as misc
 import yum.constants
 from yum.constants import *
 from yum.packages import YumInstalledPackage, YumAvailablePackage, PackageObject
-from yum.i18n import to_unicode
+from yum.i18n import to_unicode, to_utf8
 
 
 _history_dir = '/var/lib/yum/history'
@@ -425,12 +425,15 @@ class YumHistory:
         cur = self._get_cursor()
         if cur is None or not self._update_db_file_2():
             return None
+        # str(problem) doesn't work if problem contains unicode(),
+        # unicode(problem) doesn't work in python 2.4.x ... *sigh*.
+        uproblem = to_unicode(problem.__str__())
         res = executeSQL(cur,
                          """INSERT INTO trans_rpmdb_problems
                          (tid, problem, msg)
                          VALUES (?, ?, ?)""", (self._tid,
                                                problem.problem,
-                                               to_unicode(str(problem))))
+                                               uproblem))
         rpid = cur.lastrowid
 
         if not rpid:
@@ -467,7 +470,7 @@ class YumHistory:
         res = executeSQL(cur,
                          """INSERT INTO trans_cmdline
                          (tid, cmdline)
-                         VALUES (?, ?)""", (self._tid, cmdline))
+                         VALUES (?, ?)""", (self._tid, to_unicode(cmdline)))
         return cur.lastrowid
 
     def beg(self, rpmdb_version, using_pkgs, txmbrs, skip_packages=[],
@@ -610,7 +613,7 @@ class YumHistory:
             # open file in append
             fo = open(data_fn, 'w+')
             # write data
-            fo.write(data)
+            fo.write(to_utf8(data))
             # flush data
             fo.flush()
             fo.close()
@@ -914,17 +917,19 @@ class YumHistory:
             version || '-' || release || '.' || arch AS nevra
      FROM trans_skip_pkgs JOIN pkgtups USING(pkgtupid)
      ORDER BY name;
-''', # NOTE: Old versions of sqlite don't like this next view, they are only
-     #       there for debugging anyway ... but it's worth remembering.
+''', # NOTE: Old versions of sqlite don't like the normal way to do the next
+     #       view. So we do it with the select. It's for debugging only, so
+     #       no big deal.
 '''\
 \
- CREATE VIEW vtrans_prob_pkgs AS
+ CREATE VIEW vtrans_prob_pkgs2 AS
      SELECT tid,rpid,name,epoch,version,release,arch,pkgtups.pkgtupid,
-            main,
+            main,problem,msg,
             name || '-' || epoch || ':' ||
             version || '-' || release || '.' || arch AS nevra
-     FROM (trans_prob_pkgs JOIN trans_rpmdb_problems USING(rpid))
-                           JOIN pkgtups USING(pkgtupid)
+     FROM (SELECT * FROM trans_prob_pkgs,trans_rpmdb_problems WHERE
+           trans_prob_pkgs.rpid=trans_rpmdb_problems.rpid)
+           JOIN pkgtups USING(pkgtupid)
      ORDER BY name;
 ''']
 
diff --git a/yum/pgpmsg.py b/yum/pgpmsg.py
index 9cf8217..b23eabc 100644
--- a/yum/pgpmsg.py
+++ b/yum/pgpmsg.py
@@ -1186,7 +1186,7 @@ def decode(msg) :
         idx = idx + pkt_len
     return pkt_list
 
-def decode_msg(msg) :
+def decode_msg(msg, multi=False) :
     """decode_msg(msg) ==> list of OpenPGP "packet" objects
 Takes an ascii-armored PGP block and returns a list of objects each of which
 corresponds to a PGP "packets".
@@ -1242,11 +1242,17 @@ a PGP "certificate" includes a public key, user id(s), and signature.
                 pkt_idx = cert.load(pkt_list)
                 cert_list.append(cert)
                 pkt_list[0:pkt_idx] = []
+            if not multi:
+                if not cert_list:
+                    return None
+                return cert_list[0]
             return cert_list
         
         # add the data to our buffer then
         block_buf.write(l)
 
+    if not multi:
+        return None
     return []
 
 def decode_multiple_keys(msg):
@@ -1266,7 +1272,7 @@ def decode_multiple_keys(msg):
         block += '%s\n' % l
         if l == '-----END PGP PUBLIC KEY BLOCK-----':
             in_block = 0
-            thesecerts = decode_msg(block)
+            thesecerts = decode_msg(block, multi=True)
             if thesecerts:
                 certs.extend(thesecerts)
             block = ''
diff --git a/yumcommands.py b/yumcommands.py
index a7f5d9e..9c6fc75 100644
--- a/yumcommands.py
+++ b/yumcommands.py
@@ -122,6 +122,25 @@ def checkShellArg(base, basecmd, extcmds):
         base.usage()
         raise cli.CliError
 
+def checkEnabledRepo(base, possible_local_files=[]):
+    """
+    Verify that there is at least one enabled repo.
+
+    @param base: a YumBase object.
+    """
+    if base.repos.listEnabled():
+        return
+
+    for lfile in possible_local_files:
+        if lfile.endswith(".rpm") and os.path.exists(lfile):
+            return
+
+    msg = _('There are no enabled repos.\n'
+            ' Run "yum repolist all" to see the repos you have.\n'
+            ' You can enable repos with yum-config-manager --enable <repo>')
+    base.logger.critical(msg)
+    raise cli.CliError
+
 class YumCommand:
         
     def __init__(self):
@@ -176,6 +195,7 @@ class InstallCommand(YumCommand):
         checkRootUID(base)
         checkGPGKey(base)
         checkPackageArg(base, basecmd, extcmds)
+        checkEnabledRepo(base, extcmds)
 
     def doCommand(self, base, basecmd, extcmds):
         self.doneCommand(base, _("Setting up Install Process"))
@@ -197,6 +217,7 @@ class UpdateCommand(YumCommand):
     def doCheck(self, base, basecmd, extcmds):
         checkRootUID(base)
         checkGPGKey(base)
+        checkEnabledRepo(base, extcmds)
 
     def doCommand(self, base, basecmd, extcmds):
         self.doneCommand(base, _("Setting up Update Process"))
@@ -218,6 +239,7 @@ class DistroSyncCommand(YumCommand):
     def doCheck(self, base, basecmd, extcmds):
         checkRootUID(base)
         checkGPGKey(base)
+        checkEnabledRepo(base, extcmds)
 
     def doCommand(self, base, basecmd, extcmds):
         self.doneCommand(base, _("Setting up Distribution Synchronization Process"))
@@ -420,6 +442,9 @@ class GroupListCommand(GroupCommand):
     def getSummary(self):
         return _("List available package groups")
     
+    def doCheck(self, base, basecmd, extcmds):
+        checkEnabledRepo(base)
+
     def doCommand(self, base, basecmd, extcmds):
         GroupCommand.doCommand(self, base, basecmd, extcmds)
         return base.returnGroupLists(extcmds)
@@ -441,6 +466,7 @@ class GroupInstallCommand(GroupCommand):
         checkRootUID(base)
         checkGPGKey(base)
         checkGroupArg(base, basecmd, extcmds)
+        checkEnabledRepo(base)
 
     def doCommand(self, base, basecmd, extcmds):
         GroupCommand.doCommand(self, base, basecmd, extcmds)
@@ -462,6 +488,7 @@ class GroupRemoveCommand(GroupCommand):
     def doCheck(self, base, basecmd, extcmds):
         checkRootUID(base)
         checkGroupArg(base, basecmd, extcmds)
+        checkEnabledRepo(base)
 
     def doCommand(self, base, basecmd, extcmds):
         GroupCommand.doCommand(self, base, basecmd, extcmds)
@@ -488,6 +515,7 @@ class GroupInfoCommand(GroupCommand):
 
     def doCheck(self, base, basecmd, extcmds):
         checkGroupArg(base, basecmd, extcmds)
+        checkEnabledRepo(base)
 
     def doCommand(self, base, basecmd, extcmds):
         GroupCommand.doCommand(self, base, basecmd, extcmds)
@@ -511,7 +539,7 @@ class MakeCacheCommand(YumCommand):
         return _("Generate the metadata cache")
 
     def doCheck(self, base, basecmd, extcmds):
-        pass
+        checkEnabledRepo(base)
 
     def doCommand(self, base, basecmd, extcmds):
         base.logger.debug(_("Making cache files for all metadata files."))
@@ -554,6 +582,7 @@ class CleanCommand(YumCommand):
 
     def doCheck(self, base, basecmd, extcmds):
         checkCleanArg(base, basecmd, extcmds)
+        checkEnabledRepo(base)
         
     def doCommand(self, base, basecmd, extcmds):
         base.conf.cache = 1
@@ -592,6 +621,9 @@ class CheckUpdateCommand(YumCommand):
     def getSummary(self):
         return _("Check for available package updates")
 
+    def doCheck(self, base, basecmd, extcmds):
+        checkEnabledRepo(base)
+
     def doCommand(self, base, basecmd, extcmds):
         base.extcmds.insert(0, 'updates')
         result = 0
@@ -668,6 +700,7 @@ class UpgradeCommand(YumCommand):
     def doCheck(self, base, basecmd, extcmds):
         checkRootUID(base)
         checkGPGKey(base)
+        checkEnabledRepo(base, extcmds)
 
     def doCommand(self, base, basecmd, extcmds):
         base.conf.obsoletes = 1
@@ -1104,6 +1137,7 @@ class ReInstallCommand(YumCommand):
         checkRootUID(base)
         checkGPGKey(base)
         checkPackageArg(base, basecmd, extcmds)
+        checkEnabledRepo(base, extcmds)
 
     def doCommand(self, base, basecmd, extcmds):
         self.doneCommand(base, _("Setting up Reinstall Process"))
@@ -1130,6 +1164,7 @@ class DowngradeCommand(YumCommand):
         checkRootUID(base)
         checkGPGKey(base)
         checkPackageArg(base, basecmd, extcmds)
+        checkEnabledRepo(base, extcmds)
 
     def doCommand(self, base, basecmd, extcmds):
         self.doneCommand(base, _("Setting up Downgrade Process"))