Mercurial > hg
comparison mercurial/commands.py @ 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 |
comparison
equal
deleted
inserted
replaced
11336:3dfbe26cfded | 11337:0f3c8a47960e |
---|---|
846 lookup = repo.lookup | 846 lookup = repo.lookup |
847 else: | 847 else: |
848 raise util.Abort(_('either two or three arguments required')) | 848 raise util.Abort(_('either two or three arguments required')) |
849 a = r.ancestor(lookup(rev1), lookup(rev2)) | 849 a = r.ancestor(lookup(rev1), lookup(rev2)) |
850 ui.write("%d:%s\n" % (r.rev(a), hex(a))) | 850 ui.write("%d:%s\n" % (r.rev(a), hex(a))) |
851 | |
852 def debugbuilddag(ui, repo, text, | |
853 mergeable_file=False, | |
854 appended_file=False, | |
855 overwritten_file=False, | |
856 new_file=False): | |
857 """builds a repo with a given dag from scratch in the current empty repo | |
858 | |
859 Elements: | |
860 | |
861 - "+n" is a linear run of n nodes based on the current default parent | |
862 - "." is a single node based on the current default parent | |
863 - "$" resets the default parent to null (implied at the start); | |
864 otherwise the default parent is always the last node created | |
865 - "<p" sets the default parent to the backref p | |
866 - "*p" is a fork at parent p, which is a backref | |
867 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs | |
868 - "/p2" is a merge of the preceding node and p2 | |
869 - ":tag" defines a local tag for the preceding node | |
870 - "@branch" sets the named branch for subsequent nodes | |
871 - "!command" runs the command using your shell | |
872 - "!!my command\\n" is like "!", but to the end of the line | |
873 - "#...\\n" is a comment up to the end of the line | |
874 | |
875 Whitespace between the above elements is ignored. | |
876 | |
877 A backref is either | |
878 | |
879 - a number n, which references the node curr-n, where curr is the current | |
880 node, or | |
881 - the name of a local tag you placed earlier using ":tag", or | |
882 - empty to denote the default parent. | |
883 | |
884 All string valued-elements are either strictly alphanumeric, or must | |
885 be enclosed in double quotes ("..."), with "\" as escape character. | |
886 | |
887 Note that the --overwritten-file and --appended-file options imply the | |
888 use of "HGMERGE=internal:local" during DAG buildup. | |
889 """ | |
890 | |
891 if not (mergeable_file or appended_file or overwritten_file or new_file): | |
892 raise Exception(_('need at least one of -m, -a, -o, -n')) | |
893 | |
894 if len(repo.changelog) > 0: | |
895 raise Exception(_('repository is not empty')) | |
896 | |
897 if overwritten_file or appended_file: | |
898 # we don't want to fail in merges during buildup | |
899 os.environ['HGMERGE'] = 'internal:local' | |
900 | |
901 def writefile(fname, text, fmode="w"): | |
902 f = open(fname, fmode) | |
903 try: | |
904 f.write(text) | |
905 finally: | |
906 f.close() | |
907 | |
908 if mergeable_file: | |
909 linesperrev = 2 | |
910 # determine number of revs in DAG | |
911 n = 0 | |
912 for type, data in dagparser.parsedag(text): | |
913 if type == 'n': | |
914 n += 1 | |
915 # make a file with k lines per rev | |
916 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev)) | |
917 + "\n") | |
918 | |
919 at = -1 | |
920 atbranch = 'default' | |
921 for type, data in dagparser.parsedag(text): | |
922 if type == 'n': | |
923 ui.status('node %s\n' % format(data)) | |
924 id, ps = data | |
925 p1 = ps[0] | |
926 if p1 != at: | |
927 update(ui, repo, node=p1, clean=True) | |
928 at = p1 | |
929 if repo.dirstate.branch() != atbranch: | |
930 branch(ui, repo, atbranch, force=True) | |
931 if len(ps) > 1: | |
932 p2 = ps[1] | |
933 merge(ui, repo, node=p2) | |
934 | |
935 if mergeable_file: | |
936 f = open("mf", "r+") | |
937 try: | |
938 lines = f.read().split("\n") | |
939 lines[id * linesperrev] += " r%i" % id | |
940 f.seek(0) | |
941 f.write("\n".join(lines)) | |
942 finally: | |
943 f.close() | |
944 | |
945 if appended_file: | |
946 writefile("af", "r%i\n" % id, "a") | |
947 | |
948 if overwritten_file: | |
949 writefile("of", "r%i\n" % id) | |
950 | |
951 if new_file: | |
952 writefile("nf%i" % id, "r%i\n" % id) | |
953 | |
954 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0)) | |
955 at = id | |
956 elif type == 'l': | |
957 id, name = data | |
958 ui.status('tag %s\n' % name) | |
959 tag(ui, repo, name, local=True) | |
960 elif type == 'a': | |
961 ui.status('branch %s\n' % data) | |
962 atbranch = data | |
963 elif type in 'cC': | |
964 r = util.system(data, cwd=repo.root) | |
965 if r: | |
966 desc, r = util.explain_exit(r) | |
967 raise util.Abort(_('%s command %s') % (data, desc)) | |
851 | 968 |
852 def debugcommands(ui, cmd='', *args): | 969 def debugcommands(ui, cmd='', *args): |
853 """list all available commands and options""" | 970 """list all available commands and options""" |
854 for cmd, vals in sorted(table.iteritems()): | 971 for cmd, vals in sorted(table.iteritems()): |
855 cmd = cmd.split('|')[0].strip('^') | 972 cmd = cmd.split('|')[0].strip('^') |
3921 ('f', 'force', None, | 4038 ('f', 'force', None, |
3922 _('forcibly copy over an existing managed file')), | 4039 _('forcibly copy over an existing managed file')), |
3923 ] + walkopts + dryrunopts, | 4040 ] + walkopts + dryrunopts, |
3924 _('[OPTION]... [SOURCE]... DEST')), | 4041 _('[OPTION]... [SOURCE]... DEST')), |
3925 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')), | 4042 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')), |
4043 "debugbuilddag": | |
4044 (debugbuilddag, | |
4045 [('m', 'mergeable-file', None, _('add single file mergeable changes')), | |
4046 ('a', 'appended-file', None, _('add single file all revs append to')), | |
4047 ('o', 'overwritten-file', None, _('add single file all revs overwrite')), | |
4048 ('n', 'new-file', None, _('add new file at each rev')), | |
4049 ], | |
4050 _('[OPTION]... TEXT')), | |
3926 "debugcheckstate": (debugcheckstate, [], ''), | 4051 "debugcheckstate": (debugcheckstate, [], ''), |
3927 "debugcommands": (debugcommands, [], _('[COMMAND]')), | 4052 "debugcommands": (debugcommands, [], _('[COMMAND]')), |
3928 "debugcomplete": | 4053 "debugcomplete": |
3929 (debugcomplete, | 4054 (debugcomplete, |
3930 [('o', 'options', None, _('show the command options'))], | 4055 [('o', 'options', None, _('show the command options'))], |