##// END OF EJS Templates
check-code: check txt files for trailing whitespace
Mads Kiilerich -
r18960:170fc094 default
parent child Browse files
Show More
@@ -1,465 +1,475
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 l = len(comment.rstrip())
23 23 return "#" * l + comment[l:]
24 24 return repquote(m)
25 25
26 26 def repcomment(m):
27 27 return m.group(1) + "#" * len(m.group(2))
28 28
29 29 def repccomment(m):
30 30 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
31 31 return m.group(1) + t + "*/"
32 32
33 33 def repcallspaces(m):
34 34 t = re.sub(r"\n\s+", "\n", m.group(2))
35 35 return m.group(1) + t
36 36
37 37 def repinclude(m):
38 38 return m.group(1) + "<foo>"
39 39
40 40 def rephere(m):
41 41 t = re.sub(r"\S", "x", m.group(2))
42 42 return m.group(1) + t
43 43
44 44
45 45 testpats = [
46 46 [
47 47 (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
48 48 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
49 49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
50 50 (r'sed.*-i', "don't use 'sed -i', use a temporary file"),
51 51 (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"),
52 52 (r'echo -n', "don't use 'echo -n', use printf"),
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 57 (r'printf.*\\([1-9]|0\d)', "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'[^\n]\Z', "no trailing newline"),
65 65 (r'export.*=', "don't export and assign at once"),
66 66 (r'^source\b', "don't use 'source', use '.'"),
67 67 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
68 68 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
69 69 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
70 70 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
71 71 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
72 72 (r'^alias\b.*=', "don't use alias, use a function"),
73 73 (r'if\s*!', "don't use '!' to negate exit status"),
74 74 (r'/dev/u?random', "don't use entropy, use /dev/zero"),
75 75 (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"),
76 76 (r'^( *)\t', "don't use tabs to indent"),
77 77 ],
78 78 # warnings
79 79 [
80 80 (r'^function', "don't use 'function', use old style"),
81 81 (r'^diff.*-\w*N', "don't use 'diff -N'"),
82 82 (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"),
83 83 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
84 84 (r'kill (`|\$\()', "don't use kill, use killdaemons.py")
85 85 ]
86 86 ]
87 87
88 88 testfilters = [
89 89 (r"( *)(#([^\n]*\S)?)", repcomment),
90 90 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
91 91 ]
92 92
93 93 winglobmsg = "use (glob) to match Windows paths too"
94 94 uprefix = r"^ \$ "
95 95 utestpats = [
96 96 [
97 97 (r'^(\S.*|| [$>] .*)[ \t]\n', "trailing whitespace on non-output"),
98 98 (uprefix + r'.*\|\s*sed[^|>\n]*\n',
99 99 "use regex test output patterns instead of sed"),
100 100 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
101 101 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
102 102 (uprefix + r'.*\|\| echo.*(fail|error)',
103 103 "explicit exit code checks unnecessary"),
104 104 (uprefix + r'set -e', "don't use set -e"),
105 105 (uprefix + r'\s', "don't indent commands, use > for continued lines"),
106 106 (r'^ saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg),
107 107 (r'^ changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$',
108 108 winglobmsg),
109 109 (r'^ pulling from \$TESTTMP/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'),
110 110 ],
111 111 # warnings
112 112 [
113 113 (r'^ [^*?/\n]* \(glob\)$',
114 114 "warning: glob match with no glob character (?*/)"),
115 115 ]
116 116 ]
117 117
118 118 for i in [0, 1]:
119 119 for p, m in testpats[i]:
120 120 if p.startswith(r'^'):
121 121 p = r"^ [$>] (%s)" % p[1:]
122 122 else:
123 123 p = r"^ [$>] .*(%s)" % p
124 124 utestpats[i].append((p, m))
125 125
126 126 utestfilters = [
127 127 (r"<<(\S+)((.|\n)*?\n > \1)", rephere),
128 128 (r"( *)(#([^\n]*\S)?)", repcomment),
129 129 ]
130 130
131 131 pypats = [
132 132 [
133 133 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
134 134 "tuple parameter unpacking not available in Python 3+"),
135 135 (r'lambda\s*\(.*,.*\)',
136 136 "tuple parameter unpacking not available in Python 3+"),
137 137 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
138 138 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
139 139 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
140 140 (r'\s<>\s', '<> operator is not available in Python 3+, use !='),
141 141 (r'^\s*\t', "don't use tabs"),
142 142 (r'\S;\s*\n', "semicolon"),
143 143 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
144 144 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
145 145 (r'(\w|\)),\w', "missing whitespace after ,"),
146 146 (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"),
147 147 (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"),
148 148 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
149 149 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Python 2.4'),
150 150 (r'(\s+)try:\n((?:\n|\1\s.*\n)*?)\1\s*yield\b.*?'
151 151 r'((?:\n|\1\s.*\n)+?)\1finally:',
152 152 'no yield inside try/finally in Python 2.4'),
153 153 (r'.{81}', "line too long"),
154 154 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
155 155 (r'[^\n]\Z', "no trailing newline"),
156 156 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
157 157 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
158 158 # "don't use underbars in identifiers"),
159 159 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
160 160 "don't use camelcase in identifiers"),
161 161 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
162 162 "linebreak after :"),
163 163 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
164 164 (r'class\s[^( \n]+\(\):',
165 165 "class foo() not available in Python 2.4, use class foo(object)"),
166 166 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
167 167 "Python keyword is not a function"),
168 168 (r',]', "unneeded trailing ',' in list"),
169 169 # (r'class\s[A-Z][^\(]*\((?!Exception)',
170 170 # "don't capitalize non-exception classes"),
171 171 # (r'in range\(', "use xrange"),
172 172 # (r'^\s*print\s+', "avoid using print in core and extensions"),
173 173 (r'[\x80-\xff]', "non-ASCII character literal"),
174 174 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
175 175 (r'^\s*with\s+', "with not available in Python 2.4"),
176 176 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
177 177 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
178 178 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
179 179 (r'(?<!def)\s+(any|all|format)\(',
180 180 "any/all/format not available in Python 2.4"),
181 181 (r'(?<!def)\s+(callable)\(',
182 182 "callable not available in Python 3, use getattr(f, '__call__', None)"),
183 183 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
184 184 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
185 185 "gratuitous whitespace after Python keyword"),
186 186 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
187 187 # (r'\s\s=', "gratuitous whitespace before ="),
188 188 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
189 189 "missing whitespace around operator"),
190 190 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s',
191 191 "missing whitespace around operator"),
192 192 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
193 193 "missing whitespace around operator"),
194 194 (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]',
195 195 "wrong whitespace around ="),
196 196 (r'raise Exception', "don't raise generic exceptions"),
197 197 (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$',
198 198 "don't use old-style two-argument raise, use Exception(message)"),
199 199 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
200 200 (r' [=!]=\s+(True|False|None)',
201 201 "comparison with singleton, use 'is' or 'is not' instead"),
202 202 (r'^\s*(while|if) [01]:',
203 203 "use True/False for constant Boolean expression"),
204 204 (r'(?:(?<!def)\s+|\()hasattr',
205 205 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
206 206 (r'opener\([^)]*\).read\(',
207 207 "use opener.read() instead"),
208 208 (r'BaseException', 'not in Python 2.4, use Exception'),
209 209 (r'os\.path\.relpath', 'os.path.relpath is not in Python 2.5'),
210 210 (r'opener\([^)]*\).write\(',
211 211 "use opener.write() instead"),
212 212 (r'[\s\(](open|file)\([^)]*\)\.read\(',
213 213 "use util.readfile() instead"),
214 214 (r'[\s\(](open|file)\([^)]*\)\.write\(',
215 215 "use util.readfile() instead"),
216 216 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
217 217 "always assign an opened file to a variable, and close it afterwards"),
218 218 (r'[\s\(](open|file)\([^)]*\)\.',
219 219 "always assign an opened file to a variable, and close it afterwards"),
220 220 (r'(?i)descendent', "the proper spelling is descendAnt"),
221 221 (r'\.debug\(\_', "don't mark debug messages for translation"),
222 222 (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
223 223 (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'),
224 224 (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"),
225 225 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
226 226 "missing _() in ui message (use () to hide false-positives)"),
227 227 ],
228 228 # warnings
229 229 [
230 230 ]
231 231 ]
232 232
233 233 pyfilters = [
234 234 (r"""(?msx)(?P<comment>\#.*?$)|
235 235 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
236 236 (?P<text>(([^\\]|\\.)*?))
237 237 (?P=quote))""", reppython),
238 238 ]
239 239
240 txtfilters = []
241
242 txtpats = [
243 [
244 ('\s$', 'trailing whitespace'),
245 ],
246 []
247 ]
248
240 249 cpats = [
241 250 [
242 251 (r'//', "don't use //-style comments"),
243 252 (r'^ ', "don't use spaces to indent"),
244 253 (r'\S\t', "don't use tabs except for indent"),
245 254 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
246 255 (r'.{81}', "line too long"),
247 256 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
248 257 (r'return\(', "return is not a function"),
249 258 (r' ;', "no space before ;"),
250 259 (r'\w+\* \w+', "use int *foo, not int* foo"),
251 260 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
252 261 (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
253 262 (r'\w,\w', "missing whitespace after ,"),
254 263 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
255 264 (r'^#\s+\w', "use #foo, not # foo"),
256 265 (r'[^\n]\Z', "no trailing newline"),
257 266 (r'^\s*#import\b', "use only #include in standard C code"),
258 267 ],
259 268 # warnings
260 269 []
261 270 ]
262 271
263 272 cfilters = [
264 273 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
265 274 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
266 275 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
267 276 (r'(\()([^)]+\))', repcallspaces),
268 277 ]
269 278
270 279 inutilpats = [
271 280 [
272 281 (r'\bui\.', "don't use ui in util"),
273 282 ],
274 283 # warnings
275 284 []
276 285 ]
277 286
278 287 inrevlogpats = [
279 288 [
280 289 (r'\brepo\.', "don't use repo in revlog"),
281 290 ],
282 291 # warnings
283 292 []
284 293 ]
285 294
286 295 checks = [
287 296 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
288 297 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
289 298 ('c', r'.*\.c$', cfilters, cpats),
290 299 ('unified test', r'.*\.t$', utestfilters, utestpats),
291 300 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
292 301 inrevlogpats),
293 302 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
294 303 inutilpats),
304 ('txt', r'.*\.txt$', txtfilters, txtpats),
295 305 ]
296 306
297 307 class norepeatlogger(object):
298 308 def __init__(self):
299 309 self._lastseen = None
300 310
301 311 def log(self, fname, lineno, line, msg, blame):
302 312 """print error related a to given line of a given file.
303 313
304 314 The faulty line will also be printed but only once in the case
305 315 of multiple errors.
306 316
307 317 :fname: filename
308 318 :lineno: line number
309 319 :line: actual content of the line
310 320 :msg: error message
311 321 """
312 322 msgid = fname, lineno, line
313 323 if msgid != self._lastseen:
314 324 if blame:
315 325 print "%s:%d (%s):" % (fname, lineno, blame)
316 326 else:
317 327 print "%s:%d:" % (fname, lineno)
318 328 print " > %s" % line
319 329 self._lastseen = msgid
320 330 print " " + msg
321 331
322 332 _defaultlogger = norepeatlogger()
323 333
324 334 def getblame(f):
325 335 lines = []
326 336 for l in os.popen('hg annotate -un %s' % f):
327 337 start, line = l.split(':', 1)
328 338 user, rev = start.split()
329 339 lines.append((line[1:-1], user, rev))
330 340 return lines
331 341
332 342 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
333 343 blame=False, debug=False, lineno=True):
334 344 """checks style and portability of a given file
335 345
336 346 :f: filepath
337 347 :logfunc: function used to report error
338 348 logfunc(filename, linenumber, linecontent, errormessage)
339 349 :maxerr: number of error to display before aborting.
340 350 Set to false (default) to report all errors
341 351
342 352 return True if no error is found, False otherwise.
343 353 """
344 354 blamecache = None
345 355 result = True
346 356 for name, match, filters, pats in checks:
347 357 if debug:
348 358 print name, f
349 359 fc = 0
350 360 if not re.match(match, f):
351 361 if debug:
352 362 print "Skipping %s for %s it doesn't match %s" % (
353 363 name, match, f)
354 364 continue
355 365 fp = open(f)
356 366 pre = post = fp.read()
357 367 fp.close()
358 368 if "no-" + "check-code" in pre:
359 369 if debug:
360 370 print "Skipping %s for %s it has no- and check-code" % (
361 371 name, f)
362 372 break
363 373 for p, r in filters:
364 374 post = re.sub(p, r, post)
365 375 if warnings:
366 376 pats = pats[0] + pats[1]
367 377 else:
368 378 pats = pats[0]
369 379 # print post # uncomment to show filtered version
370 380
371 381 if debug:
372 382 print "Checking %s for %s" % (name, f)
373 383
374 384 prelines = None
375 385 errors = []
376 386 for pat in pats:
377 387 if len(pat) == 3:
378 388 p, msg, ignore = pat
379 389 else:
380 390 p, msg = pat
381 391 ignore = None
382 392
383 393 # fix-up regexes for multi-line searches
384 394 po = p
385 395 # \s doesn't match \n
386 396 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
387 397 # [^...] doesn't match newline
388 398 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
389 399
390 400 #print po, '=>', p
391 401
392 402 pos = 0
393 403 n = 0
394 404 for m in re.finditer(p, post, re.MULTILINE):
395 405 if prelines is None:
396 406 prelines = pre.splitlines()
397 407 postlines = post.splitlines(True)
398 408
399 409 start = m.start()
400 410 while n < len(postlines):
401 411 step = len(postlines[n])
402 412 if pos + step > start:
403 413 break
404 414 pos += step
405 415 n += 1
406 416 l = prelines[n]
407 417
408 418 if "check-code" + "-ignore" in l:
409 419 if debug:
410 420 print "Skipping %s for %s:%s (check-code -ignore)" % (
411 421 name, f, n)
412 422 continue
413 423 elif ignore and re.search(ignore, l, re.MULTILINE):
414 424 continue
415 425 bd = ""
416 426 if blame:
417 427 bd = 'working directory'
418 428 if not blamecache:
419 429 blamecache = getblame(f)
420 430 if n < len(blamecache):
421 431 bl, bu, br = blamecache[n]
422 432 if bl == l:
423 433 bd = '%s@%s' % (bu, br)
424 434 errors.append((f, lineno and n + 1, l, msg, bd))
425 435 result = False
426 436
427 437 errors.sort()
428 438 for e in errors:
429 439 logfunc(*e)
430 440 fc += 1
431 441 if maxerr and fc >= maxerr:
432 442 print " (too many errors, giving up)"
433 443 break
434 444
435 445 return result
436 446
437 447 if __name__ == "__main__":
438 448 parser = optparse.OptionParser("%prog [options] [files]")
439 449 parser.add_option("-w", "--warnings", action="store_true",
440 450 help="include warning-level checks")
441 451 parser.add_option("-p", "--per-file", type="int",
442 452 help="max warnings per file")
443 453 parser.add_option("-b", "--blame", action="store_true",
444 454 help="use annotate to generate blame info")
445 455 parser.add_option("", "--debug", action="store_true",
446 456 help="show debug information")
447 457 parser.add_option("", "--nolineno", action="store_false",
448 458 dest='lineno', help="don't show line numbers")
449 459
450 460 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
451 461 lineno=True)
452 462 (options, args) = parser.parse_args()
453 463
454 464 if len(args) == 0:
455 465 check = glob.glob("*")
456 466 else:
457 467 check = args
458 468
459 469 ret = 0
460 470 for f in check:
461 471 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
462 472 blame=options.blame, debug=options.debug,
463 473 lineno=options.lineno):
464 474 ret = 1
465 475 sys.exit(ret)
@@ -1,133 +1,133
1 1 The standalone Windows installer for Mercurial is built in a somewhat
2 2 jury-rigged fashion.
3 3
4 4 It has the following prerequisites. Ensure to take the packages
5 5 matching the mercurial version you want to build (32-bit or 64-bit).
6 6
7 7 Python 2.6 for Windows
8 8 http://www.python.org/download/releases/
9 9
10 10 A compiler:
11 11 either MinGW
12 12 http://www.mingw.org/
13 13 or Microsoft Visual C++ 2008 SP1 Express Edition
14 14 http://www.microsoft.com/express/Downloads/Download-2008.aspx
15 15
16 16 Python for Windows Extensions
17 17 http://sourceforge.net/projects/pywin32/
18 18
19 19 mfc71.dll (just download, don't install; not needed for Python 2.6)
20 20 http://starship.python.net/crew/mhammond/win32/
21 21
22 22 Visual C++ 2008 redistributable package (needed for >= Python 2.6 or if you compile with MSVC)
23 23 for 32-bit:
24 24 http://www.microsoft.com/downloads/details.aspx?FamilyID=9b2da534-3e03-4391-8a4d-074b9f2bc1bf
25 25 for 64-bit:
26 26 http://www.microsoft.com/downloads/details.aspx?familyid=bd2a6171-e2d6-4230-b809-9a8d7548c1b6
27
27
28 28 The py2exe distutils extension
29 29 http://sourceforge.net/projects/py2exe/
30 30
31 31 GnuWin32 gettext utility (if you want to build translations)
32 32 http://gnuwin32.sourceforge.net/packages/gettext.htm
33 33
34 34 Inno Setup
35 35 http://www.jrsoftware.org/isdl.php#qsp
36 36
37 37 Get and install ispack-5.3.10.exe or later (includes Inno Setup Processor),
38 38 which is necessary to package Mercurial.
39 39
40 40 ISTool - optional
41 41 http://www.istool.org/default.aspx/
42 42
43 43 add_path (you need only add_path.exe in the zip file)
44 44 http://www.barisione.org/apps.html#add_path
45 45
46 46 Docutils
47 47 http://docutils.sourceforge.net/
48 48
49 49 CA Certs file
50 50 http://curl.haxx.se/ca/cacert.pem
51 51
52 52 And, of course, Mercurial itself.
53 53
54 54 Once you have all this installed and built, clone a copy of the
55 55 Mercurial repository you want to package, and name the repo
56 56 C:\hg\hg-release.
57 57
58 58 In a shell, build a standalone copy of the hg.exe program.
59 59
60 60 Building instructions for MinGW:
61 61 python setup.py build -c mingw32
62 62 python setup.py py2exe -b 2
63 63 Note: the previously suggested combined command of "python setup.py build -c
64 64 mingw32 py2exe -b 2" doesn't work correctly anymore as it doesn't include the
65 65 extensions in the mercurial subdirectory.
66 66 If you want to create a file named setup.cfg with the contents:
67 67 [build]
68 68 compiler=mingw32
69 69 you can skip the first build step.
70 70
71 71 Building instructions with MSVC 2008 Express Edition:
72 72 for 32-bit:
73 73 "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86
74 74 python setup.py py2exe -b 2
75 75 for 64-bit:
76 76 "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86_amd64
77 77 python setup.py py2exe -b 3
78 78
79 79 Copy add_path.exe and cacert.pem files into the dist directory that just got created.
80 80
81 81 If you are using Python up to version 2.5.4, copy mfc71.dll into the dist
82 82 directory that just got created.
83 83
84 84 If you are using Python 2.6 or later, or if you are using MSVC 2008 to compile
85 85 mercurial, you must include the C runtime libraries in the installer. To do so,
86 86 install the Visual C++ 2008 redistributable package. Then in your windows\winsxs
87 87 folder, locate the folder containing the dlls version 9.0.21022.8.
88 88 For x86, it should be named like x86_Microsoft.VC90.CRT_(...)_9.0.21022.8(...).
89 89 For x64, it should be named like amd64_Microsoft.VC90.CRT_(...)_9.0.21022.8(...).
90 90 Copy the files named msvcm90.dll, msvcp90.dll and msvcr90.dll into the dist
91 91 directory.
92 92 Then in the windows\winsxs\manifests folder, locate the corresponding manifest
93 93 file (x86_Microsoft.VC90.CRT_(...)_9.0.21022.8(...).manifest for x86,
94 94 amd64_Microsoft.VC90.CRT_(...)_9.0.21022.8(...).manifest for x64), copy it in the
95 95 dist directory and rename it to Microsoft.VC90.CRT.manifest.
96 96
97 Before building the installer, you have to build Mercurial HTML documentation
97 Before building the installer, you have to build Mercurial HTML documentation
98 98 (or fix mercurial.iss to not reference the doc directory):
99 99
100 100 cd doc
101 101 mingw32-make html
102 102 cd ..
103 103
104 104 If you use ISTool, you open the C:\hg\hg-release\contrib\win32\mercurial.iss
105 105 file and type Ctrl-F9 to compile the installer file.
106 106
107 107 Otherwise you run the Inno Setup compiler. Assuming it's in the path
108 108 you should execute:
109 109
110 110 iscc contrib\win32\mercurial.iss /dVERSION=foo
111 111
112 112 Where 'foo' is the version number you would like to see in the
113 113 'Add/Remove Applications' tool. The installer will be placed into
114 114 a directory named Output/ at the root of your repository.
115 115 If the /dVERSION=foo parameter is not given in the command line, the
116 116 installer will retrieve the version information from the __version__.py file.
117 117
118 118 If you want to build an installer for a 64-bit mercurial, add /dARCH=x64 to
119 119 your command line:
120 120 iscc contrib\win32\mercurial.iss /dARCH=x64
121 121
122 122 To automate the steps above you may want to create a batchfile based on the
123 123 following (MinGW build chain):
124 124
125 125 echo [build] > setup.cfg
126 126 echo compiler=mingw32 >> setup.cfg
127 127 python setup.py py2exe -b 2
128 128 cd doc
129 129 mingw32-make html
130 130 cd ..
131 131 iscc contrib\win32\mercurial.iss /dVERSION=snapshot
132 132
133 133 and run it from the root of the hg repository (c:\hg\hg-release).
@@ -1,119 +1,119
1 1 ====
2 2 hg
3 3 ====
4 4
5 5 ---------------------------------------
6 6 Mercurial source code management system
7 7 ---------------------------------------
8 8
9 9 :Author: Matt Mackall <mpm@selenic.com>
10 10 :Organization: Mercurial
11 11 :Manual section: 1
12 12 :Manual group: Mercurial Manual
13 13
14 14 .. contents::
15 15 :backlinks: top
16 16 :class: htmlonly
17 17 :depth: 1
18 18
19 19
20 20 Synopsis
21 21 """"""""
22 22 **hg** *command* [*option*]... [*argument*]...
23 23
24 24 Description
25 25 """""""""""
26 26 The **hg** command provides a command line interface to the Mercurial
27 27 system.
28 28
29 29 Command Elements
30 30 """"""""""""""""
31 31
32 32 files...
33 33 indicates one or more filename or relative path filenames; see
34 34 `File Name Patterns`_ for information on pattern matching
35 35
36 36 path
37 37 indicates a path on the local machine
38 38
39 39 revision
40 40 indicates a changeset which can be specified as a changeset
41 41 revision number, a tag, or a unique substring of the changeset
42 42 hash value
43 43
44 44 repository path
45 45 either the pathname of a local repository or the URI of a remote
46 46 repository.
47 47
48 48 .. include:: hg.1.gendoc.txt
49 49
50 50 Files
51 51 """""
52 52
53 53 ``/etc/mercurial/hgrc``, ``$HOME/.hgrc``, ``.hg/hgrc``
54 54 This file contains defaults and configuration. Values in
55 55 ``.hg/hgrc`` override those in ``$HOME/.hgrc``, and these override
56 56 settings made in the global ``/etc/mercurial/hgrc`` configuration.
57 57 See |hgrc(5)|_ for details of the contents and format of these
58 58 files.
59 59
60 60 ``.hgignore``
61 61 This file contains regular expressions (one per line) that
62 62 describe file names that should be ignored by **hg**. For details,
63 63 see |hgignore(5)|_.
64 64
65 65 ``.hgsub``
66 66 This file defines the locations of all subrepositories, and
67 67 tells where the subrepository checkouts came from. For details, see
68 68 :hg:`help subrepos`.
69 69
70 70 ``.hgsubstate``
71 71 This file is where Mercurial stores all nested repository states. *NB: This
72 72 file should not be edited manually.*
73 73
74 74 ``.hgtags``
75 75 This file contains changeset hash values and text tag names (one
76 76 of each separated by spaces) that correspond to tagged versions of
77 77 the repository contents. The file content is encoded using UTF-8.
78 78
79 79 ``.hg/last-message.txt``
80 80 This file is used by :hg:`commit` to store a backup of the commit message
81 81 in case the commit fails.
82 82
83 83 ``.hg/localtags``
84 84 This file can be used to define local tags which are not shared among
85 85 repositories. The file format is the same as for ``.hgtags``, but it is
86 86 encoded using the local system encoding.
87
87
88 88 Some commands (e.g. revert) produce backup files ending in ``.orig``,
89 89 if the ``.orig`` file already exists and is not tracked by Mercurial,
90 90 it will be overwritten.
91 91
92 92 Bugs
93 93 """"
94 94 Probably lots, please post them to the mailing list (see Resources_
95 95 below) when you find them.
96 96
97 97 See Also
98 98 """"""""
99 99 |hgignore(5)|_, |hgrc(5)|_
100 100
101 101 Author
102 102 """"""
103 103 Written by Matt Mackall <mpm@selenic.com>
104 104
105 105 Resources
106 106 """""""""
107 107 Main Web Site: http://mercurial.selenic.com/
108 108
109 109 Source code repository: http://selenic.com/hg
110 110
111 111 Mailing list: http://selenic.com/mailman/listinfo/mercurial
112 112
113 113 Copying
114 114 """""""
115 115 Copyright (C) 2005-2012 Matt Mackall.
116 116 Free use of this software is granted under the terms of the GNU General
117 117 Public License version 2 or any later version.
118 118
119 119 .. include:: common.txt
@@ -1,65 +1,65
1 1 Mercurial supports a functional language for selecting a set of
2 files.
2 files.
3 3
4 4 Like other file patterns, this pattern type is indicated by a prefix,
5 5 'set:'. The language supports a number of predicates which are joined
6 6 by infix operators. Parenthesis can be used for grouping.
7 7
8 8 Identifiers such as filenames or patterns must be quoted with single
9 9 or double quotes if they contain characters outside of
10 10 ``[.*{}[]?/\_a-zA-Z0-9\x80-\xff]`` or if they match one of the
11 11 predefined predicates. This generally applies to file patterns other
12 12 than globs and arguments for predicates.
13 13
14 14 Special characters can be used in quoted identifiers by escaping them,
15 15 e.g., ``\n`` is interpreted as a newline. To prevent them from being
16 16 interpreted, strings can be prefixed with ``r``, e.g. ``r'...'``.
17 17
18 18 There is a single prefix operator:
19 19
20 20 ``not x``
21 21 Files not in x. Short form is ``! x``.
22 22
23 23 These are the supported infix operators:
24 24
25 25 ``x and y``
26 26 The intersection of files in x and y. Short form is ``x & y``.
27 27
28 28 ``x or y``
29 29 The union of files in x and y. There are two alternative short
30 30 forms: ``x | y`` and ``x + y``.
31 31
32 32 ``x - y``
33 33 Files in x but not in y.
34 34
35 35 The following predicates are supported:
36 36
37 37 .. predicatesmarker
38 38
39 39 Some sample queries:
40 40
41 41 - Show status of files that appear to be binary in the working directory::
42 42
43 43 hg status -A "set:binary()"
44 44
45 45 - Forget files that are in .hgignore but are already tracked::
46 46
47 47 hg forget "set:hgignore() and not ignored()"
48 48
49 49 - Find text files that contain a string::
50 50
51 51 hg locate "set:grep(magic) and not binary()"
52 52
53 53 - Find C files in a non-standard encoding::
54 54
55 55 hg locate "set:**.c and not encoding('UTF-8')"
56 56
57 57 - Revert copies of large binary files::
58 58
59 59 hg revert "set:copied() and binary() and size('>1M')"
60 60
61 61 - Remove files listed in foo.lst that contain the letter a or b::
62 62
63 63 hg remove "set: 'listfile:foo.lst' and (**a* or **b*)"
64 64
65 65 See also :hg:`help patterns`.
@@ -1,57 +1,57
1 1 Mercurial accepts several notations for identifying one or more files
2 2 at a time.
3 3
4 4 By default, Mercurial treats filenames as shell-style extended glob
5 5 patterns.
6 6
7 7 Alternate pattern notations must be specified explicitly.
8 8
9 9 .. note::
10 Patterns specified in ``.hgignore`` are not rooted.
10 Patterns specified in ``.hgignore`` are not rooted.
11 11 Please see :hg:`help hgignore` for details.
12 12
13 13 To use a plain path name without any pattern matching, start it with
14 14 ``path:``. These path names must completely match starting at the
15 15 current repository root.
16 16
17 17 To use an extended glob, start a name with ``glob:``. Globs are rooted
18 18 at the current directory; a glob such as ``*.c`` will only match files
19 19 in the current directory ending with ``.c``.
20 20
21 21 The supported glob syntax extensions are ``**`` to match any string
22 22 across path separators and ``{a,b}`` to mean "a or b".
23 23
24 24 To use a Perl/Python regular expression, start a name with ``re:``.
25 25 Regexp pattern matching is anchored at the root of the repository.
26 26
27 27 To read name patterns from a file, use ``listfile:`` or ``listfile0:``.
28 28 The latter expects null delimited patterns while the former expects line
29 29 feeds. Each string read from the file is itself treated as a file
30 30 pattern.
31 31
32 32 Plain examples::
33 33
34 34 path:foo/bar a name bar in a directory named foo in the root
35 35 of the repository
36 36 path:path:name a file or directory named "path:name"
37 37
38 38 Glob examples::
39 39
40 40 glob:*.c any name ending in ".c" in the current directory
41 41 *.c any name ending in ".c" in the current directory
42 42 **.c any name ending in ".c" in any subdirectory of the
43 43 current directory including itself.
44 44 foo/*.c any name ending in ".c" in the directory foo
45 45 foo/**.c any name ending in ".c" in any subdirectory of foo
46 46 including itself.
47 47
48 48 Regexp examples::
49 49
50 50 re:.*\.c$ any name ending in ".c", anywhere in the repository
51 51
52 52 File examples::
53 53
54 54 listfile:list.txt read list from list.txt with one file pattern per line
55 55 listfile0:list.txt read list from list.txt with null byte delimiters
56 56
57 57 See also :hg:`help filesets`.
@@ -1,84 +1,84
1 1 What are phases?
2 2 ================
3 3
4 4 Phases are a system for tracking which changesets have been or should
5 5 be shared. This helps prevent common mistakes when modifying history
6 6 (for instance, with the mq or rebase extensions).
7 7
8 8 Each changeset in a repository is in one of the following phases:
9 9
10 10 - public : changeset is visible on a public server
11 11 - draft : changeset is not yet published
12 12 - secret : changeset should not be pushed, pulled, or cloned
13 13
14 14 These phases are ordered (public < draft < secret) and no changeset
15 15 can be in a lower phase than its ancestors. For instance, if a
16 16 changeset is public, all its ancestors are also public. Lastly,
17 17 changeset phases should only be changed towards the public phase.
18 18
19 19 How are phases managed?
20 20 =======================
21 21
22 22 For the most part, phases should work transparently. By default, a
23 23 changeset is created in the draft phase and is moved into the public
24 24 phase when it is pushed to another repository.
25 25
26 26 Once changesets become public, extensions like mq and rebase will
27 27 refuse to operate on them to prevent creating duplicate changesets.
28 28 Phases can also be manually manipulated with the :hg:`phase` command
29 29 if needed. See :hg:`help -v phase` for examples.
30 30
31 31 Phases and servers
32 32 ==================
33 33
34 34 Normally, all servers are ``publishing`` by default. This means::
35 35
36 36 - all draft changesets that are pulled or cloned appear in phase
37 37 public on the client
38 38
39 39 - all draft changesets that are pushed appear as public on both
40 40 client and server
41 41
42 42 - secret changesets are neither pushed, pulled, or cloned
43 43
44 44 .. note::
45 45 Pulling a draft changeset from a publishing server does not mark it
46 46 as public on the server side due to the read-only nature of pull.
47 47
48 48 Sometimes it may be desirable to push and pull changesets in the draft
49 49 phase to share unfinished work. This can be done by setting a
50 50 repository to disable publishing in its configuration file::
51 51
52 52 [phases]
53 53 publish = False
54 54
55 55 See :hg:`help config` for more information on config files.
56 56
57 57 .. note::
58 58 Servers running older versions of Mercurial are treated as
59 59 publishing.
60 60
61 61 Examples
62 62 ========
63 63
64 64 - list changesets in draft or secret phase::
65 65
66 66 hg log -r "not public()"
67 67
68 68 - change all secret changesets to draft::
69 69
70 70 hg phase --draft "secret()"
71 71
72 72 - forcibly move the current changeset and descendants from public to draft::
73 73
74 74 hg phase --force --draft .
75 75
76 76 - show a list of changeset revision and phase::
77 77
78 78 hg log --template "{rev} {phase}\n"
79 79
80 80 - resynchronize draft changesets relative to a remote repository::
81 81
82 hg phase -fd 'outgoing(URL)'
82 hg phase -fd 'outgoing(URL)'
83 83
84 84 See :hg:`help phase` for more information on manually manipulating phases.
General Comments 0
You need to be logged in to leave comments. Login now