view tests/bruterebase.py @ 48454:473af5cbc209

rhg: Add support for `rhg status --copies` Copy sources are collected during `status()` rather than after the fact like in Python, because `status()` takes a `&mut` exclusive reference to the dirstate map (in order to potentially mutate it for directory mtimes) and returns `Cow<'_, HgPath>` that borrow the dirstate map. Even though with `Cow` only some shared borrows remain, the still extend the same lifetime of the initial `&mut` so the dirstate map cannot be borrowed again to access copy sources after the fact: https://doc.rust-lang.org/nomicon/lifetime-mismatch.html#limits-of-lifetimes Additionally, collecting copy sources during the dirstate tree traversal that `status()` already does avoids the cost of another traversal or other lookups (though I haven’t benchmarked that cost). Differential Revision: https://phab.mercurial-scm.org/D11899
author Simon Sapin <simon.sapin@octobus.net>
date Fri, 10 Dec 2021 16:18:58 +0100
parents 7a430116f639
children 6000f5b25c9b
line wrap: on
line source

# bruterebase.py - brute force rebase testing
#
# Copyright 2017 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import absolute_import

from mercurial import (
    error,
    registrar,
    revsetlang,
)

from hgext import rebase

try:
    xrange
except NameError:
    xrange = range

cmdtable = {}
command = registrar.command(cmdtable)


@command(b'debugbruterebase')
def debugbruterebase(ui, repo, source, dest):
    """for every non-empty subset of source, run rebase -r subset -d dest

    Print one line summary for each subset. Assume obsstore is enabled.
    """
    srevs = list(repo.revs(source))

    with repo.wlock(), repo.lock():
        repolen = len(repo)
        cl = repo.changelog

        def getdesc(rev):
            result = cl.changelogrevision(rev).description
            if rev >= repolen:
                result += b"'"
            return result

        for i in xrange(1, 2 ** len(srevs)):
            subset = [rev for j, rev in enumerate(srevs) if i & (1 << j) != 0]
            spec = revsetlang.formatspec(b'%ld', subset)
            tr = repo.transaction(b'rebase')
            tr._report = lambda x: 0  # hide "transaction abort"

            with ui.silent():
                try:
                    rebase.rebase(ui, repo, dest=dest, rev=[spec])
                except error.Abort as ex:
                    summary = b'ABORT: %s' % ex.message
                except Exception as ex:
                    summary = b'CRASH: %s' % ex
                else:
                    # short summary about new nodes
                    cl = repo.changelog
                    descs = []
                    for rev in xrange(repolen, len(repo)):
                        desc = b'%s:' % getdesc(rev)
                        for prev in cl.parentrevs(rev):
                            if prev > -1:
                                desc += getdesc(prev)
                        descs.append(desc)
                    descs.sort()
                    summary = b' '.join(descs)
            repo.vfs.tryunlink(b'rebasestate')

            subsetdesc = b''.join(getdesc(rev) for rev in subset)
            ui.write(b'%s: %s\n' % (subsetdesc.rjust(len(srevs)), summary))
            tr.abort()