def callcatch()

in eden/scm/edenscm/mercurial/scmutil.py [0:0]


def callcatch(ui, req, 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:
        try:
            try:
                return func()
            except Exception as ex:  # re-raises
                # Swap in the repo's ui if available since this includes the repo's config.
                if req.cmdrepo:
                    ui = req.cmdrepo.ui

                ui.traceback()

                # Log error info for all non-zero exits.
                _uploadtraceback(ui, str(ex), util.smartformatexc())

                raise
            finally:
                # Print 'remote:' messages before 'abort:' messages.
                # This also avoids sshpeer.__del__ during Py_Finalize -> GC
                # on Python 3, which can cause deadlocks waiting for the
                # stderr reading thread.
                from . import sshpeer

                sshpeer.cleanupall()

        except (
            error.HttpError,
            error.FetchError,
            error.NetworkError,
            error.TlsError,
        ) as inst:
            if ui.configbool("experimental", "network-doctor"):
                problem = bindings.doctor.diagnose_network(ui._rcfg._rcfg)
                if problem:
                    ui.warn("\n{}\n".format(problem[0]), label="doctor.treatment")
                    ui.note("  {}\n".format(problem[1]))
                    ui.debug("\nOriginal error:\n{}\n".format(inst))
                    return 1

            raise

    # 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.lockinfo
        else:
            reason = _("lock held by %r") % inst.lockinfo
        ui.warn(_("%s: %s\n") % (inst.desc or inst.filename, reason), error=_("abort"))
        if not inst.lockinfo:
            ui.warn(_("(lock might be very busy)\n"))
    except error.LockUnavailable as inst:
        ui.warn(
            _("could not lock %s: %s\n")
            % (inst.desc or inst.filename, encoding.strtolocal(inst.strerror)),
            error=_("abort"),
        )
    except error.OutOfBandError as inst:
        if inst.args:
            msg = _("remote error:\n")
        else:
            msg = _("remote error\n")
        ui.warn(msg, error=_("abort"))
        if inst.args:
            ui.warn("".join(inst.args))
        if inst.hint:
            ui.warn("(%s)\n" % inst.hint)
    except error.RepoError as inst:
        ui.warn(_("%s!\n") % inst, error=_("abort"))
        inst.printcontext(ui)
        if inst.hint:
            ui.warn(_("(%s)\n") % inst.hint)
    except error.ResponseError as inst:
        ui.warn(inst.args[0], error=_("abort"))
        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(_("file censored %s!\n") % inst, error=_("abort"))
    except error.CommitLookupError as inst:
        ui.warn(_("%s!\n") % inst.args[0], error=_("abort"))
    except error.CertificateError as inst:
        # This error is definitively due to a problem with the user's client
        # certificate, so print the configured remediation message.
        helptext = ui.config("help", "tlsauthhelp")
        if helptext is None:
            helptext = _("(run 'hg config auth' to see configured certificates)")
        ui.warn(
            _("%s!\n\n%s\n") % (inst.args[0], helptext),
            error=_("certificate error"),
        )
    except error.TlsError as inst:
        # This is a generic TLS error that may or may not be due to the user's
        # client certificate, so print a more generic message about TLS errors.
        helptext = ui.config("help", "tlshelp")
        if helptext is None:
            helptext = _("(is your client certificate valid?)")
        ui.warn(
            _("%s!\n\n%s\n") % (inst.args[0], helptext),
            error=_("tls error"),
        )
    except error.RevlogError as inst:
        ui.warn(_("%s!\n") % inst, error=_("abort"))
        inst.printcontext(ui)
    except error.InterventionRequired as inst:
        ui.warn("%s\n" % inst)
        if inst.hint:
            ui.warn(_("(%s)\n") % inst.hint)
        return 1
    except error.WdirUnsupported:
        ui.warn(_("working directory revision cannot be specified\n"), error=_("abort"))
    except error.Abort as inst:
        ui.warn(_("%s\n") % inst, error=_("abort"), component=inst.component)
        inst.printcontext(ui)
        if inst.hint:
            ui.warn(_("(%s)\n") % inst.hint)
        return inst.exitcode
    except (error.IndexedLogError, error.MetaLogError) as inst:
        ui.warn(_("internal storage is corrupted\n"), error=_("abort"))
        ui.warn(_("  %s\n\n") % str(inst).replace("\n", "\n  "))
        ui.warn(_("(this usually happens after hard reboot or system crash)\n"))
        ui.warn(_("(try '@prog@ doctor' to attempt to fix it)\n"))
    except error.RevisionstoreError as inst:
        ui.warn(_("%s\n") % inst, error=_("abort"))
    except error.NonUTF8PathError as inst:
        ui.warn(_("%s\n") % str(inst), error=_("abort"))
    except ImportError as inst:
        ui.warn(_("%s!\n") % inst, error=_("abort"))
        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(_("%s\n") % inst, error=_("abort"))
        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, pycompat.unicode):
                # SSLError of Python 2.7.9 contains a unicode
                reason = encoding.unitolocal(reason)
            ui.warn(_("error: %s\n") % reason, error=_("abort"))
        elif (
            util.safehasattr(inst, "args") and inst.args and inst.args[0] == errno.EPIPE
        ):
            pass
        elif getattr(inst, "strerror", None):
            filename = getattr(inst, "filename", None)
            if filename:
                ui.warn(
                    _("%s: %s\n") % (encoding.strtolocal(inst.strerror), inst.filename),
                    error=_("abort"),
                )
            else:
                ui.warn(
                    _("%s\n") % encoding.strtolocal(inst.strerror), error=_("abort")
                )
            if not pycompat.iswindows:
                # For permission errors on POSIX. Show more information about the
                # current user, group, and stat results.
                num = getattr(inst, "errno", None)
                if filename is not None and num in {errno.EACCES, errno.EPERM}:
                    if util.istest():
                        uid = 42
                    else:
                        uid = os.getuid()
                    ui.warn(_("(current process runs with uid %s)\n") % uid)
                    _printstat(ui, filename)
                    _printstat(ui, os.path.dirname(filename))
        else:
            ui.warn(_("%s\n") % inst, error=_("abort"))
    except OSError as inst:
        if getattr(inst, "filename", None) is not None:
            ui.warn(
                _("%s: %s\n") % (encoding.strtolocal(inst.strerror), inst.filename),
                error=_("abort"),
            )
        else:
            ui.warn(_("%s\n") % encoding.strtolocal(inst.strerror), error=_("abort"))
    except MemoryError:
        ui.warn(_("out of memory\n"), error=_("abort"))
    except SystemExit as inst:
        # Commands shouldn't sys.exit directly, but give a return code.
        # Just in case catch this and pass exit code to caller.
        return inst.code
    except socket.error as inst:
        ui.warn(_("%s\n") % inst.args[-1], error=_("abort"))
    except Exception as e:
        if type(e).__name__ == "TApplicationException":
            ui.warn(_("ThriftError: %s\n") % e, error=_("abort"))
            ui.warn(_("(try 'eden doctor' to diagnose this issue)\n"))
        else:
            raise

    return -1