##// END OF EJS Templates
check-code: fix check for trailing whitespace on continued lines too...
Mads Kiilerich -
r17347:2da47de3 default
parent child Browse files
Show More
@@ -1,450 +1,450
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.*|| \$ .*)[ \t]\n', "trailing whitespace on non-output"),
94 (r'^(\S.*|| [$>] .*)[ \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$',
103 (r'^ saved backup bundle to \$TESTTMP.*\.hg$',
104 "use (glob) to match Windows paths too"),
104 "use (glob) to match Windows paths too"),
105 ],
105 ],
106 # warnings
106 # warnings
107 []
107 []
108 ]
108 ]
109
109
110 for i in [0, 1]:
110 for i in [0, 1]:
111 for p, m in testpats[i]:
111 for p, m in testpats[i]:
112 if p.startswith(r'^'):
112 if p.startswith(r'^'):
113 p = r"^ [$>] (%s)" % p[1:]
113 p = r"^ [$>] (%s)" % p[1:]
114 else:
114 else:
115 p = r"^ [$>] .*(%s)" % p
115 p = r"^ [$>] .*(%s)" % p
116 utestpats[i].append((p, m))
116 utestpats[i].append((p, m))
117
117
118 utestfilters = [
118 utestfilters = [
119 (r"( *)(#([^\n]*\S)?)", repcomment),
119 (r"( *)(#([^\n]*\S)?)", repcomment),
120 ]
120 ]
121
121
122 pypats = [
122 pypats = [
123 [
123 [
124 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
124 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
125 "tuple parameter unpacking not available in Python 3+"),
125 "tuple parameter unpacking not available in Python 3+"),
126 (r'lambda\s*\(.*,.*\)',
126 (r'lambda\s*\(.*,.*\)',
127 "tuple parameter unpacking not available in Python 3+"),
127 "tuple parameter unpacking not available in Python 3+"),
128 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
128 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
129 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
129 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
130 (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+"),
131 (r'^\s*\t', "don't use tabs"),
131 (r'^\s*\t', "don't use tabs"),
132 (r'\S;\s*\n', "semicolon"),
132 (r'\S;\s*\n', "semicolon"),
133 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
133 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
134 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
134 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
135 (r'\w,\w', "missing whitespace after ,"),
135 (r'\w,\w', "missing whitespace after ,"),
136 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
136 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
137 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
137 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
138 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
138 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
139 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'),
140 (r'.{81}', "line too long"),
140 (r'.{81}', "line too long"),
141 (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'),
142 (r'[^\n]\Z', "no trailing newline"),
142 (r'[^\n]\Z', "no trailing newline"),
143 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
143 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
144 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
144 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
145 # "don't use underbars in identifiers"),
145 # "don't use underbars in identifiers"),
146 (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* = ',
147 "don't use camelcase in identifiers"),
147 "don't use camelcase in identifiers"),
148 (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]+',
149 "linebreak after :"),
149 "linebreak after :"),
150 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
150 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
151 (r'class\s[^( \n]+\(\):',
151 (r'class\s[^( \n]+\(\):',
152 "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)"),
153 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
153 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
154 "Python keyword is not a function"),
154 "Python keyword is not a function"),
155 (r',]', "unneeded trailing ',' in list"),
155 (r',]', "unneeded trailing ',' in list"),
156 # (r'class\s[A-Z][^\(]*\((?!Exception)',
156 # (r'class\s[A-Z][^\(]*\((?!Exception)',
157 # "don't capitalize non-exception classes"),
157 # "don't capitalize non-exception classes"),
158 # (r'in range\(', "use xrange"),
158 # (r'in range\(', "use xrange"),
159 # (r'^\s*print\s+', "avoid using print in core and extensions"),
159 # (r'^\s*print\s+', "avoid using print in core and extensions"),
160 (r'[\x80-\xff]', "non-ASCII character literal"),
160 (r'[\x80-\xff]', "non-ASCII character literal"),
161 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
161 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
162 (r'^\s*with\s+', "with not available in Python 2.4"),
162 (r'^\s*with\s+', "with not available in Python 2.4"),
163 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
163 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
164 (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"),
165 (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"),
166 (r'(?<!def)\s+(any|all|format)\(',
166 (r'(?<!def)\s+(any|all|format)\(',
167 "any/all/format not available in Python 2.4"),
167 "any/all/format not available in Python 2.4"),
168 (r'(?<!def)\s+(callable)\(',
168 (r'(?<!def)\s+(callable)\(',
169 "callable not available in Python 3, use getattr(f, '__call__', None)"),
169 "callable not available in Python 3, use getattr(f, '__call__', None)"),
170 (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"),
171 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
171 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
172 "gratuitous whitespace after Python keyword"),
172 "gratuitous whitespace after Python keyword"),
173 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
173 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
174 # (r'\s\s=', "gratuitous whitespace before ="),
174 # (r'\s\s=', "gratuitous whitespace before ="),
175 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
175 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
176 "missing whitespace around operator"),
176 "missing whitespace around operator"),
177 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s',
177 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s',
178 "missing whitespace around operator"),
178 "missing whitespace around operator"),
179 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
179 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
180 "missing whitespace around operator"),
180 "missing whitespace around operator"),
181 (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]',
181 (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]',
182 "wrong whitespace around ="),
182 "wrong whitespace around ="),
183 (r'raise Exception', "don't raise generic exceptions"),
183 (r'raise Exception', "don't raise generic exceptions"),
184 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
184 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
185 (r' [=!]=\s+(True|False|None)',
185 (r' [=!]=\s+(True|False|None)',
186 "comparison with singleton, use 'is' or 'is not' instead"),
186 "comparison with singleton, use 'is' or 'is not' instead"),
187 (r'^\s*(while|if) [01]:',
187 (r'^\s*(while|if) [01]:',
188 "use True/False for constant Boolean expression"),
188 "use True/False for constant Boolean expression"),
189 (r'(?:(?<!def)\s+|\()hasattr',
189 (r'(?:(?<!def)\s+|\()hasattr',
190 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
190 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
191 (r'opener\([^)]*\).read\(',
191 (r'opener\([^)]*\).read\(',
192 "use opener.read() instead"),
192 "use opener.read() instead"),
193 (r'BaseException', 'not in Py2.4, use Exception'),
193 (r'BaseException', 'not in Py2.4, use Exception'),
194 (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'),
195 (r'opener\([^)]*\).write\(',
195 (r'opener\([^)]*\).write\(',
196 "use opener.write() instead"),
196 "use opener.write() instead"),
197 (r'[\s\(](open|file)\([^)]*\)\.read\(',
197 (r'[\s\(](open|file)\([^)]*\)\.read\(',
198 "use util.readfile() instead"),
198 "use util.readfile() instead"),
199 (r'[\s\(](open|file)\([^)]*\)\.write\(',
199 (r'[\s\(](open|file)\([^)]*\)\.write\(',
200 "use util.readfile() instead"),
200 "use util.readfile() instead"),
201 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
201 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
202 "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"),
203 (r'[\s\(](open|file)\([^)]*\)\.',
203 (r'[\s\(](open|file)\([^)]*\)\.',
204 "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"),
205 (r'(?i)descendent', "the proper spelling is descendAnt"),
205 (r'(?i)descendent', "the proper spelling is descendAnt"),
206 (r'\.debug\(\_', "don't mark debug messages for translation"),
206 (r'\.debug\(\_', "don't mark debug messages for translation"),
207 (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
207 (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
208 (r'^\s*except\s*:', "warning: naked except clause", r'#.*re-raises'),
208 (r'^\s*except\s*:', "warning: naked except clause", r'#.*re-raises'),
209 (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"),
209 (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"),
210 ],
210 ],
211 # warnings
211 # warnings
212 [
212 [
213 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
213 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
214 "warning: unwrapped ui message"),
214 "warning: unwrapped ui message"),
215 ]
215 ]
216 ]
216 ]
217
217
218 pyfilters = [
218 pyfilters = [
219 (r"""(?msx)(?P<comment>\#.*?$)|
219 (r"""(?msx)(?P<comment>\#.*?$)|
220 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
220 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
221 (?P<text>(([^\\]|\\.)*?))
221 (?P<text>(([^\\]|\\.)*?))
222 (?P=quote))""", reppython),
222 (?P=quote))""", reppython),
223 ]
223 ]
224
224
225 cpats = [
225 cpats = [
226 [
226 [
227 (r'//', "don't use //-style comments"),
227 (r'//', "don't use //-style comments"),
228 (r'^ ', "don't use spaces to indent"),
228 (r'^ ', "don't use spaces to indent"),
229 (r'\S\t', "don't use tabs except for indent"),
229 (r'\S\t', "don't use tabs except for indent"),
230 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
230 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
231 (r'.{81}', "line too long"),
231 (r'.{81}', "line too long"),
232 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
232 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
233 (r'return\(', "return is not a function"),
233 (r'return\(', "return is not a function"),
234 (r' ;', "no space before ;"),
234 (r' ;', "no space before ;"),
235 (r'\w+\* \w+', "use int *foo, not int* foo"),
235 (r'\w+\* \w+', "use int *foo, not int* foo"),
236 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
236 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
237 (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
237 (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
238 (r'\w,\w', "missing whitespace after ,"),
238 (r'\w,\w', "missing whitespace after ,"),
239 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
239 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
240 (r'^#\s+\w', "use #foo, not # foo"),
240 (r'^#\s+\w', "use #foo, not # foo"),
241 (r'[^\n]\Z', "no trailing newline"),
241 (r'[^\n]\Z', "no trailing newline"),
242 (r'^\s*#import\b', "use only #include in standard C code"),
242 (r'^\s*#import\b', "use only #include in standard C code"),
243 ],
243 ],
244 # warnings
244 # warnings
245 []
245 []
246 ]
246 ]
247
247
248 cfilters = [
248 cfilters = [
249 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
249 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
250 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
250 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
251 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
251 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
252 (r'(\()([^)]+\))', repcallspaces),
252 (r'(\()([^)]+\))', repcallspaces),
253 ]
253 ]
254
254
255 inutilpats = [
255 inutilpats = [
256 [
256 [
257 (r'\bui\.', "don't use ui in util"),
257 (r'\bui\.', "don't use ui in util"),
258 ],
258 ],
259 # warnings
259 # warnings
260 []
260 []
261 ]
261 ]
262
262
263 inrevlogpats = [
263 inrevlogpats = [
264 [
264 [
265 (r'\brepo\.', "don't use repo in revlog"),
265 (r'\brepo\.', "don't use repo in revlog"),
266 ],
266 ],
267 # warnings
267 # warnings
268 []
268 []
269 ]
269 ]
270
270
271 checks = [
271 checks = [
272 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
272 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
273 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
273 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
274 ('c', r'.*\.c$', cfilters, cpats),
274 ('c', r'.*\.c$', cfilters, cpats),
275 ('unified test', r'.*\.t$', utestfilters, utestpats),
275 ('unified test', r'.*\.t$', utestfilters, utestpats),
276 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
276 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
277 inrevlogpats),
277 inrevlogpats),
278 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
278 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
279 inutilpats),
279 inutilpats),
280 ]
280 ]
281
281
282 class norepeatlogger(object):
282 class norepeatlogger(object):
283 def __init__(self):
283 def __init__(self):
284 self._lastseen = None
284 self._lastseen = None
285
285
286 def log(self, fname, lineno, line, msg, blame):
286 def log(self, fname, lineno, line, msg, blame):
287 """print error related a to given line of a given file.
287 """print error related a to given line of a given file.
288
288
289 The faulty line will also be printed but only once in the case
289 The faulty line will also be printed but only once in the case
290 of multiple errors.
290 of multiple errors.
291
291
292 :fname: filename
292 :fname: filename
293 :lineno: line number
293 :lineno: line number
294 :line: actual content of the line
294 :line: actual content of the line
295 :msg: error message
295 :msg: error message
296 """
296 """
297 msgid = fname, lineno, line
297 msgid = fname, lineno, line
298 if msgid != self._lastseen:
298 if msgid != self._lastseen:
299 if blame:
299 if blame:
300 print "%s:%d (%s):" % (fname, lineno, blame)
300 print "%s:%d (%s):" % (fname, lineno, blame)
301 else:
301 else:
302 print "%s:%d:" % (fname, lineno)
302 print "%s:%d:" % (fname, lineno)
303 print " > %s" % line
303 print " > %s" % line
304 self._lastseen = msgid
304 self._lastseen = msgid
305 print " " + msg
305 print " " + msg
306
306
307 _defaultlogger = norepeatlogger()
307 _defaultlogger = norepeatlogger()
308
308
309 def getblame(f):
309 def getblame(f):
310 lines = []
310 lines = []
311 for l in os.popen('hg annotate -un %s' % f):
311 for l in os.popen('hg annotate -un %s' % f):
312 start, line = l.split(':', 1)
312 start, line = l.split(':', 1)
313 user, rev = start.split()
313 user, rev = start.split()
314 lines.append((line[1:-1], user, rev))
314 lines.append((line[1:-1], user, rev))
315 return lines
315 return lines
316
316
317 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
317 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
318 blame=False, debug=False, lineno=True):
318 blame=False, debug=False, lineno=True):
319 """checks style and portability of a given file
319 """checks style and portability of a given file
320
320
321 :f: filepath
321 :f: filepath
322 :logfunc: function used to report error
322 :logfunc: function used to report error
323 logfunc(filename, linenumber, linecontent, errormessage)
323 logfunc(filename, linenumber, linecontent, errormessage)
324 :maxerr: number of error to display before arborting.
324 :maxerr: number of error to display before arborting.
325 Set to false (default) to report all errors
325 Set to false (default) to report all errors
326
326
327 return True if no error is found, False otherwise.
327 return True if no error is found, False otherwise.
328 """
328 """
329 blamecache = None
329 blamecache = None
330 result = True
330 result = True
331 for name, match, filters, pats in checks:
331 for name, match, filters, pats in checks:
332 if debug:
332 if debug:
333 print name, f
333 print name, f
334 fc = 0
334 fc = 0
335 if not re.match(match, f):
335 if not re.match(match, f):
336 if debug:
336 if debug:
337 print "Skipping %s for %s it doesn't match %s" % (
337 print "Skipping %s for %s it doesn't match %s" % (
338 name, match, f)
338 name, match, f)
339 continue
339 continue
340 fp = open(f)
340 fp = open(f)
341 pre = post = fp.read()
341 pre = post = fp.read()
342 fp.close()
342 fp.close()
343 if "no-" + "check-code" in pre:
343 if "no-" + "check-code" in pre:
344 if debug:
344 if debug:
345 print "Skipping %s for %s it has no- and check-code" % (
345 print "Skipping %s for %s it has no- and check-code" % (
346 name, f)
346 name, f)
347 break
347 break
348 for p, r in filters:
348 for p, r in filters:
349 post = re.sub(p, r, post)
349 post = re.sub(p, r, post)
350 if warnings:
350 if warnings:
351 pats = pats[0] + pats[1]
351 pats = pats[0] + pats[1]
352 else:
352 else:
353 pats = pats[0]
353 pats = pats[0]
354 # print post # uncomment to show filtered version
354 # print post # uncomment to show filtered version
355
355
356 if debug:
356 if debug:
357 print "Checking %s for %s" % (name, f)
357 print "Checking %s for %s" % (name, f)
358
358
359 prelines = None
359 prelines = None
360 errors = []
360 errors = []
361 for pat in pats:
361 for pat in pats:
362 if len(pat) == 3:
362 if len(pat) == 3:
363 p, msg, ignore = pat
363 p, msg, ignore = pat
364 else:
364 else:
365 p, msg = pat
365 p, msg = pat
366 ignore = None
366 ignore = None
367
367
368 # fix-up regexes for multiline searches
368 # fix-up regexes for multiline searches
369 po = p
369 po = p
370 # \s doesn't match \n
370 # \s doesn't match \n
371 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
371 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
372 # [^...] doesn't match newline
372 # [^...] doesn't match newline
373 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
373 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
374
374
375 #print po, '=>', p
375 #print po, '=>', p
376
376
377 pos = 0
377 pos = 0
378 n = 0
378 n = 0
379 for m in re.finditer(p, post, re.MULTILINE):
379 for m in re.finditer(p, post, re.MULTILINE):
380 if prelines is None:
380 if prelines is None:
381 prelines = pre.splitlines()
381 prelines = pre.splitlines()
382 postlines = post.splitlines(True)
382 postlines = post.splitlines(True)
383
383
384 start = m.start()
384 start = m.start()
385 while n < len(postlines):
385 while n < len(postlines):
386 step = len(postlines[n])
386 step = len(postlines[n])
387 if pos + step > start:
387 if pos + step > start:
388 break
388 break
389 pos += step
389 pos += step
390 n += 1
390 n += 1
391 l = prelines[n]
391 l = prelines[n]
392
392
393 if "check-code" + "-ignore" in l:
393 if "check-code" + "-ignore" in l:
394 if debug:
394 if debug:
395 print "Skipping %s for %s:%s (check-code -ignore)" % (
395 print "Skipping %s for %s:%s (check-code -ignore)" % (
396 name, f, n)
396 name, f, n)
397 continue
397 continue
398 elif ignore and re.search(ignore, l, re.MULTILINE):
398 elif ignore and re.search(ignore, l, re.MULTILINE):
399 continue
399 continue
400 bd = ""
400 bd = ""
401 if blame:
401 if blame:
402 bd = 'working directory'
402 bd = 'working directory'
403 if not blamecache:
403 if not blamecache:
404 blamecache = getblame(f)
404 blamecache = getblame(f)
405 if n < len(blamecache):
405 if n < len(blamecache):
406 bl, bu, br = blamecache[n]
406 bl, bu, br = blamecache[n]
407 if bl == l:
407 if bl == l:
408 bd = '%s@%s' % (bu, br)
408 bd = '%s@%s' % (bu, br)
409 errors.append((f, lineno and n + 1, l, msg, bd))
409 errors.append((f, lineno and n + 1, l, msg, bd))
410 result = False
410 result = False
411
411
412 errors.sort()
412 errors.sort()
413 for e in errors:
413 for e in errors:
414 logfunc(*e)
414 logfunc(*e)
415 fc += 1
415 fc += 1
416 if maxerr and fc >= maxerr:
416 if maxerr and fc >= maxerr:
417 print " (too many errors, giving up)"
417 print " (too many errors, giving up)"
418 break
418 break
419
419
420 return result
420 return result
421
421
422 if __name__ == "__main__":
422 if __name__ == "__main__":
423 parser = optparse.OptionParser("%prog [options] [files]")
423 parser = optparse.OptionParser("%prog [options] [files]")
424 parser.add_option("-w", "--warnings", action="store_true",
424 parser.add_option("-w", "--warnings", action="store_true",
425 help="include warning-level checks")
425 help="include warning-level checks")
426 parser.add_option("-p", "--per-file", type="int",
426 parser.add_option("-p", "--per-file", type="int",
427 help="max warnings per file")
427 help="max warnings per file")
428 parser.add_option("-b", "--blame", action="store_true",
428 parser.add_option("-b", "--blame", action="store_true",
429 help="use annotate to generate blame info")
429 help="use annotate to generate blame info")
430 parser.add_option("", "--debug", action="store_true",
430 parser.add_option("", "--debug", action="store_true",
431 help="show debug information")
431 help="show debug information")
432 parser.add_option("", "--nolineno", action="store_false",
432 parser.add_option("", "--nolineno", action="store_false",
433 dest='lineno', help="don't show line numbers")
433 dest='lineno', help="don't show line numbers")
434
434
435 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
435 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
436 lineno=True)
436 lineno=True)
437 (options, args) = parser.parse_args()
437 (options, args) = parser.parse_args()
438
438
439 if len(args) == 0:
439 if len(args) == 0:
440 check = glob.glob("*")
440 check = glob.glob("*")
441 else:
441 else:
442 check = args
442 check = args
443
443
444 ret = 0
444 ret = 0
445 for f in check:
445 for f in check:
446 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
446 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
447 blame=options.blame, debug=options.debug,
447 blame=options.blame, debug=options.debug,
448 lineno=options.lineno):
448 lineno=options.lineno):
449 ret = 1
449 ret = 1
450 sys.exit(ret)
450 sys.exit(ret)
@@ -1,322 +1,322
1 $ HGMERGE=true; export HGMERGE
1 $ HGMERGE=true; export HGMERGE
2
2
3 init
3 init
4
4
5 $ hg init repo
5 $ hg init repo
6 $ cd repo
6 $ cd repo
7
7
8 commit
8 commit
9
9
10 $ echo 'a' > a
10 $ echo 'a' > a
11 $ hg ci -A -m test -u nobody -d '1 0'
11 $ hg ci -A -m test -u nobody -d '1 0'
12 adding a
12 adding a
13
13
14 annotate -c
14 annotate -c
15
15
16 $ hg annotate -c a
16 $ hg annotate -c a
17 8435f90966e4: a
17 8435f90966e4: a
18
18
19 annotate -cl
19 annotate -cl
20
20
21 $ hg annotate -cl a
21 $ hg annotate -cl a
22 8435f90966e4:1: a
22 8435f90966e4:1: a
23
23
24 annotate -d
24 annotate -d
25
25
26 $ hg annotate -d a
26 $ hg annotate -d a
27 Thu Jan 01 00:00:01 1970 +0000: a
27 Thu Jan 01 00:00:01 1970 +0000: a
28
28
29 annotate -n
29 annotate -n
30
30
31 $ hg annotate -n a
31 $ hg annotate -n a
32 0: a
32 0: a
33
33
34 annotate -nl
34 annotate -nl
35
35
36 $ hg annotate -nl a
36 $ hg annotate -nl a
37 0:1: a
37 0:1: a
38
38
39 annotate -u
39 annotate -u
40
40
41 $ hg annotate -u a
41 $ hg annotate -u a
42 nobody: a
42 nobody: a
43
43
44 annotate -cdnu
44 annotate -cdnu
45
45
46 $ hg annotate -cdnu a
46 $ hg annotate -cdnu a
47 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000: a
47 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000: a
48
48
49 annotate -cdnul
49 annotate -cdnul
50
50
51 $ hg annotate -cdnul a
51 $ hg annotate -cdnul a
52 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000:1: a
52 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000:1: a
53
53
54 $ cat <<EOF >>a
54 $ cat <<EOF >>a
55 > a
55 > a
56 > a
56 > a
57 > EOF
57 > EOF
58 $ hg ci -ma1 -d '1 0'
58 $ hg ci -ma1 -d '1 0'
59 $ hg cp a b
59 $ hg cp a b
60 $ hg ci -mb -d '1 0'
60 $ hg ci -mb -d '1 0'
61 $ cat <<EOF >> b
61 $ cat <<EOF >> b
62 > b4
62 > b4
63 > b5
63 > b5
64 > b6
64 > b6
65 > EOF
65 > EOF
66 $ hg ci -mb2 -d '2 0'
66 $ hg ci -mb2 -d '2 0'
67
67
68 annotate -n b
68 annotate -n b
69
69
70 $ hg annotate -n b
70 $ hg annotate -n b
71 0: a
71 0: a
72 1: a
72 1: a
73 1: a
73 1: a
74 3: b4
74 3: b4
75 3: b5
75 3: b5
76 3: b6
76 3: b6
77
77
78 annotate --no-follow b
78 annotate --no-follow b
79
79
80 $ hg annotate --no-follow b
80 $ hg annotate --no-follow b
81 2: a
81 2: a
82 2: a
82 2: a
83 2: a
83 2: a
84 3: b4
84 3: b4
85 3: b5
85 3: b5
86 3: b6
86 3: b6
87
87
88 annotate -nl b
88 annotate -nl b
89
89
90 $ hg annotate -nl b
90 $ hg annotate -nl b
91 0:1: a
91 0:1: a
92 1:2: a
92 1:2: a
93 1:3: a
93 1:3: a
94 3:4: b4
94 3:4: b4
95 3:5: b5
95 3:5: b5
96 3:6: b6
96 3:6: b6
97
97
98 annotate -nf b
98 annotate -nf b
99
99
100 $ hg annotate -nf b
100 $ hg annotate -nf b
101 0 a: a
101 0 a: a
102 1 a: a
102 1 a: a
103 1 a: a
103 1 a: a
104 3 b: b4
104 3 b: b4
105 3 b: b5
105 3 b: b5
106 3 b: b6
106 3 b: b6
107
107
108 annotate -nlf b
108 annotate -nlf b
109
109
110 $ hg annotate -nlf b
110 $ hg annotate -nlf b
111 0 a:1: a
111 0 a:1: a
112 1 a:2: a
112 1 a:2: a
113 1 a:3: a
113 1 a:3: a
114 3 b:4: b4
114 3 b:4: b4
115 3 b:5: b5
115 3 b:5: b5
116 3 b:6: b6
116 3 b:6: b6
117
117
118 $ hg up -C 2
118 $ hg up -C 2
119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 $ cat <<EOF >> b
120 $ cat <<EOF >> b
121 > b4
121 > b4
122 > c
122 > c
123 > b5
123 > b5
124 > EOF
124 > EOF
125 $ hg ci -mb2.1 -d '2 0'
125 $ hg ci -mb2.1 -d '2 0'
126 created new head
126 created new head
127 $ hg merge
127 $ hg merge
128 merging b
128 merging b
129 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
129 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
130 (branch merge, don't forget to commit)
130 (branch merge, don't forget to commit)
131 $ hg ci -mmergeb -d '3 0'
131 $ hg ci -mmergeb -d '3 0'
132
132
133 annotate after merge
133 annotate after merge
134
134
135 $ hg annotate -nf b
135 $ hg annotate -nf b
136 0 a: a
136 0 a: a
137 1 a: a
137 1 a: a
138 1 a: a
138 1 a: a
139 3 b: b4
139 3 b: b4
140 4 b: c
140 4 b: c
141 3 b: b5
141 3 b: b5
142
142
143 annotate after merge with -l
143 annotate after merge with -l
144
144
145 $ hg annotate -nlf b
145 $ hg annotate -nlf b
146 0 a:1: a
146 0 a:1: a
147 1 a:2: a
147 1 a:2: a
148 1 a:3: a
148 1 a:3: a
149 3 b:4: b4
149 3 b:4: b4
150 4 b:5: c
150 4 b:5: c
151 3 b:5: b5
151 3 b:5: b5
152
152
153 $ hg up -C 1
153 $ hg up -C 1
154 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
154 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
155 $ hg cp a b
155 $ hg cp a b
156 $ cat <<EOF > b
156 $ cat <<EOF > b
157 > a
157 > a
158 > z
158 > z
159 > a
159 > a
160 > EOF
160 > EOF
161 $ hg ci -mc -d '3 0'
161 $ hg ci -mc -d '3 0'
162 created new head
162 created new head
163 $ hg merge
163 $ hg merge
164 merging b
164 merging b
165 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
165 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
166 (branch merge, don't forget to commit)
166 (branch merge, don't forget to commit)
167 $ cat <<EOF >> b
167 $ cat <<EOF >> b
168 > b4
168 > b4
169 > c
169 > c
170 > b5
170 > b5
171 > EOF
171 > EOF
172 $ echo d >> b
172 $ echo d >> b
173 $ hg ci -mmerge2 -d '4 0'
173 $ hg ci -mmerge2 -d '4 0'
174
174
175 annotate after rename merge
175 annotate after rename merge
176
176
177 $ hg annotate -nf b
177 $ hg annotate -nf b
178 0 a: a
178 0 a: a
179 6 b: z
179 6 b: z
180 1 a: a
180 1 a: a
181 3 b: b4
181 3 b: b4
182 4 b: c
182 4 b: c
183 3 b: b5
183 3 b: b5
184 7 b: d
184 7 b: d
185
185
186 annotate after rename merge with -l
186 annotate after rename merge with -l
187
187
188 $ hg annotate -nlf b
188 $ hg annotate -nlf b
189 0 a:1: a
189 0 a:1: a
190 6 b:2: z
190 6 b:2: z
191 1 a:3: a
191 1 a:3: a
192 3 b:4: b4
192 3 b:4: b4
193 4 b:5: c
193 4 b:5: c
194 3 b:5: b5
194 3 b:5: b5
195 7 b:7: d
195 7 b:7: d
196
196
197 Issue2807: alignment of line numbers with -l
197 Issue2807: alignment of line numbers with -l
198
198
199 $ echo more >> b
199 $ echo more >> b
200 $ hg ci -mmore -d '5 0'
200 $ hg ci -mmore -d '5 0'
201 $ echo more >> b
201 $ echo more >> b
202 $ hg ci -mmore -d '6 0'
202 $ hg ci -mmore -d '6 0'
203 $ echo more >> b
203 $ echo more >> b
204 $ hg ci -mmore -d '7 0'
204 $ hg ci -mmore -d '7 0'
205 $ hg annotate -nlf b
205 $ hg annotate -nlf b
206 0 a: 1: a
206 0 a: 1: a
207 6 b: 2: z
207 6 b: 2: z
208 1 a: 3: a
208 1 a: 3: a
209 3 b: 4: b4
209 3 b: 4: b4
210 4 b: 5: c
210 4 b: 5: c
211 3 b: 5: b5
211 3 b: 5: b5
212 7 b: 7: d
212 7 b: 7: d
213 8 b: 8: more
213 8 b: 8: more
214 9 b: 9: more
214 9 b: 9: more
215 10 b:10: more
215 10 b:10: more
216
216
217 linkrev vs rev
217 linkrev vs rev
218
218
219 $ hg annotate -r tip -n a
219 $ hg annotate -r tip -n a
220 0: a
220 0: a
221 1: a
221 1: a
222 1: a
222 1: a
223
223
224 linkrev vs rev with -l
224 linkrev vs rev with -l
225
225
226 $ hg annotate -r tip -nl a
226 $ hg annotate -r tip -nl a
227 0:1: a
227 0:1: a
228 1:2: a
228 1:2: a
229 1:3: a
229 1:3: a
230
230
231 Issue589: "undelete" sequence leads to crash
231 Issue589: "undelete" sequence leads to crash
232
232
233 annotate was crashing when trying to --follow something
233 annotate was crashing when trying to --follow something
234
234
235 like A -> B -> A
235 like A -> B -> A
236
236
237 generate ABA rename configuration
237 generate ABA rename configuration
238
238
239 $ echo foo > foo
239 $ echo foo > foo
240 $ hg add foo
240 $ hg add foo
241 $ hg ci -m addfoo
241 $ hg ci -m addfoo
242 $ hg rename foo bar
242 $ hg rename foo bar
243 $ hg ci -m renamefoo
243 $ hg ci -m renamefoo
244 $ hg rename bar foo
244 $ hg rename bar foo
245 $ hg ci -m renamebar
245 $ hg ci -m renamebar
246
246
247 annotate after ABA with follow
247 annotate after ABA with follow
248
248
249 $ hg annotate --follow foo
249 $ hg annotate --follow foo
250 foo: foo
250 foo: foo
251
251
252 missing file
252 missing file
253
253
254 $ hg ann nosuchfile
254 $ hg ann nosuchfile
255 abort: nosuchfile: no such file in rev e9e6b4fa872f
255 abort: nosuchfile: no such file in rev e9e6b4fa872f
256 [255]
256 [255]
257
257
258 annotate file without '\n' on last line
258 annotate file without '\n' on last line
259
259
260 $ printf "" > c
260 $ printf "" > c
261 $ hg ci -A -m test -u nobody -d '1 0'
261 $ hg ci -A -m test -u nobody -d '1 0'
262 adding c
262 adding c
263 $ hg annotate c
263 $ hg annotate c
264 $ printf "a\nb" > c
264 $ printf "a\nb" > c
265 $ hg ci -m test
265 $ hg ci -m test
266 $ hg annotate c
266 $ hg annotate c
267 [0-9]+: a (re)
267 [0-9]+: a (re)
268 [0-9]+: b (re)
268 [0-9]+: b (re)
269
269
270 Test annotate with whitespace options
270 Test annotate with whitespace options
271
271
272 $ cd ..
272 $ cd ..
273 $ hg init repo-ws
273 $ hg init repo-ws
274 $ cd repo-ws
274 $ cd repo-ws
275 $ cat > a <<EOF
275 $ cat > a <<EOF
276 > aa
276 > aa
277 >
277 >
278 > b b
278 > b b
279 > EOF
279 > EOF
280 $ hg ci -Am "adda"
280 $ hg ci -Am "adda"
281 adding a
281 adding a
282 $ cat > a <<EOF
282 $ sed 's/EOL$//g' > a <<EOF
283 > a a
283 > a a
284 >
284 >
285 >
285 > EOL
286 > b b
286 > b b
287 > EOF
287 > EOF
288 $ hg ci -m "changea"
288 $ hg ci -m "changea"
289
289
290 Annotate with no option
290 Annotate with no option
291
291
292 $ hg annotate a
292 $ hg annotate a
293 1: a a
293 1: a a
294 0:
294 0:
295 1:
295 1:
296 1: b b
296 1: b b
297
297
298 Annotate with --ignore-space-change
298 Annotate with --ignore-space-change
299
299
300 $ hg annotate --ignore-space-change a
300 $ hg annotate --ignore-space-change a
301 1: a a
301 1: a a
302 1:
302 1:
303 0:
303 0:
304 0: b b
304 0: b b
305
305
306 Annotate with --ignore-all-space
306 Annotate with --ignore-all-space
307
307
308 $ hg annotate --ignore-all-space a
308 $ hg annotate --ignore-all-space a
309 0: a a
309 0: a a
310 0:
310 0:
311 1:
311 1:
312 0: b b
312 0: b b
313
313
314 Annotate with --ignore-blank-lines (similar to no options case)
314 Annotate with --ignore-blank-lines (similar to no options case)
315
315
316 $ hg annotate --ignore-blank-lines a
316 $ hg annotate --ignore-blank-lines a
317 1: a a
317 1: a a
318 0:
318 0:
319 1:
319 1:
320 1: b b
320 1: b b
321
321
322 $ cd ..
322 $ cd ..
@@ -1,611 +1,611
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3
3
4 New file:
4 New file:
5
5
6 $ hg import -d "1000000 0" -mnew - <<EOF
6 $ hg import -d "1000000 0" -mnew - <<EOF
7 > diff --git a/new b/new
7 > diff --git a/new b/new
8 > new file mode 100644
8 > new file mode 100644
9 > index 0000000..7898192
9 > index 0000000..7898192
10 > --- /dev/null
10 > --- /dev/null
11 > +++ b/new
11 > +++ b/new
12 > @@ -0,0 +1 @@
12 > @@ -0,0 +1 @@
13 > +a
13 > +a
14 > EOF
14 > EOF
15 applying patch from stdin
15 applying patch from stdin
16
16
17 $ hg tip -q
17 $ hg tip -q
18 0:ae3ee40d2079
18 0:ae3ee40d2079
19
19
20 New empty file:
20 New empty file:
21
21
22 $ hg import -d "1000000 0" -mempty - <<EOF
22 $ hg import -d "1000000 0" -mempty - <<EOF
23 > diff --git a/empty b/empty
23 > diff --git a/empty b/empty
24 > new file mode 100644
24 > new file mode 100644
25 > EOF
25 > EOF
26 applying patch from stdin
26 applying patch from stdin
27
27
28 $ hg tip -q
28 $ hg tip -q
29 1:ab199dc869b5
29 1:ab199dc869b5
30
30
31 $ hg locate empty
31 $ hg locate empty
32 empty
32 empty
33
33
34 chmod +x:
34 chmod +x:
35
35
36 $ hg import -d "1000000 0" -msetx - <<EOF
36 $ hg import -d "1000000 0" -msetx - <<EOF
37 > diff --git a/new b/new
37 > diff --git a/new b/new
38 > old mode 100644
38 > old mode 100644
39 > new mode 100755
39 > new mode 100755
40 > EOF
40 > EOF
41 applying patch from stdin
41 applying patch from stdin
42
42
43 #if execbit
43 #if execbit
44 $ hg tip -q
44 $ hg tip -q
45 2:3a34410f282e
45 2:3a34410f282e
46 $ test -x new
46 $ test -x new
47 $ hg rollback -q
47 $ hg rollback -q
48 #else
48 #else
49 $ hg tip -q
49 $ hg tip -q
50 1:ab199dc869b5
50 1:ab199dc869b5
51 #endif
51 #endif
52
52
53 Copy and removing x bit:
53 Copy and removing x bit:
54
54
55 $ hg import -f -d "1000000 0" -mcopy - <<EOF
55 $ hg import -f -d "1000000 0" -mcopy - <<EOF
56 > diff --git a/new b/copy
56 > diff --git a/new b/copy
57 > old mode 100755
57 > old mode 100755
58 > new mode 100644
58 > new mode 100644
59 > similarity index 100%
59 > similarity index 100%
60 > copy from new
60 > copy from new
61 > copy to copy
61 > copy to copy
62 > diff --git a/new b/copyx
62 > diff --git a/new b/copyx
63 > similarity index 100%
63 > similarity index 100%
64 > copy from new
64 > copy from new
65 > copy to copyx
65 > copy to copyx
66 > EOF
66 > EOF
67 applying patch from stdin
67 applying patch from stdin
68
68
69 $ test -f copy
69 $ test -f copy
70 #if execbit
70 #if execbit
71 $ test ! -x copy
71 $ test ! -x copy
72 $ test -x copyx
72 $ test -x copyx
73 $ hg tip -q
73 $ hg tip -q
74 2:21dfaae65c71
74 2:21dfaae65c71
75 #else
75 #else
76 $ hg tip -q
76 $ hg tip -q
77 2:0efdaa8e3bf3
77 2:0efdaa8e3bf3
78 #endif
78 #endif
79
79
80 $ hg up -qCr1
80 $ hg up -qCr1
81 $ hg rollback -q
81 $ hg rollback -q
82
82
83 Copy (like above but independent of execbit):
83 Copy (like above but independent of execbit):
84
84
85 $ hg import -d "1000000 0" -mcopy - <<EOF
85 $ hg import -d "1000000 0" -mcopy - <<EOF
86 > diff --git a/new b/copy
86 > diff --git a/new b/copy
87 > similarity index 100%
87 > similarity index 100%
88 > copy from new
88 > copy from new
89 > copy to copy
89 > copy to copy
90 > diff --git a/new b/copyx
90 > diff --git a/new b/copyx
91 > similarity index 100%
91 > similarity index 100%
92 > copy from new
92 > copy from new
93 > copy to copyx
93 > copy to copyx
94 > EOF
94 > EOF
95 applying patch from stdin
95 applying patch from stdin
96
96
97 $ hg tip -q
97 $ hg tip -q
98 2:0efdaa8e3bf3
98 2:0efdaa8e3bf3
99 $ test -f copy
99 $ test -f copy
100
100
101 $ cat copy
101 $ cat copy
102 a
102 a
103
103
104 $ hg cat copy
104 $ hg cat copy
105 a
105 a
106
106
107 Rename:
107 Rename:
108
108
109 $ hg import -d "1000000 0" -mrename - <<EOF
109 $ hg import -d "1000000 0" -mrename - <<EOF
110 > diff --git a/copy b/rename
110 > diff --git a/copy b/rename
111 > similarity index 100%
111 > similarity index 100%
112 > rename from copy
112 > rename from copy
113 > rename to rename
113 > rename to rename
114 > EOF
114 > EOF
115 applying patch from stdin
115 applying patch from stdin
116
116
117 $ hg tip -q
117 $ hg tip -q
118 3:b1f57753fad2
118 3:b1f57753fad2
119
119
120 $ hg locate
120 $ hg locate
121 copyx
121 copyx
122 empty
122 empty
123 new
123 new
124 rename
124 rename
125
125
126 Delete:
126 Delete:
127
127
128 $ hg import -d "1000000 0" -mdelete - <<EOF
128 $ hg import -d "1000000 0" -mdelete - <<EOF
129 > diff --git a/copyx b/copyx
129 > diff --git a/copyx b/copyx
130 > deleted file mode 100755
130 > deleted file mode 100755
131 > index 7898192..0000000
131 > index 7898192..0000000
132 > --- a/copyx
132 > --- a/copyx
133 > +++ /dev/null
133 > +++ /dev/null
134 > @@ -1 +0,0 @@
134 > @@ -1 +0,0 @@
135 > -a
135 > -a
136 > EOF
136 > EOF
137 applying patch from stdin
137 applying patch from stdin
138
138
139 $ hg tip -q
139 $ hg tip -q
140 4:1bd1da94b9b2
140 4:1bd1da94b9b2
141
141
142 $ hg locate
142 $ hg locate
143 empty
143 empty
144 new
144 new
145 rename
145 rename
146
146
147 $ test -f copyx
147 $ test -f copyx
148 [1]
148 [1]
149
149
150 Regular diff:
150 Regular diff:
151
151
152 $ hg import -d "1000000 0" -mregular - <<EOF
152 $ hg import -d "1000000 0" -mregular - <<EOF
153 > diff --git a/rename b/rename
153 > diff --git a/rename b/rename
154 > index 7898192..72e1fe3 100644
154 > index 7898192..72e1fe3 100644
155 > --- a/rename
155 > --- a/rename
156 > +++ b/rename
156 > +++ b/rename
157 > @@ -1 +1,5 @@
157 > @@ -1 +1,5 @@
158 > a
158 > a
159 > +a
159 > +a
160 > +a
160 > +a
161 > +a
161 > +a
162 > +a
162 > +a
163 > EOF
163 > EOF
164 applying patch from stdin
164 applying patch from stdin
165
165
166 $ hg tip -q
166 $ hg tip -q
167 5:46fe99cb3035
167 5:46fe99cb3035
168
168
169 Copy and modify:
169 Copy and modify:
170
170
171 $ hg import -d "1000000 0" -mcopymod - <<EOF
171 $ hg import -d "1000000 0" -mcopymod - <<EOF
172 > diff --git a/rename b/copy2
172 > diff --git a/rename b/copy2
173 > similarity index 80%
173 > similarity index 80%
174 > copy from rename
174 > copy from rename
175 > copy to copy2
175 > copy to copy2
176 > index 72e1fe3..b53c148 100644
176 > index 72e1fe3..b53c148 100644
177 > --- a/rename
177 > --- a/rename
178 > +++ b/copy2
178 > +++ b/copy2
179 > @@ -1,5 +1,5 @@
179 > @@ -1,5 +1,5 @@
180 > a
180 > a
181 > a
181 > a
182 > -a
182 > -a
183 > +b
183 > +b
184 > a
184 > a
185 > a
185 > a
186 > EOF
186 > EOF
187 applying patch from stdin
187 applying patch from stdin
188
188
189 $ hg tip -q
189 $ hg tip -q
190 6:ffeb3197c12d
190 6:ffeb3197c12d
191
191
192 $ hg cat copy2
192 $ hg cat copy2
193 a
193 a
194 a
194 a
195 b
195 b
196 a
196 a
197 a
197 a
198
198
199 Rename and modify:
199 Rename and modify:
200
200
201 $ hg import -d "1000000 0" -mrenamemod - <<EOF
201 $ hg import -d "1000000 0" -mrenamemod - <<EOF
202 > diff --git a/copy2 b/rename2
202 > diff --git a/copy2 b/rename2
203 > similarity index 80%
203 > similarity index 80%
204 > rename from copy2
204 > rename from copy2
205 > rename to rename2
205 > rename to rename2
206 > index b53c148..8f81e29 100644
206 > index b53c148..8f81e29 100644
207 > --- a/copy2
207 > --- a/copy2
208 > +++ b/rename2
208 > +++ b/rename2
209 > @@ -1,5 +1,5 @@
209 > @@ -1,5 +1,5 @@
210 > a
210 > a
211 > a
211 > a
212 > b
212 > b
213 > -a
213 > -a
214 > +c
214 > +c
215 > a
215 > a
216 > EOF
216 > EOF
217 applying patch from stdin
217 applying patch from stdin
218
218
219 $ hg tip -q
219 $ hg tip -q
220 7:401aede9e6bb
220 7:401aede9e6bb
221
221
222 $ hg locate copy2
222 $ hg locate copy2
223 [1]
223 [1]
224 $ hg cat rename2
224 $ hg cat rename2
225 a
225 a
226 a
226 a
227 b
227 b
228 c
228 c
229 a
229 a
230
230
231 One file renamed multiple times:
231 One file renamed multiple times:
232
232
233 $ hg import -d "1000000 0" -mmultirenames - <<EOF
233 $ hg import -d "1000000 0" -mmultirenames - <<EOF
234 > diff --git a/rename2 b/rename3
234 > diff --git a/rename2 b/rename3
235 > rename from rename2
235 > rename from rename2
236 > rename to rename3
236 > rename to rename3
237 > diff --git a/rename2 b/rename3-2
237 > diff --git a/rename2 b/rename3-2
238 > rename from rename2
238 > rename from rename2
239 > rename to rename3-2
239 > rename to rename3-2
240 > EOF
240 > EOF
241 applying patch from stdin
241 applying patch from stdin
242
242
243 $ hg tip -q
243 $ hg tip -q
244 8:2ef727e684e8
244 8:2ef727e684e8
245
245
246 $ hg log -vr. --template '{rev} {files} / {file_copies}\n'
246 $ hg log -vr. --template '{rev} {files} / {file_copies}\n'
247 8 rename2 rename3 rename3-2 / rename3 (rename2)rename3-2 (rename2)
247 8 rename2 rename3 rename3-2 / rename3 (rename2)rename3-2 (rename2)
248
248
249 $ hg locate rename2 rename3 rename3-2
249 $ hg locate rename2 rename3 rename3-2
250 rename3
250 rename3
251 rename3-2
251 rename3-2
252
252
253 $ hg cat rename3
253 $ hg cat rename3
254 a
254 a
255 a
255 a
256 b
256 b
257 c
257 c
258 a
258 a
259
259
260 $ hg cat rename3-2
260 $ hg cat rename3-2
261 a
261 a
262 a
262 a
263 b
263 b
264 c
264 c
265 a
265 a
266
266
267 $ echo foo > foo
267 $ echo foo > foo
268 $ hg add foo
268 $ hg add foo
269 $ hg ci -m 'add foo'
269 $ hg ci -m 'add foo'
270
270
271 Binary files and regular patch hunks:
271 Binary files and regular patch hunks:
272
272
273 $ hg import -d "1000000 0" -m binaryregular - <<EOF
273 $ hg import -d "1000000 0" -m binaryregular - <<EOF
274 > diff --git a/binary b/binary
274 > diff --git a/binary b/binary
275 > new file mode 100644
275 > new file mode 100644
276 > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4
276 > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4
277 > GIT binary patch
277 > GIT binary patch
278 > literal 4
278 > literal 4
279 > Lc\${NkU|;|M00aO5
279 > Lc\${NkU|;|M00aO5
280 >
280 >
281 > diff --git a/foo b/foo2
281 > diff --git a/foo b/foo2
282 > rename from foo
282 > rename from foo
283 > rename to foo2
283 > rename to foo2
284 > EOF
284 > EOF
285 applying patch from stdin
285 applying patch from stdin
286
286
287 $ hg tip -q
287 $ hg tip -q
288 10:27377172366e
288 10:27377172366e
289
289
290 $ cat foo2
290 $ cat foo2
291 foo
291 foo
292
292
293 $ hg manifest --debug | grep binary
293 $ hg manifest --debug | grep binary
294 045c85ba38952325e126c70962cc0f9d9077bc67 644 binary
294 045c85ba38952325e126c70962cc0f9d9077bc67 644 binary
295
295
296 Multiple binary files:
296 Multiple binary files:
297
297
298 $ hg import -d "1000000 0" -m multibinary - <<EOF
298 $ hg import -d "1000000 0" -m multibinary - <<EOF
299 > diff --git a/mbinary1 b/mbinary1
299 > diff --git a/mbinary1 b/mbinary1
300 > new file mode 100644
300 > new file mode 100644
301 > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4
301 > index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4
302 > GIT binary patch
302 > GIT binary patch
303 > literal 4
303 > literal 4
304 > Lc\${NkU|;|M00aO5
304 > Lc\${NkU|;|M00aO5
305 >
305 >
306 > diff --git a/mbinary2 b/mbinary2
306 > diff --git a/mbinary2 b/mbinary2
307 > new file mode 100644
307 > new file mode 100644
308 > index 0000000000000000000000000000000000000000..112363ac1917b417ffbd7f376ca786a1e5fa7490
308 > index 0000000000000000000000000000000000000000..112363ac1917b417ffbd7f376ca786a1e5fa7490
309 > GIT binary patch
309 > GIT binary patch
310 > literal 5
310 > literal 5
311 > Mc\${NkU|\`?^000jF3jhEB
311 > Mc\${NkU|\`?^000jF3jhEB
312 >
312 >
313 > EOF
313 > EOF
314 applying patch from stdin
314 applying patch from stdin
315
315
316 $ hg tip -q
316 $ hg tip -q
317 11:18b73a84b4ab
317 11:18b73a84b4ab
318
318
319 $ hg manifest --debug | grep mbinary
319 $ hg manifest --debug | grep mbinary
320 045c85ba38952325e126c70962cc0f9d9077bc67 644 mbinary1
320 045c85ba38952325e126c70962cc0f9d9077bc67 644 mbinary1
321 a874b471193996e7cb034bb301cac7bdaf3e3f46 644 mbinary2
321 a874b471193996e7cb034bb301cac7bdaf3e3f46 644 mbinary2
322
322
323 Filenames with spaces:
323 Filenames with spaces:
324
324
325 $ hg import -d "1000000 0" -m spaces - <<EOF
325 $ sed 's,EOL$,,g' <<EOF | hg import -d "1000000 0" -m spaces -
326 > diff --git a/foo bar b/foo bar
326 > diff --git a/foo bar b/foo bar
327 > new file mode 100644
327 > new file mode 100644
328 > index 0000000..257cc56
328 > index 0000000..257cc56
329 > --- /dev/null
329 > --- /dev/null
330 > +++ b/foo bar
330 > +++ b/foo bar EOL
331 > @@ -0,0 +1 @@
331 > @@ -0,0 +1 @@
332 > +foo
332 > +foo
333 > EOF
333 > EOF
334 applying patch from stdin
334 applying patch from stdin
335
335
336 $ hg tip -q
336 $ hg tip -q
337 12:47500ce1614e
337 12:47500ce1614e
338
338
339 $ cat "foo bar"
339 $ cat "foo bar"
340 foo
340 foo
341
341
342 Copy then modify the original file:
342 Copy then modify the original file:
343
343
344 $ hg import -d "1000000 0" -m copy-mod-orig - <<EOF
344 $ hg import -d "1000000 0" -m copy-mod-orig - <<EOF
345 > diff --git a/foo2 b/foo2
345 > diff --git a/foo2 b/foo2
346 > index 257cc56..fe08ec6 100644
346 > index 257cc56..fe08ec6 100644
347 > --- a/foo2
347 > --- a/foo2
348 > +++ b/foo2
348 > +++ b/foo2
349 > @@ -1 +1,2 @@
349 > @@ -1 +1,2 @@
350 > foo
350 > foo
351 > +new line
351 > +new line
352 > diff --git a/foo2 b/foo3
352 > diff --git a/foo2 b/foo3
353 > similarity index 100%
353 > similarity index 100%
354 > copy from foo2
354 > copy from foo2
355 > copy to foo3
355 > copy to foo3
356 > EOF
356 > EOF
357 applying patch from stdin
357 applying patch from stdin
358
358
359 $ hg tip -q
359 $ hg tip -q
360 13:6757efb07ea9
360 13:6757efb07ea9
361
361
362 $ cat foo3
362 $ cat foo3
363 foo
363 foo
364
364
365 Move text file and patch as binary
365 Move text file and patch as binary
366
366
367 $ echo a > text2
367 $ echo a > text2
368 $ hg ci -Am0
368 $ hg ci -Am0
369 adding text2
369 adding text2
370 $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
370 $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
371 > diff --git a/text2 b/binary2
371 > diff --git a/text2 b/binary2
372 > rename from text2
372 > rename from text2
373 > rename to binary2
373 > rename to binary2
374 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
374 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
375 > GIT binary patch
375 > GIT binary patch
376 > literal 5
376 > literal 5
377 > Mc$`b*O5$Pw00T?_*Z=?k
377 > Mc$`b*O5$Pw00T?_*Z=?k
378 >
378 >
379 > EOF
379 > EOF
380 applying patch from stdin
380 applying patch from stdin
381
381
382 $ cat binary2
382 $ cat binary2
383 a
383 a
384 b
384 b
385 \x00 (no-eol) (esc)
385 \x00 (no-eol) (esc)
386
386
387 $ hg st --copies --change .
387 $ hg st --copies --change .
388 A binary2
388 A binary2
389 text2
389 text2
390 R text2
390 R text2
391
391
392 Invalid base85 content
392 Invalid base85 content
393
393
394 $ hg rollback
394 $ hg rollback
395 repository tip rolled back to revision 14 (undo import)
395 repository tip rolled back to revision 14 (undo import)
396 working directory now based on revision 14
396 working directory now based on revision 14
397 $ hg revert -aq
397 $ hg revert -aq
398 $ hg import -d "1000000 0" -m invalid-binary - <<"EOF"
398 $ hg import -d "1000000 0" -m invalid-binary - <<"EOF"
399 > diff --git a/text2 b/binary2
399 > diff --git a/text2 b/binary2
400 > rename from text2
400 > rename from text2
401 > rename to binary2
401 > rename to binary2
402 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
402 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
403 > GIT binary patch
403 > GIT binary patch
404 > literal 5
404 > literal 5
405 > Mc$`b*O.$Pw00T?_*Z=?k
405 > Mc$`b*O.$Pw00T?_*Z=?k
406 >
406 >
407 > EOF
407 > EOF
408 applying patch from stdin
408 applying patch from stdin
409 abort: could not decode "binary2" binary patch: bad base85 character at position 6
409 abort: could not decode "binary2" binary patch: bad base85 character at position 6
410 [255]
410 [255]
411
411
412 $ hg revert -aq
412 $ hg revert -aq
413 $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
413 $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
414 > diff --git a/text2 b/binary2
414 > diff --git a/text2 b/binary2
415 > rename from text2
415 > rename from text2
416 > rename to binary2
416 > rename to binary2
417 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
417 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
418 > GIT binary patch
418 > GIT binary patch
419 > literal 6
419 > literal 6
420 > Mc$`b*O5$Pw00T?_*Z=?k
420 > Mc$`b*O5$Pw00T?_*Z=?k
421 >
421 >
422 > EOF
422 > EOF
423 applying patch from stdin
423 applying patch from stdin
424 abort: "binary2" length is 5 bytes, should be 6
424 abort: "binary2" length is 5 bytes, should be 6
425 [255]
425 [255]
426
426
427 $ hg revert -aq
427 $ hg revert -aq
428 $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
428 $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
429 > diff --git a/text2 b/binary2
429 > diff --git a/text2 b/binary2
430 > rename from text2
430 > rename from text2
431 > rename to binary2
431 > rename to binary2
432 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
432 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
433 > GIT binary patch
433 > GIT binary patch
434 > Mc$`b*O5$Pw00T?_*Z=?k
434 > Mc$`b*O5$Pw00T?_*Z=?k
435 >
435 >
436 > EOF
436 > EOF
437 applying patch from stdin
437 applying patch from stdin
438 abort: could not extract "binary2" binary data
438 abort: could not extract "binary2" binary data
439 [255]
439 [255]
440
440
441 Simulate a copy/paste turning LF into CRLF (issue2870)
441 Simulate a copy/paste turning LF into CRLF (issue2870)
442
442
443 $ hg revert -aq
443 $ hg revert -aq
444 $ cat > binary.diff <<"EOF"
444 $ cat > binary.diff <<"EOF"
445 > diff --git a/text2 b/binary2
445 > diff --git a/text2 b/binary2
446 > rename from text2
446 > rename from text2
447 > rename to binary2
447 > rename to binary2
448 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
448 > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
449 > GIT binary patch
449 > GIT binary patch
450 > literal 5
450 > literal 5
451 > Mc$`b*O5$Pw00T?_*Z=?k
451 > Mc$`b*O5$Pw00T?_*Z=?k
452 >
452 >
453 > EOF
453 > EOF
454 >>> fp = file('binary.diff', 'rb')
454 >>> fp = file('binary.diff', 'rb')
455 >>> data = fp.read()
455 >>> data = fp.read()
456 >>> fp.close()
456 >>> fp.close()
457 >>> file('binary.diff', 'wb').write(data.replace('\n', '\r\n'))
457 >>> file('binary.diff', 'wb').write(data.replace('\n', '\r\n'))
458 $ rm binary2
458 $ rm binary2
459 $ hg import --no-commit binary.diff
459 $ hg import --no-commit binary.diff
460 applying binary.diff
460 applying binary.diff
461
461
462 $ cd ..
462 $ cd ..
463
463
464 Consecutive import with renames (issue2459)
464 Consecutive import with renames (issue2459)
465
465
466 $ hg init issue2459
466 $ hg init issue2459
467 $ cd issue2459
467 $ cd issue2459
468 $ hg import --no-commit --force - <<EOF
468 $ hg import --no-commit --force - <<EOF
469 > diff --git a/a b/a
469 > diff --git a/a b/a
470 > new file mode 100644
470 > new file mode 100644
471 > EOF
471 > EOF
472 applying patch from stdin
472 applying patch from stdin
473 $ hg import --no-commit --force - <<EOF
473 $ hg import --no-commit --force - <<EOF
474 > diff --git a/a b/b
474 > diff --git a/a b/b
475 > rename from a
475 > rename from a
476 > rename to b
476 > rename to b
477 > EOF
477 > EOF
478 applying patch from stdin
478 applying patch from stdin
479 a has not been committed yet, so no copy data will be stored for b.
479 a has not been committed yet, so no copy data will be stored for b.
480 $ hg debugstate
480 $ hg debugstate
481 a 0 -1 unset b
481 a 0 -1 unset b
482 $ hg ci -m done
482 $ hg ci -m done
483 $ cd ..
483 $ cd ..
484
484
485 Renames and strip
485 Renames and strip
486
486
487 $ hg init renameandstrip
487 $ hg init renameandstrip
488 $ cd renameandstrip
488 $ cd renameandstrip
489 $ echo a > a
489 $ echo a > a
490 $ hg ci -Am adda
490 $ hg ci -Am adda
491 adding a
491 adding a
492 $ hg import --no-commit -p2 - <<EOF
492 $ hg import --no-commit -p2 - <<EOF
493 > diff --git a/foo/a b/foo/b
493 > diff --git a/foo/a b/foo/b
494 > rename from foo/a
494 > rename from foo/a
495 > rename to foo/b
495 > rename to foo/b
496 > EOF
496 > EOF
497 applying patch from stdin
497 applying patch from stdin
498 $ hg st --copies
498 $ hg st --copies
499 A b
499 A b
500 a
500 a
501 R a
501 R a
502
502
503 Renames, similarity and git diff
503 Renames, similarity and git diff
504
504
505 $ hg revert -aC
505 $ hg revert -aC
506 undeleting a
506 undeleting a
507 forgetting b
507 forgetting b
508 $ rm b
508 $ rm b
509 $ hg import --similarity 90 --no-commit - <<EOF
509 $ hg import --similarity 90 --no-commit - <<EOF
510 > diff --git a/a b/b
510 > diff --git a/a b/b
511 > rename from a
511 > rename from a
512 > rename to b
512 > rename to b
513 > EOF
513 > EOF
514 applying patch from stdin
514 applying patch from stdin
515 $ hg st --copies
515 $ hg st --copies
516 A b
516 A b
517 a
517 a
518 R a
518 R a
519 $ cd ..
519 $ cd ..
520
520
521 Pure copy with existing destination
521 Pure copy with existing destination
522
522
523 $ hg init copytoexisting
523 $ hg init copytoexisting
524 $ cd copytoexisting
524 $ cd copytoexisting
525 $ echo a > a
525 $ echo a > a
526 $ echo b > b
526 $ echo b > b
527 $ hg ci -Am add
527 $ hg ci -Am add
528 adding a
528 adding a
529 adding b
529 adding b
530 $ hg import --no-commit - <<EOF
530 $ hg import --no-commit - <<EOF
531 > diff --git a/a b/b
531 > diff --git a/a b/b
532 > copy from a
532 > copy from a
533 > copy to b
533 > copy to b
534 > EOF
534 > EOF
535 applying patch from stdin
535 applying patch from stdin
536 abort: cannot create b: destination already exists
536 abort: cannot create b: destination already exists
537 [255]
537 [255]
538 $ cat b
538 $ cat b
539 b
539 b
540
540
541 Copy and changes with existing destination
541 Copy and changes with existing destination
542
542
543 $ hg import --no-commit - <<EOF
543 $ hg import --no-commit - <<EOF
544 > diff --git a/a b/b
544 > diff --git a/a b/b
545 > copy from a
545 > copy from a
546 > copy to b
546 > copy to b
547 > --- a/a
547 > --- a/a
548 > +++ b/b
548 > +++ b/b
549 > @@ -1,1 +1,2 @@
549 > @@ -1,1 +1,2 @@
550 > a
550 > a
551 > +b
551 > +b
552 > EOF
552 > EOF
553 applying patch from stdin
553 applying patch from stdin
554 cannot create b: destination already exists
554 cannot create b: destination already exists
555 1 out of 1 hunks FAILED -- saving rejects to file b.rej
555 1 out of 1 hunks FAILED -- saving rejects to file b.rej
556 abort: patch failed to apply
556 abort: patch failed to apply
557 [255]
557 [255]
558 $ cat b
558 $ cat b
559 b
559 b
560
560
561 #if symlink
561 #if symlink
562
562
563 $ ln -s b linkb
563 $ ln -s b linkb
564 $ hg add linkb
564 $ hg add linkb
565 $ hg ci -m addlinkb
565 $ hg ci -m addlinkb
566 $ hg import --no-commit - <<EOF
566 $ hg import --no-commit - <<EOF
567 > diff --git a/linkb b/linkb
567 > diff --git a/linkb b/linkb
568 > deleted file mode 120000
568 > deleted file mode 120000
569 > --- a/linkb
569 > --- a/linkb
570 > +++ /dev/null
570 > +++ /dev/null
571 > @@ -1,1 +0,0 @@
571 > @@ -1,1 +0,0 @@
572 > -badhunk
572 > -badhunk
573 > \ No newline at end of file
573 > \ No newline at end of file
574 > EOF
574 > EOF
575 applying patch from stdin
575 applying patch from stdin
576 patching file linkb
576 patching file linkb
577 Hunk #1 FAILED at 0
577 Hunk #1 FAILED at 0
578 1 out of 1 hunks FAILED -- saving rejects to file linkb.rej
578 1 out of 1 hunks FAILED -- saving rejects to file linkb.rej
579 abort: patch failed to apply
579 abort: patch failed to apply
580 [255]
580 [255]
581 $ hg st
581 $ hg st
582 ? b.rej
582 ? b.rej
583 ? linkb.rej
583 ? linkb.rej
584
584
585 #endif
585 #endif
586
586
587 Test corner case involving copies and multiple hunks (issue3384)
587 Test corner case involving copies and multiple hunks (issue3384)
588
588
589 $ hg revert -qa
589 $ hg revert -qa
590 $ hg import --no-commit - <<EOF
590 $ hg import --no-commit - <<EOF
591 > diff --git a/a b/c
591 > diff --git a/a b/c
592 > copy from a
592 > copy from a
593 > copy to c
593 > copy to c
594 > --- a/a
594 > --- a/a
595 > +++ b/c
595 > +++ b/c
596 > @@ -1,1 +1,2 @@
596 > @@ -1,1 +1,2 @@
597 > a
597 > a
598 > +a
598 > +a
599 > @@ -2,1 +2,2 @@
599 > @@ -2,1 +2,2 @@
600 > a
600 > a
601 > +a
601 > +a
602 > diff --git a/a b/a
602 > diff --git a/a b/a
603 > --- a/a
603 > --- a/a
604 > +++ b/a
604 > +++ b/a
605 > @@ -1,1 +1,2 @@
605 > @@ -1,1 +1,2 @@
606 > a
606 > a
607 > +b
607 > +b
608 > EOF
608 > EOF
609 applying patch from stdin
609 applying patch from stdin
610
610
611 $ cd ..
611 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now