# HG changeset patch # User Gregory Szorc <gregory.sz...@gmail.com> # Date 1478799942 28800 # Thu Nov 10 09:45:42 2016 -0800 # Node ID 6a4f8298893b2c6c98a2cae4ddb46a704545f7e1 # Parent 52e8ce0d0992ad87be2815bd7c5f0d92aab21851 debugcommands: move debugbuilddag
And we drop some now unused imports from commands.py. diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -30,17 +30,16 @@ from .node import ( ) from . import ( archival, bookmarks, bundle2, changegroup, cmdutil, commandserver, - context, copies, dagparser, dagutil, destutil, discovery, encoding, error, exchange, @@ -62,17 +61,16 @@ from . import ( policy, pvec, pycompat, repair, revlog, revset, scmutil, setdiscovery, - simplemerge, sshserver, sslutil, streamclone, templatekw, templater, treediscovery, ui as uimod, util, @@ -1862,168 +1860,16 @@ def copy(ui, repo, *pats, **opts): This command takes effect with the next commit. To undo a copy before that, see :hg:`revert`. Returns 0 on success, 1 if errors are encountered. """ with repo.wlock(False): return cmdutil.copy(ui, repo, pats, opts) -@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 - - "<p" sets the default parent to the backref p - - "*p" is a fork at parent p, which is a backref - - "*p1/p2" is a merge of parents p1 and p2, which are backrefs - - "/p2" is a merge of the preceding node and p2 - - ":tag" defines a local tag for the preceding node - - "@branch" sets the named branch for subsequent nodes - - "#...\\n" is a comment up to the end of the line - - Whitespace between the above elements is ignored. - - A backref is either - - - a number n, which references the node curr-n, where curr is the current - node, or - - the name of a local tag you placed earlier using ":tag", or - - empty to denote the default parent. - - All string valued-elements are either strictly alphanumeric, or must - be enclosed in double quotes ("..."), with "\\" as escape character. - """ - - if text is None: - ui.status(_("reading DAG from stdin\n")) - text = ui.fin.read() - - cl = repo.changelog - if len(cl) > 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) - @command('debugbundle', [('a', 'all', None, _('show all details')), ('', 'spec', None, _('print the bundlespec of the bundle'))], _('FILE'), norepo=True) def debugbundle(ui, bundlepath, all=None, spec=None, **opts): """lists the contents of a bundle""" with hg.openpath(ui, bundlepath) as f: diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -8,21 +8,27 @@ from __future__ import absolute_import import os from .i18n import _ 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: @@ -35,8 +41,160 @@ def debugancestor(ui, repo, *args): '(.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 + - "<p" sets the default parent to the backref p + - "*p" is a fork at parent p, which is a backref + - "*p1/p2" is a merge of parents p1 and p2, which are backrefs + - "/p2" is a merge of the preceding node and p2 + - ":tag" defines a local tag for the preceding node + - "@branch" sets the named branch for subsequent nodes + - "#...\\n" is a comment up to the end of the line + + Whitespace between the above elements is ignored. + + A backref is either + + - a number n, which references the node curr-n, where curr is the current + node, or + - the name of a local tag you placed earlier using ":tag", or + - empty to denote the default parent. + + All string valued-elements are either strictly alphanumeric, or must + be enclosed in double quotes ("..."), with "\\" as escape character. + """ + + if text is None: + ui.status(_("reading DAG from stdin\n")) + text = ui.fin.read() + + cl = repo.changelog + if len(cl) > 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) diff --git a/tests/test-ancestor.py b/tests/test-ancestor.py --- a/tests/test-ancestor.py +++ b/tests/test-ancestor.py @@ -7,16 +7,17 @@ import os import random import sys import time from mercurial.node import nullrev from mercurial import ( ancestor, commands, + debugcommands, hg, ui as uimod, util, ) def buildgraph(rng, nodes=100, rootprob=0.05, mergeprob=0.2, prevprob=0.7): '''nodes: total number of nodes in the graph rootprob: probability that a new node (not 0) will be a root @@ -221,17 +222,17 @@ def test_gca(): u = uimod.ui() for i, dag in enumerate(dagtests): repo = hg.repository(u, 'gca%d' % i, create=1) cl = repo.changelog if not util.safehasattr(cl.index, 'ancestors'): # C version not available return - commands.debugbuilddag(u, repo, dag) + debugcommands.debugbuilddag(u, repo, dag) # Compare the results of the Python and C versions. This does not # include choosing a winner when more than one gca exists -- we make # sure both return exactly the same set of gcas. for a in cl: for b in cl: cgcas = sorted(cl.index.ancestors(a, b)) pygcas = sorted(ancestor.ancestors(cl.parentrevs, a, b)) if cgcas != pygcas: _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel