Module yumcommands
[hide private]
[frames] | no frames]

Source Code for Module yumcommands

   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 2006 Duke University  
  16  # Written by Seth Vidal 
  17   
  18  """ 
  19  Classes for subcommands of the yum command line interface. 
  20  """ 
  21   
  22  import os 
  23  import cli 
  24  from yum import logginglevels 
  25  from yum import _ 
  26  from yum import misc 
  27  import yum.Errors 
  28  import operator 
  29  import locale 
  30  import fnmatch 
  31  import time 
  32  from yum.i18n import utf8_width, utf8_width_fill, to_unicode 
  33   
  34  import yum.config 
35 36 -def checkRootUID(base):
37 """ 38 Verify that the program is being run by the root user. 39 40 @param base: a YumBase object. 41 """ 42 if base.conf.uid != 0: 43 base.logger.critical(_('You need to be root to perform this command.')) 44 raise cli.CliError
45
46 -def checkGPGKey(base):
47 if not base.gpgKeyCheck(): 48 for repo in base.repos.listEnabled(): 49 if (repo.gpgcheck or repo.repo_gpgcheck) and repo.gpgkey == '': 50 msg = _(""" 51 You have enabled checking of packages via GPG keys. This is a good thing. 52 However, you do not have any GPG public keys installed. You need to download 53 the keys for packages you wish to install and install them. 54 You can do that by running the command: 55 rpm --import public.gpg.key 56 57 58 Alternatively you can specify the url to the key you would like to use 59 for a repository in the 'gpgkey' option in a repository section and yum 60 will install it for you. 61 62 For more information contact your distribution or package provider. 63 """) 64 base.logger.critical(msg) 65 raise cli.CliError
66
67 -def checkPackageArg(base, basecmd, extcmds):
68 if len(extcmds) == 0: 69 base.logger.critical( 70 _('Error: Need to pass a list of pkgs to %s') % basecmd) 71 base.usage() 72 raise cli.CliError
73
74 -def checkItemArg(base, basecmd, extcmds):
75 if len(extcmds) == 0: 76 base.logger.critical(_('Error: Need an item to match')) 77 base.usage() 78 raise cli.CliError
79
80 -def checkGroupArg(base, basecmd, extcmds):
81 if len(extcmds) == 0: 82 base.logger.critical(_('Error: Need a group or list of groups')) 83 base.usage() 84 raise cli.CliError
85
86 -def checkCleanArg(base, basecmd, extcmds):
87 VALID_ARGS = ('headers', 'packages', 'metadata', 'dbcache', 'plugins', 88 'expire-cache', 'rpmdb', 'all') 89 90 if len(extcmds) == 0: 91 base.logger.critical(_('Error: clean requires an option: %s') % ( 92 ", ".join(VALID_ARGS))) 93 94 for cmd in extcmds: 95 if cmd not in VALID_ARGS: 96 base.logger.critical(_('Error: invalid clean argument: %r') % cmd) 97 base.usage() 98 raise cli.CliError
99
100 -def checkShellArg(base, basecmd, extcmds):
101 """ 102 Verify that the arguments given to 'yum shell' are valid. 103 104 yum shell can be given either no args, or exactly one argument, 105 which is the name of a file. If these are not met, 106 raise cli.CliError. 107 """ 108 if len(extcmds) == 0: 109 base.verbose_logger.debug(_("No argument to shell")) 110 elif len(extcmds) == 1: 111 base.verbose_logger.debug(_("Filename passed to shell: %s"), 112 extcmds[0]) 113 if not os.path.isfile(extcmds[0]): 114 base.logger.critical( 115 _("File %s given as argument to shell does not exist."), 116 extcmds[0]) 117 base.usage() 118 raise cli.CliError 119 else: 120 base.logger.critical( 121 _("Error: more than one file given as argument to shell.")) 122 base.usage() 123 raise cli.CliError
124
125 -class YumCommand:
126
127 - def __init__(self):
128 self.done_command_once = False
129
130 - def doneCommand(self, base, msg, *args):
131 if not self.done_command_once: 132 base.verbose_logger.log(logginglevels.INFO_2, msg, *args) 133 self.done_command_once = True
134
135 - def getNames(self):
136 return []
137
138 - def getUsage(self):
139 """ 140 @return: A usage string for the command, including arguments. 141 """ 142 raise NotImplementedError
143
144 - def getSummary(self):
145 """ 146 @return: A one line summary of what the command does. 147 """ 148 raise NotImplementedError
149
150 - def doCheck(self, base, basecmd, extcmds):
151 pass
152
153 - def doCommand(self, base, basecmd, extcmds):
154 """ 155 @return: (exit_code, [ errors ]) where exit_code is: 156 0 = we're done, exit 157 1 = we've errored, exit with error string 158 2 = we've got work yet to do, onto the next stage 159 """ 160 return 0, [_('Nothing to do')]
161
162 - def needTs(self, base, basecmd, extcmds):
163 return True
164
165 -class InstallCommand(YumCommand):
166 - def getNames(self):
167 return ['install']
168
169 - def getUsage(self):
170 return _("PACKAGE...")
171
172 - def getSummary(self):
173 return _("Install a package or packages on your system")
174
175 - def doCheck(self, base, basecmd, extcmds):
176 checkRootUID(base) 177 checkGPGKey(base) 178 checkPackageArg(base, basecmd, extcmds)
179
180 - def doCommand(self, base, basecmd, extcmds):
181 self.doneCommand(base, _("Setting up Install Process")) 182 try: 183 return base.installPkgs(extcmds) 184 except yum.Errors.YumBaseError, e: 185 return 1, [str(e)]
186
187 -class UpdateCommand(YumCommand):
188 - def getNames(self):
189 return ['update']
190
191 - def getUsage(self):
192 return _("[PACKAGE...]")
193
194 - def getSummary(self):
195 return _("Update a package or packages on your system")
196
197 - def doCheck(self, base, basecmd, extcmds):
198 checkRootUID(base) 199 checkGPGKey(base)
200
201 - def doCommand(self, base, basecmd, extcmds):
202 self.doneCommand(base, _("Setting up Update Process")) 203 try: 204 return base.updatePkgs(extcmds) 205 except yum.Errors.YumBaseError, e: 206 return 1, [str(e)]
207
208 -def _add_pkg_simple_list_lens(data, pkg, indent=''):
209 """ Get the length of each pkg's column. Add that to data. 210 This "knows" about simpleList and printVer. """ 211 na = len(pkg.name) + 1 + len(pkg.arch) + len(indent) 212 ver = len(pkg.version) + 1 + len(pkg.release) 213 rid = len(pkg.ui_from_repo) 214 if pkg.epoch != '0': 215 ver += len(pkg.epoch) + 1 216 for (d, v) in (('na', na), ('ver', ver), ('rid', rid)): 217 data[d].setdefault(v, 0) 218 data[d][v] += 1
219
220 -def _list_cmd_calc_columns(base, ypl):
221 """ Work out the dynamic size of the columns to pass to fmtColumns. """ 222 data = {'na' : {}, 'ver' : {}, 'rid' : {}} 223 for lst in (ypl.installed, ypl.available, ypl.extras, 224 ypl.updates, ypl.recent): 225 for pkg in lst: 226 _add_pkg_simple_list_lens(data, pkg) 227 if len(ypl.obsoletes) > 0: 228 for (npkg, opkg) in ypl.obsoletesTuples: 229 _add_pkg_simple_list_lens(data, npkg) 230 _add_pkg_simple_list_lens(data, opkg, indent=" " * 4) 231 232 data = [data['na'], data['ver'], data['rid']] 233 columns = base.calcColumns(data, remainder_column=1) 234 return (-columns[0], -columns[1], -columns[2])
235
236 -class InfoCommand(YumCommand):
237 - def getNames(self):
238 return ['info']
239
240 - def getUsage(self):
241 return "[PACKAGE|all|installed|updates|extras|obsoletes|recent]"
242
243 - def getSummary(self):
244 return _("Display details about a package or group of packages")
245
246 - def doCommand(self, base, basecmd, extcmds):
247 try: 248 highlight = base.term.MODE['bold'] 249 ypl = base.returnPkgLists(extcmds, installed_available=highlight) 250 except yum.Errors.YumBaseError, e: 251 return 1, [str(e)] 252 else: 253 update_pkgs = {} 254 inst_pkgs = {} 255 local_pkgs = {} 256 257 columns = None 258 if basecmd == 'list': 259 # Dynamically size the columns 260 columns = _list_cmd_calc_columns(base, ypl) 261 262 if highlight and ypl.installed: 263 # If we have installed and available lists, then do the 264 # highlighting for the installed packages so you can see what's 265 # available to update, an extra, or newer than what we have. 266 for pkg in (ypl.hidden_available + 267 ypl.reinstall_available + 268 ypl.old_available): 269 key = (pkg.name, pkg.arch) 270 if key not in update_pkgs or pkg.verGT(update_pkgs[key]): 271 update_pkgs[key] = pkg 272 273 if highlight and ypl.available: 274 # If we have installed and available lists, then do the 275 # highlighting for the available packages so you can see what's 276 # available to install vs. update vs. old. 277 for pkg in ypl.hidden_installed: 278 key = (pkg.name, pkg.arch) 279 if key not in inst_pkgs or pkg.verGT(inst_pkgs[key]): 280 inst_pkgs[key] = pkg 281 282 if highlight and ypl.updates: 283 # Do the local/remote split we get in "yum updates" 284 for po in sorted(ypl.updates): 285 if po.repo.id != 'installed' and po.verifyLocalPkg(): 286 local_pkgs[(po.name, po.arch)] = po 287 288 # Output the packages: 289 clio = base.conf.color_list_installed_older 290 clin = base.conf.color_list_installed_newer 291 clir = base.conf.color_list_installed_reinstall 292 clie = base.conf.color_list_installed_extra 293 rip = base.listPkgs(ypl.installed, _('Installed Packages'), basecmd, 294 highlight_na=update_pkgs, columns=columns, 295 highlight_modes={'>' : clio, '<' : clin, 296 '=' : clir, 'not in' : clie}) 297 clau = base.conf.color_list_available_upgrade 298 clad = base.conf.color_list_available_downgrade 299 clar = base.conf.color_list_available_reinstall 300 clai = base.conf.color_list_available_install 301 rap = base.listPkgs(ypl.available, _('Available Packages'), basecmd, 302 highlight_na=inst_pkgs, columns=columns, 303 highlight_modes={'<' : clau, '>' : clad, 304 '=' : clar, 'not in' : clai}) 305 rep = base.listPkgs(ypl.extras, _('Extra Packages'), basecmd, 306 columns=columns) 307 cul = base.conf.color_update_local 308 cur = base.conf.color_update_remote 309 rup = base.listPkgs(ypl.updates, _('Updated Packages'), basecmd, 310 highlight_na=local_pkgs, columns=columns, 311 highlight_modes={'=' : cul, 'not in' : cur}) 312 313 # XXX put this into the ListCommand at some point 314 if len(ypl.obsoletes) > 0 and basecmd == 'list': 315 # if we've looked up obsolete lists and it's a list request 316 rop = [0, ''] 317 print _('Obsoleting Packages') 318 # The tuple is (newPkg, oldPkg) ... so sort by new 319 for obtup in sorted(ypl.obsoletesTuples, 320 key=operator.itemgetter(0)): 321 base.updatesObsoletesList(obtup, 'obsoletes', 322 columns=columns) 323 else: 324 rop = base.listPkgs(ypl.obsoletes, _('Obsoleting Packages'), 325 basecmd, columns=columns) 326 rrap = base.listPkgs(ypl.recent, _('Recently Added Packages'), 327 basecmd, columns=columns) 328 # extcmds is pop(0)'d if they pass a "special" param like "updates" 329 # in returnPkgLists(). This allows us to always return "ok" for 330 # things like "yum list updates". 331 if len(extcmds) and \ 332 rrap[0] and rop[0] and rup[0] and rep[0] and rap[0] and rip[0]: 333 return 1, [_('No matching Packages to list')] 334 return 0, []
335
336 - def needTs(self, base, basecmd, extcmds):
337 if len(extcmds) and extcmds[0] == 'installed': 338 return False 339 340 return True
341
342 -class ListCommand(InfoCommand):
343 - def getNames(self):
344 return ['list']
345
346 - def getSummary(self):
347 return _("List a package or groups of packages")
348
349 350 -class EraseCommand(YumCommand):
351
352 - def getNames(self):
353 return ['erase', 'remove']
354
355 - def getUsage(self):
356 return "PACKAGE..."
357
358 - def getSummary(self):
359 return _("Remove a package or packages from your system")
360
361 - def doCheck(self, base, basecmd, extcmds):
362 checkRootUID(base) 363 checkPackageArg(base, basecmd, extcmds)
364
365 - def doCommand(self, base, basecmd, extcmds):
366 self.doneCommand(base, _("Setting up Remove Process")) 367 try: 368 return base.erasePkgs(extcmds) 369 except yum.Errors.YumBaseError, e: 370 return 1, [str(e)]
371
372 - def needTs(self, base, basecmd, extcmds):
373 return False
374
375 - def needTsRemove(self, base, basecmd, extcmds):
376 return True
377
378 -class GroupCommand(YumCommand):
379 - def doCommand(self, base, basecmd, extcmds):
380 self.doneCommand(base, _("Setting up Group Process")) 381 382 base.doRepoSetup(dosack=0) 383 try: 384 base.doGroupSetup() 385 except yum.Errors.GroupsError: 386 return 1, [_('No Groups on which to run command')] 387 except yum.Errors.YumBaseError, e: 388 return 1, [str(e)]
389
390 391 -class GroupListCommand(GroupCommand):
392 - def getNames(self):
393 return ['grouplist']
394
395 - def getUsage(self):
396 return ""
397
398 - def getSummary(self):
399 return _("List available package groups")
400
401 - def doCommand(self, base, basecmd, extcmds):
402 GroupCommand.doCommand(self, base, basecmd, extcmds) 403 return base.returnGroupLists(extcmds)
404
405 - def needTs(self, base, basecmd, extcmds):
406 return False
407
408 -class GroupInstallCommand(GroupCommand):
409 - def getNames(self):
410 return ['groupinstall', 'groupupdate']
411
412 - def getUsage(self):
413 return "GROUP..."
414
415 - def getSummary(self):
416 return _("Install the packages in a group on your system")
417
418 - def doCheck(self, base, basecmd, extcmds):
419 checkRootUID(base) 420 checkGPGKey(base) 421 checkGroupArg(base, basecmd, extcmds)
422
423 - def doCommand(self, base, basecmd, extcmds):
424 GroupCommand.doCommand(self, base, basecmd, extcmds) 425 try: 426 return base.installGroups(extcmds) 427 except yum.Errors.YumBaseError, e: 428 return 1, [str(e)]
429
430 -class GroupRemoveCommand(GroupCommand):
431 - def getNames(self):
432 return ['groupremove', 'grouperase']
433
434 - def getUsage(self):
435 return "GROUP..."
436
437 - def getSummary(self):
438 return _("Remove the packages in a group from your system")
439
440 - def doCheck(self, base, basecmd, extcmds):
441 checkRootUID(base) 442 checkGroupArg(base, basecmd, extcmds)
443
444 - def doCommand(self, base, basecmd, extcmds):
445 GroupCommand.doCommand(self, base, basecmd, extcmds) 446 try: 447 return base.removeGroups(extcmds) 448 except yum.Errors.YumBaseError, e: 449 return 1, [str(e)]
450
451 - def needTs(self, base, basecmd, extcmds):
452 return False
453
454 - def needTsRemove(self, base, basecmd, extcmds):
455 return True
456
457 -class GroupInfoCommand(GroupCommand):
458 - def getNames(self):
459 return ['groupinfo']
460
461 - def getUsage(self):
462 return "GROUP..."
463
464 - def getSummary(self):
465 return _("Display details about a package group")
466
467 - def doCheck(self, base, basecmd, extcmds):
468 checkGroupArg(base, basecmd, extcmds)
469
470 - def doCommand(self, base, basecmd, extcmds):
471 GroupCommand.doCommand(self, base, basecmd, extcmds) 472 try: 473 return base.returnGroupInfo(extcmds) 474 except yum.Errors.YumBaseError, e: 475 return 1, [str(e)]
476
477 - def needTs(self, base, basecmd, extcmds):
478 return False
479
480 -class MakeCacheCommand(YumCommand):
481
482 - def getNames(self):
483 return ['makecache']
484
485 - def getUsage(self):
486 return ""
487
488 - def getSummary(self):
489 return _("Generate the metadata cache")
490
491 - def doCheck(self, base, basecmd, extcmds):
492 pass
493
494 - def doCommand(self, base, basecmd, extcmds):
495 base.logger.debug(_("Making cache files for all metadata files.")) 496 base.logger.debug(_("This may take a while depending on the speed of this computer")) 497 try: 498 for repo in base.repos.findRepos('*'): 499 repo.metadata_expire = 0 500 repo.mdpolicy = "group:all" 501 base.doRepoSetup(dosack=0) 502 base.repos.doSetup() 503 for repo in base.repos.listEnabled(): 504 repo.repoXML 505 506 # These convert the downloaded data into usable data, 507 # we can't remove them until *LoadRepo() can do: 508 # 1. Download a .sqlite.bz2 and convert to .sqlite 509 # 2. Download a .xml.gz and convert to .xml.gz.sqlite 510 base.repos.populateSack(mdtype='metadata', cacheonly=1) 511 base.repos.populateSack(mdtype='filelists', cacheonly=1) 512 base.repos.populateSack(mdtype='otherdata', cacheonly=1) 513 514 515 except yum.Errors.YumBaseError, e: 516 return 1, [str(e)] 517 return 0, [_('Metadata Cache Created')]
518
519 - def needTs(self, base, basecmd, extcmds):
520 return False
521
522 -class CleanCommand(YumCommand):
523
524 - def getNames(self):
525 return ['clean']
526
527 - def getUsage(self):
528 return "[headers|packages|metadata|dbcache|plugins|expire-cache|all]"
529
530 - def getSummary(self):
531 return _("Remove cached data")
532
533 - def doCheck(self, base, basecmd, extcmds):
534 checkCleanArg(base, basecmd, extcmds)
535
536 - def doCommand(self, base, basecmd, extcmds):
537 base.conf.cache = 1 538 return base.cleanCli(extcmds)
539
540 - def needTs(self, base, basecmd, extcmds):
541 return False
542
543 -class ProvidesCommand(YumCommand):
544 - def getNames(self):
545 return ['provides', 'whatprovides']
546
547 - def getUsage(self):
548 return "SOME_STRING"
549
550 - def getSummary(self):
551 return _("Find what package provides the given value")
552
553 - def doCheck(self, base, basecmd, extcmds):
554 checkItemArg(base, basecmd, extcmds)
555
556 - def doCommand(self, base, basecmd, extcmds):
557 base.logger.debug("Searching Packages: ") 558 try: 559 return base.provides(extcmds) 560 except yum.Errors.YumBaseError, e: 561 return 1, [str(e)]
562
563 -class CheckUpdateCommand(YumCommand):
564 - def getNames(self):
565 return ['check-update']
566
567 - def getUsage(self):
568 return "[PACKAGE...]"
569
570 - def getSummary(self):
571 return _("Check for available package updates")
572
573 - def doCommand(self, base, basecmd, extcmds):
574 base.extcmds.insert(0, 'updates') 575 result = 0 576 try: 577 ypl = base.returnPkgLists(extcmds) 578 if (base.conf.obsoletes or 579 base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3)): 580 typl = base.returnPkgLists(['obsoletes']) 581 ypl.obsoletes = typl.obsoletes 582 ypl.obsoletesTuples = typl.obsoletesTuples 583 584 columns = _list_cmd_calc_columns(base, ypl) 585 if len(ypl.updates) > 0: 586 local_pkgs = {} 587 highlight = base.term.MODE['bold'] 588 if highlight: 589 # Do the local/remote split we get in "yum updates" 590 for po in sorted(ypl.updates): 591 if po.repo.id != 'installed' and po.verifyLocalPkg(): 592 local_pkgs[(po.name, po.arch)] = po 593 594 cul = base.conf.color_update_local 595 cur = base.conf.color_update_remote 596 base.listPkgs(ypl.updates, '', outputType='list', 597 highlight_na=local_pkgs, columns=columns, 598 highlight_modes={'=' : cul, 'not in' : cur}) 599 result = 100 600 if len(ypl.obsoletes) > 0: # This only happens in verbose mode 601 print _('Obsoleting Packages') 602 # The tuple is (newPkg, oldPkg) ... so sort by new 603 for obtup in sorted(ypl.obsoletesTuples, 604 key=operator.itemgetter(0)): 605 base.updatesObsoletesList(obtup, 'obsoletes', 606 columns=columns) 607 result = 100 608 except yum.Errors.YumBaseError, e: 609 return 1, [str(e)] 610 else: 611 return result, []
612
613 -class SearchCommand(YumCommand):
614 - def getNames(self):
615 return ['search']
616
617 - def getUsage(self):
618 return "SOME_STRING"
619
620 - def getSummary(self):
621 return _("Search package details for the given string")
622
623 - def doCheck(self, base, basecmd, extcmds):
624 checkItemArg(base, basecmd, extcmds)
625
626 - def doCommand(self, base, basecmd, extcmds):
627 base.logger.debug(_("Searching Packages: ")) 628 try: 629 return base.search(extcmds) 630 except yum.Errors.YumBaseError, e: 631 return 1, [str(e)]
632
633 - def needTs(self, base, basecmd, extcmds):
634 return False
635
636 -class UpgradeCommand(YumCommand):
637 - def getNames(self):
638 return ['upgrade']
639
640 - def getUsage(self):
641 return 'PACKAGE...'
642
643 - def getSummary(self):
644 return _("Update packages taking obsoletes into account")
645
646 - def doCheck(self, base, basecmd, extcmds):
647 checkRootUID(base) 648 checkGPGKey(base)
649
650 - def doCommand(self, base, basecmd, extcmds):
651 base.conf.obsoletes = 1 652 self.doneCommand(base, _("Setting up Upgrade Process")) 653 try: 654 return base.updatePkgs(extcmds) 655 except yum.Errors.YumBaseError, e: 656 return 1, [str(e)]
657
658 -class LocalInstallCommand(YumCommand):
659 - def getNames(self):
660 return ['localinstall', 'localupdate']
661
662 - def getUsage(self):
663 return "FILE"
664
665 - def getSummary(self):
666 return _("Install a local RPM")
667
668 - def doCheck(self, base, basecmd, extcmds):
669 checkRootUID(base) 670 checkGPGKey(base) 671 checkPackageArg(base, basecmd, extcmds)
672
673 - def doCommand(self, base, basecmd, extcmds):
674 self.doneCommand(base, _("Setting up Local Package Process")) 675 676 updateonly = basecmd == 'localupdate' 677 try: 678 return base.localInstall(filelist=extcmds, updateonly=updateonly) 679 except yum.Errors.YumBaseError, e: 680 return 1, [str(e)]
681
682 - def needTs(self, base, basecmd, extcmds):
683 return False
684
685 -class ResolveDepCommand(YumCommand):
686 - def getNames(self):
687 return ['resolvedep']
688
689 - def getUsage(self):
690 return "DEPENDENCY"
691
692 - def getSummary(self):
693 return _("Determine which package provides the given dependency")
694
695 - def doCommand(self, base, basecmd, extcmds):
696 base.logger.debug(_("Searching Packages for Dependency:")) 697 try: 698 return base.resolveDepCli(extcmds) 699 except yum.Errors.YumBaseError, e: 700 return 1, [str(e)]
701
702 -class ShellCommand(YumCommand):
703 - def getNames(self):
704 return ['shell']
705
706 - def getUsage(self):
707 return "[FILENAME]"
708
709 - def getSummary(self):
710 return _("Run an interactive yum shell")
711
712 - def doCheck(self, base, basecmd, extcmds):
713 checkShellArg(base, basecmd, extcmds)
714
715 - def doCommand(self, base, basecmd, extcmds):
716 self.doneCommand(base, _('Setting up Yum Shell')) 717 try: 718 return base.doShell() 719 except yum.Errors.YumBaseError, e: 720 return 1, [str(e)]
721
722 - def needTs(self, base, basecmd, extcmds):
723 return False
724
725 726 -class DepListCommand(YumCommand):
727 - def getNames(self):
728 return ['deplist']
729
730 - def getUsage(self):
731 return 'PACKAGE...'
732
733 - def getSummary(self):
734 return _("List a package's dependencies")
735
736 - def doCheck(self, base, basecmd, extcmds):
737 checkPackageArg(base, basecmd, extcmds)
738
739 - def doCommand(self, base, basecmd, extcmds):
740 self.doneCommand(base, _("Finding dependencies: ")) 741 try: 742 return base.deplist(extcmds) 743 except yum.Errors.YumBaseError, e: 744 return 1, [str(e)]
745
746 747 -class RepoListCommand(YumCommand):
748
749 - def getNames(self):
750 return ('repolist',)
751
752 - def getUsage(self):
753 return '[all|enabled|disabled]'
754
755 - def getSummary(self):
756 return _('Display the configured software repositories')
757
758 - def doCommand(self, base, basecmd, extcmds):
759 def _repo_size(repo): 760 ret = 0 761 for pkg in repo.sack.returnPackages(): 762 ret += pkg.packagesize 763 return base.format_number(ret)
764 765 def _repo_match(repo, patterns): 766 rid = repo.id.lower() 767 rnm = repo.name.lower() 768 for pat in patterns: 769 if fnmatch.fnmatch(rid, pat): 770 return True 771 if fnmatch.fnmatch(rnm, pat): 772 return True 773 return False
774 775 def _num2ui_num(num): 776 return to_unicode(locale.format("%d", num, True)) 777 778 if len(extcmds) >= 1 and extcmds[0] in ('all', 'disabled', 'enabled'): 779 arg = extcmds[0] 780 extcmds = extcmds[1:] 781 else: 782 arg = 'enabled' 783 extcmds = map(lambda x: x.lower(), extcmds) 784 785 verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3) 786 if arg != 'disabled' or extcmds: 787 try: 788 # Setup so len(repo.sack) is correct 789 base.repos.populateSack() 790 base.pkgSack # Need to setup the pkgSack, so excludes work 791 except yum.Errors.RepoError: 792 if verbose: 793 raise 794 795 repos = base.repos.repos.values() 796 repos.sort() 797 enabled_repos = base.repos.listEnabled() 798 on_ehibeg = base.term.FG_COLOR['green'] + base.term.MODE['bold'] 799 on_dhibeg = base.term.FG_COLOR['red'] 800 on_hiend = base.term.MODE['normal'] 801 tot_num = 0 802 cols = [] 803 for repo in repos: 804 if len(extcmds) and not _repo_match(repo, extcmds): 805 continue 806 (ehibeg, dhibeg, hiend) = '', '', '' 807 ui_enabled = '' 808 ui_endis_wid = 0 809 ui_num = "" 810 ui_excludes_num = '' 811 force_show = False 812 if arg == 'all' or repo.id in extcmds or repo.name in extcmds: 813 force_show = True 814 (ehibeg, dhibeg, hiend) = (on_ehibeg, on_dhibeg, on_hiend) 815 if repo in enabled_repos: 816 enabled = True 817 if arg == 'enabled': 818 force_show = False 819 elif arg == 'disabled' and not force_show: 820 continue 821 if force_show or verbose: 822 ui_enabled = ehibeg + _('enabled') + hiend 823 ui_endis_wid = utf8_width(_('enabled')) 824 if not verbose: 825 ui_enabled += ": " 826 ui_endis_wid += 2 827 if verbose: 828 ui_size = _repo_size(repo) 829 # We don't show status for list disabled 830 if arg != 'disabled' or verbose: 831 if verbose or base.conf.exclude or repo.exclude: 832 num = len(repo.sack.simplePkgList()) 833 else: 834 num = len(repo.sack) 835 ui_num = _num2ui_num(num) 836 excludes = repo.sack._excludes 837 excludes = len([pid for r,pid in excludes if r == repo]) 838 if excludes: 839 ui_excludes_num = _num2ui_num(excludes) 840 if not verbose: 841 ui_num += "+%s" % ui_excludes_num 842 tot_num += num 843 else: 844 enabled = False 845 if arg == 'disabled': 846 force_show = False 847 elif arg == 'enabled' and not force_show: 848 continue 849 ui_enabled = dhibeg + _('disabled') + hiend 850 ui_endis_wid = utf8_width(_('disabled')) 851 852 if True: # Here to make patch smaller, TODO: rm 853 if not verbose: 854 rid = str(repo) 855 if enabled and repo.metalink: 856 mdts = repo.metalink_data.repomd.timestamp 857 if mdts > repo.repoXML.timestamp: 858 rid = '*' + rid 859 cols.append((rid, repo.name, 860 (ui_enabled, ui_endis_wid), ui_num)) 861 else: 862 if enabled: 863 md = repo.repoXML 864 else: 865 md = None 866 out = [base.fmtKeyValFill(_("Repo-id : "), repo), 867 base.fmtKeyValFill(_("Repo-name : "), repo.name)] 868 869 if force_show or extcmds: 870 out += [base.fmtKeyValFill(_("Repo-status : "), 871 ui_enabled)] 872 if md and md.revision is not None: 873 out += [base.fmtKeyValFill(_("Repo-revision: "), 874 md.revision)] 875 if md and md.tags['content']: 876 tags = md.tags['content'] 877 out += [base.fmtKeyValFill(_("Repo-tags : "), 878 ", ".join(sorted(tags)))] 879 880 if md and md.tags['distro']: 881 for distro in sorted(md.tags['distro']): 882 tags = md.tags['distro'][distro] 883 out += [base.fmtKeyValFill(_("Repo-distro-tags: "), 884 "[%s]: %s" % (distro, 885 ", ".join(sorted(tags))))] 886 887 if md: 888 out += [base.fmtKeyValFill(_("Repo-updated : "), 889 time.ctime(md.timestamp)), 890 base.fmtKeyValFill(_("Repo-pkgs : "),ui_num), 891 base.fmtKeyValFill(_("Repo-size : "),ui_size)] 892 893 if hasattr(repo, '_orig_baseurl'): 894 baseurls = repo._orig_baseurl 895 else: 896 baseurls = repo.baseurl 897 if baseurls: 898 out += [base.fmtKeyValFill(_("Repo-baseurl : "), 899 ", ".join(baseurls))] 900 901 if enabled: 902 # This needs to be here due to the mirrorlists are 903 # metalinks hack. 904 repo.urls 905 if repo.metalink: 906 out += [base.fmtKeyValFill(_("Repo-metalink: "), 907 repo.metalink)] 908 if enabled: 909 ts = repo.metalink_data.repomd.timestamp 910 out += [base.fmtKeyValFill(_(" Updated : "), 911 time.ctime(ts))] 912 elif repo.mirrorlist: 913 out += [base.fmtKeyValFill(_("Repo-mirrors : "), 914 repo.mirrorlist)] 915 916 if not os.path.exists(repo.metadata_cookie): 917 last = _("Unknown") 918 else: 919 last = os.stat(repo.metadata_cookie).st_mtime 920 last = time.ctime(last) 921 922 if repo.metadata_expire <= -1: 923 num = _("Never (last: %s)") % last 924 elif not repo.metadata_expire: 925 num = _("Instant (last: %s)") % last 926 else: 927 num = _num2ui_num(repo.metadata_expire) 928 num = _("%s second(s) (last: %s)") % (num, last) 929 930 out += [base.fmtKeyValFill(_("Repo-expire : "), num)] 931 932 if repo.exclude: 933 out += [base.fmtKeyValFill(_("Repo-exclude : "), 934 ", ".join(repo.exclude))] 935 936 if repo.includepkgs: 937 out += [base.fmtKeyValFill(_("Repo-include : "), 938 ", ".join(repo.includepkgs))] 939 940 if ui_excludes_num: 941 out += [base.fmtKeyValFill(_("Repo-excluded: "), 942 ui_excludes_num)] 943 944 base.verbose_logger.log(logginglevels.DEBUG_3, 945 "%s\n", 946 "\n".join(map(misc.to_unicode, out))) 947 948 if not verbose and cols: 949 # Work out the first (id) and last (enabled/disalbed/count), 950 # then chop the middle (name)... 951 id_len = utf8_width(_('repo id')) 952 nm_len = 0 953 st_len = 0 954 ui_len = 0 955 956 for (rid, rname, (ui_enabled, ui_endis_wid), ui_num) in cols: 957 if id_len < utf8_width(rid): 958 id_len = utf8_width(rid) 959 if nm_len < utf8_width(rname): 960 nm_len = utf8_width(rname) 961 if st_len < (ui_endis_wid + len(ui_num)): 962 st_len = (ui_endis_wid + len(ui_num)) 963 # Need this as well as above for: utf8_width_fill() 964 if ui_len < len(ui_num): 965 ui_len = len(ui_num) 966 if arg == 'disabled': # Don't output a status column. 967 left = base.term.columns - (id_len + 1) 968 elif utf8_width(_('status')) > st_len: 969 left = base.term.columns - (id_len + utf8_width(_('status')) +2) 970 else: 971 left = base.term.columns - (id_len + st_len + 2) 972 973 if left < nm_len: # Name gets chopped 974 nm_len = left 975 else: # Share the extra... 976 left -= nm_len 977 id_len += left / 2 978 nm_len += left - (left / 2) 979 980 txt_rid = utf8_width_fill(_('repo id'), id_len) 981 txt_rnam = utf8_width_fill(_('repo name'), nm_len, nm_len) 982 if arg == 'disabled': # Don't output a status column. 983 base.verbose_logger.log(logginglevels.INFO_2,"%s %s", 984 txt_rid, txt_rnam) 985 else: 986 base.verbose_logger.log(logginglevels.INFO_2,"%s %s %s", 987 txt_rid, txt_rnam, _('status')) 988 for (rid, rname, (ui_enabled, ui_endis_wid), ui_num) in cols: 989 if arg == 'disabled': # Don't output a status column. 990 base.verbose_logger.log(logginglevels.INFO_2, "%s %s", 991 utf8_width_fill(rid, id_len), 992 utf8_width_fill(rname, nm_len, 993 nm_len)) 994 continue 995 996 if ui_num: 997 ui_num = utf8_width_fill(ui_num, ui_len, left=False) 998 base.verbose_logger.log(logginglevels.INFO_2, "%s %s %s%s", 999 utf8_width_fill(rid, id_len), 1000 utf8_width_fill(rname, nm_len, nm_len), 1001 ui_enabled, ui_num) 1002 1003 return 0, ['repolist: ' +to_unicode(locale.format("%d", tot_num, True))] 1004
1005 - def needTs(self, base, basecmd, extcmds):
1006 return False
1007
1008 1009 -class HelpCommand(YumCommand):
1010
1011 - def getNames(self):
1012 return ['help']
1013
1014 - def getUsage(self):
1015 return "COMMAND"
1016
1017 - def getSummary(self):
1018 return _("Display a helpful usage message")
1019
1020 - def doCheck(self, base, basecmd, extcmds):
1021 if len(extcmds) == 0: 1022 base.usage() 1023 raise cli.CliError 1024 elif len(extcmds) > 1 or extcmds[0] not in base.yum_cli_commands: 1025 base.usage() 1026 raise cli.CliError
1027 1028 @staticmethod
1029 - def _makeOutput(command):
1030 canonical_name = command.getNames()[0] 1031 1032 # Check for the methods in case we have plugins that don't 1033 # implement these. 1034 # XXX Remove this once usage/summary are common enough 1035 try: 1036 usage = command.getUsage() 1037 except (AttributeError, NotImplementedError): 1038 usage = None 1039 try: 1040 summary = command.getSummary() 1041 except (AttributeError, NotImplementedError): 1042 summary = None 1043 1044 # XXX need detailed help here, too 1045 help_output = "" 1046 if usage is not None: 1047 help_output += "%s %s" % (canonical_name, usage) 1048 if summary is not None: 1049 help_output += "\n\n%s" % summary 1050 1051 if usage is None and summary is None: 1052 help_output = _("No help available for %s") % canonical_name 1053 1054 command_names = command.getNames() 1055 if len(command_names) > 1: 1056 if len(command_names) > 2: 1057 help_output += _("\n\naliases: ") 1058 else: 1059 help_output += _("\n\nalias: ") 1060 help_output += ', '.join(command.getNames()[1:]) 1061 1062 return help_output
1063
1064 - def doCommand(self, base, basecmd, extcmds):
1065 if extcmds[0] in base.yum_cli_commands: 1066 command = base.yum_cli_commands[extcmds[0]] 1067 base.verbose_logger.log(logginglevels.INFO_2, 1068 self._makeOutput(command)) 1069 return 0, []
1070
1071 - def needTs(self, base, basecmd, extcmds):
1072 return False
1073
1074 -class ReInstallCommand(YumCommand):
1075 - def getNames(self):
1076 return ['reinstall']
1077
1078 - def getUsage(self):
1079 return "PACKAGE..."
1080
1081 - def doCheck(self, base, basecmd, extcmds):
1082 checkRootUID(base) 1083 checkGPGKey(base) 1084 checkPackageArg(base, basecmd, extcmds)
1085
1086 - def doCommand(self, base, basecmd, extcmds):
1087 self.doneCommand(base, _("Setting up Reinstall Process")) 1088 try: 1089 return base.reinstallPkgs(extcmds) 1090 1091 except yum.Errors.YumBaseError, e: 1092 return 1, [to_unicode(e)]
1093
1094 - def getSummary(self):
1095 return _("reinstall a package")
1096
1097 - def needTs(self, base, basecmd, extcmds):
1098 return False
1099
1100 -class DowngradeCommand(YumCommand):
1101 - def getNames(self):
1102 return ['downgrade']
1103
1104 - def getUsage(self):
1105 return "PACKAGE..."
1106
1107 - def doCheck(self, base, basecmd, extcmds):
1108 checkRootUID(base) 1109 checkGPGKey(base) 1110 checkPackageArg(base, basecmd, extcmds)
1111
1112 - def doCommand(self, base, basecmd, extcmds):
1113 self.doneCommand(base, _("Setting up Downgrade Process")) 1114 try: 1115 return base.downgradePkgs(extcmds) 1116 except yum.Errors.YumBaseError, e: 1117 return 1, [str(e)]
1118
1119 - def getSummary(self):
1120 return _("downgrade a package")
1121
1122 - def needTs(self, base, basecmd, extcmds):
1123 return False
1124
1125 1126 -class VersionCommand(YumCommand):
1127 - def getNames(self):
1128 return ['version']
1129
1130 - def getUsage(self):
1131 return "[all|installed|available]"
1132
1133 - def getSummary(self):
1134 return _("Display a version for the machine and/or available repos.")
1135
1136 - def doCommand(self, base, basecmd, extcmds):
1137 vcmd = 'installed' 1138 if extcmds: 1139 vcmd = extcmds[0] 1140 1141 def _append_repos(cols, repo_data): 1142 for repoid in sorted(repo_data): 1143 cur = repo_data[repoid] 1144 ncols = [] 1145 last_rev = None 1146 for rev in sorted(cur): 1147 if rev is None: 1148 continue 1149 last_rev = cur[rev] 1150 ncols.append((" %s/%s" % (repoid, rev), str(cur[rev]))) 1151 if None in cur and (not last_rev or cur[None] != last_rev): 1152 cols.append((" %s" % repoid, str(cur[None]))) 1153 cols.extend(ncols)
1154 1155 verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3) 1156 groups = {} 1157 if vcmd in ('nogroups', 'nogroups-installed', 'nogroups-available', 1158 'nogroups-all'): 1159 gconf = [] 1160 if vcmd == 'nogroups': 1161 vcmd = 'installed' 1162 else: 1163 vcmd = vcmd[len('nogroups-'):] 1164 else: 1165 gconf = yum.config.readVersionGroupsConfig() 1166 1167 for group in gconf: 1168 groups[group] = set(gconf[group].pkglist) 1169 if gconf[group].run_with_packages: 1170 groups[group].update(base.run_with_package_names) 1171 1172 if vcmd == 'grouplist': 1173 print _(" Yum version groups:") 1174 for group in sorted(groups): 1175 print " ", group 1176 1177 return 0, ['version grouplist'] 1178 1179 if vcmd == 'groupinfo': 1180 for group in groups: 1181 if group not in extcmds[1:]: 1182 continue 1183 print _(" Group :"), group 1184 print _(" Packages:") 1185 if not verbose: 1186 for pkgname in sorted(groups[group]): 1187 print " ", pkgname 1188 else: 1189 data = {'envra' : {}, 'rid' : {}} 1190 pkg_names = groups[group] 1191 pkg_names2pkgs = base._group_names2aipkgs(pkg_names) 1192 base._calcDataPkgColumns(data, pkg_names, pkg_names2pkgs) 1193 data = [data['envra'], data['rid']] 1194 columns = base.calcColumns(data) 1195 columns = (-columns[0], -columns[1]) 1196 base._displayPkgsFromNames(pkg_names, True, pkg_names2pkgs, 1197 columns=columns) 1198 1199 return 0, ['version groupinfo'] 1200 1201 rel = base.conf.yumvar['releasever'] 1202 ba = base.conf.yumvar['basearch'] 1203 cols = [] 1204 if vcmd in ('installed', 'all', 'group-installed', 'group-all'): 1205 try: 1206 data = base.rpmdb.simpleVersion(not verbose, groups=groups) 1207 lastdbv = base.history.last() 1208 if lastdbv is not None: 1209 lastdbv = lastdbv.end_rpmdbversion 1210 if lastdbv is None or data[0] != lastdbv: 1211 base._rpmdb_warn_checks(warn=lastdbv is not None) 1212 if vcmd not in ('group-installed', 'group-all'): 1213 cols.append(("%s %s/%s" % (_("Installed:"), rel, ba), 1214 str(data[0]))) 1215 _append_repos(cols, data[1]) 1216 if groups: 1217 for grp in sorted(data[2]): 1218 cols.append(("%s %s" % (_("Group-Installed:"), grp), 1219 str(data[2][grp]))) 1220 _append_repos(cols, data[3][grp]) 1221 except yum.Errors.YumBaseError, e: 1222 return 1, [str(e)] 1223 if vcmd in ('available', 'all', 'group-available', 'group-all'): 1224 try: 1225 data = base.pkgSack.simpleVersion(not verbose, groups=groups) 1226 if vcmd not in ('group-available', 'group-all'): 1227 cols.append(("%s %s/%s" % (_("Available:"), rel, ba), 1228 str(data[0]))) 1229 if verbose: 1230 _append_repos(cols, data[1]) 1231 if groups: 1232 for grp in sorted(data[2]): 1233 cols.append(("%s %s" % (_("Group-Available:"), grp), 1234 str(data[2][grp]))) 1235 if verbose: 1236 _append_repos(cols, data[3][grp]) 1237 except yum.Errors.YumBaseError, e: 1238 return 1, [str(e)] 1239 1240 data = {'rid' : {}, 'ver' : {}} 1241 for (rid, ver) in cols: 1242 for (d, v) in (('rid', len(rid)), ('ver', len(ver))): 1243 data[d].setdefault(v, 0) 1244 data[d][v] += 1 1245 data = [data['rid'], data['ver']] 1246 columns = base.calcColumns(data) 1247 columns = (-columns[0], columns[1]) 1248 1249 for line in cols: 1250 print base.fmtColumns(zip(line, columns)) 1251 1252 return 0, ['version']
1253
1254 - def needTs(self, base, basecmd, extcmds):
1255 vcmd = 'installed' 1256 if extcmds: 1257 vcmd = extcmds[0] 1258 verbose = base.verbose_logger.isEnabledFor(logginglevels.DEBUG_3) 1259 if vcmd == 'groupinfo' and verbose: 1260 return True 1261 return vcmd in ('available', 'all', 'group-available', 'group-all')
1262
1263 1264 -class HistoryCommand(YumCommand):
1265 - def getNames(self):
1266 return ['history']
1267
1268 - def getUsage(self):
1269 return "[info|list|summary|redo|undo|new]"
1270
1271 - def getSummary(self):
1272 return _("Display, or use, the transaction history")
1273
1274 - def _hcmd_redo(self, base, extcmds):
1275 old = base._history_get_transaction(extcmds) 1276 if old is None: 1277 return 1, ['Failed history redo'] 1278 tm = time.ctime(old.beg_timestamp) 1279 print "Repeating transaction %u, from %s" % (old.tid, tm) 1280 base.historyInfoCmdPkgsAltered(old) 1281 if base.history_redo(old): 1282 return 2, ["Repeating transaction %u" % (old.tid,)]
1283
1284 - def _hcmd_undo(self, base, extcmds):
1285 old = base._history_get_transaction(extcmds) 1286 if old is None: 1287 return 1, ['Failed history undo'] 1288 tm = time.ctime(old.beg_timestamp) 1289 print "Undoing transaction %u, from %s" % (old.tid, tm) 1290 base.historyInfoCmdPkgsAltered(old) 1291 if base.history_undo(old): 1292 return 2, ["Undoing transaction %u" % (old.tid,)]
1293
1294 - def _hcmd_new(self, base, extcmds):
1296
1297 - def doCheck(self, base, basecmd, extcmds):
1298 cmds = ('list', 'info', 'summary', 'repeat', 'redo', 'undo', 'new') 1299 if extcmds and extcmds[0] not in cmds: 1300 base.logger.critical(_('Invalid history sub-command, use: %s.'), 1301 ", ".join(cmds)) 1302 raise cli.CliError 1303 if extcmds and extcmds[0] in ('repeat', 'redo', 'undo', 'new'): 1304 checkRootUID(base) 1305 checkGPGKey(base)
1306
1307 - def doCommand(self, base, basecmd, extcmds):
1308 vcmd = 'list' 1309 if extcmds: 1310 vcmd = extcmds[0] 1311 1312 if False: pass 1313 elif vcmd == 'list': 1314 ret = base.historyListCmd(extcmds) 1315 elif vcmd == 'info': 1316 ret = base.historyInfoCmd(extcmds) 1317 elif vcmd == 'summary': 1318 ret = base.historySummaryCmd(extcmds) 1319 elif vcmd == 'undo': 1320 ret = self._hcmd_undo(base, extcmds) 1321 elif vcmd in ('redo', 'repeat'): 1322 ret = self._hcmd_redo(base, extcmds) 1323 elif vcmd == 'new': 1324 ret = self._hcmd_new(base, extcmds) 1325 1326 if ret is None: 1327 return 0, ['history %s' % (vcmd,)] 1328 return ret
1329
1330 - def needTs(self, base, basecmd, extcmds):
1331 vcmd = 'list' 1332 if extcmds: 1333 vcmd = extcmds[0] 1334 return vcmd in ('repeat', 'redo', 'undo')
1335
1336 1337 -class CheckRpmdbCommand(YumCommand):
1338 - def getNames(self):
1339 return ['check', 'check-rpmdb']
1340
1341 - def getUsage(self):
1342 return "[dependencies|duplicates|all]"
1343
1344 - def getSummary(self):
1345 return _("Check for problems in the rpmdb")
1346
1347 - def doCommand(self, base, basecmd, extcmds):
1348 chkcmd = 'all' 1349 if extcmds: 1350 chkcmd = extcmds[0] 1351 1352 def _out(x): 1353 print x
1354 1355 rc = 0 1356 if base._rpmdb_warn_checks(_out, False, chkcmd): 1357 rc = 1 1358 return rc, ['%s %s' % (basecmd, chkcmd)]
1359
1360 - def needTs(self, base, basecmd, extcmds):
1361 return False
1362