Mercurial > hg
comparison mercurial/scmutil.py @ 30520:4338f87dbf6f
dispatch: move part of callcatch to scmutil
Per discussion at 39149b6036e6 [1], we need "callcatch" in worker.py. Move
it to scmutil.py to avoid cycles.
Note that dispatch's callcatch handles some additional high-level exceptions
related to config parsing, and commands. Moving them to scmutil will make
scmutil depend on "commands" or require "_formatparse" and "_getsimilar"
(and "difflib") to be moved as well. In the worker use-case, it is forked
when config and commands are fully loaded. So it should not care about those
exceptions.
[1]: https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-August/087116.html
author | Jun Wu <quark@fb.com> |
---|---|
date | Thu, 24 Nov 2016 00:48:40 +0000 |
parents | 854190becacb |
children | d524c88511a7 |
comparison
equal
deleted
inserted
replaced
30519:20a42325fdef | 30520:4338f87dbf6f |
---|---|
12 import glob | 12 import glob |
13 import hashlib | 13 import hashlib |
14 import os | 14 import os |
15 import re | 15 import re |
16 import shutil | 16 import shutil |
17 import socket | |
17 import stat | 18 import stat |
18 import tempfile | 19 import tempfile |
19 import threading | 20 import threading |
20 | 21 |
21 from .i18n import _ | 22 from .i18n import _ |
138 if secretlist: | 139 if secretlist: |
139 ui.status(_("no changes found (ignored %d secret changesets)\n") | 140 ui.status(_("no changes found (ignored %d secret changesets)\n") |
140 % len(secretlist)) | 141 % len(secretlist)) |
141 else: | 142 else: |
142 ui.status(_("no changes found\n")) | 143 ui.status(_("no changes found\n")) |
144 | |
145 def callcatch(ui, func): | |
146 """call func() with global exception handling | |
147 | |
148 return func() if no exception happens. otherwise do some error handling | |
149 and return an exit code accordingly. does not handle all exceptions. | |
150 """ | |
151 try: | |
152 return func() | |
153 # Global exception handling, alphabetically | |
154 # Mercurial-specific first, followed by built-in and library exceptions | |
155 except error.LockHeld as inst: | |
156 if inst.errno == errno.ETIMEDOUT: | |
157 reason = _('timed out waiting for lock held by %s') % inst.locker | |
158 else: | |
159 reason = _('lock held by %s') % inst.locker | |
160 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason)) | |
161 except error.LockUnavailable as inst: | |
162 ui.warn(_("abort: could not lock %s: %s\n") % | |
163 (inst.desc or inst.filename, inst.strerror)) | |
164 except error.OutOfBandError as inst: | |
165 if inst.args: | |
166 msg = _("abort: remote error:\n") | |
167 else: | |
168 msg = _("abort: remote error\n") | |
169 ui.warn(msg) | |
170 if inst.args: | |
171 ui.warn(''.join(inst.args)) | |
172 if inst.hint: | |
173 ui.warn('(%s)\n' % inst.hint) | |
174 except error.RepoError as inst: | |
175 ui.warn(_("abort: %s!\n") % inst) | |
176 if inst.hint: | |
177 ui.warn(_("(%s)\n") % inst.hint) | |
178 except error.ResponseError as inst: | |
179 ui.warn(_("abort: %s") % inst.args[0]) | |
180 if not isinstance(inst.args[1], basestring): | |
181 ui.warn(" %r\n" % (inst.args[1],)) | |
182 elif not inst.args[1]: | |
183 ui.warn(_(" empty string\n")) | |
184 else: | |
185 ui.warn("\n%r\n" % util.ellipsis(inst.args[1])) | |
186 except error.CensoredNodeError as inst: | |
187 ui.warn(_("abort: file censored %s!\n") % inst) | |
188 except error.RevlogError as inst: | |
189 ui.warn(_("abort: %s!\n") % inst) | |
190 except error.SignalInterrupt: | |
191 ui.warn(_("killed!\n")) | |
192 except error.InterventionRequired as inst: | |
193 ui.warn("%s\n" % inst) | |
194 if inst.hint: | |
195 ui.warn(_("(%s)\n") % inst.hint) | |
196 return 1 | |
197 except error.Abort as inst: | |
198 ui.warn(_("abort: %s\n") % inst) | |
199 if inst.hint: | |
200 ui.warn(_("(%s)\n") % inst.hint) | |
201 except ImportError as inst: | |
202 ui.warn(_("abort: %s!\n") % inst) | |
203 m = str(inst).split()[-1] | |
204 if m in "mpatch bdiff".split(): | |
205 ui.warn(_("(did you forget to compile extensions?)\n")) | |
206 elif m in "zlib".split(): | |
207 ui.warn(_("(is your Python install correct?)\n")) | |
208 except IOError as inst: | |
209 if util.safehasattr(inst, "code"): | |
210 ui.warn(_("abort: %s\n") % inst) | |
211 elif util.safehasattr(inst, "reason"): | |
212 try: # usually it is in the form (errno, strerror) | |
213 reason = inst.reason.args[1] | |
214 except (AttributeError, IndexError): | |
215 # it might be anything, for example a string | |
216 reason = inst.reason | |
217 if isinstance(reason, unicode): | |
218 # SSLError of Python 2.7.9 contains a unicode | |
219 reason = reason.encode(encoding.encoding, 'replace') | |
220 ui.warn(_("abort: error: %s\n") % reason) | |
221 elif (util.safehasattr(inst, "args") | |
222 and inst.args and inst.args[0] == errno.EPIPE): | |
223 pass | |
224 elif getattr(inst, "strerror", None): | |
225 if getattr(inst, "filename", None): | |
226 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) | |
227 else: | |
228 ui.warn(_("abort: %s\n") % inst.strerror) | |
229 else: | |
230 raise | |
231 except OSError as inst: | |
232 if getattr(inst, "filename", None) is not None: | |
233 ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename)) | |
234 else: | |
235 ui.warn(_("abort: %s\n") % inst.strerror) | |
236 except MemoryError: | |
237 ui.warn(_("abort: out of memory\n")) | |
238 except SystemExit as inst: | |
239 # Commands shouldn't sys.exit directly, but give a return code. | |
240 # Just in case catch this and and pass exit code to caller. | |
241 return inst.code | |
242 except socket.error as inst: | |
243 ui.warn(_("abort: %s\n") % inst.args[-1]) | |
244 | |
245 return -1 | |
143 | 246 |
144 def checknewlabel(repo, lbl, kind): | 247 def checknewlabel(repo, lbl, kind): |
145 # Do not use the "kind" parameter in ui output. | 248 # Do not use the "kind" parameter in ui output. |
146 # It makes strings difficult to translate. | 249 # It makes strings difficult to translate. |
147 if lbl in ['tip', '.', 'null']: | 250 if lbl in ['tip', '.', 'null']: |