Beispiel #1
0
def graphqlgetdiff(repo, diffid):
    """Resolves a phabricator Diff number to a commit hash of it's latest version"""
    if util.istest():
        hexnode = repo.ui.config("phrevset", "mock-D%s" % diffid)
        if hexnode:
            return {
                "source_control_system": "hg",
                "description": "Commit rCALLSIGN{}".format(hexnode),
                "phabricator_version_properties": {
                    "edges": [
                        {
                            "node": {
                                "property_name": "local:commits",
                                "property_value": json.dumps(
                                    {hexnode: {"commit": hexnode, "rev": hexnode}}
                                ),
                            }
                        }
                    ]
                },
            }
    timeout = repo.ui.configint("ssl", "timeout", 10)
    ca_certs = repo.ui.configpath("web", "cacerts")
    try:
        client = graphql.Client(
            repodir=pycompat.getcwd(), ca_bundle=ca_certs, repo=repo
        )
        return client.getdifflatestversion(timeout, diffid)
    except Exception as e:
        raise error.Abort(
            "Could not call phabricator graphql API: %s" % e,
            hint="perhaps you need to connect to the VPN or run 'jf auth'?",
        )
Beispiel #2
0
    def close(self):
        # Make it "run-tests.py -i" friendly
        if util.istest():
            global fetchcost
            fetchcost = 0
        if fetches:
            msg = ("%s files fetched over %d fetches - " +
                   "(%d misses, %0.2f%% hit ratio) over %0.2fs\n") % (
                       fetched,
                       fetches,
                       fetchmisses,
                       float(fetched - fetchmisses) / float(fetched) * 100.0,
                       fetchcost,
                   )
            if self.debugoutput:
                self.ui.warn(msg)
            self.ui.log(
                "remotefilelog.prefetch",
                msg.replace("%", "%%"),
                remotefilelogfetched=fetched,
                remotefilelogfetches=fetches,
                remotefilelogfetchmisses=fetchmisses,
                remotefilelogfetchtime=fetchcost * 1000,
            )

        if self.remotecache.connected:
            self.remotecache.close()
Beispiel #3
0
def reposetup(ui, repo):
    # Do not track known long-running commands.
    if not repo.local():
        return
    if ui.cmdname in {"debugedenimporthelper"} and not util.istest():
        return
    interval = ui.configint("sigtrace", "interval")
    if not interval or interval <= 0:
        return

    def writesigtracethread(path, interval):
        try:
            dir = os.path.dirname(path)
            util.makedirs(dir)
            while True:
                time.sleep(interval)
                # Keep 10 minutes of sigtraces.
                util.gcdir(dir, 60 * 10)
                writesigtrace(path)
        except Exception:
            pass

    path = repo.localvfs.join("sigtrace",
                              "pid-%s-%s" % (os.getpid(), ui.cmdname))
    thread = threading.Thread(target=writesigtracethread,
                              args=(path, interval),
                              name="sigtracethread")
    thread.daemon = True
    thread.start()
Beispiel #4
0
def _debug(ui, msg):
    config = ui.configbool("simplecache", "showdebug", None)
    if config is None:
        config = not util.istest()

    if config:
        ui.debug(msg)
Beispiel #5
0
def _analyzewrapper(orig, x, ui):
    """Wraps analyzer to detect the use of colons in the revisions"""
    result = orig(x)

    warn = ui.configbool("tweakdefaults", "singlecolonwarn")
    abort = ui.configbool("tweakdefaults", "singlecolonabort")
    enabled = warn or abort

    # The last condition is added so that warnings are not shown if
    # hg log --follow is invoked w/o arguments
    if (
        enabled
        and isinstance(x, tuple)
        and (x[0] in ("range", "rangepre", "rangepost"))
        and x != ("rangepre", ("symbol", "."))
    ):
        if not util.istest():
            ui.deprecate("single-colon-revset", "':' is deprecated in revsets")
        msg = ui.config("tweakdefaults", "singlecolonmsg")
        if abort:
            raise error.Abort("%s" % msg)
        if warn:
            ui.warn(_("warning: %s\n") % msg)

    return result
Beispiel #6
0
def diffidtonode(repo, diffid):
    """Return node that matches a given Differential ID or None.

    The node might exist or not exist in the repo.
    This function does not raise.
    """

    repo_callsigns = repo.ui.configlist("phrevset", "callsign")
    if not repo_callsigns:
        msg = _("phrevset.callsign is not set - doing a linear search\n")
        hint = _("This will be slow if the diff was not committed recently\n")
        repo.ui.warn(msg)
        repo.ui.warn(hint)
        node = localgetdiff(repo, diffid)
        if node is None:
            repo.ui.warn(_("Could not find diff D%s in changelog\n") % diffid)
        return node

    node, resp = search(repo, diffid)

    if node is not None:
        # The log walk found the diff, nothing more to do
        return node

    if resp is None:
        # The graphql query finished but didn't return anything
        return None

    vcs = resp.get("source_control_system")
    localreponame = repo.ui.config("remotefilelog", "reponame")
    diffreponame = None
    repository = resp.get("repository")
    if repository is not None:
        diffreponame = repository.get("scm_name")
    if diffreponame in repo.ui.configlist("phrevset", "aliases"):
        diffreponame = localreponame

    if not util.istest() and (diffreponame != localreponame):
        raise error.Abort(
            "D%s is for repo '%s', not this repo ('%s')"
            % (diffid, diffreponame, localreponame)
        )

    repo.ui.debug("[diffrev] VCS is %s\n" % vcs)

    if vcs == "git":
        gitrev = parsedesc(repo, resp, ignoreparsefailure=False)
        repo.ui.debug("[diffrev] GIT rev is %s\n" % gitrev)

        peerpath = repo.ui.expandpath("default")
        remoterepo = hg.peer(repo, {}, peerpath)
        remoterev = remoterepo.lookup("_gitlookup_git_%s" % gitrev)

        repo.ui.debug("[diffrev] HG rev is %s\n" % hex(remoterev))
        if not remoterev:
            repo.ui.debug("[diffrev] Falling back to linear search\n")
            node = localgetdiff(repo, diffid)
            if node is None:
                repo.ui.warn(_("Could not find diff D%s in changelog\n") % diffid)

            return node

        return remoterev

    elif vcs == "hg":
        rev = parsedesc(repo, resp, ignoreparsefailure=True)
        if rev:
            # The response from phabricator contains a changeset ID.
            # Convert it back to a node.
            try:
                return repo[rev].node()
            except error.RepoLookupError:
                # TODO: 's/svnrev/globalrev' after turning off Subversion
                # servers. We will know about this when we remove the `svnrev`
                # revset.
                #
                # Unfortunately the rev can also be a svnrev/globalrev :(.
                if rev.isdigit():
                    try:
                        return list(repo.nodes("svnrev(%s)" % rev))[0]
                    except (IndexError, error.RepoLookupError):
                        pass

                if len(rev) == len(nullhex):
                    return bin(rev)
                else:
                    return None

        # commit is still local, get its hash

        try:
            props = resp["phabricator_version_properties"]["edges"]
            commits = {}
            for prop in props:
                if prop["node"]["property_name"] == "local:commits":
                    commits = json.loads(prop["node"]["property_value"])
            hexnodes = [c["commit"] for c in commits.values()]
        except (AttributeError, IndexError, KeyError):
            hexnodes = []

        # find a better alternative of the commit hash specified in
        # graphql response by looking up successors.
        for hexnode in hexnodes:
            if len(hexnode) != len(nullhex):
                continue

            node = bin(hexnode)
            unfi = repo
            if node in unfi:
                # Find a successor.
                successors = list(
                    unfi.nodes("last(successors(%n)-%n-obsolete())", node, node)
                )
                if successors:
                    return successors[0]
            return node

        # local:commits is empty
        return None

    else:
        if not vcs:
            msg = (
                "D%s does not have an associated version control system\n"
                "You can view the diff at https:///our.internmc.facebook.com/intern/diff/D%s\n"
            )
            repo.ui.warn(msg % (diffid, diffid))

            return None
        else:
            repo.ui.warn(
                _("Conduit returned unknown sourceControlSystem: '%s'\n") % vcs
            )

            return None