##// END OF EJS Templates
tests: tighten checks for octal escapes in shell printf....
Jim Hague -
r16098:c6c9b83a stable
parent child Browse files
Show More
@@ -1,430 +1,430 b''
1 1 #!/usr/bin/env python
2 2 #
3 3 # check-code - a style and portability checker for Mercurial
4 4 #
5 5 # Copyright 2010 Matt Mackall <mpm@selenic.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 import re, glob, os, sys
11 11 import keyword
12 12 import optparse
13 13
14 14 def repquote(m):
15 15 t = re.sub(r"\w", "x", m.group('text'))
16 16 t = re.sub(r"[^\s\nx]", "o", t)
17 17 return m.group('quote') + t + m.group('quote')
18 18
19 19 def reppython(m):
20 20 comment = m.group('comment')
21 21 if comment:
22 22 return "#" * len(comment)
23 23 return repquote(m)
24 24
25 25 def repcomment(m):
26 26 return m.group(1) + "#" * len(m.group(2))
27 27
28 28 def repccomment(m):
29 29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
30 30 return m.group(1) + t + "*/"
31 31
32 32 def repcallspaces(m):
33 33 t = re.sub(r"\n\s+", "\n", m.group(2))
34 34 return m.group(1) + t
35 35
36 36 def repinclude(m):
37 37 return m.group(1) + "<foo>"
38 38
39 39 def rephere(m):
40 40 t = re.sub(r"\S", "x", m.group(2))
41 41 return m.group(1) + t
42 42
43 43
44 44 testpats = [
45 45 [
46 46 (r'(pushd|popd)', "don't use 'pushd' or 'popd', use 'cd'"),
47 47 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
48 48 (r'^function', "don't use 'function', use old style"),
49 49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
50 50 (r'echo.*\\n', "don't use 'echo \\n', use printf"),
51 51 (r'echo -n', "don't use 'echo -n', use printf"),
52 52 (r'^diff.*-\w*N', "don't use 'diff -N'"),
53 53 (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
54 54 (r'head -c', "don't use 'head -c', use 'dd'"),
55 55 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
56 56 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
57 (r'printf.*\\\d\d\d', "don't use 'printf \NNN', use Python"),
57 (r'printf.*\\\d{1,3}', "don't use 'printf \NNN', use Python"),
58 58 (r'printf.*\\x', "don't use printf \\x, use Python"),
59 59 (r'\$\(.*\)', "don't use $(expr), use `expr`"),
60 60 (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
61 61 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
62 62 "use egrep for extended grep syntax"),
63 63 (r'/bin/', "don't use explicit paths for tools"),
64 64 (r'\$PWD', "don't use $PWD, use `pwd`"),
65 65 (r'[^\n]\Z', "no trailing newline"),
66 66 (r'export.*=', "don't export and assign at once"),
67 67 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\\^', "^ must be quoted"),
68 68 (r'^source\b', "don't use 'source', use '.'"),
69 69 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
70 70 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
71 71 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
72 72 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
73 73 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
74 74 (r'^alias\b.*=', "don't use alias, use a function"),
75 75 ],
76 76 # warnings
77 77 []
78 78 ]
79 79
80 80 testfilters = [
81 81 (r"( *)(#([^\n]*\S)?)", repcomment),
82 82 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
83 83 ]
84 84
85 85 uprefix = r"^ \$ "
86 86 uprefixc = r"^ > "
87 87 utestpats = [
88 88 [
89 89 (r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"),
90 90 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"),
91 91 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
92 92 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
93 93 (uprefix + r'.*\|\| echo.*(fail|error)',
94 94 "explicit exit code checks unnecessary"),
95 95 (uprefix + r'set -e', "don't use set -e"),
96 96 (uprefixc + r'( *)\t', "don't use tabs to indent"),
97 97 ],
98 98 # warnings
99 99 []
100 100 ]
101 101
102 102 for i in [0, 1]:
103 103 for p, m in testpats[i]:
104 104 if p.startswith(r'^'):
105 105 p = uprefix + p[1:]
106 106 else:
107 107 p = uprefix + ".*" + p
108 108 utestpats[i].append((p, m))
109 109
110 110 utestfilters = [
111 111 (r"( *)(#([^\n]*\S)?)", repcomment),
112 112 ]
113 113
114 114 pypats = [
115 115 [
116 116 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
117 117 "tuple parameter unpacking not available in Python 3+"),
118 118 (r'lambda\s*\(.*,.*\)',
119 119 "tuple parameter unpacking not available in Python 3+"),
120 120 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
121 121 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
122 122 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
123 123 (r'^\s*\t', "don't use tabs"),
124 124 (r'\S;\s*\n', "semicolon"),
125 125 (r'\w,\w', "missing whitespace after ,"),
126 126 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
127 127 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
128 128 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
129 129 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Py2.4'),
130 130 (r'.{85}', "line too long"),
131 131 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
132 132 (r'[^\n]\Z', "no trailing newline"),
133 133 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
134 134 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
135 135 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
136 136 "don't use camelcase in identifiers"),
137 137 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
138 138 "linebreak after :"),
139 139 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
140 140 (r'class\s[^( \n]+\(\):',
141 141 "class foo() not available in Python 2.4, use class foo(object)"),
142 142 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
143 143 "Python keyword is not a function"),
144 144 (r',]', "unneeded trailing ',' in list"),
145 145 # (r'class\s[A-Z][^\(]*\((?!Exception)',
146 146 # "don't capitalize non-exception classes"),
147 147 # (r'in range\(', "use xrange"),
148 148 # (r'^\s*print\s+', "avoid using print in core and extensions"),
149 149 (r'[\x80-\xff]', "non-ASCII character literal"),
150 150 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
151 151 (r'^\s*with\s+', "with not available in Python 2.4"),
152 152 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
153 153 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
154 154 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
155 155 (r'(?<!def)\s+(any|all|format)\(',
156 156 "any/all/format not available in Python 2.4"),
157 157 (r'(?<!def)\s+(callable)\(',
158 158 "callable not available in Python 3, use getattr(f, '__call__', None)"),
159 159 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
160 160 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
161 161 "gratuitous whitespace after Python keyword"),
162 162 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
163 163 # (r'\s\s=', "gratuitous whitespace before ="),
164 164 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
165 165 "missing whitespace around operator"),
166 166 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s',
167 167 "missing whitespace around operator"),
168 168 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
169 169 "missing whitespace around operator"),
170 170 (r'[^+=*/!<>&| -](\s=|=\s)[^= ]',
171 171 "wrong whitespace around ="),
172 172 (r'raise Exception', "don't raise generic exceptions"),
173 173 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
174 174 (r' [=!]=\s+(True|False|None)',
175 175 "comparison with singleton, use 'is' or 'is not' instead"),
176 176 (r'^\s*(while|if) [01]:',
177 177 "use True/False for constant Boolean expression"),
178 178 (r'(?<!def)\s+hasattr',
179 179 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
180 180 (r'opener\([^)]*\).read\(',
181 181 "use opener.read() instead"),
182 182 (r'BaseException', 'not in Py2.4, use Exception'),
183 183 (r'os\.path\.relpath', 'os.path.relpath is not in Py2.5'),
184 184 (r'opener\([^)]*\).write\(',
185 185 "use opener.write() instead"),
186 186 (r'[\s\(](open|file)\([^)]*\)\.read\(',
187 187 "use util.readfile() instead"),
188 188 (r'[\s\(](open|file)\([^)]*\)\.write\(',
189 189 "use util.readfile() instead"),
190 190 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
191 191 "always assign an opened file to a variable, and close it afterwards"),
192 192 (r'[\s\(](open|file)\([^)]*\)\.',
193 193 "always assign an opened file to a variable, and close it afterwards"),
194 194 (r'(?i)descendent', "the proper spelling is descendAnt"),
195 195 (r'\.debug\(\_', "don't mark debug messages for translation"),
196 196 ],
197 197 # warnings
198 198 [
199 199 (r'.{81}', "warning: line over 80 characters"),
200 200 (r'^\s*except:$', "warning: naked except clause"),
201 201 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
202 202 "warning: unwrapped ui message"),
203 203 ]
204 204 ]
205 205
206 206 pyfilters = [
207 207 (r"""(?msx)(?P<comment>\#.*?$)|
208 208 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
209 209 (?P<text>(([^\\]|\\.)*?))
210 210 (?P=quote))""", reppython),
211 211 ]
212 212
213 213 cpats = [
214 214 [
215 215 (r'//', "don't use //-style comments"),
216 216 (r'^ ', "don't use spaces to indent"),
217 217 (r'\S\t', "don't use tabs except for indent"),
218 218 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
219 219 (r'.{85}', "line too long"),
220 220 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
221 221 (r'return\(', "return is not a function"),
222 222 (r' ;', "no space before ;"),
223 223 (r'\w+\* \w+', "use int *foo, not int* foo"),
224 224 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
225 225 (r'\S+ (\+\+|--)', "use foo++, not foo ++"),
226 226 (r'\w,\w', "missing whitespace after ,"),
227 227 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
228 228 (r'^#\s+\w', "use #foo, not # foo"),
229 229 (r'[^\n]\Z', "no trailing newline"),
230 230 (r'^\s*#import\b', "use only #include in standard C code"),
231 231 ],
232 232 # warnings
233 233 []
234 234 ]
235 235
236 236 cfilters = [
237 237 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
238 238 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
239 239 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
240 240 (r'(\()([^)]+\))', repcallspaces),
241 241 ]
242 242
243 243 inutilpats = [
244 244 [
245 245 (r'\bui\.', "don't use ui in util"),
246 246 ],
247 247 # warnings
248 248 []
249 249 ]
250 250
251 251 inrevlogpats = [
252 252 [
253 253 (r'\brepo\.', "don't use repo in revlog"),
254 254 ],
255 255 # warnings
256 256 []
257 257 ]
258 258
259 259 checks = [
260 260 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
261 261 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
262 262 ('c', r'.*\.c$', cfilters, cpats),
263 263 ('unified test', r'.*\.t$', utestfilters, utestpats),
264 264 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
265 265 inrevlogpats),
266 266 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
267 267 inutilpats),
268 268 ]
269 269
270 270 class norepeatlogger(object):
271 271 def __init__(self):
272 272 self._lastseen = None
273 273
274 274 def log(self, fname, lineno, line, msg, blame):
275 275 """print error related a to given line of a given file.
276 276
277 277 The faulty line will also be printed but only once in the case
278 278 of multiple errors.
279 279
280 280 :fname: filename
281 281 :lineno: line number
282 282 :line: actual content of the line
283 283 :msg: error message
284 284 """
285 285 msgid = fname, lineno, line
286 286 if msgid != self._lastseen:
287 287 if blame:
288 288 print "%s:%d (%s):" % (fname, lineno, blame)
289 289 else:
290 290 print "%s:%d:" % (fname, lineno)
291 291 print " > %s" % line
292 292 self._lastseen = msgid
293 293 print " " + msg
294 294
295 295 _defaultlogger = norepeatlogger()
296 296
297 297 def getblame(f):
298 298 lines = []
299 299 for l in os.popen('hg annotate -un %s' % f):
300 300 start, line = l.split(':', 1)
301 301 user, rev = start.split()
302 302 lines.append((line[1:-1], user, rev))
303 303 return lines
304 304
305 305 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
306 306 blame=False, debug=False, lineno=True):
307 307 """checks style and portability of a given file
308 308
309 309 :f: filepath
310 310 :logfunc: function used to report error
311 311 logfunc(filename, linenumber, linecontent, errormessage)
312 312 :maxerr: number of error to display before arborting.
313 313 Set to false (default) to report all errors
314 314
315 315 return True if no error is found, False otherwise.
316 316 """
317 317 blamecache = None
318 318 result = True
319 319 for name, match, filters, pats in checks:
320 320 if debug:
321 321 print name, f
322 322 fc = 0
323 323 if not re.match(match, f):
324 324 if debug:
325 325 print "Skipping %s for %s it doesn't match %s" % (
326 326 name, match, f)
327 327 continue
328 328 fp = open(f)
329 329 pre = post = fp.read()
330 330 fp.close()
331 331 if "no-" + "check-code" in pre:
332 332 if debug:
333 333 print "Skipping %s for %s it has no- and check-code" % (
334 334 name, f)
335 335 break
336 336 for p, r in filters:
337 337 post = re.sub(p, r, post)
338 338 if warnings:
339 339 pats = pats[0] + pats[1]
340 340 else:
341 341 pats = pats[0]
342 342 # print post # uncomment to show filtered version
343 343
344 344 if debug:
345 345 print "Checking %s for %s" % (name, f)
346 346
347 347 prelines = None
348 348 errors = []
349 349 for p, msg in pats:
350 350 # fix-up regexes for multiline searches
351 351 po = p
352 352 # \s doesn't match \n
353 353 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
354 354 # [^...] doesn't match newline
355 355 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
356 356
357 357 #print po, '=>', p
358 358
359 359 pos = 0
360 360 n = 0
361 361 for m in re.finditer(p, post, re.MULTILINE):
362 362 if prelines is None:
363 363 prelines = pre.splitlines()
364 364 postlines = post.splitlines(True)
365 365
366 366 start = m.start()
367 367 while n < len(postlines):
368 368 step = len(postlines[n])
369 369 if pos + step > start:
370 370 break
371 371 pos += step
372 372 n += 1
373 373 l = prelines[n]
374 374
375 375 if "check-code" + "-ignore" in l:
376 376 if debug:
377 377 print "Skipping %s for %s:%s (check-code -ignore)" % (
378 378 name, f, n)
379 379 continue
380 380 bd = ""
381 381 if blame:
382 382 bd = 'working directory'
383 383 if not blamecache:
384 384 blamecache = getblame(f)
385 385 if n < len(blamecache):
386 386 bl, bu, br = blamecache[n]
387 387 if bl == l:
388 388 bd = '%s@%s' % (bu, br)
389 389 errors.append((f, lineno and n + 1, l, msg, bd))
390 390 result = False
391 391
392 392 errors.sort()
393 393 for e in errors:
394 394 logfunc(*e)
395 395 fc += 1
396 396 if maxerr and fc >= maxerr:
397 397 print " (too many errors, giving up)"
398 398 break
399 399
400 400 return result
401 401
402 402 if __name__ == "__main__":
403 403 parser = optparse.OptionParser("%prog [options] [files]")
404 404 parser.add_option("-w", "--warnings", action="store_true",
405 405 help="include warning-level checks")
406 406 parser.add_option("-p", "--per-file", type="int",
407 407 help="max warnings per file")
408 408 parser.add_option("-b", "--blame", action="store_true",
409 409 help="use annotate to generate blame info")
410 410 parser.add_option("", "--debug", action="store_true",
411 411 help="show debug information")
412 412 parser.add_option("", "--nolineno", action="store_false",
413 413 dest='lineno', help="don't show line numbers")
414 414
415 415 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
416 416 lineno=True)
417 417 (options, args) = parser.parse_args()
418 418
419 419 if len(args) == 0:
420 420 check = glob.glob("*")
421 421 else:
422 422 check = args
423 423
424 424 ret = 0
425 425 for f in check:
426 426 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
427 427 blame=options.blame, debug=options.debug,
428 428 lineno=options.lineno):
429 429 ret = 1
430 430 sys.exit(ret)
@@ -1,71 +1,71 b''
1 1 $ hg init repo
2 2 $ cd repo
3 3 $ i=0; while [ "$i" -lt 213 ]; do echo a >> a; i=`expr $i + 1`; done
4 4 $ hg add a
5 5 $ cp a b
6 6 $ hg add b
7 7
8 8 Wide diffstat:
9 9
10 10 $ hg diff --stat
11 11 a | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 12 b | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 13 2 files changed, 426 insertions(+), 0 deletions(-)
14 14
15 15 diffstat width:
16 16
17 17 $ COLUMNS=24 hg diff --config ui.interactive=true --stat
18 18 a | 213 ++++++++++++++
19 19 b | 213 ++++++++++++++
20 20 2 files changed, 426 insertions(+), 0 deletions(-)
21 21
22 22 $ hg ci -m adda
23 23
24 24 $ cat >> a <<EOF
25 25 > a
26 26 > a
27 27 > a
28 28 > EOF
29 29
30 30 Narrow diffstat:
31 31
32 32 $ hg diff --stat
33 33 a | 3 +++
34 34 1 files changed, 3 insertions(+), 0 deletions(-)
35 35
36 36 $ hg ci -m appenda
37 37
38 $ printf '\0' > c
38 >>> open("c", "wb").write("\0")
39 39 $ touch d
40 40 $ hg add c d
41 41
42 42 Binary diffstat:
43 43
44 44 $ hg diff --stat
45 45 c | Bin
46 46 1 files changed, 0 insertions(+), 0 deletions(-)
47 47
48 48 Binary git diffstat:
49 49
50 50 $ hg diff --stat --git
51 51 c | Bin
52 52 d | 0
53 53 2 files changed, 0 insertions(+), 0 deletions(-)
54 54
55 55 $ hg ci -m createb
56 56
57 $ printf '\0' > "file with spaces"
57 >>> open("file with spaces", "wb").write("\0")
58 58 $ hg add "file with spaces"
59 59
60 60 Filename with spaces diffstat:
61 61
62 62 $ hg diff --stat
63 63 file with spaces | Bin
64 64 1 files changed, 0 insertions(+), 0 deletions(-)
65 65
66 66 Filename with spaces git diffstat:
67 67
68 68 $ hg diff --stat --git
69 69 file with spaces | Bin
70 70 1 files changed, 0 insertions(+), 0 deletions(-)
71 71
@@ -1,1108 +1,1108 b''
1 1 $ "$TESTDIR/hghave" symlink unix-permissions serve || exit 80
2 2
3 3 $ cat <<EOF >> $HGRCPATH
4 4 > [extensions]
5 5 > keyword =
6 6 > mq =
7 7 > notify =
8 8 > record =
9 9 > transplant =
10 10 > [ui]
11 11 > interactive = true
12 12 > EOF
13 13
14 14 Run kwdemo before [keyword] files are set up
15 15 as it would succeed without uisetup otherwise
16 16
17 17 $ hg --quiet kwdemo
18 18 [extensions]
19 19 keyword =
20 20 [keyword]
21 21 demo.txt =
22 22 [keywordset]
23 23 svn = False
24 24 [keywordmaps]
25 25 Author = {author|user}
26 26 Date = {date|utcdate}
27 27 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
28 28 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
29 29 RCSFile = {file|basename},v
30 30 RCSfile = {file|basename},v
31 31 Revision = {node|short}
32 32 Source = {root}/{file},v
33 33 $Author: test $
34 34 $Date: ????/??/?? ??:??:?? $ (glob)
35 35 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
36 36 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
37 37 $RCSFile: demo.txt,v $
38 38 $RCSfile: demo.txt,v $
39 39 $Revision: ???????????? $ (glob)
40 40 $Source: */demo.txt,v $ (glob)
41 41
42 42 $ hg --quiet kwdemo "Branch = {branches}"
43 43 [extensions]
44 44 keyword =
45 45 [keyword]
46 46 demo.txt =
47 47 [keywordset]
48 48 svn = False
49 49 [keywordmaps]
50 50 Branch = {branches}
51 51 $Branch: demobranch $
52 52
53 53 $ cat <<EOF >> $HGRCPATH
54 54 > [keyword]
55 55 > ** =
56 56 > b = ignore
57 57 > i = ignore
58 58 > [hooks]
59 59 > EOF
60 60 $ cp $HGRCPATH $HGRCPATH.nohooks
61 61 > cat <<EOF >> $HGRCPATH
62 62 > commit=
63 63 > commit.test=cp a hooktest
64 64 > EOF
65 65
66 66 $ hg init Test-bndl
67 67 $ cd Test-bndl
68 68
69 69 kwshrink should exit silently in empty/invalid repo
70 70
71 71 $ hg kwshrink
72 72
73 73 Symlinks cannot be created on Windows.
74 74 A bundle to test this was made with:
75 75 hg init t
76 76 cd t
77 77 echo a > a
78 78 ln -s a sym
79 79 hg add sym
80 80 hg ci -m addsym -u mercurial
81 81 hg bundle --base null ../test-keyword.hg
82 82
83 83 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
84 84 pulling from *test-keyword.hg (glob)
85 85 requesting all changes
86 86 adding changesets
87 87 adding manifests
88 88 adding file changes
89 89 added 1 changesets with 1 changes to 1 files
90 90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 91
92 92 $ echo 'expand $Id$' > a
93 93 $ echo 'do not process $Id:' >> a
94 94 $ echo 'xxx $' >> a
95 95 $ echo 'ignore $Id$' > b
96 96
97 97 Output files as they were created
98 98
99 99 $ cat a b
100 100 expand $Id$
101 101 do not process $Id:
102 102 xxx $
103 103 ignore $Id$
104 104
105 105 no kwfiles
106 106
107 107 $ hg kwfiles
108 108
109 109 untracked candidates
110 110
111 111 $ hg -v kwfiles --unknown
112 112 k a
113 113
114 114 Add files and check status
115 115
116 116 $ hg addremove
117 117 adding a
118 118 adding b
119 119 $ hg status
120 120 A a
121 121 A b
122 122
123 123
124 124 Default keyword expansion including commit hook
125 125 Interrupted commit should not change state or run commit hook
126 126
127 127 $ hg --debug commit
128 128 abort: empty commit message
129 129 [255]
130 130 $ hg status
131 131 A a
132 132 A b
133 133
134 134 Commit with several checks
135 135
136 136 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
137 137 a
138 138 b
139 139 overwriting a expanding keywords
140 140 running hook commit.test: cp a hooktest
141 141 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
142 142 $ hg status
143 143 ? hooktest
144 144 $ hg debugrebuildstate
145 145 $ hg --quiet identify
146 146 ef63ca68695b
147 147
148 148 cat files in working directory with keywords expanded
149 149
150 150 $ cat a b
151 151 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
152 152 do not process $Id:
153 153 xxx $
154 154 ignore $Id$
155 155
156 156 hg cat files and symlink, no expansion
157 157
158 158 $ hg cat sym a b && echo
159 159 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
160 160 do not process $Id:
161 161 xxx $
162 162 ignore $Id$
163 163 a
164 164
165 165 $ diff a hooktest
166 166
167 167 $ cp $HGRCPATH.nohooks $HGRCPATH
168 168 $ rm hooktest
169 169
170 170 hg status of kw-ignored binary file starting with '\1\n'
171 171
172 $ printf '\1\nfoo' > i
172 >>> open("i", "wb").write("\1\nfoo")
173 173 $ hg -q commit -Am metasep i
174 174 $ hg status
175 $ printf '\1\nbar' > i
175 >>> open("i", "wb").write("\1\nbar")
176 176 $ hg status
177 177 M i
178 178 $ hg -q commit -m "modify metasep" i
179 179 $ hg status --rev 2:3
180 180 M i
181 181 $ touch empty
182 182 $ hg -q commit -A -m "another file"
183 183 $ hg status -A --rev 3:4 i
184 184 C i
185 185
186 186 $ hg -q strip -n 2
187 187
188 188 Test hook execution
189 189
190 190 bundle
191 191
192 192 $ hg bundle --base null ../kw.hg
193 193 2 changesets found
194 194 $ cd ..
195 195 $ hg init Test
196 196 $ cd Test
197 197
198 198 Notify on pull to check whether keywords stay as is in email
199 199 ie. if patch.diff wrapper acts as it should
200 200
201 201 $ cat <<EOF >> $HGRCPATH
202 202 > [hooks]
203 203 > incoming.notify = python:hgext.notify.hook
204 204 > [notify]
205 205 > sources = pull
206 206 > diffstat = False
207 207 > maxsubject = 15
208 208 > [reposubs]
209 209 > * = Test
210 210 > EOF
211 211
212 212 Pull from bundle and trigger notify
213 213
214 214 $ hg pull -u ../kw.hg
215 215 pulling from ../kw.hg
216 216 requesting all changes
217 217 adding changesets
218 218 adding manifests
219 219 adding file changes
220 220 added 2 changesets with 3 changes to 3 files
221 221 Content-Type: text/plain; charset="us-ascii"
222 222 MIME-Version: 1.0
223 223 Content-Transfer-Encoding: 7bit
224 224 Date: * (glob)
225 225 Subject: changeset in...
226 226 From: mercurial
227 227 X-Hg-Notification: changeset a2392c293916
228 228 Message-Id: <hg.a2392c293916*> (glob)
229 229 To: Test
230 230
231 231 changeset a2392c293916 in $TESTTMP/Test (glob)
232 232 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
233 233 description:
234 234 addsym
235 235
236 236 diffs (6 lines):
237 237
238 238 diff -r 000000000000 -r a2392c293916 sym
239 239 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
240 240 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
241 241 @@ -0,0 +1,1 @@
242 242 +a
243 243 \ No newline at end of file
244 244 Content-Type: text/plain; charset="us-ascii"
245 245 MIME-Version: 1.0
246 246 Content-Transfer-Encoding: 7bit
247 247 Date:* (glob)
248 248 Subject: changeset in...
249 249 From: User Name <user@example.com>
250 250 X-Hg-Notification: changeset ef63ca68695b
251 251 Message-Id: <hg.ef63ca68695b*> (glob)
252 252 To: Test
253 253
254 254 changeset ef63ca68695b in $TESTTMP/Test (glob)
255 255 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
256 256 description:
257 257 absym
258 258
259 259 diffs (12 lines):
260 260
261 261 diff -r a2392c293916 -r ef63ca68695b a
262 262 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
263 263 +++ b/a Thu Jan 01 00:00:00 1970 +0000
264 264 @@ -0,0 +1,3 @@
265 265 +expand $Id$
266 266 +do not process $Id:
267 267 +xxx $
268 268 diff -r a2392c293916 -r ef63ca68695b b
269 269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
270 270 +++ b/b Thu Jan 01 00:00:00 1970 +0000
271 271 @@ -0,0 +1,1 @@
272 272 +ignore $Id$
273 273 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
274 274
275 275 $ cp $HGRCPATH.nohooks $HGRCPATH
276 276
277 277 Touch files and check with status
278 278
279 279 $ touch a b
280 280 $ hg status
281 281
282 282 Update and expand
283 283
284 284 $ rm sym a b
285 285 $ hg update -C
286 286 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 287 $ cat a b
288 288 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
289 289 do not process $Id:
290 290 xxx $
291 291 ignore $Id$
292 292
293 293 Check whether expansion is filewise and file mode is preserved
294 294
295 295 $ echo '$Id$' > c
296 296 $ echo 'tests for different changenodes' >> c
297 297 $ chmod 600 c
298 298 $ ls -l c | cut -b 1-10
299 299 -rw-------
300 300
301 301 commit file c
302 302
303 303 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
304 304 adding c
305 305 $ ls -l c | cut -b 1-10
306 306 -rw-------
307 307
308 308 force expansion
309 309
310 310 $ hg -v kwexpand
311 311 overwriting a expanding keywords
312 312 overwriting c expanding keywords
313 313
314 314 compare changenodes in a and c
315 315
316 316 $ cat a c
317 317 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
318 318 do not process $Id:
319 319 xxx $
320 320 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
321 321 tests for different changenodes
322 322
323 323 record
324 324
325 325 $ echo '$Id$' > r
326 326 $ hg add r
327 327
328 328 record chunk
329 329
330 330 >>> lines = open('a').readlines()
331 331 >>> lines.insert(1, 'foo\n')
332 332 >>> lines.append('bar\n')
333 333 >>> open('a', 'w').writelines(lines)
334 334 $ hg record -d '1 10' -m rectest a<<EOF
335 335 > y
336 336 > y
337 337 > n
338 338 > EOF
339 339 diff --git a/a b/a
340 340 2 hunks, 2 lines changed
341 341 examine changes to 'a'? [Ynsfdaq?]
342 342 @@ -1,3 +1,4 @@
343 343 expand $Id$
344 344 +foo
345 345 do not process $Id:
346 346 xxx $
347 347 record change 1/2 to 'a'? [Ynsfdaq?]
348 348 @@ -2,2 +3,3 @@
349 349 do not process $Id:
350 350 xxx $
351 351 +bar
352 352 record change 2/2 to 'a'? [Ynsfdaq?]
353 353
354 354 $ hg identify
355 355 d17e03c92c97+ tip
356 356 $ hg status
357 357 M a
358 358 A r
359 359
360 360 Cat modified file a
361 361
362 362 $ cat a
363 363 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
364 364 foo
365 365 do not process $Id:
366 366 xxx $
367 367 bar
368 368
369 369 Diff remaining chunk
370 370
371 371 $ hg diff a
372 372 diff -r d17e03c92c97 a
373 373 --- a/a Wed Dec 31 23:59:51 1969 -0000
374 374 +++ b/a * (glob)
375 375 @@ -2,3 +2,4 @@
376 376 foo
377 377 do not process $Id:
378 378 xxx $
379 379 +bar
380 380
381 381 $ hg rollback
382 382 repository tip rolled back to revision 2 (undo commit)
383 383 working directory now based on revision 2
384 384
385 385 Record all chunks in file a
386 386
387 387 $ echo foo > msg
388 388
389 389 - do not use "hg record -m" here!
390 390
391 391 $ hg record -l msg -d '1 11' a<<EOF
392 392 > y
393 393 > y
394 394 > y
395 395 > EOF
396 396 diff --git a/a b/a
397 397 2 hunks, 2 lines changed
398 398 examine changes to 'a'? [Ynsfdaq?]
399 399 @@ -1,3 +1,4 @@
400 400 expand $Id$
401 401 +foo
402 402 do not process $Id:
403 403 xxx $
404 404 record change 1/2 to 'a'? [Ynsfdaq?]
405 405 @@ -2,2 +3,3 @@
406 406 do not process $Id:
407 407 xxx $
408 408 +bar
409 409 record change 2/2 to 'a'? [Ynsfdaq?]
410 410
411 411 File a should be clean
412 412
413 413 $ hg status -A a
414 414 C a
415 415
416 416 rollback and revert expansion
417 417
418 418 $ cat a
419 419 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
420 420 foo
421 421 do not process $Id:
422 422 xxx $
423 423 bar
424 424 $ hg --verbose rollback
425 425 repository tip rolled back to revision 2 (undo commit)
426 426 working directory now based on revision 2
427 427 overwriting a expanding keywords
428 428 $ hg status a
429 429 M a
430 430 $ cat a
431 431 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
432 432 foo
433 433 do not process $Id:
434 434 xxx $
435 435 bar
436 436 $ echo '$Id$' > y
437 437 $ echo '$Id$' > z
438 438 $ hg add y
439 439 $ hg commit -Am "rollback only" z
440 440 $ cat z
441 441 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
442 442 $ hg --verbose rollback
443 443 repository tip rolled back to revision 2 (undo commit)
444 444 working directory now based on revision 2
445 445 overwriting z shrinking keywords
446 446
447 447 Only z should be overwritten
448 448
449 449 $ hg status a y z
450 450 M a
451 451 A y
452 452 A z
453 453 $ cat z
454 454 $Id$
455 455 $ hg forget y z
456 456 $ rm y z
457 457
458 458 record added file alone
459 459
460 460 $ hg -v record -l msg -d '1 12' r<<EOF
461 461 > y
462 462 > EOF
463 463 diff --git a/r b/r
464 464 new file mode 100644
465 465 examine changes to 'r'? [Ynsfdaq?]
466 466 r
467 467 committed changeset 3:899491280810
468 468 overwriting r expanding keywords
469 469 - status call required for dirstate.normallookup() check
470 470 $ hg status r
471 471 $ hg --verbose rollback
472 472 repository tip rolled back to revision 2 (undo commit)
473 473 working directory now based on revision 2
474 474 overwriting r shrinking keywords
475 475 $ hg forget r
476 476 $ rm msg r
477 477 $ hg update -C
478 478 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
479 479
480 480 record added keyword ignored file
481 481
482 482 $ echo '$Id$' > i
483 483 $ hg add i
484 484 $ hg --verbose record -d '1 13' -m recignored<<EOF
485 485 > y
486 486 > EOF
487 487 diff --git a/i b/i
488 488 new file mode 100644
489 489 examine changes to 'i'? [Ynsfdaq?]
490 490 i
491 491 committed changeset 3:5f40fe93bbdc
492 492 $ cat i
493 493 $Id$
494 494 $ hg -q rollback
495 495 $ hg forget i
496 496 $ rm i
497 497
498 498 Test patch queue repo
499 499
500 500 $ hg init --mq
501 501 $ hg qimport -r tip -n mqtest.diff
502 502 $ hg commit --mq -m mqtest
503 503
504 504 Keywords should not be expanded in patch
505 505
506 506 $ cat .hg/patches/mqtest.diff
507 507 # HG changeset patch
508 508 # User User Name <user@example.com>
509 509 # Date 1 0
510 510 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
511 511 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
512 512 cndiff
513 513
514 514 diff -r ef63ca68695b -r 40a904bbbe4c c
515 515 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
516 516 +++ b/c Thu Jan 01 00:00:01 1970 +0000
517 517 @@ -0,0 +1,2 @@
518 518 +$Id$
519 519 +tests for different changenodes
520 520
521 521 $ hg qpop
522 522 popping mqtest.diff
523 523 patch queue now empty
524 524
525 525 qgoto, implying qpush, should expand
526 526
527 527 $ hg qgoto mqtest.diff
528 528 applying mqtest.diff
529 529 now at: mqtest.diff
530 530 $ cat c
531 531 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
532 532 tests for different changenodes
533 533 $ hg cat c
534 534 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
535 535 tests for different changenodes
536 536
537 537 Keywords should not be expanded in filelog
538 538
539 539 $ hg --config 'extensions.keyword=!' cat c
540 540 $Id$
541 541 tests for different changenodes
542 542
543 543 qpop and move on
544 544
545 545 $ hg qpop
546 546 popping mqtest.diff
547 547 patch queue now empty
548 548
549 549 Copy and show added kwfiles
550 550
551 551 $ hg cp a c
552 552 $ hg kwfiles
553 553 a
554 554 c
555 555
556 556 Commit and show expansion in original and copy
557 557
558 558 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
559 559 invalidating branch cache (tip differs)
560 560 c
561 561 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
562 562 overwriting c expanding keywords
563 563 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
564 564 $ cat a c
565 565 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
566 566 do not process $Id:
567 567 xxx $
568 568 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
569 569 do not process $Id:
570 570 xxx $
571 571
572 572 Touch copied c and check its status
573 573
574 574 $ touch c
575 575 $ hg status
576 576
577 577 Copy kwfile to keyword ignored file unexpanding keywords
578 578
579 579 $ hg --verbose copy a i
580 580 copying a to i
581 581 overwriting i shrinking keywords
582 582 $ head -n 1 i
583 583 expand $Id$
584 584 $ hg forget i
585 585 $ rm i
586 586
587 587 Copy ignored file to ignored file: no overwriting
588 588
589 589 $ hg --verbose copy b i
590 590 copying b to i
591 591 $ hg forget i
592 592 $ rm i
593 593
594 594 cp symlink file; hg cp -A symlink file (part1)
595 595 - copied symlink points to kwfile: overwrite
596 596
597 597 $ cp sym i
598 598 $ ls -l i
599 599 -rw-r--r--* (glob)
600 600 $ head -1 i
601 601 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
602 602 $ hg copy --after --verbose sym i
603 603 copying sym to i
604 604 overwriting i shrinking keywords
605 605 $ head -1 i
606 606 expand $Id$
607 607 $ hg forget i
608 608 $ rm i
609 609
610 610 Test different options of hg kwfiles
611 611
612 612 $ hg kwfiles
613 613 a
614 614 c
615 615 $ hg -v kwfiles --ignore
616 616 I b
617 617 I sym
618 618 $ hg kwfiles --all
619 619 K a
620 620 K c
621 621 I b
622 622 I sym
623 623
624 624 Diff specific revision
625 625
626 626 $ hg diff --rev 1
627 627 diff -r ef63ca68695b c
628 628 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
629 629 +++ b/c * (glob)
630 630 @@ -0,0 +1,3 @@
631 631 +expand $Id$
632 632 +do not process $Id:
633 633 +xxx $
634 634
635 635 Status after rollback:
636 636
637 637 $ hg rollback
638 638 repository tip rolled back to revision 1 (undo commit)
639 639 working directory now based on revision 1
640 640 $ hg status
641 641 A c
642 642 $ hg update --clean
643 643 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
644 644
645 645 cp symlink file; hg cp -A symlink file (part2)
646 646 - copied symlink points to kw ignored file: do not overwrite
647 647
648 648 $ cat a > i
649 649 $ ln -s i symignored
650 650 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
651 651 $ cp symignored x
652 652 $ hg copy --after --verbose symignored x
653 653 copying symignored to x
654 654 $ head -n 1 x
655 655 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
656 656 $ hg forget x
657 657 $ rm x
658 658
659 659 $ hg rollback
660 660 repository tip rolled back to revision 1 (undo commit)
661 661 working directory now based on revision 1
662 662 $ hg update --clean
663 663 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
664 664 $ rm i symignored
665 665
666 666 Custom keywordmaps as argument to kwdemo
667 667
668 668 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
669 669 [extensions]
670 670 keyword =
671 671 [keyword]
672 672 ** =
673 673 b = ignore
674 674 demo.txt =
675 675 i = ignore
676 676 [keywordset]
677 677 svn = False
678 678 [keywordmaps]
679 679 Xinfo = {author}: {desc}
680 680 $Xinfo: test: hg keyword configuration and expansion example $
681 681
682 682 Configure custom keywordmaps
683 683
684 684 $ cat <<EOF >>$HGRCPATH
685 685 > [keywordmaps]
686 686 > Id = {file} {node|short} {date|rfc822date} {author|user}
687 687 > Xinfo = {author}: {desc}
688 688 > EOF
689 689
690 690 Cat and hg cat files before custom expansion
691 691
692 692 $ cat a b
693 693 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
694 694 do not process $Id:
695 695 xxx $
696 696 ignore $Id$
697 697 $ hg cat sym a b && echo
698 698 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
699 699 do not process $Id:
700 700 xxx $
701 701 ignore $Id$
702 702 a
703 703
704 704 Write custom keyword and prepare multiline commit message
705 705
706 706 $ echo '$Xinfo$' >> a
707 707 $ cat <<EOF >> log
708 708 > firstline
709 709 > secondline
710 710 > EOF
711 711
712 712 Interrupted commit should not change state
713 713
714 714 $ hg commit
715 715 abort: empty commit message
716 716 [255]
717 717 $ hg status
718 718 M a
719 719 ? c
720 720 ? log
721 721
722 722 Commit with multiline message and custom expansion
723 723
724 724 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
725 725 a
726 726 overwriting a expanding keywords
727 727 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
728 728 $ rm log
729 729
730 730 Stat, verify and show custom expansion (firstline)
731 731
732 732 $ hg status
733 733 ? c
734 734 $ hg verify
735 735 checking changesets
736 736 checking manifests
737 737 crosschecking files in changesets and manifests
738 738 checking files
739 739 3 files, 3 changesets, 4 total revisions
740 740 $ cat a b
741 741 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
742 742 do not process $Id:
743 743 xxx $
744 744 $Xinfo: User Name <user@example.com>: firstline $
745 745 ignore $Id$
746 746 $ hg cat sym a b && echo
747 747 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
748 748 do not process $Id:
749 749 xxx $
750 750 $Xinfo: User Name <user@example.com>: firstline $
751 751 ignore $Id$
752 752 a
753 753
754 754 annotate
755 755
756 756 $ hg annotate a
757 757 1: expand $Id$
758 758 1: do not process $Id:
759 759 1: xxx $
760 760 2: $Xinfo$
761 761
762 762 remove with status checks
763 763
764 764 $ hg debugrebuildstate
765 765 $ hg remove a
766 766 $ hg --debug commit -m rma
767 767 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
768 768 $ hg status
769 769 ? c
770 770
771 771 Rollback, revert, and check expansion
772 772
773 773 $ hg rollback
774 774 repository tip rolled back to revision 2 (undo commit)
775 775 working directory now based on revision 2
776 776 $ hg status
777 777 R a
778 778 ? c
779 779 $ hg revert --no-backup --rev tip a
780 780 $ cat a
781 781 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
782 782 do not process $Id:
783 783 xxx $
784 784 $Xinfo: User Name <user@example.com>: firstline $
785 785
786 786 Clone to test global and local configurations
787 787
788 788 $ cd ..
789 789
790 790 Expansion in destinaton with global configuration
791 791
792 792 $ hg --quiet clone Test globalconf
793 793 $ cat globalconf/a
794 794 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
795 795 do not process $Id:
796 796 xxx $
797 797 $Xinfo: User Name <user@example.com>: firstline $
798 798
799 799 No expansion in destination with local configuration in origin only
800 800
801 801 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
802 802 $ cat localconf/a
803 803 expand $Id$
804 804 do not process $Id:
805 805 xxx $
806 806 $Xinfo$
807 807
808 808 Clone to test incoming
809 809
810 810 $ hg clone -r1 Test Test-a
811 811 adding changesets
812 812 adding manifests
813 813 adding file changes
814 814 added 2 changesets with 3 changes to 3 files
815 815 updating to branch default
816 816 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
817 817 $ cd Test-a
818 818 $ cat <<EOF >> .hg/hgrc
819 819 > [paths]
820 820 > default = ../Test
821 821 > EOF
822 822 $ hg incoming
823 823 comparing with $TESTTMP/Test (glob)
824 824 searching for changes
825 825 changeset: 2:bb948857c743
826 826 tag: tip
827 827 user: User Name <user@example.com>
828 828 date: Thu Jan 01 00:00:02 1970 +0000
829 829 summary: firstline
830 830
831 831 Imported patch should not be rejected
832 832
833 833 >>> import re
834 834 >>> text = re.sub(r'(Id.*)', r'\1 rejecttest', open('a').read())
835 835 >>> open('a', 'wb').write(text)
836 836 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
837 837 a
838 838 overwriting a expanding keywords
839 839 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
840 840 $ hg export -o ../rejecttest.diff tip
841 841 $ cd ../Test
842 842 $ hg import ../rejecttest.diff
843 843 applying ../rejecttest.diff
844 844 $ cat a b
845 845 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
846 846 do not process $Id: rejecttest
847 847 xxx $
848 848 $Xinfo: User Name <user@example.com>: rejects? $
849 849 ignore $Id$
850 850
851 851 $ hg rollback
852 852 repository tip rolled back to revision 2 (undo import)
853 853 working directory now based on revision 2
854 854 $ hg update --clean
855 855 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
856 856
857 857 kwexpand/kwshrink on selected files
858 858
859 859 $ mkdir x
860 860 $ hg copy a x/a
861 861 $ hg --verbose kwshrink a
862 862 overwriting a shrinking keywords
863 863 - sleep required for dirstate.normal() check
864 864 $ sleep 1
865 865 $ hg status a
866 866 $ hg --verbose kwexpand a
867 867 overwriting a expanding keywords
868 868 $ hg status a
869 869
870 870 kwexpand x/a should abort
871 871
872 872 $ hg --verbose kwexpand x/a
873 873 abort: outstanding uncommitted changes
874 874 [255]
875 875 $ cd x
876 876 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
877 877 x/a
878 878 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
879 879 overwriting x/a expanding keywords
880 880 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
881 881 $ cat a
882 882 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
883 883 do not process $Id:
884 884 xxx $
885 885 $Xinfo: User Name <user@example.com>: xa $
886 886
887 887 kwshrink a inside directory x
888 888
889 889 $ hg --verbose kwshrink a
890 890 overwriting x/a shrinking keywords
891 891 $ cat a
892 892 expand $Id$
893 893 do not process $Id:
894 894 xxx $
895 895 $Xinfo$
896 896 $ cd ..
897 897
898 898 kwexpand nonexistent
899 899
900 900 $ hg kwexpand nonexistent
901 901 nonexistent:* (glob)
902 902
903 903
904 904 hg serve
905 905 - expand with hgweb file
906 906 - no expansion with hgweb annotate/changeset/filediff
907 907 - check errors
908 908
909 909 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
910 910 $ cat hg.pid >> $DAEMON_PIDS
911 911 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
912 912 200 Script output follows
913 913
914 914 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
915 915 do not process $Id:
916 916 xxx $
917 917 $Xinfo: User Name <user@example.com>: firstline $
918 918 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
919 919 200 Script output follows
920 920
921 921
922 922 user@1: expand $Id$
923 923 user@1: do not process $Id:
924 924 user@1: xxx $
925 925 user@2: $Xinfo$
926 926
927 927
928 928
929 929
930 930 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
931 931 200 Script output follows
932 932
933 933
934 934 # HG changeset patch
935 935 # User User Name <user@example.com>
936 936 # Date 3 0
937 937 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
938 938 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
939 939 xa
940 940
941 941 diff -r bb948857c743 -r b4560182a3f9 x/a
942 942 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
943 943 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
944 944 @@ -0,0 +1,4 @@
945 945 +expand $Id$
946 946 +do not process $Id:
947 947 +xxx $
948 948 +$Xinfo$
949 949
950 950 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
951 951 200 Script output follows
952 952
953 953
954 954 diff -r ef63ca68695b -r bb948857c743 a
955 955 --- a/a Thu Jan 01 00:00:00 1970 +0000
956 956 +++ b/a Thu Jan 01 00:00:02 1970 +0000
957 957 @@ -1,3 +1,4 @@
958 958 expand $Id$
959 959 do not process $Id:
960 960 xxx $
961 961 +$Xinfo$
962 962
963 963
964 964
965 965
966 966 $ cat errors.log
967 967
968 968 Prepare merge and resolve tests
969 969
970 970 $ echo '$Id$' > m
971 971 $ hg add m
972 972 $ hg commit -m 4kw
973 973 $ echo foo >> m
974 974 $ hg commit -m 5foo
975 975
976 976 simplemerge
977 977
978 978 $ hg update 4
979 979 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
980 980 $ echo foo >> m
981 981 $ hg commit -m 6foo
982 982 created new head
983 983 $ hg merge
984 984 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
985 985 (branch merge, don't forget to commit)
986 986 $ hg commit -m simplemerge
987 987 $ cat m
988 988 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
989 989 foo
990 990
991 991 conflict: keyword should stay outside conflict zone
992 992
993 993 $ hg update 4
994 994 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
995 995 $ echo bar >> m
996 996 $ hg commit -m 8bar
997 997 created new head
998 998 $ hg merge
999 999 merging m
1000 1000 warning: conflicts during merge.
1001 1001 merging m incomplete! (edit conflicts, then use 'hg resolve --mark')
1002 1002 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1003 1003 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1004 1004 [1]
1005 1005 $ cat m
1006 1006 $Id$
1007 1007 <<<<<<< local
1008 1008 bar
1009 1009 =======
1010 1010 foo
1011 1011 >>>>>>> other
1012 1012
1013 1013 resolve to local
1014 1014
1015 1015 $ HGMERGE=internal:local hg resolve -a
1016 1016 $ hg commit -m localresolve
1017 1017 $ cat m
1018 1018 $Id: m 800511b3a22d Thu, 01 Jan 1970 00:00:00 +0000 test $
1019 1019 bar
1020 1020
1021 1021 Test restricted mode with transplant -b
1022 1022
1023 1023 $ hg update 6
1024 1024 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1025 1025 $ hg branch foo
1026 1026 marked working directory as branch foo
1027 1027 (branches are permanent and global, did you want a bookmark?)
1028 1028 $ mv a a.bak
1029 1029 $ echo foobranch > a
1030 1030 $ cat a.bak >> a
1031 1031 $ rm a.bak
1032 1032 $ hg commit -m 9foobranch
1033 1033 $ hg update default
1034 1034 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1035 1035 $ hg -y transplant -b foo tip
1036 1036 applying 4aa30d025d50
1037 1037 4aa30d025d50 transplanted to e00abbf63521
1038 1038
1039 1039 Expansion in changeset but not in file
1040 1040
1041 1041 $ hg tip -p
1042 1042 changeset: 11:e00abbf63521
1043 1043 tag: tip
1044 1044 parent: 9:800511b3a22d
1045 1045 user: test
1046 1046 date: Thu Jan 01 00:00:00 1970 +0000
1047 1047 summary: 9foobranch
1048 1048
1049 1049 diff -r 800511b3a22d -r e00abbf63521 a
1050 1050 --- a/a Thu Jan 01 00:00:00 1970 +0000
1051 1051 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1052 1052 @@ -1,3 +1,4 @@
1053 1053 +foobranch
1054 1054 expand $Id$
1055 1055 do not process $Id:
1056 1056 xxx $
1057 1057
1058 1058 $ head -n 2 a
1059 1059 foobranch
1060 1060 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1061 1061
1062 1062 Turn off expansion
1063 1063
1064 1064 $ hg -q rollback
1065 1065 $ hg -q update -C
1066 1066
1067 1067 kwshrink with unknown file u
1068 1068
1069 1069 $ cp a u
1070 1070 $ hg --verbose kwshrink
1071 1071 overwriting a shrinking keywords
1072 1072 overwriting m shrinking keywords
1073 1073 overwriting x/a shrinking keywords
1074 1074
1075 1075 Keywords shrunk in working directory, but not yet disabled
1076 1076 - cat shows unexpanded keywords
1077 1077 - hg cat shows expanded keywords
1078 1078
1079 1079 $ cat a b
1080 1080 expand $Id$
1081 1081 do not process $Id:
1082 1082 xxx $
1083 1083 $Xinfo$
1084 1084 ignore $Id$
1085 1085 $ hg cat sym a b && echo
1086 1086 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1087 1087 do not process $Id:
1088 1088 xxx $
1089 1089 $Xinfo: User Name <user@example.com>: firstline $
1090 1090 ignore $Id$
1091 1091 a
1092 1092
1093 1093 Now disable keyword expansion
1094 1094
1095 1095 $ rm "$HGRCPATH"
1096 1096 $ cat a b
1097 1097 expand $Id$
1098 1098 do not process $Id:
1099 1099 xxx $
1100 1100 $Xinfo$
1101 1101 ignore $Id$
1102 1102 $ hg cat sym a b && echo
1103 1103 expand $Id$
1104 1104 do not process $Id:
1105 1105 xxx $
1106 1106 $Xinfo$
1107 1107 ignore $Id$
1108 1108 a
@@ -1,297 +1,297 b''
1 1 $ hg init repo1
2 2 $ cd repo1
3 3 $ mkdir a b a/1 b/1 b/2
4 4 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
5 5
6 6 hg status in repo root:
7 7
8 8 $ hg status
9 9 ? a/1/in_a_1
10 10 ? a/in_a
11 11 ? b/1/in_b_1
12 12 ? b/2/in_b_2
13 13 ? b/in_b
14 14 ? in_root
15 15
16 16 hg status . in repo root:
17 17
18 18 $ hg status .
19 19 ? a/1/in_a_1
20 20 ? a/in_a
21 21 ? b/1/in_b_1
22 22 ? b/2/in_b_2
23 23 ? b/in_b
24 24 ? in_root
25 25
26 26 $ hg status --cwd a
27 27 ? a/1/in_a_1
28 28 ? a/in_a
29 29 ? b/1/in_b_1
30 30 ? b/2/in_b_2
31 31 ? b/in_b
32 32 ? in_root
33 33 $ hg status --cwd a .
34 34 ? 1/in_a_1
35 35 ? in_a
36 36 $ hg status --cwd a ..
37 37 ? 1/in_a_1
38 38 ? in_a
39 39 ? ../b/1/in_b_1
40 40 ? ../b/2/in_b_2
41 41 ? ../b/in_b
42 42 ? ../in_root
43 43
44 44 $ hg status --cwd b
45 45 ? a/1/in_a_1
46 46 ? a/in_a
47 47 ? b/1/in_b_1
48 48 ? b/2/in_b_2
49 49 ? b/in_b
50 50 ? in_root
51 51 $ hg status --cwd b .
52 52 ? 1/in_b_1
53 53 ? 2/in_b_2
54 54 ? in_b
55 55 $ hg status --cwd b ..
56 56 ? ../a/1/in_a_1
57 57 ? ../a/in_a
58 58 ? 1/in_b_1
59 59 ? 2/in_b_2
60 60 ? in_b
61 61 ? ../in_root
62 62
63 63 $ hg status --cwd a/1
64 64 ? a/1/in_a_1
65 65 ? a/in_a
66 66 ? b/1/in_b_1
67 67 ? b/2/in_b_2
68 68 ? b/in_b
69 69 ? in_root
70 70 $ hg status --cwd a/1 .
71 71 ? in_a_1
72 72 $ hg status --cwd a/1 ..
73 73 ? in_a_1
74 74 ? ../in_a
75 75
76 76 $ hg status --cwd b/1
77 77 ? a/1/in_a_1
78 78 ? a/in_a
79 79 ? b/1/in_b_1
80 80 ? b/2/in_b_2
81 81 ? b/in_b
82 82 ? in_root
83 83 $ hg status --cwd b/1 .
84 84 ? in_b_1
85 85 $ hg status --cwd b/1 ..
86 86 ? in_b_1
87 87 ? ../2/in_b_2
88 88 ? ../in_b
89 89
90 90 $ hg status --cwd b/2
91 91 ? a/1/in_a_1
92 92 ? a/in_a
93 93 ? b/1/in_b_1
94 94 ? b/2/in_b_2
95 95 ? b/in_b
96 96 ? in_root
97 97 $ hg status --cwd b/2 .
98 98 ? in_b_2
99 99 $ hg status --cwd b/2 ..
100 100 ? ../1/in_b_1
101 101 ? in_b_2
102 102 ? ../in_b
103 103 $ cd ..
104 104
105 105 $ hg init repo2
106 106 $ cd repo2
107 107 $ touch modified removed deleted ignored
108 108 $ echo "^ignored$" > .hgignore
109 109 $ hg ci -A -m 'initial checkin'
110 110 adding .hgignore
111 111 adding deleted
112 112 adding modified
113 113 adding removed
114 114 $ touch modified added unknown ignored
115 115 $ hg add added
116 116 $ hg remove removed
117 117 $ rm deleted
118 118
119 119 hg status:
120 120
121 121 $ hg status
122 122 A added
123 123 R removed
124 124 ! deleted
125 125 ? unknown
126 126
127 127 hg status modified added removed deleted unknown never-existed ignored:
128 128
129 129 $ hg status modified added removed deleted unknown never-existed ignored
130 130 never-existed: * (glob)
131 131 A added
132 132 R removed
133 133 ! deleted
134 134 ? unknown
135 135
136 136 $ hg copy modified copied
137 137
138 138 hg status -C:
139 139
140 140 $ hg status -C
141 141 A added
142 142 A copied
143 143 modified
144 144 R removed
145 145 ! deleted
146 146 ? unknown
147 147
148 148 hg status -A:
149 149
150 150 $ hg status -A
151 151 A added
152 152 A copied
153 153 modified
154 154 R removed
155 155 ! deleted
156 156 ? unknown
157 157 I ignored
158 158 C .hgignore
159 159 C modified
160 160
161 161
162 162 $ echo "^ignoreddir$" > .hgignore
163 163 $ mkdir ignoreddir
164 164 $ touch ignoreddir/file
165 165
166 166 hg status ignoreddir/file:
167 167
168 168 $ hg status ignoreddir/file
169 169
170 170 hg status -i ignoreddir/file:
171 171
172 172 $ hg status -i ignoreddir/file
173 173 I ignoreddir/file
174 174 $ cd ..
175 175
176 176 Check 'status -q' and some combinations
177 177
178 178 $ hg init repo3
179 179 $ cd repo3
180 180 $ touch modified removed deleted ignored
181 181 $ echo "^ignored$" > .hgignore
182 182 $ hg commit -A -m 'initial checkin'
183 183 adding .hgignore
184 184 adding deleted
185 185 adding modified
186 186 adding removed
187 187 $ touch added unknown ignored
188 188 $ hg add added
189 189 $ echo "test" >> modified
190 190 $ hg remove removed
191 191 $ rm deleted
192 192 $ hg copy modified copied
193 193
194 194 Run status with 2 different flags.
195 195 Check if result is the same or different.
196 196 If result is not as expected, raise error
197 197
198 198 $ assert() {
199 199 > hg status $1 > ../a
200 200 > hg status $2 > ../b
201 201 > if diff ../a ../b > /dev/null; then
202 202 > out=0
203 203 > else
204 204 > out=1
205 205 > fi
206 206 > if [ $3 -eq 0 ]; then
207 207 > df="same"
208 208 > else
209 209 > df="different"
210 210 > fi
211 211 > if [ $out -ne $3 ]; then
212 212 > echo "Error on $1 and $2, should be $df."
213 213 > fi
214 214 > }
215 215
216 216 Assert flag1 flag2 [0-same | 1-different]
217 217
218 218 $ assert "-q" "-mard" 0
219 219 $ assert "-A" "-marduicC" 0
220 220 $ assert "-qA" "-mardcC" 0
221 221 $ assert "-qAui" "-A" 0
222 222 $ assert "-qAu" "-marducC" 0
223 223 $ assert "-qAi" "-mardicC" 0
224 224 $ assert "-qu" "-u" 0
225 225 $ assert "-q" "-u" 1
226 226 $ assert "-m" "-a" 1
227 227 $ assert "-r" "-d" 1
228 228 $ cd ..
229 229
230 230 $ hg init repo4
231 231 $ cd repo4
232 232 $ touch modified removed deleted
233 233 $ hg ci -q -A -m 'initial checkin'
234 234 $ touch added unknown
235 235 $ hg add added
236 236 $ hg remove removed
237 237 $ rm deleted
238 238 $ echo x > modified
239 239 $ hg copy modified copied
240 240 $ hg ci -m 'test checkin' -d "1000001 0"
241 241 $ rm *
242 242 $ touch unrelated
243 243 $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"
244 244
245 245 hg status --change 1:
246 246
247 247 $ hg status --change 1
248 248 M modified
249 249 A added
250 250 A copied
251 251 R removed
252 252
253 253 hg status --change 1 unrelated:
254 254
255 255 $ hg status --change 1 unrelated
256 256
257 257 hg status -C --change 1 added modified copied removed deleted:
258 258
259 259 $ hg status -C --change 1 added modified copied removed deleted
260 260 M modified
261 261 A added
262 262 A copied
263 263 modified
264 264 R removed
265 265
266 266 hg status -A --change 1 and revset:
267 267
268 268 $ hg status -A --change '1|1'
269 269 M modified
270 270 A added
271 271 A copied
272 272 modified
273 273 R removed
274 274 C deleted
275 275
276 276 $ cd ..
277 277
278 278 hg status of binary file starting with '\1\n', a separator for metadata:
279 279
280 280 $ hg init repo5
281 281 $ cd repo5
282 $ printf '\1\nfoo' > 010a
282 >>> open("010a", "wb").write("\1\nfoo")
283 283 $ hg ci -q -A -m 'initial checkin'
284 284 $ hg status -A
285 285 C 010a
286 286
287 $ printf '\1\nbar' > 010a
287 >>> open("010a", "wb").write("\1\nbar")
288 288 $ hg status -A
289 289 M 010a
290 290 $ hg ci -q -m 'modify 010a'
291 291 $ hg status -A --rev 0:1
292 292 M 010a
293 293
294 294 $ touch empty
295 295 $ hg ci -q -A -m 'add another file'
296 296 $ hg status -A --rev 1:2 010a
297 297 C 010a
@@ -1,59 +1,59 b''
1 1 $ hg init outer
2 2 $ cd outer
3 3
4 4 $ echo '[paths]' >> .hg/hgrc
5 5 $ echo 'default = http://example.net/' >> .hg/hgrc
6 6
7 7 hg debugsub with no remapping
8 8
9 9 $ echo 'sub = libfoo' > .hgsub
10 10 $ hg add .hgsub
11 11
12 12 $ hg debugsub
13 13 path sub
14 14 source libfoo
15 15 revision
16 16
17 17 hg debugsub with remapping
18 18
19 19 $ echo '[subpaths]' >> .hg/hgrc
20 $ printf 'http://example.net/lib(.*) = C:\\libs\\\\1-lib\\\n' >> .hg/hgrc
20 $ printf 'http://example.net/lib(.*) = C:\\libs\\\\1-lib\\\n' >> .hg/hgrc # no-check-code
21 21
22 22 $ hg debugsub
23 23 path sub
24 24 source C:\libs\foo-lib\
25 25 revision
26 26
27 27 test cumulative remapping, the $HGRCPATH file is loaded first
28 28
29 29 $ echo '[subpaths]' >> $HGRCPATH
30 30 $ echo 'libfoo = libbar' >> $HGRCPATH
31 31 $ hg debugsub
32 32 path sub
33 33 source C:\libs\bar-lib\
34 34 revision
35 35
36 36 test absolute source path -- testing with a URL is important since
37 37 standard os.path.join wont treat that as an absolute path
38 38
39 39 $ echo 'abs = http://example.net/abs' > .hgsub
40 40 $ hg debugsub
41 41 path abs
42 42 source http://example.net/abs
43 43 revision
44 44
45 45 $ echo 'abs = /abs' > .hgsub
46 46 $ hg debugsub
47 47 path abs
48 48 source /abs
49 49 revision
50 50
51 51 test bad subpaths pattern
52 52
53 53 $ cat > .hg/hgrc <<EOF
54 54 > [subpaths]
55 55 > .* = \1
56 56 > EOF
57 57 $ hg debugsub
58 58 abort: bad subrepository pattern in $TESTTMP/outer/.hg/hgrc:2: invalid group reference (glob)
59 59 [255]
General Comments 0
You need to be logged in to leave comments. Login now