1# bruterebase.py - brute force rebase testing 2# 3# Copyright 2017 Facebook, Inc. 4# 5# This software may be used and distributed according to the terms of the 6# GNU General Public License version 2 or any later version. 7 8from __future__ import absolute_import 9 10from mercurial import ( 11 error, 12 registrar, 13 revsetlang, 14) 15 16from hgext import rebase 17 18try: 19 xrange 20except NameError: 21 xrange = range 22 23cmdtable = {} 24command = registrar.command(cmdtable) 25 26 27@command(b'debugbruterebase') 28def debugbruterebase(ui, repo, source, dest): 29 """for every non-empty subset of source, run rebase -r subset -d dest 30 31 Print one line summary for each subset. Assume obsstore is enabled. 32 """ 33 srevs = list(repo.revs(source)) 34 35 with repo.wlock(), repo.lock(): 36 repolen = len(repo) 37 cl = repo.changelog 38 39 def getdesc(rev): 40 result = cl.changelogrevision(rev).description 41 if rev >= repolen: 42 result += b"'" 43 return result 44 45 for i in xrange(1, 2 ** len(srevs)): 46 subset = [rev for j, rev in enumerate(srevs) if i & (1 << j) != 0] 47 spec = revsetlang.formatspec(b'%ld', subset) 48 tr = repo.transaction(b'rebase') 49 tr._report = lambda x: 0 # hide "transaction abort" 50 51 with ui.silent(): 52 try: 53 rebase.rebase(ui, repo, dest=dest, rev=[spec]) 54 except error.Abort as ex: 55 summary = b'ABORT: %s' % ex.message 56 except Exception as ex: 57 summary = b'CRASH: %s' % ex 58 else: 59 # short summary about new nodes 60 cl = repo.changelog 61 descs = [] 62 for rev in xrange(repolen, len(repo)): 63 desc = b'%s:' % getdesc(rev) 64 for prev in cl.parentrevs(rev): 65 if prev > -1: 66 desc += getdesc(prev) 67 descs.append(desc) 68 descs.sort() 69 summary = b' '.join(descs) 70 repo.vfs.tryunlink(b'rebasestate') 71 72 subsetdesc = b''.join(getdesc(rev) for rev in subset) 73 ui.write(b'%s: %s\n' % (subsetdesc.rjust(len(srevs)), summary)) 74 tr.abort() 75