Handle also errors which can sneak out of httplib
[opensuse:osc.git] / osc / babysitter.py
1 # Copyright (C) 2008 Novell Inc.  All rights reserved.
2 # This program is free software; it may be used, copied, modified
3 # and distributed under the terms of the GNU General Public Licence,
4 # either version 2, or (at your option) any later version.
5
6 import os.path
7 import sys
8 import signal
9 import errno
10 from osc import oscerr
11 from urllib2 import URLError, HTTPError
12 from httplib import HTTPException, BadStatusLine
13 from oscsslexcp import NoSecureSSLError
14 from osc.util.cpio import CpioError
15 from osc.util.packagequery import PackageError
16
17 try:
18     from M2Crypto.SSL.Checker import SSLVerificationError
19     from M2Crypto.SSL import SSLError as SSLError
20 except:
21     SSLError = None
22     SSLVerificationError = None
23
24 try:
25     # import as RPMError because the class "error" is too generic
26     from rpm import error as RPMError
27 except:
28     # if rpm-python isn't installed (we might be on a debian system):
29     RPMError = None
30
31
32 # the good things are stolen from Matt Mackall's mercurial
33
34 def catchterm(*args):
35     raise oscerr.SignalInterrupt
36
37 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
38     num = getattr(signal, name, None)
39     if num: signal.signal(num, catchterm)
40
41
42 def run(prg):
43
44     try:
45
46         try:
47             if '--debugger' in sys.argv:
48                 import pdb
49                 pdb.set_trace()
50
51             # here we actually run the program:
52             return prg.main()
53
54         except:
55             # look for an option in the prg.options object and in the config dict
56             # print stack trace, if desired
57             if getattr(prg.options, 'traceback', None) or getattr(prg.conf, 'config', {}).get('traceback', None) or \
58                getattr(prg.options, 'post_mortem', None) or getattr(prg.conf, 'config', {}).get('post_mortem', None):
59                 import traceback
60                 traceback.print_exc(file=sys.stderr)
61                 # we could use http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52215
62
63             # enter the debugger, if desired
64             if getattr(prg.options, 'post_mortem', None) or getattr(prg.conf, 'config', {}).get('post_mortem', None):
65                 if sys.stdout.isatty() and not hasattr(sys, 'ps1'):
66                     import pdb
67                     pdb.post_mortem(sys.exc_info()[2])
68                 else:
69                     print >>sys.stderr, 'sys.stdout is not a tty. Not jumping into pdb.'
70             raise
71
72     except oscerr.SignalInterrupt:
73         print >>sys.stderr, 'killed!'
74         return 1
75
76     except KeyboardInterrupt:
77         print >>sys.stderr, 'interrupted!'
78         return 1
79
80     except oscerr.UserAbort:
81         print >>sys.stderr, 'aborted.'
82         return 1
83
84     except oscerr.APIError, e:
85         print >>sys.stderr, 'BuildService API error:', e.msg
86         return 1
87
88     except oscerr.LinkExpandError, e:
89         print >>sys.stderr, 'Link "%s/%s" cannot be expanded:\n' % (e.prj, e.pac), e.msg
90         print >>sys.stderr, 'Use "osc repairlink" to fix merge conflicts.\n'
91         return 1
92
93     except oscerr.WorkingCopyWrongVersion, e:
94         print >>sys.stderr, e
95
96     except oscerr.NoWorkingCopy, e:
97         print >>sys.stderr, e
98         if os.path.isdir('.git'): print >>sys.stderr, "Current directory looks like git."
99         if os.path.isdir('.hg'):  print >>sys.stderr, "Current directory looks like mercurial."
100         if os.path.isdir('.svn'): print >>sys.stderr, "Current directory looks like svn."
101         if os.path.isdir('CVS'):  print >>sys.stderr, "Current directory looks like cvs."
102         return 1
103
104     except HTTPError, e:
105         print >>sys.stderr, 'Server returned an error:', e
106         if hasattr(e, 'osc_msg'):
107             print >>sys.stderr, e.osc_msg
108
109         try:
110             body = e.read()
111         except AttributeError:
112             body = ''
113
114         if getattr(prg.options, 'debug', None) or \
115            getattr(prg.conf, 'config', {}).get('debug', None):
116             print >>sys.stderr, e.hdrs
117             print >>sys.stderr, body
118
119         if e.code in [ 400, 403, 404, 500 ]:
120             if '<summary>' in body:
121                 msg = body.split('<summary>')[1]
122                 msg = msg.split('</summary>')[0]
123                 print >>sys.stderr, msg
124
125         return 1
126
127     except BadStatusLine, e:
128         print >>sys.stderr, 'Server returned an invalid response:', e
129         print >>sys.stderr, e.line
130         return 1
131
132     except HTTPException, e:
133         print >>sys.stderr, e
134         return 1
135
136     except URLError, e:
137         print >>sys.stderr, 'Failed to reach a server:\n', e.reason
138         return 1
139
140     except IOError, e:
141         # ignore broken pipe
142         if e.errno != errno.EPIPE:
143             raise
144         return 1
145
146     except OSError, e:
147         if e.errno != errno.ENOENT:
148             raise
149         print >>sys.stderr, e
150         return 1
151
152     except (oscerr.ConfigError, oscerr.NoConfigfile), e:
153         print >>sys.stderr, e.msg
154         return 1
155
156     except oscerr.OscIOError, e:
157         print >>sys.stderr, e.msg
158         if getattr(prg.options, 'debug', None) or \
159            getattr(prg.conf, 'config', {}).get('debug', None):
160             print >>sys.stderr, e.e
161         return 1
162
163     except (oscerr.WrongOptions, oscerr.WrongArgs), e:
164         print >>sys.stderr, e
165         return 2
166
167     except oscerr.ExtRuntimeError, e:
168         print >>sys.stderr, e.msg
169         return 1
170
171     except oscerr.WorkingCopyOutdated, e:
172         print >>sys.stderr, e
173         return 1
174
175     except (oscerr.PackageExists, oscerr.PackageMissing, oscerr.WorkingCopyInconsistent), e:
176         print >>sys.stderr, e.msg
177         return 1
178
179     except oscerr.PackageInternalError, e:
180         import traceback
181         print >>sys.stderr, 'a package internal error occured\n' \
182             'please file a bug and attach your current package working copy ' \
183             'and the following traceback to it:'
184         print >>sys.stderr, e.msg
185         traceback.print_exc(file=sys.stderr)
186         return 1
187
188     except oscerr.PackageError, e:
189         print >>sys.stderr, e.msg
190         return 1
191
192     except PackageError, e:
193         print >>sys.stderr, '%s:' % e.fname, e.msg
194         return 1
195
196     except RPMError, e:
197         print >>sys.stderr, e
198         return 1
199
200     except SSLError, e:
201         print >>sys.stderr, "SSL Error:", e
202         return 1
203
204     except SSLVerificationError, e:
205         print >>sys.stderr, "Certificate Verification Error:", e
206         return 1
207
208     except NoSecureSSLError, e:
209         print >>sys.stderr, e
210         return 1
211
212     except CpioError, e:
213         print >>sys.stderr, e
214         return 1
215
216     except oscerr.OscBaseError, e:
217         print >>sys.stderr, '*** Error:', e
218         return 1
219
220 # vim: sw=4 et