1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
31
32 """
33 Interactive yum shell.
34 """
35
37 cmd.Cmd.__init__(self)
38 self.base = base
39 self.prompt = '> '
40 self.result = 0
41 self.identchars += '-'
42 self.from_file = False
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
55 """split the input using shlex rules, and error or exit accordingly"""
56
57 inputs = []
58 if input_string is None:
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
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
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
110
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
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
158 self.resultmsgs = ['Leaving Shell']
159 return True
160
162 self.resultmsgs = ['Leaving Shell']
163 return True
164
166 self.resultmsgs = ['Leaving Shell']
167 return True
168
171
200
202 (cmd, args, line) = self.parseline(line)
203
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
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:
248 self.base.pkgSack = None
249 self.base.up = None
250
251 self.base.closeRpmDB()
252 else:
253 self.do_help('config')
254
257
320
322 (cmd, args, line) = self.parseline(line)
323 print cmd
324 print args
325 print line
326
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