##// END OF EJS Templates
check-code: verify that 'saved backup bundle to ...' is '(glob)'ed...
Mads Kiilerich -
r17111:bddf1220 default
parent child Browse files
Show More
@@ -1,447 +1,449 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # check-code - a style and portability checker for Mercurial
3 # check-code - a style and portability checker for Mercurial
4 #
4 #
5 # Copyright 2010 Matt Mackall <mpm@selenic.com>
5 # Copyright 2010 Matt Mackall <mpm@selenic.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 import re, glob, os, sys
10 import re, glob, os, sys
11 import keyword
11 import keyword
12 import optparse
12 import optparse
13
13
14 def repquote(m):
14 def repquote(m):
15 t = re.sub(r"\w", "x", m.group('text'))
15 t = re.sub(r"\w", "x", m.group('text'))
16 t = re.sub(r"[^\s\nx]", "o", t)
16 t = re.sub(r"[^\s\nx]", "o", t)
17 return m.group('quote') + t + m.group('quote')
17 return m.group('quote') + t + m.group('quote')
18
18
19 def reppython(m):
19 def reppython(m):
20 comment = m.group('comment')
20 comment = m.group('comment')
21 if comment:
21 if comment:
22 return "#" * len(comment)
22 return "#" * len(comment)
23 return repquote(m)
23 return repquote(m)
24
24
25 def repcomment(m):
25 def repcomment(m):
26 return m.group(1) + "#" * len(m.group(2))
26 return m.group(1) + "#" * len(m.group(2))
27
27
28 def repccomment(m):
28 def repccomment(m):
29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
30 return m.group(1) + t + "*/"
30 return m.group(1) + t + "*/"
31
31
32 def repcallspaces(m):
32 def repcallspaces(m):
33 t = re.sub(r"\n\s+", "\n", m.group(2))
33 t = re.sub(r"\n\s+", "\n", m.group(2))
34 return m.group(1) + t
34 return m.group(1) + t
35
35
36 def repinclude(m):
36 def repinclude(m):
37 return m.group(1) + "<foo>"
37 return m.group(1) + "<foo>"
38
38
39 def rephere(m):
39 def rephere(m):
40 t = re.sub(r"\S", "x", m.group(2))
40 t = re.sub(r"\S", "x", m.group(2))
41 return m.group(1) + t
41 return m.group(1) + t
42
42
43
43
44 testpats = [
44 testpats = [
45 [
45 [
46 (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
46 (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
47 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
47 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
48 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
48 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
49 (r'sed.*-i', "don't use 'sed -i', use a temporary file"),
49 (r'sed.*-i', "don't use 'sed -i', use a temporary file"),
50 (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"),
50 (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"),
51 (r'echo -n', "don't use 'echo -n', use printf"),
51 (r'echo -n', "don't use 'echo -n', use printf"),
52 (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
52 (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
53 (r'head -c', "don't use 'head -c', use 'dd'"),
53 (r'head -c', "don't use 'head -c', use 'dd'"),
54 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
54 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
55 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
55 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
56 (r'printf.*\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"),
56 (r'printf.*\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"),
57 (r'printf.*\\x', "don't use printf \\x, use Python"),
57 (r'printf.*\\x', "don't use printf \\x, use Python"),
58 (r'\$\(.*\)', "don't use $(expr), use `expr`"),
58 (r'\$\(.*\)', "don't use $(expr), use `expr`"),
59 (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
59 (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
60 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
60 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
61 "use egrep for extended grep syntax"),
61 "use egrep for extended grep syntax"),
62 (r'/bin/', "don't use explicit paths for tools"),
62 (r'/bin/', "don't use explicit paths for tools"),
63 (r'[^\n]\Z', "no trailing newline"),
63 (r'[^\n]\Z', "no trailing newline"),
64 (r'export.*=', "don't export and assign at once"),
64 (r'export.*=', "don't export and assign at once"),
65 (r'^source\b', "don't use 'source', use '.'"),
65 (r'^source\b', "don't use 'source', use '.'"),
66 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
66 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
67 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
67 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
68 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
68 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
69 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
69 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
70 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
70 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
71 (r'^alias\b.*=', "don't use alias, use a function"),
71 (r'^alias\b.*=', "don't use alias, use a function"),
72 (r'if\s*!', "don't use '!' to negate exit status"),
72 (r'if\s*!', "don't use '!' to negate exit status"),
73 (r'/dev/u?random', "don't use entropy, use /dev/zero"),
73 (r'/dev/u?random', "don't use entropy, use /dev/zero"),
74 (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"),
74 (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"),
75 (r'^( *)\t', "don't use tabs to indent"),
75 (r'^( *)\t', "don't use tabs to indent"),
76 ],
76 ],
77 # warnings
77 # warnings
78 [
78 [
79 (r'^function', "don't use 'function', use old style"),
79 (r'^function', "don't use 'function', use old style"),
80 (r'^diff.*-\w*N', "don't use 'diff -N'"),
80 (r'^diff.*-\w*N', "don't use 'diff -N'"),
81 (r'\$PWD', "don't use $PWD, use `pwd`"),
81 (r'\$PWD', "don't use $PWD, use `pwd`"),
82 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
82 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
83 ]
83 ]
84 ]
84 ]
85
85
86 testfilters = [
86 testfilters = [
87 (r"( *)(#([^\n]*\S)?)", repcomment),
87 (r"( *)(#([^\n]*\S)?)", repcomment),
88 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
88 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
89 ]
89 ]
90
90
91 uprefix = r"^ \$ "
91 uprefix = r"^ \$ "
92 utestpats = [
92 utestpats = [
93 [
93 [
94 (r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"),
94 (r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"),
95 (uprefix + r'.*\|\s*sed[^|>\n]*\n',
95 (uprefix + r'.*\|\s*sed[^|>\n]*\n',
96 "use regex test output patterns instead of sed"),
96 "use regex test output patterns instead of sed"),
97 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
97 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
98 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
98 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
99 (uprefix + r'.*\|\| echo.*(fail|error)',
99 (uprefix + r'.*\|\| echo.*(fail|error)',
100 "explicit exit code checks unnecessary"),
100 "explicit exit code checks unnecessary"),
101 (uprefix + r'set -e', "don't use set -e"),
101 (uprefix + r'set -e', "don't use set -e"),
102 (uprefix + r'\s', "don't indent commands, use > for continued lines"),
102 (uprefix + r'\s', "don't indent commands, use > for continued lines"),
103 (r'^ saved backup bundle to \$TESTTMP.*\.hg$',
104 "use (glob) to match Windows paths too"),
103 ],
105 ],
104 # warnings
106 # warnings
105 []
107 []
106 ]
108 ]
107
109
108 for i in [0, 1]:
110 for i in [0, 1]:
109 for p, m in testpats[i]:
111 for p, m in testpats[i]:
110 if p.startswith(r'^'):
112 if p.startswith(r'^'):
111 p = r"^ [$>] (%s)" % p[1:]
113 p = r"^ [$>] (%s)" % p[1:]
112 else:
114 else:
113 p = r"^ [$>] .*(%s)" % p
115 p = r"^ [$>] .*(%s)" % p
114 utestpats[i].append((p, m))
116 utestpats[i].append((p, m))
115
117
116 utestfilters = [
118 utestfilters = [
117 (r"( *)(#([^\n]*\S)?)", repcomment),
119 (r"( *)(#([^\n]*\S)?)", repcomment),
118 ]
120 ]
119
121
120 pypats = [
122 pypats = [
121 [
123 [
122 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
124 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
123 "tuple parameter unpacking not available in Python 3+"),
125 "tuple parameter unpacking not available in Python 3+"),
124 (r'lambda\s*\(.*,.*\)',
126 (r'lambda\s*\(.*,.*\)',
125 "tuple parameter unpacking not available in Python 3+"),
127 "tuple parameter unpacking not available in Python 3+"),
126 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
128 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
127 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
129 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
128 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
130 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
129 (r'^\s*\t', "don't use tabs"),
131 (r'^\s*\t', "don't use tabs"),
130 (r'\S;\s*\n', "semicolon"),
132 (r'\S;\s*\n', "semicolon"),
131 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
133 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
132 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
134 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
133 (r'\w,\w', "missing whitespace after ,"),
135 (r'\w,\w', "missing whitespace after ,"),
134 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
136 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
135 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
137 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
136 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
138 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
137 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Py2.4'),
139 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Py2.4'),
138 (r'.{81}', "line too long"),
140 (r'.{81}', "line too long"),
139 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
141 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
140 (r'[^\n]\Z', "no trailing newline"),
142 (r'[^\n]\Z', "no trailing newline"),
141 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
143 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
142 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
144 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
143 # "don't use underbars in identifiers"),
145 # "don't use underbars in identifiers"),
144 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
146 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
145 "don't use camelcase in identifiers"),
147 "don't use camelcase in identifiers"),
146 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
148 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
147 "linebreak after :"),
149 "linebreak after :"),
148 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
150 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
149 (r'class\s[^( \n]+\(\):',
151 (r'class\s[^( \n]+\(\):',
150 "class foo() not available in Python 2.4, use class foo(object)"),
152 "class foo() not available in Python 2.4, use class foo(object)"),
151 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
153 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
152 "Python keyword is not a function"),
154 "Python keyword is not a function"),
153 (r',]', "unneeded trailing ',' in list"),
155 (r',]', "unneeded trailing ',' in list"),
154 # (r'class\s[A-Z][^\(]*\((?!Exception)',
156 # (r'class\s[A-Z][^\(]*\((?!Exception)',
155 # "don't capitalize non-exception classes"),
157 # "don't capitalize non-exception classes"),
156 # (r'in range\(', "use xrange"),
158 # (r'in range\(', "use xrange"),
157 # (r'^\s*print\s+', "avoid using print in core and extensions"),
159 # (r'^\s*print\s+', "avoid using print in core and extensions"),
158 (r'[\x80-\xff]', "non-ASCII character literal"),
160 (r'[\x80-\xff]', "non-ASCII character literal"),
159 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
161 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
160 (r'^\s*with\s+', "with not available in Python 2.4"),
162 (r'^\s*with\s+', "with not available in Python 2.4"),
161 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
163 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
162 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
164 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
163 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
165 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
164 (r'(?<!def)\s+(any|all|format)\(',
166 (r'(?<!def)\s+(any|all|format)\(',
165 "any/all/format not available in Python 2.4"),
167 "any/all/format not available in Python 2.4"),
166 (r'(?<!def)\s+(callable)\(',
168 (r'(?<!def)\s+(callable)\(',
167 "callable not available in Python 3, use getattr(f, '__call__', None)"),
169 "callable not available in Python 3, use getattr(f, '__call__', None)"),
168 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
170 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
169 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
171 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
170 "gratuitous whitespace after Python keyword"),
172 "gratuitous whitespace after Python keyword"),
171 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
173 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
172 # (r'\s\s=', "gratuitous whitespace before ="),
174 # (r'\s\s=', "gratuitous whitespace before ="),
173 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
175 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
174 "missing whitespace around operator"),
176 "missing whitespace around operator"),
175 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s',
177 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s',
176 "missing whitespace around operator"),
178 "missing whitespace around operator"),
177 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
179 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
178 "missing whitespace around operator"),
180 "missing whitespace around operator"),
179 (r'[^^+=*/!<>&| -](\s=|=\s)[^= ]',
181 (r'[^^+=*/!<>&| -](\s=|=\s)[^= ]',
180 "wrong whitespace around ="),
182 "wrong whitespace around ="),
181 (r'raise Exception', "don't raise generic exceptions"),
183 (r'raise Exception', "don't raise generic exceptions"),
182 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
184 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
183 (r' [=!]=\s+(True|False|None)',
185 (r' [=!]=\s+(True|False|None)',
184 "comparison with singleton, use 'is' or 'is not' instead"),
186 "comparison with singleton, use 'is' or 'is not' instead"),
185 (r'^\s*(while|if) [01]:',
187 (r'^\s*(while|if) [01]:',
186 "use True/False for constant Boolean expression"),
188 "use True/False for constant Boolean expression"),
187 (r'(?:(?<!def)\s+|\()hasattr',
189 (r'(?:(?<!def)\s+|\()hasattr',
188 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
190 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
189 (r'opener\([^)]*\).read\(',
191 (r'opener\([^)]*\).read\(',
190 "use opener.read() instead"),
192 "use opener.read() instead"),
191 (r'BaseException', 'not in Py2.4, use Exception'),
193 (r'BaseException', 'not in Py2.4, use Exception'),
192 (r'os\.path\.relpath', 'os.path.relpath is not in Py2.5'),
194 (r'os\.path\.relpath', 'os.path.relpath is not in Py2.5'),
193 (r'opener\([^)]*\).write\(',
195 (r'opener\([^)]*\).write\(',
194 "use opener.write() instead"),
196 "use opener.write() instead"),
195 (r'[\s\(](open|file)\([^)]*\)\.read\(',
197 (r'[\s\(](open|file)\([^)]*\)\.read\(',
196 "use util.readfile() instead"),
198 "use util.readfile() instead"),
197 (r'[\s\(](open|file)\([^)]*\)\.write\(',
199 (r'[\s\(](open|file)\([^)]*\)\.write\(',
198 "use util.readfile() instead"),
200 "use util.readfile() instead"),
199 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
201 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
200 "always assign an opened file to a variable, and close it afterwards"),
202 "always assign an opened file to a variable, and close it afterwards"),
201 (r'[\s\(](open|file)\([^)]*\)\.',
203 (r'[\s\(](open|file)\([^)]*\)\.',
202 "always assign an opened file to a variable, and close it afterwards"),
204 "always assign an opened file to a variable, and close it afterwards"),
203 (r'(?i)descendent', "the proper spelling is descendAnt"),
205 (r'(?i)descendent', "the proper spelling is descendAnt"),
204 (r'\.debug\(\_', "don't mark debug messages for translation"),
206 (r'\.debug\(\_', "don't mark debug messages for translation"),
205 (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
207 (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
206 (r'^\s*except\s*:', "warning: naked except clause", r'#.*re-raises'),
208 (r'^\s*except\s*:', "warning: naked except clause", r'#.*re-raises'),
207 ],
209 ],
208 # warnings
210 # warnings
209 [
211 [
210 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
212 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
211 "warning: unwrapped ui message"),
213 "warning: unwrapped ui message"),
212 ]
214 ]
213 ]
215 ]
214
216
215 pyfilters = [
217 pyfilters = [
216 (r"""(?msx)(?P<comment>\#.*?$)|
218 (r"""(?msx)(?P<comment>\#.*?$)|
217 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
219 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
218 (?P<text>(([^\\]|\\.)*?))
220 (?P<text>(([^\\]|\\.)*?))
219 (?P=quote))""", reppython),
221 (?P=quote))""", reppython),
220 ]
222 ]
221
223
222 cpats = [
224 cpats = [
223 [
225 [
224 (r'//', "don't use //-style comments"),
226 (r'//', "don't use //-style comments"),
225 (r'^ ', "don't use spaces to indent"),
227 (r'^ ', "don't use spaces to indent"),
226 (r'\S\t', "don't use tabs except for indent"),
228 (r'\S\t', "don't use tabs except for indent"),
227 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
229 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
228 (r'.{81}', "line too long"),
230 (r'.{81}', "line too long"),
229 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
231 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
230 (r'return\(', "return is not a function"),
232 (r'return\(', "return is not a function"),
231 (r' ;', "no space before ;"),
233 (r' ;', "no space before ;"),
232 (r'\w+\* \w+', "use int *foo, not int* foo"),
234 (r'\w+\* \w+', "use int *foo, not int* foo"),
233 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
235 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
234 (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
236 (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
235 (r'\w,\w', "missing whitespace after ,"),
237 (r'\w,\w', "missing whitespace after ,"),
236 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
238 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
237 (r'^#\s+\w', "use #foo, not # foo"),
239 (r'^#\s+\w', "use #foo, not # foo"),
238 (r'[^\n]\Z', "no trailing newline"),
240 (r'[^\n]\Z', "no trailing newline"),
239 (r'^\s*#import\b', "use only #include in standard C code"),
241 (r'^\s*#import\b', "use only #include in standard C code"),
240 ],
242 ],
241 # warnings
243 # warnings
242 []
244 []
243 ]
245 ]
244
246
245 cfilters = [
247 cfilters = [
246 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
248 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
247 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
249 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
248 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
250 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
249 (r'(\()([^)]+\))', repcallspaces),
251 (r'(\()([^)]+\))', repcallspaces),
250 ]
252 ]
251
253
252 inutilpats = [
254 inutilpats = [
253 [
255 [
254 (r'\bui\.', "don't use ui in util"),
256 (r'\bui\.', "don't use ui in util"),
255 ],
257 ],
256 # warnings
258 # warnings
257 []
259 []
258 ]
260 ]
259
261
260 inrevlogpats = [
262 inrevlogpats = [
261 [
263 [
262 (r'\brepo\.', "don't use repo in revlog"),
264 (r'\brepo\.', "don't use repo in revlog"),
263 ],
265 ],
264 # warnings
266 # warnings
265 []
267 []
266 ]
268 ]
267
269
268 checks = [
270 checks = [
269 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
271 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
270 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
272 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
271 ('c', r'.*\.c$', cfilters, cpats),
273 ('c', r'.*\.c$', cfilters, cpats),
272 ('unified test', r'.*\.t$', utestfilters, utestpats),
274 ('unified test', r'.*\.t$', utestfilters, utestpats),
273 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
275 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
274 inrevlogpats),
276 inrevlogpats),
275 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
277 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
276 inutilpats),
278 inutilpats),
277 ]
279 ]
278
280
279 class norepeatlogger(object):
281 class norepeatlogger(object):
280 def __init__(self):
282 def __init__(self):
281 self._lastseen = None
283 self._lastseen = None
282
284
283 def log(self, fname, lineno, line, msg, blame):
285 def log(self, fname, lineno, line, msg, blame):
284 """print error related a to given line of a given file.
286 """print error related a to given line of a given file.
285
287
286 The faulty line will also be printed but only once in the case
288 The faulty line will also be printed but only once in the case
287 of multiple errors.
289 of multiple errors.
288
290
289 :fname: filename
291 :fname: filename
290 :lineno: line number
292 :lineno: line number
291 :line: actual content of the line
293 :line: actual content of the line
292 :msg: error message
294 :msg: error message
293 """
295 """
294 msgid = fname, lineno, line
296 msgid = fname, lineno, line
295 if msgid != self._lastseen:
297 if msgid != self._lastseen:
296 if blame:
298 if blame:
297 print "%s:%d (%s):" % (fname, lineno, blame)
299 print "%s:%d (%s):" % (fname, lineno, blame)
298 else:
300 else:
299 print "%s:%d:" % (fname, lineno)
301 print "%s:%d:" % (fname, lineno)
300 print " > %s" % line
302 print " > %s" % line
301 self._lastseen = msgid
303 self._lastseen = msgid
302 print " " + msg
304 print " " + msg
303
305
304 _defaultlogger = norepeatlogger()
306 _defaultlogger = norepeatlogger()
305
307
306 def getblame(f):
308 def getblame(f):
307 lines = []
309 lines = []
308 for l in os.popen('hg annotate -un %s' % f):
310 for l in os.popen('hg annotate -un %s' % f):
309 start, line = l.split(':', 1)
311 start, line = l.split(':', 1)
310 user, rev = start.split()
312 user, rev = start.split()
311 lines.append((line[1:-1], user, rev))
313 lines.append((line[1:-1], user, rev))
312 return lines
314 return lines
313
315
314 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
316 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
315 blame=False, debug=False, lineno=True):
317 blame=False, debug=False, lineno=True):
316 """checks style and portability of a given file
318 """checks style and portability of a given file
317
319
318 :f: filepath
320 :f: filepath
319 :logfunc: function used to report error
321 :logfunc: function used to report error
320 logfunc(filename, linenumber, linecontent, errormessage)
322 logfunc(filename, linenumber, linecontent, errormessage)
321 :maxerr: number of error to display before arborting.
323 :maxerr: number of error to display before arborting.
322 Set to false (default) to report all errors
324 Set to false (default) to report all errors
323
325
324 return True if no error is found, False otherwise.
326 return True if no error is found, False otherwise.
325 """
327 """
326 blamecache = None
328 blamecache = None
327 result = True
329 result = True
328 for name, match, filters, pats in checks:
330 for name, match, filters, pats in checks:
329 if debug:
331 if debug:
330 print name, f
332 print name, f
331 fc = 0
333 fc = 0
332 if not re.match(match, f):
334 if not re.match(match, f):
333 if debug:
335 if debug:
334 print "Skipping %s for %s it doesn't match %s" % (
336 print "Skipping %s for %s it doesn't match %s" % (
335 name, match, f)
337 name, match, f)
336 continue
338 continue
337 fp = open(f)
339 fp = open(f)
338 pre = post = fp.read()
340 pre = post = fp.read()
339 fp.close()
341 fp.close()
340 if "no-" + "check-code" in pre:
342 if "no-" + "check-code" in pre:
341 if debug:
343 if debug:
342 print "Skipping %s for %s it has no- and check-code" % (
344 print "Skipping %s for %s it has no- and check-code" % (
343 name, f)
345 name, f)
344 break
346 break
345 for p, r in filters:
347 for p, r in filters:
346 post = re.sub(p, r, post)
348 post = re.sub(p, r, post)
347 if warnings:
349 if warnings:
348 pats = pats[0] + pats[1]
350 pats = pats[0] + pats[1]
349 else:
351 else:
350 pats = pats[0]
352 pats = pats[0]
351 # print post # uncomment to show filtered version
353 # print post # uncomment to show filtered version
352
354
353 if debug:
355 if debug:
354 print "Checking %s for %s" % (name, f)
356 print "Checking %s for %s" % (name, f)
355
357
356 prelines = None
358 prelines = None
357 errors = []
359 errors = []
358 for pat in pats:
360 for pat in pats:
359 if len(pat) == 3:
361 if len(pat) == 3:
360 p, msg, ignore = pat
362 p, msg, ignore = pat
361 else:
363 else:
362 p, msg = pat
364 p, msg = pat
363 ignore = None
365 ignore = None
364
366
365 # fix-up regexes for multiline searches
367 # fix-up regexes for multiline searches
366 po = p
368 po = p
367 # \s doesn't match \n
369 # \s doesn't match \n
368 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
370 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
369 # [^...] doesn't match newline
371 # [^...] doesn't match newline
370 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
372 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
371
373
372 #print po, '=>', p
374 #print po, '=>', p
373
375
374 pos = 0
376 pos = 0
375 n = 0
377 n = 0
376 for m in re.finditer(p, post, re.MULTILINE):
378 for m in re.finditer(p, post, re.MULTILINE):
377 if prelines is None:
379 if prelines is None:
378 prelines = pre.splitlines()
380 prelines = pre.splitlines()
379 postlines = post.splitlines(True)
381 postlines = post.splitlines(True)
380
382
381 start = m.start()
383 start = m.start()
382 while n < len(postlines):
384 while n < len(postlines):
383 step = len(postlines[n])
385 step = len(postlines[n])
384 if pos + step > start:
386 if pos + step > start:
385 break
387 break
386 pos += step
388 pos += step
387 n += 1
389 n += 1
388 l = prelines[n]
390 l = prelines[n]
389
391
390 if "check-code" + "-ignore" in l:
392 if "check-code" + "-ignore" in l:
391 if debug:
393 if debug:
392 print "Skipping %s for %s:%s (check-code -ignore)" % (
394 print "Skipping %s for %s:%s (check-code -ignore)" % (
393 name, f, n)
395 name, f, n)
394 continue
396 continue
395 elif ignore and re.search(ignore, l, re.MULTILINE):
397 elif ignore and re.search(ignore, l, re.MULTILINE):
396 continue
398 continue
397 bd = ""
399 bd = ""
398 if blame:
400 if blame:
399 bd = 'working directory'
401 bd = 'working directory'
400 if not blamecache:
402 if not blamecache:
401 blamecache = getblame(f)
403 blamecache = getblame(f)
402 if n < len(blamecache):
404 if n < len(blamecache):
403 bl, bu, br = blamecache[n]
405 bl, bu, br = blamecache[n]
404 if bl == l:
406 if bl == l:
405 bd = '%s@%s' % (bu, br)
407 bd = '%s@%s' % (bu, br)
406 errors.append((f, lineno and n + 1, l, msg, bd))
408 errors.append((f, lineno and n + 1, l, msg, bd))
407 result = False
409 result = False
408
410
409 errors.sort()
411 errors.sort()
410 for e in errors:
412 for e in errors:
411 logfunc(*e)
413 logfunc(*e)
412 fc += 1
414 fc += 1
413 if maxerr and fc >= maxerr:
415 if maxerr and fc >= maxerr:
414 print " (too many errors, giving up)"
416 print " (too many errors, giving up)"
415 break
417 break
416
418
417 return result
419 return result
418
420
419 if __name__ == "__main__":
421 if __name__ == "__main__":
420 parser = optparse.OptionParser("%prog [options] [files]")
422 parser = optparse.OptionParser("%prog [options] [files]")
421 parser.add_option("-w", "--warnings", action="store_true",
423 parser.add_option("-w", "--warnings", action="store_true",
422 help="include warning-level checks")
424 help="include warning-level checks")
423 parser.add_option("-p", "--per-file", type="int",
425 parser.add_option("-p", "--per-file", type="int",
424 help="max warnings per file")
426 help="max warnings per file")
425 parser.add_option("-b", "--blame", action="store_true",
427 parser.add_option("-b", "--blame", action="store_true",
426 help="use annotate to generate blame info")
428 help="use annotate to generate blame info")
427 parser.add_option("", "--debug", action="store_true",
429 parser.add_option("", "--debug", action="store_true",
428 help="show debug information")
430 help="show debug information")
429 parser.add_option("", "--nolineno", action="store_false",
431 parser.add_option("", "--nolineno", action="store_false",
430 dest='lineno', help="don't show line numbers")
432 dest='lineno', help="don't show line numbers")
431
433
432 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
434 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
433 lineno=True)
435 lineno=True)
434 (options, args) = parser.parse_args()
436 (options, args) = parser.parse_args()
435
437
436 if len(args) == 0:
438 if len(args) == 0:
437 check = glob.glob("*")
439 check = glob.glob("*")
438 else:
440 else:
439 check = args
441 check = args
440
442
441 ret = 0
443 ret = 0
442 for f in check:
444 for f in check:
443 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
445 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
444 blame=options.blame, debug=options.debug,
446 blame=options.blame, debug=options.debug,
445 lineno=options.lineno):
447 lineno=options.lineno):
446 ret = 1
448 ret = 1
447 sys.exit(ret)
449 sys.exit(ret)
@@ -1,563 +1,563 b''
1
1
2 $ HGMERGE=true; export HGMERGE
2 $ HGMERGE=true; export HGMERGE
3 $ echo '[extensions]' >> $HGRCPATH
3 $ echo '[extensions]' >> $HGRCPATH
4 $ echo 'graphlog =' >> $HGRCPATH
4 $ echo 'graphlog =' >> $HGRCPATH
5 $ echo 'convert =' >> $HGRCPATH
5 $ echo 'convert =' >> $HGRCPATH
6 $ glog()
6 $ glog()
7 > {
7 > {
8 > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
8 > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
9 > }
9 > }
10 $ hg init source
10 $ hg init source
11 $ cd source
11 $ cd source
12 $ echo foo > foo
12 $ echo foo > foo
13 $ echo baz > baz
13 $ echo baz > baz
14 $ mkdir -p dir/subdir
14 $ mkdir -p dir/subdir
15 $ echo dir/file >> dir/file
15 $ echo dir/file >> dir/file
16 $ echo dir/file2 >> dir/file2
16 $ echo dir/file2 >> dir/file2
17 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
17 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
18 $ echo dir/subdir/file3 >> dir/subdir/file3
18 $ echo dir/subdir/file3 >> dir/subdir/file3
19 $ echo dir/subdir/file4 >> dir/subdir/file4
19 $ echo dir/subdir/file4 >> dir/subdir/file4
20 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
20 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
21 $ echo bar > bar
21 $ echo bar > bar
22 $ echo quux > quux
22 $ echo quux > quux
23 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
23 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
24 $ hg copy foo copied
24 $ hg copy foo copied
25 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
25 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
26 $ echo >> foo
26 $ echo >> foo
27 $ hg ci -d '2 0' -m '2: change foo'
27 $ hg ci -d '2 0' -m '2: change foo'
28 $ hg up -qC 1
28 $ hg up -qC 1
29 $ echo >> bar
29 $ echo >> bar
30 $ echo >> quux
30 $ echo >> quux
31 $ hg ci -d '3 0' -m '3: change bar quux'
31 $ hg ci -d '3 0' -m '3: change bar quux'
32 created new head
32 created new head
33 $ hg up -qC 2
33 $ hg up -qC 2
34 $ hg merge -qr 3
34 $ hg merge -qr 3
35 $ echo >> bar
35 $ echo >> bar
36 $ echo >> baz
36 $ echo >> baz
37 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
37 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
38 $ echo >> bar
38 $ echo >> bar
39 $ echo 1 >> baz
39 $ echo 1 >> baz
40 $ echo >> quux
40 $ echo >> quux
41 $ hg ci -d '5 0' -m '5: change bar baz quux'
41 $ hg ci -d '5 0' -m '5: change bar baz quux'
42 $ hg up -qC 4
42 $ hg up -qC 4
43 $ echo >> foo
43 $ echo >> foo
44 $ echo 2 >> baz
44 $ echo 2 >> baz
45 $ hg ci -d '6 0' -m '6: change foo baz'
45 $ hg ci -d '6 0' -m '6: change foo baz'
46 created new head
46 created new head
47 $ hg up -qC 5
47 $ hg up -qC 5
48 $ hg merge -qr 6
48 $ hg merge -qr 6
49 $ echo >> bar
49 $ echo >> bar
50 $ hg ci -d '7 0' -m '7: second merge; change bar'
50 $ hg ci -d '7 0' -m '7: second merge; change bar'
51 $ echo >> foo
51 $ echo >> foo
52 $ hg ci -m '8: change foo'
52 $ hg ci -m '8: change foo'
53 $ glog
53 $ glog
54 @ 8 "8: change foo" files: foo
54 @ 8 "8: change foo" files: foo
55 |
55 |
56 o 7 "7: second merge; change bar" files: bar baz
56 o 7 "7: second merge; change bar" files: bar baz
57 |\
57 |\
58 | o 6 "6: change foo baz" files: baz foo
58 | o 6 "6: change foo baz" files: baz foo
59 | |
59 | |
60 o | 5 "5: change bar baz quux" files: bar baz quux
60 o | 5 "5: change bar baz quux" files: bar baz quux
61 |/
61 |/
62 o 4 "4: first merge; change bar baz" files: bar baz
62 o 4 "4: first merge; change bar baz" files: bar baz
63 |\
63 |\
64 | o 3 "3: change bar quux" files: bar quux
64 | o 3 "3: change bar quux" files: bar quux
65 | |
65 | |
66 o | 2 "2: change foo" files: foo
66 o | 2 "2: change foo" files: foo
67 |/
67 |/
68 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
68 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
69 |
69 |
70 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
70 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
71
71
72
72
73 final file versions in this repo:
73 final file versions in this repo:
74
74
75 $ hg manifest --debug
75 $ hg manifest --debug
76 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
76 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
77 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
77 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
78 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
78 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
79 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
79 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
80 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
80 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
81 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
81 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
82 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
82 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
83 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
83 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
84 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
84 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
85 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
85 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
86 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
86 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
87 $ hg debugrename copied
87 $ hg debugrename copied
88 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
88 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
89
89
90 $ cd ..
90 $ cd ..
91 $ splitrepo()
91 $ splitrepo()
92 > {
92 > {
93 > msg="$1"
93 > msg="$1"
94 > files="$2"
94 > files="$2"
95 > opts=$3
95 > opts=$3
96 > echo "% $files: $msg"
96 > echo "% $files: $msg"
97 > prefix=`echo "$files" | sed -e 's/ /-/g'`
97 > prefix=`echo "$files" | sed -e 's/ /-/g'`
98 > fmap="$prefix.fmap"
98 > fmap="$prefix.fmap"
99 > repo="$prefix.repo"
99 > repo="$prefix.repo"
100 > for i in $files; do
100 > for i in $files; do
101 > echo "include $i" >> "$fmap"
101 > echo "include $i" >> "$fmap"
102 > done
102 > done
103 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
103 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
104 > hg up -q -R "$repo"
104 > hg up -q -R "$repo"
105 > glog -R "$repo"
105 > glog -R "$repo"
106 > hg -R "$repo" manifest --debug
106 > hg -R "$repo" manifest --debug
107 > }
107 > }
108 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
108 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
109 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
109 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
110 @ 3 "8: change foo" files: foo
110 @ 3 "8: change foo" files: foo
111 |
111 |
112 o 2 "6: change foo baz" files: foo
112 o 2 "6: change foo baz" files: foo
113 |
113 |
114 o 1 "2: change foo" files: foo
114 o 1 "2: change foo" files: foo
115 |
115 |
116 o 0 "0: add foo baz dir/" files: foo
116 o 0 "0: add foo baz dir/" files: foo
117
117
118 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
118 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
119 $ splitrepo 'merges are not merges anymore' bar
119 $ splitrepo 'merges are not merges anymore' bar
120 % bar: merges are not merges anymore
120 % bar: merges are not merges anymore
121 @ 4 "7: second merge; change bar" files: bar
121 @ 4 "7: second merge; change bar" files: bar
122 |
122 |
123 o 3 "5: change bar baz quux" files: bar
123 o 3 "5: change bar baz quux" files: bar
124 |
124 |
125 o 2 "4: first merge; change bar baz" files: bar
125 o 2 "4: first merge; change bar baz" files: bar
126 |
126 |
127 o 1 "3: change bar quux" files: bar
127 o 1 "3: change bar quux" files: bar
128 |
128 |
129 o 0 "1: add bar quux; copy foo to copied" files: bar
129 o 0 "1: add bar quux; copy foo to copied" files: bar
130
130
131 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
131 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
132 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
132 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
133 % baz: 1st merge is not a merge anymore; 2nd still is
133 % baz: 1st merge is not a merge anymore; 2nd still is
134 @ 4 "7: second merge; change bar" files: baz
134 @ 4 "7: second merge; change bar" files: baz
135 |\
135 |\
136 | o 3 "6: change foo baz" files: baz
136 | o 3 "6: change foo baz" files: baz
137 | |
137 | |
138 o | 2 "5: change bar baz quux" files: baz
138 o | 2 "5: change bar baz quux" files: baz
139 |/
139 |/
140 o 1 "4: first merge; change bar baz" files: baz
140 o 1 "4: first merge; change bar baz" files: baz
141 |
141 |
142 o 0 "0: add foo baz dir/" files: baz
142 o 0 "0: add foo baz dir/" files: baz
143
143
144 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
144 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
145 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
145 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
146 % foo quux: we add additional merges when they are interesting
146 % foo quux: we add additional merges when they are interesting
147 @ 8 "8: change foo" files: foo
147 @ 8 "8: change foo" files: foo
148 |
148 |
149 o 7 "7: second merge; change bar" files:
149 o 7 "7: second merge; change bar" files:
150 |\
150 |\
151 | o 6 "6: change foo baz" files: foo
151 | o 6 "6: change foo baz" files: foo
152 | |
152 | |
153 o | 5 "5: change bar baz quux" files: quux
153 o | 5 "5: change bar baz quux" files: quux
154 |/
154 |/
155 o 4 "4: first merge; change bar baz" files:
155 o 4 "4: first merge; change bar baz" files:
156 |\
156 |\
157 | o 3 "3: change bar quux" files: quux
157 | o 3 "3: change bar quux" files: quux
158 | |
158 | |
159 o | 2 "2: change foo" files: foo
159 o | 2 "2: change foo" files: foo
160 |/
160 |/
161 o 1 "1: add bar quux; copy foo to copied" files: quux
161 o 1 "1: add bar quux; copy foo to copied" files: quux
162 |
162 |
163 o 0 "0: add foo baz dir/" files: foo
163 o 0 "0: add foo baz dir/" files: foo
164
164
165 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
165 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
166 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
166 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
167 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
167 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
168 % bar quux: partial conversion
168 % bar quux: partial conversion
169 @ 1 "3: change bar quux" files: bar quux
169 @ 1 "3: change bar quux" files: bar quux
170 |
170 |
171 o 0 "1: add bar quux; copy foo to copied" files: bar quux
171 o 0 "1: add bar quux; copy foo to copied" files: bar quux
172
172
173 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
173 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
174 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
174 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
175 $ splitrepo 'complete the partial conversion' 'bar quux'
175 $ splitrepo 'complete the partial conversion' 'bar quux'
176 % bar quux: complete the partial conversion
176 % bar quux: complete the partial conversion
177 @ 4 "7: second merge; change bar" files: bar
177 @ 4 "7: second merge; change bar" files: bar
178 |
178 |
179 o 3 "5: change bar baz quux" files: bar quux
179 o 3 "5: change bar baz quux" files: bar quux
180 |
180 |
181 o 2 "4: first merge; change bar baz" files: bar
181 o 2 "4: first merge; change bar baz" files: bar
182 |
182 |
183 o 1 "3: change bar quux" files: bar quux
183 o 1 "3: change bar quux" files: bar quux
184 |
184 |
185 o 0 "1: add bar quux; copy foo to copied" files: bar quux
185 o 0 "1: add bar quux; copy foo to copied" files: bar quux
186
186
187 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
187 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
188 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
188 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
189 $ rm -r foo.repo
189 $ rm -r foo.repo
190 $ splitrepo 'partial conversion' 'foo' '-r 3'
190 $ splitrepo 'partial conversion' 'foo' '-r 3'
191 % foo: partial conversion
191 % foo: partial conversion
192 @ 0 "0: add foo baz dir/" files: foo
192 @ 0 "0: add foo baz dir/" files: foo
193
193
194 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
194 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
195 $ splitrepo 'complete the partial conversion' 'foo'
195 $ splitrepo 'complete the partial conversion' 'foo'
196 % foo: complete the partial conversion
196 % foo: complete the partial conversion
197 @ 3 "8: change foo" files: foo
197 @ 3 "8: change foo" files: foo
198 |
198 |
199 o 2 "6: change foo baz" files: foo
199 o 2 "6: change foo baz" files: foo
200 |
200 |
201 o 1 "2: change foo" files: foo
201 o 1 "2: change foo" files: foo
202 |
202 |
203 o 0 "0: add foo baz dir/" files: foo
203 o 0 "0: add foo baz dir/" files: foo
204
204
205 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
205 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
206 $ splitrepo 'copied file; source not included in new repo' copied
206 $ splitrepo 'copied file; source not included in new repo' copied
207 % copied: copied file; source not included in new repo
207 % copied: copied file; source not included in new repo
208 @ 0 "1: add bar quux; copy foo to copied" files: copied
208 @ 0 "1: add bar quux; copy foo to copied" files: copied
209
209
210 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
210 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
211 $ hg --cwd copied.repo debugrename copied
211 $ hg --cwd copied.repo debugrename copied
212 copied not renamed
212 copied not renamed
213 $ splitrepo 'copied file; source included in new repo' 'foo copied'
213 $ splitrepo 'copied file; source included in new repo' 'foo copied'
214 % foo copied: copied file; source included in new repo
214 % foo copied: copied file; source included in new repo
215 @ 4 "8: change foo" files: foo
215 @ 4 "8: change foo" files: foo
216 |
216 |
217 o 3 "6: change foo baz" files: foo
217 o 3 "6: change foo baz" files: foo
218 |
218 |
219 o 2 "2: change foo" files: foo
219 o 2 "2: change foo" files: foo
220 |
220 |
221 o 1 "1: add bar quux; copy foo to copied" files: copied
221 o 1 "1: add bar quux; copy foo to copied" files: copied
222 |
222 |
223 o 0 "0: add foo baz dir/" files: foo
223 o 0 "0: add foo baz dir/" files: foo
224
224
225 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
225 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
226 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
226 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
227 $ hg --cwd foo-copied.repo debugrename copied
227 $ hg --cwd foo-copied.repo debugrename copied
228 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
228 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
229 $ cat > renames.fmap <<EOF
229 $ cat > renames.fmap <<EOF
230 > include dir
230 > include dir
231 > exclude dir/file2
231 > exclude dir/file2
232 > rename dir dir2
232 > rename dir dir2
233 > include foo
233 > include foo
234 > include copied
234 > include copied
235 > rename foo foo2
235 > rename foo foo2
236 > rename copied copied2
236 > rename copied copied2
237 > exclude dir/subdir
237 > exclude dir/subdir
238 > include dir/subdir/file3
238 > include dir/subdir/file3
239 > EOF
239 > EOF
240 $ rm source/.hg/store/data/dir/file3.i
240 $ rm source/.hg/store/data/dir/file3.i
241 $ rm source/.hg/store/data/dir/file4.i
241 $ rm source/.hg/store/data/dir/file4.i
242 $ hg -q convert --filemap renames.fmap --datesort source dummydest
242 $ hg -q convert --filemap renames.fmap --datesort source dummydest
243 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
243 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
244 [255]
244 [255]
245 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
245 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
246 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
246 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
247 ignoring: data/dir/file4.i@6edd55f559cd: no match found
247 ignoring: data/dir/file4.i@6edd55f559cd: no match found
248 $ hg up -q -R renames.repo
248 $ hg up -q -R renames.repo
249 $ glog -R renames.repo
249 $ glog -R renames.repo
250 @ 4 "8: change foo" files: foo2
250 @ 4 "8: change foo" files: foo2
251 |
251 |
252 o 3 "6: change foo baz" files: foo2
252 o 3 "6: change foo baz" files: foo2
253 |
253 |
254 o 2 "2: change foo" files: foo2
254 o 2 "2: change foo" files: foo2
255 |
255 |
256 o 1 "1: add bar quux; copy foo to copied" files: copied2
256 o 1 "1: add bar quux; copy foo to copied" files: copied2
257 |
257 |
258 o 0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
258 o 0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
259
259
260 $ hg -R renames.repo manifest --debug
260 $ hg -R renames.repo manifest --debug
261 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
261 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
262 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/file
262 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/file
263 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/subdir/file3
263 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/subdir/file3
264 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
264 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
265 $ hg --cwd renames.repo debugrename copied2
265 $ hg --cwd renames.repo debugrename copied2
266 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
266 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
267
267
268 copied:
268 copied:
269
269
270 $ hg --cwd source cat copied
270 $ hg --cwd source cat copied
271 foo
271 foo
272
272
273 copied2:
273 copied2:
274
274
275 $ hg --cwd renames.repo cat copied2
275 $ hg --cwd renames.repo cat copied2
276 foo
276 foo
277
277
278 filemap errors
278 filemap errors
279
279
280 $ cat > errors.fmap <<EOF
280 $ cat > errors.fmap <<EOF
281 > include dir/ # beware that comments changes error line numbers!
281 > include dir/ # beware that comments changes error line numbers!
282 > exclude /dir
282 > exclude /dir
283 > rename dir//dir /dir//dir/ "out of sync"
283 > rename dir//dir /dir//dir/ "out of sync"
284 > include
284 > include
285 > EOF
285 > EOF
286 $ hg -q convert --filemap errors.fmap source errors.repo
286 $ hg -q convert --filemap errors.fmap source errors.repo
287 errors.fmap:1: superfluous / in exclude 'dir/'
287 errors.fmap:1: superfluous / in exclude 'dir/'
288 errors.fmap:3: superfluous / in include '/dir'
288 errors.fmap:3: superfluous / in include '/dir'
289 errors.fmap:3: superfluous / in rename '/dir'
289 errors.fmap:3: superfluous / in rename '/dir'
290 errors.fmap:3: superfluous / in exclude 'dir//dir'
290 errors.fmap:3: superfluous / in exclude 'dir//dir'
291 errors.fmap:4: unknown directive 'out of sync'
291 errors.fmap:4: unknown directive 'out of sync'
292 errors.fmap:5: path to exclude is missing
292 errors.fmap:5: path to exclude is missing
293 abort: errors in filemap
293 abort: errors in filemap
294 [255]
294 [255]
295
295
296 test branch closing revision pruning if branch is pruned
296 test branch closing revision pruning if branch is pruned
297
297
298 $ hg init branchpruning
298 $ hg init branchpruning
299 $ cd branchpruning
299 $ cd branchpruning
300 $ hg branch foo
300 $ hg branch foo
301 marked working directory as branch foo
301 marked working directory as branch foo
302 (branches are permanent and global, did you want a bookmark?)
302 (branches are permanent and global, did you want a bookmark?)
303 $ echo a > a
303 $ echo a > a
304 $ hg ci -Am adda
304 $ hg ci -Am adda
305 adding a
305 adding a
306 $ hg ci --close-branch -m closefoo
306 $ hg ci --close-branch -m closefoo
307 $ hg up 0
307 $ hg up 0
308 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
308 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
309 $ hg branch empty
309 $ hg branch empty
310 marked working directory as branch empty
310 marked working directory as branch empty
311 (branches are permanent and global, did you want a bookmark?)
311 (branches are permanent and global, did you want a bookmark?)
312 $ hg ci -m emptybranch
312 $ hg ci -m emptybranch
313 $ hg ci --close-branch -m closeempty
313 $ hg ci --close-branch -m closeempty
314 $ hg up 0
314 $ hg up 0
315 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
315 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 $ hg branch default
316 $ hg branch default
317 marked working directory as branch default
317 marked working directory as branch default
318 (branches are permanent and global, did you want a bookmark?)
318 (branches are permanent and global, did you want a bookmark?)
319 $ echo b > b
319 $ echo b > b
320 $ hg ci -Am addb
320 $ hg ci -Am addb
321 adding b
321 adding b
322 $ hg ci --close-branch -m closedefault
322 $ hg ci --close-branch -m closedefault
323 $ cat > filemap <<EOF
323 $ cat > filemap <<EOF
324 > include b
324 > include b
325 > EOF
325 > EOF
326 $ cd ..
326 $ cd ..
327 $ hg convert branchpruning branchpruning-hg1
327 $ hg convert branchpruning branchpruning-hg1
328 initializing destination branchpruning-hg1 repository
328 initializing destination branchpruning-hg1 repository
329 scanning source...
329 scanning source...
330 sorting...
330 sorting...
331 converting...
331 converting...
332 5 adda
332 5 adda
333 4 closefoo
333 4 closefoo
334 3 emptybranch
334 3 emptybranch
335 2 closeempty
335 2 closeempty
336 1 addb
336 1 addb
337 0 closedefault
337 0 closedefault
338 $ glog -R branchpruning-hg1
338 $ glog -R branchpruning-hg1
339 o 5 "closedefault" files:
339 o 5 "closedefault" files:
340 |
340 |
341 o 4 "addb" files: b
341 o 4 "addb" files: b
342 |
342 |
343 | o 3 "closeempty" files:
343 | o 3 "closeempty" files:
344 | |
344 | |
345 | o 2 "emptybranch" files:
345 | o 2 "emptybranch" files:
346 |/
346 |/
347 | o 1 "closefoo" files:
347 | o 1 "closefoo" files:
348 |/
348 |/
349 o 0 "adda" files: a
349 o 0 "adda" files: a
350
350
351
351
352 exercise incremental conversion at the same time
352 exercise incremental conversion at the same time
353
353
354 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
354 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
355 initializing destination branchpruning-hg2 repository
355 initializing destination branchpruning-hg2 repository
356 scanning source...
356 scanning source...
357 sorting...
357 sorting...
358 converting...
358 converting...
359 0 adda
359 0 adda
360 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
360 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
361 scanning source...
361 scanning source...
362 sorting...
362 sorting...
363 converting...
363 converting...
364 0 addb
364 0 addb
365 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
365 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
366 scanning source...
366 scanning source...
367 sorting...
367 sorting...
368 converting...
368 converting...
369 3 closefoo
369 3 closefoo
370 2 emptybranch
370 2 emptybranch
371 1 closeempty
371 1 closeempty
372 0 closedefault
372 0 closedefault
373 $ glog -R branchpruning-hg2
373 $ glog -R branchpruning-hg2
374 o 1 "closedefault" files:
374 o 1 "closedefault" files:
375 |
375 |
376 o 0 "addb" files: b
376 o 0 "addb" files: b
377
377
378
378
379 test merge parents/empty merges pruning
379 test merge parents/empty merges pruning
380
380
381 $ glog()
381 $ glog()
382 > {
382 > {
383 > hg glog --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
383 > hg glog --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
384 > }
384 > }
385
385
386 test anonymous branch pruning
386 test anonymous branch pruning
387
387
388 $ hg init anonymousbranch
388 $ hg init anonymousbranch
389 $ cd anonymousbranch
389 $ cd anonymousbranch
390 $ echo a > a
390 $ echo a > a
391 $ echo b > b
391 $ echo b > b
392 $ hg ci -Am add
392 $ hg ci -Am add
393 adding a
393 adding a
394 adding b
394 adding b
395 $ echo a >> a
395 $ echo a >> a
396 $ hg ci -m changea
396 $ hg ci -m changea
397 $ hg up 0
397 $ hg up 0
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 $ echo b >> b
399 $ echo b >> b
400 $ hg ci -m changeb
400 $ hg ci -m changeb
401 created new head
401 created new head
402 $ hg up 1
402 $ hg up 1
403 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
403 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 $ hg merge
404 $ hg merge
405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
406 (branch merge, don't forget to commit)
406 (branch merge, don't forget to commit)
407 $ hg ci -m merge
407 $ hg ci -m merge
408 $ cd ..
408 $ cd ..
409
409
410 $ cat > filemap <<EOF
410 $ cat > filemap <<EOF
411 > include a
411 > include a
412 > EOF
412 > EOF
413 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
413 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg
414 initializing destination anonymousbranch-hg repository
414 initializing destination anonymousbranch-hg repository
415 scanning source...
415 scanning source...
416 sorting...
416 sorting...
417 converting...
417 converting...
418 3 add
418 3 add
419 2 changea
419 2 changea
420 1 changeb
420 1 changeb
421 0 merge
421 0 merge
422 $ glog -R anonymousbranch
422 $ glog -R anonymousbranch
423 @ 3:c71d5201a498@default "merge" files:
423 @ 3:c71d5201a498@default "merge" files:
424 |\
424 |\
425 | o 2:607eb44b17f9@default "changeb" files: b
425 | o 2:607eb44b17f9@default "changeb" files: b
426 | |
426 | |
427 o | 1:1f60ea617824@default "changea" files: a
427 o | 1:1f60ea617824@default "changea" files: a
428 |/
428 |/
429 o 0:0146e6129113@default "add" files: a b
429 o 0:0146e6129113@default "add" files: a b
430
430
431 $ glog -R anonymousbranch-hg
431 $ glog -R anonymousbranch-hg
432 o 1:cda818e7219b@default "changea" files: a
432 o 1:cda818e7219b@default "changea" files: a
433 |
433 |
434 o 0:c334dc3be0da@default "add" files: a
434 o 0:c334dc3be0da@default "add" files: a
435
435
436 $ cat anonymousbranch-hg/.hg/shamap
436 $ cat anonymousbranch-hg/.hg/shamap
437 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
437 0146e6129113dba9ac90207cfdf2d7ed35257ae5 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
438 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
438 1f60ea61782421edf8d051ff4fcb61b330f26a4a cda818e7219b5f7f3fb9f49780054ed6a1905ec3
439 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
439 607eb44b17f9348cd5cbd26e16af87ba77b0b037 c334dc3be0daa2a4e9ce4d2e2bdcba40c09d4916
440 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
440 c71d5201a498b2658d105a6bf69d7a0df2649aea cda818e7219b5f7f3fb9f49780054ed6a1905ec3
441
441
442 $ cat > filemap <<EOF
442 $ cat > filemap <<EOF
443 > include b
443 > include b
444 > EOF
444 > EOF
445 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
445 $ hg convert --filemap filemap anonymousbranch anonymousbranch-hg2
446 initializing destination anonymousbranch-hg2 repository
446 initializing destination anonymousbranch-hg2 repository
447 scanning source...
447 scanning source...
448 sorting...
448 sorting...
449 converting...
449 converting...
450 3 add
450 3 add
451 2 changea
451 2 changea
452 1 changeb
452 1 changeb
453 0 merge
453 0 merge
454 $ glog -R anonymousbranch
454 $ glog -R anonymousbranch
455 @ 3:c71d5201a498@default "merge" files:
455 @ 3:c71d5201a498@default "merge" files:
456 |\
456 |\
457 | o 2:607eb44b17f9@default "changeb" files: b
457 | o 2:607eb44b17f9@default "changeb" files: b
458 | |
458 | |
459 o | 1:1f60ea617824@default "changea" files: a
459 o | 1:1f60ea617824@default "changea" files: a
460 |/
460 |/
461 o 0:0146e6129113@default "add" files: a b
461 o 0:0146e6129113@default "add" files: a b
462
462
463 $ glog -R anonymousbranch-hg2
463 $ glog -R anonymousbranch-hg2
464 o 1:62dd350b0df6@default "changeb" files: b
464 o 1:62dd350b0df6@default "changeb" files: b
465 |
465 |
466 o 0:4b9ced861657@default "add" files: b
466 o 0:4b9ced861657@default "add" files: b
467
467
468 $ cat anonymousbranch-hg2/.hg/shamap
468 $ cat anonymousbranch-hg2/.hg/shamap
469 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
469 0146e6129113dba9ac90207cfdf2d7ed35257ae5 4b9ced86165703791653059a1db6ed864630a523
470 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
470 1f60ea61782421edf8d051ff4fcb61b330f26a4a 4b9ced86165703791653059a1db6ed864630a523
471 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
471 607eb44b17f9348cd5cbd26e16af87ba77b0b037 62dd350b0df695f7d2c82a02e0499b16fd790f22
472 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
472 c71d5201a498b2658d105a6bf69d7a0df2649aea 62dd350b0df695f7d2c82a02e0499b16fd790f22
473
473
474 test named branch pruning
474 test named branch pruning
475
475
476 $ hg init namedbranch
476 $ hg init namedbranch
477 $ cd namedbranch
477 $ cd namedbranch
478 $ echo a > a
478 $ echo a > a
479 $ echo b > b
479 $ echo b > b
480 $ hg ci -Am add
480 $ hg ci -Am add
481 adding a
481 adding a
482 adding b
482 adding b
483 $ echo a >> a
483 $ echo a >> a
484 $ hg ci -m changea
484 $ hg ci -m changea
485 $ hg up 0
485 $ hg up 0
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
487 $ hg branch foo
487 $ hg branch foo
488 marked working directory as branch foo
488 marked working directory as branch foo
489 (branches are permanent and global, did you want a bookmark?)
489 (branches are permanent and global, did you want a bookmark?)
490 $ echo b >> b
490 $ echo b >> b
491 $ hg ci -m changeb
491 $ hg ci -m changeb
492 $ hg up default
492 $ hg up default
493 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
493 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
494 $ hg merge foo
494 $ hg merge foo
495 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
495 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
496 (branch merge, don't forget to commit)
496 (branch merge, don't forget to commit)
497 $ hg ci -m merge
497 $ hg ci -m merge
498 $ cd ..
498 $ cd ..
499
499
500 $ cat > filemap <<EOF
500 $ cat > filemap <<EOF
501 > include a
501 > include a
502 > EOF
502 > EOF
503 $ hg convert --filemap filemap namedbranch namedbranch-hg
503 $ hg convert --filemap filemap namedbranch namedbranch-hg
504 initializing destination namedbranch-hg repository
504 initializing destination namedbranch-hg repository
505 scanning source...
505 scanning source...
506 sorting...
506 sorting...
507 converting...
507 converting...
508 3 add
508 3 add
509 2 changea
509 2 changea
510 1 changeb
510 1 changeb
511 0 merge
511 0 merge
512 $ glog -R namedbranch
512 $ glog -R namedbranch
513 @ 3:73899bcbe45c@default "merge" files:
513 @ 3:73899bcbe45c@default "merge" files:
514 |\
514 |\
515 | o 2:8097982d19fc@foo "changeb" files: b
515 | o 2:8097982d19fc@foo "changeb" files: b
516 | |
516 | |
517 o | 1:1f60ea617824@default "changea" files: a
517 o | 1:1f60ea617824@default "changea" files: a
518 |/
518 |/
519 o 0:0146e6129113@default "add" files: a b
519 o 0:0146e6129113@default "add" files: a b
520
520
521 $ glog -R namedbranch-hg
521 $ glog -R namedbranch-hg
522 o 1:cda818e7219b@default "changea" files: a
522 o 1:cda818e7219b@default "changea" files: a
523 |
523 |
524 o 0:c334dc3be0da@default "add" files: a
524 o 0:c334dc3be0da@default "add" files: a
525
525
526
526
527 $ cd namedbranch
527 $ cd namedbranch
528 $ hg --config extensions.mq= strip tip
528 $ hg --config extensions.mq= strip tip
529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-backup.hg
530 saved backup bundle to $TESTTMP/namedbranch/.hg/strip-backup/73899bcbe45c-backup.hg (glob)
531 $ hg up foo
531 $ hg up foo
532 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
532 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
533 $ hg merge default
533 $ hg merge default
534 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
534 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
535 (branch merge, don't forget to commit)
535 (branch merge, don't forget to commit)
536 $ hg ci -m merge
536 $ hg ci -m merge
537 $ cd ..
537 $ cd ..
538
538
539 $ hg convert --filemap filemap namedbranch namedbranch-hg2
539 $ hg convert --filemap filemap namedbranch namedbranch-hg2
540 initializing destination namedbranch-hg2 repository
540 initializing destination namedbranch-hg2 repository
541 scanning source...
541 scanning source...
542 sorting...
542 sorting...
543 converting...
543 converting...
544 3 add
544 3 add
545 2 changea
545 2 changea
546 1 changeb
546 1 changeb
547 0 merge
547 0 merge
548 $ glog -R namedbranch
548 $ glog -R namedbranch
549 @ 3:e1959de76e1b@foo "merge" files:
549 @ 3:e1959de76e1b@foo "merge" files:
550 |\
550 |\
551 | o 2:8097982d19fc@foo "changeb" files: b
551 | o 2:8097982d19fc@foo "changeb" files: b
552 | |
552 | |
553 o | 1:1f60ea617824@default "changea" files: a
553 o | 1:1f60ea617824@default "changea" files: a
554 |/
554 |/
555 o 0:0146e6129113@default "add" files: a b
555 o 0:0146e6129113@default "add" files: a b
556
556
557 $ glog -R namedbranch-hg2
557 $ glog -R namedbranch-hg2
558 o 2:dcf314454667@foo "merge" files:
558 o 2:dcf314454667@foo "merge" files:
559 |\
559 |\
560 | o 1:cda818e7219b@default "changea" files: a
560 | o 1:cda818e7219b@default "changea" files: a
561 |/
561 |/
562 o 0:c334dc3be0da@default "add" files: a
562 o 0:c334dc3be0da@default "add" files: a
563
563
General Comments 0
You need to be logged in to leave comments. Login now