Mercurial > hg
changeset 11337:0f3c8a47960e
debugbuilddag: build a changelog dag from a concise description
Useful in tests to quickly build a complex DAG in an empty repo.
Handles local tags and named branches.
Options to, at each rev,
- create a new file,
- overwrite the same file,
- append to the same file,
- write to a specific line in a mergeable file.
Can run shell commands during DAG buildup.
author | Peter Arrenbrecht <peter.arrenbrecht@gmail.com> |
---|---|
date | Thu, 10 Jun 2010 11:49:48 +0200 |
parents | 3dfbe26cfded |
children | 285bcf40e04b |
files | mercurial/commands.py tests/test-debugbuilddag tests/test-debugbuilddag.out tests/test-debugcomplete.out tests/test-doctest.py |
diffstat | 5 files changed, 470 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/commands.py Thu Jun 10 11:48:45 2010 +0200 +++ b/mercurial/commands.py Thu Jun 10 11:49:48 2010 +0200 @@ -849,6 +849,123 @@ a = r.ancestor(lookup(rev1), lookup(rev2)) ui.write("%d:%s\n" % (r.rev(a), hex(a))) +def debugbuilddag(ui, repo, text, + mergeable_file=False, + appended_file=False, + overwritten_file=False, + new_file=False): + """builds a repo with a given dag from scratch in the current empty repo + + 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 + - "!command" runs the command using your shell + - "!!my command\\n" is like "!", but to the end of the line + - "#...\\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. + + Note that the --overwritten-file and --appended-file options imply the + use of "HGMERGE=internal:local" during DAG buildup. + """ + + if not (mergeable_file or appended_file or overwritten_file or new_file): + raise Exception(_('need at least one of -m, -a, -o, -n')) + + if len(repo.changelog) > 0: + raise Exception(_('repository is not empty')) + + if overwritten_file or appended_file: + # we don't want to fail in merges during buildup + os.environ['HGMERGE'] = 'internal:local' + + def writefile(fname, text, fmode="w"): + f = open(fname, fmode) + try: + f.write(text) + finally: + f.close() + + if mergeable_file: + linesperrev = 2 + # determine number of revs in DAG + n = 0 + for type, data in dagparser.parsedag(text): + if type == 'n': + n += 1 + # make a file with k lines per rev + writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev)) + + "\n") + + at = -1 + atbranch = 'default' + for type, data in dagparser.parsedag(text): + if type == 'n': + ui.status('node %s\n' % format(data)) + id, ps = data + p1 = ps[0] + if p1 != at: + update(ui, repo, node=p1, clean=True) + at = p1 + if repo.dirstate.branch() != atbranch: + branch(ui, repo, atbranch, force=True) + if len(ps) > 1: + p2 = ps[1] + merge(ui, repo, node=p2) + + if mergeable_file: + f = open("mf", "r+") + try: + lines = f.read().split("\n") + lines[id * linesperrev] += " r%i" % id + f.seek(0) + f.write("\n".join(lines)) + finally: + f.close() + + if appended_file: + writefile("af", "r%i\n" % id, "a") + + if overwritten_file: + writefile("of", "r%i\n" % id) + + if new_file: + writefile("nf%i" % id, "r%i\n" % id) + + commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0)) + at = id + elif type == 'l': + id, name = data + ui.status('tag %s\n' % name) + tag(ui, repo, name, local=True) + elif type == 'a': + ui.status('branch %s\n' % data) + atbranch = data + elif type in 'cC': + r = util.system(data, cwd=repo.root) + if r: + desc, r = util.explain_exit(r) + raise util.Abort(_('%s command %s') % (data, desc)) + def debugcommands(ui, cmd='', *args): """list all available commands and options""" for cmd, vals in sorted(table.iteritems()): @@ -3923,6 +4040,14 @@ ] + walkopts + dryrunopts, _('[OPTION]... [SOURCE]... DEST')), "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')), + "debugbuilddag": + (debugbuilddag, + [('m', 'mergeable-file', None, _('add single file mergeable changes')), + ('a', 'appended-file', None, _('add single file all revs append to')), + ('o', 'overwritten-file', None, _('add single file all revs overwrite')), + ('n', 'new-file', None, _('add new file at each rev')), + ], + _('[OPTION]... TEXT')), "debugcheckstate": (debugcheckstate, [], ''), "debugcommands": (debugcommands, [], _('[COMMAND]')), "debugcomplete":
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-debugbuilddag Thu Jun 10 11:49:48 2010 +0200 @@ -0,0 +1,70 @@ +#! /bin/sh + +echo "[extensions]" >> $HGRCPATH +echo "graphlog=" >> $HGRCPATH + + + +echo ---- overwritten and appended files + +rm -rf repo +hg init repo +cd repo +hg debugbuilddag '+2:f +3:p2 @temp <f+4 @default /p2 +2' -q -oa +echo -- dag +hg debugdag -t -b +echo -- glog +hg glog --template '{rev}: {desc} [{branches}] @ {date}\n' +echo -- glog of +hg glog --template '{rev}: {desc} [{branches}]\n' of +echo -- glog af +hg glog --template '{rev}: {desc} [{branches}]\n' af +echo -- tags +hg tags -v +echo -- cat of +hg cat of +echo -- cat af +hg cat af +cd .. + +echo ---- new and mergeable files + +rm -rf repo +hg init repo +cd repo +hg debugbuilddag '+2:f +3:p2 @temp <f+4 @default /p2 +2' -q -mn +echo -- dag +hg debugdag -t -b +echo -- glog +hg glog --template '{rev}: {desc} [{branches}] @ {date}\n' +echo -- glog mf +hg glog --template '{rev}: {desc} [{branches}]\n' mf + +echo -- man r4 +hg manifest -r4 +echo -- cat r4 mf +hg cat -r4 mf +echo -- man r8 +hg manifest -r8 +echo -- cat r8 mf +hg cat -r8 mf +echo -- man +hg manifest +echo -- cat mf +hg cat mf +cd .. + +echo ---- command + +rm -rf repo +hg init repo +cd repo +hg debugbuilddag '+2 !"touch X" +2' -q -o +echo -- dag +hg debugdag -t -b +echo -- glog +hg glog --template '{rev}: {desc} [{branches}]\n' +echo -- glog X +hg glog --template '{rev}: {desc} [{branches}]\n' X +cd .. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-debugbuilddag.out Thu Jun 10 11:49:48 2010 +0200 @@ -0,0 +1,272 @@ +---- overwritten and appended files +-- dag ++2:f ++3:p2 +@temp*f+3 +@default*/p2+2:tip +-- glog +@ 11: r11 [] @ 11.00 +| +o 10: r10 [] @ 10.00 +| +o 9: r9 [] @ 9.00 +|\ +| o 8: r8 [temp] @ 8.00 +| | +| o 7: r7 [temp] @ 7.00 +| | +| o 6: r6 [temp] @ 6.00 +| | +| o 5: r5 [temp] @ 5.00 +| | +o | 4: r4 [] @ 4.00 +| | +o | 3: r3 [] @ 3.00 +| | +o | 2: r2 [] @ 2.00 +|/ +o 1: r1 [] @ 1.00 +| +o 0: r0 [] @ 0.00 + +-- glog of +@ 11: r11 [] +| +o 10: r10 [] +| +o 9: r9 [] +|\ +| o 8: r8 [temp] +| | +| o 7: r7 [temp] +| | +| o 6: r6 [temp] +| | +| o 5: r5 [temp] +| | +o | 4: r4 [] +| | +o | 3: r3 [] +| | +o | 2: r2 [] +|/ +o 1: r1 [] +| +o 0: r0 [] + +-- glog af +@ 11: r11 [] +| +o 10: r10 [] +| +o 9: r9 [] +|\ +| o 8: r8 [temp] +| | +| o 7: r7 [temp] +| | +| o 6: r6 [temp] +| | +| o 5: r5 [temp] +| | +o | 4: r4 [] +| | +o | 3: r3 [] +| | +o | 2: r2 [] +|/ +o 1: r1 [] +| +o 0: r0 [] + +-- tags +tip 11:f96e381c614c +p2 4:d9d6db981b55 local +f 1:73253def624e local +-- cat of +r11 +-- cat af +r0 +r1 +r5 +r6 +r7 +r8 +r9 +r10 +r11 +---- new and mergeable files +-- dag ++2:f ++3:p2 +@temp*f+3 +@default*/p2+2:tip +-- glog +@ 11: r11 [] @ 11.00 +| +o 10: r10 [] @ 10.00 +| +o 9: r9 [] @ 9.00 +|\ +| o 8: r8 [temp] @ 8.00 +| | +| o 7: r7 [temp] @ 7.00 +| | +| o 6: r6 [temp] @ 6.00 +| | +| o 5: r5 [temp] @ 5.00 +| | +o | 4: r4 [] @ 4.00 +| | +o | 3: r3 [] @ 3.00 +| | +o | 2: r2 [] @ 2.00 +|/ +o 1: r1 [] @ 1.00 +| +o 0: r0 [] @ 0.00 + +-- glog mf +@ 11: r11 [] +| +o 10: r10 [] +| +o 9: r9 [] +|\ +| o 8: r8 [temp] +| | +| o 7: r7 [temp] +| | +| o 6: r6 [temp] +| | +| o 5: r5 [temp] +| | +o | 4: r4 [] +| | +o | 3: r3 [] +| | +o | 2: r2 [] +|/ +o 1: r1 [] +| +o 0: r0 [] + +-- man r4 +mf +nf0 +nf1 +nf2 +nf3 +nf4 +-- cat r4 mf +0 r0 +1 +2 r1 +3 +4 r2 +5 +6 r3 +7 +8 r4 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +-- man r8 +mf +nf0 +nf1 +nf5 +nf6 +nf7 +nf8 +-- cat r8 mf +0 r0 +1 +2 r1 +3 +4 +5 +6 +7 +8 +9 +10 r5 +11 +12 r6 +13 +14 r7 +15 +16 r8 +17 +18 +19 +20 +21 +22 +23 +-- man +mf +nf0 +nf1 +nf10 +nf11 +nf2 +nf3 +nf4 +nf5 +nf6 +nf7 +nf8 +nf9 +-- cat mf +0 r0 +1 +2 r1 +3 +4 r2 +5 +6 r3 +7 +8 r4 +9 +10 r5 +11 +12 r6 +13 +14 r7 +15 +16 r8 +17 +18 r9 +19 +20 r10 +21 +22 r11 +23 +---- command +-- dag ++4:tip +-- glog +@ 3: r3 [] +| +o 2: r2 [] +| +o 1: r1 [] +| +o 0: r0 [] + +-- glog X +o 2: r2 [] +
--- a/tests/test-debugcomplete.out Thu Jun 10 11:48:45 2010 +0200 +++ b/tests/test-debugcomplete.out Thu Jun 10 11:49:48 2010 +0200 @@ -61,6 +61,7 @@ % Show debug commands if there are no other candidates debugancestor +debugbuilddag debugcheckstate debugcommands debugcomplete @@ -192,6 +193,7 @@ cat: output, rev, decode, include, exclude copy: after, force, include, exclude, dry-run debugancestor: +debugbuilddag: mergeable-file, appended-file, overwritten-file, new-file debugcheckstate: debugcommands: debugcomplete: options
--- a/tests/test-doctest.py Thu Jun 10 11:48:45 2010 +0200 +++ b/tests/test-doctest.py Thu Jun 10 11:49:48 2010 +0200 @@ -16,7 +16,7 @@ doctest.testmod(mercurial.util) import mercurial.dagparser -doctest.testmod(mercurial.dagparser) +doctest.testmod(mercurial.dagparser, optionflags=doctest.NORMALIZE_WHITESPACE) import hgext.convert.cvsps doctest.testmod(hgext.convert.cvsps)