#! /usr/bin/python -tt
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2005 Duke University
"""
A shell implementation for the yum command line interface.
"""
import sys
import cmd
import shlex
import logging
from yum import Errors
from yum.constants import *
import yum.logginglevels as logginglevels
class YumShell(cmd.Cmd):
"""
Interactive yum shell.
"""
def __init__(self, base):
cmd.Cmd.__init__(self)
self.base = base
self.prompt = '> '
self.result = 0
self.identchars += '-'
self.from_file = False # if we're running from a file, set this
self.resultmsgs = ['Leaving Shell']
if (len(base.extcmds)) > 0:
self.file = base.extcmds[0]
self.shell_specific_commands = ['repo', 'repository', 'exit', 'quit',
'run', 'ts', 'transaction', 'config']
self.commandlist = self.shell_specific_commands + self.base.yum_cli_commands.keys()
self.logger = logging.getLogger("yum.cli")
self.verbose_logger = logging.getLogger("yum.verbose.cli")
# NOTE: This is shared with self.base ... so don't reassign.
self._shell_history_cmds = []
def _shell_history_add_cmds(self, cmds):
if not self.base.conf.history_record:
return
self._shell_history_cmds.append(cmds)
def _shlex_split(self, input_string):
"""split the input using shlex rules, and error or exit accordingly"""
inputs = []
if input_string is None: # apparently shlex.split() doesn't like None as its input :)
return inputs
try:
inputs = shlex.split(input_string)
except ValueError, e:
self.logger.critical('Script Error: %s', e)
if self.from_file:
raise Errors.YumBaseError, "Fatal error in script, exiting"
return inputs
def script(self):
try:
fd = open(self.file, 'r')
except IOError:
sys.exit("Error: Cannot open %s for reading" % self.file)
lines = fd.readlines()
fd.close()
self.from_file = True
for line in lines:
self.onecmd(line)
self.onecmd('EOF')
return True
def default(self, line):
if len(line) > 0 and line.strip()[0] == '#':
pass
else:
(cmd, args, line) = self.parseline(line)
if cmd not in self.commandlist:
xargs = [cmd]
self.base.plugins.run('args', args=xargs)
if xargs[0] == cmd:
self.do_help('')
return False
if cmd == 'shell':
return
self.base.cmdstring = line
self.base.cmdstring = self.base.cmdstring.replace('\n', '')
self.base.cmds = self._shlex_split(self.base.cmdstring)
self.base.plugins.run('args', args=self.base.cmds)
self._shell_history_add_cmds(self.base.cmds)
try:
self.base.parseCommands()
except Errors.YumBaseError:
pass
else:
self.base.doCommands()
def emptyline(self):
pass
def completenames(self, text, line, begidx, endidx):
ret = cmd.Cmd.completenames(self, text, line, begidx, endidx)
for command in self.base.yum_cli_commands:
if command.startswith(text) and command != "shell":
ret.append(command)
return ret
def do_help(self, arg):
msg = """
Shell specific arguments:
config - set config options
repository (or repo) - enable/disable/list repositories
transaction (or ts) - list, reset or run the transaction set
run - run the transaction set
exit or quit - exit the shell
"""
if arg in ['transaction', 'ts']:
msg = """
%s arg
list: lists the contents of the transaction
reset: reset (zero-out) the transaction
solve: run the dependency solver on the transaction
run: run the transaction
""" % arg
elif arg in ['repo', 'repository']:
msg = """
%s arg [option]
list: lists repositories and their status. option = [all] name/id glob
enable: enable repositories. option = repository id
disable: disable repositories. option = repository id
""" % arg
elif arg == 'config':
msg = """
%s arg [value]
args: debuglevel, errorlevel, obsoletes, gpgcheck, assumeyes, exclude
If no value is given it prints the current value.
If value is given it sets that value.
""" % arg
else:
self.base.shellUsage()
self.verbose_logger.info(msg)
def do_EOF(self, line):
self.resultmsgs = ['Leaving Shell']
return True
def do_quit(self, line):
self.resultmsgs = ['Leaving Shell']
return True
def do_exit(self, line):
self.resultmsgs = ['Leaving Shell']
return True
def do_ts(self, line):
self.do_transaction(line)
def do_transaction(self, line):
(cmd, args, line) = self.parseline(line)
if cmd in ['list', None]:
self.verbose_logger.log(logginglevels.INFO_2,
self.base.listTransaction())
elif cmd == 'reset':
self.base.closeRpmDB()
elif cmd == 'solve':
try:
(code, msgs) = self.base.buildTransaction()
except Errors.YumBaseError, e:
self.logger.critical('Error building transaction: %s', e)
return False
if code == 1:
for msg in msgs:
self.logger.critical('Error: %s', msg)
else:
self.verbose_logger.log(logginglevels.INFO_2,
'Success resolving dependencies')
elif cmd == 'run':
return self.do_run('')
else:
self.do_help('transaction')
def do_config(self, line):
(cmd, args, line) = self.parseline(line)
# logs
if cmd in ['debuglevel', 'errorlevel']:
opts = self._shlex_split(args)
if not opts:
self.verbose_logger.log(logginglevels.INFO_2, '%s: %s', cmd,
getattr(self.base.conf, cmd))
else:
val = opts[0]
try:
val = int(val)
except ValueError:
self.logger.critical('Value %s for %s cannot be made to an int', val, cmd)
return
setattr(self.base.conf, cmd, val)
if cmd == 'debuglevel':
logginglevels.setDebugLevel(val)
elif cmd == 'errorlevel':
logginglevels.setErrorLevel(val)
# bools
elif cmd in ['gpgcheck', 'repo_gpgcheck', 'obsoletes', 'assumeyes']:
opts = self._shlex_split(args)
if not opts:
self.verbose_logger.log(logginglevels.INFO_2, '%s: %s', cmd,
getattr(self.base.conf, cmd))
else:
value = opts[0]
if value.lower() not in BOOLEAN_STATES:
self.logger.critical('Value %s for %s is not a Boolean', value, cmd)
return False
value = BOOLEAN_STATES[value.lower()]
setattr(self.base.conf, cmd, value)
if cmd == 'obsoletes':
self.base.up = None
elif cmd in ['exclude']:
args = args.replace(',', ' ')
opts = self._shlex_split(args)
if not opts:
msg = '%s: ' % cmd
msg = msg + ' '.join(getattr(self.base.conf, cmd))
self.verbose_logger.log(logginglevels.INFO_2, msg)
return False
else:
setattr(self.base.conf, cmd, opts)
if self.base.pkgSack: # kill the pkgSack
self.base.pkgSack = None
self.base.up = None # reset the updates
# reset the transaction set, we have to or we shall surely die!
self.base.closeRpmDB()
else:
self.do_help('config')
def do_repository(self, line):
self.do_repo(line)
def do_repo(self, line):
(cmd, args, line) = self.parseline(line)
if cmd in ['list', None]:
# Munge things to run the repolist command
cmds = self._shlex_split(args)
if not cmds:
cmds = ['enabled']
cmds.insert(0, 'repolist')
self.base.cmds = cmds
self._shell_history_add_cmds(self.base.cmds)
try:
self.base.parseCommands()
except Errors.YumBaseError:
pass
else:
self.base.doCommands()
elif cmd == 'enable':
repos = self._shlex_split(args)
for repo in repos:
try:
# Setup the sacks/repos, we need this because we are about
# to setup the enabled one. And having some setup is bad.
self.base.pkgSack
changed = self.base.repos.enableRepo(repo)
except Errors.ConfigError, e:
self.logger.critical(e)
except Errors.RepoError, e:
self.logger.critical(e)
else:
for repo in changed:
try:
self.base.doRepoSetup(thisrepo=repo)
except Errors.RepoError, e:
self.logger.critical('Disabling Repository')
self.base.repos.disableRepo(repo)
return False
self.base.up = None
elif cmd == 'disable':
repos = self._shlex_split(args)
for repo in repos:
try:
offrepos = self.base.repos.disableRepo(repo)
except Errors.ConfigError, e:
self.logger.critical(e)
except Errors.RepoError, e:
self.logger.critical(e)
else:
# close the repos, too
for repoid in offrepos:
thisrepo = self.base.repos.repos[repoid]
thisrepo.close() # kill the pkgSack
# rebuild the indexes to be sure we cleaned up
self.base.pkgSack.buildIndexes()
else:
self.do_help('repo')
def do_test(self, line):
(cmd, args, line) = self.parseline(line)
print cmd
print args
print line
def do_run(self, line):
if len(self.base.tsInfo) > 0:
try:
(code, msgs) = self.base.buildTransaction()
if code == 1:
for msg in msgs:
self.logger.critical('Error: %s', msg)
return False
returnval = self.base.doTransaction()
except Errors.YumBaseError, e:
self.logger.critical('Error: %s', e)
except KeyboardInterrupt, e:
self.logger.critical('\n\nExiting on user cancel')
except IOError, e:
if e.errno == 32:
self.logger.critical('\n\nExiting on Broken Pipe')
else:
if returnval not in [0,1,-1]:
self.verbose_logger.info('Transaction encountered a serious error.')
else:
if returnval == 1:
self.verbose_logger.info('There were non-fatal errors in the transaction')
elif returnval == -1:
self.verbose_logger.info("Transaction didn't start")
self.verbose_logger.log(logginglevels.INFO_2,
'Finished Transaction')
self.base.closeRpmDB()
Copyright 2K16 - 2K18 Indonesian Hacker Rulez