diff -r 20a42325fdef -r 4338f87dbf6f mercurial/scmutil.py --- a/mercurial/scmutil.py Wed Nov 23 00:03:11 2016 +0530 +++ b/mercurial/scmutil.py Thu Nov 24 00:48:40 2016 +0000 @@ -14,6 +14,7 @@ import os import re import shutil +import socket import stat import tempfile import threading @@ -141,6 +142,108 @@ else: ui.status(_("no changes found\n")) +def callcatch(ui, func): + """call func() with global exception handling + + return func() if no exception happens. otherwise do some error handling + and return an exit code accordingly. does not handle all exceptions. + """ + try: + return func() + # Global exception handling, alphabetically + # Mercurial-specific first, followed by built-in and library exceptions + except error.LockHeld as inst: + if inst.errno == errno.ETIMEDOUT: + reason = _('timed out waiting for lock held by %s') % inst.locker + else: + reason = _('lock held by %s') % inst.locker + ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason)) + except error.LockUnavailable as inst: + ui.warn(_("abort: could not lock %s: %s\n") % + (inst.desc or inst.filename, inst.strerror)) + except error.OutOfBandError as inst: + if inst.args: + msg = _("abort: remote error:\n") + else: + msg = _("abort: remote error\n") + ui.warn(msg) + if inst.args: + ui.warn(''.join(inst.args)) + if inst.hint: + ui.warn('(%s)\n' % inst.hint) + except error.RepoError as inst: + ui.warn(_("abort: %s!\n") % inst) + if inst.hint: + ui.warn(_("(%s)\n") % inst.hint) + except error.ResponseError as inst: + ui.warn(_("abort: %s") % inst.args[0]) + if not isinstance(inst.args[1], basestring): + ui.warn(" %r\n" % (inst.args[1],)) + elif not inst.args[1]: + ui.warn(_(" empty string\n")) + else: + ui.warn("\n%r\n" % util.ellipsis(inst.args[1])) + except error.CensoredNodeError as inst: + ui.warn(_("abort: file censored %s!\n") % inst) + except error.RevlogError as inst: + ui.warn(_("abort: %s!\n") % inst) + except error.SignalInterrupt: + ui.warn(_("killed!\n")) + except error.InterventionRequired as inst: + ui.warn("%s\n" % inst) + if inst.hint: + ui.warn(_("(%s)\n") % inst.hint) + return 1 + except error.Abort as inst: + ui.warn(_("abort: %s\n") % inst) + if inst.hint: + ui.warn(_("(%s)\n") % inst.hint) + except ImportError as inst: + ui.warn(_("abort: %s!\n") % inst) + m = str(inst).split()[-1] + if m in "mpatch bdiff".split(): + ui.warn(_("(did you forget to compile extensions?)\n")) + elif m in "zlib".split(): + ui.warn(_("(is your Python install correct?)\n")) + except IOError as inst: + if util.safehasattr(inst, "code"): + ui.warn(_("abort: %s\n") % inst) + elif util.safehasattr(inst, "reason"): + try: # usually it is in the form (errno, strerror) + reason = inst.reason.args[1] + except (AttributeError, IndexError): + # it might be anything, for example a string + reason = inst.reason + if isinstance(reason, unicode): + # SSLError of Python 2.7.9 contains a unicode + reason = reason.encode(encoding.encoding, 'replace') + ui.warn(_("abort: error: %s\n") % reason) + elif (util.safehasattr(inst, "args") + and inst.args and inst.args[0] == errno.EPIPE): + pass + elif getattr(inst, "strerror", None): + if getattr(inst, "filename", None): + ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) + else: + ui.warn(_("abort: %s\n") % inst.strerror) + else: + raise + except OSError as inst: + if getattr(inst, "filename", None) is not None: + ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename)) + else: + ui.warn(_("abort: %s\n") % inst.strerror) + except MemoryError: + ui.warn(_("abort: out of memory\n")) + except SystemExit as inst: + # Commands shouldn't sys.exit directly, but give a return code. + # Just in case catch this and and pass exit code to caller. + return inst.code + except socket.error as inst: + ui.warn(_("abort: %s\n") % inst.args[-1]) + + return -1 + def checknewlabel(repo, lbl, kind): # Do not use the "kind" parameter in ui output. # It makes strings difficult to translate.