source: yum/trunk/yummain.py@ 1569

Last change on this file since 1569 was 516, checked in by Yuri Dario, 11 years ago

yum: update trunk to 3.4.3.

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1#!/usr/bin/python -t
2# This program is free software; you can redistribute it and/or modify
3# it under the terms of the GNU General Public License as published by
4# the Free Software Foundation; either version 2 of the License, or
5# (at your option) any later version.
6#
7# This program is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10# GNU Library General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with this program; if not, write to the Free Software
14# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15# Copyright 2005 Duke University
16
17"""
18Entrance point for the yum command line interface.
19"""
20
21import os
22import os.path
23import sys
24import logging
25import time
26import errno
27
28from yum import Errors
29from yum import plugins
30from yum import logginglevels
31from yum import _
32from yum.i18n import to_unicode, utf8_width
33import yum.misc
34import cli
35from utils import suppress_keyboard_interrupt_message, show_lock_owner, exception2msg
36
37def main(args):
38 """This does all the real work"""
39
40 yum.misc.setup_locale(override_time=True)
41
42 def exUserCancel():
43 logger.critical(_('\n\nExiting on user cancel'))
44 if unlock(): return 200
45 return 1
46
47 def exIOError(e):
48 if e.errno == 32:
49 logger.critical(_('\n\nExiting on Broken Pipe'))
50 else:
51 logger.critical(_('\n\n%s') % exception2msg(e))
52 if unlock(): return 200
53 return 1
54
55 def exPluginExit(e):
56 '''Called when a plugin raises PluginYumExit.
57
58 Log the plugin's exit message if one was supplied.
59 ''' # ' xemacs hack
60 exitmsg = exception2msg(e)
61 if exitmsg:
62 logger.warn('\n\n%s', exitmsg)
63 if unlock(): return 200
64 return 1
65
66 def exFatal(e):
67 logger.critical('\n\n%s', exception2msg(e.value))
68 if unlock(): return 200
69 return 1
70
71 def unlock():
72 try:
73 base.closeRpmDB()
74 base.doUnlock()
75 except Errors.LockError, e:
76 return 200
77 return 0
78
79 def rpmdb_warn_checks():
80 try:
81 probs = base._rpmdb_warn_checks(out=verbose_logger.info, warn=False)
82 except Errors.YumBaseError, e:
83 # This is mainly for PackageSackError from rpmdb.
84 verbose_logger.info(_(" Yum checks failed: %s"), exception2msg(e))
85 probs = []
86 if not probs:
87 verbose_logger.info(_(" You could try running: rpm -Va --nofiles --nodigest"))
88
89 logger = logging.getLogger("yum.main")
90 verbose_logger = logging.getLogger("yum.verbose.main")
91
92 # our core object for the cli
93 base = cli.YumBaseCli()
94
95 # do our cli parsing and config file setup
96 # also sanity check the things being passed on the cli
97 try:
98 base.getOptionsConfig(args)
99 except plugins.PluginYumExit, e:
100 return exPluginExit(e)
101 except Errors.YumBaseError, e:
102 return exFatal(e)
103
104 # Try to open the current directory to see if we have
105 # read and write access. If not, chdir to /
106 try:
107 f = open(".")
108 except IOError, e:
109 if e.errno == errno.EACCES:
110 logger.critical(_('No read/write access in current directory, moving to /'))
111 os.chdir("/")
112 else:
113 close(f)
114
115 lockerr = ""
116 while True:
117 try:
118 base.doLock()
119 except Errors.LockError, e:
120 if exception2msg(e) != lockerr:
121 lockerr = exception2msg(e)
122 logger.critical(lockerr)
123 if (e.errno not in (errno.EPERM, errno.EACCES) and
124 not base.conf.exit_on_lock):
125 logger.critical(_("Another app is currently holding the yum lock; waiting for it to exit..."))
126 tm = 0.1
127 if show_lock_owner(e.pid, logger):
128 tm = 2
129 time.sleep(tm)
130 elif e.errno in (errno.EPERM, errno.EACCES):
131 logger.critical(_("Can't create lock file; exiting"))
132 return 1
133 else:
134 logger.critical(_("Another app is currently holding the yum lock; exiting as configured by exit_on_lock"))
135 return 1
136 else:
137 break
138
139 try:
140 result, resultmsgs = base.doCommands()
141 except plugins.PluginYumExit, e:
142 return exPluginExit(e)
143 except Errors.YumBaseError, e:
144 result = 1
145 resultmsgs = [exception2msg(e)]
146 except KeyboardInterrupt:
147 return exUserCancel()
148 except IOError, e:
149 return exIOError(e)
150
151 # Act on the command/shell result
152 if result == 0:
153 # Normal exit
154 for msg in resultmsgs:
155 verbose_logger.log(logginglevels.INFO_2, '%s', msg)
156 if unlock(): return 200
157 return 0
158 elif result == 1:
159 # Fatal error
160 for msg in resultmsgs:
161 logger.critical(_('Error: %s'), msg)
162 if unlock(): return 200
163 return 1
164 elif result == 2:
165 # Continue on
166 pass
167 elif result == 100:
168 if unlock(): return 200
169 return 100
170 else:
171 logger.critical(_('Unknown Error(s): Exit Code: %d:'), result)
172 for msg in resultmsgs:
173 logger.critical(msg)
174 if unlock(): return 200
175 return 3
176
177 # Depsolve stage
178 verbose_logger.log(logginglevels.INFO_2, _('Resolving Dependencies'))
179
180 try:
181 (result, resultmsgs) = base.buildTransaction()
182 except plugins.PluginYumExit, e:
183 return exPluginExit(e)
184 except Errors.YumBaseError, e:
185 result = 1
186 resultmsgs = [exception2msg(e)]
187 except KeyboardInterrupt:
188 return exUserCancel()
189 except IOError, e:
190 return exIOError(e)
191
192 # Act on the depsolve result
193 if result == 0:
194 # Normal exit
195 if unlock(): return 200
196 return 0
197 elif result == 1:
198 # Fatal error
199 for msg in resultmsgs:
200 prefix = _('Error: %s')
201 prefix2nd = (' ' * (utf8_width(prefix) - 2))
202 logger.critical(prefix, msg.replace('\n', '\n' + prefix2nd))
203 if base._depsolving_failed:
204 if not base.conf.skip_broken:
205 verbose_logger.info(_(" You could try using --skip-broken to work around the problem"))
206 rpmdb_warn_checks()
207 if unlock(): return 200
208 return 1
209 elif result == 2:
210 # Continue on
211 pass
212 else:
213 logger.critical(_('Unknown Error(s): Exit Code: %d:'), result)
214 for msg in resultmsgs:
215 logger.critical(msg)
216 if unlock(): return 200
217 return 3
218
219 verbose_logger.log(logginglevels.INFO_2, _('\nDependencies Resolved'))
220
221 # Run the transaction
222 try:
223 return_code = base.doTransaction()
224 except plugins.PluginYumExit, e:
225 return exPluginExit(e)
226 except Errors.YumBaseError, e:
227 return exFatal(e)
228 except KeyboardInterrupt:
229 return exUserCancel()
230 except IOError, e:
231 return exIOError(e)
232
233 # rpm ts.check() failed.
234 if type(return_code) == type((0,)) and len(return_code) == 2:
235 (result, resultmsgs) = return_code
236 for msg in resultmsgs:
237 logger.critical("%s", msg)
238 rpmdb_warn_checks()
239 return_code = result
240 if base._ts_save_file:
241 verbose_logger.info(_("Your transaction was saved, rerun it with: yum load-transaction %s") % base._ts_save_file)
242 elif return_code < 0:
243 return_code = 1 # Means the pre-transaction checks failed...
244 else:
245 verbose_logger.log(logginglevels.INFO_2, _('Complete!'))
246
247 if unlock(): return 200
248 return return_code
249
250def hotshot(func, *args, **kwargs):
251 import hotshot.stats
252 fn = os.path.expanduser("~/yum.prof")
253 prof = hotshot.Profile(fn)
254 rc = prof.runcall(func, *args, **kwargs)
255 prof.close()
256 print_stats(hotshot.stats.load(fn))
257 return rc
258
259def cprof(func, *args, **kwargs):
260 import cProfile, pstats
261 fn = os.path.expanduser("~/yum.prof")
262 prof = cProfile.Profile()
263 rc = prof.runcall(func, *args, **kwargs)
264 prof.dump_stats(fn)
265 print_stats(pstats.Stats(fn))
266 return rc
267
268def print_stats(stats):
269 stats.strip_dirs()
270 stats.sort_stats('time', 'calls')
271 stats.print_stats(20)
272 stats.sort_stats('cumulative')
273 stats.print_stats(40)
274
275def user_main(args, exit_code=False):
276 """ This calls one of the multiple main() functions based on env. vars """
277 errcode = None
278 if 'YUM_PROF' in os.environ:
279 if os.environ['YUM_PROF'] == 'cprof':
280 errcode = cprof(main, args)
281 if os.environ['YUM_PROF'] == 'hotshot':
282 errcode = hotshot(main, args)
283 if 'YUM_PDB' in os.environ:
284 import pdb
285 pdb.run(main(args))
286
287 if errcode is None:
288 errcode = main(args)
289 if exit_code:
290 sys.exit(errcode)
291 return errcode
292
293suppress_keyboard_interrupt_message()
294
295if __name__ == "__main__":
296 try:
297 user_main(sys.argv[1:], exit_code=True)
298 except KeyboardInterrupt, e:
299 print >> sys.stderr, _("\n\nExiting on user cancel.")
300 sys.exit(1)
Note: See TracBrowser for help on using the repository browser.