# debugcommands.py - command processing for debug* commands # # Copyright 2005-2016 Matt Mackall # # 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 import os from .i18n import _ from .node import ( hex, ) from . import ( cmdutil, commands, context, dagparser, error, lock as lockmod, revlog, scmutil, simplemerge, ) release = lockmod.release # We reuse the command table from commands because it is easier than # teaching dispatch about multiple tables. command = cmdutil.command(commands.table) @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True) def debugancestor(ui, repo, *args): """find the ancestor revision of two revisions in a given index""" if len(args) == 3: index, rev1, rev2 = args r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index) lookup = r.lookup elif len(args) == 2: if not repo: raise error.Abort(_('there is no Mercurial repository here ' '(.hg not found)')) rev1, rev2 = args r = repo.changelog lookup = repo.lookup else: raise error.Abort(_('either two or three arguments required')) a = r.ancestor(lookup(rev1), lookup(rev2)) ui.write('%d:%s\n' % (r.rev(a), hex(a))) @command('debugbuilddag', [('m', 'mergeable-file', None, _('add single file mergeable changes')), ('o', 'overwritten-file', None, _('add single file all revs overwrite')), ('n', 'new-file', None, _('add new file at each rev'))], _('[OPTION]... [TEXT]')) def debugbuilddag(ui, repo, text=None, mergeable_file=False, overwritten_file=False, new_file=False): """builds a repo with a given DAG from scratch in the current empty repo The description of the DAG is read from stdin if not given on the command line. Elements: - "+n" is a linear run of n nodes based on the current default parent - "." is a single node based on the current default parent - "$" resets the default parent to null (implied at the start); otherwise the default parent is always the last node created - " 0: raise error.Abort(_('repository is not empty')) # determine number of revs in DAG total = 0 for type, data in dagparser.parsedag(text): if type == 'n': total += 1 if mergeable_file: linesperrev = 2 # make a file with k lines per rev initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)] initialmergedlines.append("") tags = [] wlock = lock = tr = None try: wlock = repo.wlock() lock = repo.lock() tr = repo.transaction("builddag") at = -1 atbranch = 'default' nodeids = [] id = 0 ui.progress(_('building'), id, unit=_('revisions'), total=total) for type, data in dagparser.parsedag(text): if type == 'n': ui.note(('node %s\n' % str(data))) id, ps = data files = [] fctxs = {} p2 = None if mergeable_file: fn = "mf" p1 = repo[ps[0]] if len(ps) > 1: p2 = repo[ps[1]] pa = p1.ancestor(p2) base, local, other = [x[fn].data() for x in (pa, p1, p2)] m3 = simplemerge.Merge3Text(base, local, other) ml = [l.strip() for l in m3.merge_lines()] ml.append("") elif at > 0: ml = p1[fn].data().split("\n") else: ml = initialmergedlines ml[id * linesperrev] += " r%i" % id mergedtext = "\n".join(ml) files.append(fn) fctxs[fn] = context.memfilectx(repo, fn, mergedtext) if overwritten_file: fn = "of" files.append(fn) fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id) if new_file: fn = "nf%i" % id files.append(fn) fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id) if len(ps) > 1: if not p2: p2 = repo[ps[1]] for fn in p2: if fn.startswith("nf"): files.append(fn) fctxs[fn] = p2[fn] def fctxfn(repo, cx, path): return fctxs.get(path) if len(ps) == 0 or ps[0] < 0: pars = [None, None] elif len(ps) == 1: pars = [nodeids[ps[0]], None] else: pars = [nodeids[p] for p in ps] cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn, date=(id, 0), user="debugbuilddag", extra={'branch': atbranch}) nodeid = repo.commitctx(cx) nodeids.append(nodeid) at = id elif type == 'l': id, name = data ui.note(('tag %s\n' % name)) tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name)) elif type == 'a': ui.note(('branch %s\n' % data)) atbranch = data ui.progress(_('building'), id, unit=_('revisions'), total=total) tr.close() if tags: repo.vfs.write("localtags", "".join(tags)) finally: ui.progress(_('building'), None) release(tr, lock, wlock)