def _makerage()

in eden/scm/edenscm/hgext/rage.py [0:0]


def _makerage(ui, repo, **opts):
    configoverrides = {
        # Make graphlog shorter.
        ("experimental", "graphshorten"): "1",
        # Force use of lines-square renderer, as the user's configuration may
        # not render properly in a text file.
        ("experimental", "graph.renderer"): "lines-square",
        # Reduce the amount of data used for debugnetwork speed tests to
        # increase the chance they complete within 20s.
        ("debugnetwork", "speed-test-download-size"): "4M",
        ("debugnetwork", "speed-test-upload-size"): "1M",
    }

    # Override the encoding to "UTF-8" to generate the rage in UTF-8.
    oldencoding = encoding.encoding
    oldencodingmode = encoding.encodingmode
    encoding.encoding = "UTF-8"
    encoding.encodingmode = "replace"

    def hgcmd(cmdname, *args, **additional_opts):
        cmd, opts = cmdutil.getcmdanddefaultopts(cmdname, commands.table)
        opts.update(additional_opts)

        _repo = repo
        if "_repo" in opts:
            _repo = opts["_repo"]
            del opts["_repo"]
        # If we failed to popbuffer for some reason, do not mess up with the
        # main `ui` object.
        newui = ui.copy()
        newui.pushbuffer(error=True, subproc=True)
        newui._colormode = None

        def remoteui(orig, src, opts):
            rui = orig(src, opts)
            rui._outputui = newui
            return rui

        try:
            with newui.configoverride(
                configoverrides, "rage"
            ), extensions.wrappedfunction(hg, "remoteui", remoteui):
                if cmd.norepo:
                    cmd(newui, *args, **opts)
                else:
                    cmd(newui, _repo, *args, **opts)
        finally:
            return newui.popbuffer()

    basic = [
        ("date", lambda: time.ctime()),
        ("unixname", lambda: encoding.environ.get("LOGNAME")),
        ("hostname", lambda: socket.gethostname()),
        ("repo location", lambda: repo.root),
        ("cwd", lambda: pycompat.getcwd()),
        ("fstype", lambda: util.getfstype(repo.root)),
        ("active bookmark", lambda: bookmarks._readactive(repo, repo._bookmarks)),
        (
            "hg version",
            lambda: __import__(
                "edenscm.mercurial.__version__"
            ).mercurial.__version__.version,
        ),
    ]

    def _edenfs_rage():
        ragecmd = "edenfsctl rage --stdout"
        if opts.get("preview"):
            return shcmd(ragecmd + " --dry-run")
        return shcmd(ragecmd)

    detailed = [
        (
            "disk space usage",
            lambda: shcmd(
                "wmic LogicalDisk Where DriveType=3 Get DeviceId,FileSystem,FreeSpace,Size"
                if pycompat.iswindows
                else "df -h",
                check=False,
            ),
        ),
        # smartlog as the user sees it
        ("hg sl", lambda: hgcmd("smartlog", template="{sl_debug}")),
        (
            "hg debugmetalog -t 'since 2d ago'",
            lambda: hgcmd("debugmetalog", time_range=["since 2d ago"]),
        ),
        (
            'first 20 lines of "hg status"',
            lambda: "\n".join(hgcmd("status").splitlines()[:20]),
        ),
        (
            "hg debugmutation -r 'draft() & date(-4)' -t 'since 4d ago'",
            lambda: hgcmd(
                "debugmutation", rev=["draft() & date(-4)"], time_range=["since 4d ago"]
            ),
        ),
        (
            "hg bookmarks --list-subscriptions",
            lambda: hgcmd("bookmarks", list_subscriptions=True),
        ),
        ("sigtrace", lambda: readsigtraces(repo)),
        (
            "hg blackbox",
            lambda: "\n".join(
                hgcmd("blackbox", pattern=BLACKBOX_PATTERN).splitlines()[-500:]
            ),
        ),
        ("hg summary", lambda: hgcmd("summary")),
        ("hg cloud status", lambda: hgcmd("cloud status")),
        ("hg debugprocesstree", lambda: hgcmd("debugprocesstree")),
        ("hg config (local)", lambda: "\n".join(localconfig(ui))),
        ("hg sparse", lambda: hgcmd("sparse")),
        ("hg debugchangelog", lambda: hgcmd("debugchangelog")),
        ("hg debugexpandpaths", lambda: hgcmd("debugexpandpaths")),
        ("hg debuginstall", lambda: hgcmd("debuginstall")),
        ("hg debugdetectissues", lambda: hgcmd("debugdetectissues")),
        ("usechg", usechginfo),
        (
            "uptime",
            lambda: shcmd(
                "wmic path Win32_OperatingSystem get LastBootUpTime"
                if pycompat.iswindows
                else "uptime"
            ),
        ),
        ("rpm info", (partial(rpminfo, ui))),
        ("klist", lambda: shcmd("klist", check=False)),
        ("ifconfig", lambda: shcmd("ipconfig" if pycompat.iswindows else "ifconfig")),
        (
            "airport",
            lambda: shcmd(
                "/System/Library/PrivateFrameworks/Apple80211."
                + "framework/Versions/Current/Resources/airport "
                + "--getinfo",
                check=False,
            ),
        ),
        ("hg debugnetwork", lambda: hgcmd("debugnetwork")),
        ("infinitepush backup state", lambda: readinfinitepushbackupstate(repo)),
        ("commit cloud workspace sync state", lambda: readcommitcloudstate(repo)),
        (
            "infinitepush / commitcloud backup logs",
            lambda: infinitepushbackuplogs(ui, repo),
        ),
        ("scm daemon logs", lambda: scmdaemonlog(ui, repo)),
        ("debugstatus", lambda: hgcmd("debugstatus")),
        ("debugtree", lambda: hgcmd("debugtree")),
        ("hg config (all)", lambda: "\n".join(allconfig(ui))),
        ("edenfs rage", _edenfs_rage),
        (
            "environment variables",
            lambda: "\n".join(
                sorted(["{}={}".format(k, v) for k, v in encoding.environ.items()])
            ),
        ),
        ("ssh config", lambda: shcmd("ssh -G hg.vip.facebook.com", check=False)),
        ("debuglocks", lambda: hgcmd("debuglocks")),
        ("x2pagentd info", lambda: checkproxyagentstate(ui)),
        ("sks-agent rage", lambda: sksagentrage(ui)),
    ]

    msg = ""

    footnotes = []
    timeout = opts.get("timeout") or 20

    def _failsafe(gen, timeout=timeout):
        class TimedOut(RuntimeError):
            pass

        def target(result, gen):
            try:
                result.append(gen())
            except TimedOut:
                return
            except Exception as ex:
                index = len(footnotes) + 1
                footnotes.append(
                    "[%d]: %s\n%s\n\n" % (index, str(ex), traceback.format_exc())
                )
                result.append("(Failed. See footnote [%d])" % index)

        result = []
        thread = threading.Thread(target=target, args=(result, gen))
        thread.daemon = True
        thread.start()
        thread.join(timeout)
        if result:
            value = result[0]
            return value
        else:
            if thread.is_alive():
                # Attempt to stop the thread, since hg is not thread safe.
                # There is no pure Python API to interrupt a thread.
                # But CPython C API can do that.
                ctypes.pythonapi.PyThreadState_SetAsyncExc(
                    ctypes.c_long(thread.ident), ctypes.py_object(TimedOut)
                )
            return (
                "(Did not complete in %s seconds, rerun with a larger --timeout to collect this)"
                % timeout
            )

    msg = []
    profile = []
    allstart = time.time()
    for name, gen in basic:
        msg.append("%s: %s\n\n" % (name, _failsafe(gen)))
    profile.append((time.time() - allstart, "basic info", None))
    for name, gen in detailed:
        start = time.time()
        with progress.spinner(ui, name):
            value = _failsafe(gen)
        finish = time.time()
        msg.append(
            "%s: (%.2f s)\n---------------------------\n%s\n\n"
            % (name, finish - start, value)
        )
        profile.append((finish - start, name, value.count("\n")))
    allfinish = time.time()
    profile.append((allfinish - allstart, "total time", None))

    msg.append("hg rage profile:\n")
    width = max([len(name) for _t, name, _l in profile])
    for timetaken, name, lines in reversed(sorted(profile)):
        m = "  %-*s  %8.2f s" % (width + 1, name + ":", timetaken)
        if lines is not None:
            msg.append("%s for %4d lines\n" % (m, lines))
        else:
            msg.append("%s\n" % m)
    msg.append("\n")

    msg.extend(footnotes)
    msg = "".join(msg)

    encoding.encoding = oldencoding
    encoding.encodingmode = oldencodingmode
    return msg