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

Source Code for Module shell

  1  # This program is free software; you can redistribute it and/or modify 
  2  # it under the terms of the GNU General Public License as published by 
  3  # the Free Software Foundation; either version 2 of the License, or 
  4  # (at your option) any later version. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU Library General Public License for more details. 
 10  # 
 11  # You should have received a copy of the GNU General Public License 
 12  # along with this program; if not, write to the Free Software 
 13  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 14  # Copyright 2005 Duke University 
 15   
 16  """ 
 17  A shell implementation for the yum command line interface. 
 18  """ 
 19   
 20  import sys 
 21  import cmd 
 22  import shlex 
 23  import logging 
 24   
 25  from yum import Errors 
 26  from yum.constants import * 
 27  import yum.logginglevels as logginglevels 
 28   
 29   
30 -class YumShell(cmd.Cmd):
31 32 """ 33 Interactive yum shell. 34 """ 35
36 - def __init__(self, base):
37 cmd.Cmd.__init__(self) 38 self.base = base 39 self.prompt = '> ' 40 self.result = 0 41 self.identchars += '-' 42 self.from_file = False # if we're running from a file, set this 43 self.resultmsgs = ['Leaving Shell'] 44 if (len(base.extcmds)) > 0: 45 self.file = base.extcmds[0] 46 self.shell_specific_commands = ['repo', 'repository', 'exit', 'quit', 47 'run', 'ts', 'transaction', 'config'] 48 49 self.commandlist = self.shell_specific_commands + self.base.yum_cli_commands.keys() 50 self.logger = logging.getLogger("yum.cli") 51 self.verbose_logger = logging.getLogger("yum.verbose.cli")
52 53
54 - def _shlex_split(self, input_string):
55 """split the input using shlex rules, and error or exit accordingly""" 56 57 inputs = [] 58 if input_string is None: # apparently shlex.split() doesn't like None as its input :) 59 return inputs 60 61 try: 62 inputs = shlex.split(input_string) 63 except ValueError, e: 64 self.logger.critical('Script Error: %s', e) 65 if self.from_file: 66 raise Errors.YumBaseError, "Fatal error in script, exiting" 67 68 return inputs
69
70 - def script(self):
71 try: 72 fd = open(self.file, 'r') 73 except IOError: 74 sys.exit("Error: Cannot open %s for reading" % self.file) 75 lines = fd.readlines() 76 fd.close() 77 self.from_file = True 78 for line in lines: 79 self.onecmd(line) 80 self.onecmd('EOF') 81 return True
82
83 - def default(self, line):
84 if len(line) > 0 and line.strip()[0] == '#': 85 pass 86 else: 87 (cmd, args, line) = self.parseline(line) 88 if cmd not in self.commandlist: 89 xargs = [cmd] 90 self.base.plugins.run('args', args=xargs) 91 if xargs[0] == cmd: 92 self.do_help('') 93 return False 94 if cmd == 'shell': 95 return 96 self.base.cmdstring = line 97 self.base.cmdstring = self.base.cmdstring.replace('\n', '') 98 self.base.cmds = self._shlex_split(self.base.cmdstring) 99 self.base.plugins.run('args', args=self.base.cmds) 100 101 try: 102 self.base.parseCommands() 103 except Errors.YumBaseError: 104 pass 105 else: 106 self.base.doCommands()
107
108 - def emptyline(self):
109 pass
110
111 - def completenames(self, text, line, begidx, endidx):
112 ret = cmd.Cmd.completenames(self, text, line, begidx, endidx) 113 for command in self.base.yum_cli_commands: 114 if command.startswith(text) and command != "shell": 115 ret.append(command) 116 return ret
117
118 - def do_help(self, arg):
119 msg = """ 120 Shell specific arguments: 121 config - set config options 122 repository (or repo) - enable/disable/list repositories 123 transaction (or ts) - list, reset or run the transaction set 124 run - run the transaction set 125 exit or quit - exit the shell 126 """ 127 128 if arg in ['transaction', 'ts']: 129 msg = """ 130 %s arg 131 list: lists the contents of the transaction 132 reset: reset (zero-out) the transaction 133 solve: run the dependency solver on the transaction 134 run: run the transaction 135 """ % arg 136 elif arg in ['repo', 'repository']: 137 msg = """ 138 %s arg [option] 139 list: lists repositories and their status. option = [all] name/id glob 140 enable: enable repositories. option = repository id 141 disable: disable repositories. option = repository id 142 """ % arg 143 144 elif arg == 'config': 145 msg = """ 146 %s arg [value] 147 args: debuglevel, errorlevel, obsoletes, gpgcheck, assumeyes, exclude 148 If no value is given it prints the current value. 149 If value is given it sets that value. 150 """ % arg 151 152 else: 153 self.base.shellUsage() 154 155 self.verbose_logger.info(msg)
156
157 - def do_EOF(self, line):
158 self.resultmsgs = ['Leaving Shell'] 159 return True
160
161 - def do_quit(self, line):
162 self.resultmsgs = ['Leaving Shell'] 163 return True
164
165 - def do_exit(self, line):
166 self.resultmsgs = ['Leaving Shell'] 167 return True
168
169 - def do_ts(self, line):
170 self.do_transaction(line)
171
172 - def do_transaction(self, line):
173 (cmd, args, line) = self.parseline(line) 174 if cmd in ['list', None]: 175 self.verbose_logger.log(logginglevels.INFO_2, 176 self.base.listTransaction()) 177 178 elif cmd == 'reset': 179 self.base.closeRpmDB() 180 181 elif cmd == 'solve': 182 try: 183 (code, msgs) = self.base.buildTransaction() 184 except Errors.YumBaseError, e: 185 self.logger.critical('Error building transaction: %s', e) 186 return False 187 188 if code == 1: 189 for msg in msgs: 190 self.logger.critical('Error: %s', msg) 191 else: 192 self.verbose_logger.log(logginglevels.INFO_2, 193 'Success resolving dependencies') 194 195 elif cmd == 'run': 196 return self.do_run('') 197 198 else: 199 self.do_help('transaction')
200
201 - def do_config(self, line):
202 (cmd, args, line) = self.parseline(line) 203 # logs 204 if cmd in ['debuglevel', 'errorlevel']: 205 opts = self._shlex_split(args) 206 if not opts: 207 self.verbose_logger.log(logginglevels.INFO_2, '%s: %s', cmd, 208 getattr(self.base.conf, cmd)) 209 else: 210 val = opts[0] 211 try: 212 val = int(val) 213 except ValueError: 214 self.logger.critical('Value %s for %s cannot be made to an int', val, cmd) 215 return 216 setattr(self.base.conf, cmd, val) 217 if cmd == 'debuglevel': 218 logginglevels.setDebugLevel(val) 219 elif cmd == 'errorlevel': 220 logginglevels.setErrorLevel(val) 221 # bools 222 elif cmd in ['gpgcheck', 'repo_gpgcheck', 'obsoletes', 'assumeyes']: 223 opts = self._shlex_split(args) 224 if not opts: 225 self.verbose_logger.log(logginglevels.INFO_2, '%s: %s', cmd, 226 getattr(self.base.conf, cmd)) 227 else: 228 value = opts[0] 229 if value.lower() not in BOOLEAN_STATES: 230 self.logger.critical('Value %s for %s is not a Boolean', value, cmd) 231 return False 232 value = BOOLEAN_STATES[value.lower()] 233 setattr(self.base.conf, cmd, value) 234 if cmd == 'obsoletes': 235 self.base.up = None 236 237 elif cmd in ['exclude']: 238 args = args.replace(',', ' ') 239 opts = self._shlex_split(args) 240 if not opts: 241 msg = '%s: ' % cmd 242 msg = msg + ' '.join(getattr(self.base.conf, cmd)) 243 self.verbose_logger.log(logginglevels.INFO_2, msg) 244 return False 245 else: 246 setattr(self.base.conf, cmd, opts) 247 if self.base.pkgSack: # kill the pkgSack 248 self.base.pkgSack = None 249 self.base.up = None # reset the updates 250 # reset the transaction set, we have to or we shall surely die! 251 self.base.closeRpmDB() 252 else: 253 self.do_help('config')
254
255 - def do_repository(self, line):
256 self.do_repo(line)
257
258 - def do_repo(self, line):
259 (cmd, args, line) = self.parseline(line) 260 if cmd in ['list', None]: 261 # Munge things to run the repolist command 262 cmds = self._shlex_split(args) 263 264 if not cmds: 265 cmds = ['enabled'] 266 cmds.insert(0, 'repolist') 267 self.base.cmds = cmds 268 269 try: 270 self.base.parseCommands() 271 except Errors.YumBaseError: 272 pass 273 else: 274 self.base.doCommands() 275 276 elif cmd == 'enable': 277 repos = self._shlex_split(args) 278 for repo in repos: 279 try: 280 # Setup the sacks/repos, we need this because we are about 281 # to setup the enabled one. And having some setup is bad. 282 self.base.pkgSack 283 changed = self.base.repos.enableRepo(repo) 284 except Errors.ConfigError, e: 285 self.logger.critical(e) 286 except Errors.RepoError, e: 287 self.logger.critical(e) 288 289 else: 290 for repo in changed: 291 try: 292 self.base.doRepoSetup(thisrepo=repo) 293 except Errors.RepoError, e: 294 self.logger.critical('Disabling Repository') 295 self.base.repos.disableRepo(repo) 296 return False 297 298 self.base.up = None 299 300 elif cmd == 'disable': 301 repos = self._shlex_split(args) 302 for repo in repos: 303 try: 304 offrepos = self.base.repos.disableRepo(repo) 305 except Errors.ConfigError, e: 306 self.logger.critical(e) 307 except Errors.RepoError, e: 308 self.logger.critical(e) 309 310 else: 311 # close the repos, too 312 for repoid in offrepos: 313 thisrepo = self.base.repos.repos[repoid] 314 thisrepo.close() # kill the pkgSack 315 # rebuild the indexes to be sure we cleaned up 316 self.base.pkgSack.buildIndexes() 317 318 else: 319 self.do_help('repo')
320
321 - def do_test(self, line):
322 (cmd, args, line) = self.parseline(line) 323 print cmd 324 print args 325 print line
326
327 - def do_run(self, line):
328 if len(self.base.tsInfo) > 0: 329 try: 330 (code, msgs) = self.base.buildTransaction() 331 if code == 1: 332 for msg in msgs: 333 self.logger.critical('Error: %s', msg) 334 return False 335 336 returnval = self.base.doTransaction() 337 except Errors.YumBaseError, e: 338 self.logger.critical('Error: %s', e) 339 except KeyboardInterrupt, e: 340 self.logger.critical('\n\nExiting on user cancel') 341 except IOError, e: 342 if e.errno == 32: 343 self.logger.critical('\n\nExiting on Broken Pipe') 344 else: 345 if returnval not in [0,1]: 346 self.verbose_logger.info('Transaction encountered a serious error.') 347 else: 348 if returnval == 1: 349 self.verbose_logger.info('There were non-fatal errors in the transaction') 350 self.verbose_logger.log(logginglevels.INFO_2, 351 'Finished Transaction') 352 self.base.closeRpmDB()
353