| 1 | #!/usr/bin/python -t
|
|---|
| 2 | # This program is free software; you can redistribute it and/or modify
|
|---|
| 3 | # it under the terms of the GNU General Public License as published by
|
|---|
| 4 | # the Free Software Foundation; either version 2 of the License, or
|
|---|
| 5 | # (at your option) any later version.
|
|---|
| 6 | #
|
|---|
| 7 | # This program is distributed in the hope that it will be useful,
|
|---|
| 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 10 | # GNU Library General Public License for more details.
|
|---|
| 11 | #
|
|---|
| 12 | # You should have received a copy of the GNU General Public License
|
|---|
| 13 | # along with this program; if not, write to the Free Software
|
|---|
| 14 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|---|
| 15 | # Copyright 2005 Duke University
|
|---|
| 16 | # Written by Seth Vidal
|
|---|
| 17 |
|
|---|
| 18 | """
|
|---|
| 19 | Command line interface yum class and related.
|
|---|
| 20 | """
|
|---|
| 21 |
|
|---|
| 22 | import os
|
|---|
| 23 | import re
|
|---|
| 24 | import sys
|
|---|
| 25 | import time
|
|---|
| 26 | import random
|
|---|
| 27 | import logging
|
|---|
| 28 | from optparse import OptionParser,OptionGroup
|
|---|
| 29 | import rpm
|
|---|
| 30 |
|
|---|
| 31 | from weakref import proxy as weakref
|
|---|
| 32 |
|
|---|
| 33 | import output
|
|---|
| 34 | import shell
|
|---|
| 35 | import yum
|
|---|
| 36 | import yum.Errors
|
|---|
| 37 | import yum.logginglevels
|
|---|
| 38 | import yum.misc
|
|---|
| 39 | import yum.plugins
|
|---|
| 40 | from rpmUtils.arch import isMultiLibArch
|
|---|
| 41 | from yum import _
|
|---|
| 42 | from yum.rpmtrans import RPMTransaction
|
|---|
| 43 | import signal
|
|---|
| 44 | import yumcommands
|
|---|
| 45 |
|
|---|
| 46 | from yum.i18n import to_unicode, to_utf8
|
|---|
| 47 |
|
|---|
| 48 | def sigquit(signum, frame):
|
|---|
| 49 | """ SIGQUIT handler for the yum cli. """
|
|---|
| 50 | print >> sys.stderr, "Quit signal sent - exiting immediately"
|
|---|
| 51 | sys.exit(1)
|
|---|
| 52 |
|
|---|
| 53 | class CliError(yum.Errors.YumBaseError):
|
|---|
| 54 |
|
|---|
| 55 | """
|
|---|
| 56 | Command line interface related Exception.
|
|---|
| 57 | """
|
|---|
| 58 |
|
|---|
| 59 | def __init__(self, args=''):
|
|---|
| 60 | yum.Errors.YumBaseError.__init__(self)
|
|---|
| 61 | self.args = args
|
|---|
| 62 |
|
|---|
| 63 | class YumBaseCli(yum.YumBase, output.YumOutput):
|
|---|
| 64 | """This is the base class for yum cli.
|
|---|
| 65 | Inherits from yum.YumBase and output.YumOutput """
|
|---|
| 66 |
|
|---|
| 67 | def __init__(self):
|
|---|
| 68 | # handle sigquit early on
|
|---|
| 69 | signal.signal(signal.SIGQUIT, sigquit)
|
|---|
| 70 | yum.YumBase.__init__(self)
|
|---|
| 71 | output.YumOutput.__init__(self)
|
|---|
| 72 | logging.basicConfig()
|
|---|
| 73 | self.logger = logging.getLogger("yum.cli")
|
|---|
| 74 | self.verbose_logger = logging.getLogger("yum.verbose.cli")
|
|---|
| 75 | self.yum_cli_commands = {}
|
|---|
| 76 | self.registerCommand(yumcommands.InstallCommand())
|
|---|
| 77 | self.registerCommand(yumcommands.UpdateCommand())
|
|---|
| 78 | self.registerCommand(yumcommands.InfoCommand())
|
|---|
| 79 | self.registerCommand(yumcommands.ListCommand())
|
|---|
| 80 | self.registerCommand(yumcommands.EraseCommand())
|
|---|
| 81 | self.registerCommand(yumcommands.GroupCommand())
|
|---|
| 82 | self.registerCommand(yumcommands.GroupListCommand())
|
|---|
| 83 | self.registerCommand(yumcommands.GroupInstallCommand())
|
|---|
| 84 | self.registerCommand(yumcommands.GroupRemoveCommand())
|
|---|
| 85 | self.registerCommand(yumcommands.GroupInfoCommand())
|
|---|
| 86 | self.registerCommand(yumcommands.MakeCacheCommand())
|
|---|
| 87 | self.registerCommand(yumcommands.CleanCommand())
|
|---|
| 88 | self.registerCommand(yumcommands.ProvidesCommand())
|
|---|
| 89 | self.registerCommand(yumcommands.CheckUpdateCommand())
|
|---|
| 90 | self.registerCommand(yumcommands.SearchCommand())
|
|---|
| 91 | self.registerCommand(yumcommands.UpgradeCommand())
|
|---|
| 92 | self.registerCommand(yumcommands.LocalInstallCommand())
|
|---|
| 93 | self.registerCommand(yumcommands.ResolveDepCommand())
|
|---|
| 94 | self.registerCommand(yumcommands.ShellCommand())
|
|---|
| 95 | self.registerCommand(yumcommands.DepListCommand())
|
|---|
| 96 | self.registerCommand(yumcommands.RepoListCommand())
|
|---|
| 97 | self.registerCommand(yumcommands.HelpCommand())
|
|---|
| 98 | self.registerCommand(yumcommands.ReInstallCommand())
|
|---|
| 99 | self.registerCommand(yumcommands.DowngradeCommand())
|
|---|
| 100 | self.registerCommand(yumcommands.VersionCommand())
|
|---|
| 101 | self.registerCommand(yumcommands.HistoryCommand())
|
|---|
| 102 | self.registerCommand(yumcommands.CheckRpmdbCommand())
|
|---|
| 103 |
|
|---|
| 104 | def registerCommand(self, command):
|
|---|
| 105 | for name in command.getNames():
|
|---|
| 106 | if name in self.yum_cli_commands:
|
|---|
| 107 | raise yum.Errors.ConfigError(_('Command "%s" already defined') % name)
|
|---|
| 108 | self.yum_cli_commands[name] = command
|
|---|
| 109 |
|
|---|
| 110 | def doRepoSetup(self, thisrepo=None, dosack=1):
|
|---|
| 111 | """grabs the repomd.xml for each enabled repository
|
|---|
| 112 | and sets up the basics of the repository"""
|
|---|
| 113 |
|
|---|
| 114 | if self._repos and thisrepo is None:
|
|---|
| 115 | return self._repos
|
|---|
| 116 |
|
|---|
| 117 | if not thisrepo:
|
|---|
| 118 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 119 | _('Setting up repositories'))
|
|---|
| 120 |
|
|---|
| 121 | # Call parent class to do the bulk of work
|
|---|
| 122 | # (this also ensures that reposetup plugin hook is called)
|
|---|
| 123 | if thisrepo:
|
|---|
| 124 | yum.YumBase._getRepos(self, thisrepo=thisrepo, doSetup=True)
|
|---|
| 125 | else:
|
|---|
| 126 | yum.YumBase._getRepos(self, thisrepo=thisrepo)
|
|---|
| 127 |
|
|---|
| 128 | if dosack: # so we can make the dirs and grab the repomd.xml but not import the md
|
|---|
| 129 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 130 | _('Reading repository metadata in from local files'))
|
|---|
| 131 | self._getSacks(thisrepo=thisrepo)
|
|---|
| 132 |
|
|---|
| 133 | return self._repos
|
|---|
| 134 |
|
|---|
| 135 | def _makeUsage(self):
|
|---|
| 136 | """
|
|---|
| 137 | Format an attractive usage string for yum, listing subcommand
|
|---|
| 138 | names and summary usages.
|
|---|
| 139 | """
|
|---|
| 140 | usage = 'yum [options] COMMAND\n\nList of Commands:\n\n'
|
|---|
| 141 | commands = yum.misc.unique(self.yum_cli_commands.values())
|
|---|
| 142 | commands.sort(key=lambda x: x.getNames()[0])
|
|---|
| 143 | for command in commands:
|
|---|
| 144 | # XXX Remove this when getSummary is common in plugins
|
|---|
| 145 | try:
|
|---|
| 146 | summary = command.getSummary()
|
|---|
| 147 | usage += "%-14s %s\n" % (command.getNames()[0], summary)
|
|---|
| 148 | except (AttributeError, NotImplementedError):
|
|---|
| 149 | usage += "%s\n" % command.getNames()[0]
|
|---|
| 150 |
|
|---|
| 151 | return usage
|
|---|
| 152 |
|
|---|
| 153 | def getOptionsConfig(self, args):
|
|---|
| 154 | """parses command line arguments, takes cli args:
|
|---|
| 155 | sets up self.conf and self.cmds as well as logger objects
|
|---|
| 156 | in base instance"""
|
|---|
| 157 |
|
|---|
| 158 | self.optparser = YumOptionParser(base=self, usage=self._makeUsage())
|
|---|
| 159 |
|
|---|
| 160 | # Parse only command line options that affect basic yum setup
|
|---|
| 161 | opts = self.optparser.firstParse(args)
|
|---|
| 162 |
|
|---|
| 163 | # Just print out the version if that's what the user wanted
|
|---|
| 164 | if opts.version:
|
|---|
| 165 | print yum.__version__
|
|---|
| 166 | opts.quiet = True
|
|---|
| 167 | opts.verbose = False
|
|---|
| 168 |
|
|---|
| 169 | # get the install root to use
|
|---|
| 170 | root = self.optparser.getRoot(opts)
|
|---|
| 171 |
|
|---|
| 172 | if opts.quiet:
|
|---|
| 173 | opts.debuglevel = 0
|
|---|
| 174 | if opts.verbose:
|
|---|
| 175 | opts.debuglevel = opts.errorlevel = 6
|
|---|
| 176 |
|
|---|
| 177 | # Read up configuration options and initialise plugins
|
|---|
| 178 | try:
|
|---|
| 179 | pc = self.preconf
|
|---|
| 180 | pc.fn = opts.conffile
|
|---|
| 181 | pc.root = root
|
|---|
| 182 | pc.init_plugins = not opts.noplugins
|
|---|
| 183 | pc.plugin_types = (yum.plugins.TYPE_CORE,
|
|---|
| 184 | yum.plugins.TYPE_INTERACTIVE)
|
|---|
| 185 | pc.optparser = self.optparser
|
|---|
| 186 | pc.debuglevel = opts.debuglevel
|
|---|
| 187 | pc.errorlevel = opts.errorlevel
|
|---|
| 188 | pc.disabled_plugins = self.optparser._splitArg(opts.disableplugins)
|
|---|
| 189 | pc.enabled_plugins = self.optparser._splitArg(opts.enableplugins)
|
|---|
| 190 | pc.releasever = opts.releasever
|
|---|
| 191 | self.conf
|
|---|
| 192 |
|
|---|
| 193 | except yum.Errors.ConfigError, e:
|
|---|
| 194 | self.logger.critical(_('Config Error: %s'), e)
|
|---|
| 195 | sys.exit(1)
|
|---|
| 196 | except ValueError, e:
|
|---|
| 197 | self.logger.critical(_('Options Error: %s'), e)
|
|---|
| 198 | sys.exit(1)
|
|---|
| 199 |
|
|---|
| 200 | # update usage in case plugins have added commands
|
|---|
| 201 | self.optparser.set_usage(self._makeUsage())
|
|---|
| 202 |
|
|---|
| 203 | self.plugins.run('args', args=args)
|
|---|
| 204 | # Now parse the command line for real and
|
|---|
| 205 | # apply some of the options to self.conf
|
|---|
| 206 | (opts, self.cmds) = self.optparser.setupYumConfig(args=args)
|
|---|
| 207 |
|
|---|
| 208 | if opts.version:
|
|---|
| 209 | self.conf.cache = 1
|
|---|
| 210 | yum_progs = self.run_with_package_names
|
|---|
| 211 | done = False
|
|---|
| 212 | def sm_ui_time(x):
|
|---|
| 213 | return time.strftime("%Y-%m-%d %H:%M", time.gmtime(x))
|
|---|
| 214 | def sm_ui_date(x): # For changelogs, there is no time
|
|---|
| 215 | return time.strftime("%Y-%m-%d", time.gmtime(x))
|
|---|
| 216 | for pkg in sorted(self.rpmdb.returnPackages(patterns=yum_progs)):
|
|---|
| 217 | # We should only have 1 version of each...
|
|---|
| 218 | if done: print ""
|
|---|
| 219 | done = True
|
|---|
| 220 | if pkg.epoch == '0':
|
|---|
| 221 | ver = '%s-%s.%s' % (pkg.version, pkg.release, pkg.arch)
|
|---|
| 222 | else:
|
|---|
| 223 | ver = '%s:%s-%s.%s' % (pkg.epoch,
|
|---|
| 224 | pkg.version, pkg.release, pkg.arch)
|
|---|
| 225 | name = "%s%s%s" % (self.term.MODE['bold'], pkg.name,
|
|---|
| 226 | self.term.MODE['normal'])
|
|---|
| 227 | print _(" Installed: %s-%s at %s") %(name, ver,
|
|---|
| 228 | sm_ui_time(pkg.installtime))
|
|---|
| 229 | print _(" Built : %s at %s") % (pkg.packager,
|
|---|
| 230 | sm_ui_time(pkg.buildtime))
|
|---|
| 231 | print _(" Committed: %s at %s") % (pkg.committer,
|
|---|
| 232 | sm_ui_date(pkg.committime))
|
|---|
| 233 | sys.exit(0)
|
|---|
| 234 |
|
|---|
| 235 | if opts.sleeptime is not None:
|
|---|
| 236 | sleeptime = random.randrange(opts.sleeptime*60)
|
|---|
| 237 | else:
|
|---|
| 238 | sleeptime = 0
|
|---|
| 239 |
|
|---|
| 240 | # save our original args out
|
|---|
| 241 | self.args = args
|
|---|
| 242 | # save out as a nice command string
|
|---|
| 243 | self.cmdstring = 'yum '
|
|---|
| 244 | for arg in self.args:
|
|---|
| 245 | self.cmdstring += '%s ' % arg
|
|---|
| 246 |
|
|---|
| 247 | try:
|
|---|
| 248 | self.parseCommands() # before we return check over the base command + args
|
|---|
| 249 | # make sure they match/make sense
|
|---|
| 250 | except CliError:
|
|---|
| 251 | sys.exit(1)
|
|---|
| 252 |
|
|---|
| 253 | # run the sleep - if it's unchanged then it won't matter
|
|---|
| 254 | time.sleep(sleeptime)
|
|---|
| 255 |
|
|---|
| 256 | def parseCommands(self):
|
|---|
| 257 | """reads self.cmds and parses them out to make sure that the requested
|
|---|
| 258 | base command + argument makes any sense at all"""
|
|---|
| 259 |
|
|---|
| 260 | self.verbose_logger.debug('Yum Version: %s', yum.__version__)
|
|---|
| 261 | self.verbose_logger.log(yum.logginglevels.DEBUG_4,
|
|---|
| 262 | 'COMMAND: %s', self.cmdstring)
|
|---|
| 263 | self.verbose_logger.log(yum.logginglevels.DEBUG_4,
|
|---|
| 264 | 'Installroot: %s', self.conf.installroot)
|
|---|
| 265 | if len(self.conf.commands) == 0 and len(self.cmds) < 1:
|
|---|
| 266 | self.cmds = self.conf.commands
|
|---|
| 267 | else:
|
|---|
| 268 | self.conf.commands = self.cmds
|
|---|
| 269 | if len(self.cmds) < 1:
|
|---|
| 270 | self.logger.critical(_('You need to give some command'))
|
|---|
| 271 | self.usage()
|
|---|
| 272 | raise CliError
|
|---|
| 273 |
|
|---|
| 274 | self.basecmd = self.cmds[0] # our base command
|
|---|
| 275 | self.extcmds = self.cmds[1:] # out extended arguments/commands
|
|---|
| 276 |
|
|---|
| 277 | if len(self.extcmds) > 0:
|
|---|
| 278 | self.verbose_logger.log(yum.logginglevels.DEBUG_4,
|
|---|
| 279 | 'Ext Commands:\n')
|
|---|
| 280 | for arg in self.extcmds:
|
|---|
| 281 | self.verbose_logger.log(yum.logginglevels.DEBUG_4, ' %s', arg)
|
|---|
| 282 |
|
|---|
| 283 | if self.basecmd not in self.yum_cli_commands:
|
|---|
| 284 | self.logger.critical(_('No such command: %s. Please use %s --help'),
|
|---|
| 285 | self.basecmd, sys.argv[0])
|
|---|
| 286 | raise CliError
|
|---|
| 287 |
|
|---|
| 288 | self.yum_cli_commands[self.basecmd].doCheck(self, self.basecmd, self.extcmds)
|
|---|
| 289 |
|
|---|
| 290 | def doShell(self):
|
|---|
| 291 | """do a shell-like interface for yum commands"""
|
|---|
| 292 |
|
|---|
| 293 | yumshell = shell.YumShell(base=self)
|
|---|
| 294 | if len(self.extcmds) == 0:
|
|---|
| 295 | yumshell.cmdloop()
|
|---|
| 296 | else:
|
|---|
| 297 | yumshell.script()
|
|---|
| 298 | return yumshell.result, yumshell.resultmsgs
|
|---|
| 299 |
|
|---|
| 300 | def errorSummary(self, errstring):
|
|---|
| 301 | """ parse the error string for 'interesting' errors which can
|
|---|
| 302 | be grouped, such as disk space issues """
|
|---|
| 303 | summary = ''
|
|---|
| 304 | # do disk space report first
|
|---|
| 305 | p = re.compile('needs (\d+)MB on the (\S+) filesystem')
|
|---|
| 306 | disk = {}
|
|---|
| 307 | for m in p.finditer(errstring):
|
|---|
| 308 | if not disk.has_key(m.group(2)):
|
|---|
| 309 | disk[m.group(2)] = int(m.group(1))
|
|---|
| 310 | if disk[m.group(2)] < int(m.group(1)):
|
|---|
| 311 | disk[m.group(2)] = int(m.group(1))
|
|---|
| 312 |
|
|---|
| 313 | if disk:
|
|---|
| 314 | summary += _('Disk Requirements:\n')
|
|---|
| 315 | for k in disk:
|
|---|
| 316 | summary += _(' At least %dMB more space needed on the %s filesystem.\n') % (disk[k], k)
|
|---|
| 317 |
|
|---|
| 318 | # TODO: simplify the dependency errors?
|
|---|
| 319 |
|
|---|
| 320 | # Fixup the summary
|
|---|
| 321 | summary = _('Error Summary\n-------------\n') + summary
|
|---|
| 322 |
|
|---|
| 323 | return summary
|
|---|
| 324 |
|
|---|
| 325 |
|
|---|
| 326 | def doCommands(self):
|
|---|
| 327 | """
|
|---|
| 328 | Calls the base command passes the extended commands/args out to be
|
|---|
| 329 | parsed (most notably package globs).
|
|---|
| 330 |
|
|---|
| 331 | Returns a numeric result code and an optional string
|
|---|
| 332 | - 0 = we're done, exit
|
|---|
| 333 | - 1 = we've errored, exit with error string
|
|---|
| 334 | - 2 = we've got work yet to do, onto the next stage
|
|---|
| 335 | """
|
|---|
| 336 |
|
|---|
| 337 | # at this point we know the args are valid - we don't know their meaning
|
|---|
| 338 | # but we know we're not being sent garbage
|
|---|
| 339 |
|
|---|
| 340 | # setup our transaction set if the command we're using needs it
|
|---|
| 341 | # compat with odd modules not subclassing YumCommand
|
|---|
| 342 | needTs = True
|
|---|
| 343 | needTsRemove = False
|
|---|
| 344 | cmd = self.yum_cli_commands[self.basecmd]
|
|---|
| 345 | if hasattr(cmd, 'needTs'):
|
|---|
| 346 | needTs = cmd.needTs(self, self.basecmd, self.extcmds)
|
|---|
| 347 | if not needTs and hasattr(cmd, 'needTsRemove'):
|
|---|
| 348 | needTsRemove = cmd.needTsRemove(self, self.basecmd, self.extcmds)
|
|---|
| 349 |
|
|---|
| 350 | if needTs or needTsRemove:
|
|---|
| 351 | try:
|
|---|
| 352 | self._getTs(needTsRemove)
|
|---|
| 353 | except yum.Errors.YumBaseError, e:
|
|---|
| 354 | return 1, [str(e)]
|
|---|
| 355 |
|
|---|
| 356 | return self.yum_cli_commands[self.basecmd].doCommand(self, self.basecmd, self.extcmds)
|
|---|
| 357 |
|
|---|
| 358 | def doTransaction(self):
|
|---|
| 359 | """takes care of package downloading, checking, user confirmation and actually
|
|---|
| 360 | RUNNING the transaction"""
|
|---|
| 361 |
|
|---|
| 362 | # just make sure there's not, well, nothing to do
|
|---|
| 363 | if len(self.tsInfo) == 0:
|
|---|
| 364 | self.verbose_logger.info(_('Trying to run the transaction but nothing to do. Exiting.'))
|
|---|
| 365 | return 1
|
|---|
| 366 |
|
|---|
| 367 | # NOTE: In theory we can skip this in -q -y mode, for a slight perf.
|
|---|
| 368 | # gain. But it's probably doom to have a different code path.
|
|---|
| 369 | lsts = self.listTransaction()
|
|---|
| 370 | if self.verbose_logger.isEnabledFor(yum.logginglevels.INFO_1):
|
|---|
| 371 | self.verbose_logger.log(yum.logginglevels.INFO_1, lsts)
|
|---|
| 372 | elif not self.conf.assumeyes:
|
|---|
| 373 | # If we are in quiet, and assumeyes isn't on we want to output
|
|---|
| 374 | # at least the transaction list anyway.
|
|---|
| 375 | self.logger.warn(lsts)
|
|---|
| 376 |
|
|---|
| 377 | # Check which packages have to be downloaded
|
|---|
| 378 | downloadpkgs = []
|
|---|
| 379 | stuff_to_download = False
|
|---|
| 380 | install_only = True
|
|---|
| 381 | for txmbr in self.tsInfo.getMembers():
|
|---|
| 382 | if txmbr.ts_state not in ('i', 'u'):
|
|---|
| 383 | install_only = False
|
|---|
| 384 | else:
|
|---|
| 385 | stuff_to_download = True
|
|---|
| 386 | po = txmbr.po
|
|---|
| 387 | if po:
|
|---|
| 388 | downloadpkgs.append(po)
|
|---|
| 389 |
|
|---|
| 390 | # Close the connection to the rpmdb so that rpm doesn't hold the SIGINT
|
|---|
| 391 | # handler during the downloads. self.ts is reinitialised later in this
|
|---|
| 392 | # function anyway (initActionTs).
|
|---|
| 393 | self.ts.close()
|
|---|
| 394 |
|
|---|
| 395 | # Report the total download size to the user, so he/she can base
|
|---|
| 396 | # the answer on this info
|
|---|
| 397 | if stuff_to_download:
|
|---|
| 398 | self.reportDownloadSize(downloadpkgs, install_only)
|
|---|
| 399 |
|
|---|
| 400 | # confirm with user
|
|---|
| 401 | if self._promptWanted():
|
|---|
| 402 | if not self.userconfirm():
|
|---|
| 403 | self.verbose_logger.info(_('Exiting on user Command'))
|
|---|
| 404 | return 1
|
|---|
| 405 |
|
|---|
| 406 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 407 | _('Downloading Packages:'))
|
|---|
| 408 | problems = self.downloadPkgs(downloadpkgs, callback_total=self.download_callback_total_cb)
|
|---|
| 409 |
|
|---|
| 410 | if len(problems) > 0:
|
|---|
| 411 | errstring = ''
|
|---|
| 412 | errstring += _('Error Downloading Packages:\n')
|
|---|
| 413 | for key in problems:
|
|---|
| 414 | errors = yum.misc.unique(problems[key])
|
|---|
| 415 | for error in errors:
|
|---|
| 416 | errstring += ' %s: %s\n' % (key, error)
|
|---|
| 417 | raise yum.Errors.YumBaseError, errstring
|
|---|
| 418 |
|
|---|
| 419 | # Check GPG signatures
|
|---|
| 420 | if self.gpgsigcheck(downloadpkgs) != 0:
|
|---|
| 421 | return 1
|
|---|
| 422 |
|
|---|
| 423 | if self.conf.rpm_check_debug:
|
|---|
| 424 | rcd_st = time.time()
|
|---|
| 425 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 426 | _('Running rpm_check_debug'))
|
|---|
| 427 | msgs = self._run_rpm_check_debug()
|
|---|
| 428 | if msgs:
|
|---|
| 429 | rpmlib_only = True
|
|---|
| 430 | for msg in msgs:
|
|---|
| 431 | if msg.startswith('rpmlib('):
|
|---|
| 432 | continue
|
|---|
| 433 | rpmlib_only = False
|
|---|
| 434 | if rpmlib_only:
|
|---|
| 435 | print _("ERROR You need to update rpm to handle:")
|
|---|
| 436 | else:
|
|---|
| 437 | print _('ERROR with rpm_check_debug vs depsolve:')
|
|---|
| 438 |
|
|---|
| 439 | for msg in msgs:
|
|---|
| 440 | print to_utf8(msg)
|
|---|
| 441 |
|
|---|
| 442 | if rpmlib_only:
|
|---|
| 443 | return 1, [_('RPM needs to be updated')]
|
|---|
| 444 | return 1, [_('Please report this error in %s') % self.conf.bugtracker_url]
|
|---|
| 445 |
|
|---|
| 446 | self.verbose_logger.debug('rpm_check_debug time: %0.3f' % (time.time() - rcd_st))
|
|---|
| 447 |
|
|---|
| 448 | tt_st = time.time()
|
|---|
| 449 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 450 | _('Running Transaction Test'))
|
|---|
| 451 | if not self.conf.diskspacecheck:
|
|---|
| 452 | self.tsInfo.probFilterFlags.append(rpm.RPMPROB_FILTER_DISKSPACE)
|
|---|
| 453 |
|
|---|
| 454 |
|
|---|
| 455 | testcb = RPMTransaction(self, test=True)
|
|---|
| 456 |
|
|---|
| 457 | self.initActionTs()
|
|---|
| 458 | # save our dsCallback out
|
|---|
| 459 | dscb = self.dsCallback
|
|---|
| 460 | self.dsCallback = None # dumb, dumb dumb dumb!
|
|---|
| 461 | self.populateTs(keepold=0) # sigh
|
|---|
| 462 | tserrors = self.ts.test(testcb)
|
|---|
| 463 | del testcb
|
|---|
| 464 |
|
|---|
| 465 | if len(tserrors) > 0:
|
|---|
| 466 | errstring = _('Transaction Check Error:\n')
|
|---|
| 467 | for descr in tserrors:
|
|---|
| 468 | errstring += ' %s\n' % to_unicode(descr)
|
|---|
| 469 |
|
|---|
| 470 | raise yum.Errors.YumBaseError, errstring + '\n' + \
|
|---|
| 471 | self.errorSummary(errstring)
|
|---|
| 472 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 473 | _('Transaction Test Succeeded'))
|
|---|
| 474 | del self.ts
|
|---|
| 475 |
|
|---|
| 476 | self.verbose_logger.debug('Transaction Test time: %0.3f' % (time.time() - tt_st))
|
|---|
| 477 |
|
|---|
| 478 | # unset the sigquit handler
|
|---|
| 479 | signal.signal(signal.SIGQUIT, signal.SIG_DFL)
|
|---|
| 480 |
|
|---|
| 481 | ts_st = time.time()
|
|---|
| 482 | self.initActionTs() # make a new, blank ts to populate
|
|---|
| 483 | self.populateTs(keepold=0) # populate the ts
|
|---|
| 484 | self.ts.check() #required for ordering
|
|---|
| 485 | self.ts.order() # order
|
|---|
| 486 |
|
|---|
| 487 | # put back our depcheck callback
|
|---|
| 488 | self.dsCallback = dscb
|
|---|
| 489 | # setup our rpm ts callback
|
|---|
| 490 | cb = RPMTransaction(self,
|
|---|
| 491 | display=output.YumCliRPMCallBack(weakref(self)))
|
|---|
| 492 | if self.conf.debuglevel < 2:
|
|---|
| 493 | cb.display.output = False
|
|---|
| 494 |
|
|---|
| 495 | self.verbose_logger.log(yum.logginglevels.INFO_2, _('Running Transaction'))
|
|---|
| 496 | resultobject = self.runTransaction(cb=cb)
|
|---|
| 497 |
|
|---|
| 498 | self.verbose_logger.debug('Transaction time: %0.3f' % (time.time() - ts_st))
|
|---|
| 499 | # close things
|
|---|
| 500 | self.verbose_logger.log(yum.logginglevels.INFO_1,
|
|---|
| 501 | self.postTransactionOutput())
|
|---|
| 502 |
|
|---|
| 503 | # put back the sigquit handler
|
|---|
| 504 | signal.signal(signal.SIGQUIT, sigquit)
|
|---|
| 505 |
|
|---|
| 506 | return resultobject.return_code
|
|---|
| 507 |
|
|---|
| 508 | def gpgsigcheck(self, pkgs):
|
|---|
| 509 | '''Perform GPG signature verification on the given packages, installing
|
|---|
| 510 | keys if possible
|
|---|
| 511 |
|
|---|
| 512 | Returns non-zero if execution should stop (user abort).
|
|---|
| 513 | Will raise YumBaseError if there's a problem
|
|---|
| 514 | '''
|
|---|
| 515 | for po in pkgs:
|
|---|
| 516 | result, errmsg = self.sigCheckPkg(po)
|
|---|
| 517 |
|
|---|
| 518 | if result == 0:
|
|---|
| 519 | # Verified ok, or verify not req'd
|
|---|
| 520 | continue
|
|---|
| 521 |
|
|---|
| 522 | elif result == 1:
|
|---|
| 523 | if not sys.stdin.isatty() and not self.conf.assumeyes:
|
|---|
| 524 | raise yum.Errors.YumBaseError, \
|
|---|
| 525 | _('Refusing to automatically import keys when running ' \
|
|---|
| 526 | 'unattended.\nUse "-y" to override.')
|
|---|
| 527 |
|
|---|
| 528 | # the callback here expects to be able to take options which
|
|---|
| 529 | # userconfirm really doesn't... so fake it
|
|---|
| 530 | self.getKeyForPackage(po, lambda x, y, z: self.userconfirm())
|
|---|
| 531 |
|
|---|
| 532 | else:
|
|---|
| 533 | # Fatal error
|
|---|
| 534 | raise yum.Errors.YumBaseError, errmsg
|
|---|
| 535 |
|
|---|
| 536 | return 0
|
|---|
| 537 |
|
|---|
| 538 | def _maybeYouMeant(self, arg):
|
|---|
| 539 | """ If install argument doesn't match with case, tell the user. """
|
|---|
| 540 | matches = self.doPackageLists(patterns=[arg], ignore_case=True)
|
|---|
| 541 | matches = matches.installed + matches.available
|
|---|
| 542 | matches = set(map(lambda x: x.name, matches))
|
|---|
| 543 | if matches:
|
|---|
| 544 | msg = self.fmtKeyValFill(_(' * Maybe you meant: '),
|
|---|
| 545 | ", ".join(matches))
|
|---|
| 546 | self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
|
|---|
| 547 |
|
|---|
| 548 | def _checkMaybeYouMeant(self, arg, always_output=True):
|
|---|
| 549 | """ If the update/remove argument doesn't match with case, or due
|
|---|
| 550 | to not being installed, tell the user. """
|
|---|
| 551 | # always_output is a wart due to update/remove not producing the
|
|---|
| 552 | # same output.
|
|---|
| 553 | matches = self.doPackageLists(patterns=[arg], ignore_case=False)
|
|---|
| 554 | if (matches.installed or (not matches.available and
|
|---|
| 555 | self.returnInstalledPackagesByDep(arg))):
|
|---|
| 556 | return # Found a match so ignore
|
|---|
| 557 | hibeg = self.term.MODE['bold']
|
|---|
| 558 | hiend = self.term.MODE['normal']
|
|---|
| 559 | if matches.available:
|
|---|
| 560 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 561 | _('Package(s) %s%s%s available, but not installed.'),
|
|---|
| 562 | hibeg, arg, hiend)
|
|---|
| 563 | return
|
|---|
| 564 |
|
|---|
| 565 | # No package name, so do the maybeYouMeant thing here too
|
|---|
| 566 | matches = self.doPackageLists(patterns=[arg], ignore_case=True)
|
|---|
| 567 | if not matches.installed and matches.available:
|
|---|
| 568 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 569 | _('Package(s) %s%s%s available, but not installed.'),
|
|---|
| 570 | hibeg, arg, hiend)
|
|---|
| 571 | return
|
|---|
| 572 | matches = set(map(lambda x: x.name, matches.installed))
|
|---|
| 573 | if always_output or matches:
|
|---|
| 574 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 575 | _('No package %s%s%s available.'),
|
|---|
| 576 | hibeg, arg, hiend)
|
|---|
| 577 | if matches:
|
|---|
| 578 | msg = self.fmtKeyValFill(_(' * Maybe you meant: '),
|
|---|
| 579 | ", ".join(matches))
|
|---|
| 580 | self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
|
|---|
| 581 |
|
|---|
| 582 | def installPkgs(self, userlist):
|
|---|
| 583 | """Attempts to take the user specified list of packages/wildcards
|
|---|
| 584 | and install them, or if they are installed, update them to a newer
|
|---|
| 585 | version. If a complete version number if specified, attempt to
|
|---|
| 586 | upgrade (or downgrade if they have been removed) them to the
|
|---|
| 587 | specified version"""
|
|---|
| 588 | # get the list of available packages
|
|---|
| 589 | # iterate over the user's list
|
|---|
| 590 | # add packages to Transaction holding class if they match.
|
|---|
| 591 | # if we've added any packages to the transaction then return 2 and a string
|
|---|
| 592 | # if we've hit a snag, return 1 and the failure explanation
|
|---|
| 593 | # if we've got nothing to do, return 0 and a 'nothing available to install' string
|
|---|
| 594 |
|
|---|
| 595 | oldcount = len(self.tsInfo)
|
|---|
| 596 |
|
|---|
| 597 | for arg in userlist:
|
|---|
| 598 | if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
|
|---|
| 599 | os.path.exists(arg))):
|
|---|
| 600 | self.localInstall(filelist=[arg])
|
|---|
| 601 | continue # it was something on disk and it ended in rpm
|
|---|
| 602 | # no matter what we don't go looking at repos
|
|---|
| 603 | try:
|
|---|
| 604 | self.install(pattern=arg)
|
|---|
| 605 | except yum.Errors.InstallError:
|
|---|
| 606 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 607 | _('No package %s%s%s available.'),
|
|---|
| 608 | self.term.MODE['bold'], arg,
|
|---|
| 609 | self.term.MODE['normal'])
|
|---|
| 610 | self._maybeYouMeant(arg)
|
|---|
| 611 | if len(self.tsInfo) > oldcount:
|
|---|
| 612 | return 2, [_('Package(s) to install')]
|
|---|
| 613 | return 0, [_('Nothing to do')]
|
|---|
| 614 |
|
|---|
| 615 | def updatePkgs(self, userlist, quiet=0):
|
|---|
| 616 | """take user commands and populate transaction wrapper with
|
|---|
| 617 | packages to be updated"""
|
|---|
| 618 |
|
|---|
| 619 | # if there is no userlist, then do global update below
|
|---|
| 620 | # this is probably 90% of the calls
|
|---|
| 621 | # if there is a userlist then it's for updating pkgs, not obsoleting
|
|---|
| 622 |
|
|---|
| 623 | oldcount = len(self.tsInfo)
|
|---|
| 624 | if len(userlist) == 0: # simple case - do them all
|
|---|
| 625 | self.update()
|
|---|
| 626 |
|
|---|
| 627 | else:
|
|---|
| 628 | # go through the userlist - look for items that are local rpms. If we find them
|
|---|
| 629 | # pass them off to localInstall() and then move on
|
|---|
| 630 | localupdates = []
|
|---|
| 631 | for item in userlist:
|
|---|
| 632 | if (item.endswith('.rpm') and (yum.misc.re_remote_url(item) or
|
|---|
| 633 | os.path.exists(item))):
|
|---|
| 634 | localupdates.append(item)
|
|---|
| 635 |
|
|---|
| 636 | if len(localupdates) > 0:
|
|---|
| 637 | self.localInstall(filelist=localupdates, updateonly=1)
|
|---|
| 638 | for item in localupdates:
|
|---|
| 639 | userlist.remove(item)
|
|---|
| 640 |
|
|---|
| 641 | for arg in userlist:
|
|---|
| 642 | if not self.update(pattern=arg):
|
|---|
| 643 | self._checkMaybeYouMeant(arg)
|
|---|
| 644 |
|
|---|
| 645 | if len(self.tsInfo) > oldcount:
|
|---|
| 646 | change = len(self.tsInfo) - oldcount
|
|---|
| 647 | msg = _('%d packages marked for Update') % change
|
|---|
| 648 | return 2, [msg]
|
|---|
| 649 | else:
|
|---|
| 650 | return 0, [_('No Packages marked for Update')]
|
|---|
| 651 |
|
|---|
| 652 | def erasePkgs(self, userlist):
|
|---|
| 653 | """take user commands and populate a transaction wrapper with packages
|
|---|
| 654 | to be erased/removed"""
|
|---|
| 655 |
|
|---|
| 656 | oldcount = len(self.tsInfo)
|
|---|
| 657 |
|
|---|
| 658 | for arg in userlist:
|
|---|
| 659 | if not self.remove(pattern=arg):
|
|---|
| 660 | self._checkMaybeYouMeant(arg, always_output=False)
|
|---|
| 661 |
|
|---|
| 662 | if len(self.tsInfo) > oldcount:
|
|---|
| 663 | change = len(self.tsInfo) - oldcount
|
|---|
| 664 | msg = _('%d packages marked for removal') % change
|
|---|
| 665 | return 2, [msg]
|
|---|
| 666 | else:
|
|---|
| 667 | return 0, [_('No Packages marked for removal')]
|
|---|
| 668 |
|
|---|
| 669 | def downgradePkgs(self, userlist):
|
|---|
| 670 | """Attempts to take the user specified list of packages/wildcards
|
|---|
| 671 | and downgrade them. If a complete version number if specified,
|
|---|
| 672 | attempt to downgrade them to the specified version"""
|
|---|
| 673 |
|
|---|
| 674 | oldcount = len(self.tsInfo)
|
|---|
| 675 |
|
|---|
| 676 | for arg in userlist:
|
|---|
| 677 | if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
|
|---|
| 678 | os.path.exists(arg))):
|
|---|
| 679 | self.downgradeLocal(arg)
|
|---|
| 680 | continue # it was something on disk and it ended in rpm
|
|---|
| 681 | # no matter what we don't go looking at repos
|
|---|
| 682 |
|
|---|
| 683 | try:
|
|---|
| 684 | self.downgrade(pattern=arg)
|
|---|
| 685 | except yum.Errors.DowngradeError:
|
|---|
| 686 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 687 | _('No package %s%s%s available.'),
|
|---|
| 688 | self.term.MODE['bold'], arg,
|
|---|
| 689 | self.term.MODE['normal'])
|
|---|
| 690 | self._maybeYouMeant(arg)
|
|---|
| 691 | if len(self.tsInfo) > oldcount:
|
|---|
| 692 | return 2, [_('Package(s) to downgrade')]
|
|---|
| 693 | return 0, [_('Nothing to do')]
|
|---|
| 694 |
|
|---|
| 695 | def reinstallPkgs(self, userlist):
|
|---|
| 696 | """Attempts to take the user specified list of packages/wildcards
|
|---|
| 697 | and reinstall them. """
|
|---|
| 698 |
|
|---|
| 699 | oldcount = len(self.tsInfo)
|
|---|
| 700 |
|
|---|
| 701 | for arg in userlist:
|
|---|
| 702 | if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
|
|---|
| 703 | os.path.exists(arg))):
|
|---|
| 704 | self.reinstallLocal(arg)
|
|---|
| 705 | continue # it was something on disk and it ended in rpm
|
|---|
| 706 | # no matter what we don't go looking at repos
|
|---|
| 707 |
|
|---|
| 708 | try:
|
|---|
| 709 | self.reinstall(pattern=arg)
|
|---|
| 710 | except yum.Errors.ReinstallRemoveError:
|
|---|
| 711 | self._checkMaybeYouMeant(arg, always_output=False)
|
|---|
| 712 | except yum.Errors.ReinstallInstallError, e:
|
|---|
| 713 | ipkg = self.rpmdb.returnPackages(patterns=[arg])[0]
|
|---|
| 714 | xmsg = ''
|
|---|
| 715 | if 'from_repo' in ipkg.yumdb_info:
|
|---|
| 716 | xmsg = ipkg.yumdb_info.from_repo
|
|---|
| 717 | xmsg = _(' (from %s)') % xmsg
|
|---|
| 718 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 719 | _('Installed package %s%s%s%s not available.'),
|
|---|
| 720 | self.term.MODE['bold'], ipkg,
|
|---|
| 721 | self.term.MODE['normal'], xmsg)
|
|---|
| 722 | except yum.Errors.ReinstallError, e:
|
|---|
| 723 | assert False, "Shouldn't happen, but just in case"
|
|---|
| 724 | self.verbose_logger.log(yum.logginglevels.INFO_2, e)
|
|---|
| 725 | if len(self.tsInfo) > oldcount:
|
|---|
| 726 | return 2, [_('Package(s) to reinstall')]
|
|---|
| 727 | return 0, [_('Nothing to do')]
|
|---|
| 728 |
|
|---|
| 729 | def localInstall(self, filelist, updateonly=0):
|
|---|
| 730 | """handles installs/updates of rpms provided on the filesystem in a
|
|---|
| 731 | local dir (ie: not from a repo)"""
|
|---|
| 732 |
|
|---|
| 733 | # read in each package into a YumLocalPackage Object
|
|---|
| 734 | # append it to self.localPackages
|
|---|
| 735 | # check if it can be installed or updated based on nevra versus rpmdb
|
|---|
| 736 | # don't import the repos until we absolutely need them for depsolving
|
|---|
| 737 |
|
|---|
| 738 | if len(filelist) == 0:
|
|---|
| 739 | return 0, [_('No Packages Provided')]
|
|---|
| 740 |
|
|---|
| 741 | installing = False
|
|---|
| 742 | for pkg in filelist:
|
|---|
| 743 | txmbrs = self.installLocal(pkg, updateonly=updateonly)
|
|---|
| 744 | if txmbrs:
|
|---|
| 745 | installing = True
|
|---|
| 746 |
|
|---|
| 747 | if installing:
|
|---|
| 748 | return 2, [_('Package(s) to install')]
|
|---|
| 749 | return 0, [_('Nothing to do')]
|
|---|
| 750 |
|
|---|
| 751 | def returnPkgLists(self, extcmds, installed_available=False):
|
|---|
| 752 | """Returns packages lists based on arguments on the cli.returns a
|
|---|
| 753 | GenericHolder instance with the following lists defined:
|
|---|
| 754 | available = list of packageObjects
|
|---|
| 755 | installed = list of packageObjects
|
|---|
| 756 | updates = tuples of packageObjects (updating, installed)
|
|---|
| 757 | extras = list of packageObjects
|
|---|
| 758 | obsoletes = tuples of packageObjects (obsoleting, installed)
|
|---|
| 759 | recent = list of packageObjects
|
|---|
| 760 |
|
|---|
| 761 | installed_available = that the available package list is present
|
|---|
| 762 | as .hidden_available when doing any of:
|
|---|
| 763 | all/available/installed
|
|---|
| 764 | """
|
|---|
| 765 |
|
|---|
| 766 | special = ['available', 'installed', 'all', 'extras', 'updates', 'recent',
|
|---|
| 767 | 'obsoletes']
|
|---|
| 768 |
|
|---|
| 769 | pkgnarrow = 'all'
|
|---|
| 770 | done_hidden_available = False
|
|---|
| 771 | done_hidden_installed = False
|
|---|
| 772 | if len(extcmds) > 0:
|
|---|
| 773 | if installed_available and extcmds[0] == 'installed':
|
|---|
| 774 | done_hidden_available = True
|
|---|
| 775 | extcmds.pop(0)
|
|---|
| 776 | elif installed_available and extcmds[0] == 'available':
|
|---|
| 777 | done_hidden_installed = True
|
|---|
| 778 | extcmds.pop(0)
|
|---|
| 779 | elif extcmds[0] in special:
|
|---|
| 780 | pkgnarrow = extcmds.pop(0)
|
|---|
| 781 |
|
|---|
| 782 | ypl = self.doPackageLists(pkgnarrow=pkgnarrow, patterns=extcmds,
|
|---|
| 783 | ignore_case=True)
|
|---|
| 784 | if self.conf.showdupesfromrepos:
|
|---|
| 785 | ypl.available += ypl.reinstall_available
|
|---|
| 786 |
|
|---|
| 787 | if installed_available:
|
|---|
| 788 | ypl.hidden_available = ypl.available
|
|---|
| 789 | ypl.hidden_installed = ypl.installed
|
|---|
| 790 | if done_hidden_available:
|
|---|
| 791 | ypl.available = []
|
|---|
| 792 | if done_hidden_installed:
|
|---|
| 793 | ypl.installed = []
|
|---|
| 794 | return ypl
|
|---|
| 795 |
|
|---|
| 796 | def search(self, args):
|
|---|
| 797 | """cli wrapper method for module search function, searches simple
|
|---|
| 798 | text tags in a package object"""
|
|---|
| 799 |
|
|---|
| 800 | # call the yum module search function with lists of tags to search
|
|---|
| 801 | # and what to search for
|
|---|
| 802 | # display the list of matches
|
|---|
| 803 |
|
|---|
| 804 | searchlist = ['name', 'summary', 'description', 'url']
|
|---|
| 805 | dups = self.conf.showdupesfromrepos
|
|---|
| 806 | args = map(to_unicode, args)
|
|---|
| 807 | matching = self.searchGenerator(searchlist, args,
|
|---|
| 808 | showdups=dups, keys=True)
|
|---|
| 809 |
|
|---|
| 810 | okeys = set()
|
|---|
| 811 | akeys = set()
|
|---|
| 812 | for (po, keys, matched_value) in matching:
|
|---|
| 813 | if keys != okeys:
|
|---|
| 814 | if akeys:
|
|---|
| 815 | print ""
|
|---|
| 816 | # Print them in the order they were passed
|
|---|
| 817 | used_keys = [arg for arg in args if arg in keys]
|
|---|
| 818 | print self.fmtSection(_('Matched: %s') % ", ".join(used_keys))
|
|---|
| 819 | okeys = keys
|
|---|
| 820 | akeys.update(keys)
|
|---|
| 821 | self.matchcallback(po, matched_value, args)
|
|---|
| 822 |
|
|---|
| 823 | for arg in args:
|
|---|
| 824 | if arg not in akeys:
|
|---|
| 825 | self.logger.warning(_('Warning: No matches found for: %s'), arg)
|
|---|
| 826 |
|
|---|
| 827 | if not akeys:
|
|---|
| 828 | return 0, [_('No Matches found')]
|
|---|
| 829 | return 0, matching
|
|---|
| 830 |
|
|---|
| 831 | def deplist(self, args):
|
|---|
| 832 | """cli wrapper method for findDeps method takes a list of packages and
|
|---|
| 833 | returns a formatted deplist for that package"""
|
|---|
| 834 |
|
|---|
| 835 | pkgs = []
|
|---|
| 836 | for arg in args:
|
|---|
| 837 | if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
|
|---|
| 838 | os.path.exists(arg))):
|
|---|
| 839 | thispkg = yum.packages.YumUrlPackage(self, self.ts, arg)
|
|---|
| 840 | pkgs.append(thispkg)
|
|---|
| 841 | else:
|
|---|
| 842 | ematch, match, unmatch = self.pkgSack.matchPackageNames([arg])
|
|---|
| 843 | for po in ematch + match:
|
|---|
| 844 | pkgs.append(po)
|
|---|
| 845 |
|
|---|
| 846 | results = self.findDeps(pkgs)
|
|---|
| 847 | self.depListOutput(results)
|
|---|
| 848 |
|
|---|
| 849 | return 0, []
|
|---|
| 850 |
|
|---|
| 851 | def provides(self, args):
|
|---|
| 852 | """use the provides methods in the rpmdb and pkgsack to produce a list
|
|---|
| 853 | of items matching the provides strings. This is a cli wrapper to the
|
|---|
| 854 | module"""
|
|---|
| 855 |
|
|---|
| 856 | old_sdup = self.conf.showdupesfromrepos
|
|---|
| 857 | # For output, as searchPackageProvides() is always in showdups mode
|
|---|
| 858 | self.conf.showdupesfromrepos = True
|
|---|
| 859 | cb = self.matchcallback_verbose
|
|---|
| 860 | matching = self.searchPackageProvides(args, callback=cb,
|
|---|
| 861 | callback_has_matchfor=True)
|
|---|
| 862 | self.conf.showdupesfromrepos = old_sdup
|
|---|
| 863 |
|
|---|
| 864 | if len(matching) == 0:
|
|---|
| 865 | for arg in args:
|
|---|
| 866 | if '*' in arg or (arg and arg[0] == '/'):
|
|---|
| 867 | continue
|
|---|
| 868 | self.logger.warning(_('Warning: 3.0.x versions of yum would erroneously match against filenames.\n You can use "%s*/%s%s" and/or "%s*bin/%s%s" to get that behaviour'),
|
|---|
| 869 | self.term.MODE['bold'], arg,
|
|---|
| 870 | self.term.MODE['normal'],
|
|---|
| 871 | self.term.MODE['bold'], arg,
|
|---|
| 872 | self.term.MODE['normal'])
|
|---|
| 873 | return 0, ['No Matches found']
|
|---|
| 874 |
|
|---|
| 875 | return 0, []
|
|---|
| 876 |
|
|---|
| 877 | def resolveDepCli(self, args):
|
|---|
| 878 | """returns a package (one per user arg) that provide the supplied arg"""
|
|---|
| 879 |
|
|---|
| 880 | for arg in args:
|
|---|
| 881 | try:
|
|---|
| 882 | pkg = self.returnPackageByDep(arg)
|
|---|
| 883 | except yum.Errors.YumBaseError:
|
|---|
| 884 | self.logger.critical(_('No Package Found for %s'), arg)
|
|---|
| 885 | else:
|
|---|
| 886 | msg = '%s:%s-%s-%s.%s' % (pkg.epoch, pkg.name, pkg.version, pkg.release, pkg.arch)
|
|---|
| 887 | self.verbose_logger.info(msg)
|
|---|
| 888 |
|
|---|
| 889 | return 0, []
|
|---|
| 890 |
|
|---|
| 891 | def cleanCli(self, userlist):
|
|---|
| 892 | hdrcode = pkgcode = xmlcode = dbcode = expccode = 0
|
|---|
| 893 | pkgresults = hdrresults = xmlresults = dbresults = expcresults = []
|
|---|
| 894 | if 'all' in userlist:
|
|---|
| 895 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 896 | _('Cleaning up Everything'))
|
|---|
| 897 | pkgcode, pkgresults = self.cleanPackages()
|
|---|
| 898 | hdrcode, hdrresults = self.cleanHeaders()
|
|---|
| 899 | xmlcode, xmlresults = self.cleanMetadata()
|
|---|
| 900 | dbcode, dbresults = self.cleanSqlite()
|
|---|
| 901 | rpmcode, rpmresults = self.cleanRpmDB()
|
|---|
| 902 | self.plugins.run('clean')
|
|---|
| 903 |
|
|---|
| 904 | code = hdrcode + pkgcode + xmlcode + dbcode + rpmcode
|
|---|
| 905 | results = (hdrresults + pkgresults + xmlresults + dbresults +
|
|---|
| 906 | rpmresults)
|
|---|
| 907 | for msg in results:
|
|---|
| 908 | self.logger.debug(msg)
|
|---|
| 909 | return code, []
|
|---|
| 910 |
|
|---|
| 911 | if 'headers' in userlist:
|
|---|
| 912 | self.logger.debug(_('Cleaning up Headers'))
|
|---|
| 913 | hdrcode, hdrresults = self.cleanHeaders()
|
|---|
| 914 | if 'packages' in userlist:
|
|---|
| 915 | self.logger.debug(_('Cleaning up Packages'))
|
|---|
| 916 | pkgcode, pkgresults = self.cleanPackages()
|
|---|
| 917 | if 'metadata' in userlist:
|
|---|
| 918 | self.logger.debug(_('Cleaning up xml metadata'))
|
|---|
| 919 | xmlcode, xmlresults = self.cleanMetadata()
|
|---|
| 920 | if 'dbcache' in userlist or 'metadata' in userlist:
|
|---|
| 921 | self.logger.debug(_('Cleaning up database cache'))
|
|---|
| 922 | dbcode, dbresults = self.cleanSqlite()
|
|---|
| 923 | if 'expire-cache' in userlist or 'metadata' in userlist:
|
|---|
| 924 | self.logger.debug(_('Cleaning up expire-cache metadata'))
|
|---|
| 925 | expccode, expcresults = self.cleanExpireCache()
|
|---|
| 926 | if 'rpmdb' in userlist:
|
|---|
| 927 | self.logger.debug(_('Cleaning up cached rpmdb data'))
|
|---|
| 928 | expccode, expcresults = self.cleanRpmDB()
|
|---|
| 929 | if 'plugins' in userlist:
|
|---|
| 930 | self.logger.debug(_('Cleaning up plugins'))
|
|---|
| 931 | self.plugins.run('clean')
|
|---|
| 932 |
|
|---|
| 933 | code = hdrcode + pkgcode + xmlcode + dbcode + expccode
|
|---|
| 934 | results = hdrresults + pkgresults + xmlresults + dbresults + expcresults
|
|---|
| 935 | for msg in results:
|
|---|
| 936 | self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
|
|---|
| 937 | return code, []
|
|---|
| 938 |
|
|---|
| 939 | def returnGroupLists(self, userlist):
|
|---|
| 940 |
|
|---|
| 941 | uservisible=1
|
|---|
| 942 |
|
|---|
| 943 | if len(userlist) > 0:
|
|---|
| 944 | if userlist[0] == 'hidden':
|
|---|
| 945 | uservisible=0
|
|---|
| 946 | userlist.pop(0)
|
|---|
| 947 | if not userlist:
|
|---|
| 948 | userlist = None # Match everything...
|
|---|
| 949 |
|
|---|
| 950 | installed, available = self.doGroupLists(uservisible=uservisible,
|
|---|
| 951 | patterns=userlist)
|
|---|
| 952 |
|
|---|
| 953 | if len(installed) > 0:
|
|---|
| 954 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 955 | _('Installed Groups:'))
|
|---|
| 956 | for group in installed:
|
|---|
| 957 | if self.verbose_logger.isEnabledFor(yum.logginglevels.DEBUG_3):
|
|---|
| 958 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 959 | ' %s (%s)', group.ui_name,
|
|---|
| 960 | group.groupid)
|
|---|
| 961 | else:
|
|---|
| 962 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 963 | ' %s', group.ui_name)
|
|---|
| 964 |
|
|---|
| 965 | if len(available) > 0:
|
|---|
| 966 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 967 | _('Available Groups:'))
|
|---|
| 968 | for group in available:
|
|---|
| 969 | if self.verbose_logger.isEnabledFor(yum.logginglevels.DEBUG_3):
|
|---|
| 970 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 971 | ' %s (%s)', group.ui_name,
|
|---|
| 972 | group.groupid)
|
|---|
| 973 | else:
|
|---|
| 974 | self.verbose_logger.log(yum.logginglevels.INFO_2,
|
|---|
| 975 | ' %s', group.ui_name)
|
|---|
| 976 |
|
|---|
| 977 | return 0, [_('Done')]
|
|---|
| 978 |
|
|---|
| 979 | def returnGroupInfo(self, userlist):
|
|---|
| 980 | """returns complete information on a list of groups"""
|
|---|
| 981 | for strng in userlist:
|
|---|
| 982 | group_matched = False
|
|---|
| 983 | for group in self.comps.return_groups(strng):
|
|---|
| 984 | self.displayPkgsInGroups(group)
|
|---|
| 985 | group_matched = True
|
|---|
| 986 |
|
|---|
| 987 | if not group_matched:
|
|---|
| 988 | self.logger.error(_('Warning: Group %s does not exist.'), strng)
|
|---|
| 989 |
|
|---|
| 990 | return 0, []
|
|---|
| 991 |
|
|---|
| 992 | def installGroups(self, grouplist):
|
|---|
| 993 | """for each group requested do 'selectGroup' on them."""
|
|---|
| 994 |
|
|---|
| 995 | pkgs_used = []
|
|---|
| 996 |
|
|---|
| 997 | for group_string in grouplist:
|
|---|
| 998 | group_matched = False
|
|---|
| 999 | for group in self.comps.return_groups(group_string):
|
|---|
| 1000 | group_matched = True
|
|---|
| 1001 |
|
|---|
| 1002 |
|
|---|
| 1003 | try:
|
|---|
| 1004 | txmbrs = self.selectGroup(group.groupid)
|
|---|
| 1005 | except yum.Errors.GroupsError:
|
|---|
| 1006 | self.logger.critical(_('Warning: Group %s does not exist.'), group_string)
|
|---|
| 1007 | continue
|
|---|
| 1008 | else:
|
|---|
| 1009 | pkgs_used.extend(txmbrs)
|
|---|
| 1010 |
|
|---|
| 1011 | if not group_matched:
|
|---|
| 1012 | self.logger.error(_('Warning: Group %s does not exist.'), group_string)
|
|---|
| 1013 | continue
|
|---|
| 1014 |
|
|---|
| 1015 | if not pkgs_used:
|
|---|
| 1016 | return 0, [_('No packages in any requested group available to install or update')]
|
|---|
| 1017 | else:
|
|---|
| 1018 | return 2, [_('%d Package(s) to Install') % len(pkgs_used)]
|
|---|
| 1019 |
|
|---|
| 1020 | def removeGroups(self, grouplist):
|
|---|
| 1021 | """Remove only packages of the named group(s). Do not recurse."""
|
|---|
| 1022 |
|
|---|
| 1023 | pkgs_used = []
|
|---|
| 1024 | for group_string in grouplist:
|
|---|
| 1025 | try:
|
|---|
| 1026 | txmbrs = self.groupRemove(group_string)
|
|---|
| 1027 | except yum.Errors.GroupsError:
|
|---|
| 1028 | self.logger.critical(_('No group named %s exists'), group_string)
|
|---|
| 1029 | continue
|
|---|
| 1030 | else:
|
|---|
| 1031 | pkgs_used.extend(txmbrs)
|
|---|
| 1032 |
|
|---|
| 1033 | if not pkgs_used:
|
|---|
| 1034 | return 0, [_('No packages to remove from groups')]
|
|---|
| 1035 | else:
|
|---|
| 1036 | return 2, [_('%d Package(s) to remove') % len(pkgs_used)]
|
|---|
| 1037 |
|
|---|
| 1038 |
|
|---|
| 1039 |
|
|---|
| 1040 | def _promptWanted(self):
|
|---|
| 1041 | # shortcut for the always-off/always-on options
|
|---|
| 1042 | if self.conf.assumeyes:
|
|---|
| 1043 | return False
|
|---|
| 1044 | if self.conf.alwaysprompt:
|
|---|
| 1045 | return True
|
|---|
| 1046 |
|
|---|
| 1047 | # prompt if:
|
|---|
| 1048 | # package was added to fill a dependency
|
|---|
| 1049 | # package is being removed
|
|---|
| 1050 | # package wasn't explictly given on the command line
|
|---|
| 1051 | for txmbr in self.tsInfo.getMembers():
|
|---|
| 1052 | if txmbr.isDep or \
|
|---|
| 1053 | txmbr.ts_state == 'e' or \
|
|---|
| 1054 | txmbr.name not in self.extcmds:
|
|---|
| 1055 | return True
|
|---|
| 1056 |
|
|---|
| 1057 | # otherwise, don't prompt
|
|---|
| 1058 | return False
|
|---|
| 1059 |
|
|---|
| 1060 | def usage(self):
|
|---|
| 1061 | ''' Print out command line usage '''
|
|---|
| 1062 | sys.stdout.write(self.optparser.format_help())
|
|---|
| 1063 |
|
|---|
| 1064 | def shellUsage(self):
|
|---|
| 1065 | ''' Print out the shell usage '''
|
|---|
| 1066 | sys.stdout.write(self.optparser.get_usage())
|
|---|
| 1067 |
|
|---|
| 1068 | def _installable(self, pkg, ematch=False):
|
|---|
| 1069 |
|
|---|
| 1070 | """check if the package is reasonably installable, true/false"""
|
|---|
| 1071 |
|
|---|
| 1072 | exactarchlist = self.conf.exactarchlist
|
|---|
| 1073 | # we look through each returned possibility and rule out the
|
|---|
| 1074 | # ones that we obviously can't use
|
|---|
| 1075 |
|
|---|
| 1076 | if self.rpmdb.contains(po=pkg):
|
|---|
| 1077 | self.verbose_logger.log(yum.logginglevels.DEBUG_3,
|
|---|
| 1078 | _('Package %s is already installed, skipping'), pkg)
|
|---|
| 1079 | return False
|
|---|
| 1080 |
|
|---|
| 1081 | # everything installed that matches the name
|
|---|
| 1082 | installedByKey = self.rpmdb.searchNevra(name=pkg.name)
|
|---|
| 1083 | comparable = []
|
|---|
| 1084 | for instpo in installedByKey:
|
|---|
| 1085 | if isMultiLibArch(instpo.arch) == isMultiLibArch(pkg.arch):
|
|---|
| 1086 | comparable.append(instpo)
|
|---|
| 1087 | else:
|
|---|
| 1088 | self.verbose_logger.log(yum.logginglevels.DEBUG_3,
|
|---|
| 1089 | _('Discarding non-comparable pkg %s.%s'), instpo.name, instpo.arch)
|
|---|
| 1090 | continue
|
|---|
| 1091 |
|
|---|
| 1092 | # go through each package
|
|---|
| 1093 | if len(comparable) > 0:
|
|---|
| 1094 | for instpo in comparable:
|
|---|
| 1095 | if pkg.verGT(instpo): # we're newer - this is an update, pass to them
|
|---|
| 1096 | if instpo.name in exactarchlist:
|
|---|
| 1097 | if pkg.arch == instpo.arch:
|
|---|
| 1098 | return True
|
|---|
| 1099 | else:
|
|---|
| 1100 | return True
|
|---|
| 1101 |
|
|---|
| 1102 | elif pkg.verEQ(instpo): # same, ignore
|
|---|
| 1103 | return False
|
|---|
| 1104 |
|
|---|
| 1105 | elif pkg.verLT(instpo): # lesser, check if the pkgtup is an exactmatch
|
|---|
| 1106 | # if so then add it to be installed
|
|---|
| 1107 | # if it can be multiply installed
|
|---|
| 1108 | # this is where we could handle setting
|
|---|
| 1109 | # it to be an 'oldpackage' revert.
|
|---|
| 1110 |
|
|---|
| 1111 | if ematch and self.allowedMultipleInstalls(pkg):
|
|---|
| 1112 | return True
|
|---|
| 1113 |
|
|---|
| 1114 | else: # we've not got any installed that match n or n+a
|
|---|
| 1115 | self.verbose_logger.log(yum.logginglevels.DEBUG_1, _('No other %s installed, adding to list for potential install'), pkg.name)
|
|---|
| 1116 | return True
|
|---|
| 1117 |
|
|---|
| 1118 | return False
|
|---|
| 1119 |
|
|---|
| 1120 | class YumOptionParser(OptionParser):
|
|---|
| 1121 | '''Subclass that makes some minor tweaks to make OptionParser do things the
|
|---|
| 1122 | "yum way".
|
|---|
| 1123 | '''
|
|---|
| 1124 |
|
|---|
| 1125 | def __init__(self,base, **kwargs):
|
|---|
| 1126 | # check if this is called with a utils=True/False parameter
|
|---|
| 1127 | if 'utils' in kwargs:
|
|---|
| 1128 | self._utils = kwargs['utils']
|
|---|
| 1129 | del kwargs['utils']
|
|---|
| 1130 | else:
|
|---|
| 1131 | self._utils = False
|
|---|
| 1132 | OptionParser.__init__(self, **kwargs)
|
|---|
| 1133 | self.logger = logging.getLogger("yum.cli")
|
|---|
| 1134 | self.base = base
|
|---|
| 1135 | self.plugin_option_group = OptionGroup(self, _("Plugin Options"))
|
|---|
| 1136 | self.add_option_group(self.plugin_option_group)
|
|---|
| 1137 |
|
|---|
| 1138 | self._addYumBasicOptions()
|
|---|
| 1139 |
|
|---|
| 1140 | def error(self, msg):
|
|---|
| 1141 | '''This method is overridden so that error output goes to logger. '''
|
|---|
| 1142 | self.print_usage()
|
|---|
| 1143 | self.logger.critical(_("Command line error: %s"), msg)
|
|---|
| 1144 | sys.exit(1)
|
|---|
| 1145 |
|
|---|
| 1146 | def firstParse(self,args):
|
|---|
| 1147 | # Parse only command line options that affect basic yum setup
|
|---|
| 1148 | try:
|
|---|
| 1149 | args = _filtercmdline(
|
|---|
| 1150 | ('--noplugins','--version','-q', '-v', "--quiet", "--verbose"),
|
|---|
| 1151 | ('-c', '-d', '-e', '--installroot',
|
|---|
| 1152 | '--disableplugin', '--enableplugin', '--releasever'),
|
|---|
| 1153 | args)
|
|---|
| 1154 | except ValueError, arg:
|
|---|
| 1155 | self.base.usage()
|
|---|
| 1156 | print >> sys.stderr, (_("\n\n%s: %s option requires an argument") %
|
|---|
| 1157 | ('Command line error', arg))
|
|---|
| 1158 | sys.exit(1)
|
|---|
| 1159 | return self.parse_args(args=args)[0]
|
|---|
| 1160 |
|
|---|
| 1161 | @staticmethod
|
|---|
| 1162 | def _splitArg(seq):
|
|---|
| 1163 | """ Split all strings in seq, at "," and whitespace.
|
|---|
| 1164 | Returns a new list. """
|
|---|
| 1165 | ret = []
|
|---|
| 1166 | for arg in seq:
|
|---|
| 1167 | ret.extend(arg.replace(",", " ").split())
|
|---|
| 1168 | return ret
|
|---|
| 1169 |
|
|---|
| 1170 | def setupYumConfig(self, args=None):
|
|---|
| 1171 | # Now parse the command line for real
|
|---|
| 1172 | if not args:
|
|---|
| 1173 | (opts, cmds) = self.parse_args()
|
|---|
| 1174 | else:
|
|---|
| 1175 | (opts, cmds) = self.parse_args(args=args)
|
|---|
| 1176 |
|
|---|
| 1177 | # Let the plugins know what happened on the command line
|
|---|
| 1178 | self.base.plugins.setCmdLine(opts, cmds)
|
|---|
| 1179 |
|
|---|
| 1180 | try:
|
|---|
| 1181 | # config file is parsed and moving us forward
|
|---|
| 1182 | # set some things in it.
|
|---|
| 1183 |
|
|---|
| 1184 | # Handle remaining options
|
|---|
| 1185 | if opts.assumeyes:
|
|---|
| 1186 | self.base.conf.assumeyes =1
|
|---|
| 1187 |
|
|---|
| 1188 | # Instead of going cache-only for a non-root user, try to use a
|
|---|
| 1189 | # user writable cachedir. If that fails fall back to cache-only.
|
|---|
| 1190 | if opts.cacheonly:
|
|---|
| 1191 | self.base.conf.cache = 1
|
|---|
| 1192 | elif not self.base.setCacheDir():
|
|---|
| 1193 | self.base.conf.cache = 1
|
|---|
| 1194 |
|
|---|
| 1195 | if opts.obsoletes:
|
|---|
| 1196 | self.base.conf.obsoletes = 1
|
|---|
| 1197 |
|
|---|
| 1198 | if opts.installroot:
|
|---|
| 1199 | self.base.conf.installroot = opts.installroot
|
|---|
| 1200 |
|
|---|
| 1201 | if opts.skipbroken:
|
|---|
| 1202 | self.base.conf.skip_broken = True
|
|---|
| 1203 |
|
|---|
| 1204 | if opts.showdupesfromrepos:
|
|---|
| 1205 | self.base.conf.showdupesfromrepos = True
|
|---|
| 1206 |
|
|---|
| 1207 | if opts.color not in (None, 'auto', 'always', 'never',
|
|---|
| 1208 | 'tty', 'if-tty', 'yes', 'no', 'on', 'off'):
|
|---|
| 1209 | raise ValueError, _("--color takes one of: auto, always, never")
|
|---|
| 1210 | elif opts.color is None:
|
|---|
| 1211 | if self.base.conf.color != 'auto':
|
|---|
| 1212 | self.base.term.reinit(color=self.base.conf.color)
|
|---|
| 1213 | else:
|
|---|
| 1214 | _remap = {'tty' : 'auto', 'if-tty' : 'auto',
|
|---|
| 1215 | '1' : 'always', 'true' : 'always',
|
|---|
| 1216 | 'yes' : 'always', 'on' : 'always',
|
|---|
| 1217 | '0' : 'always', 'false' : 'always',
|
|---|
| 1218 | 'no' : 'never', 'off' : 'never'}
|
|---|
| 1219 | opts.color = _remap.get(opts.color, opts.color)
|
|---|
| 1220 | if opts.color != 'auto':
|
|---|
| 1221 | self.base.term.reinit(color=opts.color)
|
|---|
| 1222 |
|
|---|
| 1223 | if opts.disableexcludes:
|
|---|
| 1224 | disable_excludes = self._splitArg(opts.disableexcludes)
|
|---|
| 1225 | else:
|
|---|
| 1226 | disable_excludes = []
|
|---|
| 1227 | self.base.conf.disable_excludes = disable_excludes
|
|---|
| 1228 |
|
|---|
| 1229 | for exclude in self._splitArg(opts.exclude):
|
|---|
| 1230 | try:
|
|---|
| 1231 | excludelist = self.base.conf.exclude
|
|---|
| 1232 | excludelist.append(exclude)
|
|---|
| 1233 | self.base.conf.exclude = excludelist
|
|---|
| 1234 | except yum.Errors.ConfigError, e:
|
|---|
| 1235 | self.logger.critical(e)
|
|---|
| 1236 | self.base.usage()
|
|---|
| 1237 | sys.exit(1)
|
|---|
| 1238 |
|
|---|
| 1239 | if opts.rpmverbosity is not None:
|
|---|
| 1240 | self.base.conf.rpmverbosity = opts.rpmverbosity
|
|---|
| 1241 |
|
|---|
| 1242 | # setup the progress bars/callbacks
|
|---|
| 1243 | self.base.setupProgressCallbacks()
|
|---|
| 1244 | # setup the callbacks to import gpg pubkeys and confirm them
|
|---|
| 1245 | self.base.setupKeyImportCallbacks()
|
|---|
| 1246 |
|
|---|
| 1247 | # Process repo enables and disables in order
|
|---|
| 1248 | for opt, repoexp in opts.repos:
|
|---|
| 1249 | try:
|
|---|
| 1250 | if opt == '--enablerepo':
|
|---|
| 1251 | self.base.repos.enableRepo(repoexp)
|
|---|
| 1252 | elif opt == '--disablerepo':
|
|---|
| 1253 | self.base.repos.disableRepo(repoexp)
|
|---|
| 1254 | except yum.Errors.ConfigError, e:
|
|---|
| 1255 | self.logger.critical(e)
|
|---|
| 1256 | self.base.usage()
|
|---|
| 1257 | sys.exit(1)
|
|---|
| 1258 |
|
|---|
| 1259 | # make sure the added repos are setup.
|
|---|
| 1260 | if len(opts.repos) > 0:
|
|---|
| 1261 | self.base._getRepos(doSetup=True)
|
|---|
| 1262 |
|
|---|
| 1263 | # Disable all gpg key checking, if requested.
|
|---|
| 1264 | if opts.nogpgcheck:
|
|---|
| 1265 | self.base.conf.gpgcheck = False
|
|---|
| 1266 | self.base.conf.repo_gpgcheck = False
|
|---|
| 1267 | for repo in self.base.repos.listEnabled():
|
|---|
| 1268 | repo.gpgcheck = False
|
|---|
| 1269 | repo.repo_gpgcheck = False
|
|---|
| 1270 |
|
|---|
| 1271 | except ValueError, e:
|
|---|
| 1272 | self.logger.critical(_('Options Error: %s'), e)
|
|---|
| 1273 | self.base.usage()
|
|---|
| 1274 | sys.exit(1)
|
|---|
| 1275 |
|
|---|
| 1276 | return opts, cmds
|
|---|
| 1277 |
|
|---|
| 1278 | def getRoot(self,opts):
|
|---|
| 1279 | # If the conf file is inside the installroot - use that.
|
|---|
| 1280 | # otherwise look for it in the normal root
|
|---|
| 1281 | if opts.installroot:
|
|---|
| 1282 | if os.access(opts.installroot+'/'+opts.conffile, os.R_OK):
|
|---|
| 1283 | opts.conffile = opts.installroot+'/'+opts.conffile
|
|---|
| 1284 | elif opts.conffile == '/etc/yum/yum.conf':
|
|---|
| 1285 | # check if /installroot/etc/yum.conf exists.
|
|---|
| 1286 | if os.access(opts.installroot+'/etc/yum.conf', os.R_OK):
|
|---|
| 1287 | opts.conffile = opts.installroot+'/etc/yum.conf'
|
|---|
| 1288 | root=opts.installroot
|
|---|
| 1289 | else:
|
|---|
| 1290 | root = '/@unixroot'
|
|---|
| 1291 | return root
|
|---|
| 1292 |
|
|---|
| 1293 | def _wrapOptParseUsage(self, opt, value, parser, *args, **kwargs):
|
|---|
| 1294 | self.base.usage()
|
|---|
| 1295 | self.exit()
|
|---|
| 1296 |
|
|---|
| 1297 | def _addYumBasicOptions(self):
|
|---|
| 1298 | def repo_optcb(optobj, opt, value, parser):
|
|---|
| 1299 | '''Callback for the enablerepo and disablerepo option.
|
|---|
| 1300 |
|
|---|
| 1301 | Combines the values given for these options while preserving order
|
|---|
| 1302 | from command line.
|
|---|
| 1303 | '''
|
|---|
| 1304 | dest = eval('parser.values.%s' % optobj.dest)
|
|---|
| 1305 | dest.append((opt, value))
|
|---|
| 1306 |
|
|---|
| 1307 | if self._utils:
|
|---|
| 1308 | group = OptionGroup(self, "Yum Base Options")
|
|---|
| 1309 | self.add_option_group(group)
|
|---|
| 1310 | else:
|
|---|
| 1311 | group = self
|
|---|
| 1312 |
|
|---|
| 1313 | # Note that we can't use the default action="help" because of the
|
|---|
| 1314 | # fact that print_help() unconditionally does .encode() ... which is
|
|---|
| 1315 | # bad on unicode input.
|
|---|
| 1316 | group.conflict_handler = "resolve"
|
|---|
| 1317 | group.add_option("-h", "--help", action="callback",
|
|---|
| 1318 | callback=self._wrapOptParseUsage,
|
|---|
| 1319 | help=_("show this help message and exit"))
|
|---|
| 1320 | group.conflict_handler = "error"
|
|---|
| 1321 |
|
|---|
| 1322 | group.add_option("-t", "--tolerant", action="store_true",
|
|---|
| 1323 | help=_("be tolerant of errors"))
|
|---|
| 1324 | group.add_option("-C", "--cacheonly", dest="cacheonly",
|
|---|
| 1325 | action="store_true",
|
|---|
| 1326 | help=_("run entirely from system cache, don't update cache"))
|
|---|
| 1327 | group.add_option("-c", "--config", dest="conffile",
|
|---|
| 1328 | default='/@unixroot/etc/yum/yum.conf',
|
|---|
| 1329 | help=_("config file location"), metavar='[config file]')
|
|---|
| 1330 | group.add_option("-R", "--randomwait", dest="sleeptime", type='int',
|
|---|
| 1331 | default=None,
|
|---|
| 1332 | help=_("maximum command wait time"), metavar='[minutes]')
|
|---|
| 1333 | group.add_option("-d", "--debuglevel", dest="debuglevel", default=None,
|
|---|
| 1334 | help=_("debugging output level"), type='int',
|
|---|
| 1335 | metavar='[debug level]')
|
|---|
| 1336 | group.add_option("--showduplicates", dest="showdupesfromrepos",
|
|---|
| 1337 | action="store_true",
|
|---|
| 1338 | help=_("show duplicates, in repos, in list/search commands"))
|
|---|
| 1339 | group.add_option("-e", "--errorlevel", dest="errorlevel", default=None,
|
|---|
| 1340 | help=_("error output level"), type='int',
|
|---|
| 1341 | metavar='[error level]')
|
|---|
| 1342 | group.add_option("", "--rpmverbosity", default=None,
|
|---|
| 1343 | help=_("debugging output level for rpm"),
|
|---|
| 1344 | metavar='[debug level name]')
|
|---|
| 1345 | group.add_option("-q", "--quiet", dest="quiet", action="store_true",
|
|---|
| 1346 | help=_("quiet operation"))
|
|---|
| 1347 | group.add_option("-v", "--verbose", dest="verbose", action="store_true",
|
|---|
| 1348 | help=_("verbose operation"))
|
|---|
| 1349 | group.add_option("-y", "--assumeyes", dest="assumeyes",
|
|---|
| 1350 | action="store_true", help=_("answer yes for all questions"))
|
|---|
| 1351 | group.add_option("--version", action="store_true",
|
|---|
| 1352 | help=_("show Yum version and exit"))
|
|---|
| 1353 | group.add_option("--installroot", help=_("set install root"),
|
|---|
| 1354 | metavar='[path]')
|
|---|
| 1355 | group.add_option("--enablerepo", action='callback',
|
|---|
| 1356 | type='string', callback=repo_optcb, dest='repos', default=[],
|
|---|
| 1357 | help=_("enable one or more repositories (wildcards allowed)"),
|
|---|
| 1358 | metavar='[repo]')
|
|---|
| 1359 | group.add_option("--disablerepo", action='callback',
|
|---|
| 1360 | type='string', callback=repo_optcb, dest='repos', default=[],
|
|---|
| 1361 | help=_("disable one or more repositories (wildcards allowed)"),
|
|---|
| 1362 | metavar='[repo]')
|
|---|
| 1363 | group.add_option("-x", "--exclude", default=[], action="append",
|
|---|
| 1364 | help=_("exclude package(s) by name or glob"), metavar='[package]')
|
|---|
| 1365 | group.add_option("", "--disableexcludes", default=[], action="append",
|
|---|
| 1366 | help=_("disable exclude from main, for a repo or for everything"),
|
|---|
| 1367 | metavar='[repo]')
|
|---|
| 1368 | group.add_option("--obsoletes", action="store_true",
|
|---|
| 1369 | help=_("enable obsoletes processing during updates"))
|
|---|
| 1370 | group.add_option("--noplugins", action="store_true",
|
|---|
| 1371 | help=_("disable Yum plugins"))
|
|---|
| 1372 | group.add_option("--nogpgcheck", action="store_true",
|
|---|
| 1373 | help=_("disable gpg signature checking"))
|
|---|
| 1374 | group.add_option("", "--disableplugin", dest="disableplugins", default=[],
|
|---|
| 1375 | action="append", help=_("disable plugins by name"),
|
|---|
| 1376 | metavar='[plugin]')
|
|---|
| 1377 | group.add_option("", "--enableplugin", dest="enableplugins", default=[],
|
|---|
| 1378 | action="append", help=_("enable plugins by name"),
|
|---|
| 1379 | metavar='[plugin]')
|
|---|
| 1380 | group.add_option("--skip-broken", action="store_true", dest="skipbroken",
|
|---|
| 1381 | help=_("skip packages with depsolving problems"))
|
|---|
| 1382 | group.add_option("", "--color", dest="color", default=None,
|
|---|
| 1383 | help=_("control whether color is used"))
|
|---|
| 1384 | group.add_option("", "--releasever", dest="releasever", default=None,
|
|---|
| 1385 | help=_("set value of $releasever in yum config and repo files"))
|
|---|
| 1386 |
|
|---|
| 1387 |
|
|---|
| 1388 |
|
|---|
| 1389 | def _filtercmdline(novalopts, valopts, args):
|
|---|
| 1390 | '''Keep only specific options from the command line argument list
|
|---|
| 1391 |
|
|---|
| 1392 | This function allows us to peek at specific command line options when using
|
|---|
| 1393 | the optparse module. This is useful when some options affect what other
|
|---|
| 1394 | options should be available.
|
|---|
| 1395 |
|
|---|
| 1396 | @param novalopts: A sequence of options to keep that don't take an argument.
|
|---|
| 1397 | @param valopts: A sequence of options to keep that take a single argument.
|
|---|
| 1398 | @param args: The command line arguments to parse (as per sys.argv[:1]
|
|---|
| 1399 | @return: A list of strings containing the filtered version of args.
|
|---|
| 1400 |
|
|---|
| 1401 | Will raise ValueError if there was a problem parsing the command line.
|
|---|
| 1402 | '''
|
|---|
| 1403 | out = []
|
|---|
| 1404 | args = list(args) # Make a copy because this func is destructive
|
|---|
| 1405 |
|
|---|
| 1406 | while len(args) > 0:
|
|---|
| 1407 | a = args.pop(0)
|
|---|
| 1408 | if '=' in a:
|
|---|
| 1409 | opt, _ = a.split('=', 1)
|
|---|
| 1410 | if opt in valopts:
|
|---|
| 1411 | out.append(a)
|
|---|
| 1412 |
|
|---|
| 1413 | elif a in novalopts:
|
|---|
| 1414 | out.append(a)
|
|---|
| 1415 |
|
|---|
| 1416 | elif a in valopts:
|
|---|
| 1417 | if len(args) < 1:
|
|---|
| 1418 | raise ValueError, a
|
|---|
| 1419 | next = args.pop(0)
|
|---|
| 1420 | if next[0] == '-':
|
|---|
| 1421 | raise ValueError, a
|
|---|
| 1422 |
|
|---|
| 1423 | out.extend([a, next])
|
|---|
| 1424 |
|
|---|
| 1425 | else:
|
|---|
| 1426 | # Check for single letter options that take a value, where the
|
|---|
| 1427 | # value is right up against the option
|
|---|
| 1428 | for opt in valopts:
|
|---|
| 1429 | if len(opt) == 2 and a.startswith(opt):
|
|---|
| 1430 | out.append(a)
|
|---|
| 1431 |
|
|---|
| 1432 | return out
|
|---|
| 1433 |
|
|---|