source: yum/vendor/yum-3.2.27/shell.py@ 2

Last change on this file since 2 was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 12.3 KB
Line 
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"""
17A shell implementation for the yum command line interface.
18"""
19
20import sys
21import cmd
22import shlex
23import logging
24
25from yum import Errors
26from yum.constants import *
27import yum.logginglevels as logginglevels
28
29
30class 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
354
Note: See TracBrowser for help on using the repository browser.