diff --git a/tests/bruterebase.py b/tests/bruterebase.py new file mode 100644 --- /dev/null +++ b/tests/bruterebase.py @@ -0,0 +1,69 @@ +# 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 + +cmdtable = {} +command = registrar.command(cmdtable) + +@command('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 += "'" + 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('%ld', subset) + tr = repo.transaction('rebase') + tr.report = lambda x: 0 # hide "transaction abort" + + ui.pushbuffer() + try: + rebase.rebase(ui, repo, dest=dest, rev=[spec]) + except error.Abort as ex: + summary = 'ABORT: %s' % ex + except Exception as ex: + summary = 'CRASH: %s' % ex + else: + # short summary about new nodes + cl = repo.changelog + descs = [] + for rev in xrange(repolen, len(repo)): + desc = '%s:' % getdesc(rev) + for prev in cl.parentrevs(rev): + if prev > -1: + desc += getdesc(prev) + descs.append(desc) + descs.sort() + summary = ' '.join(descs) + ui.popbuffer() + repo.vfs.tryunlink('rebasestate') + + subsetdesc = ''.join(getdesc(rev) for rev in subset) + ui.write(('%s: %s\n') % (subsetdesc.rjust(len(srevs)), summary)) + tr.abort() diff --git a/tests/test-rebase-brute-force.t b/tests/test-rebase-brute-force.t new file mode 100644 --- /dev/null +++ b/tests/test-rebase-brute-force.t @@ -0,0 +1,55 @@ + $ cat >> $HGRCPATH < [extensions] + > drawdag=$TESTDIR/drawdag.py + > bruterebase=$TESTDIR/bruterebase.py + > [experimental] + > evolution=createmarkers,allowunstable + > EOF + $ init() { + > N=`expr ${N:-0} + 1` + > cd $TESTTMP && hg init repo$N && cd repo$N + > hg debugdrawdag + > } + +Source looks like "N" + + $ init <<'EOS' + > C D + > |\| + > A B Z + > EOS + + $ hg debugbruterebase 'all()-Z' Z + A: A':Z + B: B':Z + AB: A':Z B':Z + C: ABORT: cannot use revision 3 as base, result would have 3 parents + AC: A':Z C':A'B + BC: B':Z C':B'A + ABC: A':Z B':Z C':A'B' + D: D':Z + AD: A':Z D':Z + BD: B':Z D':B' + ABD: A':Z B':Z D':B' + CD: CRASH: revlog index out of range + ACD: A':Z C':A'A' D':Z + BCD: B':Z C':B'A D':B' + ABCD: A':Z B':Z C':A'B' D':B' + +Moving backwards + + $ init <<'EOS' + > C + > |\ + > A B + > | + > Z + > EOS + $ hg debugbruterebase 'all()-Z' Z + B: B':Z + A: + BA: B':Z + C: ABORT: cannot use revision 3 as base, result would have 3 parents + BC: B':Z C':B'A + AC: + BAC: ABORT: nothing to merge