1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
49 """ SIGQUIT handler for the yum cli. """
50 print >> sys.stderr, "Quit signal sent - exiting immediately"
51 sys.exit(1)
52
54
55 """
56 Command line interface related Exception.
57 """
58
62
64 """This is the base class for yum cli.
65 Inherits from yum.YumBase and output.YumOutput """
66
103
109
134
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
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
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
161 opts = self.optparser.firstParse(args)
162
163
164 if opts.version:
165 print yum.__version__
166 opts.quiet = True
167 opts.verbose = False
168
169
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
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
201 self.optparser.set_usage(self._makeUsage())
202
203 self.plugins.run('args', args=args)
204
205
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):
215 return time.strftime("%Y-%m-%d", time.gmtime(x))
216 for pkg in sorted(self.rpmdb.returnPackages(patterns=yum_progs)):
217
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
241 self.args = args
242
243 self.cmdstring = 'yum '
244 for arg in self.args:
245 self.cmdstring += '%s ' % arg
246
247 try:
248 self.parseCommands()
249
250 except CliError:
251 sys.exit(1)
252
253
254 time.sleep(sleeptime)
255
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]
275 self.extcmds = self.cmds[1:]
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
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
301 """ parse the error string for 'interesting' errors which can
302 be grouped, such as disk space issues """
303 summary = ''
304
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
319
320
321 summary = _('Error Summary\n-------------\n') + summary
322
323 return summary
324
325
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
338
339
340
341
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
359 """takes care of package downloading, checking, user confirmation and actually
360 RUNNING the transaction"""
361
362
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
368
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
374
375 self.logger.warn(lsts)
376
377
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
391
392
393 self.ts.close()
394
395
396
397 if stuff_to_download:
398 self.reportDownloadSize(downloadpkgs, install_only)
399
400
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
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
459 dscb = self.dsCallback
460 self.dsCallback = None
461 self.populateTs(keepold=0)
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
479 signal.signal(signal.SIGQUIT, signal.SIG_DFL)
480
481 ts_st = time.time()
482 self.initActionTs()
483 self.populateTs(keepold=0)
484 self.ts.check()
485 self.ts.order()
486
487
488 self.dsCallback = dscb
489
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
500 self.verbose_logger.log(yum.logginglevels.INFO_1,
501 self.postTransactionOutput())
502
503
504 signal.signal(signal.SIGQUIT, sigquit)
505
506 return resultobject.return_code
507
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
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
529
530 self.getKeyForPackage(po, lambda x, y, z: self.userconfirm())
531
532 else:
533
534 raise yum.Errors.YumBaseError, errmsg
535
536 return 0
537
547
549 """ If the update/remove argument doesn't match with case, or due
550 to not being installed, tell the user. """
551
552
553 matches = self.doPackageLists(patterns=[arg], ignore_case=False)
554 if (matches.installed or (not matches.available and
555 self.returnInstalledPackagesByDep(arg))):
556 return
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
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
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
589
590
591
592
593
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
602
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
616 """take user commands and populate transaction wrapper with
617 packages to be updated"""
618
619
620
621
622
623 oldcount = len(self.tsInfo)
624 if len(userlist) == 0:
625 self.update()
626
627 else:
628
629
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
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
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
681
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
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
706
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
730 """handles installs/updates of rpms provided on the filesystem in a
731 local dir (ie: not from a repo)"""
732
733
734
735
736
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
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
797 """cli wrapper method for module search function, searches simple
798 text tags in a package object"""
799
800
801
802
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
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
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
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
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
890
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
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
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
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
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
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
1041
1042 if self.conf.assumeyes:
1043 return False
1044 if self.conf.alwaysprompt:
1045 return True
1046
1047
1048
1049
1050
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
1058 return False
1059
1061 ''' Print out command line usage '''
1062 sys.stdout.write(self.optparser.format_help())
1063
1065 ''' Print out the shell usage '''
1066 sys.stdout.write(self.optparser.get_usage())
1067
1069
1070 """check if the package is reasonably installable, true/false"""
1071
1072 exactarchlist = self.conf.exactarchlist
1073
1074
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
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
1093 if len(comparable) > 0:
1094 for instpo in comparable:
1095 if pkg.verGT(instpo):
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):
1103 return False
1104
1105 elif pkg.verLT(instpo):
1106
1107
1108
1109
1110
1111 if ematch and self.allowedMultipleInstalls(pkg):
1112 return True
1113
1114 else:
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
1121 '''Subclass that makes some minor tweaks to make OptionParser do things the
1122 "yum way".
1123 '''
1124
1126
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
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
1147
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
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
1171
1172 if not args:
1173 (opts, cmds) = self.parse_args()
1174 else:
1175 (opts, cmds) = self.parse_args(args=args)
1176
1177
1178 self.base.plugins.setCmdLine(opts, cmds)
1179
1180 try:
1181
1182
1183
1184
1185 if opts.assumeyes:
1186 self.base.conf.assumeyes =1
1187
1188
1189
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
1243 self.base.setupProgressCallbacks()
1244
1245 self.base.setupKeyImportCallbacks()
1246
1247
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
1260 if len(opts.repos) > 0:
1261 self.base._getRepos(doSetup=True)
1262
1263
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
1279
1280
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
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 = '/'
1291 return root
1292
1294 self.base.usage()
1295 self.exit()
1296
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
1314
1315
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='/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
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)
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
1427
1428 for opt in valopts:
1429 if len(opt) == 2 and a.startswith(opt):
1430 out.append(a)
1431
1432 return out
1433