##// END OF EJS Templates
pvec: introduce pvecs
Matt Mackall -
r16249:0d175ac5 default
parent child Browse files
Show More
@@ -0,0 +1,210 b''
1 # pvec.py - probabilistic vector clocks for Mercurial
2 #
3 # Copyright 2012 Matt Mackall <mpm@selenic.com>
4 #
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
7
8 '''
9 A "pvec" is a changeset property based on the theory of vector clocks
10 that can be compared to discover relatedness without consulting a
11 graph. This can be useful for tasks like determining how a
12 disconnected patch relates to a repository.
13
14 Currently a pvec consist of 448 bits, of which 24 are 'depth' and the
15 remainder are a bit vector. It is represented as a 70-character base85
16 string.
17
18 Construction:
19
20 - a root changeset has a depth of 0 and a bit vector based on its hash
21 - a normal commit has a changeset where depth is increased by one and
22 one bit vector bit is flipped based on its hash
23 - a merge changeset pvec is constructed by copying changes from one pvec into
24 the other to balance its depth
25
26 Properties:
27
28 - for linear changes, difference in depth is always <= hamming distance
29 - otherwise, changes are probably divergent
30 - when hamming distance is < 200, we can reliably detect when pvecs are near
31
32 Issues:
33
34 - hamming distance ceases to work over distances of ~ 200
35 - detecting divergence is less accurate when the common ancestor is very close
36 to either revision or total distance is high
37 - this could probably be improved by modeling the relation between
38 delta and hdist
39
40 Uses:
41
42 - a patch pvec can be used to locate the nearest available common ancestor for
43 resolving conflicts
44 - ordering of patches can be established without a DAG
45 - two head pvecs can be compared to determine whether push/pull/merge is needed
46 and approximately how many changesets are involved
47 - can be used to find a heuristic divergence measure between changesets on
48 different branches
49 '''
50
51 import base85, util
52 from node import nullrev
53
54 _size = 448 # 70 chars b85-encoded
55 _bytes = _size / 8
56 _depthbits = 24
57 _depthbytes = _depthbits / 8
58 _vecbytes = _bytes - _depthbytes
59 _vecbits = _vecbytes * 8
60 _radius = (_vecbits - 30) / 2 # high probability vecs are related
61
62 def _bin(bs):
63 '''convert a bytestring to a long'''
64 v = 0
65 for b in bs:
66 v = v * 256 + ord(b)
67 return v
68
69 def _str(v, l):
70 bs = ""
71 for p in xrange(l):
72 bs = chr(v & 255) + bs
73 v >>= 8
74 return bs
75
76 def _split(b):
77 '''depth and bitvec'''
78 return _bin(b[:_depthbytes]), _bin(b[_depthbytes:])
79
80 def _join(depth, bitvec):
81 return _str(depth, _depthbytes) + _str(bitvec, _vecbytes)
82
83 def _hweight(x):
84 c = 0
85 while x:
86 if x & 1:
87 c += 1
88 x >>= 1
89 return c
90 _htab = [_hweight(x) for x in xrange(256)]
91
92 def _hamming(a, b):
93 '''find the hamming distance between two longs'''
94 d = a ^ b
95 c = 0
96 while d:
97 c += _htab[d & 0xff]
98 d >>= 8
99 return c
100
101 def _mergevec(x, y, c):
102 # Ideally, this function would be x ^ y ^ ancestor, but finding
103 # ancestors is a nuisance. So instead we find the minimal number
104 # of changes to balance the depth and hamming distance
105
106 d1, v1 = x
107 d2, v2 = y
108 if d1 < d2:
109 d1, d2, v1, v2 = d2, d1, v2, v1
110
111 hdist = _hamming(v1, v2)
112 ddist = d1 - d2
113 v = v1
114 m = v1 ^ v2 # mask of different bits
115 i = 1
116
117 if hdist > ddist:
118 # if delta = 10 and hdist = 100, then we need to go up 55 steps
119 # to the ancestor and down 45
120 changes = (hdist - ddist + 1) / 2
121 else:
122 # must make at least one change
123 changes = 1
124 depth = d1 + changes
125
126 # copy changes from v2
127 if m:
128 while changes:
129 if m & i:
130 v ^= i
131 changes -= 1
132 i <<= 1
133 else:
134 v = _flipbit(v, c)
135
136 return depth, v
137
138 def _flipbit(v, node):
139 # converting bit strings to longs is slow
140 bit = (hash(node) & 0xffffffff) % _vecbits
141 return v ^ (1<<bit)
142
143 def ctxpvec(ctx):
144 '''construct a pvec for ctx while filling in the cache'''
145 r = ctx._repo
146 if not util.safehasattr(r, "_pveccache"):
147 r._pveccache = {}
148 pvc = r._pveccache
149 if ctx.rev() not in pvc:
150 cl = r.changelog
151 for n in xrange(ctx.rev() + 1):
152 if n not in pvc:
153 node = cl.node(n)
154 p1, p2 = cl.parentrevs(n)
155 if p1 == nullrev:
156 # start with a 'random' vector at root
157 pvc[n] = (0, _bin((node * 3)[:_vecbytes]))
158 elif p2 == nullrev:
159 d, v = pvc[p1]
160 pvc[n] = (d + 1, _flipbit(v, node))
161 else:
162 pvc[n] = _mergevec(pvc[p1], pvc[p2], node)
163 bs = _join(*pvc[ctx.rev()])
164 return pvec(base85.b85encode(bs))
165
166 class pvec(object):
167 def __init__(self, hashorctx):
168 if isinstance(hashorctx, str):
169 self._bs = hashorctx
170 self._depth, self._vec = _split(base85.b85decode(hashorctx))
171 else:
172 self._vec = ctxpvec(ctx)
173
174 def __str__(self):
175 return self._bs
176
177 def __eq__(self, b):
178 return self._vec == b._vec and self._depth == b._depth
179
180 def __lt__(self, b):
181 delta = b._depth - self._depth
182 if delta < 0:
183 return False # always correct
184 if _hamming(self._vec, b._vec) > delta:
185 return False
186 return True
187
188 def __gt__(self, b):
189 return b < self
190
191 def __or__(self, b):
192 delta = abs(b._depth - self._depth)
193 if _hamming(self._vec, b._vec) <= delta:
194 return False
195 return True
196
197 def __sub__(self, b):
198 if self | b:
199 raise ValueError("concurrent pvecs")
200 return self._depth - b._depth
201
202 def distance(self, b):
203 d = abs(b._depth - self._depth)
204 h = _hamming(self._vec, b._vec)
205 return max(d, h)
206
207 def near(self, b):
208 dist = abs(b.depth - self._depth)
209 if dist > _radius or _hamming(self._vec, b._vec) > _radius:
210 return False
@@ -1,432 +1,432 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # check-code - a style and portability checker for Mercurial
3 # check-code - a style and portability checker for Mercurial
4 #
4 #
5 # Copyright 2010 Matt Mackall <mpm@selenic.com>
5 # Copyright 2010 Matt Mackall <mpm@selenic.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 import re, glob, os, sys
10 import re, glob, os, sys
11 import keyword
11 import keyword
12 import optparse
12 import optparse
13
13
14 def repquote(m):
14 def repquote(m):
15 t = re.sub(r"\w", "x", m.group('text'))
15 t = re.sub(r"\w", "x", m.group('text'))
16 t = re.sub(r"[^\s\nx]", "o", t)
16 t = re.sub(r"[^\s\nx]", "o", t)
17 return m.group('quote') + t + m.group('quote')
17 return m.group('quote') + t + m.group('quote')
18
18
19 def reppython(m):
19 def reppython(m):
20 comment = m.group('comment')
20 comment = m.group('comment')
21 if comment:
21 if comment:
22 return "#" * len(comment)
22 return "#" * len(comment)
23 return repquote(m)
23 return repquote(m)
24
24
25 def repcomment(m):
25 def repcomment(m):
26 return m.group(1) + "#" * len(m.group(2))
26 return m.group(1) + "#" * len(m.group(2))
27
27
28 def repccomment(m):
28 def repccomment(m):
29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
30 return m.group(1) + t + "*/"
30 return m.group(1) + t + "*/"
31
31
32 def repcallspaces(m):
32 def repcallspaces(m):
33 t = re.sub(r"\n\s+", "\n", m.group(2))
33 t = re.sub(r"\n\s+", "\n", m.group(2))
34 return m.group(1) + t
34 return m.group(1) + t
35
35
36 def repinclude(m):
36 def repinclude(m):
37 return m.group(1) + "<foo>"
37 return m.group(1) + "<foo>"
38
38
39 def rephere(m):
39 def rephere(m):
40 t = re.sub(r"\S", "x", m.group(2))
40 t = re.sub(r"\S", "x", m.group(2))
41 return m.group(1) + t
41 return m.group(1) + t
42
42
43
43
44 testpats = [
44 testpats = [
45 [
45 [
46 (r'(pushd|popd)', "don't use 'pushd' or 'popd', use 'cd'"),
46 (r'(pushd|popd)', "don't use 'pushd' or 'popd', use 'cd'"),
47 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
47 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
48 (r'^function', "don't use 'function', use old style"),
48 (r'^function', "don't use 'function', use old style"),
49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
50 (r'echo.*\\n', "don't use 'echo \\n', use printf"),
50 (r'echo.*\\n', "don't use 'echo \\n', use printf"),
51 (r'echo -n', "don't use 'echo -n', use printf"),
51 (r'echo -n', "don't use 'echo -n', use printf"),
52 (r'^diff.*-\w*N', "don't use 'diff -N'"),
52 (r'^diff.*-\w*N', "don't use 'diff -N'"),
53 (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
53 (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
54 (r'head -c', "don't use 'head -c', use 'dd'"),
54 (r'head -c', "don't use 'head -c', use 'dd'"),
55 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
55 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
56 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
56 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
57 (r'printf.*\\\d{1,3}', "don't use 'printf \NNN', use Python"),
57 (r'printf.*\\\d{1,3}', "don't use 'printf \NNN', use Python"),
58 (r'printf.*\\x', "don't use printf \\x, use Python"),
58 (r'printf.*\\x', "don't use printf \\x, use Python"),
59 (r'\$\(.*\)', "don't use $(expr), use `expr`"),
59 (r'\$\(.*\)', "don't use $(expr), use `expr`"),
60 (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
60 (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
61 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
61 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
62 "use egrep for extended grep syntax"),
62 "use egrep for extended grep syntax"),
63 (r'/bin/', "don't use explicit paths for tools"),
63 (r'/bin/', "don't use explicit paths for tools"),
64 (r'\$PWD', "don't use $PWD, use `pwd`"),
64 (r'\$PWD', "don't use $PWD, use `pwd`"),
65 (r'[^\n]\Z', "no trailing newline"),
65 (r'[^\n]\Z', "no trailing newline"),
66 (r'export.*=', "don't export and assign at once"),
66 (r'export.*=', "don't export and assign at once"),
67 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\\^', "^ must be quoted"),
67 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\\^', "^ must be quoted"),
68 (r'^source\b', "don't use 'source', use '.'"),
68 (r'^source\b', "don't use 'source', use '.'"),
69 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
69 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
70 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
70 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
71 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
71 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
72 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
72 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
73 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
73 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
74 (r'^alias\b.*=', "don't use alias, use a function"),
74 (r'^alias\b.*=', "don't use alias, use a function"),
75 ],
75 ],
76 # warnings
76 # warnings
77 []
77 []
78 ]
78 ]
79
79
80 testfilters = [
80 testfilters = [
81 (r"( *)(#([^\n]*\S)?)", repcomment),
81 (r"( *)(#([^\n]*\S)?)", repcomment),
82 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
82 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
83 ]
83 ]
84
84
85 uprefix = r"^ \$ "
85 uprefix = r"^ \$ "
86 uprefixc = r"^ > "
86 uprefixc = r"^ > "
87 utestpats = [
87 utestpats = [
88 [
88 [
89 (r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"),
89 (r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"),
90 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"),
90 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"),
91 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
91 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
92 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
92 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
93 (uprefix + r'.*\|\| echo.*(fail|error)',
93 (uprefix + r'.*\|\| echo.*(fail|error)',
94 "explicit exit code checks unnecessary"),
94 "explicit exit code checks unnecessary"),
95 (uprefix + r'set -e', "don't use set -e"),
95 (uprefix + r'set -e', "don't use set -e"),
96 (uprefixc + r'( *)\t', "don't use tabs to indent"),
96 (uprefixc + r'( *)\t', "don't use tabs to indent"),
97 ],
97 ],
98 # warnings
98 # warnings
99 []
99 []
100 ]
100 ]
101
101
102 for i in [0, 1]:
102 for i in [0, 1]:
103 for p, m in testpats[i]:
103 for p, m in testpats[i]:
104 if p.startswith(r'^'):
104 if p.startswith(r'^'):
105 p = uprefix + p[1:]
105 p = uprefix + p[1:]
106 else:
106 else:
107 p = uprefix + ".*" + p
107 p = uprefix + ".*" + p
108 utestpats[i].append((p, m))
108 utestpats[i].append((p, m))
109
109
110 utestfilters = [
110 utestfilters = [
111 (r"( *)(#([^\n]*\S)?)", repcomment),
111 (r"( *)(#([^\n]*\S)?)", repcomment),
112 ]
112 ]
113
113
114 pypats = [
114 pypats = [
115 [
115 [
116 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
116 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
117 "tuple parameter unpacking not available in Python 3+"),
117 "tuple parameter unpacking not available in Python 3+"),
118 (r'lambda\s*\(.*,.*\)',
118 (r'lambda\s*\(.*,.*\)',
119 "tuple parameter unpacking not available in Python 3+"),
119 "tuple parameter unpacking not available in Python 3+"),
120 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
120 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
121 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
121 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
122 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
122 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
123 (r'^\s*\t', "don't use tabs"),
123 (r'^\s*\t', "don't use tabs"),
124 (r'\S;\s*\n', "semicolon"),
124 (r'\S;\s*\n', "semicolon"),
125 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
125 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"),
126 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
126 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"),
127 (r'\w,\w', "missing whitespace after ,"),
127 (r'\w,\w', "missing whitespace after ,"),
128 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
128 (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
129 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
129 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"),
130 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
130 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n'
131 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Py2.4'),
131 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Py2.4'),
132 (r'.{85}', "line too long"),
132 (r'.{85}', "line too long"),
133 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
133 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'),
134 (r'[^\n]\Z', "no trailing newline"),
134 (r'[^\n]\Z', "no trailing newline"),
135 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
135 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
136 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
136 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
137 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
137 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ',
138 "don't use camelcase in identifiers"),
138 "don't use camelcase in identifiers"),
139 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
139 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
140 "linebreak after :"),
140 "linebreak after :"),
141 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
141 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"),
142 (r'class\s[^( \n]+\(\):',
142 (r'class\s[^( \n]+\(\):',
143 "class foo() not available in Python 2.4, use class foo(object)"),
143 "class foo() not available in Python 2.4, use class foo(object)"),
144 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
144 (r'\b(%s)\(' % '|'.join(keyword.kwlist),
145 "Python keyword is not a function"),
145 "Python keyword is not a function"),
146 (r',]', "unneeded trailing ',' in list"),
146 (r',]', "unneeded trailing ',' in list"),
147 # (r'class\s[A-Z][^\(]*\((?!Exception)',
147 # (r'class\s[A-Z][^\(]*\((?!Exception)',
148 # "don't capitalize non-exception classes"),
148 # "don't capitalize non-exception classes"),
149 # (r'in range\(', "use xrange"),
149 # (r'in range\(', "use xrange"),
150 # (r'^\s*print\s+', "avoid using print in core and extensions"),
150 # (r'^\s*print\s+', "avoid using print in core and extensions"),
151 (r'[\x80-\xff]', "non-ASCII character literal"),
151 (r'[\x80-\xff]', "non-ASCII character literal"),
152 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
152 (r'("\')\.format\(', "str.format() not available in Python 2.4"),
153 (r'^\s*with\s+', "with not available in Python 2.4"),
153 (r'^\s*with\s+', "with not available in Python 2.4"),
154 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
154 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
155 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
155 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
156 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
156 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
157 (r'(?<!def)\s+(any|all|format)\(',
157 (r'(?<!def)\s+(any|all|format)\(',
158 "any/all/format not available in Python 2.4"),
158 "any/all/format not available in Python 2.4"),
159 (r'(?<!def)\s+(callable)\(',
159 (r'(?<!def)\s+(callable)\(',
160 "callable not available in Python 3, use getattr(f, '__call__', None)"),
160 "callable not available in Python 3, use getattr(f, '__call__', None)"),
161 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
161 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
162 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
162 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
163 "gratuitous whitespace after Python keyword"),
163 "gratuitous whitespace after Python keyword"),
164 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
164 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
165 # (r'\s\s=', "gratuitous whitespace before ="),
165 # (r'\s\s=', "gratuitous whitespace before ="),
166 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
166 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
167 "missing whitespace around operator"),
167 "missing whitespace around operator"),
168 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s',
168 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s',
169 "missing whitespace around operator"),
169 "missing whitespace around operator"),
170 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
170 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
171 "missing whitespace around operator"),
171 "missing whitespace around operator"),
172 (r'[^+=*/!<>&| -](\s=|=\s)[^= ]',
172 (r'[^^+=*/!<>&| -](\s=|=\s)[^= ]',
173 "wrong whitespace around ="),
173 "wrong whitespace around ="),
174 (r'raise Exception', "don't raise generic exceptions"),
174 (r'raise Exception', "don't raise generic exceptions"),
175 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
175 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
176 (r' [=!]=\s+(True|False|None)',
176 (r' [=!]=\s+(True|False|None)',
177 "comparison with singleton, use 'is' or 'is not' instead"),
177 "comparison with singleton, use 'is' or 'is not' instead"),
178 (r'^\s*(while|if) [01]:',
178 (r'^\s*(while|if) [01]:',
179 "use True/False for constant Boolean expression"),
179 "use True/False for constant Boolean expression"),
180 (r'(?<!def)\s+hasattr',
180 (r'(?<!def)\s+hasattr',
181 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
181 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'),
182 (r'opener\([^)]*\).read\(',
182 (r'opener\([^)]*\).read\(',
183 "use opener.read() instead"),
183 "use opener.read() instead"),
184 (r'BaseException', 'not in Py2.4, use Exception'),
184 (r'BaseException', 'not in Py2.4, use Exception'),
185 (r'os\.path\.relpath', 'os.path.relpath is not in Py2.5'),
185 (r'os\.path\.relpath', 'os.path.relpath is not in Py2.5'),
186 (r'opener\([^)]*\).write\(',
186 (r'opener\([^)]*\).write\(',
187 "use opener.write() instead"),
187 "use opener.write() instead"),
188 (r'[\s\(](open|file)\([^)]*\)\.read\(',
188 (r'[\s\(](open|file)\([^)]*\)\.read\(',
189 "use util.readfile() instead"),
189 "use util.readfile() instead"),
190 (r'[\s\(](open|file)\([^)]*\)\.write\(',
190 (r'[\s\(](open|file)\([^)]*\)\.write\(',
191 "use util.readfile() instead"),
191 "use util.readfile() instead"),
192 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
192 (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
193 "always assign an opened file to a variable, and close it afterwards"),
193 "always assign an opened file to a variable, and close it afterwards"),
194 (r'[\s\(](open|file)\([^)]*\)\.',
194 (r'[\s\(](open|file)\([^)]*\)\.',
195 "always assign an opened file to a variable, and close it afterwards"),
195 "always assign an opened file to a variable, and close it afterwards"),
196 (r'(?i)descendent', "the proper spelling is descendAnt"),
196 (r'(?i)descendent', "the proper spelling is descendAnt"),
197 (r'\.debug\(\_', "don't mark debug messages for translation"),
197 (r'\.debug\(\_', "don't mark debug messages for translation"),
198 ],
198 ],
199 # warnings
199 # warnings
200 [
200 [
201 (r'.{81}', "warning: line over 80 characters"),
201 (r'.{81}', "warning: line over 80 characters"),
202 (r'^\s*except:$', "warning: naked except clause"),
202 (r'^\s*except:$', "warning: naked except clause"),
203 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
203 (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
204 "warning: unwrapped ui message"),
204 "warning: unwrapped ui message"),
205 ]
205 ]
206 ]
206 ]
207
207
208 pyfilters = [
208 pyfilters = [
209 (r"""(?msx)(?P<comment>\#.*?$)|
209 (r"""(?msx)(?P<comment>\#.*?$)|
210 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
210 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
211 (?P<text>(([^\\]|\\.)*?))
211 (?P<text>(([^\\]|\\.)*?))
212 (?P=quote))""", reppython),
212 (?P=quote))""", reppython),
213 ]
213 ]
214
214
215 cpats = [
215 cpats = [
216 [
216 [
217 (r'//', "don't use //-style comments"),
217 (r'//', "don't use //-style comments"),
218 (r'^ ', "don't use spaces to indent"),
218 (r'^ ', "don't use spaces to indent"),
219 (r'\S\t', "don't use tabs except for indent"),
219 (r'\S\t', "don't use tabs except for indent"),
220 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
220 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
221 (r'.{85}', "line too long"),
221 (r'.{85}', "line too long"),
222 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
222 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
223 (r'return\(', "return is not a function"),
223 (r'return\(', "return is not a function"),
224 (r' ;', "no space before ;"),
224 (r' ;', "no space before ;"),
225 (r'\w+\* \w+', "use int *foo, not int* foo"),
225 (r'\w+\* \w+', "use int *foo, not int* foo"),
226 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
226 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
227 (r'\S+ (\+\+|--)', "use foo++, not foo ++"),
227 (r'\S+ (\+\+|--)', "use foo++, not foo ++"),
228 (r'\w,\w', "missing whitespace after ,"),
228 (r'\w,\w', "missing whitespace after ,"),
229 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
229 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
230 (r'^#\s+\w', "use #foo, not # foo"),
230 (r'^#\s+\w', "use #foo, not # foo"),
231 (r'[^\n]\Z', "no trailing newline"),
231 (r'[^\n]\Z', "no trailing newline"),
232 (r'^\s*#import\b', "use only #include in standard C code"),
232 (r'^\s*#import\b', "use only #include in standard C code"),
233 ],
233 ],
234 # warnings
234 # warnings
235 []
235 []
236 ]
236 ]
237
237
238 cfilters = [
238 cfilters = [
239 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
239 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
240 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
240 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
241 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
241 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
242 (r'(\()([^)]+\))', repcallspaces),
242 (r'(\()([^)]+\))', repcallspaces),
243 ]
243 ]
244
244
245 inutilpats = [
245 inutilpats = [
246 [
246 [
247 (r'\bui\.', "don't use ui in util"),
247 (r'\bui\.', "don't use ui in util"),
248 ],
248 ],
249 # warnings
249 # warnings
250 []
250 []
251 ]
251 ]
252
252
253 inrevlogpats = [
253 inrevlogpats = [
254 [
254 [
255 (r'\brepo\.', "don't use repo in revlog"),
255 (r'\brepo\.', "don't use repo in revlog"),
256 ],
256 ],
257 # warnings
257 # warnings
258 []
258 []
259 ]
259 ]
260
260
261 checks = [
261 checks = [
262 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
262 ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
263 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
263 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
264 ('c', r'.*\.c$', cfilters, cpats),
264 ('c', r'.*\.c$', cfilters, cpats),
265 ('unified test', r'.*\.t$', utestfilters, utestpats),
265 ('unified test', r'.*\.t$', utestfilters, utestpats),
266 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
266 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
267 inrevlogpats),
267 inrevlogpats),
268 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
268 ('layering violation ui in util', r'mercurial/util\.py', pyfilters,
269 inutilpats),
269 inutilpats),
270 ]
270 ]
271
271
272 class norepeatlogger(object):
272 class norepeatlogger(object):
273 def __init__(self):
273 def __init__(self):
274 self._lastseen = None
274 self._lastseen = None
275
275
276 def log(self, fname, lineno, line, msg, blame):
276 def log(self, fname, lineno, line, msg, blame):
277 """print error related a to given line of a given file.
277 """print error related a to given line of a given file.
278
278
279 The faulty line will also be printed but only once in the case
279 The faulty line will also be printed but only once in the case
280 of multiple errors.
280 of multiple errors.
281
281
282 :fname: filename
282 :fname: filename
283 :lineno: line number
283 :lineno: line number
284 :line: actual content of the line
284 :line: actual content of the line
285 :msg: error message
285 :msg: error message
286 """
286 """
287 msgid = fname, lineno, line
287 msgid = fname, lineno, line
288 if msgid != self._lastseen:
288 if msgid != self._lastseen:
289 if blame:
289 if blame:
290 print "%s:%d (%s):" % (fname, lineno, blame)
290 print "%s:%d (%s):" % (fname, lineno, blame)
291 else:
291 else:
292 print "%s:%d:" % (fname, lineno)
292 print "%s:%d:" % (fname, lineno)
293 print " > %s" % line
293 print " > %s" % line
294 self._lastseen = msgid
294 self._lastseen = msgid
295 print " " + msg
295 print " " + msg
296
296
297 _defaultlogger = norepeatlogger()
297 _defaultlogger = norepeatlogger()
298
298
299 def getblame(f):
299 def getblame(f):
300 lines = []
300 lines = []
301 for l in os.popen('hg annotate -un %s' % f):
301 for l in os.popen('hg annotate -un %s' % f):
302 start, line = l.split(':', 1)
302 start, line = l.split(':', 1)
303 user, rev = start.split()
303 user, rev = start.split()
304 lines.append((line[1:-1], user, rev))
304 lines.append((line[1:-1], user, rev))
305 return lines
305 return lines
306
306
307 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
307 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
308 blame=False, debug=False, lineno=True):
308 blame=False, debug=False, lineno=True):
309 """checks style and portability of a given file
309 """checks style and portability of a given file
310
310
311 :f: filepath
311 :f: filepath
312 :logfunc: function used to report error
312 :logfunc: function used to report error
313 logfunc(filename, linenumber, linecontent, errormessage)
313 logfunc(filename, linenumber, linecontent, errormessage)
314 :maxerr: number of error to display before arborting.
314 :maxerr: number of error to display before arborting.
315 Set to false (default) to report all errors
315 Set to false (default) to report all errors
316
316
317 return True if no error is found, False otherwise.
317 return True if no error is found, False otherwise.
318 """
318 """
319 blamecache = None
319 blamecache = None
320 result = True
320 result = True
321 for name, match, filters, pats in checks:
321 for name, match, filters, pats in checks:
322 if debug:
322 if debug:
323 print name, f
323 print name, f
324 fc = 0
324 fc = 0
325 if not re.match(match, f):
325 if not re.match(match, f):
326 if debug:
326 if debug:
327 print "Skipping %s for %s it doesn't match %s" % (
327 print "Skipping %s for %s it doesn't match %s" % (
328 name, match, f)
328 name, match, f)
329 continue
329 continue
330 fp = open(f)
330 fp = open(f)
331 pre = post = fp.read()
331 pre = post = fp.read()
332 fp.close()
332 fp.close()
333 if "no-" + "check-code" in pre:
333 if "no-" + "check-code" in pre:
334 if debug:
334 if debug:
335 print "Skipping %s for %s it has no- and check-code" % (
335 print "Skipping %s for %s it has no- and check-code" % (
336 name, f)
336 name, f)
337 break
337 break
338 for p, r in filters:
338 for p, r in filters:
339 post = re.sub(p, r, post)
339 post = re.sub(p, r, post)
340 if warnings:
340 if warnings:
341 pats = pats[0] + pats[1]
341 pats = pats[0] + pats[1]
342 else:
342 else:
343 pats = pats[0]
343 pats = pats[0]
344 # print post # uncomment to show filtered version
344 # print post # uncomment to show filtered version
345
345
346 if debug:
346 if debug:
347 print "Checking %s for %s" % (name, f)
347 print "Checking %s for %s" % (name, f)
348
348
349 prelines = None
349 prelines = None
350 errors = []
350 errors = []
351 for p, msg in pats:
351 for p, msg in pats:
352 # fix-up regexes for multiline searches
352 # fix-up regexes for multiline searches
353 po = p
353 po = p
354 # \s doesn't match \n
354 # \s doesn't match \n
355 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
355 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
356 # [^...] doesn't match newline
356 # [^...] doesn't match newline
357 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
357 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
358
358
359 #print po, '=>', p
359 #print po, '=>', p
360
360
361 pos = 0
361 pos = 0
362 n = 0
362 n = 0
363 for m in re.finditer(p, post, re.MULTILINE):
363 for m in re.finditer(p, post, re.MULTILINE):
364 if prelines is None:
364 if prelines is None:
365 prelines = pre.splitlines()
365 prelines = pre.splitlines()
366 postlines = post.splitlines(True)
366 postlines = post.splitlines(True)
367
367
368 start = m.start()
368 start = m.start()
369 while n < len(postlines):
369 while n < len(postlines):
370 step = len(postlines[n])
370 step = len(postlines[n])
371 if pos + step > start:
371 if pos + step > start:
372 break
372 break
373 pos += step
373 pos += step
374 n += 1
374 n += 1
375 l = prelines[n]
375 l = prelines[n]
376
376
377 if "check-code" + "-ignore" in l:
377 if "check-code" + "-ignore" in l:
378 if debug:
378 if debug:
379 print "Skipping %s for %s:%s (check-code -ignore)" % (
379 print "Skipping %s for %s:%s (check-code -ignore)" % (
380 name, f, n)
380 name, f, n)
381 continue
381 continue
382 bd = ""
382 bd = ""
383 if blame:
383 if blame:
384 bd = 'working directory'
384 bd = 'working directory'
385 if not blamecache:
385 if not blamecache:
386 blamecache = getblame(f)
386 blamecache = getblame(f)
387 if n < len(blamecache):
387 if n < len(blamecache):
388 bl, bu, br = blamecache[n]
388 bl, bu, br = blamecache[n]
389 if bl == l:
389 if bl == l:
390 bd = '%s@%s' % (bu, br)
390 bd = '%s@%s' % (bu, br)
391 errors.append((f, lineno and n + 1, l, msg, bd))
391 errors.append((f, lineno and n + 1, l, msg, bd))
392 result = False
392 result = False
393
393
394 errors.sort()
394 errors.sort()
395 for e in errors:
395 for e in errors:
396 logfunc(*e)
396 logfunc(*e)
397 fc += 1
397 fc += 1
398 if maxerr and fc >= maxerr:
398 if maxerr and fc >= maxerr:
399 print " (too many errors, giving up)"
399 print " (too many errors, giving up)"
400 break
400 break
401
401
402 return result
402 return result
403
403
404 if __name__ == "__main__":
404 if __name__ == "__main__":
405 parser = optparse.OptionParser("%prog [options] [files]")
405 parser = optparse.OptionParser("%prog [options] [files]")
406 parser.add_option("-w", "--warnings", action="store_true",
406 parser.add_option("-w", "--warnings", action="store_true",
407 help="include warning-level checks")
407 help="include warning-level checks")
408 parser.add_option("-p", "--per-file", type="int",
408 parser.add_option("-p", "--per-file", type="int",
409 help="max warnings per file")
409 help="max warnings per file")
410 parser.add_option("-b", "--blame", action="store_true",
410 parser.add_option("-b", "--blame", action="store_true",
411 help="use annotate to generate blame info")
411 help="use annotate to generate blame info")
412 parser.add_option("", "--debug", action="store_true",
412 parser.add_option("", "--debug", action="store_true",
413 help="show debug information")
413 help="show debug information")
414 parser.add_option("", "--nolineno", action="store_false",
414 parser.add_option("", "--nolineno", action="store_false",
415 dest='lineno', help="don't show line numbers")
415 dest='lineno', help="don't show line numbers")
416
416
417 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
417 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
418 lineno=True)
418 lineno=True)
419 (options, args) = parser.parse_args()
419 (options, args) = parser.parse_args()
420
420
421 if len(args) == 0:
421 if len(args) == 0:
422 check = glob.glob("*")
422 check = glob.glob("*")
423 else:
423 else:
424 check = args
424 check = args
425
425
426 ret = 0
426 ret = 0
427 for f in check:
427 for f in check:
428 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
428 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
429 blame=options.blame, debug=options.debug,
429 blame=options.blame, debug=options.debug,
430 lineno=options.lineno):
430 lineno=options.lineno):
431 ret = 1
431 ret = 1
432 sys.exit(ret)
432 sys.exit(ret)
@@ -1,5795 +1,5816 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil
19 import random, setdiscovery, treediscovery, dagutil, pvec
20 import phases
20 import phases
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ] + templateopts
101 ] + templateopts
102
102
103 diffopts = [
103 diffopts = [
104 ('a', 'text', None, _('treat all files as text')),
104 ('a', 'text', None, _('treat all files as text')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('', 'nodates', None, _('omit dates from diff headers'))
106 ('', 'nodates', None, _('omit dates from diff headers'))
107 ]
107 ]
108
108
109 diffwsopts = [
109 diffwsopts = [
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ]
116 ]
117
117
118 diffopts2 = [
118 diffopts2 = [
119 ('p', 'show-function', None, _('show which function each change is in')),
119 ('p', 'show-function', None, _('show which function each change is in')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ] + diffwsopts + [
121 ] + diffwsopts + [
122 ('U', 'unified', '',
122 ('U', 'unified', '',
123 _('number of lines of context to show'), _('NUM')),
123 _('number of lines of context to show'), _('NUM')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ]
125 ]
126
126
127 mergetoolopts = [
127 mergetoolopts = [
128 ('t', 'tool', '', _('specify merge tool')),
128 ('t', 'tool', '', _('specify merge tool')),
129 ]
129 ]
130
130
131 similarityopts = [
131 similarityopts = [
132 ('s', 'similarity', '',
132 ('s', 'similarity', '',
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 ]
134 ]
135
135
136 subrepoopts = [
136 subrepoopts = [
137 ('S', 'subrepos', None,
137 ('S', 'subrepos', None,
138 _('recurse into subrepositories'))
138 _('recurse into subrepositories'))
139 ]
139 ]
140
140
141 # Commands start here, listed alphabetically
141 # Commands start here, listed alphabetically
142
142
143 @command('^add',
143 @command('^add',
144 walkopts + subrepoopts + dryrunopts,
144 walkopts + subrepoopts + dryrunopts,
145 _('[OPTION]... [FILE]...'))
145 _('[OPTION]... [FILE]...'))
146 def add(ui, repo, *pats, **opts):
146 def add(ui, repo, *pats, **opts):
147 """add the specified files on the next commit
147 """add the specified files on the next commit
148
148
149 Schedule files to be version controlled and added to the
149 Schedule files to be version controlled and added to the
150 repository.
150 repository.
151
151
152 The files will be added to the repository at the next commit. To
152 The files will be added to the repository at the next commit. To
153 undo an add before that, see :hg:`forget`.
153 undo an add before that, see :hg:`forget`.
154
154
155 If no names are given, add all files to the repository.
155 If no names are given, add all files to the repository.
156
156
157 .. container:: verbose
157 .. container:: verbose
158
158
159 An example showing how new (unknown) files are added
159 An example showing how new (unknown) files are added
160 automatically by :hg:`add`::
160 automatically by :hg:`add`::
161
161
162 $ ls
162 $ ls
163 foo.c
163 foo.c
164 $ hg status
164 $ hg status
165 ? foo.c
165 ? foo.c
166 $ hg add
166 $ hg add
167 adding foo.c
167 adding foo.c
168 $ hg status
168 $ hg status
169 A foo.c
169 A foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, opts)
174 m = scmutil.match(repo[None], pats, opts)
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 opts.get('subrepos'), prefix="", explicitonly=False)
176 opts.get('subrepos'), prefix="", explicitonly=False)
177 return rejected and 1 or 0
177 return rejected and 1 or 0
178
178
179 @command('addremove',
179 @command('addremove',
180 similarityopts + walkopts + dryrunopts,
180 similarityopts + walkopts + dryrunopts,
181 _('[OPTION]... [FILE]...'))
181 _('[OPTION]... [FILE]...'))
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 New files are ignored if they match any of the patterns in
188 New files are ignored if they match any of the patterns in
189 ``.hgignore``. As with add, these changes take effect at the next
189 ``.hgignore``. As with add, these changes take effect at the next
190 commit.
190 commit.
191
191
192 Use the -s/--similarity option to detect renamed files. With a
192 Use the -s/--similarity option to detect renamed files. With a
193 parameter greater than 0, this compares every removed file with
193 parameter greater than 0, this compares every removed file with
194 every added file and records those similar enough as renames. This
194 every added file and records those similar enough as renames. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. Detecting renamed files this way
196 be identical) as its parameter. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed.
198 used to check which files were identified as moved or renamed.
199
199
200 Returns 0 if all files are successfully added.
200 Returns 0 if all files are successfully added.
201 """
201 """
202 try:
202 try:
203 sim = float(opts.get('similarity') or 100)
203 sim = float(opts.get('similarity') or 100)
204 except ValueError:
204 except ValueError:
205 raise util.Abort(_('similarity must be a number'))
205 raise util.Abort(_('similarity must be a number'))
206 if sim < 0 or sim > 100:
206 if sim < 0 or sim > 100:
207 raise util.Abort(_('similarity must be between 0 and 100'))
207 raise util.Abort(_('similarity must be between 0 and 100'))
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209
209
210 @command('^annotate|blame',
210 @command('^annotate|blame',
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 ('', 'follow', None,
212 ('', 'follow', None,
213 _('follow copies/renames and list the filename (DEPRECATED)')),
213 _('follow copies/renames and list the filename (DEPRECATED)')),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
214 ('', 'no-follow', None, _("don't follow copies and renames")),
215 ('a', 'text', None, _('treat all files as text')),
215 ('a', 'text', None, _('treat all files as text')),
216 ('u', 'user', None, _('list the author (long with -v)')),
216 ('u', 'user', None, _('list the author (long with -v)')),
217 ('f', 'file', None, _('list the filename')),
217 ('f', 'file', None, _('list the filename')),
218 ('d', 'date', None, _('list the date (short with -q)')),
218 ('d', 'date', None, _('list the date (short with -q)')),
219 ('n', 'number', None, _('list the revision number (default)')),
219 ('n', 'number', None, _('list the revision number (default)')),
220 ('c', 'changeset', None, _('list the changeset')),
220 ('c', 'changeset', None, _('list the changeset')),
221 ('l', 'line-number', None, _('show line number at the first appearance'))
221 ('l', 'line-number', None, _('show line number at the first appearance'))
222 ] + diffwsopts + walkopts,
222 ] + diffwsopts + walkopts,
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 def annotate(ui, repo, *pats, **opts):
224 def annotate(ui, repo, *pats, **opts):
225 """show changeset information by line for each file
225 """show changeset information by line for each file
226
226
227 List changes in files, showing the revision id responsible for
227 List changes in files, showing the revision id responsible for
228 each line
228 each line
229
229
230 This command is useful for discovering when a change was made and
230 This command is useful for discovering when a change was made and
231 by whom.
231 by whom.
232
232
233 Without the -a/--text option, annotate will avoid processing files
233 Without the -a/--text option, annotate will avoid processing files
234 it detects as binary. With -a, annotate will annotate the file
234 it detects as binary. With -a, annotate will annotate the file
235 anyway, although the results will probably be neither useful
235 anyway, although the results will probably be neither useful
236 nor desirable.
236 nor desirable.
237
237
238 Returns 0 on success.
238 Returns 0 on success.
239 """
239 """
240 if opts.get('follow'):
240 if opts.get('follow'):
241 # --follow is deprecated and now just an alias for -f/--file
241 # --follow is deprecated and now just an alias for -f/--file
242 # to mimic the behavior of Mercurial before version 1.5
242 # to mimic the behavior of Mercurial before version 1.5
243 opts['file'] = True
243 opts['file'] = True
244
244
245 datefunc = ui.quiet and util.shortdate or util.datestr
245 datefunc = ui.quiet and util.shortdate or util.datestr
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247
247
248 if not pats:
248 if not pats:
249 raise util.Abort(_('at least one filename or pattern is required'))
249 raise util.Abort(_('at least one filename or pattern is required'))
250
250
251 hexfn = ui.debugflag and hex or short
251 hexfn = ui.debugflag and hex or short
252
252
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
253 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
254 ('number', ' ', lambda x: str(x[0].rev())),
254 ('number', ' ', lambda x: str(x[0].rev())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
255 ('changeset', ' ', lambda x: hexfn(x[0].node())),
256 ('date', ' ', getdate),
256 ('date', ' ', getdate),
257 ('file', ' ', lambda x: x[0].path()),
257 ('file', ' ', lambda x: x[0].path()),
258 ('line_number', ':', lambda x: str(x[1])),
258 ('line_number', ':', lambda x: str(x[1])),
259 ]
259 ]
260
260
261 if (not opts.get('user') and not opts.get('changeset')
261 if (not opts.get('user') and not opts.get('changeset')
262 and not opts.get('date') and not opts.get('file')):
262 and not opts.get('date') and not opts.get('file')):
263 opts['number'] = True
263 opts['number'] = True
264
264
265 linenumber = opts.get('line_number') is not None
265 linenumber = opts.get('line_number') is not None
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
266 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
267 raise util.Abort(_('at least one of -n/-c is required for -l'))
268
268
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
269 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
270 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
271
271
272 def bad(x, y):
272 def bad(x, y):
273 raise util.Abort("%s: %s" % (x, y))
273 raise util.Abort("%s: %s" % (x, y))
274
274
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
275 ctx = scmutil.revsingle(repo, opts.get('rev'))
276 m = scmutil.match(ctx, pats, opts)
276 m = scmutil.match(ctx, pats, opts)
277 m.bad = bad
277 m.bad = bad
278 follow = not opts.get('no_follow')
278 follow = not opts.get('no_follow')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
279 diffopts = patch.diffopts(ui, opts, section='annotate')
280 for abs in ctx.walk(m):
280 for abs in ctx.walk(m):
281 fctx = ctx[abs]
281 fctx = ctx[abs]
282 if not opts.get('text') and util.binary(fctx.data()):
282 if not opts.get('text') and util.binary(fctx.data()):
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
283 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
284 continue
284 continue
285
285
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
286 lines = fctx.annotate(follow=follow, linenumber=linenumber,
287 diffopts=diffopts)
287 diffopts=diffopts)
288 pieces = []
288 pieces = []
289
289
290 for f, sep in funcmap:
290 for f, sep in funcmap:
291 l = [f(n) for n, dummy in lines]
291 l = [f(n) for n, dummy in lines]
292 if l:
292 if l:
293 sized = [(x, encoding.colwidth(x)) for x in l]
293 sized = [(x, encoding.colwidth(x)) for x in l]
294 ml = max([w for x, w in sized])
294 ml = max([w for x, w in sized])
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
295 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
296 for x, w in sized])
296 for x, w in sized])
297
297
298 if pieces:
298 if pieces:
299 for p, l in zip(zip(*pieces), lines):
299 for p, l in zip(zip(*pieces), lines):
300 ui.write("%s: %s" % ("".join(p), l[1]))
300 ui.write("%s: %s" % ("".join(p), l[1]))
301
301
302 if lines and not lines[-1][1].endswith('\n'):
302 if lines and not lines[-1][1].endswith('\n'):
303 ui.write('\n')
303 ui.write('\n')
304
304
305 @command('archive',
305 @command('archive',
306 [('', 'no-decode', None, _('do not pass files through decoders')),
306 [('', 'no-decode', None, _('do not pass files through decoders')),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
307 ('p', 'prefix', '', _('directory prefix for files in archive'),
308 _('PREFIX')),
308 _('PREFIX')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
309 ('r', 'rev', '', _('revision to distribute'), _('REV')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
310 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
311 ] + subrepoopts + walkopts,
311 ] + subrepoopts + walkopts,
312 _('[OPTION]... DEST'))
312 _('[OPTION]... DEST'))
313 def archive(ui, repo, dest, **opts):
313 def archive(ui, repo, dest, **opts):
314 '''create an unversioned archive of a repository revision
314 '''create an unversioned archive of a repository revision
315
315
316 By default, the revision used is the parent of the working
316 By default, the revision used is the parent of the working
317 directory; use -r/--rev to specify a different revision.
317 directory; use -r/--rev to specify a different revision.
318
318
319 The archive type is automatically detected based on file
319 The archive type is automatically detected based on file
320 extension (or override using -t/--type).
320 extension (or override using -t/--type).
321
321
322 .. container:: verbose
322 .. container:: verbose
323
323
324 Examples:
324 Examples:
325
325
326 - create a zip file containing the 1.0 release::
326 - create a zip file containing the 1.0 release::
327
327
328 hg archive -r 1.0 project-1.0.zip
328 hg archive -r 1.0 project-1.0.zip
329
329
330 - create a tarball excluding .hg files::
330 - create a tarball excluding .hg files::
331
331
332 hg archive project.tar.gz -X ".hg*"
332 hg archive project.tar.gz -X ".hg*"
333
333
334 Valid types are:
334 Valid types are:
335
335
336 :``files``: a directory full of files (default)
336 :``files``: a directory full of files (default)
337 :``tar``: tar archive, uncompressed
337 :``tar``: tar archive, uncompressed
338 :``tbz2``: tar archive, compressed using bzip2
338 :``tbz2``: tar archive, compressed using bzip2
339 :``tgz``: tar archive, compressed using gzip
339 :``tgz``: tar archive, compressed using gzip
340 :``uzip``: zip archive, uncompressed
340 :``uzip``: zip archive, uncompressed
341 :``zip``: zip archive, compressed using deflate
341 :``zip``: zip archive, compressed using deflate
342
342
343 The exact name of the destination archive or directory is given
343 The exact name of the destination archive or directory is given
344 using a format string; see :hg:`help export` for details.
344 using a format string; see :hg:`help export` for details.
345
345
346 Each member added to an archive file has a directory prefix
346 Each member added to an archive file has a directory prefix
347 prepended. Use -p/--prefix to specify a format string for the
347 prepended. Use -p/--prefix to specify a format string for the
348 prefix. The default is the basename of the archive, with suffixes
348 prefix. The default is the basename of the archive, with suffixes
349 removed.
349 removed.
350
350
351 Returns 0 on success.
351 Returns 0 on success.
352 '''
352 '''
353
353
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
354 ctx = scmutil.revsingle(repo, opts.get('rev'))
355 if not ctx:
355 if not ctx:
356 raise util.Abort(_('no working directory: please specify a revision'))
356 raise util.Abort(_('no working directory: please specify a revision'))
357 node = ctx.node()
357 node = ctx.node()
358 dest = cmdutil.makefilename(repo, dest, node)
358 dest = cmdutil.makefilename(repo, dest, node)
359 if os.path.realpath(dest) == repo.root:
359 if os.path.realpath(dest) == repo.root:
360 raise util.Abort(_('repository root cannot be destination'))
360 raise util.Abort(_('repository root cannot be destination'))
361
361
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
362 kind = opts.get('type') or archival.guesskind(dest) or 'files'
363 prefix = opts.get('prefix')
363 prefix = opts.get('prefix')
364
364
365 if dest == '-':
365 if dest == '-':
366 if kind == 'files':
366 if kind == 'files':
367 raise util.Abort(_('cannot archive plain files to stdout'))
367 raise util.Abort(_('cannot archive plain files to stdout'))
368 dest = cmdutil.makefileobj(repo, dest)
368 dest = cmdutil.makefileobj(repo, dest)
369 if not prefix:
369 if not prefix:
370 prefix = os.path.basename(repo.root) + '-%h'
370 prefix = os.path.basename(repo.root) + '-%h'
371
371
372 prefix = cmdutil.makefilename(repo, prefix, node)
372 prefix = cmdutil.makefilename(repo, prefix, node)
373 matchfn = scmutil.match(ctx, [], opts)
373 matchfn = scmutil.match(ctx, [], opts)
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
374 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
375 matchfn, prefix, subrepos=opts.get('subrepos'))
375 matchfn, prefix, subrepos=opts.get('subrepos'))
376
376
377 @command('backout',
377 @command('backout',
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
378 [('', 'merge', None, _('merge with old dirstate parent after backout')),
379 ('', 'parent', '',
379 ('', 'parent', '',
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
380 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
381 ('r', 'rev', '', _('revision to backout'), _('REV')),
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
382 ] + mergetoolopts + walkopts + commitopts + commitopts2,
383 _('[OPTION]... [-r] REV'))
383 _('[OPTION]... [-r] REV'))
384 def backout(ui, repo, node=None, rev=None, **opts):
384 def backout(ui, repo, node=None, rev=None, **opts):
385 '''reverse effect of earlier changeset
385 '''reverse effect of earlier changeset
386
386
387 Prepare a new changeset with the effect of REV undone in the
387 Prepare a new changeset with the effect of REV undone in the
388 current working directory.
388 current working directory.
389
389
390 If REV is the parent of the working directory, then this new changeset
390 If REV is the parent of the working directory, then this new changeset
391 is committed automatically. Otherwise, hg needs to merge the
391 is committed automatically. Otherwise, hg needs to merge the
392 changes and the merged result is left uncommitted.
392 changes and the merged result is left uncommitted.
393
393
394 .. note::
394 .. note::
395 backout cannot be used to fix either an unwanted or
395 backout cannot be used to fix either an unwanted or
396 incorrect merge.
396 incorrect merge.
397
397
398 .. container:: verbose
398 .. container:: verbose
399
399
400 By default, the pending changeset will have one parent,
400 By default, the pending changeset will have one parent,
401 maintaining a linear history. With --merge, the pending
401 maintaining a linear history. With --merge, the pending
402 changeset will instead have two parents: the old parent of the
402 changeset will instead have two parents: the old parent of the
403 working directory and a new child of REV that simply undoes REV.
403 working directory and a new child of REV that simply undoes REV.
404
404
405 Before version 1.7, the behavior without --merge was equivalent
405 Before version 1.7, the behavior without --merge was equivalent
406 to specifying --merge followed by :hg:`update --clean .` to
406 to specifying --merge followed by :hg:`update --clean .` to
407 cancel the merge and leave the child of REV as a head to be
407 cancel the merge and leave the child of REV as a head to be
408 merged separately.
408 merged separately.
409
409
410 See :hg:`help dates` for a list of formats valid for -d/--date.
410 See :hg:`help dates` for a list of formats valid for -d/--date.
411
411
412 Returns 0 on success.
412 Returns 0 on success.
413 '''
413 '''
414 if rev and node:
414 if rev and node:
415 raise util.Abort(_("please specify just one revision"))
415 raise util.Abort(_("please specify just one revision"))
416
416
417 if not rev:
417 if not rev:
418 rev = node
418 rev = node
419
419
420 if not rev:
420 if not rev:
421 raise util.Abort(_("please specify a revision to backout"))
421 raise util.Abort(_("please specify a revision to backout"))
422
422
423 date = opts.get('date')
423 date = opts.get('date')
424 if date:
424 if date:
425 opts['date'] = util.parsedate(date)
425 opts['date'] = util.parsedate(date)
426
426
427 cmdutil.bailifchanged(repo)
427 cmdutil.bailifchanged(repo)
428 node = scmutil.revsingle(repo, rev).node()
428 node = scmutil.revsingle(repo, rev).node()
429
429
430 op1, op2 = repo.dirstate.parents()
430 op1, op2 = repo.dirstate.parents()
431 a = repo.changelog.ancestor(op1, node)
431 a = repo.changelog.ancestor(op1, node)
432 if a != node:
432 if a != node:
433 raise util.Abort(_('cannot backout change on a different branch'))
433 raise util.Abort(_('cannot backout change on a different branch'))
434
434
435 p1, p2 = repo.changelog.parents(node)
435 p1, p2 = repo.changelog.parents(node)
436 if p1 == nullid:
436 if p1 == nullid:
437 raise util.Abort(_('cannot backout a change with no parents'))
437 raise util.Abort(_('cannot backout a change with no parents'))
438 if p2 != nullid:
438 if p2 != nullid:
439 if not opts.get('parent'):
439 if not opts.get('parent'):
440 raise util.Abort(_('cannot backout a merge changeset'))
440 raise util.Abort(_('cannot backout a merge changeset'))
441 p = repo.lookup(opts['parent'])
441 p = repo.lookup(opts['parent'])
442 if p not in (p1, p2):
442 if p not in (p1, p2):
443 raise util.Abort(_('%s is not a parent of %s') %
443 raise util.Abort(_('%s is not a parent of %s') %
444 (short(p), short(node)))
444 (short(p), short(node)))
445 parent = p
445 parent = p
446 else:
446 else:
447 if opts.get('parent'):
447 if opts.get('parent'):
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
448 raise util.Abort(_('cannot use --parent on non-merge changeset'))
449 parent = p1
449 parent = p1
450
450
451 # the backout should appear on the same branch
451 # the backout should appear on the same branch
452 branch = repo.dirstate.branch()
452 branch = repo.dirstate.branch()
453 hg.clean(repo, node, show_stats=False)
453 hg.clean(repo, node, show_stats=False)
454 repo.dirstate.setbranch(branch)
454 repo.dirstate.setbranch(branch)
455 revert_opts = opts.copy()
455 revert_opts = opts.copy()
456 revert_opts['date'] = None
456 revert_opts['date'] = None
457 revert_opts['all'] = True
457 revert_opts['all'] = True
458 revert_opts['rev'] = hex(parent)
458 revert_opts['rev'] = hex(parent)
459 revert_opts['no_backup'] = None
459 revert_opts['no_backup'] = None
460 revert(ui, repo, **revert_opts)
460 revert(ui, repo, **revert_opts)
461 if not opts.get('merge') and op1 != node:
461 if not opts.get('merge') and op1 != node:
462 try:
462 try:
463 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
463 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
464 return hg.update(repo, op1)
464 return hg.update(repo, op1)
465 finally:
465 finally:
466 ui.setconfig('ui', 'forcemerge', '')
466 ui.setconfig('ui', 'forcemerge', '')
467
467
468 commit_opts = opts.copy()
468 commit_opts = opts.copy()
469 commit_opts['addremove'] = False
469 commit_opts['addremove'] = False
470 if not commit_opts['message'] and not commit_opts['logfile']:
470 if not commit_opts['message'] and not commit_opts['logfile']:
471 # we don't translate commit messages
471 # we don't translate commit messages
472 commit_opts['message'] = "Backed out changeset %s" % short(node)
472 commit_opts['message'] = "Backed out changeset %s" % short(node)
473 commit_opts['force_editor'] = True
473 commit_opts['force_editor'] = True
474 commit(ui, repo, **commit_opts)
474 commit(ui, repo, **commit_opts)
475 def nice(node):
475 def nice(node):
476 return '%d:%s' % (repo.changelog.rev(node), short(node))
476 return '%d:%s' % (repo.changelog.rev(node), short(node))
477 ui.status(_('changeset %s backs out changeset %s\n') %
477 ui.status(_('changeset %s backs out changeset %s\n') %
478 (nice(repo.changelog.tip()), nice(node)))
478 (nice(repo.changelog.tip()), nice(node)))
479 if opts.get('merge') and op1 != node:
479 if opts.get('merge') and op1 != node:
480 hg.clean(repo, op1, show_stats=False)
480 hg.clean(repo, op1, show_stats=False)
481 ui.status(_('merging with changeset %s\n')
481 ui.status(_('merging with changeset %s\n')
482 % nice(repo.changelog.tip()))
482 % nice(repo.changelog.tip()))
483 try:
483 try:
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
485 return hg.merge(repo, hex(repo.changelog.tip()))
485 return hg.merge(repo, hex(repo.changelog.tip()))
486 finally:
486 finally:
487 ui.setconfig('ui', 'forcemerge', '')
487 ui.setconfig('ui', 'forcemerge', '')
488 return 0
488 return 0
489
489
490 @command('bisect',
490 @command('bisect',
491 [('r', 'reset', False, _('reset bisect state')),
491 [('r', 'reset', False, _('reset bisect state')),
492 ('g', 'good', False, _('mark changeset good')),
492 ('g', 'good', False, _('mark changeset good')),
493 ('b', 'bad', False, _('mark changeset bad')),
493 ('b', 'bad', False, _('mark changeset bad')),
494 ('s', 'skip', False, _('skip testing changeset')),
494 ('s', 'skip', False, _('skip testing changeset')),
495 ('e', 'extend', False, _('extend the bisect range')),
495 ('e', 'extend', False, _('extend the bisect range')),
496 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
496 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
497 ('U', 'noupdate', False, _('do not update to target'))],
497 ('U', 'noupdate', False, _('do not update to target'))],
498 _("[-gbsr] [-U] [-c CMD] [REV]"))
498 _("[-gbsr] [-U] [-c CMD] [REV]"))
499 def bisect(ui, repo, rev=None, extra=None, command=None,
499 def bisect(ui, repo, rev=None, extra=None, command=None,
500 reset=None, good=None, bad=None, skip=None, extend=None,
500 reset=None, good=None, bad=None, skip=None, extend=None,
501 noupdate=None):
501 noupdate=None):
502 """subdivision search of changesets
502 """subdivision search of changesets
503
503
504 This command helps to find changesets which introduce problems. To
504 This command helps to find changesets which introduce problems. To
505 use, mark the earliest changeset you know exhibits the problem as
505 use, mark the earliest changeset you know exhibits the problem as
506 bad, then mark the latest changeset which is free from the problem
506 bad, then mark the latest changeset which is free from the problem
507 as good. Bisect will update your working directory to a revision
507 as good. Bisect will update your working directory to a revision
508 for testing (unless the -U/--noupdate option is specified). Once
508 for testing (unless the -U/--noupdate option is specified). Once
509 you have performed tests, mark the working directory as good or
509 you have performed tests, mark the working directory as good or
510 bad, and bisect will either update to another candidate changeset
510 bad, and bisect will either update to another candidate changeset
511 or announce that it has found the bad revision.
511 or announce that it has found the bad revision.
512
512
513 As a shortcut, you can also use the revision argument to mark a
513 As a shortcut, you can also use the revision argument to mark a
514 revision as good or bad without checking it out first.
514 revision as good or bad without checking it out first.
515
515
516 If you supply a command, it will be used for automatic bisection.
516 If you supply a command, it will be used for automatic bisection.
517 Its exit status will be used to mark revisions as good or bad:
517 Its exit status will be used to mark revisions as good or bad:
518 status 0 means good, 125 means to skip the revision, 127
518 status 0 means good, 125 means to skip the revision, 127
519 (command not found) will abort the bisection, and any other
519 (command not found) will abort the bisection, and any other
520 non-zero exit status means the revision is bad.
520 non-zero exit status means the revision is bad.
521
521
522 .. container:: verbose
522 .. container:: verbose
523
523
524 Some examples:
524 Some examples:
525
525
526 - start a bisection with known bad revision 12, and good revision 34::
526 - start a bisection with known bad revision 12, and good revision 34::
527
527
528 hg bisect --bad 34
528 hg bisect --bad 34
529 hg bisect --good 12
529 hg bisect --good 12
530
530
531 - advance the current bisection by marking current revision as good or
531 - advance the current bisection by marking current revision as good or
532 bad::
532 bad::
533
533
534 hg bisect --good
534 hg bisect --good
535 hg bisect --bad
535 hg bisect --bad
536
536
537 - mark the current revision, or a known revision, to be skipped (eg. if
537 - mark the current revision, or a known revision, to be skipped (eg. if
538 that revision is not usable because of another issue)::
538 that revision is not usable because of another issue)::
539
539
540 hg bisect --skip
540 hg bisect --skip
541 hg bisect --skip 23
541 hg bisect --skip 23
542
542
543 - forget the current bisection::
543 - forget the current bisection::
544
544
545 hg bisect --reset
545 hg bisect --reset
546
546
547 - use 'make && make tests' to automatically find the first broken
547 - use 'make && make tests' to automatically find the first broken
548 revision::
548 revision::
549
549
550 hg bisect --reset
550 hg bisect --reset
551 hg bisect --bad 34
551 hg bisect --bad 34
552 hg bisect --good 12
552 hg bisect --good 12
553 hg bisect --command 'make && make tests'
553 hg bisect --command 'make && make tests'
554
554
555 - see all changesets whose states are already known in the current
555 - see all changesets whose states are already known in the current
556 bisection::
556 bisection::
557
557
558 hg log -r "bisect(pruned)"
558 hg log -r "bisect(pruned)"
559
559
560 - see all changesets that took part in the current bisection::
560 - see all changesets that took part in the current bisection::
561
561
562 hg log -r "bisect(range)"
562 hg log -r "bisect(range)"
563
563
564 - with the graphlog extension, you can even get a nice graph::
564 - with the graphlog extension, you can even get a nice graph::
565
565
566 hg log --graph -r "bisect(range)"
566 hg log --graph -r "bisect(range)"
567
567
568 See :hg:`help revsets` for more about the `bisect()` keyword.
568 See :hg:`help revsets` for more about the `bisect()` keyword.
569
569
570 Returns 0 on success.
570 Returns 0 on success.
571 """
571 """
572 def extendbisectrange(nodes, good):
572 def extendbisectrange(nodes, good):
573 # bisect is incomplete when it ends on a merge node and
573 # bisect is incomplete when it ends on a merge node and
574 # one of the parent was not checked.
574 # one of the parent was not checked.
575 parents = repo[nodes[0]].parents()
575 parents = repo[nodes[0]].parents()
576 if len(parents) > 1:
576 if len(parents) > 1:
577 side = good and state['bad'] or state['good']
577 side = good and state['bad'] or state['good']
578 num = len(set(i.node() for i in parents) & set(side))
578 num = len(set(i.node() for i in parents) & set(side))
579 if num == 1:
579 if num == 1:
580 return parents[0].ancestor(parents[1])
580 return parents[0].ancestor(parents[1])
581 return None
581 return None
582
582
583 def print_result(nodes, good):
583 def print_result(nodes, good):
584 displayer = cmdutil.show_changeset(ui, repo, {})
584 displayer = cmdutil.show_changeset(ui, repo, {})
585 if len(nodes) == 1:
585 if len(nodes) == 1:
586 # narrowed it down to a single revision
586 # narrowed it down to a single revision
587 if good:
587 if good:
588 ui.write(_("The first good revision is:\n"))
588 ui.write(_("The first good revision is:\n"))
589 else:
589 else:
590 ui.write(_("The first bad revision is:\n"))
590 ui.write(_("The first bad revision is:\n"))
591 displayer.show(repo[nodes[0]])
591 displayer.show(repo[nodes[0]])
592 extendnode = extendbisectrange(nodes, good)
592 extendnode = extendbisectrange(nodes, good)
593 if extendnode is not None:
593 if extendnode is not None:
594 ui.write(_('Not all ancestors of this changeset have been'
594 ui.write(_('Not all ancestors of this changeset have been'
595 ' checked.\nUse bisect --extend to continue the '
595 ' checked.\nUse bisect --extend to continue the '
596 'bisection from\nthe common ancestor, %s.\n')
596 'bisection from\nthe common ancestor, %s.\n')
597 % extendnode)
597 % extendnode)
598 else:
598 else:
599 # multiple possible revisions
599 # multiple possible revisions
600 if good:
600 if good:
601 ui.write(_("Due to skipped revisions, the first "
601 ui.write(_("Due to skipped revisions, the first "
602 "good revision could be any of:\n"))
602 "good revision could be any of:\n"))
603 else:
603 else:
604 ui.write(_("Due to skipped revisions, the first "
604 ui.write(_("Due to skipped revisions, the first "
605 "bad revision could be any of:\n"))
605 "bad revision could be any of:\n"))
606 for n in nodes:
606 for n in nodes:
607 displayer.show(repo[n])
607 displayer.show(repo[n])
608 displayer.close()
608 displayer.close()
609
609
610 def check_state(state, interactive=True):
610 def check_state(state, interactive=True):
611 if not state['good'] or not state['bad']:
611 if not state['good'] or not state['bad']:
612 if (good or bad or skip or reset) and interactive:
612 if (good or bad or skip or reset) and interactive:
613 return
613 return
614 if not state['good']:
614 if not state['good']:
615 raise util.Abort(_('cannot bisect (no known good revisions)'))
615 raise util.Abort(_('cannot bisect (no known good revisions)'))
616 else:
616 else:
617 raise util.Abort(_('cannot bisect (no known bad revisions)'))
617 raise util.Abort(_('cannot bisect (no known bad revisions)'))
618 return True
618 return True
619
619
620 # backward compatibility
620 # backward compatibility
621 if rev in "good bad reset init".split():
621 if rev in "good bad reset init".split():
622 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
622 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
623 cmd, rev, extra = rev, extra, None
623 cmd, rev, extra = rev, extra, None
624 if cmd == "good":
624 if cmd == "good":
625 good = True
625 good = True
626 elif cmd == "bad":
626 elif cmd == "bad":
627 bad = True
627 bad = True
628 else:
628 else:
629 reset = True
629 reset = True
630 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
630 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
631 raise util.Abort(_('incompatible arguments'))
631 raise util.Abort(_('incompatible arguments'))
632
632
633 if reset:
633 if reset:
634 p = repo.join("bisect.state")
634 p = repo.join("bisect.state")
635 if os.path.exists(p):
635 if os.path.exists(p):
636 os.unlink(p)
636 os.unlink(p)
637 return
637 return
638
638
639 state = hbisect.load_state(repo)
639 state = hbisect.load_state(repo)
640
640
641 if command:
641 if command:
642 changesets = 1
642 changesets = 1
643 try:
643 try:
644 while changesets:
644 while changesets:
645 # update state
645 # update state
646 status = util.system(command, out=ui.fout)
646 status = util.system(command, out=ui.fout)
647 if status == 125:
647 if status == 125:
648 transition = "skip"
648 transition = "skip"
649 elif status == 0:
649 elif status == 0:
650 transition = "good"
650 transition = "good"
651 # status < 0 means process was killed
651 # status < 0 means process was killed
652 elif status == 127:
652 elif status == 127:
653 raise util.Abort(_("failed to execute %s") % command)
653 raise util.Abort(_("failed to execute %s") % command)
654 elif status < 0:
654 elif status < 0:
655 raise util.Abort(_("%s killed") % command)
655 raise util.Abort(_("%s killed") % command)
656 else:
656 else:
657 transition = "bad"
657 transition = "bad"
658 ctx = scmutil.revsingle(repo, rev)
658 ctx = scmutil.revsingle(repo, rev)
659 rev = None # clear for future iterations
659 rev = None # clear for future iterations
660 state[transition].append(ctx.node())
660 state[transition].append(ctx.node())
661 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
661 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
662 check_state(state, interactive=False)
662 check_state(state, interactive=False)
663 # bisect
663 # bisect
664 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
664 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
665 # update to next check
665 # update to next check
666 cmdutil.bailifchanged(repo)
666 cmdutil.bailifchanged(repo)
667 hg.clean(repo, nodes[0], show_stats=False)
667 hg.clean(repo, nodes[0], show_stats=False)
668 finally:
668 finally:
669 hbisect.save_state(repo, state)
669 hbisect.save_state(repo, state)
670 print_result(nodes, good)
670 print_result(nodes, good)
671 return
671 return
672
672
673 # update state
673 # update state
674
674
675 if rev:
675 if rev:
676 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
676 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
677 else:
677 else:
678 nodes = [repo.lookup('.')]
678 nodes = [repo.lookup('.')]
679
679
680 if good or bad or skip:
680 if good or bad or skip:
681 if good:
681 if good:
682 state['good'] += nodes
682 state['good'] += nodes
683 elif bad:
683 elif bad:
684 state['bad'] += nodes
684 state['bad'] += nodes
685 elif skip:
685 elif skip:
686 state['skip'] += nodes
686 state['skip'] += nodes
687 hbisect.save_state(repo, state)
687 hbisect.save_state(repo, state)
688
688
689 if not check_state(state):
689 if not check_state(state):
690 return
690 return
691
691
692 # actually bisect
692 # actually bisect
693 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
693 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
694 if extend:
694 if extend:
695 if not changesets:
695 if not changesets:
696 extendnode = extendbisectrange(nodes, good)
696 extendnode = extendbisectrange(nodes, good)
697 if extendnode is not None:
697 if extendnode is not None:
698 ui.write(_("Extending search to changeset %d:%s\n"
698 ui.write(_("Extending search to changeset %d:%s\n"
699 % (extendnode.rev(), extendnode)))
699 % (extendnode.rev(), extendnode)))
700 if noupdate:
700 if noupdate:
701 return
701 return
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 return hg.clean(repo, extendnode.node())
703 return hg.clean(repo, extendnode.node())
704 raise util.Abort(_("nothing to extend"))
704 raise util.Abort(_("nothing to extend"))
705
705
706 if changesets == 0:
706 if changesets == 0:
707 print_result(nodes, good)
707 print_result(nodes, good)
708 else:
708 else:
709 assert len(nodes) == 1 # only a single node can be tested next
709 assert len(nodes) == 1 # only a single node can be tested next
710 node = nodes[0]
710 node = nodes[0]
711 # compute the approximate number of remaining tests
711 # compute the approximate number of remaining tests
712 tests, size = 0, 2
712 tests, size = 0, 2
713 while size <= changesets:
713 while size <= changesets:
714 tests, size = tests + 1, size * 2
714 tests, size = tests + 1, size * 2
715 rev = repo.changelog.rev(node)
715 rev = repo.changelog.rev(node)
716 ui.write(_("Testing changeset %d:%s "
716 ui.write(_("Testing changeset %d:%s "
717 "(%d changesets remaining, ~%d tests)\n")
717 "(%d changesets remaining, ~%d tests)\n")
718 % (rev, short(node), changesets, tests))
718 % (rev, short(node), changesets, tests))
719 if not noupdate:
719 if not noupdate:
720 cmdutil.bailifchanged(repo)
720 cmdutil.bailifchanged(repo)
721 return hg.clean(repo, node)
721 return hg.clean(repo, node)
722
722
723 @command('bookmarks',
723 @command('bookmarks',
724 [('f', 'force', False, _('force')),
724 [('f', 'force', False, _('force')),
725 ('r', 'rev', '', _('revision'), _('REV')),
725 ('r', 'rev', '', _('revision'), _('REV')),
726 ('d', 'delete', False, _('delete a given bookmark')),
726 ('d', 'delete', False, _('delete a given bookmark')),
727 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
727 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
728 ('i', 'inactive', False, _('mark a bookmark inactive'))],
728 ('i', 'inactive', False, _('mark a bookmark inactive'))],
729 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
729 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
730 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
730 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
731 rename=None, inactive=False):
731 rename=None, inactive=False):
732 '''track a line of development with movable markers
732 '''track a line of development with movable markers
733
733
734 Bookmarks are pointers to certain commits that move when committing.
734 Bookmarks are pointers to certain commits that move when committing.
735 Bookmarks are local. They can be renamed, copied and deleted. It is
735 Bookmarks are local. They can be renamed, copied and deleted. It is
736 possible to use :hg:`merge NAME` to merge from a given bookmark, and
736 possible to use :hg:`merge NAME` to merge from a given bookmark, and
737 :hg:`update NAME` to update to a given bookmark.
737 :hg:`update NAME` to update to a given bookmark.
738
738
739 You can use :hg:`bookmark NAME` to set a bookmark on the working
739 You can use :hg:`bookmark NAME` to set a bookmark on the working
740 directory's parent revision with the given name. If you specify
740 directory's parent revision with the given name. If you specify
741 a revision using -r REV (where REV may be an existing bookmark),
741 a revision using -r REV (where REV may be an existing bookmark),
742 the bookmark is assigned to that revision.
742 the bookmark is assigned to that revision.
743
743
744 Bookmarks can be pushed and pulled between repositories (see :hg:`help
744 Bookmarks can be pushed and pulled between repositories (see :hg:`help
745 push` and :hg:`help pull`). This requires both the local and remote
745 push` and :hg:`help pull`). This requires both the local and remote
746 repositories to support bookmarks. For versions prior to 1.8, this means
746 repositories to support bookmarks. For versions prior to 1.8, this means
747 the bookmarks extension must be enabled.
747 the bookmarks extension must be enabled.
748
748
749 With -i/--inactive, the new bookmark will not be made the active
749 With -i/--inactive, the new bookmark will not be made the active
750 bookmark. If -r/--rev is given, the new bookmark will not be made
750 bookmark. If -r/--rev is given, the new bookmark will not be made
751 active even if -i/--inactive is not given. If no NAME is given, the
751 active even if -i/--inactive is not given. If no NAME is given, the
752 current active bookmark will be marked inactive.
752 current active bookmark will be marked inactive.
753 '''
753 '''
754 hexfn = ui.debugflag and hex or short
754 hexfn = ui.debugflag and hex or short
755 marks = repo._bookmarks
755 marks = repo._bookmarks
756 cur = repo.changectx('.').node()
756 cur = repo.changectx('.').node()
757
757
758 if delete:
758 if delete:
759 if mark is None:
759 if mark is None:
760 raise util.Abort(_("bookmark name required"))
760 raise util.Abort(_("bookmark name required"))
761 if mark not in marks:
761 if mark not in marks:
762 raise util.Abort(_("bookmark '%s' does not exist") % mark)
762 raise util.Abort(_("bookmark '%s' does not exist") % mark)
763 if mark == repo._bookmarkcurrent:
763 if mark == repo._bookmarkcurrent:
764 bookmarks.setcurrent(repo, None)
764 bookmarks.setcurrent(repo, None)
765 del marks[mark]
765 del marks[mark]
766 bookmarks.write(repo)
766 bookmarks.write(repo)
767 return
767 return
768
768
769 if rename:
769 if rename:
770 if rename not in marks:
770 if rename not in marks:
771 raise util.Abort(_("bookmark '%s' does not exist") % rename)
771 raise util.Abort(_("bookmark '%s' does not exist") % rename)
772 if mark in marks and not force:
772 if mark in marks and not force:
773 raise util.Abort(_("bookmark '%s' already exists "
773 raise util.Abort(_("bookmark '%s' already exists "
774 "(use -f to force)") % mark)
774 "(use -f to force)") % mark)
775 if mark is None:
775 if mark is None:
776 raise util.Abort(_("new bookmark name required"))
776 raise util.Abort(_("new bookmark name required"))
777 marks[mark] = marks[rename]
777 marks[mark] = marks[rename]
778 if repo._bookmarkcurrent == rename and not inactive:
778 if repo._bookmarkcurrent == rename and not inactive:
779 bookmarks.setcurrent(repo, mark)
779 bookmarks.setcurrent(repo, mark)
780 del marks[rename]
780 del marks[rename]
781 bookmarks.write(repo)
781 bookmarks.write(repo)
782 return
782 return
783
783
784 if mark is not None:
784 if mark is not None:
785 if "\n" in mark:
785 if "\n" in mark:
786 raise util.Abort(_("bookmark name cannot contain newlines"))
786 raise util.Abort(_("bookmark name cannot contain newlines"))
787 mark = mark.strip()
787 mark = mark.strip()
788 if not mark:
788 if not mark:
789 raise util.Abort(_("bookmark names cannot consist entirely of "
789 raise util.Abort(_("bookmark names cannot consist entirely of "
790 "whitespace"))
790 "whitespace"))
791 if inactive and mark == repo._bookmarkcurrent:
791 if inactive and mark == repo._bookmarkcurrent:
792 bookmarks.setcurrent(repo, None)
792 bookmarks.setcurrent(repo, None)
793 return
793 return
794 if mark in marks and not force:
794 if mark in marks and not force:
795 raise util.Abort(_("bookmark '%s' already exists "
795 raise util.Abort(_("bookmark '%s' already exists "
796 "(use -f to force)") % mark)
796 "(use -f to force)") % mark)
797 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
797 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
798 and not force):
798 and not force):
799 raise util.Abort(
799 raise util.Abort(
800 _("a bookmark cannot have the name of an existing branch"))
800 _("a bookmark cannot have the name of an existing branch"))
801 if rev:
801 if rev:
802 marks[mark] = repo.lookup(rev)
802 marks[mark] = repo.lookup(rev)
803 else:
803 else:
804 marks[mark] = cur
804 marks[mark] = cur
805 if not inactive and cur == marks[mark]:
805 if not inactive and cur == marks[mark]:
806 bookmarks.setcurrent(repo, mark)
806 bookmarks.setcurrent(repo, mark)
807 bookmarks.write(repo)
807 bookmarks.write(repo)
808 return
808 return
809
809
810 if mark is None:
810 if mark is None:
811 if rev:
811 if rev:
812 raise util.Abort(_("bookmark name required"))
812 raise util.Abort(_("bookmark name required"))
813 if len(marks) == 0:
813 if len(marks) == 0:
814 ui.status(_("no bookmarks set\n"))
814 ui.status(_("no bookmarks set\n"))
815 else:
815 else:
816 for bmark, n in sorted(marks.iteritems()):
816 for bmark, n in sorted(marks.iteritems()):
817 current = repo._bookmarkcurrent
817 current = repo._bookmarkcurrent
818 if bmark == current and n == cur:
818 if bmark == current and n == cur:
819 prefix, label = '*', 'bookmarks.current'
819 prefix, label = '*', 'bookmarks.current'
820 else:
820 else:
821 prefix, label = ' ', ''
821 prefix, label = ' ', ''
822
822
823 if ui.quiet:
823 if ui.quiet:
824 ui.write("%s\n" % bmark, label=label)
824 ui.write("%s\n" % bmark, label=label)
825 else:
825 else:
826 ui.write(" %s %-25s %d:%s\n" % (
826 ui.write(" %s %-25s %d:%s\n" % (
827 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
827 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
828 label=label)
828 label=label)
829 return
829 return
830
830
831 @command('branch',
831 @command('branch',
832 [('f', 'force', None,
832 [('f', 'force', None,
833 _('set branch name even if it shadows an existing branch')),
833 _('set branch name even if it shadows an existing branch')),
834 ('C', 'clean', None, _('reset branch name to parent branch name'))],
834 ('C', 'clean', None, _('reset branch name to parent branch name'))],
835 _('[-fC] [NAME]'))
835 _('[-fC] [NAME]'))
836 def branch(ui, repo, label=None, **opts):
836 def branch(ui, repo, label=None, **opts):
837 """set or show the current branch name
837 """set or show the current branch name
838
838
839 .. note::
839 .. note::
840 Branch names are permanent and global. Use :hg:`bookmark` to create a
840 Branch names are permanent and global. Use :hg:`bookmark` to create a
841 light-weight bookmark instead. See :hg:`help glossary` for more
841 light-weight bookmark instead. See :hg:`help glossary` for more
842 information about named branches and bookmarks.
842 information about named branches and bookmarks.
843
843
844 With no argument, show the current branch name. With one argument,
844 With no argument, show the current branch name. With one argument,
845 set the working directory branch name (the branch will not exist
845 set the working directory branch name (the branch will not exist
846 in the repository until the next commit). Standard practice
846 in the repository until the next commit). Standard practice
847 recommends that primary development take place on the 'default'
847 recommends that primary development take place on the 'default'
848 branch.
848 branch.
849
849
850 Unless -f/--force is specified, branch will not let you set a
850 Unless -f/--force is specified, branch will not let you set a
851 branch name that already exists, even if it's inactive.
851 branch name that already exists, even if it's inactive.
852
852
853 Use -C/--clean to reset the working directory branch to that of
853 Use -C/--clean to reset the working directory branch to that of
854 the parent of the working directory, negating a previous branch
854 the parent of the working directory, negating a previous branch
855 change.
855 change.
856
856
857 Use the command :hg:`update` to switch to an existing branch. Use
857 Use the command :hg:`update` to switch to an existing branch. Use
858 :hg:`commit --close-branch` to mark this branch as closed.
858 :hg:`commit --close-branch` to mark this branch as closed.
859
859
860 Returns 0 on success.
860 Returns 0 on success.
861 """
861 """
862
862
863 if opts.get('clean'):
863 if opts.get('clean'):
864 label = repo[None].p1().branch()
864 label = repo[None].p1().branch()
865 repo.dirstate.setbranch(label)
865 repo.dirstate.setbranch(label)
866 ui.status(_('reset working directory to branch %s\n') % label)
866 ui.status(_('reset working directory to branch %s\n') % label)
867 elif label:
867 elif label:
868 if not opts.get('force') and label in repo.branchtags():
868 if not opts.get('force') and label in repo.branchtags():
869 if label not in [p.branch() for p in repo.parents()]:
869 if label not in [p.branch() for p in repo.parents()]:
870 raise util.Abort(_('a branch of the same name already exists'),
870 raise util.Abort(_('a branch of the same name already exists'),
871 # i18n: "it" refers to an existing branch
871 # i18n: "it" refers to an existing branch
872 hint=_("use 'hg update' to switch to it"))
872 hint=_("use 'hg update' to switch to it"))
873 repo.dirstate.setbranch(label)
873 repo.dirstate.setbranch(label)
874 ui.status(_('marked working directory as branch %s\n') % label)
874 ui.status(_('marked working directory as branch %s\n') % label)
875 ui.status(_('(branches are permanent and global, '
875 ui.status(_('(branches are permanent and global, '
876 'did you want a bookmark?)\n'))
876 'did you want a bookmark?)\n'))
877 else:
877 else:
878 ui.write("%s\n" % repo.dirstate.branch())
878 ui.write("%s\n" % repo.dirstate.branch())
879
879
880 @command('branches',
880 @command('branches',
881 [('a', 'active', False, _('show only branches that have unmerged heads')),
881 [('a', 'active', False, _('show only branches that have unmerged heads')),
882 ('c', 'closed', False, _('show normal and closed branches'))],
882 ('c', 'closed', False, _('show normal and closed branches'))],
883 _('[-ac]'))
883 _('[-ac]'))
884 def branches(ui, repo, active=False, closed=False):
884 def branches(ui, repo, active=False, closed=False):
885 """list repository named branches
885 """list repository named branches
886
886
887 List the repository's named branches, indicating which ones are
887 List the repository's named branches, indicating which ones are
888 inactive. If -c/--closed is specified, also list branches which have
888 inactive. If -c/--closed is specified, also list branches which have
889 been marked closed (see :hg:`commit --close-branch`).
889 been marked closed (see :hg:`commit --close-branch`).
890
890
891 If -a/--active is specified, only show active branches. A branch
891 If -a/--active is specified, only show active branches. A branch
892 is considered active if it contains repository heads.
892 is considered active if it contains repository heads.
893
893
894 Use the command :hg:`update` to switch to an existing branch.
894 Use the command :hg:`update` to switch to an existing branch.
895
895
896 Returns 0.
896 Returns 0.
897 """
897 """
898
898
899 hexfunc = ui.debugflag and hex or short
899 hexfunc = ui.debugflag and hex or short
900 activebranches = [repo[n].branch() for n in repo.heads()]
900 activebranches = [repo[n].branch() for n in repo.heads()]
901 def testactive(tag, node):
901 def testactive(tag, node):
902 realhead = tag in activebranches
902 realhead = tag in activebranches
903 open = node in repo.branchheads(tag, closed=False)
903 open = node in repo.branchheads(tag, closed=False)
904 return realhead and open
904 return realhead and open
905 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
905 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
906 for tag, node in repo.branchtags().items()],
906 for tag, node in repo.branchtags().items()],
907 reverse=True)
907 reverse=True)
908
908
909 for isactive, node, tag in branches:
909 for isactive, node, tag in branches:
910 if (not active) or isactive:
910 if (not active) or isactive:
911 if ui.quiet:
911 if ui.quiet:
912 ui.write("%s\n" % tag)
912 ui.write("%s\n" % tag)
913 else:
913 else:
914 hn = repo.lookup(node)
914 hn = repo.lookup(node)
915 if isactive:
915 if isactive:
916 label = 'branches.active'
916 label = 'branches.active'
917 notice = ''
917 notice = ''
918 elif hn not in repo.branchheads(tag, closed=False):
918 elif hn not in repo.branchheads(tag, closed=False):
919 if not closed:
919 if not closed:
920 continue
920 continue
921 label = 'branches.closed'
921 label = 'branches.closed'
922 notice = _(' (closed)')
922 notice = _(' (closed)')
923 else:
923 else:
924 label = 'branches.inactive'
924 label = 'branches.inactive'
925 notice = _(' (inactive)')
925 notice = _(' (inactive)')
926 if tag == repo.dirstate.branch():
926 if tag == repo.dirstate.branch():
927 label = 'branches.current'
927 label = 'branches.current'
928 rev = str(node).rjust(31 - encoding.colwidth(tag))
928 rev = str(node).rjust(31 - encoding.colwidth(tag))
929 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
929 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
930 tag = ui.label(tag, label)
930 tag = ui.label(tag, label)
931 ui.write("%s %s%s\n" % (tag, rev, notice))
931 ui.write("%s %s%s\n" % (tag, rev, notice))
932
932
933 @command('bundle',
933 @command('bundle',
934 [('f', 'force', None, _('run even when the destination is unrelated')),
934 [('f', 'force', None, _('run even when the destination is unrelated')),
935 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
935 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
936 _('REV')),
936 _('REV')),
937 ('b', 'branch', [], _('a specific branch you would like to bundle'),
937 ('b', 'branch', [], _('a specific branch you would like to bundle'),
938 _('BRANCH')),
938 _('BRANCH')),
939 ('', 'base', [],
939 ('', 'base', [],
940 _('a base changeset assumed to be available at the destination'),
940 _('a base changeset assumed to be available at the destination'),
941 _('REV')),
941 _('REV')),
942 ('a', 'all', None, _('bundle all changesets in the repository')),
942 ('a', 'all', None, _('bundle all changesets in the repository')),
943 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
943 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
944 ] + remoteopts,
944 ] + remoteopts,
945 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
945 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
946 def bundle(ui, repo, fname, dest=None, **opts):
946 def bundle(ui, repo, fname, dest=None, **opts):
947 """create a changegroup file
947 """create a changegroup file
948
948
949 Generate a compressed changegroup file collecting changesets not
949 Generate a compressed changegroup file collecting changesets not
950 known to be in another repository.
950 known to be in another repository.
951
951
952 If you omit the destination repository, then hg assumes the
952 If you omit the destination repository, then hg assumes the
953 destination will have all the nodes you specify with --base
953 destination will have all the nodes you specify with --base
954 parameters. To create a bundle containing all changesets, use
954 parameters. To create a bundle containing all changesets, use
955 -a/--all (or --base null).
955 -a/--all (or --base null).
956
956
957 You can change compression method with the -t/--type option.
957 You can change compression method with the -t/--type option.
958 The available compression methods are: none, bzip2, and
958 The available compression methods are: none, bzip2, and
959 gzip (by default, bundles are compressed using bzip2).
959 gzip (by default, bundles are compressed using bzip2).
960
960
961 The bundle file can then be transferred using conventional means
961 The bundle file can then be transferred using conventional means
962 and applied to another repository with the unbundle or pull
962 and applied to another repository with the unbundle or pull
963 command. This is useful when direct push and pull are not
963 command. This is useful when direct push and pull are not
964 available or when exporting an entire repository is undesirable.
964 available or when exporting an entire repository is undesirable.
965
965
966 Applying bundles preserves all changeset contents including
966 Applying bundles preserves all changeset contents including
967 permissions, copy/rename information, and revision history.
967 permissions, copy/rename information, and revision history.
968
968
969 Returns 0 on success, 1 if no changes found.
969 Returns 0 on success, 1 if no changes found.
970 """
970 """
971 revs = None
971 revs = None
972 if 'rev' in opts:
972 if 'rev' in opts:
973 revs = scmutil.revrange(repo, opts['rev'])
973 revs = scmutil.revrange(repo, opts['rev'])
974
974
975 if opts.get('all'):
975 if opts.get('all'):
976 base = ['null']
976 base = ['null']
977 else:
977 else:
978 base = scmutil.revrange(repo, opts.get('base'))
978 base = scmutil.revrange(repo, opts.get('base'))
979 if base:
979 if base:
980 if dest:
980 if dest:
981 raise util.Abort(_("--base is incompatible with specifying "
981 raise util.Abort(_("--base is incompatible with specifying "
982 "a destination"))
982 "a destination"))
983 common = [repo.lookup(rev) for rev in base]
983 common = [repo.lookup(rev) for rev in base]
984 heads = revs and map(repo.lookup, revs) or revs
984 heads = revs and map(repo.lookup, revs) or revs
985 cg = repo.getbundle('bundle', heads=heads, common=common)
985 cg = repo.getbundle('bundle', heads=heads, common=common)
986 outgoing = None
986 outgoing = None
987 else:
987 else:
988 dest = ui.expandpath(dest or 'default-push', dest or 'default')
988 dest = ui.expandpath(dest or 'default-push', dest or 'default')
989 dest, branches = hg.parseurl(dest, opts.get('branch'))
989 dest, branches = hg.parseurl(dest, opts.get('branch'))
990 other = hg.peer(repo, opts, dest)
990 other = hg.peer(repo, opts, dest)
991 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
991 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
992 heads = revs and map(repo.lookup, revs) or revs
992 heads = revs and map(repo.lookup, revs) or revs
993 outgoing = discovery.findcommonoutgoing(repo, other,
993 outgoing = discovery.findcommonoutgoing(repo, other,
994 onlyheads=heads,
994 onlyheads=heads,
995 force=opts.get('force'))
995 force=opts.get('force'))
996 cg = repo.getlocalbundle('bundle', outgoing)
996 cg = repo.getlocalbundle('bundle', outgoing)
997 if not cg:
997 if not cg:
998 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
998 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
999 return 1
999 return 1
1000
1000
1001 bundletype = opts.get('type', 'bzip2').lower()
1001 bundletype = opts.get('type', 'bzip2').lower()
1002 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1002 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1003 bundletype = btypes.get(bundletype)
1003 bundletype = btypes.get(bundletype)
1004 if bundletype not in changegroup.bundletypes:
1004 if bundletype not in changegroup.bundletypes:
1005 raise util.Abort(_('unknown bundle type specified with --type'))
1005 raise util.Abort(_('unknown bundle type specified with --type'))
1006
1006
1007 changegroup.writebundle(cg, fname, bundletype)
1007 changegroup.writebundle(cg, fname, bundletype)
1008
1008
1009 @command('cat',
1009 @command('cat',
1010 [('o', 'output', '',
1010 [('o', 'output', '',
1011 _('print output to file with formatted name'), _('FORMAT')),
1011 _('print output to file with formatted name'), _('FORMAT')),
1012 ('r', 'rev', '', _('print the given revision'), _('REV')),
1012 ('r', 'rev', '', _('print the given revision'), _('REV')),
1013 ('', 'decode', None, _('apply any matching decode filter')),
1013 ('', 'decode', None, _('apply any matching decode filter')),
1014 ] + walkopts,
1014 ] + walkopts,
1015 _('[OPTION]... FILE...'))
1015 _('[OPTION]... FILE...'))
1016 def cat(ui, repo, file1, *pats, **opts):
1016 def cat(ui, repo, file1, *pats, **opts):
1017 """output the current or given revision of files
1017 """output the current or given revision of files
1018
1018
1019 Print the specified files as they were at the given revision. If
1019 Print the specified files as they were at the given revision. If
1020 no revision is given, the parent of the working directory is used,
1020 no revision is given, the parent of the working directory is used,
1021 or tip if no revision is checked out.
1021 or tip if no revision is checked out.
1022
1022
1023 Output may be to a file, in which case the name of the file is
1023 Output may be to a file, in which case the name of the file is
1024 given using a format string. The formatting rules are the same as
1024 given using a format string. The formatting rules are the same as
1025 for the export command, with the following additions:
1025 for the export command, with the following additions:
1026
1026
1027 :``%s``: basename of file being printed
1027 :``%s``: basename of file being printed
1028 :``%d``: dirname of file being printed, or '.' if in repository root
1028 :``%d``: dirname of file being printed, or '.' if in repository root
1029 :``%p``: root-relative path name of file being printed
1029 :``%p``: root-relative path name of file being printed
1030
1030
1031 Returns 0 on success.
1031 Returns 0 on success.
1032 """
1032 """
1033 ctx = scmutil.revsingle(repo, opts.get('rev'))
1033 ctx = scmutil.revsingle(repo, opts.get('rev'))
1034 err = 1
1034 err = 1
1035 m = scmutil.match(ctx, (file1,) + pats, opts)
1035 m = scmutil.match(ctx, (file1,) + pats, opts)
1036 for abs in ctx.walk(m):
1036 for abs in ctx.walk(m):
1037 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1037 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1038 pathname=abs)
1038 pathname=abs)
1039 data = ctx[abs].data()
1039 data = ctx[abs].data()
1040 if opts.get('decode'):
1040 if opts.get('decode'):
1041 data = repo.wwritedata(abs, data)
1041 data = repo.wwritedata(abs, data)
1042 fp.write(data)
1042 fp.write(data)
1043 fp.close()
1043 fp.close()
1044 err = 0
1044 err = 0
1045 return err
1045 return err
1046
1046
1047 @command('^clone',
1047 @command('^clone',
1048 [('U', 'noupdate', None,
1048 [('U', 'noupdate', None,
1049 _('the clone will include an empty working copy (only a repository)')),
1049 _('the clone will include an empty working copy (only a repository)')),
1050 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1050 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1051 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1051 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1052 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1052 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1053 ('', 'pull', None, _('use pull protocol to copy metadata')),
1053 ('', 'pull', None, _('use pull protocol to copy metadata')),
1054 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1054 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1055 ] + remoteopts,
1055 ] + remoteopts,
1056 _('[OPTION]... SOURCE [DEST]'))
1056 _('[OPTION]... SOURCE [DEST]'))
1057 def clone(ui, source, dest=None, **opts):
1057 def clone(ui, source, dest=None, **opts):
1058 """make a copy of an existing repository
1058 """make a copy of an existing repository
1059
1059
1060 Create a copy of an existing repository in a new directory.
1060 Create a copy of an existing repository in a new directory.
1061
1061
1062 If no destination directory name is specified, it defaults to the
1062 If no destination directory name is specified, it defaults to the
1063 basename of the source.
1063 basename of the source.
1064
1064
1065 The location of the source is added to the new repository's
1065 The location of the source is added to the new repository's
1066 ``.hg/hgrc`` file, as the default to be used for future pulls.
1066 ``.hg/hgrc`` file, as the default to be used for future pulls.
1067
1067
1068 Only local paths and ``ssh://`` URLs are supported as
1068 Only local paths and ``ssh://`` URLs are supported as
1069 destinations. For ``ssh://`` destinations, no working directory or
1069 destinations. For ``ssh://`` destinations, no working directory or
1070 ``.hg/hgrc`` will be created on the remote side.
1070 ``.hg/hgrc`` will be created on the remote side.
1071
1071
1072 To pull only a subset of changesets, specify one or more revisions
1072 To pull only a subset of changesets, specify one or more revisions
1073 identifiers with -r/--rev or branches with -b/--branch. The
1073 identifiers with -r/--rev or branches with -b/--branch. The
1074 resulting clone will contain only the specified changesets and
1074 resulting clone will contain only the specified changesets and
1075 their ancestors. These options (or 'clone src#rev dest') imply
1075 their ancestors. These options (or 'clone src#rev dest') imply
1076 --pull, even for local source repositories. Note that specifying a
1076 --pull, even for local source repositories. Note that specifying a
1077 tag will include the tagged changeset but not the changeset
1077 tag will include the tagged changeset but not the changeset
1078 containing the tag.
1078 containing the tag.
1079
1079
1080 To check out a particular version, use -u/--update, or
1080 To check out a particular version, use -u/--update, or
1081 -U/--noupdate to create a clone with no working directory.
1081 -U/--noupdate to create a clone with no working directory.
1082
1082
1083 .. container:: verbose
1083 .. container:: verbose
1084
1084
1085 For efficiency, hardlinks are used for cloning whenever the
1085 For efficiency, hardlinks are used for cloning whenever the
1086 source and destination are on the same filesystem (note this
1086 source and destination are on the same filesystem (note this
1087 applies only to the repository data, not to the working
1087 applies only to the repository data, not to the working
1088 directory). Some filesystems, such as AFS, implement hardlinking
1088 directory). Some filesystems, such as AFS, implement hardlinking
1089 incorrectly, but do not report errors. In these cases, use the
1089 incorrectly, but do not report errors. In these cases, use the
1090 --pull option to avoid hardlinking.
1090 --pull option to avoid hardlinking.
1091
1091
1092 In some cases, you can clone repositories and the working
1092 In some cases, you can clone repositories and the working
1093 directory using full hardlinks with ::
1093 directory using full hardlinks with ::
1094
1094
1095 $ cp -al REPO REPOCLONE
1095 $ cp -al REPO REPOCLONE
1096
1096
1097 This is the fastest way to clone, but it is not always safe. The
1097 This is the fastest way to clone, but it is not always safe. The
1098 operation is not atomic (making sure REPO is not modified during
1098 operation is not atomic (making sure REPO is not modified during
1099 the operation is up to you) and you have to make sure your
1099 the operation is up to you) and you have to make sure your
1100 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1100 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1101 so). Also, this is not compatible with certain extensions that
1101 so). Also, this is not compatible with certain extensions that
1102 place their metadata under the .hg directory, such as mq.
1102 place their metadata under the .hg directory, such as mq.
1103
1103
1104 Mercurial will update the working directory to the first applicable
1104 Mercurial will update the working directory to the first applicable
1105 revision from this list:
1105 revision from this list:
1106
1106
1107 a) null if -U or the source repository has no changesets
1107 a) null if -U or the source repository has no changesets
1108 b) if -u . and the source repository is local, the first parent of
1108 b) if -u . and the source repository is local, the first parent of
1109 the source repository's working directory
1109 the source repository's working directory
1110 c) the changeset specified with -u (if a branch name, this means the
1110 c) the changeset specified with -u (if a branch name, this means the
1111 latest head of that branch)
1111 latest head of that branch)
1112 d) the changeset specified with -r
1112 d) the changeset specified with -r
1113 e) the tipmost head specified with -b
1113 e) the tipmost head specified with -b
1114 f) the tipmost head specified with the url#branch source syntax
1114 f) the tipmost head specified with the url#branch source syntax
1115 g) the tipmost head of the default branch
1115 g) the tipmost head of the default branch
1116 h) tip
1116 h) tip
1117
1117
1118 Examples:
1118 Examples:
1119
1119
1120 - clone a remote repository to a new directory named hg/::
1120 - clone a remote repository to a new directory named hg/::
1121
1121
1122 hg clone http://selenic.com/hg
1122 hg clone http://selenic.com/hg
1123
1123
1124 - create a lightweight local clone::
1124 - create a lightweight local clone::
1125
1125
1126 hg clone project/ project-feature/
1126 hg clone project/ project-feature/
1127
1127
1128 - clone from an absolute path on an ssh server (note double-slash)::
1128 - clone from an absolute path on an ssh server (note double-slash)::
1129
1129
1130 hg clone ssh://user@server//home/projects/alpha/
1130 hg clone ssh://user@server//home/projects/alpha/
1131
1131
1132 - do a high-speed clone over a LAN while checking out a
1132 - do a high-speed clone over a LAN while checking out a
1133 specified version::
1133 specified version::
1134
1134
1135 hg clone --uncompressed http://server/repo -u 1.5
1135 hg clone --uncompressed http://server/repo -u 1.5
1136
1136
1137 - create a repository without changesets after a particular revision::
1137 - create a repository without changesets after a particular revision::
1138
1138
1139 hg clone -r 04e544 experimental/ good/
1139 hg clone -r 04e544 experimental/ good/
1140
1140
1141 - clone (and track) a particular named branch::
1141 - clone (and track) a particular named branch::
1142
1142
1143 hg clone http://selenic.com/hg#stable
1143 hg clone http://selenic.com/hg#stable
1144
1144
1145 See :hg:`help urls` for details on specifying URLs.
1145 See :hg:`help urls` for details on specifying URLs.
1146
1146
1147 Returns 0 on success.
1147 Returns 0 on success.
1148 """
1148 """
1149 if opts.get('noupdate') and opts.get('updaterev'):
1149 if opts.get('noupdate') and opts.get('updaterev'):
1150 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1150 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1151
1151
1152 r = hg.clone(ui, opts, source, dest,
1152 r = hg.clone(ui, opts, source, dest,
1153 pull=opts.get('pull'),
1153 pull=opts.get('pull'),
1154 stream=opts.get('uncompressed'),
1154 stream=opts.get('uncompressed'),
1155 rev=opts.get('rev'),
1155 rev=opts.get('rev'),
1156 update=opts.get('updaterev') or not opts.get('noupdate'),
1156 update=opts.get('updaterev') or not opts.get('noupdate'),
1157 branch=opts.get('branch'))
1157 branch=opts.get('branch'))
1158
1158
1159 return r is None
1159 return r is None
1160
1160
1161 @command('^commit|ci',
1161 @command('^commit|ci',
1162 [('A', 'addremove', None,
1162 [('A', 'addremove', None,
1163 _('mark new/missing files as added/removed before committing')),
1163 _('mark new/missing files as added/removed before committing')),
1164 ('', 'close-branch', None,
1164 ('', 'close-branch', None,
1165 _('mark a branch as closed, hiding it from the branch list')),
1165 _('mark a branch as closed, hiding it from the branch list')),
1166 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1166 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1167 _('[OPTION]... [FILE]...'))
1167 _('[OPTION]... [FILE]...'))
1168 def commit(ui, repo, *pats, **opts):
1168 def commit(ui, repo, *pats, **opts):
1169 """commit the specified files or all outstanding changes
1169 """commit the specified files or all outstanding changes
1170
1170
1171 Commit changes to the given files into the repository. Unlike a
1171 Commit changes to the given files into the repository. Unlike a
1172 centralized SCM, this operation is a local operation. See
1172 centralized SCM, this operation is a local operation. See
1173 :hg:`push` for a way to actively distribute your changes.
1173 :hg:`push` for a way to actively distribute your changes.
1174
1174
1175 If a list of files is omitted, all changes reported by :hg:`status`
1175 If a list of files is omitted, all changes reported by :hg:`status`
1176 will be committed.
1176 will be committed.
1177
1177
1178 If you are committing the result of a merge, do not provide any
1178 If you are committing the result of a merge, do not provide any
1179 filenames or -I/-X filters.
1179 filenames or -I/-X filters.
1180
1180
1181 If no commit message is specified, Mercurial starts your
1181 If no commit message is specified, Mercurial starts your
1182 configured editor where you can enter a message. In case your
1182 configured editor where you can enter a message. In case your
1183 commit fails, you will find a backup of your message in
1183 commit fails, you will find a backup of your message in
1184 ``.hg/last-message.txt``.
1184 ``.hg/last-message.txt``.
1185
1185
1186 See :hg:`help dates` for a list of formats valid for -d/--date.
1186 See :hg:`help dates` for a list of formats valid for -d/--date.
1187
1187
1188 Returns 0 on success, 1 if nothing changed.
1188 Returns 0 on success, 1 if nothing changed.
1189 """
1189 """
1190 if opts.get('subrepos'):
1190 if opts.get('subrepos'):
1191 # Let --subrepos on the command line overide config setting.
1191 # Let --subrepos on the command line overide config setting.
1192 ui.setconfig('ui', 'commitsubrepos', True)
1192 ui.setconfig('ui', 'commitsubrepos', True)
1193
1193
1194 extra = {}
1194 extra = {}
1195 if opts.get('close_branch'):
1195 if opts.get('close_branch'):
1196 if repo['.'].node() not in repo.branchheads():
1196 if repo['.'].node() not in repo.branchheads():
1197 # The topo heads set is included in the branch heads set of the
1197 # The topo heads set is included in the branch heads set of the
1198 # current branch, so it's sufficient to test branchheads
1198 # current branch, so it's sufficient to test branchheads
1199 raise util.Abort(_('can only close branch heads'))
1199 raise util.Abort(_('can only close branch heads'))
1200 extra['close'] = 1
1200 extra['close'] = 1
1201 e = cmdutil.commiteditor
1201 e = cmdutil.commiteditor
1202 if opts.get('force_editor'):
1202 if opts.get('force_editor'):
1203 e = cmdutil.commitforceeditor
1203 e = cmdutil.commitforceeditor
1204
1204
1205 def commitfunc(ui, repo, message, match, opts):
1205 def commitfunc(ui, repo, message, match, opts):
1206 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1206 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1207 editor=e, extra=extra)
1207 editor=e, extra=extra)
1208
1208
1209 branch = repo[None].branch()
1209 branch = repo[None].branch()
1210 bheads = repo.branchheads(branch)
1210 bheads = repo.branchheads(branch)
1211
1211
1212 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1212 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1213 if not node:
1213 if not node:
1214 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1214 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1215 if stat[3]:
1215 if stat[3]:
1216 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1216 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1217 % len(stat[3]))
1217 % len(stat[3]))
1218 else:
1218 else:
1219 ui.status(_("nothing changed\n"))
1219 ui.status(_("nothing changed\n"))
1220 return 1
1220 return 1
1221
1221
1222 ctx = repo[node]
1222 ctx = repo[node]
1223 parents = ctx.parents()
1223 parents = ctx.parents()
1224
1224
1225 if (bheads and node not in bheads and not
1225 if (bheads and node not in bheads and not
1226 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1226 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1227 ui.status(_('created new head\n'))
1227 ui.status(_('created new head\n'))
1228 # The message is not printed for initial roots. For the other
1228 # The message is not printed for initial roots. For the other
1229 # changesets, it is printed in the following situations:
1229 # changesets, it is printed in the following situations:
1230 #
1230 #
1231 # Par column: for the 2 parents with ...
1231 # Par column: for the 2 parents with ...
1232 # N: null or no parent
1232 # N: null or no parent
1233 # B: parent is on another named branch
1233 # B: parent is on another named branch
1234 # C: parent is a regular non head changeset
1234 # C: parent is a regular non head changeset
1235 # H: parent was a branch head of the current branch
1235 # H: parent was a branch head of the current branch
1236 # Msg column: whether we print "created new head" message
1236 # Msg column: whether we print "created new head" message
1237 # In the following, it is assumed that there already exists some
1237 # In the following, it is assumed that there already exists some
1238 # initial branch heads of the current branch, otherwise nothing is
1238 # initial branch heads of the current branch, otherwise nothing is
1239 # printed anyway.
1239 # printed anyway.
1240 #
1240 #
1241 # Par Msg Comment
1241 # Par Msg Comment
1242 # NN y additional topo root
1242 # NN y additional topo root
1243 #
1243 #
1244 # BN y additional branch root
1244 # BN y additional branch root
1245 # CN y additional topo head
1245 # CN y additional topo head
1246 # HN n usual case
1246 # HN n usual case
1247 #
1247 #
1248 # BB y weird additional branch root
1248 # BB y weird additional branch root
1249 # CB y branch merge
1249 # CB y branch merge
1250 # HB n merge with named branch
1250 # HB n merge with named branch
1251 #
1251 #
1252 # CC y additional head from merge
1252 # CC y additional head from merge
1253 # CH n merge with a head
1253 # CH n merge with a head
1254 #
1254 #
1255 # HH n head merge: head count decreases
1255 # HH n head merge: head count decreases
1256
1256
1257 if not opts.get('close_branch'):
1257 if not opts.get('close_branch'):
1258 for r in parents:
1258 for r in parents:
1259 if r.extra().get('close') and r.branch() == branch:
1259 if r.extra().get('close') and r.branch() == branch:
1260 ui.status(_('reopening closed branch head %d\n') % r)
1260 ui.status(_('reopening closed branch head %d\n') % r)
1261
1261
1262 if ui.debugflag:
1262 if ui.debugflag:
1263 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1263 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1264 elif ui.verbose:
1264 elif ui.verbose:
1265 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1265 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1266
1266
1267 @command('copy|cp',
1267 @command('copy|cp',
1268 [('A', 'after', None, _('record a copy that has already occurred')),
1268 [('A', 'after', None, _('record a copy that has already occurred')),
1269 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1269 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1270 ] + walkopts + dryrunopts,
1270 ] + walkopts + dryrunopts,
1271 _('[OPTION]... [SOURCE]... DEST'))
1271 _('[OPTION]... [SOURCE]... DEST'))
1272 def copy(ui, repo, *pats, **opts):
1272 def copy(ui, repo, *pats, **opts):
1273 """mark files as copied for the next commit
1273 """mark files as copied for the next commit
1274
1274
1275 Mark dest as having copies of source files. If dest is a
1275 Mark dest as having copies of source files. If dest is a
1276 directory, copies are put in that directory. If dest is a file,
1276 directory, copies are put in that directory. If dest is a file,
1277 the source must be a single file.
1277 the source must be a single file.
1278
1278
1279 By default, this command copies the contents of files as they
1279 By default, this command copies the contents of files as they
1280 exist in the working directory. If invoked with -A/--after, the
1280 exist in the working directory. If invoked with -A/--after, the
1281 operation is recorded, but no copying is performed.
1281 operation is recorded, but no copying is performed.
1282
1282
1283 This command takes effect with the next commit. To undo a copy
1283 This command takes effect with the next commit. To undo a copy
1284 before that, see :hg:`revert`.
1284 before that, see :hg:`revert`.
1285
1285
1286 Returns 0 on success, 1 if errors are encountered.
1286 Returns 0 on success, 1 if errors are encountered.
1287 """
1287 """
1288 wlock = repo.wlock(False)
1288 wlock = repo.wlock(False)
1289 try:
1289 try:
1290 return cmdutil.copy(ui, repo, pats, opts)
1290 return cmdutil.copy(ui, repo, pats, opts)
1291 finally:
1291 finally:
1292 wlock.release()
1292 wlock.release()
1293
1293
1294 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1294 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1295 def debugancestor(ui, repo, *args):
1295 def debugancestor(ui, repo, *args):
1296 """find the ancestor revision of two revisions in a given index"""
1296 """find the ancestor revision of two revisions in a given index"""
1297 if len(args) == 3:
1297 if len(args) == 3:
1298 index, rev1, rev2 = args
1298 index, rev1, rev2 = args
1299 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1299 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1300 lookup = r.lookup
1300 lookup = r.lookup
1301 elif len(args) == 2:
1301 elif len(args) == 2:
1302 if not repo:
1302 if not repo:
1303 raise util.Abort(_("there is no Mercurial repository here "
1303 raise util.Abort(_("there is no Mercurial repository here "
1304 "(.hg not found)"))
1304 "(.hg not found)"))
1305 rev1, rev2 = args
1305 rev1, rev2 = args
1306 r = repo.changelog
1306 r = repo.changelog
1307 lookup = repo.lookup
1307 lookup = repo.lookup
1308 else:
1308 else:
1309 raise util.Abort(_('either two or three arguments required'))
1309 raise util.Abort(_('either two or three arguments required'))
1310 a = r.ancestor(lookup(rev1), lookup(rev2))
1310 a = r.ancestor(lookup(rev1), lookup(rev2))
1311 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1311 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1312
1312
1313 @command('debugbuilddag',
1313 @command('debugbuilddag',
1314 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1314 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1315 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1315 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1316 ('n', 'new-file', None, _('add new file at each rev'))],
1316 ('n', 'new-file', None, _('add new file at each rev'))],
1317 _('[OPTION]... [TEXT]'))
1317 _('[OPTION]... [TEXT]'))
1318 def debugbuilddag(ui, repo, text=None,
1318 def debugbuilddag(ui, repo, text=None,
1319 mergeable_file=False,
1319 mergeable_file=False,
1320 overwritten_file=False,
1320 overwritten_file=False,
1321 new_file=False):
1321 new_file=False):
1322 """builds a repo with a given DAG from scratch in the current empty repo
1322 """builds a repo with a given DAG from scratch in the current empty repo
1323
1323
1324 The description of the DAG is read from stdin if not given on the
1324 The description of the DAG is read from stdin if not given on the
1325 command line.
1325 command line.
1326
1326
1327 Elements:
1327 Elements:
1328
1328
1329 - "+n" is a linear run of n nodes based on the current default parent
1329 - "+n" is a linear run of n nodes based on the current default parent
1330 - "." is a single node based on the current default parent
1330 - "." is a single node based on the current default parent
1331 - "$" resets the default parent to null (implied at the start);
1331 - "$" resets the default parent to null (implied at the start);
1332 otherwise the default parent is always the last node created
1332 otherwise the default parent is always the last node created
1333 - "<p" sets the default parent to the backref p
1333 - "<p" sets the default parent to the backref p
1334 - "*p" is a fork at parent p, which is a backref
1334 - "*p" is a fork at parent p, which is a backref
1335 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1335 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1336 - "/p2" is a merge of the preceding node and p2
1336 - "/p2" is a merge of the preceding node and p2
1337 - ":tag" defines a local tag for the preceding node
1337 - ":tag" defines a local tag for the preceding node
1338 - "@branch" sets the named branch for subsequent nodes
1338 - "@branch" sets the named branch for subsequent nodes
1339 - "#...\\n" is a comment up to the end of the line
1339 - "#...\\n" is a comment up to the end of the line
1340
1340
1341 Whitespace between the above elements is ignored.
1341 Whitespace between the above elements is ignored.
1342
1342
1343 A backref is either
1343 A backref is either
1344
1344
1345 - a number n, which references the node curr-n, where curr is the current
1345 - a number n, which references the node curr-n, where curr is the current
1346 node, or
1346 node, or
1347 - the name of a local tag you placed earlier using ":tag", or
1347 - the name of a local tag you placed earlier using ":tag", or
1348 - empty to denote the default parent.
1348 - empty to denote the default parent.
1349
1349
1350 All string valued-elements are either strictly alphanumeric, or must
1350 All string valued-elements are either strictly alphanumeric, or must
1351 be enclosed in double quotes ("..."), with "\\" as escape character.
1351 be enclosed in double quotes ("..."), with "\\" as escape character.
1352 """
1352 """
1353
1353
1354 if text is None:
1354 if text is None:
1355 ui.status(_("reading DAG from stdin\n"))
1355 ui.status(_("reading DAG from stdin\n"))
1356 text = ui.fin.read()
1356 text = ui.fin.read()
1357
1357
1358 cl = repo.changelog
1358 cl = repo.changelog
1359 if len(cl) > 0:
1359 if len(cl) > 0:
1360 raise util.Abort(_('repository is not empty'))
1360 raise util.Abort(_('repository is not empty'))
1361
1361
1362 # determine number of revs in DAG
1362 # determine number of revs in DAG
1363 total = 0
1363 total = 0
1364 for type, data in dagparser.parsedag(text):
1364 for type, data in dagparser.parsedag(text):
1365 if type == 'n':
1365 if type == 'n':
1366 total += 1
1366 total += 1
1367
1367
1368 if mergeable_file:
1368 if mergeable_file:
1369 linesperrev = 2
1369 linesperrev = 2
1370 # make a file with k lines per rev
1370 # make a file with k lines per rev
1371 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1371 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1372 initialmergedlines.append("")
1372 initialmergedlines.append("")
1373
1373
1374 tags = []
1374 tags = []
1375
1375
1376 lock = tr = None
1376 lock = tr = None
1377 try:
1377 try:
1378 lock = repo.lock()
1378 lock = repo.lock()
1379 tr = repo.transaction("builddag")
1379 tr = repo.transaction("builddag")
1380
1380
1381 at = -1
1381 at = -1
1382 atbranch = 'default'
1382 atbranch = 'default'
1383 nodeids = []
1383 nodeids = []
1384 id = 0
1384 id = 0
1385 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1385 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1386 for type, data in dagparser.parsedag(text):
1386 for type, data in dagparser.parsedag(text):
1387 if type == 'n':
1387 if type == 'n':
1388 ui.note('node %s\n' % str(data))
1388 ui.note('node %s\n' % str(data))
1389 id, ps = data
1389 id, ps = data
1390
1390
1391 files = []
1391 files = []
1392 fctxs = {}
1392 fctxs = {}
1393
1393
1394 p2 = None
1394 p2 = None
1395 if mergeable_file:
1395 if mergeable_file:
1396 fn = "mf"
1396 fn = "mf"
1397 p1 = repo[ps[0]]
1397 p1 = repo[ps[0]]
1398 if len(ps) > 1:
1398 if len(ps) > 1:
1399 p2 = repo[ps[1]]
1399 p2 = repo[ps[1]]
1400 pa = p1.ancestor(p2)
1400 pa = p1.ancestor(p2)
1401 base, local, other = [x[fn].data() for x in pa, p1, p2]
1401 base, local, other = [x[fn].data() for x in pa, p1, p2]
1402 m3 = simplemerge.Merge3Text(base, local, other)
1402 m3 = simplemerge.Merge3Text(base, local, other)
1403 ml = [l.strip() for l in m3.merge_lines()]
1403 ml = [l.strip() for l in m3.merge_lines()]
1404 ml.append("")
1404 ml.append("")
1405 elif at > 0:
1405 elif at > 0:
1406 ml = p1[fn].data().split("\n")
1406 ml = p1[fn].data().split("\n")
1407 else:
1407 else:
1408 ml = initialmergedlines
1408 ml = initialmergedlines
1409 ml[id * linesperrev] += " r%i" % id
1409 ml[id * linesperrev] += " r%i" % id
1410 mergedtext = "\n".join(ml)
1410 mergedtext = "\n".join(ml)
1411 files.append(fn)
1411 files.append(fn)
1412 fctxs[fn] = context.memfilectx(fn, mergedtext)
1412 fctxs[fn] = context.memfilectx(fn, mergedtext)
1413
1413
1414 if overwritten_file:
1414 if overwritten_file:
1415 fn = "of"
1415 fn = "of"
1416 files.append(fn)
1416 files.append(fn)
1417 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1417 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1418
1418
1419 if new_file:
1419 if new_file:
1420 fn = "nf%i" % id
1420 fn = "nf%i" % id
1421 files.append(fn)
1421 files.append(fn)
1422 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1422 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1423 if len(ps) > 1:
1423 if len(ps) > 1:
1424 if not p2:
1424 if not p2:
1425 p2 = repo[ps[1]]
1425 p2 = repo[ps[1]]
1426 for fn in p2:
1426 for fn in p2:
1427 if fn.startswith("nf"):
1427 if fn.startswith("nf"):
1428 files.append(fn)
1428 files.append(fn)
1429 fctxs[fn] = p2[fn]
1429 fctxs[fn] = p2[fn]
1430
1430
1431 def fctxfn(repo, cx, path):
1431 def fctxfn(repo, cx, path):
1432 return fctxs.get(path)
1432 return fctxs.get(path)
1433
1433
1434 if len(ps) == 0 or ps[0] < 0:
1434 if len(ps) == 0 or ps[0] < 0:
1435 pars = [None, None]
1435 pars = [None, None]
1436 elif len(ps) == 1:
1436 elif len(ps) == 1:
1437 pars = [nodeids[ps[0]], None]
1437 pars = [nodeids[ps[0]], None]
1438 else:
1438 else:
1439 pars = [nodeids[p] for p in ps]
1439 pars = [nodeids[p] for p in ps]
1440 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1440 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1441 date=(id, 0),
1441 date=(id, 0),
1442 user="debugbuilddag",
1442 user="debugbuilddag",
1443 extra={'branch': atbranch})
1443 extra={'branch': atbranch})
1444 nodeid = repo.commitctx(cx)
1444 nodeid = repo.commitctx(cx)
1445 nodeids.append(nodeid)
1445 nodeids.append(nodeid)
1446 at = id
1446 at = id
1447 elif type == 'l':
1447 elif type == 'l':
1448 id, name = data
1448 id, name = data
1449 ui.note('tag %s\n' % name)
1449 ui.note('tag %s\n' % name)
1450 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1450 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1451 elif type == 'a':
1451 elif type == 'a':
1452 ui.note('branch %s\n' % data)
1452 ui.note('branch %s\n' % data)
1453 atbranch = data
1453 atbranch = data
1454 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1454 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1455 tr.close()
1455 tr.close()
1456
1456
1457 if tags:
1457 if tags:
1458 repo.opener.write("localtags", "".join(tags))
1458 repo.opener.write("localtags", "".join(tags))
1459 finally:
1459 finally:
1460 ui.progress(_('building'), None)
1460 ui.progress(_('building'), None)
1461 release(tr, lock)
1461 release(tr, lock)
1462
1462
1463 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1463 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1464 def debugbundle(ui, bundlepath, all=None, **opts):
1464 def debugbundle(ui, bundlepath, all=None, **opts):
1465 """lists the contents of a bundle"""
1465 """lists the contents of a bundle"""
1466 f = url.open(ui, bundlepath)
1466 f = url.open(ui, bundlepath)
1467 try:
1467 try:
1468 gen = changegroup.readbundle(f, bundlepath)
1468 gen = changegroup.readbundle(f, bundlepath)
1469 if all:
1469 if all:
1470 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1470 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1471
1471
1472 def showchunks(named):
1472 def showchunks(named):
1473 ui.write("\n%s\n" % named)
1473 ui.write("\n%s\n" % named)
1474 chain = None
1474 chain = None
1475 while True:
1475 while True:
1476 chunkdata = gen.deltachunk(chain)
1476 chunkdata = gen.deltachunk(chain)
1477 if not chunkdata:
1477 if not chunkdata:
1478 break
1478 break
1479 node = chunkdata['node']
1479 node = chunkdata['node']
1480 p1 = chunkdata['p1']
1480 p1 = chunkdata['p1']
1481 p2 = chunkdata['p2']
1481 p2 = chunkdata['p2']
1482 cs = chunkdata['cs']
1482 cs = chunkdata['cs']
1483 deltabase = chunkdata['deltabase']
1483 deltabase = chunkdata['deltabase']
1484 delta = chunkdata['delta']
1484 delta = chunkdata['delta']
1485 ui.write("%s %s %s %s %s %s\n" %
1485 ui.write("%s %s %s %s %s %s\n" %
1486 (hex(node), hex(p1), hex(p2),
1486 (hex(node), hex(p1), hex(p2),
1487 hex(cs), hex(deltabase), len(delta)))
1487 hex(cs), hex(deltabase), len(delta)))
1488 chain = node
1488 chain = node
1489
1489
1490 chunkdata = gen.changelogheader()
1490 chunkdata = gen.changelogheader()
1491 showchunks("changelog")
1491 showchunks("changelog")
1492 chunkdata = gen.manifestheader()
1492 chunkdata = gen.manifestheader()
1493 showchunks("manifest")
1493 showchunks("manifest")
1494 while True:
1494 while True:
1495 chunkdata = gen.filelogheader()
1495 chunkdata = gen.filelogheader()
1496 if not chunkdata:
1496 if not chunkdata:
1497 break
1497 break
1498 fname = chunkdata['filename']
1498 fname = chunkdata['filename']
1499 showchunks(fname)
1499 showchunks(fname)
1500 else:
1500 else:
1501 chunkdata = gen.changelogheader()
1501 chunkdata = gen.changelogheader()
1502 chain = None
1502 chain = None
1503 while True:
1503 while True:
1504 chunkdata = gen.deltachunk(chain)
1504 chunkdata = gen.deltachunk(chain)
1505 if not chunkdata:
1505 if not chunkdata:
1506 break
1506 break
1507 node = chunkdata['node']
1507 node = chunkdata['node']
1508 ui.write("%s\n" % hex(node))
1508 ui.write("%s\n" % hex(node))
1509 chain = node
1509 chain = node
1510 finally:
1510 finally:
1511 f.close()
1511 f.close()
1512
1512
1513 @command('debugcheckstate', [], '')
1513 @command('debugcheckstate', [], '')
1514 def debugcheckstate(ui, repo):
1514 def debugcheckstate(ui, repo):
1515 """validate the correctness of the current dirstate"""
1515 """validate the correctness of the current dirstate"""
1516 parent1, parent2 = repo.dirstate.parents()
1516 parent1, parent2 = repo.dirstate.parents()
1517 m1 = repo[parent1].manifest()
1517 m1 = repo[parent1].manifest()
1518 m2 = repo[parent2].manifest()
1518 m2 = repo[parent2].manifest()
1519 errors = 0
1519 errors = 0
1520 for f in repo.dirstate:
1520 for f in repo.dirstate:
1521 state = repo.dirstate[f]
1521 state = repo.dirstate[f]
1522 if state in "nr" and f not in m1:
1522 if state in "nr" and f not in m1:
1523 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1523 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1524 errors += 1
1524 errors += 1
1525 if state in "a" and f in m1:
1525 if state in "a" and f in m1:
1526 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1526 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1527 errors += 1
1527 errors += 1
1528 if state in "m" and f not in m1 and f not in m2:
1528 if state in "m" and f not in m1 and f not in m2:
1529 ui.warn(_("%s in state %s, but not in either manifest\n") %
1529 ui.warn(_("%s in state %s, but not in either manifest\n") %
1530 (f, state))
1530 (f, state))
1531 errors += 1
1531 errors += 1
1532 for f in m1:
1532 for f in m1:
1533 state = repo.dirstate[f]
1533 state = repo.dirstate[f]
1534 if state not in "nrm":
1534 if state not in "nrm":
1535 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1535 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1536 errors += 1
1536 errors += 1
1537 if errors:
1537 if errors:
1538 error = _(".hg/dirstate inconsistent with current parent's manifest")
1538 error = _(".hg/dirstate inconsistent with current parent's manifest")
1539 raise util.Abort(error)
1539 raise util.Abort(error)
1540
1540
1541 @command('debugcommands', [], _('[COMMAND]'))
1541 @command('debugcommands', [], _('[COMMAND]'))
1542 def debugcommands(ui, cmd='', *args):
1542 def debugcommands(ui, cmd='', *args):
1543 """list all available commands and options"""
1543 """list all available commands and options"""
1544 for cmd, vals in sorted(table.iteritems()):
1544 for cmd, vals in sorted(table.iteritems()):
1545 cmd = cmd.split('|')[0].strip('^')
1545 cmd = cmd.split('|')[0].strip('^')
1546 opts = ', '.join([i[1] for i in vals[1]])
1546 opts = ', '.join([i[1] for i in vals[1]])
1547 ui.write('%s: %s\n' % (cmd, opts))
1547 ui.write('%s: %s\n' % (cmd, opts))
1548
1548
1549 @command('debugcomplete',
1549 @command('debugcomplete',
1550 [('o', 'options', None, _('show the command options'))],
1550 [('o', 'options', None, _('show the command options'))],
1551 _('[-o] CMD'))
1551 _('[-o] CMD'))
1552 def debugcomplete(ui, cmd='', **opts):
1552 def debugcomplete(ui, cmd='', **opts):
1553 """returns the completion list associated with the given command"""
1553 """returns the completion list associated with the given command"""
1554
1554
1555 if opts.get('options'):
1555 if opts.get('options'):
1556 options = []
1556 options = []
1557 otables = [globalopts]
1557 otables = [globalopts]
1558 if cmd:
1558 if cmd:
1559 aliases, entry = cmdutil.findcmd(cmd, table, False)
1559 aliases, entry = cmdutil.findcmd(cmd, table, False)
1560 otables.append(entry[1])
1560 otables.append(entry[1])
1561 for t in otables:
1561 for t in otables:
1562 for o in t:
1562 for o in t:
1563 if "(DEPRECATED)" in o[3]:
1563 if "(DEPRECATED)" in o[3]:
1564 continue
1564 continue
1565 if o[0]:
1565 if o[0]:
1566 options.append('-%s' % o[0])
1566 options.append('-%s' % o[0])
1567 options.append('--%s' % o[1])
1567 options.append('--%s' % o[1])
1568 ui.write("%s\n" % "\n".join(options))
1568 ui.write("%s\n" % "\n".join(options))
1569 return
1569 return
1570
1570
1571 cmdlist = cmdutil.findpossible(cmd, table)
1571 cmdlist = cmdutil.findpossible(cmd, table)
1572 if ui.verbose:
1572 if ui.verbose:
1573 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1573 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1574 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1574 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1575
1575
1576 @command('debugdag',
1576 @command('debugdag',
1577 [('t', 'tags', None, _('use tags as labels')),
1577 [('t', 'tags', None, _('use tags as labels')),
1578 ('b', 'branches', None, _('annotate with branch names')),
1578 ('b', 'branches', None, _('annotate with branch names')),
1579 ('', 'dots', None, _('use dots for runs')),
1579 ('', 'dots', None, _('use dots for runs')),
1580 ('s', 'spaces', None, _('separate elements by spaces'))],
1580 ('s', 'spaces', None, _('separate elements by spaces'))],
1581 _('[OPTION]... [FILE [REV]...]'))
1581 _('[OPTION]... [FILE [REV]...]'))
1582 def debugdag(ui, repo, file_=None, *revs, **opts):
1582 def debugdag(ui, repo, file_=None, *revs, **opts):
1583 """format the changelog or an index DAG as a concise textual description
1583 """format the changelog or an index DAG as a concise textual description
1584
1584
1585 If you pass a revlog index, the revlog's DAG is emitted. If you list
1585 If you pass a revlog index, the revlog's DAG is emitted. If you list
1586 revision numbers, they get labelled in the output as rN.
1586 revision numbers, they get labelled in the output as rN.
1587
1587
1588 Otherwise, the changelog DAG of the current repo is emitted.
1588 Otherwise, the changelog DAG of the current repo is emitted.
1589 """
1589 """
1590 spaces = opts.get('spaces')
1590 spaces = opts.get('spaces')
1591 dots = opts.get('dots')
1591 dots = opts.get('dots')
1592 if file_:
1592 if file_:
1593 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1593 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1594 revs = set((int(r) for r in revs))
1594 revs = set((int(r) for r in revs))
1595 def events():
1595 def events():
1596 for r in rlog:
1596 for r in rlog:
1597 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1597 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1598 if r in revs:
1598 if r in revs:
1599 yield 'l', (r, "r%i" % r)
1599 yield 'l', (r, "r%i" % r)
1600 elif repo:
1600 elif repo:
1601 cl = repo.changelog
1601 cl = repo.changelog
1602 tags = opts.get('tags')
1602 tags = opts.get('tags')
1603 branches = opts.get('branches')
1603 branches = opts.get('branches')
1604 if tags:
1604 if tags:
1605 labels = {}
1605 labels = {}
1606 for l, n in repo.tags().items():
1606 for l, n in repo.tags().items():
1607 labels.setdefault(cl.rev(n), []).append(l)
1607 labels.setdefault(cl.rev(n), []).append(l)
1608 def events():
1608 def events():
1609 b = "default"
1609 b = "default"
1610 for r in cl:
1610 for r in cl:
1611 if branches:
1611 if branches:
1612 newb = cl.read(cl.node(r))[5]['branch']
1612 newb = cl.read(cl.node(r))[5]['branch']
1613 if newb != b:
1613 if newb != b:
1614 yield 'a', newb
1614 yield 'a', newb
1615 b = newb
1615 b = newb
1616 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1616 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1617 if tags:
1617 if tags:
1618 ls = labels.get(r)
1618 ls = labels.get(r)
1619 if ls:
1619 if ls:
1620 for l in ls:
1620 for l in ls:
1621 yield 'l', (r, l)
1621 yield 'l', (r, l)
1622 else:
1622 else:
1623 raise util.Abort(_('need repo for changelog dag'))
1623 raise util.Abort(_('need repo for changelog dag'))
1624
1624
1625 for line in dagparser.dagtextlines(events(),
1625 for line in dagparser.dagtextlines(events(),
1626 addspaces=spaces,
1626 addspaces=spaces,
1627 wraplabels=True,
1627 wraplabels=True,
1628 wrapannotations=True,
1628 wrapannotations=True,
1629 wrapnonlinear=dots,
1629 wrapnonlinear=dots,
1630 usedots=dots,
1630 usedots=dots,
1631 maxlinewidth=70):
1631 maxlinewidth=70):
1632 ui.write(line)
1632 ui.write(line)
1633 ui.write("\n")
1633 ui.write("\n")
1634
1634
1635 @command('debugdata',
1635 @command('debugdata',
1636 [('c', 'changelog', False, _('open changelog')),
1636 [('c', 'changelog', False, _('open changelog')),
1637 ('m', 'manifest', False, _('open manifest'))],
1637 ('m', 'manifest', False, _('open manifest'))],
1638 _('-c|-m|FILE REV'))
1638 _('-c|-m|FILE REV'))
1639 def debugdata(ui, repo, file_, rev = None, **opts):
1639 def debugdata(ui, repo, file_, rev = None, **opts):
1640 """dump the contents of a data file revision"""
1640 """dump the contents of a data file revision"""
1641 if opts.get('changelog') or opts.get('manifest'):
1641 if opts.get('changelog') or opts.get('manifest'):
1642 file_, rev = None, file_
1642 file_, rev = None, file_
1643 elif rev is None:
1643 elif rev is None:
1644 raise error.CommandError('debugdata', _('invalid arguments'))
1644 raise error.CommandError('debugdata', _('invalid arguments'))
1645 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1645 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1646 try:
1646 try:
1647 ui.write(r.revision(r.lookup(rev)))
1647 ui.write(r.revision(r.lookup(rev)))
1648 except KeyError:
1648 except KeyError:
1649 raise util.Abort(_('invalid revision identifier %s') % rev)
1649 raise util.Abort(_('invalid revision identifier %s') % rev)
1650
1650
1651 @command('debugdate',
1651 @command('debugdate',
1652 [('e', 'extended', None, _('try extended date formats'))],
1652 [('e', 'extended', None, _('try extended date formats'))],
1653 _('[-e] DATE [RANGE]'))
1653 _('[-e] DATE [RANGE]'))
1654 def debugdate(ui, date, range=None, **opts):
1654 def debugdate(ui, date, range=None, **opts):
1655 """parse and display a date"""
1655 """parse and display a date"""
1656 if opts["extended"]:
1656 if opts["extended"]:
1657 d = util.parsedate(date, util.extendeddateformats)
1657 d = util.parsedate(date, util.extendeddateformats)
1658 else:
1658 else:
1659 d = util.parsedate(date)
1659 d = util.parsedate(date)
1660 ui.write("internal: %s %s\n" % d)
1660 ui.write("internal: %s %s\n" % d)
1661 ui.write("standard: %s\n" % util.datestr(d))
1661 ui.write("standard: %s\n" % util.datestr(d))
1662 if range:
1662 if range:
1663 m = util.matchdate(range)
1663 m = util.matchdate(range)
1664 ui.write("match: %s\n" % m(d[0]))
1664 ui.write("match: %s\n" % m(d[0]))
1665
1665
1666 @command('debugdiscovery',
1666 @command('debugdiscovery',
1667 [('', 'old', None, _('use old-style discovery')),
1667 [('', 'old', None, _('use old-style discovery')),
1668 ('', 'nonheads', None,
1668 ('', 'nonheads', None,
1669 _('use old-style discovery with non-heads included')),
1669 _('use old-style discovery with non-heads included')),
1670 ] + remoteopts,
1670 ] + remoteopts,
1671 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1671 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1672 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1672 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1673 """runs the changeset discovery protocol in isolation"""
1673 """runs the changeset discovery protocol in isolation"""
1674 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1674 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1675 remote = hg.peer(repo, opts, remoteurl)
1675 remote = hg.peer(repo, opts, remoteurl)
1676 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1676 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1677
1677
1678 # make sure tests are repeatable
1678 # make sure tests are repeatable
1679 random.seed(12323)
1679 random.seed(12323)
1680
1680
1681 def doit(localheads, remoteheads):
1681 def doit(localheads, remoteheads):
1682 if opts.get('old'):
1682 if opts.get('old'):
1683 if localheads:
1683 if localheads:
1684 raise util.Abort('cannot use localheads with old style discovery')
1684 raise util.Abort('cannot use localheads with old style discovery')
1685 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1685 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1686 force=True)
1686 force=True)
1687 common = set(common)
1687 common = set(common)
1688 if not opts.get('nonheads'):
1688 if not opts.get('nonheads'):
1689 ui.write("unpruned common: %s\n" % " ".join([short(n)
1689 ui.write("unpruned common: %s\n" % " ".join([short(n)
1690 for n in common]))
1690 for n in common]))
1691 dag = dagutil.revlogdag(repo.changelog)
1691 dag = dagutil.revlogdag(repo.changelog)
1692 all = dag.ancestorset(dag.internalizeall(common))
1692 all = dag.ancestorset(dag.internalizeall(common))
1693 common = dag.externalizeall(dag.headsetofconnecteds(all))
1693 common = dag.externalizeall(dag.headsetofconnecteds(all))
1694 else:
1694 else:
1695 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1695 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1696 common = set(common)
1696 common = set(common)
1697 rheads = set(hds)
1697 rheads = set(hds)
1698 lheads = set(repo.heads())
1698 lheads = set(repo.heads())
1699 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1699 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1700 if lheads <= common:
1700 if lheads <= common:
1701 ui.write("local is subset\n")
1701 ui.write("local is subset\n")
1702 elif rheads <= common:
1702 elif rheads <= common:
1703 ui.write("remote is subset\n")
1703 ui.write("remote is subset\n")
1704
1704
1705 serverlogs = opts.get('serverlog')
1705 serverlogs = opts.get('serverlog')
1706 if serverlogs:
1706 if serverlogs:
1707 for filename in serverlogs:
1707 for filename in serverlogs:
1708 logfile = open(filename, 'r')
1708 logfile = open(filename, 'r')
1709 try:
1709 try:
1710 line = logfile.readline()
1710 line = logfile.readline()
1711 while line:
1711 while line:
1712 parts = line.strip().split(';')
1712 parts = line.strip().split(';')
1713 op = parts[1]
1713 op = parts[1]
1714 if op == 'cg':
1714 if op == 'cg':
1715 pass
1715 pass
1716 elif op == 'cgss':
1716 elif op == 'cgss':
1717 doit(parts[2].split(' '), parts[3].split(' '))
1717 doit(parts[2].split(' '), parts[3].split(' '))
1718 elif op == 'unb':
1718 elif op == 'unb':
1719 doit(parts[3].split(' '), parts[2].split(' '))
1719 doit(parts[3].split(' '), parts[2].split(' '))
1720 line = logfile.readline()
1720 line = logfile.readline()
1721 finally:
1721 finally:
1722 logfile.close()
1722 logfile.close()
1723
1723
1724 else:
1724 else:
1725 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1725 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1726 opts.get('remote_head'))
1726 opts.get('remote_head'))
1727 localrevs = opts.get('local_head')
1727 localrevs = opts.get('local_head')
1728 doit(localrevs, remoterevs)
1728 doit(localrevs, remoterevs)
1729
1729
1730 @command('debugfileset', [], ('REVSPEC'))
1730 @command('debugfileset', [], ('REVSPEC'))
1731 def debugfileset(ui, repo, expr):
1731 def debugfileset(ui, repo, expr):
1732 '''parse and apply a fileset specification'''
1732 '''parse and apply a fileset specification'''
1733 if ui.verbose:
1733 if ui.verbose:
1734 tree = fileset.parse(expr)[0]
1734 tree = fileset.parse(expr)[0]
1735 ui.note(tree, "\n")
1735 ui.note(tree, "\n")
1736
1736
1737 for f in fileset.getfileset(repo[None], expr):
1737 for f in fileset.getfileset(repo[None], expr):
1738 ui.write("%s\n" % f)
1738 ui.write("%s\n" % f)
1739
1739
1740 @command('debugfsinfo', [], _('[PATH]'))
1740 @command('debugfsinfo', [], _('[PATH]'))
1741 def debugfsinfo(ui, path = "."):
1741 def debugfsinfo(ui, path = "."):
1742 """show information detected about current filesystem"""
1742 """show information detected about current filesystem"""
1743 util.writefile('.debugfsinfo', '')
1743 util.writefile('.debugfsinfo', '')
1744 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1744 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1745 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1745 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1746 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1746 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1747 and 'yes' or 'no'))
1747 and 'yes' or 'no'))
1748 os.unlink('.debugfsinfo')
1748 os.unlink('.debugfsinfo')
1749
1749
1750 @command('debuggetbundle',
1750 @command('debuggetbundle',
1751 [('H', 'head', [], _('id of head node'), _('ID')),
1751 [('H', 'head', [], _('id of head node'), _('ID')),
1752 ('C', 'common', [], _('id of common node'), _('ID')),
1752 ('C', 'common', [], _('id of common node'), _('ID')),
1753 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1753 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1754 _('REPO FILE [-H|-C ID]...'))
1754 _('REPO FILE [-H|-C ID]...'))
1755 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1755 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1756 """retrieves a bundle from a repo
1756 """retrieves a bundle from a repo
1757
1757
1758 Every ID must be a full-length hex node id string. Saves the bundle to the
1758 Every ID must be a full-length hex node id string. Saves the bundle to the
1759 given file.
1759 given file.
1760 """
1760 """
1761 repo = hg.peer(ui, opts, repopath)
1761 repo = hg.peer(ui, opts, repopath)
1762 if not repo.capable('getbundle'):
1762 if not repo.capable('getbundle'):
1763 raise util.Abort("getbundle() not supported by target repository")
1763 raise util.Abort("getbundle() not supported by target repository")
1764 args = {}
1764 args = {}
1765 if common:
1765 if common:
1766 args['common'] = [bin(s) for s in common]
1766 args['common'] = [bin(s) for s in common]
1767 if head:
1767 if head:
1768 args['heads'] = [bin(s) for s in head]
1768 args['heads'] = [bin(s) for s in head]
1769 bundle = repo.getbundle('debug', **args)
1769 bundle = repo.getbundle('debug', **args)
1770
1770
1771 bundletype = opts.get('type', 'bzip2').lower()
1771 bundletype = opts.get('type', 'bzip2').lower()
1772 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1772 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1773 bundletype = btypes.get(bundletype)
1773 bundletype = btypes.get(bundletype)
1774 if bundletype not in changegroup.bundletypes:
1774 if bundletype not in changegroup.bundletypes:
1775 raise util.Abort(_('unknown bundle type specified with --type'))
1775 raise util.Abort(_('unknown bundle type specified with --type'))
1776 changegroup.writebundle(bundle, bundlepath, bundletype)
1776 changegroup.writebundle(bundle, bundlepath, bundletype)
1777
1777
1778 @command('debugignore', [], '')
1778 @command('debugignore', [], '')
1779 def debugignore(ui, repo, *values, **opts):
1779 def debugignore(ui, repo, *values, **opts):
1780 """display the combined ignore pattern"""
1780 """display the combined ignore pattern"""
1781 ignore = repo.dirstate._ignore
1781 ignore = repo.dirstate._ignore
1782 includepat = getattr(ignore, 'includepat', None)
1782 includepat = getattr(ignore, 'includepat', None)
1783 if includepat is not None:
1783 if includepat is not None:
1784 ui.write("%s\n" % includepat)
1784 ui.write("%s\n" % includepat)
1785 else:
1785 else:
1786 raise util.Abort(_("no ignore patterns found"))
1786 raise util.Abort(_("no ignore patterns found"))
1787
1787
1788 @command('debugindex',
1788 @command('debugindex',
1789 [('c', 'changelog', False, _('open changelog')),
1789 [('c', 'changelog', False, _('open changelog')),
1790 ('m', 'manifest', False, _('open manifest')),
1790 ('m', 'manifest', False, _('open manifest')),
1791 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1791 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1792 _('[-f FORMAT] -c|-m|FILE'))
1792 _('[-f FORMAT] -c|-m|FILE'))
1793 def debugindex(ui, repo, file_ = None, **opts):
1793 def debugindex(ui, repo, file_ = None, **opts):
1794 """dump the contents of an index file"""
1794 """dump the contents of an index file"""
1795 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1795 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1796 format = opts.get('format', 0)
1796 format = opts.get('format', 0)
1797 if format not in (0, 1):
1797 if format not in (0, 1):
1798 raise util.Abort(_("unknown format %d") % format)
1798 raise util.Abort(_("unknown format %d") % format)
1799
1799
1800 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1800 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1801 if generaldelta:
1801 if generaldelta:
1802 basehdr = ' delta'
1802 basehdr = ' delta'
1803 else:
1803 else:
1804 basehdr = ' base'
1804 basehdr = ' base'
1805
1805
1806 if format == 0:
1806 if format == 0:
1807 ui.write(" rev offset length " + basehdr + " linkrev"
1807 ui.write(" rev offset length " + basehdr + " linkrev"
1808 " nodeid p1 p2\n")
1808 " nodeid p1 p2\n")
1809 elif format == 1:
1809 elif format == 1:
1810 ui.write(" rev flag offset length"
1810 ui.write(" rev flag offset length"
1811 " size " + basehdr + " link p1 p2 nodeid\n")
1811 " size " + basehdr + " link p1 p2 nodeid\n")
1812
1812
1813 for i in r:
1813 for i in r:
1814 node = r.node(i)
1814 node = r.node(i)
1815 if generaldelta:
1815 if generaldelta:
1816 base = r.deltaparent(i)
1816 base = r.deltaparent(i)
1817 else:
1817 else:
1818 base = r.chainbase(i)
1818 base = r.chainbase(i)
1819 if format == 0:
1819 if format == 0:
1820 try:
1820 try:
1821 pp = r.parents(node)
1821 pp = r.parents(node)
1822 except:
1822 except:
1823 pp = [nullid, nullid]
1823 pp = [nullid, nullid]
1824 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1824 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1825 i, r.start(i), r.length(i), base, r.linkrev(i),
1825 i, r.start(i), r.length(i), base, r.linkrev(i),
1826 short(node), short(pp[0]), short(pp[1])))
1826 short(node), short(pp[0]), short(pp[1])))
1827 elif format == 1:
1827 elif format == 1:
1828 pr = r.parentrevs(i)
1828 pr = r.parentrevs(i)
1829 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1829 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1830 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1830 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1831 base, r.linkrev(i), pr[0], pr[1], short(node)))
1831 base, r.linkrev(i), pr[0], pr[1], short(node)))
1832
1832
1833 @command('debugindexdot', [], _('FILE'))
1833 @command('debugindexdot', [], _('FILE'))
1834 def debugindexdot(ui, repo, file_):
1834 def debugindexdot(ui, repo, file_):
1835 """dump an index DAG as a graphviz dot file"""
1835 """dump an index DAG as a graphviz dot file"""
1836 r = None
1836 r = None
1837 if repo:
1837 if repo:
1838 filelog = repo.file(file_)
1838 filelog = repo.file(file_)
1839 if len(filelog):
1839 if len(filelog):
1840 r = filelog
1840 r = filelog
1841 if not r:
1841 if not r:
1842 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1842 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1843 ui.write("digraph G {\n")
1843 ui.write("digraph G {\n")
1844 for i in r:
1844 for i in r:
1845 node = r.node(i)
1845 node = r.node(i)
1846 pp = r.parents(node)
1846 pp = r.parents(node)
1847 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1847 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1848 if pp[1] != nullid:
1848 if pp[1] != nullid:
1849 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1849 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1850 ui.write("}\n")
1850 ui.write("}\n")
1851
1851
1852 @command('debuginstall', [], '')
1852 @command('debuginstall', [], '')
1853 def debuginstall(ui):
1853 def debuginstall(ui):
1854 '''test Mercurial installation
1854 '''test Mercurial installation
1855
1855
1856 Returns 0 on success.
1856 Returns 0 on success.
1857 '''
1857 '''
1858
1858
1859 def writetemp(contents):
1859 def writetemp(contents):
1860 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1860 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1861 f = os.fdopen(fd, "wb")
1861 f = os.fdopen(fd, "wb")
1862 f.write(contents)
1862 f.write(contents)
1863 f.close()
1863 f.close()
1864 return name
1864 return name
1865
1865
1866 problems = 0
1866 problems = 0
1867
1867
1868 # encoding
1868 # encoding
1869 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1869 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1870 try:
1870 try:
1871 encoding.fromlocal("test")
1871 encoding.fromlocal("test")
1872 except util.Abort, inst:
1872 except util.Abort, inst:
1873 ui.write(" %s\n" % inst)
1873 ui.write(" %s\n" % inst)
1874 ui.write(_(" (check that your locale is properly set)\n"))
1874 ui.write(_(" (check that your locale is properly set)\n"))
1875 problems += 1
1875 problems += 1
1876
1876
1877 # compiled modules
1877 # compiled modules
1878 ui.status(_("Checking installed modules (%s)...\n")
1878 ui.status(_("Checking installed modules (%s)...\n")
1879 % os.path.dirname(__file__))
1879 % os.path.dirname(__file__))
1880 try:
1880 try:
1881 import bdiff, mpatch, base85, osutil
1881 import bdiff, mpatch, base85, osutil
1882 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1882 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1883 except Exception, inst:
1883 except Exception, inst:
1884 ui.write(" %s\n" % inst)
1884 ui.write(" %s\n" % inst)
1885 ui.write(_(" One or more extensions could not be found"))
1885 ui.write(_(" One or more extensions could not be found"))
1886 ui.write(_(" (check that you compiled the extensions)\n"))
1886 ui.write(_(" (check that you compiled the extensions)\n"))
1887 problems += 1
1887 problems += 1
1888
1888
1889 # templates
1889 # templates
1890 import templater
1890 import templater
1891 p = templater.templatepath()
1891 p = templater.templatepath()
1892 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1892 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1893 try:
1893 try:
1894 templater.templater(templater.templatepath("map-cmdline.default"))
1894 templater.templater(templater.templatepath("map-cmdline.default"))
1895 except Exception, inst:
1895 except Exception, inst:
1896 ui.write(" %s\n" % inst)
1896 ui.write(" %s\n" % inst)
1897 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1897 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1898 problems += 1
1898 problems += 1
1899
1899
1900 # editor
1900 # editor
1901 ui.status(_("Checking commit editor...\n"))
1901 ui.status(_("Checking commit editor...\n"))
1902 editor = ui.geteditor()
1902 editor = ui.geteditor()
1903 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1903 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1904 if not cmdpath:
1904 if not cmdpath:
1905 if editor == 'vi':
1905 if editor == 'vi':
1906 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1906 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1907 ui.write(_(" (specify a commit editor in your configuration"
1907 ui.write(_(" (specify a commit editor in your configuration"
1908 " file)\n"))
1908 " file)\n"))
1909 else:
1909 else:
1910 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1910 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1911 ui.write(_(" (specify a commit editor in your configuration"
1911 ui.write(_(" (specify a commit editor in your configuration"
1912 " file)\n"))
1912 " file)\n"))
1913 problems += 1
1913 problems += 1
1914
1914
1915 # check username
1915 # check username
1916 ui.status(_("Checking username...\n"))
1916 ui.status(_("Checking username...\n"))
1917 try:
1917 try:
1918 ui.username()
1918 ui.username()
1919 except util.Abort, e:
1919 except util.Abort, e:
1920 ui.write(" %s\n" % e)
1920 ui.write(" %s\n" % e)
1921 ui.write(_(" (specify a username in your configuration file)\n"))
1921 ui.write(_(" (specify a username in your configuration file)\n"))
1922 problems += 1
1922 problems += 1
1923
1923
1924 if not problems:
1924 if not problems:
1925 ui.status(_("No problems detected\n"))
1925 ui.status(_("No problems detected\n"))
1926 else:
1926 else:
1927 ui.write(_("%s problems detected,"
1927 ui.write(_("%s problems detected,"
1928 " please check your install!\n") % problems)
1928 " please check your install!\n") % problems)
1929
1929
1930 return problems
1930 return problems
1931
1931
1932 @command('debugknown', [], _('REPO ID...'))
1932 @command('debugknown', [], _('REPO ID...'))
1933 def debugknown(ui, repopath, *ids, **opts):
1933 def debugknown(ui, repopath, *ids, **opts):
1934 """test whether node ids are known to a repo
1934 """test whether node ids are known to a repo
1935
1935
1936 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1936 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1937 indicating unknown/known.
1937 indicating unknown/known.
1938 """
1938 """
1939 repo = hg.peer(ui, opts, repopath)
1939 repo = hg.peer(ui, opts, repopath)
1940 if not repo.capable('known'):
1940 if not repo.capable('known'):
1941 raise util.Abort("known() not supported by target repository")
1941 raise util.Abort("known() not supported by target repository")
1942 flags = repo.known([bin(s) for s in ids])
1942 flags = repo.known([bin(s) for s in ids])
1943 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1943 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1944
1944
1945 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1945 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1946 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1946 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1947 '''access the pushkey key/value protocol
1947 '''access the pushkey key/value protocol
1948
1948
1949 With two args, list the keys in the given namespace.
1949 With two args, list the keys in the given namespace.
1950
1950
1951 With five args, set a key to new if it currently is set to old.
1951 With five args, set a key to new if it currently is set to old.
1952 Reports success or failure.
1952 Reports success or failure.
1953 '''
1953 '''
1954
1954
1955 target = hg.peer(ui, {}, repopath)
1955 target = hg.peer(ui, {}, repopath)
1956 if keyinfo:
1956 if keyinfo:
1957 key, old, new = keyinfo
1957 key, old, new = keyinfo
1958 r = target.pushkey(namespace, key, old, new)
1958 r = target.pushkey(namespace, key, old, new)
1959 ui.status(str(r) + '\n')
1959 ui.status(str(r) + '\n')
1960 return not r
1960 return not r
1961 else:
1961 else:
1962 for k, v in target.listkeys(namespace).iteritems():
1962 for k, v in target.listkeys(namespace).iteritems():
1963 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1963 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1964 v.encode('string-escape')))
1964 v.encode('string-escape')))
1965
1965
1966 @command('debugpvec', [], _('A B'))
1967 def debugpvec(ui, repo, a, b=None):
1968 ca = scmutil.revsingle(repo, a)
1969 cb = scmutil.revsingle(repo, b)
1970 pa = pvec.ctxpvec(ca)
1971 pb = pvec.ctxpvec(cb)
1972 if pa == pb:
1973 rel = "="
1974 elif pa > pb:
1975 rel = ">"
1976 elif pa < pb:
1977 rel = "<"
1978 elif pa | pb:
1979 rel = "|"
1980 ui.write(_("a: %s\n") % pa)
1981 ui.write(_("b: %s\n") % pb)
1982 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1983 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1984 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1985 pa.distance(pb), rel))
1986
1966 @command('debugrebuildstate',
1987 @command('debugrebuildstate',
1967 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1988 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1968 _('[-r REV] [REV]'))
1989 _('[-r REV] [REV]'))
1969 def debugrebuildstate(ui, repo, rev="tip"):
1990 def debugrebuildstate(ui, repo, rev="tip"):
1970 """rebuild the dirstate as it would look like for the given revision"""
1991 """rebuild the dirstate as it would look like for the given revision"""
1971 ctx = scmutil.revsingle(repo, rev)
1992 ctx = scmutil.revsingle(repo, rev)
1972 wlock = repo.wlock()
1993 wlock = repo.wlock()
1973 try:
1994 try:
1974 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1995 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1975 finally:
1996 finally:
1976 wlock.release()
1997 wlock.release()
1977
1998
1978 @command('debugrename',
1999 @command('debugrename',
1979 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2000 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1980 _('[-r REV] FILE'))
2001 _('[-r REV] FILE'))
1981 def debugrename(ui, repo, file1, *pats, **opts):
2002 def debugrename(ui, repo, file1, *pats, **opts):
1982 """dump rename information"""
2003 """dump rename information"""
1983
2004
1984 ctx = scmutil.revsingle(repo, opts.get('rev'))
2005 ctx = scmutil.revsingle(repo, opts.get('rev'))
1985 m = scmutil.match(ctx, (file1,) + pats, opts)
2006 m = scmutil.match(ctx, (file1,) + pats, opts)
1986 for abs in ctx.walk(m):
2007 for abs in ctx.walk(m):
1987 fctx = ctx[abs]
2008 fctx = ctx[abs]
1988 o = fctx.filelog().renamed(fctx.filenode())
2009 o = fctx.filelog().renamed(fctx.filenode())
1989 rel = m.rel(abs)
2010 rel = m.rel(abs)
1990 if o:
2011 if o:
1991 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2012 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1992 else:
2013 else:
1993 ui.write(_("%s not renamed\n") % rel)
2014 ui.write(_("%s not renamed\n") % rel)
1994
2015
1995 @command('debugrevlog',
2016 @command('debugrevlog',
1996 [('c', 'changelog', False, _('open changelog')),
2017 [('c', 'changelog', False, _('open changelog')),
1997 ('m', 'manifest', False, _('open manifest')),
2018 ('m', 'manifest', False, _('open manifest')),
1998 ('d', 'dump', False, _('dump index data'))],
2019 ('d', 'dump', False, _('dump index data'))],
1999 _('-c|-m|FILE'))
2020 _('-c|-m|FILE'))
2000 def debugrevlog(ui, repo, file_ = None, **opts):
2021 def debugrevlog(ui, repo, file_ = None, **opts):
2001 """show data and statistics about a revlog"""
2022 """show data and statistics about a revlog"""
2002 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2023 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2003
2024
2004 if opts.get("dump"):
2025 if opts.get("dump"):
2005 numrevs = len(r)
2026 numrevs = len(r)
2006 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2027 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2007 " rawsize totalsize compression heads\n")
2028 " rawsize totalsize compression heads\n")
2008 ts = 0
2029 ts = 0
2009 heads = set()
2030 heads = set()
2010 for rev in xrange(numrevs):
2031 for rev in xrange(numrevs):
2011 dbase = r.deltaparent(rev)
2032 dbase = r.deltaparent(rev)
2012 if dbase == -1:
2033 if dbase == -1:
2013 dbase = rev
2034 dbase = rev
2014 cbase = r.chainbase(rev)
2035 cbase = r.chainbase(rev)
2015 p1, p2 = r.parentrevs(rev)
2036 p1, p2 = r.parentrevs(rev)
2016 rs = r.rawsize(rev)
2037 rs = r.rawsize(rev)
2017 ts = ts + rs
2038 ts = ts + rs
2018 heads -= set(r.parentrevs(rev))
2039 heads -= set(r.parentrevs(rev))
2019 heads.add(rev)
2040 heads.add(rev)
2020 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2041 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2021 (rev, p1, p2, r.start(rev), r.end(rev),
2042 (rev, p1, p2, r.start(rev), r.end(rev),
2022 r.start(dbase), r.start(cbase),
2043 r.start(dbase), r.start(cbase),
2023 r.start(p1), r.start(p2),
2044 r.start(p1), r.start(p2),
2024 rs, ts, ts / r.end(rev), len(heads)))
2045 rs, ts, ts / r.end(rev), len(heads)))
2025 return 0
2046 return 0
2026
2047
2027 v = r.version
2048 v = r.version
2028 format = v & 0xFFFF
2049 format = v & 0xFFFF
2029 flags = []
2050 flags = []
2030 gdelta = False
2051 gdelta = False
2031 if v & revlog.REVLOGNGINLINEDATA:
2052 if v & revlog.REVLOGNGINLINEDATA:
2032 flags.append('inline')
2053 flags.append('inline')
2033 if v & revlog.REVLOGGENERALDELTA:
2054 if v & revlog.REVLOGGENERALDELTA:
2034 gdelta = True
2055 gdelta = True
2035 flags.append('generaldelta')
2056 flags.append('generaldelta')
2036 if not flags:
2057 if not flags:
2037 flags = ['(none)']
2058 flags = ['(none)']
2038
2059
2039 nummerges = 0
2060 nummerges = 0
2040 numfull = 0
2061 numfull = 0
2041 numprev = 0
2062 numprev = 0
2042 nump1 = 0
2063 nump1 = 0
2043 nump2 = 0
2064 nump2 = 0
2044 numother = 0
2065 numother = 0
2045 nump1prev = 0
2066 nump1prev = 0
2046 nump2prev = 0
2067 nump2prev = 0
2047 chainlengths = []
2068 chainlengths = []
2048
2069
2049 datasize = [None, 0, 0L]
2070 datasize = [None, 0, 0L]
2050 fullsize = [None, 0, 0L]
2071 fullsize = [None, 0, 0L]
2051 deltasize = [None, 0, 0L]
2072 deltasize = [None, 0, 0L]
2052
2073
2053 def addsize(size, l):
2074 def addsize(size, l):
2054 if l[0] is None or size < l[0]:
2075 if l[0] is None or size < l[0]:
2055 l[0] = size
2076 l[0] = size
2056 if size > l[1]:
2077 if size > l[1]:
2057 l[1] = size
2078 l[1] = size
2058 l[2] += size
2079 l[2] += size
2059
2080
2060 numrevs = len(r)
2081 numrevs = len(r)
2061 for rev in xrange(numrevs):
2082 for rev in xrange(numrevs):
2062 p1, p2 = r.parentrevs(rev)
2083 p1, p2 = r.parentrevs(rev)
2063 delta = r.deltaparent(rev)
2084 delta = r.deltaparent(rev)
2064 if format > 0:
2085 if format > 0:
2065 addsize(r.rawsize(rev), datasize)
2086 addsize(r.rawsize(rev), datasize)
2066 if p2 != nullrev:
2087 if p2 != nullrev:
2067 nummerges += 1
2088 nummerges += 1
2068 size = r.length(rev)
2089 size = r.length(rev)
2069 if delta == nullrev:
2090 if delta == nullrev:
2070 chainlengths.append(0)
2091 chainlengths.append(0)
2071 numfull += 1
2092 numfull += 1
2072 addsize(size, fullsize)
2093 addsize(size, fullsize)
2073 else:
2094 else:
2074 chainlengths.append(chainlengths[delta] + 1)
2095 chainlengths.append(chainlengths[delta] + 1)
2075 addsize(size, deltasize)
2096 addsize(size, deltasize)
2076 if delta == rev - 1:
2097 if delta == rev - 1:
2077 numprev += 1
2098 numprev += 1
2078 if delta == p1:
2099 if delta == p1:
2079 nump1prev += 1
2100 nump1prev += 1
2080 elif delta == p2:
2101 elif delta == p2:
2081 nump2prev += 1
2102 nump2prev += 1
2082 elif delta == p1:
2103 elif delta == p1:
2083 nump1 += 1
2104 nump1 += 1
2084 elif delta == p2:
2105 elif delta == p2:
2085 nump2 += 1
2106 nump2 += 1
2086 elif delta != nullrev:
2107 elif delta != nullrev:
2087 numother += 1
2108 numother += 1
2088
2109
2089 numdeltas = numrevs - numfull
2110 numdeltas = numrevs - numfull
2090 numoprev = numprev - nump1prev - nump2prev
2111 numoprev = numprev - nump1prev - nump2prev
2091 totalrawsize = datasize[2]
2112 totalrawsize = datasize[2]
2092 datasize[2] /= numrevs
2113 datasize[2] /= numrevs
2093 fulltotal = fullsize[2]
2114 fulltotal = fullsize[2]
2094 fullsize[2] /= numfull
2115 fullsize[2] /= numfull
2095 deltatotal = deltasize[2]
2116 deltatotal = deltasize[2]
2096 deltasize[2] /= numrevs - numfull
2117 deltasize[2] /= numrevs - numfull
2097 totalsize = fulltotal + deltatotal
2118 totalsize = fulltotal + deltatotal
2098 avgchainlen = sum(chainlengths) / numrevs
2119 avgchainlen = sum(chainlengths) / numrevs
2099 compratio = totalrawsize / totalsize
2120 compratio = totalrawsize / totalsize
2100
2121
2101 basedfmtstr = '%%%dd\n'
2122 basedfmtstr = '%%%dd\n'
2102 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2123 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2103
2124
2104 def dfmtstr(max):
2125 def dfmtstr(max):
2105 return basedfmtstr % len(str(max))
2126 return basedfmtstr % len(str(max))
2106 def pcfmtstr(max, padding=0):
2127 def pcfmtstr(max, padding=0):
2107 return basepcfmtstr % (len(str(max)), ' ' * padding)
2128 return basepcfmtstr % (len(str(max)), ' ' * padding)
2108
2129
2109 def pcfmt(value, total):
2130 def pcfmt(value, total):
2110 return (value, 100 * float(value) / total)
2131 return (value, 100 * float(value) / total)
2111
2132
2112 ui.write('format : %d\n' % format)
2133 ui.write('format : %d\n' % format)
2113 ui.write('flags : %s\n' % ', '.join(flags))
2134 ui.write('flags : %s\n' % ', '.join(flags))
2114
2135
2115 ui.write('\n')
2136 ui.write('\n')
2116 fmt = pcfmtstr(totalsize)
2137 fmt = pcfmtstr(totalsize)
2117 fmt2 = dfmtstr(totalsize)
2138 fmt2 = dfmtstr(totalsize)
2118 ui.write('revisions : ' + fmt2 % numrevs)
2139 ui.write('revisions : ' + fmt2 % numrevs)
2119 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2140 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2120 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2141 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2121 ui.write('revisions : ' + fmt2 % numrevs)
2142 ui.write('revisions : ' + fmt2 % numrevs)
2122 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2143 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2123 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2144 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2124 ui.write('revision size : ' + fmt2 % totalsize)
2145 ui.write('revision size : ' + fmt2 % totalsize)
2125 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2146 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2126 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2147 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2127
2148
2128 ui.write('\n')
2149 ui.write('\n')
2129 fmt = dfmtstr(max(avgchainlen, compratio))
2150 fmt = dfmtstr(max(avgchainlen, compratio))
2130 ui.write('avg chain length : ' + fmt % avgchainlen)
2151 ui.write('avg chain length : ' + fmt % avgchainlen)
2131 ui.write('compression ratio : ' + fmt % compratio)
2152 ui.write('compression ratio : ' + fmt % compratio)
2132
2153
2133 if format > 0:
2154 if format > 0:
2134 ui.write('\n')
2155 ui.write('\n')
2135 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2156 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2136 % tuple(datasize))
2157 % tuple(datasize))
2137 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2158 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2138 % tuple(fullsize))
2159 % tuple(fullsize))
2139 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2160 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2140 % tuple(deltasize))
2161 % tuple(deltasize))
2141
2162
2142 if numdeltas > 0:
2163 if numdeltas > 0:
2143 ui.write('\n')
2164 ui.write('\n')
2144 fmt = pcfmtstr(numdeltas)
2165 fmt = pcfmtstr(numdeltas)
2145 fmt2 = pcfmtstr(numdeltas, 4)
2166 fmt2 = pcfmtstr(numdeltas, 4)
2146 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2167 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2147 if numprev > 0:
2168 if numprev > 0:
2148 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2169 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2149 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2170 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2150 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2171 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2151 if gdelta:
2172 if gdelta:
2152 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2173 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2153 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2174 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2154 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2175 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2155
2176
2156 @command('debugrevspec', [], ('REVSPEC'))
2177 @command('debugrevspec', [], ('REVSPEC'))
2157 def debugrevspec(ui, repo, expr):
2178 def debugrevspec(ui, repo, expr):
2158 """parse and apply a revision specification
2179 """parse and apply a revision specification
2159
2180
2160 Use --verbose to print the parsed tree before and after aliases
2181 Use --verbose to print the parsed tree before and after aliases
2161 expansion.
2182 expansion.
2162 """
2183 """
2163 if ui.verbose:
2184 if ui.verbose:
2164 tree = revset.parse(expr)[0]
2185 tree = revset.parse(expr)[0]
2165 ui.note(revset.prettyformat(tree), "\n")
2186 ui.note(revset.prettyformat(tree), "\n")
2166 newtree = revset.findaliases(ui, tree)
2187 newtree = revset.findaliases(ui, tree)
2167 if newtree != tree:
2188 if newtree != tree:
2168 ui.note(revset.prettyformat(newtree), "\n")
2189 ui.note(revset.prettyformat(newtree), "\n")
2169 func = revset.match(ui, expr)
2190 func = revset.match(ui, expr)
2170 for c in func(repo, range(len(repo))):
2191 for c in func(repo, range(len(repo))):
2171 ui.write("%s\n" % c)
2192 ui.write("%s\n" % c)
2172
2193
2173 @command('debugsetparents', [], _('REV1 [REV2]'))
2194 @command('debugsetparents', [], _('REV1 [REV2]'))
2174 def debugsetparents(ui, repo, rev1, rev2=None):
2195 def debugsetparents(ui, repo, rev1, rev2=None):
2175 """manually set the parents of the current working directory
2196 """manually set the parents of the current working directory
2176
2197
2177 This is useful for writing repository conversion tools, but should
2198 This is useful for writing repository conversion tools, but should
2178 be used with care.
2199 be used with care.
2179
2200
2180 Returns 0 on success.
2201 Returns 0 on success.
2181 """
2202 """
2182
2203
2183 r1 = scmutil.revsingle(repo, rev1).node()
2204 r1 = scmutil.revsingle(repo, rev1).node()
2184 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2205 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2185
2206
2186 wlock = repo.wlock()
2207 wlock = repo.wlock()
2187 try:
2208 try:
2188 repo.dirstate.setparents(r1, r2)
2209 repo.dirstate.setparents(r1, r2)
2189 finally:
2210 finally:
2190 wlock.release()
2211 wlock.release()
2191
2212
2192 @command('debugstate',
2213 @command('debugstate',
2193 [('', 'nodates', None, _('do not display the saved mtime')),
2214 [('', 'nodates', None, _('do not display the saved mtime')),
2194 ('', 'datesort', None, _('sort by saved mtime'))],
2215 ('', 'datesort', None, _('sort by saved mtime'))],
2195 _('[OPTION]...'))
2216 _('[OPTION]...'))
2196 def debugstate(ui, repo, nodates=None, datesort=None):
2217 def debugstate(ui, repo, nodates=None, datesort=None):
2197 """show the contents of the current dirstate"""
2218 """show the contents of the current dirstate"""
2198 timestr = ""
2219 timestr = ""
2199 showdate = not nodates
2220 showdate = not nodates
2200 if datesort:
2221 if datesort:
2201 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2222 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2202 else:
2223 else:
2203 keyfunc = None # sort by filename
2224 keyfunc = None # sort by filename
2204 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2225 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2205 if showdate:
2226 if showdate:
2206 if ent[3] == -1:
2227 if ent[3] == -1:
2207 # Pad or slice to locale representation
2228 # Pad or slice to locale representation
2208 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2229 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2209 time.localtime(0)))
2230 time.localtime(0)))
2210 timestr = 'unset'
2231 timestr = 'unset'
2211 timestr = (timestr[:locale_len] +
2232 timestr = (timestr[:locale_len] +
2212 ' ' * (locale_len - len(timestr)))
2233 ' ' * (locale_len - len(timestr)))
2213 else:
2234 else:
2214 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2235 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2215 time.localtime(ent[3]))
2236 time.localtime(ent[3]))
2216 if ent[1] & 020000:
2237 if ent[1] & 020000:
2217 mode = 'lnk'
2238 mode = 'lnk'
2218 else:
2239 else:
2219 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2240 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2220 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2241 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2221 for f in repo.dirstate.copies():
2242 for f in repo.dirstate.copies():
2222 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2243 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2223
2244
2224 @command('debugsub',
2245 @command('debugsub',
2225 [('r', 'rev', '',
2246 [('r', 'rev', '',
2226 _('revision to check'), _('REV'))],
2247 _('revision to check'), _('REV'))],
2227 _('[-r REV] [REV]'))
2248 _('[-r REV] [REV]'))
2228 def debugsub(ui, repo, rev=None):
2249 def debugsub(ui, repo, rev=None):
2229 ctx = scmutil.revsingle(repo, rev, None)
2250 ctx = scmutil.revsingle(repo, rev, None)
2230 for k, v in sorted(ctx.substate.items()):
2251 for k, v in sorted(ctx.substate.items()):
2231 ui.write('path %s\n' % k)
2252 ui.write('path %s\n' % k)
2232 ui.write(' source %s\n' % v[0])
2253 ui.write(' source %s\n' % v[0])
2233 ui.write(' revision %s\n' % v[1])
2254 ui.write(' revision %s\n' % v[1])
2234
2255
2235 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2256 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2236 def debugwalk(ui, repo, *pats, **opts):
2257 def debugwalk(ui, repo, *pats, **opts):
2237 """show how files match on given patterns"""
2258 """show how files match on given patterns"""
2238 m = scmutil.match(repo[None], pats, opts)
2259 m = scmutil.match(repo[None], pats, opts)
2239 items = list(repo.walk(m))
2260 items = list(repo.walk(m))
2240 if not items:
2261 if not items:
2241 return
2262 return
2242 fmt = 'f %%-%ds %%-%ds %%s' % (
2263 fmt = 'f %%-%ds %%-%ds %%s' % (
2243 max([len(abs) for abs in items]),
2264 max([len(abs) for abs in items]),
2244 max([len(m.rel(abs)) for abs in items]))
2265 max([len(m.rel(abs)) for abs in items]))
2245 for abs in items:
2266 for abs in items:
2246 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2267 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2247 ui.write("%s\n" % line.rstrip())
2268 ui.write("%s\n" % line.rstrip())
2248
2269
2249 @command('debugwireargs',
2270 @command('debugwireargs',
2250 [('', 'three', '', 'three'),
2271 [('', 'three', '', 'three'),
2251 ('', 'four', '', 'four'),
2272 ('', 'four', '', 'four'),
2252 ('', 'five', '', 'five'),
2273 ('', 'five', '', 'five'),
2253 ] + remoteopts,
2274 ] + remoteopts,
2254 _('REPO [OPTIONS]... [ONE [TWO]]'))
2275 _('REPO [OPTIONS]... [ONE [TWO]]'))
2255 def debugwireargs(ui, repopath, *vals, **opts):
2276 def debugwireargs(ui, repopath, *vals, **opts):
2256 repo = hg.peer(ui, opts, repopath)
2277 repo = hg.peer(ui, opts, repopath)
2257 for opt in remoteopts:
2278 for opt in remoteopts:
2258 del opts[opt[1]]
2279 del opts[opt[1]]
2259 args = {}
2280 args = {}
2260 for k, v in opts.iteritems():
2281 for k, v in opts.iteritems():
2261 if v:
2282 if v:
2262 args[k] = v
2283 args[k] = v
2263 # run twice to check that we don't mess up the stream for the next command
2284 # run twice to check that we don't mess up the stream for the next command
2264 res1 = repo.debugwireargs(*vals, **args)
2285 res1 = repo.debugwireargs(*vals, **args)
2265 res2 = repo.debugwireargs(*vals, **args)
2286 res2 = repo.debugwireargs(*vals, **args)
2266 ui.write("%s\n" % res1)
2287 ui.write("%s\n" % res1)
2267 if res1 != res2:
2288 if res1 != res2:
2268 ui.warn("%s\n" % res2)
2289 ui.warn("%s\n" % res2)
2269
2290
2270 @command('^diff',
2291 @command('^diff',
2271 [('r', 'rev', [], _('revision'), _('REV')),
2292 [('r', 'rev', [], _('revision'), _('REV')),
2272 ('c', 'change', '', _('change made by revision'), _('REV'))
2293 ('c', 'change', '', _('change made by revision'), _('REV'))
2273 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2294 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2274 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2295 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2275 def diff(ui, repo, *pats, **opts):
2296 def diff(ui, repo, *pats, **opts):
2276 """diff repository (or selected files)
2297 """diff repository (or selected files)
2277
2298
2278 Show differences between revisions for the specified files.
2299 Show differences between revisions for the specified files.
2279
2300
2280 Differences between files are shown using the unified diff format.
2301 Differences between files are shown using the unified diff format.
2281
2302
2282 .. note::
2303 .. note::
2283 diff may generate unexpected results for merges, as it will
2304 diff may generate unexpected results for merges, as it will
2284 default to comparing against the working directory's first
2305 default to comparing against the working directory's first
2285 parent changeset if no revisions are specified.
2306 parent changeset if no revisions are specified.
2286
2307
2287 When two revision arguments are given, then changes are shown
2308 When two revision arguments are given, then changes are shown
2288 between those revisions. If only one revision is specified then
2309 between those revisions. If only one revision is specified then
2289 that revision is compared to the working directory, and, when no
2310 that revision is compared to the working directory, and, when no
2290 revisions are specified, the working directory files are compared
2311 revisions are specified, the working directory files are compared
2291 to its parent.
2312 to its parent.
2292
2313
2293 Alternatively you can specify -c/--change with a revision to see
2314 Alternatively you can specify -c/--change with a revision to see
2294 the changes in that changeset relative to its first parent.
2315 the changes in that changeset relative to its first parent.
2295
2316
2296 Without the -a/--text option, diff will avoid generating diffs of
2317 Without the -a/--text option, diff will avoid generating diffs of
2297 files it detects as binary. With -a, diff will generate a diff
2318 files it detects as binary. With -a, diff will generate a diff
2298 anyway, probably with undesirable results.
2319 anyway, probably with undesirable results.
2299
2320
2300 Use the -g/--git option to generate diffs in the git extended diff
2321 Use the -g/--git option to generate diffs in the git extended diff
2301 format. For more information, read :hg:`help diffs`.
2322 format. For more information, read :hg:`help diffs`.
2302
2323
2303 .. container:: verbose
2324 .. container:: verbose
2304
2325
2305 Examples:
2326 Examples:
2306
2327
2307 - compare a file in the current working directory to its parent::
2328 - compare a file in the current working directory to its parent::
2308
2329
2309 hg diff foo.c
2330 hg diff foo.c
2310
2331
2311 - compare two historical versions of a directory, with rename info::
2332 - compare two historical versions of a directory, with rename info::
2312
2333
2313 hg diff --git -r 1.0:1.2 lib/
2334 hg diff --git -r 1.0:1.2 lib/
2314
2335
2315 - get change stats relative to the last change on some date::
2336 - get change stats relative to the last change on some date::
2316
2337
2317 hg diff --stat -r "date('may 2')"
2338 hg diff --stat -r "date('may 2')"
2318
2339
2319 - diff all newly-added files that contain a keyword::
2340 - diff all newly-added files that contain a keyword::
2320
2341
2321 hg diff "set:added() and grep(GNU)"
2342 hg diff "set:added() and grep(GNU)"
2322
2343
2323 - compare a revision and its parents::
2344 - compare a revision and its parents::
2324
2345
2325 hg diff -c 9353 # compare against first parent
2346 hg diff -c 9353 # compare against first parent
2326 hg diff -r 9353^:9353 # same using revset syntax
2347 hg diff -r 9353^:9353 # same using revset syntax
2327 hg diff -r 9353^2:9353 # compare against the second parent
2348 hg diff -r 9353^2:9353 # compare against the second parent
2328
2349
2329 Returns 0 on success.
2350 Returns 0 on success.
2330 """
2351 """
2331
2352
2332 revs = opts.get('rev')
2353 revs = opts.get('rev')
2333 change = opts.get('change')
2354 change = opts.get('change')
2334 stat = opts.get('stat')
2355 stat = opts.get('stat')
2335 reverse = opts.get('reverse')
2356 reverse = opts.get('reverse')
2336
2357
2337 if revs and change:
2358 if revs and change:
2338 msg = _('cannot specify --rev and --change at the same time')
2359 msg = _('cannot specify --rev and --change at the same time')
2339 raise util.Abort(msg)
2360 raise util.Abort(msg)
2340 elif change:
2361 elif change:
2341 node2 = scmutil.revsingle(repo, change, None).node()
2362 node2 = scmutil.revsingle(repo, change, None).node()
2342 node1 = repo[node2].p1().node()
2363 node1 = repo[node2].p1().node()
2343 else:
2364 else:
2344 node1, node2 = scmutil.revpair(repo, revs)
2365 node1, node2 = scmutil.revpair(repo, revs)
2345
2366
2346 if reverse:
2367 if reverse:
2347 node1, node2 = node2, node1
2368 node1, node2 = node2, node1
2348
2369
2349 diffopts = patch.diffopts(ui, opts)
2370 diffopts = patch.diffopts(ui, opts)
2350 m = scmutil.match(repo[node2], pats, opts)
2371 m = scmutil.match(repo[node2], pats, opts)
2351 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2372 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2352 listsubrepos=opts.get('subrepos'))
2373 listsubrepos=opts.get('subrepos'))
2353
2374
2354 @command('^export',
2375 @command('^export',
2355 [('o', 'output', '',
2376 [('o', 'output', '',
2356 _('print output to file with formatted name'), _('FORMAT')),
2377 _('print output to file with formatted name'), _('FORMAT')),
2357 ('', 'switch-parent', None, _('diff against the second parent')),
2378 ('', 'switch-parent', None, _('diff against the second parent')),
2358 ('r', 'rev', [], _('revisions to export'), _('REV')),
2379 ('r', 'rev', [], _('revisions to export'), _('REV')),
2359 ] + diffopts,
2380 ] + diffopts,
2360 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2381 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2361 def export(ui, repo, *changesets, **opts):
2382 def export(ui, repo, *changesets, **opts):
2362 """dump the header and diffs for one or more changesets
2383 """dump the header and diffs for one or more changesets
2363
2384
2364 Print the changeset header and diffs for one or more revisions.
2385 Print the changeset header and diffs for one or more revisions.
2365
2386
2366 The information shown in the changeset header is: author, date,
2387 The information shown in the changeset header is: author, date,
2367 branch name (if non-default), changeset hash, parent(s) and commit
2388 branch name (if non-default), changeset hash, parent(s) and commit
2368 comment.
2389 comment.
2369
2390
2370 .. note::
2391 .. note::
2371 export may generate unexpected diff output for merge
2392 export may generate unexpected diff output for merge
2372 changesets, as it will compare the merge changeset against its
2393 changesets, as it will compare the merge changeset against its
2373 first parent only.
2394 first parent only.
2374
2395
2375 Output may be to a file, in which case the name of the file is
2396 Output may be to a file, in which case the name of the file is
2376 given using a format string. The formatting rules are as follows:
2397 given using a format string. The formatting rules are as follows:
2377
2398
2378 :``%%``: literal "%" character
2399 :``%%``: literal "%" character
2379 :``%H``: changeset hash (40 hexadecimal digits)
2400 :``%H``: changeset hash (40 hexadecimal digits)
2380 :``%N``: number of patches being generated
2401 :``%N``: number of patches being generated
2381 :``%R``: changeset revision number
2402 :``%R``: changeset revision number
2382 :``%b``: basename of the exporting repository
2403 :``%b``: basename of the exporting repository
2383 :``%h``: short-form changeset hash (12 hexadecimal digits)
2404 :``%h``: short-form changeset hash (12 hexadecimal digits)
2384 :``%m``: first line of the commit message (only alphanumeric characters)
2405 :``%m``: first line of the commit message (only alphanumeric characters)
2385 :``%n``: zero-padded sequence number, starting at 1
2406 :``%n``: zero-padded sequence number, starting at 1
2386 :``%r``: zero-padded changeset revision number
2407 :``%r``: zero-padded changeset revision number
2387
2408
2388 Without the -a/--text option, export will avoid generating diffs
2409 Without the -a/--text option, export will avoid generating diffs
2389 of files it detects as binary. With -a, export will generate a
2410 of files it detects as binary. With -a, export will generate a
2390 diff anyway, probably with undesirable results.
2411 diff anyway, probably with undesirable results.
2391
2412
2392 Use the -g/--git option to generate diffs in the git extended diff
2413 Use the -g/--git option to generate diffs in the git extended diff
2393 format. See :hg:`help diffs` for more information.
2414 format. See :hg:`help diffs` for more information.
2394
2415
2395 With the --switch-parent option, the diff will be against the
2416 With the --switch-parent option, the diff will be against the
2396 second parent. It can be useful to review a merge.
2417 second parent. It can be useful to review a merge.
2397
2418
2398 .. container:: verbose
2419 .. container:: verbose
2399
2420
2400 Examples:
2421 Examples:
2401
2422
2402 - use export and import to transplant a bugfix to the current
2423 - use export and import to transplant a bugfix to the current
2403 branch::
2424 branch::
2404
2425
2405 hg export -r 9353 | hg import -
2426 hg export -r 9353 | hg import -
2406
2427
2407 - export all the changesets between two revisions to a file with
2428 - export all the changesets between two revisions to a file with
2408 rename information::
2429 rename information::
2409
2430
2410 hg export --git -r 123:150 > changes.txt
2431 hg export --git -r 123:150 > changes.txt
2411
2432
2412 - split outgoing changes into a series of patches with
2433 - split outgoing changes into a series of patches with
2413 descriptive names::
2434 descriptive names::
2414
2435
2415 hg export -r "outgoing()" -o "%n-%m.patch"
2436 hg export -r "outgoing()" -o "%n-%m.patch"
2416
2437
2417 Returns 0 on success.
2438 Returns 0 on success.
2418 """
2439 """
2419 changesets += tuple(opts.get('rev', []))
2440 changesets += tuple(opts.get('rev', []))
2420 if not changesets:
2441 if not changesets:
2421 raise util.Abort(_("export requires at least one changeset"))
2442 raise util.Abort(_("export requires at least one changeset"))
2422 revs = scmutil.revrange(repo, changesets)
2443 revs = scmutil.revrange(repo, changesets)
2423 if len(revs) > 1:
2444 if len(revs) > 1:
2424 ui.note(_('exporting patches:\n'))
2445 ui.note(_('exporting patches:\n'))
2425 else:
2446 else:
2426 ui.note(_('exporting patch:\n'))
2447 ui.note(_('exporting patch:\n'))
2427 cmdutil.export(repo, revs, template=opts.get('output'),
2448 cmdutil.export(repo, revs, template=opts.get('output'),
2428 switch_parent=opts.get('switch_parent'),
2449 switch_parent=opts.get('switch_parent'),
2429 opts=patch.diffopts(ui, opts))
2450 opts=patch.diffopts(ui, opts))
2430
2451
2431 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2452 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2432 def forget(ui, repo, *pats, **opts):
2453 def forget(ui, repo, *pats, **opts):
2433 """forget the specified files on the next commit
2454 """forget the specified files on the next commit
2434
2455
2435 Mark the specified files so they will no longer be tracked
2456 Mark the specified files so they will no longer be tracked
2436 after the next commit.
2457 after the next commit.
2437
2458
2438 This only removes files from the current branch, not from the
2459 This only removes files from the current branch, not from the
2439 entire project history, and it does not delete them from the
2460 entire project history, and it does not delete them from the
2440 working directory.
2461 working directory.
2441
2462
2442 To undo a forget before the next commit, see :hg:`add`.
2463 To undo a forget before the next commit, see :hg:`add`.
2443
2464
2444 .. container:: verbose
2465 .. container:: verbose
2445
2466
2446 Examples:
2467 Examples:
2447
2468
2448 - forget newly-added binary files::
2469 - forget newly-added binary files::
2449
2470
2450 hg forget "set:added() and binary()"
2471 hg forget "set:added() and binary()"
2451
2472
2452 - forget files that would be excluded by .hgignore::
2473 - forget files that would be excluded by .hgignore::
2453
2474
2454 hg forget "set:hgignore()"
2475 hg forget "set:hgignore()"
2455
2476
2456 Returns 0 on success.
2477 Returns 0 on success.
2457 """
2478 """
2458
2479
2459 if not pats:
2480 if not pats:
2460 raise util.Abort(_('no files specified'))
2481 raise util.Abort(_('no files specified'))
2461
2482
2462 m = scmutil.match(repo[None], pats, opts)
2483 m = scmutil.match(repo[None], pats, opts)
2463 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2484 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2464 return rejected and 1 or 0
2485 return rejected and 1 or 0
2465
2486
2466 @command(
2487 @command(
2467 'graft',
2488 'graft',
2468 [('c', 'continue', False, _('resume interrupted graft')),
2489 [('c', 'continue', False, _('resume interrupted graft')),
2469 ('e', 'edit', False, _('invoke editor on commit messages')),
2490 ('e', 'edit', False, _('invoke editor on commit messages')),
2470 ('D', 'currentdate', False,
2491 ('D', 'currentdate', False,
2471 _('record the current date as commit date')),
2492 _('record the current date as commit date')),
2472 ('U', 'currentuser', False,
2493 ('U', 'currentuser', False,
2473 _('record the current user as committer'), _('DATE'))]
2494 _('record the current user as committer'), _('DATE'))]
2474 + commitopts2 + mergetoolopts,
2495 + commitopts2 + mergetoolopts,
2475 _('[OPTION]... REVISION...'))
2496 _('[OPTION]... REVISION...'))
2476 def graft(ui, repo, *revs, **opts):
2497 def graft(ui, repo, *revs, **opts):
2477 '''copy changes from other branches onto the current branch
2498 '''copy changes from other branches onto the current branch
2478
2499
2479 This command uses Mercurial's merge logic to copy individual
2500 This command uses Mercurial's merge logic to copy individual
2480 changes from other branches without merging branches in the
2501 changes from other branches without merging branches in the
2481 history graph. This is sometimes known as 'backporting' or
2502 history graph. This is sometimes known as 'backporting' or
2482 'cherry-picking'. By default, graft will copy user, date, and
2503 'cherry-picking'. By default, graft will copy user, date, and
2483 description from the source changesets.
2504 description from the source changesets.
2484
2505
2485 Changesets that are ancestors of the current revision, that have
2506 Changesets that are ancestors of the current revision, that have
2486 already been grafted, or that are merges will be skipped.
2507 already been grafted, or that are merges will be skipped.
2487
2508
2488 If a graft merge results in conflicts, the graft process is
2509 If a graft merge results in conflicts, the graft process is
2489 interrupted so that the current merge can be manually resolved.
2510 interrupted so that the current merge can be manually resolved.
2490 Once all conflicts are addressed, the graft process can be
2511 Once all conflicts are addressed, the graft process can be
2491 continued with the -c/--continue option.
2512 continued with the -c/--continue option.
2492
2513
2493 .. note::
2514 .. note::
2494 The -c/--continue option does not reapply earlier options.
2515 The -c/--continue option does not reapply earlier options.
2495
2516
2496 .. container:: verbose
2517 .. container:: verbose
2497
2518
2498 Examples:
2519 Examples:
2499
2520
2500 - copy a single change to the stable branch and edit its description::
2521 - copy a single change to the stable branch and edit its description::
2501
2522
2502 hg update stable
2523 hg update stable
2503 hg graft --edit 9393
2524 hg graft --edit 9393
2504
2525
2505 - graft a range of changesets with one exception, updating dates::
2526 - graft a range of changesets with one exception, updating dates::
2506
2527
2507 hg graft -D "2085::2093 and not 2091"
2528 hg graft -D "2085::2093 and not 2091"
2508
2529
2509 - continue a graft after resolving conflicts::
2530 - continue a graft after resolving conflicts::
2510
2531
2511 hg graft -c
2532 hg graft -c
2512
2533
2513 - show the source of a grafted changeset::
2534 - show the source of a grafted changeset::
2514
2535
2515 hg log --debug -r tip
2536 hg log --debug -r tip
2516
2537
2517 Returns 0 on successful completion.
2538 Returns 0 on successful completion.
2518 '''
2539 '''
2519
2540
2520 if not opts.get('user') and opts.get('currentuser'):
2541 if not opts.get('user') and opts.get('currentuser'):
2521 opts['user'] = ui.username()
2542 opts['user'] = ui.username()
2522 if not opts.get('date') and opts.get('currentdate'):
2543 if not opts.get('date') and opts.get('currentdate'):
2523 opts['date'] = "%d %d" % util.makedate()
2544 opts['date'] = "%d %d" % util.makedate()
2524
2545
2525 editor = None
2546 editor = None
2526 if opts.get('edit'):
2547 if opts.get('edit'):
2527 editor = cmdutil.commitforceeditor
2548 editor = cmdutil.commitforceeditor
2528
2549
2529 cont = False
2550 cont = False
2530 if opts['continue']:
2551 if opts['continue']:
2531 cont = True
2552 cont = True
2532 if revs:
2553 if revs:
2533 raise util.Abort(_("can't specify --continue and revisions"))
2554 raise util.Abort(_("can't specify --continue and revisions"))
2534 # read in unfinished revisions
2555 # read in unfinished revisions
2535 try:
2556 try:
2536 nodes = repo.opener.read('graftstate').splitlines()
2557 nodes = repo.opener.read('graftstate').splitlines()
2537 revs = [repo[node].rev() for node in nodes]
2558 revs = [repo[node].rev() for node in nodes]
2538 except IOError, inst:
2559 except IOError, inst:
2539 if inst.errno != errno.ENOENT:
2560 if inst.errno != errno.ENOENT:
2540 raise
2561 raise
2541 raise util.Abort(_("no graft state found, can't continue"))
2562 raise util.Abort(_("no graft state found, can't continue"))
2542 else:
2563 else:
2543 cmdutil.bailifchanged(repo)
2564 cmdutil.bailifchanged(repo)
2544 if not revs:
2565 if not revs:
2545 raise util.Abort(_('no revisions specified'))
2566 raise util.Abort(_('no revisions specified'))
2546 revs = scmutil.revrange(repo, revs)
2567 revs = scmutil.revrange(repo, revs)
2547
2568
2548 # check for merges
2569 # check for merges
2549 for rev in repo.revs('%ld and merge()', revs):
2570 for rev in repo.revs('%ld and merge()', revs):
2550 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2571 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2551 revs.remove(rev)
2572 revs.remove(rev)
2552 if not revs:
2573 if not revs:
2553 return -1
2574 return -1
2554
2575
2555 # check for ancestors of dest branch
2576 # check for ancestors of dest branch
2556 for rev in repo.revs('::. and %ld', revs):
2577 for rev in repo.revs('::. and %ld', revs):
2557 ui.warn(_('skipping ancestor revision %s\n') % rev)
2578 ui.warn(_('skipping ancestor revision %s\n') % rev)
2558 revs.remove(rev)
2579 revs.remove(rev)
2559 if not revs:
2580 if not revs:
2560 return -1
2581 return -1
2561
2582
2562 # analyze revs for earlier grafts
2583 # analyze revs for earlier grafts
2563 ids = {}
2584 ids = {}
2564 for ctx in repo.set("%ld", revs):
2585 for ctx in repo.set("%ld", revs):
2565 ids[ctx.hex()] = ctx.rev()
2586 ids[ctx.hex()] = ctx.rev()
2566 n = ctx.extra().get('source')
2587 n = ctx.extra().get('source')
2567 if n:
2588 if n:
2568 ids[n] = ctx.rev()
2589 ids[n] = ctx.rev()
2569
2590
2570 # check ancestors for earlier grafts
2591 # check ancestors for earlier grafts
2571 ui.debug('scanning for duplicate grafts\n')
2592 ui.debug('scanning for duplicate grafts\n')
2572 for ctx in repo.set("::. - ::%ld", revs):
2593 for ctx in repo.set("::. - ::%ld", revs):
2573 n = ctx.extra().get('source')
2594 n = ctx.extra().get('source')
2574 if n in ids:
2595 if n in ids:
2575 r = repo[n].rev()
2596 r = repo[n].rev()
2576 if r in revs:
2597 if r in revs:
2577 ui.warn(_('skipping already grafted revision %s\n') % r)
2598 ui.warn(_('skipping already grafted revision %s\n') % r)
2578 revs.remove(r)
2599 revs.remove(r)
2579 elif ids[n] in revs:
2600 elif ids[n] in revs:
2580 ui.warn(_('skipping already grafted revision %s '
2601 ui.warn(_('skipping already grafted revision %s '
2581 '(same origin %d)\n') % (ids[n], r))
2602 '(same origin %d)\n') % (ids[n], r))
2582 revs.remove(ids[n])
2603 revs.remove(ids[n])
2583 elif ctx.hex() in ids:
2604 elif ctx.hex() in ids:
2584 r = ids[ctx.hex()]
2605 r = ids[ctx.hex()]
2585 ui.warn(_('skipping already grafted revision %s '
2606 ui.warn(_('skipping already grafted revision %s '
2586 '(was grafted from %d)\n') % (r, ctx.rev()))
2607 '(was grafted from %d)\n') % (r, ctx.rev()))
2587 revs.remove(r)
2608 revs.remove(r)
2588 if not revs:
2609 if not revs:
2589 return -1
2610 return -1
2590
2611
2591 for pos, ctx in enumerate(repo.set("%ld", revs)):
2612 for pos, ctx in enumerate(repo.set("%ld", revs)):
2592 current = repo['.']
2613 current = repo['.']
2593 ui.status(_('grafting revision %s\n') % ctx.rev())
2614 ui.status(_('grafting revision %s\n') % ctx.rev())
2594
2615
2595 # we don't merge the first commit when continuing
2616 # we don't merge the first commit when continuing
2596 if not cont:
2617 if not cont:
2597 # perform the graft merge with p1(rev) as 'ancestor'
2618 # perform the graft merge with p1(rev) as 'ancestor'
2598 try:
2619 try:
2599 # ui.forcemerge is an internal variable, do not document
2620 # ui.forcemerge is an internal variable, do not document
2600 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2621 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2601 stats = mergemod.update(repo, ctx.node(), True, True, False,
2622 stats = mergemod.update(repo, ctx.node(), True, True, False,
2602 ctx.p1().node())
2623 ctx.p1().node())
2603 finally:
2624 finally:
2604 ui.setconfig('ui', 'forcemerge', '')
2625 ui.setconfig('ui', 'forcemerge', '')
2605 # drop the second merge parent
2626 # drop the second merge parent
2606 repo.dirstate.setparents(current.node(), nullid)
2627 repo.dirstate.setparents(current.node(), nullid)
2607 repo.dirstate.write()
2628 repo.dirstate.write()
2608 # fix up dirstate for copies and renames
2629 # fix up dirstate for copies and renames
2609 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2630 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2610 # report any conflicts
2631 # report any conflicts
2611 if stats and stats[3] > 0:
2632 if stats and stats[3] > 0:
2612 # write out state for --continue
2633 # write out state for --continue
2613 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2634 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2614 repo.opener.write('graftstate', ''.join(nodelines))
2635 repo.opener.write('graftstate', ''.join(nodelines))
2615 raise util.Abort(
2636 raise util.Abort(
2616 _("unresolved conflicts, can't continue"),
2637 _("unresolved conflicts, can't continue"),
2617 hint=_('use hg resolve and hg graft --continue'))
2638 hint=_('use hg resolve and hg graft --continue'))
2618 else:
2639 else:
2619 cont = False
2640 cont = False
2620
2641
2621 # commit
2642 # commit
2622 source = ctx.extra().get('source')
2643 source = ctx.extra().get('source')
2623 if not source:
2644 if not source:
2624 source = ctx.hex()
2645 source = ctx.hex()
2625 extra = {'source': source}
2646 extra = {'source': source}
2626 user = ctx.user()
2647 user = ctx.user()
2627 if opts.get('user'):
2648 if opts.get('user'):
2628 user = opts['user']
2649 user = opts['user']
2629 date = ctx.date()
2650 date = ctx.date()
2630 if opts.get('date'):
2651 if opts.get('date'):
2631 date = opts['date']
2652 date = opts['date']
2632 repo.commit(text=ctx.description(), user=user,
2653 repo.commit(text=ctx.description(), user=user,
2633 date=date, extra=extra, editor=editor)
2654 date=date, extra=extra, editor=editor)
2634
2655
2635 # remove state when we complete successfully
2656 # remove state when we complete successfully
2636 if os.path.exists(repo.join('graftstate')):
2657 if os.path.exists(repo.join('graftstate')):
2637 util.unlinkpath(repo.join('graftstate'))
2658 util.unlinkpath(repo.join('graftstate'))
2638
2659
2639 return 0
2660 return 0
2640
2661
2641 @command('grep',
2662 @command('grep',
2642 [('0', 'print0', None, _('end fields with NUL')),
2663 [('0', 'print0', None, _('end fields with NUL')),
2643 ('', 'all', None, _('print all revisions that match')),
2664 ('', 'all', None, _('print all revisions that match')),
2644 ('a', 'text', None, _('treat all files as text')),
2665 ('a', 'text', None, _('treat all files as text')),
2645 ('f', 'follow', None,
2666 ('f', 'follow', None,
2646 _('follow changeset history,'
2667 _('follow changeset history,'
2647 ' or file history across copies and renames')),
2668 ' or file history across copies and renames')),
2648 ('i', 'ignore-case', None, _('ignore case when matching')),
2669 ('i', 'ignore-case', None, _('ignore case when matching')),
2649 ('l', 'files-with-matches', None,
2670 ('l', 'files-with-matches', None,
2650 _('print only filenames and revisions that match')),
2671 _('print only filenames and revisions that match')),
2651 ('n', 'line-number', None, _('print matching line numbers')),
2672 ('n', 'line-number', None, _('print matching line numbers')),
2652 ('r', 'rev', [],
2673 ('r', 'rev', [],
2653 _('only search files changed within revision range'), _('REV')),
2674 _('only search files changed within revision range'), _('REV')),
2654 ('u', 'user', None, _('list the author (long with -v)')),
2675 ('u', 'user', None, _('list the author (long with -v)')),
2655 ('d', 'date', None, _('list the date (short with -q)')),
2676 ('d', 'date', None, _('list the date (short with -q)')),
2656 ] + walkopts,
2677 ] + walkopts,
2657 _('[OPTION]... PATTERN [FILE]...'))
2678 _('[OPTION]... PATTERN [FILE]...'))
2658 def grep(ui, repo, pattern, *pats, **opts):
2679 def grep(ui, repo, pattern, *pats, **opts):
2659 """search for a pattern in specified files and revisions
2680 """search for a pattern in specified files and revisions
2660
2681
2661 Search revisions of files for a regular expression.
2682 Search revisions of files for a regular expression.
2662
2683
2663 This command behaves differently than Unix grep. It only accepts
2684 This command behaves differently than Unix grep. It only accepts
2664 Python/Perl regexps. It searches repository history, not the
2685 Python/Perl regexps. It searches repository history, not the
2665 working directory. It always prints the revision number in which a
2686 working directory. It always prints the revision number in which a
2666 match appears.
2687 match appears.
2667
2688
2668 By default, grep only prints output for the first revision of a
2689 By default, grep only prints output for the first revision of a
2669 file in which it finds a match. To get it to print every revision
2690 file in which it finds a match. To get it to print every revision
2670 that contains a change in match status ("-" for a match that
2691 that contains a change in match status ("-" for a match that
2671 becomes a non-match, or "+" for a non-match that becomes a match),
2692 becomes a non-match, or "+" for a non-match that becomes a match),
2672 use the --all flag.
2693 use the --all flag.
2673
2694
2674 Returns 0 if a match is found, 1 otherwise.
2695 Returns 0 if a match is found, 1 otherwise.
2675 """
2696 """
2676 reflags = re.M
2697 reflags = re.M
2677 if opts.get('ignore_case'):
2698 if opts.get('ignore_case'):
2678 reflags |= re.I
2699 reflags |= re.I
2679 try:
2700 try:
2680 regexp = re.compile(pattern, reflags)
2701 regexp = re.compile(pattern, reflags)
2681 except re.error, inst:
2702 except re.error, inst:
2682 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2703 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2683 return 1
2704 return 1
2684 sep, eol = ':', '\n'
2705 sep, eol = ':', '\n'
2685 if opts.get('print0'):
2706 if opts.get('print0'):
2686 sep = eol = '\0'
2707 sep = eol = '\0'
2687
2708
2688 getfile = util.lrucachefunc(repo.file)
2709 getfile = util.lrucachefunc(repo.file)
2689
2710
2690 def matchlines(body):
2711 def matchlines(body):
2691 begin = 0
2712 begin = 0
2692 linenum = 0
2713 linenum = 0
2693 while True:
2714 while True:
2694 match = regexp.search(body, begin)
2715 match = regexp.search(body, begin)
2695 if not match:
2716 if not match:
2696 break
2717 break
2697 mstart, mend = match.span()
2718 mstart, mend = match.span()
2698 linenum += body.count('\n', begin, mstart) + 1
2719 linenum += body.count('\n', begin, mstart) + 1
2699 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2720 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2700 begin = body.find('\n', mend) + 1 or len(body) + 1
2721 begin = body.find('\n', mend) + 1 or len(body) + 1
2701 lend = begin - 1
2722 lend = begin - 1
2702 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2723 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2703
2724
2704 class linestate(object):
2725 class linestate(object):
2705 def __init__(self, line, linenum, colstart, colend):
2726 def __init__(self, line, linenum, colstart, colend):
2706 self.line = line
2727 self.line = line
2707 self.linenum = linenum
2728 self.linenum = linenum
2708 self.colstart = colstart
2729 self.colstart = colstart
2709 self.colend = colend
2730 self.colend = colend
2710
2731
2711 def __hash__(self):
2732 def __hash__(self):
2712 return hash((self.linenum, self.line))
2733 return hash((self.linenum, self.line))
2713
2734
2714 def __eq__(self, other):
2735 def __eq__(self, other):
2715 return self.line == other.line
2736 return self.line == other.line
2716
2737
2717 matches = {}
2738 matches = {}
2718 copies = {}
2739 copies = {}
2719 def grepbody(fn, rev, body):
2740 def grepbody(fn, rev, body):
2720 matches[rev].setdefault(fn, [])
2741 matches[rev].setdefault(fn, [])
2721 m = matches[rev][fn]
2742 m = matches[rev][fn]
2722 for lnum, cstart, cend, line in matchlines(body):
2743 for lnum, cstart, cend, line in matchlines(body):
2723 s = linestate(line, lnum, cstart, cend)
2744 s = linestate(line, lnum, cstart, cend)
2724 m.append(s)
2745 m.append(s)
2725
2746
2726 def difflinestates(a, b):
2747 def difflinestates(a, b):
2727 sm = difflib.SequenceMatcher(None, a, b)
2748 sm = difflib.SequenceMatcher(None, a, b)
2728 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2749 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2729 if tag == 'insert':
2750 if tag == 'insert':
2730 for i in xrange(blo, bhi):
2751 for i in xrange(blo, bhi):
2731 yield ('+', b[i])
2752 yield ('+', b[i])
2732 elif tag == 'delete':
2753 elif tag == 'delete':
2733 for i in xrange(alo, ahi):
2754 for i in xrange(alo, ahi):
2734 yield ('-', a[i])
2755 yield ('-', a[i])
2735 elif tag == 'replace':
2756 elif tag == 'replace':
2736 for i in xrange(alo, ahi):
2757 for i in xrange(alo, ahi):
2737 yield ('-', a[i])
2758 yield ('-', a[i])
2738 for i in xrange(blo, bhi):
2759 for i in xrange(blo, bhi):
2739 yield ('+', b[i])
2760 yield ('+', b[i])
2740
2761
2741 def display(fn, ctx, pstates, states):
2762 def display(fn, ctx, pstates, states):
2742 rev = ctx.rev()
2763 rev = ctx.rev()
2743 datefunc = ui.quiet and util.shortdate or util.datestr
2764 datefunc = ui.quiet and util.shortdate or util.datestr
2744 found = False
2765 found = False
2745 filerevmatches = {}
2766 filerevmatches = {}
2746 def binary():
2767 def binary():
2747 flog = getfile(fn)
2768 flog = getfile(fn)
2748 return util.binary(flog.read(ctx.filenode(fn)))
2769 return util.binary(flog.read(ctx.filenode(fn)))
2749
2770
2750 if opts.get('all'):
2771 if opts.get('all'):
2751 iter = difflinestates(pstates, states)
2772 iter = difflinestates(pstates, states)
2752 else:
2773 else:
2753 iter = [('', l) for l in states]
2774 iter = [('', l) for l in states]
2754 for change, l in iter:
2775 for change, l in iter:
2755 cols = [fn, str(rev)]
2776 cols = [fn, str(rev)]
2756 before, match, after = None, None, None
2777 before, match, after = None, None, None
2757 if opts.get('line_number'):
2778 if opts.get('line_number'):
2758 cols.append(str(l.linenum))
2779 cols.append(str(l.linenum))
2759 if opts.get('all'):
2780 if opts.get('all'):
2760 cols.append(change)
2781 cols.append(change)
2761 if opts.get('user'):
2782 if opts.get('user'):
2762 cols.append(ui.shortuser(ctx.user()))
2783 cols.append(ui.shortuser(ctx.user()))
2763 if opts.get('date'):
2784 if opts.get('date'):
2764 cols.append(datefunc(ctx.date()))
2785 cols.append(datefunc(ctx.date()))
2765 if opts.get('files_with_matches'):
2786 if opts.get('files_with_matches'):
2766 c = (fn, rev)
2787 c = (fn, rev)
2767 if c in filerevmatches:
2788 if c in filerevmatches:
2768 continue
2789 continue
2769 filerevmatches[c] = 1
2790 filerevmatches[c] = 1
2770 else:
2791 else:
2771 before = l.line[:l.colstart]
2792 before = l.line[:l.colstart]
2772 match = l.line[l.colstart:l.colend]
2793 match = l.line[l.colstart:l.colend]
2773 after = l.line[l.colend:]
2794 after = l.line[l.colend:]
2774 ui.write(sep.join(cols))
2795 ui.write(sep.join(cols))
2775 if before is not None:
2796 if before is not None:
2776 if not opts.get('text') and binary():
2797 if not opts.get('text') and binary():
2777 ui.write(sep + " Binary file matches")
2798 ui.write(sep + " Binary file matches")
2778 else:
2799 else:
2779 ui.write(sep + before)
2800 ui.write(sep + before)
2780 ui.write(match, label='grep.match')
2801 ui.write(match, label='grep.match')
2781 ui.write(after)
2802 ui.write(after)
2782 ui.write(eol)
2803 ui.write(eol)
2783 found = True
2804 found = True
2784 return found
2805 return found
2785
2806
2786 skip = {}
2807 skip = {}
2787 revfiles = {}
2808 revfiles = {}
2788 matchfn = scmutil.match(repo[None], pats, opts)
2809 matchfn = scmutil.match(repo[None], pats, opts)
2789 found = False
2810 found = False
2790 follow = opts.get('follow')
2811 follow = opts.get('follow')
2791
2812
2792 def prep(ctx, fns):
2813 def prep(ctx, fns):
2793 rev = ctx.rev()
2814 rev = ctx.rev()
2794 pctx = ctx.p1()
2815 pctx = ctx.p1()
2795 parent = pctx.rev()
2816 parent = pctx.rev()
2796 matches.setdefault(rev, {})
2817 matches.setdefault(rev, {})
2797 matches.setdefault(parent, {})
2818 matches.setdefault(parent, {})
2798 files = revfiles.setdefault(rev, [])
2819 files = revfiles.setdefault(rev, [])
2799 for fn in fns:
2820 for fn in fns:
2800 flog = getfile(fn)
2821 flog = getfile(fn)
2801 try:
2822 try:
2802 fnode = ctx.filenode(fn)
2823 fnode = ctx.filenode(fn)
2803 except error.LookupError:
2824 except error.LookupError:
2804 continue
2825 continue
2805
2826
2806 copied = flog.renamed(fnode)
2827 copied = flog.renamed(fnode)
2807 copy = follow and copied and copied[0]
2828 copy = follow and copied and copied[0]
2808 if copy:
2829 if copy:
2809 copies.setdefault(rev, {})[fn] = copy
2830 copies.setdefault(rev, {})[fn] = copy
2810 if fn in skip:
2831 if fn in skip:
2811 if copy:
2832 if copy:
2812 skip[copy] = True
2833 skip[copy] = True
2813 continue
2834 continue
2814 files.append(fn)
2835 files.append(fn)
2815
2836
2816 if fn not in matches[rev]:
2837 if fn not in matches[rev]:
2817 grepbody(fn, rev, flog.read(fnode))
2838 grepbody(fn, rev, flog.read(fnode))
2818
2839
2819 pfn = copy or fn
2840 pfn = copy or fn
2820 if pfn not in matches[parent]:
2841 if pfn not in matches[parent]:
2821 try:
2842 try:
2822 fnode = pctx.filenode(pfn)
2843 fnode = pctx.filenode(pfn)
2823 grepbody(pfn, parent, flog.read(fnode))
2844 grepbody(pfn, parent, flog.read(fnode))
2824 except error.LookupError:
2845 except error.LookupError:
2825 pass
2846 pass
2826
2847
2827 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2848 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2828 rev = ctx.rev()
2849 rev = ctx.rev()
2829 parent = ctx.p1().rev()
2850 parent = ctx.p1().rev()
2830 for fn in sorted(revfiles.get(rev, [])):
2851 for fn in sorted(revfiles.get(rev, [])):
2831 states = matches[rev][fn]
2852 states = matches[rev][fn]
2832 copy = copies.get(rev, {}).get(fn)
2853 copy = copies.get(rev, {}).get(fn)
2833 if fn in skip:
2854 if fn in skip:
2834 if copy:
2855 if copy:
2835 skip[copy] = True
2856 skip[copy] = True
2836 continue
2857 continue
2837 pstates = matches.get(parent, {}).get(copy or fn, [])
2858 pstates = matches.get(parent, {}).get(copy or fn, [])
2838 if pstates or states:
2859 if pstates or states:
2839 r = display(fn, ctx, pstates, states)
2860 r = display(fn, ctx, pstates, states)
2840 found = found or r
2861 found = found or r
2841 if r and not opts.get('all'):
2862 if r and not opts.get('all'):
2842 skip[fn] = True
2863 skip[fn] = True
2843 if copy:
2864 if copy:
2844 skip[copy] = True
2865 skip[copy] = True
2845 del matches[rev]
2866 del matches[rev]
2846 del revfiles[rev]
2867 del revfiles[rev]
2847
2868
2848 return not found
2869 return not found
2849
2870
2850 @command('heads',
2871 @command('heads',
2851 [('r', 'rev', '',
2872 [('r', 'rev', '',
2852 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2873 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2853 ('t', 'topo', False, _('show topological heads only')),
2874 ('t', 'topo', False, _('show topological heads only')),
2854 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2875 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2855 ('c', 'closed', False, _('show normal and closed branch heads')),
2876 ('c', 'closed', False, _('show normal and closed branch heads')),
2856 ] + templateopts,
2877 ] + templateopts,
2857 _('[-ac] [-r STARTREV] [REV]...'))
2878 _('[-ac] [-r STARTREV] [REV]...'))
2858 def heads(ui, repo, *branchrevs, **opts):
2879 def heads(ui, repo, *branchrevs, **opts):
2859 """show current repository heads or show branch heads
2880 """show current repository heads or show branch heads
2860
2881
2861 With no arguments, show all repository branch heads.
2882 With no arguments, show all repository branch heads.
2862
2883
2863 Repository "heads" are changesets with no child changesets. They are
2884 Repository "heads" are changesets with no child changesets. They are
2864 where development generally takes place and are the usual targets
2885 where development generally takes place and are the usual targets
2865 for update and merge operations. Branch heads are changesets that have
2886 for update and merge operations. Branch heads are changesets that have
2866 no child changeset on the same branch.
2887 no child changeset on the same branch.
2867
2888
2868 If one or more REVs are given, only branch heads on the branches
2889 If one or more REVs are given, only branch heads on the branches
2869 associated with the specified changesets are shown. This means
2890 associated with the specified changesets are shown. This means
2870 that you can use :hg:`heads foo` to see the heads on a branch
2891 that you can use :hg:`heads foo` to see the heads on a branch
2871 named ``foo``.
2892 named ``foo``.
2872
2893
2873 If -c/--closed is specified, also show branch heads marked closed
2894 If -c/--closed is specified, also show branch heads marked closed
2874 (see :hg:`commit --close-branch`).
2895 (see :hg:`commit --close-branch`).
2875
2896
2876 If STARTREV is specified, only those heads that are descendants of
2897 If STARTREV is specified, only those heads that are descendants of
2877 STARTREV will be displayed.
2898 STARTREV will be displayed.
2878
2899
2879 If -t/--topo is specified, named branch mechanics will be ignored and only
2900 If -t/--topo is specified, named branch mechanics will be ignored and only
2880 changesets without children will be shown.
2901 changesets without children will be shown.
2881
2902
2882 Returns 0 if matching heads are found, 1 if not.
2903 Returns 0 if matching heads are found, 1 if not.
2883 """
2904 """
2884
2905
2885 start = None
2906 start = None
2886 if 'rev' in opts:
2907 if 'rev' in opts:
2887 start = scmutil.revsingle(repo, opts['rev'], None).node()
2908 start = scmutil.revsingle(repo, opts['rev'], None).node()
2888
2909
2889 if opts.get('topo'):
2910 if opts.get('topo'):
2890 heads = [repo[h] for h in repo.heads(start)]
2911 heads = [repo[h] for h in repo.heads(start)]
2891 else:
2912 else:
2892 heads = []
2913 heads = []
2893 for branch in repo.branchmap():
2914 for branch in repo.branchmap():
2894 heads += repo.branchheads(branch, start, opts.get('closed'))
2915 heads += repo.branchheads(branch, start, opts.get('closed'))
2895 heads = [repo[h] for h in heads]
2916 heads = [repo[h] for h in heads]
2896
2917
2897 if branchrevs:
2918 if branchrevs:
2898 branches = set(repo[br].branch() for br in branchrevs)
2919 branches = set(repo[br].branch() for br in branchrevs)
2899 heads = [h for h in heads if h.branch() in branches]
2920 heads = [h for h in heads if h.branch() in branches]
2900
2921
2901 if opts.get('active') and branchrevs:
2922 if opts.get('active') and branchrevs:
2902 dagheads = repo.heads(start)
2923 dagheads = repo.heads(start)
2903 heads = [h for h in heads if h.node() in dagheads]
2924 heads = [h for h in heads if h.node() in dagheads]
2904
2925
2905 if branchrevs:
2926 if branchrevs:
2906 haveheads = set(h.branch() for h in heads)
2927 haveheads = set(h.branch() for h in heads)
2907 if branches - haveheads:
2928 if branches - haveheads:
2908 headless = ', '.join(b for b in branches - haveheads)
2929 headless = ', '.join(b for b in branches - haveheads)
2909 msg = _('no open branch heads found on branches %s')
2930 msg = _('no open branch heads found on branches %s')
2910 if opts.get('rev'):
2931 if opts.get('rev'):
2911 msg += _(' (started at %s)') % opts['rev']
2932 msg += _(' (started at %s)') % opts['rev']
2912 ui.warn((msg + '\n') % headless)
2933 ui.warn((msg + '\n') % headless)
2913
2934
2914 if not heads:
2935 if not heads:
2915 return 1
2936 return 1
2916
2937
2917 heads = sorted(heads, key=lambda x: -x.rev())
2938 heads = sorted(heads, key=lambda x: -x.rev())
2918 displayer = cmdutil.show_changeset(ui, repo, opts)
2939 displayer = cmdutil.show_changeset(ui, repo, opts)
2919 for ctx in heads:
2940 for ctx in heads:
2920 displayer.show(ctx)
2941 displayer.show(ctx)
2921 displayer.close()
2942 displayer.close()
2922
2943
2923 @command('help',
2944 @command('help',
2924 [('e', 'extension', None, _('show only help for extensions')),
2945 [('e', 'extension', None, _('show only help for extensions')),
2925 ('c', 'command', None, _('show only help for commands'))],
2946 ('c', 'command', None, _('show only help for commands'))],
2926 _('[-ec] [TOPIC]'))
2947 _('[-ec] [TOPIC]'))
2927 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2948 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2928 """show help for a given topic or a help overview
2949 """show help for a given topic or a help overview
2929
2950
2930 With no arguments, print a list of commands with short help messages.
2951 With no arguments, print a list of commands with short help messages.
2931
2952
2932 Given a topic, extension, or command name, print help for that
2953 Given a topic, extension, or command name, print help for that
2933 topic.
2954 topic.
2934
2955
2935 Returns 0 if successful.
2956 Returns 0 if successful.
2936 """
2957 """
2937
2958
2938 textwidth = min(ui.termwidth(), 80) - 2
2959 textwidth = min(ui.termwidth(), 80) - 2
2939
2960
2940 def optrst(options):
2961 def optrst(options):
2941 data = []
2962 data = []
2942 multioccur = False
2963 multioccur = False
2943 for option in options:
2964 for option in options:
2944 if len(option) == 5:
2965 if len(option) == 5:
2945 shortopt, longopt, default, desc, optlabel = option
2966 shortopt, longopt, default, desc, optlabel = option
2946 else:
2967 else:
2947 shortopt, longopt, default, desc = option
2968 shortopt, longopt, default, desc = option
2948 optlabel = _("VALUE") # default label
2969 optlabel = _("VALUE") # default label
2949
2970
2950 if _("DEPRECATED") in desc and not ui.verbose:
2971 if _("DEPRECATED") in desc and not ui.verbose:
2951 continue
2972 continue
2952
2973
2953 so = ''
2974 so = ''
2954 if shortopt:
2975 if shortopt:
2955 so = '-' + shortopt
2976 so = '-' + shortopt
2956 lo = '--' + longopt
2977 lo = '--' + longopt
2957 if default:
2978 if default:
2958 desc += _(" (default: %s)") % default
2979 desc += _(" (default: %s)") % default
2959
2980
2960 if isinstance(default, list):
2981 if isinstance(default, list):
2961 lo += " %s [+]" % optlabel
2982 lo += " %s [+]" % optlabel
2962 multioccur = True
2983 multioccur = True
2963 elif (default is not None) and not isinstance(default, bool):
2984 elif (default is not None) and not isinstance(default, bool):
2964 lo += " %s" % optlabel
2985 lo += " %s" % optlabel
2965
2986
2966 data.append((so, lo, desc))
2987 data.append((so, lo, desc))
2967
2988
2968 rst = minirst.maketable(data, 1)
2989 rst = minirst.maketable(data, 1)
2969
2990
2970 if multioccur:
2991 if multioccur:
2971 rst += _("\n[+] marked option can be specified multiple times\n")
2992 rst += _("\n[+] marked option can be specified multiple times\n")
2972
2993
2973 return rst
2994 return rst
2974
2995
2975 # list all option lists
2996 # list all option lists
2976 def opttext(optlist, width):
2997 def opttext(optlist, width):
2977 rst = ''
2998 rst = ''
2978 if not optlist:
2999 if not optlist:
2979 return ''
3000 return ''
2980
3001
2981 for title, options in optlist:
3002 for title, options in optlist:
2982 rst += '\n%s\n' % title
3003 rst += '\n%s\n' % title
2983 if options:
3004 if options:
2984 rst += "\n"
3005 rst += "\n"
2985 rst += optrst(options)
3006 rst += optrst(options)
2986 rst += '\n'
3007 rst += '\n'
2987
3008
2988 return '\n' + minirst.format(rst, width)
3009 return '\n' + minirst.format(rst, width)
2989
3010
2990 def addglobalopts(optlist, aliases):
3011 def addglobalopts(optlist, aliases):
2991 if ui.quiet:
3012 if ui.quiet:
2992 return []
3013 return []
2993
3014
2994 if ui.verbose:
3015 if ui.verbose:
2995 optlist.append((_("global options:"), globalopts))
3016 optlist.append((_("global options:"), globalopts))
2996 if name == 'shortlist':
3017 if name == 'shortlist':
2997 optlist.append((_('use "hg help" for the full list '
3018 optlist.append((_('use "hg help" for the full list '
2998 'of commands'), ()))
3019 'of commands'), ()))
2999 else:
3020 else:
3000 if name == 'shortlist':
3021 if name == 'shortlist':
3001 msg = _('use "hg help" for the full list of commands '
3022 msg = _('use "hg help" for the full list of commands '
3002 'or "hg -v" for details')
3023 'or "hg -v" for details')
3003 elif name and not full:
3024 elif name and not full:
3004 msg = _('use "hg help %s" to show the full help text') % name
3025 msg = _('use "hg help %s" to show the full help text') % name
3005 elif aliases:
3026 elif aliases:
3006 msg = _('use "hg -v help%s" to show builtin aliases and '
3027 msg = _('use "hg -v help%s" to show builtin aliases and '
3007 'global options') % (name and " " + name or "")
3028 'global options') % (name and " " + name or "")
3008 else:
3029 else:
3009 msg = _('use "hg -v help %s" to show more info') % name
3030 msg = _('use "hg -v help %s" to show more info') % name
3010 optlist.append((msg, ()))
3031 optlist.append((msg, ()))
3011
3032
3012 def helpcmd(name):
3033 def helpcmd(name):
3013 try:
3034 try:
3014 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3035 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3015 except error.AmbiguousCommand, inst:
3036 except error.AmbiguousCommand, inst:
3016 # py3k fix: except vars can't be used outside the scope of the
3037 # py3k fix: except vars can't be used outside the scope of the
3017 # except block, nor can be used inside a lambda. python issue4617
3038 # except block, nor can be used inside a lambda. python issue4617
3018 prefix = inst.args[0]
3039 prefix = inst.args[0]
3019 select = lambda c: c.lstrip('^').startswith(prefix)
3040 select = lambda c: c.lstrip('^').startswith(prefix)
3020 helplist(select)
3041 helplist(select)
3021 return
3042 return
3022
3043
3023 # check if it's an invalid alias and display its error if it is
3044 # check if it's an invalid alias and display its error if it is
3024 if getattr(entry[0], 'badalias', False):
3045 if getattr(entry[0], 'badalias', False):
3025 if not unknowncmd:
3046 if not unknowncmd:
3026 entry[0](ui)
3047 entry[0](ui)
3027 return
3048 return
3028
3049
3029 rst = ""
3050 rst = ""
3030
3051
3031 # synopsis
3052 # synopsis
3032 if len(entry) > 2:
3053 if len(entry) > 2:
3033 if entry[2].startswith('hg'):
3054 if entry[2].startswith('hg'):
3034 rst += "%s\n" % entry[2]
3055 rst += "%s\n" % entry[2]
3035 else:
3056 else:
3036 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3057 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3037 else:
3058 else:
3038 rst += 'hg %s\n' % aliases[0]
3059 rst += 'hg %s\n' % aliases[0]
3039
3060
3040 # aliases
3061 # aliases
3041 if full and not ui.quiet and len(aliases) > 1:
3062 if full and not ui.quiet and len(aliases) > 1:
3042 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3063 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3043
3064
3044 # description
3065 # description
3045 doc = gettext(entry[0].__doc__)
3066 doc = gettext(entry[0].__doc__)
3046 if not doc:
3067 if not doc:
3047 doc = _("(no help text available)")
3068 doc = _("(no help text available)")
3048 if util.safehasattr(entry[0], 'definition'): # aliased command
3069 if util.safehasattr(entry[0], 'definition'): # aliased command
3049 if entry[0].definition.startswith('!'): # shell alias
3070 if entry[0].definition.startswith('!'): # shell alias
3050 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3071 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3051 else:
3072 else:
3052 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3073 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3053 if ui.quiet or not full:
3074 if ui.quiet or not full:
3054 doc = doc.splitlines()[0]
3075 doc = doc.splitlines()[0]
3055 rst += "\n" + doc + "\n"
3076 rst += "\n" + doc + "\n"
3056
3077
3057 # check if this command shadows a non-trivial (multi-line)
3078 # check if this command shadows a non-trivial (multi-line)
3058 # extension help text
3079 # extension help text
3059 try:
3080 try:
3060 mod = extensions.find(name)
3081 mod = extensions.find(name)
3061 doc = gettext(mod.__doc__) or ''
3082 doc = gettext(mod.__doc__) or ''
3062 if '\n' in doc.strip():
3083 if '\n' in doc.strip():
3063 msg = _('use "hg help -e %s" to show help for '
3084 msg = _('use "hg help -e %s" to show help for '
3064 'the %s extension') % (name, name)
3085 'the %s extension') % (name, name)
3065 rst += '\n%s\n' % msg
3086 rst += '\n%s\n' % msg
3066 except KeyError:
3087 except KeyError:
3067 pass
3088 pass
3068
3089
3069 # options
3090 # options
3070 if not ui.quiet and entry[1]:
3091 if not ui.quiet and entry[1]:
3071 rst += '\n'
3092 rst += '\n'
3072 rst += _("options:")
3093 rst += _("options:")
3073 rst += '\n\n'
3094 rst += '\n\n'
3074 rst += optrst(entry[1])
3095 rst += optrst(entry[1])
3075
3096
3076 if ui.verbose:
3097 if ui.verbose:
3077 rst += '\n'
3098 rst += '\n'
3078 rst += _("global options:")
3099 rst += _("global options:")
3079 rst += '\n\n'
3100 rst += '\n\n'
3080 rst += optrst(globalopts)
3101 rst += optrst(globalopts)
3081
3102
3082 keep = ui.verbose and ['verbose'] or []
3103 keep = ui.verbose and ['verbose'] or []
3083 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3104 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3084 ui.write(formatted)
3105 ui.write(formatted)
3085
3106
3086 if not ui.verbose:
3107 if not ui.verbose:
3087 if not full:
3108 if not full:
3088 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3109 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3089 % name)
3110 % name)
3090 elif not ui.quiet:
3111 elif not ui.quiet:
3091 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3112 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3092
3113
3093
3114
3094 def helplist(select=None):
3115 def helplist(select=None):
3095 # list of commands
3116 # list of commands
3096 if name == "shortlist":
3117 if name == "shortlist":
3097 header = _('basic commands:\n\n')
3118 header = _('basic commands:\n\n')
3098 else:
3119 else:
3099 header = _('list of commands:\n\n')
3120 header = _('list of commands:\n\n')
3100
3121
3101 h = {}
3122 h = {}
3102 cmds = {}
3123 cmds = {}
3103 for c, e in table.iteritems():
3124 for c, e in table.iteritems():
3104 f = c.split("|", 1)[0]
3125 f = c.split("|", 1)[0]
3105 if select and not select(f):
3126 if select and not select(f):
3106 continue
3127 continue
3107 if (not select and name != 'shortlist' and
3128 if (not select and name != 'shortlist' and
3108 e[0].__module__ != __name__):
3129 e[0].__module__ != __name__):
3109 continue
3130 continue
3110 if name == "shortlist" and not f.startswith("^"):
3131 if name == "shortlist" and not f.startswith("^"):
3111 continue
3132 continue
3112 f = f.lstrip("^")
3133 f = f.lstrip("^")
3113 if not ui.debugflag and f.startswith("debug"):
3134 if not ui.debugflag and f.startswith("debug"):
3114 continue
3135 continue
3115 doc = e[0].__doc__
3136 doc = e[0].__doc__
3116 if doc and 'DEPRECATED' in doc and not ui.verbose:
3137 if doc and 'DEPRECATED' in doc and not ui.verbose:
3117 continue
3138 continue
3118 doc = gettext(doc)
3139 doc = gettext(doc)
3119 if not doc:
3140 if not doc:
3120 doc = _("(no help text available)")
3141 doc = _("(no help text available)")
3121 h[f] = doc.splitlines()[0].rstrip()
3142 h[f] = doc.splitlines()[0].rstrip()
3122 cmds[f] = c.lstrip("^")
3143 cmds[f] = c.lstrip("^")
3123
3144
3124 if not h:
3145 if not h:
3125 ui.status(_('no commands defined\n'))
3146 ui.status(_('no commands defined\n'))
3126 return
3147 return
3127
3148
3128 ui.status(header)
3149 ui.status(header)
3129 fns = sorted(h)
3150 fns = sorted(h)
3130 m = max(map(len, fns))
3151 m = max(map(len, fns))
3131 for f in fns:
3152 for f in fns:
3132 if ui.verbose:
3153 if ui.verbose:
3133 commands = cmds[f].replace("|",", ")
3154 commands = cmds[f].replace("|",", ")
3134 ui.write(" %s:\n %s\n"%(commands, h[f]))
3155 ui.write(" %s:\n %s\n"%(commands, h[f]))
3135 else:
3156 else:
3136 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3157 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3137 initindent=' %-*s ' % (m, f),
3158 initindent=' %-*s ' % (m, f),
3138 hangindent=' ' * (m + 4))))
3159 hangindent=' ' * (m + 4))))
3139
3160
3140 if not name:
3161 if not name:
3141 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3162 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3142 if text:
3163 if text:
3143 ui.write("\n%s" % minirst.format(text, textwidth))
3164 ui.write("\n%s" % minirst.format(text, textwidth))
3144
3165
3145 ui.write(_("\nadditional help topics:\n\n"))
3166 ui.write(_("\nadditional help topics:\n\n"))
3146 topics = []
3167 topics = []
3147 for names, header, doc in help.helptable:
3168 for names, header, doc in help.helptable:
3148 topics.append((sorted(names, key=len, reverse=True)[0], header))
3169 topics.append((sorted(names, key=len, reverse=True)[0], header))
3149 topics_len = max([len(s[0]) for s in topics])
3170 topics_len = max([len(s[0]) for s in topics])
3150 for t, desc in topics:
3171 for t, desc in topics:
3151 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3172 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3152
3173
3153 optlist = []
3174 optlist = []
3154 addglobalopts(optlist, True)
3175 addglobalopts(optlist, True)
3155 ui.write(opttext(optlist, textwidth))
3176 ui.write(opttext(optlist, textwidth))
3156
3177
3157 def helptopic(name):
3178 def helptopic(name):
3158 for names, header, doc in help.helptable:
3179 for names, header, doc in help.helptable:
3159 if name in names:
3180 if name in names:
3160 break
3181 break
3161 else:
3182 else:
3162 raise error.UnknownCommand(name)
3183 raise error.UnknownCommand(name)
3163
3184
3164 # description
3185 # description
3165 if not doc:
3186 if not doc:
3166 doc = _("(no help text available)")
3187 doc = _("(no help text available)")
3167 if util.safehasattr(doc, '__call__'):
3188 if util.safehasattr(doc, '__call__'):
3168 doc = doc()
3189 doc = doc()
3169
3190
3170 ui.write("%s\n\n" % header)
3191 ui.write("%s\n\n" % header)
3171 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3192 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3172 try:
3193 try:
3173 cmdutil.findcmd(name, table)
3194 cmdutil.findcmd(name, table)
3174 ui.write(_('\nuse "hg help -c %s" to see help for '
3195 ui.write(_('\nuse "hg help -c %s" to see help for '
3175 'the %s command\n') % (name, name))
3196 'the %s command\n') % (name, name))
3176 except error.UnknownCommand:
3197 except error.UnknownCommand:
3177 pass
3198 pass
3178
3199
3179 def helpext(name):
3200 def helpext(name):
3180 try:
3201 try:
3181 mod = extensions.find(name)
3202 mod = extensions.find(name)
3182 doc = gettext(mod.__doc__) or _('no help text available')
3203 doc = gettext(mod.__doc__) or _('no help text available')
3183 except KeyError:
3204 except KeyError:
3184 mod = None
3205 mod = None
3185 doc = extensions.disabledext(name)
3206 doc = extensions.disabledext(name)
3186 if not doc:
3207 if not doc:
3187 raise error.UnknownCommand(name)
3208 raise error.UnknownCommand(name)
3188
3209
3189 if '\n' not in doc:
3210 if '\n' not in doc:
3190 head, tail = doc, ""
3211 head, tail = doc, ""
3191 else:
3212 else:
3192 head, tail = doc.split('\n', 1)
3213 head, tail = doc.split('\n', 1)
3193 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3214 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3194 if tail:
3215 if tail:
3195 ui.write(minirst.format(tail, textwidth))
3216 ui.write(minirst.format(tail, textwidth))
3196 ui.status('\n')
3217 ui.status('\n')
3197
3218
3198 if mod:
3219 if mod:
3199 try:
3220 try:
3200 ct = mod.cmdtable
3221 ct = mod.cmdtable
3201 except AttributeError:
3222 except AttributeError:
3202 ct = {}
3223 ct = {}
3203 modcmds = set([c.split('|', 1)[0] for c in ct])
3224 modcmds = set([c.split('|', 1)[0] for c in ct])
3204 helplist(modcmds.__contains__)
3225 helplist(modcmds.__contains__)
3205 else:
3226 else:
3206 ui.write(_('use "hg help extensions" for information on enabling '
3227 ui.write(_('use "hg help extensions" for information on enabling '
3207 'extensions\n'))
3228 'extensions\n'))
3208
3229
3209 def helpextcmd(name):
3230 def helpextcmd(name):
3210 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3231 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3211 doc = gettext(mod.__doc__).splitlines()[0]
3232 doc = gettext(mod.__doc__).splitlines()[0]
3212
3233
3213 msg = help.listexts(_("'%s' is provided by the following "
3234 msg = help.listexts(_("'%s' is provided by the following "
3214 "extension:") % cmd, {ext: doc}, indent=4)
3235 "extension:") % cmd, {ext: doc}, indent=4)
3215 ui.write(minirst.format(msg, textwidth))
3236 ui.write(minirst.format(msg, textwidth))
3216 ui.write('\n')
3237 ui.write('\n')
3217 ui.write(_('use "hg help extensions" for information on enabling '
3238 ui.write(_('use "hg help extensions" for information on enabling '
3218 'extensions\n'))
3239 'extensions\n'))
3219
3240
3220 if name and name != 'shortlist':
3241 if name and name != 'shortlist':
3221 i = None
3242 i = None
3222 if unknowncmd:
3243 if unknowncmd:
3223 queries = (helpextcmd,)
3244 queries = (helpextcmd,)
3224 elif opts.get('extension'):
3245 elif opts.get('extension'):
3225 queries = (helpext,)
3246 queries = (helpext,)
3226 elif opts.get('command'):
3247 elif opts.get('command'):
3227 queries = (helpcmd,)
3248 queries = (helpcmd,)
3228 else:
3249 else:
3229 queries = (helptopic, helpcmd, helpext, helpextcmd)
3250 queries = (helptopic, helpcmd, helpext, helpextcmd)
3230 for f in queries:
3251 for f in queries:
3231 try:
3252 try:
3232 f(name)
3253 f(name)
3233 i = None
3254 i = None
3234 break
3255 break
3235 except error.UnknownCommand, inst:
3256 except error.UnknownCommand, inst:
3236 i = inst
3257 i = inst
3237 if i:
3258 if i:
3238 raise i
3259 raise i
3239 else:
3260 else:
3240 # program name
3261 # program name
3241 ui.status(_("Mercurial Distributed SCM\n"))
3262 ui.status(_("Mercurial Distributed SCM\n"))
3242 ui.status('\n')
3263 ui.status('\n')
3243 helplist()
3264 helplist()
3244
3265
3245
3266
3246 @command('identify|id',
3267 @command('identify|id',
3247 [('r', 'rev', '',
3268 [('r', 'rev', '',
3248 _('identify the specified revision'), _('REV')),
3269 _('identify the specified revision'), _('REV')),
3249 ('n', 'num', None, _('show local revision number')),
3270 ('n', 'num', None, _('show local revision number')),
3250 ('i', 'id', None, _('show global revision id')),
3271 ('i', 'id', None, _('show global revision id')),
3251 ('b', 'branch', None, _('show branch')),
3272 ('b', 'branch', None, _('show branch')),
3252 ('t', 'tags', None, _('show tags')),
3273 ('t', 'tags', None, _('show tags')),
3253 ('B', 'bookmarks', None, _('show bookmarks')),
3274 ('B', 'bookmarks', None, _('show bookmarks')),
3254 ] + remoteopts,
3275 ] + remoteopts,
3255 _('[-nibtB] [-r REV] [SOURCE]'))
3276 _('[-nibtB] [-r REV] [SOURCE]'))
3256 def identify(ui, repo, source=None, rev=None,
3277 def identify(ui, repo, source=None, rev=None,
3257 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3278 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3258 """identify the working copy or specified revision
3279 """identify the working copy or specified revision
3259
3280
3260 Print a summary identifying the repository state at REV using one or
3281 Print a summary identifying the repository state at REV using one or
3261 two parent hash identifiers, followed by a "+" if the working
3282 two parent hash identifiers, followed by a "+" if the working
3262 directory has uncommitted changes, the branch name (if not default),
3283 directory has uncommitted changes, the branch name (if not default),
3263 a list of tags, and a list of bookmarks.
3284 a list of tags, and a list of bookmarks.
3264
3285
3265 When REV is not given, print a summary of the current state of the
3286 When REV is not given, print a summary of the current state of the
3266 repository.
3287 repository.
3267
3288
3268 Specifying a path to a repository root or Mercurial bundle will
3289 Specifying a path to a repository root or Mercurial bundle will
3269 cause lookup to operate on that repository/bundle.
3290 cause lookup to operate on that repository/bundle.
3270
3291
3271 .. container:: verbose
3292 .. container:: verbose
3272
3293
3273 Examples:
3294 Examples:
3274
3295
3275 - generate a build identifier for the working directory::
3296 - generate a build identifier for the working directory::
3276
3297
3277 hg id --id > build-id.dat
3298 hg id --id > build-id.dat
3278
3299
3279 - find the revision corresponding to a tag::
3300 - find the revision corresponding to a tag::
3280
3301
3281 hg id -n -r 1.3
3302 hg id -n -r 1.3
3282
3303
3283 - check the most recent revision of a remote repository::
3304 - check the most recent revision of a remote repository::
3284
3305
3285 hg id -r tip http://selenic.com/hg/
3306 hg id -r tip http://selenic.com/hg/
3286
3307
3287 Returns 0 if successful.
3308 Returns 0 if successful.
3288 """
3309 """
3289
3310
3290 if not repo and not source:
3311 if not repo and not source:
3291 raise util.Abort(_("there is no Mercurial repository here "
3312 raise util.Abort(_("there is no Mercurial repository here "
3292 "(.hg not found)"))
3313 "(.hg not found)"))
3293
3314
3294 hexfunc = ui.debugflag and hex or short
3315 hexfunc = ui.debugflag and hex or short
3295 default = not (num or id or branch or tags or bookmarks)
3316 default = not (num or id or branch or tags or bookmarks)
3296 output = []
3317 output = []
3297 revs = []
3318 revs = []
3298
3319
3299 if source:
3320 if source:
3300 source, branches = hg.parseurl(ui.expandpath(source))
3321 source, branches = hg.parseurl(ui.expandpath(source))
3301 repo = hg.peer(ui, opts, source)
3322 repo = hg.peer(ui, opts, source)
3302 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3323 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3303
3324
3304 if not repo.local():
3325 if not repo.local():
3305 if num or branch or tags:
3326 if num or branch or tags:
3306 raise util.Abort(
3327 raise util.Abort(
3307 _("can't query remote revision number, branch, or tags"))
3328 _("can't query remote revision number, branch, or tags"))
3308 if not rev and revs:
3329 if not rev and revs:
3309 rev = revs[0]
3330 rev = revs[0]
3310 if not rev:
3331 if not rev:
3311 rev = "tip"
3332 rev = "tip"
3312
3333
3313 remoterev = repo.lookup(rev)
3334 remoterev = repo.lookup(rev)
3314 if default or id:
3335 if default or id:
3315 output = [hexfunc(remoterev)]
3336 output = [hexfunc(remoterev)]
3316
3337
3317 def getbms():
3338 def getbms():
3318 bms = []
3339 bms = []
3319
3340
3320 if 'bookmarks' in repo.listkeys('namespaces'):
3341 if 'bookmarks' in repo.listkeys('namespaces'):
3321 hexremoterev = hex(remoterev)
3342 hexremoterev = hex(remoterev)
3322 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3343 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3323 if bmr == hexremoterev]
3344 if bmr == hexremoterev]
3324
3345
3325 return bms
3346 return bms
3326
3347
3327 if bookmarks:
3348 if bookmarks:
3328 output.extend(getbms())
3349 output.extend(getbms())
3329 elif default and not ui.quiet:
3350 elif default and not ui.quiet:
3330 # multiple bookmarks for a single parent separated by '/'
3351 # multiple bookmarks for a single parent separated by '/'
3331 bm = '/'.join(getbms())
3352 bm = '/'.join(getbms())
3332 if bm:
3353 if bm:
3333 output.append(bm)
3354 output.append(bm)
3334 else:
3355 else:
3335 if not rev:
3356 if not rev:
3336 ctx = repo[None]
3357 ctx = repo[None]
3337 parents = ctx.parents()
3358 parents = ctx.parents()
3338 changed = ""
3359 changed = ""
3339 if default or id or num:
3360 if default or id or num:
3340 changed = util.any(repo.status()) and "+" or ""
3361 changed = util.any(repo.status()) and "+" or ""
3341 if default or id:
3362 if default or id:
3342 output = ["%s%s" %
3363 output = ["%s%s" %
3343 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3364 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3344 if num:
3365 if num:
3345 output.append("%s%s" %
3366 output.append("%s%s" %
3346 ('+'.join([str(p.rev()) for p in parents]), changed))
3367 ('+'.join([str(p.rev()) for p in parents]), changed))
3347 else:
3368 else:
3348 ctx = scmutil.revsingle(repo, rev)
3369 ctx = scmutil.revsingle(repo, rev)
3349 if default or id:
3370 if default or id:
3350 output = [hexfunc(ctx.node())]
3371 output = [hexfunc(ctx.node())]
3351 if num:
3372 if num:
3352 output.append(str(ctx.rev()))
3373 output.append(str(ctx.rev()))
3353
3374
3354 if default and not ui.quiet:
3375 if default and not ui.quiet:
3355 b = ctx.branch()
3376 b = ctx.branch()
3356 if b != 'default':
3377 if b != 'default':
3357 output.append("(%s)" % b)
3378 output.append("(%s)" % b)
3358
3379
3359 # multiple tags for a single parent separated by '/'
3380 # multiple tags for a single parent separated by '/'
3360 t = '/'.join(ctx.tags())
3381 t = '/'.join(ctx.tags())
3361 if t:
3382 if t:
3362 output.append(t)
3383 output.append(t)
3363
3384
3364 # multiple bookmarks for a single parent separated by '/'
3385 # multiple bookmarks for a single parent separated by '/'
3365 bm = '/'.join(ctx.bookmarks())
3386 bm = '/'.join(ctx.bookmarks())
3366 if bm:
3387 if bm:
3367 output.append(bm)
3388 output.append(bm)
3368 else:
3389 else:
3369 if branch:
3390 if branch:
3370 output.append(ctx.branch())
3391 output.append(ctx.branch())
3371
3392
3372 if tags:
3393 if tags:
3373 output.extend(ctx.tags())
3394 output.extend(ctx.tags())
3374
3395
3375 if bookmarks:
3396 if bookmarks:
3376 output.extend(ctx.bookmarks())
3397 output.extend(ctx.bookmarks())
3377
3398
3378 ui.write("%s\n" % ' '.join(output))
3399 ui.write("%s\n" % ' '.join(output))
3379
3400
3380 @command('import|patch',
3401 @command('import|patch',
3381 [('p', 'strip', 1,
3402 [('p', 'strip', 1,
3382 _('directory strip option for patch. This has the same '
3403 _('directory strip option for patch. This has the same '
3383 'meaning as the corresponding patch option'), _('NUM')),
3404 'meaning as the corresponding patch option'), _('NUM')),
3384 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3405 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3385 ('e', 'edit', False, _('invoke editor on commit messages')),
3406 ('e', 'edit', False, _('invoke editor on commit messages')),
3386 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3407 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3387 ('', 'no-commit', None,
3408 ('', 'no-commit', None,
3388 _("don't commit, just update the working directory")),
3409 _("don't commit, just update the working directory")),
3389 ('', 'bypass', None,
3410 ('', 'bypass', None,
3390 _("apply patch without touching the working directory")),
3411 _("apply patch without touching the working directory")),
3391 ('', 'exact', None,
3412 ('', 'exact', None,
3392 _('apply patch to the nodes from which it was generated')),
3413 _('apply patch to the nodes from which it was generated')),
3393 ('', 'import-branch', None,
3414 ('', 'import-branch', None,
3394 _('use any branch information in patch (implied by --exact)'))] +
3415 _('use any branch information in patch (implied by --exact)'))] +
3395 commitopts + commitopts2 + similarityopts,
3416 commitopts + commitopts2 + similarityopts,
3396 _('[OPTION]... PATCH...'))
3417 _('[OPTION]... PATCH...'))
3397 def import_(ui, repo, patch1=None, *patches, **opts):
3418 def import_(ui, repo, patch1=None, *patches, **opts):
3398 """import an ordered set of patches
3419 """import an ordered set of patches
3399
3420
3400 Import a list of patches and commit them individually (unless
3421 Import a list of patches and commit them individually (unless
3401 --no-commit is specified).
3422 --no-commit is specified).
3402
3423
3403 If there are outstanding changes in the working directory, import
3424 If there are outstanding changes in the working directory, import
3404 will abort unless given the -f/--force flag.
3425 will abort unless given the -f/--force flag.
3405
3426
3406 You can import a patch straight from a mail message. Even patches
3427 You can import a patch straight from a mail message. Even patches
3407 as attachments work (to use the body part, it must have type
3428 as attachments work (to use the body part, it must have type
3408 text/plain or text/x-patch). From and Subject headers of email
3429 text/plain or text/x-patch). From and Subject headers of email
3409 message are used as default committer and commit message. All
3430 message are used as default committer and commit message. All
3410 text/plain body parts before first diff are added to commit
3431 text/plain body parts before first diff are added to commit
3411 message.
3432 message.
3412
3433
3413 If the imported patch was generated by :hg:`export`, user and
3434 If the imported patch was generated by :hg:`export`, user and
3414 description from patch override values from message headers and
3435 description from patch override values from message headers and
3415 body. Values given on command line with -m/--message and -u/--user
3436 body. Values given on command line with -m/--message and -u/--user
3416 override these.
3437 override these.
3417
3438
3418 If --exact is specified, import will set the working directory to
3439 If --exact is specified, import will set the working directory to
3419 the parent of each patch before applying it, and will abort if the
3440 the parent of each patch before applying it, and will abort if the
3420 resulting changeset has a different ID than the one recorded in
3441 resulting changeset has a different ID than the one recorded in
3421 the patch. This may happen due to character set problems or other
3442 the patch. This may happen due to character set problems or other
3422 deficiencies in the text patch format.
3443 deficiencies in the text patch format.
3423
3444
3424 Use --bypass to apply and commit patches directly to the
3445 Use --bypass to apply and commit patches directly to the
3425 repository, not touching the working directory. Without --exact,
3446 repository, not touching the working directory. Without --exact,
3426 patches will be applied on top of the working directory parent
3447 patches will be applied on top of the working directory parent
3427 revision.
3448 revision.
3428
3449
3429 With -s/--similarity, hg will attempt to discover renames and
3450 With -s/--similarity, hg will attempt to discover renames and
3430 copies in the patch in the same way as :hg:`addremove`.
3451 copies in the patch in the same way as :hg:`addremove`.
3431
3452
3432 To read a patch from standard input, use "-" as the patch name. If
3453 To read a patch from standard input, use "-" as the patch name. If
3433 a URL is specified, the patch will be downloaded from it.
3454 a URL is specified, the patch will be downloaded from it.
3434 See :hg:`help dates` for a list of formats valid for -d/--date.
3455 See :hg:`help dates` for a list of formats valid for -d/--date.
3435
3456
3436 .. container:: verbose
3457 .. container:: verbose
3437
3458
3438 Examples:
3459 Examples:
3439
3460
3440 - import a traditional patch from a website and detect renames::
3461 - import a traditional patch from a website and detect renames::
3441
3462
3442 hg import -s 80 http://example.com/bugfix.patch
3463 hg import -s 80 http://example.com/bugfix.patch
3443
3464
3444 - import a changeset from an hgweb server::
3465 - import a changeset from an hgweb server::
3445
3466
3446 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3467 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3447
3468
3448 - import all the patches in an Unix-style mbox::
3469 - import all the patches in an Unix-style mbox::
3449
3470
3450 hg import incoming-patches.mbox
3471 hg import incoming-patches.mbox
3451
3472
3452 - attempt to exactly restore an exported changeset (not always
3473 - attempt to exactly restore an exported changeset (not always
3453 possible)::
3474 possible)::
3454
3475
3455 hg import --exact proposed-fix.patch
3476 hg import --exact proposed-fix.patch
3456
3477
3457 Returns 0 on success.
3478 Returns 0 on success.
3458 """
3479 """
3459
3480
3460 if not patch1:
3481 if not patch1:
3461 raise util.Abort(_('need at least one patch to import'))
3482 raise util.Abort(_('need at least one patch to import'))
3462
3483
3463 patches = (patch1,) + patches
3484 patches = (patch1,) + patches
3464
3485
3465 date = opts.get('date')
3486 date = opts.get('date')
3466 if date:
3487 if date:
3467 opts['date'] = util.parsedate(date)
3488 opts['date'] = util.parsedate(date)
3468
3489
3469 editor = cmdutil.commiteditor
3490 editor = cmdutil.commiteditor
3470 if opts.get('edit'):
3491 if opts.get('edit'):
3471 editor = cmdutil.commitforceeditor
3492 editor = cmdutil.commitforceeditor
3472
3493
3473 update = not opts.get('bypass')
3494 update = not opts.get('bypass')
3474 if not update and opts.get('no_commit'):
3495 if not update and opts.get('no_commit'):
3475 raise util.Abort(_('cannot use --no-commit with --bypass'))
3496 raise util.Abort(_('cannot use --no-commit with --bypass'))
3476 try:
3497 try:
3477 sim = float(opts.get('similarity') or 0)
3498 sim = float(opts.get('similarity') or 0)
3478 except ValueError:
3499 except ValueError:
3479 raise util.Abort(_('similarity must be a number'))
3500 raise util.Abort(_('similarity must be a number'))
3480 if sim < 0 or sim > 100:
3501 if sim < 0 or sim > 100:
3481 raise util.Abort(_('similarity must be between 0 and 100'))
3502 raise util.Abort(_('similarity must be between 0 and 100'))
3482 if sim and not update:
3503 if sim and not update:
3483 raise util.Abort(_('cannot use --similarity with --bypass'))
3504 raise util.Abort(_('cannot use --similarity with --bypass'))
3484
3505
3485 if (opts.get('exact') or not opts.get('force')) and update:
3506 if (opts.get('exact') or not opts.get('force')) and update:
3486 cmdutil.bailifchanged(repo)
3507 cmdutil.bailifchanged(repo)
3487
3508
3488 base = opts["base"]
3509 base = opts["base"]
3489 strip = opts["strip"]
3510 strip = opts["strip"]
3490 wlock = lock = tr = None
3511 wlock = lock = tr = None
3491 msgs = []
3512 msgs = []
3492
3513
3493 def checkexact(repo, n, nodeid):
3514 def checkexact(repo, n, nodeid):
3494 if opts.get('exact') and hex(n) != nodeid:
3515 if opts.get('exact') and hex(n) != nodeid:
3495 repo.rollback()
3516 repo.rollback()
3496 raise util.Abort(_('patch is damaged or loses information'))
3517 raise util.Abort(_('patch is damaged or loses information'))
3497
3518
3498 def tryone(ui, hunk, parents):
3519 def tryone(ui, hunk, parents):
3499 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3520 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3500 patch.extract(ui, hunk)
3521 patch.extract(ui, hunk)
3501
3522
3502 if not tmpname:
3523 if not tmpname:
3503 return (None, None)
3524 return (None, None)
3504 msg = _('applied to working directory')
3525 msg = _('applied to working directory')
3505
3526
3506 try:
3527 try:
3507 cmdline_message = cmdutil.logmessage(ui, opts)
3528 cmdline_message = cmdutil.logmessage(ui, opts)
3508 if cmdline_message:
3529 if cmdline_message:
3509 # pickup the cmdline msg
3530 # pickup the cmdline msg
3510 message = cmdline_message
3531 message = cmdline_message
3511 elif message:
3532 elif message:
3512 # pickup the patch msg
3533 # pickup the patch msg
3513 message = message.strip()
3534 message = message.strip()
3514 else:
3535 else:
3515 # launch the editor
3536 # launch the editor
3516 message = None
3537 message = None
3517 ui.debug('message:\n%s\n' % message)
3538 ui.debug('message:\n%s\n' % message)
3518
3539
3519 if len(parents) == 1:
3540 if len(parents) == 1:
3520 parents.append(repo[nullid])
3541 parents.append(repo[nullid])
3521 if opts.get('exact'):
3542 if opts.get('exact'):
3522 if not nodeid or not p1:
3543 if not nodeid or not p1:
3523 raise util.Abort(_('not a Mercurial patch'))
3544 raise util.Abort(_('not a Mercurial patch'))
3524 p1 = repo[p1]
3545 p1 = repo[p1]
3525 p2 = repo[p2 or nullid]
3546 p2 = repo[p2 or nullid]
3526 elif p2:
3547 elif p2:
3527 try:
3548 try:
3528 p1 = repo[p1]
3549 p1 = repo[p1]
3529 p2 = repo[p2]
3550 p2 = repo[p2]
3530 # Without any options, consider p2 only if the
3551 # Without any options, consider p2 only if the
3531 # patch is being applied on top of the recorded
3552 # patch is being applied on top of the recorded
3532 # first parent.
3553 # first parent.
3533 if p1 != parents[0]:
3554 if p1 != parents[0]:
3534 p1 = parents[0]
3555 p1 = parents[0]
3535 p2 = repo[nullid]
3556 p2 = repo[nullid]
3536 except error.RepoError:
3557 except error.RepoError:
3537 p1, p2 = parents
3558 p1, p2 = parents
3538 else:
3559 else:
3539 p1, p2 = parents
3560 p1, p2 = parents
3540
3561
3541 n = None
3562 n = None
3542 if update:
3563 if update:
3543 if p1 != parents[0]:
3564 if p1 != parents[0]:
3544 hg.clean(repo, p1.node())
3565 hg.clean(repo, p1.node())
3545 if p2 != parents[1]:
3566 if p2 != parents[1]:
3546 repo.dirstate.setparents(p1.node(), p2.node())
3567 repo.dirstate.setparents(p1.node(), p2.node())
3547
3568
3548 if opts.get('exact') or opts.get('import_branch'):
3569 if opts.get('exact') or opts.get('import_branch'):
3549 repo.dirstate.setbranch(branch or 'default')
3570 repo.dirstate.setbranch(branch or 'default')
3550
3571
3551 files = set()
3572 files = set()
3552 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3573 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3553 eolmode=None, similarity=sim / 100.0)
3574 eolmode=None, similarity=sim / 100.0)
3554 files = list(files)
3575 files = list(files)
3555 if opts.get('no_commit'):
3576 if opts.get('no_commit'):
3556 if message:
3577 if message:
3557 msgs.append(message)
3578 msgs.append(message)
3558 else:
3579 else:
3559 if opts.get('exact') or p2:
3580 if opts.get('exact') or p2:
3560 # If you got here, you either use --force and know what
3581 # If you got here, you either use --force and know what
3561 # you are doing or used --exact or a merge patch while
3582 # you are doing or used --exact or a merge patch while
3562 # being updated to its first parent.
3583 # being updated to its first parent.
3563 m = None
3584 m = None
3564 else:
3585 else:
3565 m = scmutil.matchfiles(repo, files or [])
3586 m = scmutil.matchfiles(repo, files or [])
3566 n = repo.commit(message, opts.get('user') or user,
3587 n = repo.commit(message, opts.get('user') or user,
3567 opts.get('date') or date, match=m,
3588 opts.get('date') or date, match=m,
3568 editor=editor)
3589 editor=editor)
3569 checkexact(repo, n, nodeid)
3590 checkexact(repo, n, nodeid)
3570 else:
3591 else:
3571 if opts.get('exact') or opts.get('import_branch'):
3592 if opts.get('exact') or opts.get('import_branch'):
3572 branch = branch or 'default'
3593 branch = branch or 'default'
3573 else:
3594 else:
3574 branch = p1.branch()
3595 branch = p1.branch()
3575 store = patch.filestore()
3596 store = patch.filestore()
3576 try:
3597 try:
3577 files = set()
3598 files = set()
3578 try:
3599 try:
3579 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3600 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3580 files, eolmode=None)
3601 files, eolmode=None)
3581 except patch.PatchError, e:
3602 except patch.PatchError, e:
3582 raise util.Abort(str(e))
3603 raise util.Abort(str(e))
3583 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3604 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3584 message,
3605 message,
3585 opts.get('user') or user,
3606 opts.get('user') or user,
3586 opts.get('date') or date,
3607 opts.get('date') or date,
3587 branch, files, store,
3608 branch, files, store,
3588 editor=cmdutil.commiteditor)
3609 editor=cmdutil.commiteditor)
3589 repo.savecommitmessage(memctx.description())
3610 repo.savecommitmessage(memctx.description())
3590 n = memctx.commit()
3611 n = memctx.commit()
3591 checkexact(repo, n, nodeid)
3612 checkexact(repo, n, nodeid)
3592 finally:
3613 finally:
3593 store.close()
3614 store.close()
3594 if n:
3615 if n:
3595 # i18n: refers to a short changeset id
3616 # i18n: refers to a short changeset id
3596 msg = _('created %s') % short(n)
3617 msg = _('created %s') % short(n)
3597 return (msg, n)
3618 return (msg, n)
3598 finally:
3619 finally:
3599 os.unlink(tmpname)
3620 os.unlink(tmpname)
3600
3621
3601 try:
3622 try:
3602 try:
3623 try:
3603 wlock = repo.wlock()
3624 wlock = repo.wlock()
3604 lock = repo.lock()
3625 lock = repo.lock()
3605 tr = repo.transaction('import')
3626 tr = repo.transaction('import')
3606 parents = repo.parents()
3627 parents = repo.parents()
3607 for patchurl in patches:
3628 for patchurl in patches:
3608 if patchurl == '-':
3629 if patchurl == '-':
3609 ui.status(_('applying patch from stdin\n'))
3630 ui.status(_('applying patch from stdin\n'))
3610 patchfile = ui.fin
3631 patchfile = ui.fin
3611 patchurl = 'stdin' # for error message
3632 patchurl = 'stdin' # for error message
3612 else:
3633 else:
3613 patchurl = os.path.join(base, patchurl)
3634 patchurl = os.path.join(base, patchurl)
3614 ui.status(_('applying %s\n') % patchurl)
3635 ui.status(_('applying %s\n') % patchurl)
3615 patchfile = url.open(ui, patchurl)
3636 patchfile = url.open(ui, patchurl)
3616
3637
3617 haspatch = False
3638 haspatch = False
3618 for hunk in patch.split(patchfile):
3639 for hunk in patch.split(patchfile):
3619 (msg, node) = tryone(ui, hunk, parents)
3640 (msg, node) = tryone(ui, hunk, parents)
3620 if msg:
3641 if msg:
3621 haspatch = True
3642 haspatch = True
3622 ui.note(msg + '\n')
3643 ui.note(msg + '\n')
3623 if update or opts.get('exact'):
3644 if update or opts.get('exact'):
3624 parents = repo.parents()
3645 parents = repo.parents()
3625 else:
3646 else:
3626 parents = [repo[node]]
3647 parents = [repo[node]]
3627
3648
3628 if not haspatch:
3649 if not haspatch:
3629 raise util.Abort(_('%s: no diffs found') % patchurl)
3650 raise util.Abort(_('%s: no diffs found') % patchurl)
3630
3651
3631 tr.close()
3652 tr.close()
3632 if msgs:
3653 if msgs:
3633 repo.savecommitmessage('\n* * *\n'.join(msgs))
3654 repo.savecommitmessage('\n* * *\n'.join(msgs))
3634 except:
3655 except:
3635 # wlock.release() indirectly calls dirstate.write(): since
3656 # wlock.release() indirectly calls dirstate.write(): since
3636 # we're crashing, we do not want to change the working dir
3657 # we're crashing, we do not want to change the working dir
3637 # parent after all, so make sure it writes nothing
3658 # parent after all, so make sure it writes nothing
3638 repo.dirstate.invalidate()
3659 repo.dirstate.invalidate()
3639 raise
3660 raise
3640 finally:
3661 finally:
3641 if tr:
3662 if tr:
3642 tr.release()
3663 tr.release()
3643 release(lock, wlock)
3664 release(lock, wlock)
3644
3665
3645 @command('incoming|in',
3666 @command('incoming|in',
3646 [('f', 'force', None,
3667 [('f', 'force', None,
3647 _('run even if remote repository is unrelated')),
3668 _('run even if remote repository is unrelated')),
3648 ('n', 'newest-first', None, _('show newest record first')),
3669 ('n', 'newest-first', None, _('show newest record first')),
3649 ('', 'bundle', '',
3670 ('', 'bundle', '',
3650 _('file to store the bundles into'), _('FILE')),
3671 _('file to store the bundles into'), _('FILE')),
3651 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3672 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3652 ('B', 'bookmarks', False, _("compare bookmarks")),
3673 ('B', 'bookmarks', False, _("compare bookmarks")),
3653 ('b', 'branch', [],
3674 ('b', 'branch', [],
3654 _('a specific branch you would like to pull'), _('BRANCH')),
3675 _('a specific branch you would like to pull'), _('BRANCH')),
3655 ] + logopts + remoteopts + subrepoopts,
3676 ] + logopts + remoteopts + subrepoopts,
3656 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3677 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3657 def incoming(ui, repo, source="default", **opts):
3678 def incoming(ui, repo, source="default", **opts):
3658 """show new changesets found in source
3679 """show new changesets found in source
3659
3680
3660 Show new changesets found in the specified path/URL or the default
3681 Show new changesets found in the specified path/URL or the default
3661 pull location. These are the changesets that would have been pulled
3682 pull location. These are the changesets that would have been pulled
3662 if a pull at the time you issued this command.
3683 if a pull at the time you issued this command.
3663
3684
3664 For remote repository, using --bundle avoids downloading the
3685 For remote repository, using --bundle avoids downloading the
3665 changesets twice if the incoming is followed by a pull.
3686 changesets twice if the incoming is followed by a pull.
3666
3687
3667 See pull for valid source format details.
3688 See pull for valid source format details.
3668
3689
3669 Returns 0 if there are incoming changes, 1 otherwise.
3690 Returns 0 if there are incoming changes, 1 otherwise.
3670 """
3691 """
3671 if opts.get('bundle') and opts.get('subrepos'):
3692 if opts.get('bundle') and opts.get('subrepos'):
3672 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3693 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3673
3694
3674 if opts.get('bookmarks'):
3695 if opts.get('bookmarks'):
3675 source, branches = hg.parseurl(ui.expandpath(source),
3696 source, branches = hg.parseurl(ui.expandpath(source),
3676 opts.get('branch'))
3697 opts.get('branch'))
3677 other = hg.peer(repo, opts, source)
3698 other = hg.peer(repo, opts, source)
3678 if 'bookmarks' not in other.listkeys('namespaces'):
3699 if 'bookmarks' not in other.listkeys('namespaces'):
3679 ui.warn(_("remote doesn't support bookmarks\n"))
3700 ui.warn(_("remote doesn't support bookmarks\n"))
3680 return 0
3701 return 0
3681 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3702 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3682 return bookmarks.diff(ui, repo, other)
3703 return bookmarks.diff(ui, repo, other)
3683
3704
3684 repo._subtoppath = ui.expandpath(source)
3705 repo._subtoppath = ui.expandpath(source)
3685 try:
3706 try:
3686 return hg.incoming(ui, repo, source, opts)
3707 return hg.incoming(ui, repo, source, opts)
3687 finally:
3708 finally:
3688 del repo._subtoppath
3709 del repo._subtoppath
3689
3710
3690
3711
3691 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3712 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3692 def init(ui, dest=".", **opts):
3713 def init(ui, dest=".", **opts):
3693 """create a new repository in the given directory
3714 """create a new repository in the given directory
3694
3715
3695 Initialize a new repository in the given directory. If the given
3716 Initialize a new repository in the given directory. If the given
3696 directory does not exist, it will be created.
3717 directory does not exist, it will be created.
3697
3718
3698 If no directory is given, the current directory is used.
3719 If no directory is given, the current directory is used.
3699
3720
3700 It is possible to specify an ``ssh://`` URL as the destination.
3721 It is possible to specify an ``ssh://`` URL as the destination.
3701 See :hg:`help urls` for more information.
3722 See :hg:`help urls` for more information.
3702
3723
3703 Returns 0 on success.
3724 Returns 0 on success.
3704 """
3725 """
3705 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3726 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3706
3727
3707 @command('locate',
3728 @command('locate',
3708 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3729 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3709 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3730 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3710 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3731 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3711 ] + walkopts,
3732 ] + walkopts,
3712 _('[OPTION]... [PATTERN]...'))
3733 _('[OPTION]... [PATTERN]...'))
3713 def locate(ui, repo, *pats, **opts):
3734 def locate(ui, repo, *pats, **opts):
3714 """locate files matching specific patterns
3735 """locate files matching specific patterns
3715
3736
3716 Print files under Mercurial control in the working directory whose
3737 Print files under Mercurial control in the working directory whose
3717 names match the given patterns.
3738 names match the given patterns.
3718
3739
3719 By default, this command searches all directories in the working
3740 By default, this command searches all directories in the working
3720 directory. To search just the current directory and its
3741 directory. To search just the current directory and its
3721 subdirectories, use "--include .".
3742 subdirectories, use "--include .".
3722
3743
3723 If no patterns are given to match, this command prints the names
3744 If no patterns are given to match, this command prints the names
3724 of all files under Mercurial control in the working directory.
3745 of all files under Mercurial control in the working directory.
3725
3746
3726 If you want to feed the output of this command into the "xargs"
3747 If you want to feed the output of this command into the "xargs"
3727 command, use the -0 option to both this command and "xargs". This
3748 command, use the -0 option to both this command and "xargs". This
3728 will avoid the problem of "xargs" treating single filenames that
3749 will avoid the problem of "xargs" treating single filenames that
3729 contain whitespace as multiple filenames.
3750 contain whitespace as multiple filenames.
3730
3751
3731 Returns 0 if a match is found, 1 otherwise.
3752 Returns 0 if a match is found, 1 otherwise.
3732 """
3753 """
3733 end = opts.get('print0') and '\0' or '\n'
3754 end = opts.get('print0') and '\0' or '\n'
3734 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3755 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3735
3756
3736 ret = 1
3757 ret = 1
3737 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3758 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3738 m.bad = lambda x, y: False
3759 m.bad = lambda x, y: False
3739 for abs in repo[rev].walk(m):
3760 for abs in repo[rev].walk(m):
3740 if not rev and abs not in repo.dirstate:
3761 if not rev and abs not in repo.dirstate:
3741 continue
3762 continue
3742 if opts.get('fullpath'):
3763 if opts.get('fullpath'):
3743 ui.write(repo.wjoin(abs), end)
3764 ui.write(repo.wjoin(abs), end)
3744 else:
3765 else:
3745 ui.write(((pats and m.rel(abs)) or abs), end)
3766 ui.write(((pats and m.rel(abs)) or abs), end)
3746 ret = 0
3767 ret = 0
3747
3768
3748 return ret
3769 return ret
3749
3770
3750 @command('^log|history',
3771 @command('^log|history',
3751 [('f', 'follow', None,
3772 [('f', 'follow', None,
3752 _('follow changeset history, or file history across copies and renames')),
3773 _('follow changeset history, or file history across copies and renames')),
3753 ('', 'follow-first', None,
3774 ('', 'follow-first', None,
3754 _('only follow the first parent of merge changesets (DEPRECATED)')),
3775 _('only follow the first parent of merge changesets (DEPRECATED)')),
3755 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3776 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3756 ('C', 'copies', None, _('show copied files')),
3777 ('C', 'copies', None, _('show copied files')),
3757 ('k', 'keyword', [],
3778 ('k', 'keyword', [],
3758 _('do case-insensitive search for a given text'), _('TEXT')),
3779 _('do case-insensitive search for a given text'), _('TEXT')),
3759 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3780 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3760 ('', 'removed', None, _('include revisions where files were removed')),
3781 ('', 'removed', None, _('include revisions where files were removed')),
3761 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3782 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3762 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3783 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3763 ('', 'only-branch', [],
3784 ('', 'only-branch', [],
3764 _('show only changesets within the given named branch (DEPRECATED)'),
3785 _('show only changesets within the given named branch (DEPRECATED)'),
3765 _('BRANCH')),
3786 _('BRANCH')),
3766 ('b', 'branch', [],
3787 ('b', 'branch', [],
3767 _('show changesets within the given named branch'), _('BRANCH')),
3788 _('show changesets within the given named branch'), _('BRANCH')),
3768 ('P', 'prune', [],
3789 ('P', 'prune', [],
3769 _('do not display revision or any of its ancestors'), _('REV')),
3790 _('do not display revision or any of its ancestors'), _('REV')),
3770 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3791 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3771 ] + logopts + walkopts,
3792 ] + logopts + walkopts,
3772 _('[OPTION]... [FILE]'))
3793 _('[OPTION]... [FILE]'))
3773 def log(ui, repo, *pats, **opts):
3794 def log(ui, repo, *pats, **opts):
3774 """show revision history of entire repository or files
3795 """show revision history of entire repository or files
3775
3796
3776 Print the revision history of the specified files or the entire
3797 Print the revision history of the specified files or the entire
3777 project.
3798 project.
3778
3799
3779 If no revision range is specified, the default is ``tip:0`` unless
3800 If no revision range is specified, the default is ``tip:0`` unless
3780 --follow is set, in which case the working directory parent is
3801 --follow is set, in which case the working directory parent is
3781 used as the starting revision.
3802 used as the starting revision.
3782
3803
3783 File history is shown without following rename or copy history of
3804 File history is shown without following rename or copy history of
3784 files. Use -f/--follow with a filename to follow history across
3805 files. Use -f/--follow with a filename to follow history across
3785 renames and copies. --follow without a filename will only show
3806 renames and copies. --follow without a filename will only show
3786 ancestors or descendants of the starting revision.
3807 ancestors or descendants of the starting revision.
3787
3808
3788 By default this command prints revision number and changeset id,
3809 By default this command prints revision number and changeset id,
3789 tags, non-trivial parents, user, date and time, and a summary for
3810 tags, non-trivial parents, user, date and time, and a summary for
3790 each commit. When the -v/--verbose switch is used, the list of
3811 each commit. When the -v/--verbose switch is used, the list of
3791 changed files and full commit message are shown.
3812 changed files and full commit message are shown.
3792
3813
3793 .. note::
3814 .. note::
3794 log -p/--patch may generate unexpected diff output for merge
3815 log -p/--patch may generate unexpected diff output for merge
3795 changesets, as it will only compare the merge changeset against
3816 changesets, as it will only compare the merge changeset against
3796 its first parent. Also, only files different from BOTH parents
3817 its first parent. Also, only files different from BOTH parents
3797 will appear in files:.
3818 will appear in files:.
3798
3819
3799 .. note::
3820 .. note::
3800 for performance reasons, log FILE may omit duplicate changes
3821 for performance reasons, log FILE may omit duplicate changes
3801 made on branches and will not show deletions. To see all
3822 made on branches and will not show deletions. To see all
3802 changes including duplicates and deletions, use the --removed
3823 changes including duplicates and deletions, use the --removed
3803 switch.
3824 switch.
3804
3825
3805 .. container:: verbose
3826 .. container:: verbose
3806
3827
3807 Some examples:
3828 Some examples:
3808
3829
3809 - changesets with full descriptions and file lists::
3830 - changesets with full descriptions and file lists::
3810
3831
3811 hg log -v
3832 hg log -v
3812
3833
3813 - changesets ancestral to the working directory::
3834 - changesets ancestral to the working directory::
3814
3835
3815 hg log -f
3836 hg log -f
3816
3837
3817 - last 10 commits on the current branch::
3838 - last 10 commits on the current branch::
3818
3839
3819 hg log -l 10 -b .
3840 hg log -l 10 -b .
3820
3841
3821 - changesets showing all modifications of a file, including removals::
3842 - changesets showing all modifications of a file, including removals::
3822
3843
3823 hg log --removed file.c
3844 hg log --removed file.c
3824
3845
3825 - all changesets that touch a directory, with diffs, excluding merges::
3846 - all changesets that touch a directory, with diffs, excluding merges::
3826
3847
3827 hg log -Mp lib/
3848 hg log -Mp lib/
3828
3849
3829 - all revision numbers that match a keyword::
3850 - all revision numbers that match a keyword::
3830
3851
3831 hg log -k bug --template "{rev}\\n"
3852 hg log -k bug --template "{rev}\\n"
3832
3853
3833 - check if a given changeset is included is a tagged release::
3854 - check if a given changeset is included is a tagged release::
3834
3855
3835 hg log -r "a21ccf and ancestor(1.9)"
3856 hg log -r "a21ccf and ancestor(1.9)"
3836
3857
3837 - find all changesets by some user in a date range::
3858 - find all changesets by some user in a date range::
3838
3859
3839 hg log -k alice -d "may 2008 to jul 2008"
3860 hg log -k alice -d "may 2008 to jul 2008"
3840
3861
3841 - summary of all changesets after the last tag::
3862 - summary of all changesets after the last tag::
3842
3863
3843 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3864 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3844
3865
3845 See :hg:`help dates` for a list of formats valid for -d/--date.
3866 See :hg:`help dates` for a list of formats valid for -d/--date.
3846
3867
3847 See :hg:`help revisions` and :hg:`help revsets` for more about
3868 See :hg:`help revisions` and :hg:`help revsets` for more about
3848 specifying revisions.
3869 specifying revisions.
3849
3870
3850 Returns 0 on success.
3871 Returns 0 on success.
3851 """
3872 """
3852
3873
3853 matchfn = scmutil.match(repo[None], pats, opts)
3874 matchfn = scmutil.match(repo[None], pats, opts)
3854 limit = cmdutil.loglimit(opts)
3875 limit = cmdutil.loglimit(opts)
3855 count = 0
3876 count = 0
3856
3877
3857 getrenamed, endrev = None, None
3878 getrenamed, endrev = None, None
3858 if opts.get('copies'):
3879 if opts.get('copies'):
3859 if opts.get('rev'):
3880 if opts.get('rev'):
3860 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3881 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3861 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3882 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3862
3883
3863 df = False
3884 df = False
3864 if opts["date"]:
3885 if opts["date"]:
3865 df = util.matchdate(opts["date"])
3886 df = util.matchdate(opts["date"])
3866
3887
3867 branches = opts.get('branch', []) + opts.get('only_branch', [])
3888 branches = opts.get('branch', []) + opts.get('only_branch', [])
3868 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3889 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3869
3890
3870 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3891 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3871 def prep(ctx, fns):
3892 def prep(ctx, fns):
3872 rev = ctx.rev()
3893 rev = ctx.rev()
3873 parents = [p for p in repo.changelog.parentrevs(rev)
3894 parents = [p for p in repo.changelog.parentrevs(rev)
3874 if p != nullrev]
3895 if p != nullrev]
3875 if opts.get('no_merges') and len(parents) == 2:
3896 if opts.get('no_merges') and len(parents) == 2:
3876 return
3897 return
3877 if opts.get('only_merges') and len(parents) != 2:
3898 if opts.get('only_merges') and len(parents) != 2:
3878 return
3899 return
3879 if opts.get('branch') and ctx.branch() not in opts['branch']:
3900 if opts.get('branch') and ctx.branch() not in opts['branch']:
3880 return
3901 return
3881 if not opts.get('hidden') and ctx.hidden():
3902 if not opts.get('hidden') and ctx.hidden():
3882 return
3903 return
3883 if df and not df(ctx.date()[0]):
3904 if df and not df(ctx.date()[0]):
3884 return
3905 return
3885
3906
3886 lower = encoding.lower
3907 lower = encoding.lower
3887 if opts.get('user'):
3908 if opts.get('user'):
3888 luser = lower(ctx.user())
3909 luser = lower(ctx.user())
3889 for k in [lower(x) for x in opts['user']]:
3910 for k in [lower(x) for x in opts['user']]:
3890 if (k in luser):
3911 if (k in luser):
3891 break
3912 break
3892 else:
3913 else:
3893 return
3914 return
3894 if opts.get('keyword'):
3915 if opts.get('keyword'):
3895 luser = lower(ctx.user())
3916 luser = lower(ctx.user())
3896 ldesc = lower(ctx.description())
3917 ldesc = lower(ctx.description())
3897 lfiles = lower(" ".join(ctx.files()))
3918 lfiles = lower(" ".join(ctx.files()))
3898 for k in [lower(x) for x in opts['keyword']]:
3919 for k in [lower(x) for x in opts['keyword']]:
3899 if (k in luser or k in ldesc or k in lfiles):
3920 if (k in luser or k in ldesc or k in lfiles):
3900 break
3921 break
3901 else:
3922 else:
3902 return
3923 return
3903
3924
3904 copies = None
3925 copies = None
3905 if getrenamed is not None and rev:
3926 if getrenamed is not None and rev:
3906 copies = []
3927 copies = []
3907 for fn in ctx.files():
3928 for fn in ctx.files():
3908 rename = getrenamed(fn, rev)
3929 rename = getrenamed(fn, rev)
3909 if rename:
3930 if rename:
3910 copies.append((fn, rename[0]))
3931 copies.append((fn, rename[0]))
3911
3932
3912 revmatchfn = None
3933 revmatchfn = None
3913 if opts.get('patch') or opts.get('stat'):
3934 if opts.get('patch') or opts.get('stat'):
3914 if opts.get('follow') or opts.get('follow_first'):
3935 if opts.get('follow') or opts.get('follow_first'):
3915 # note: this might be wrong when following through merges
3936 # note: this might be wrong when following through merges
3916 revmatchfn = scmutil.match(repo[None], fns, default='path')
3937 revmatchfn = scmutil.match(repo[None], fns, default='path')
3917 else:
3938 else:
3918 revmatchfn = matchfn
3939 revmatchfn = matchfn
3919
3940
3920 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3941 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3921
3942
3922 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3943 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3923 if count == limit:
3944 if count == limit:
3924 break
3945 break
3925 if displayer.flush(ctx.rev()):
3946 if displayer.flush(ctx.rev()):
3926 count += 1
3947 count += 1
3927 displayer.close()
3948 displayer.close()
3928
3949
3929 @command('manifest',
3950 @command('manifest',
3930 [('r', 'rev', '', _('revision to display'), _('REV')),
3951 [('r', 'rev', '', _('revision to display'), _('REV')),
3931 ('', 'all', False, _("list files from all revisions"))],
3952 ('', 'all', False, _("list files from all revisions"))],
3932 _('[-r REV]'))
3953 _('[-r REV]'))
3933 def manifest(ui, repo, node=None, rev=None, **opts):
3954 def manifest(ui, repo, node=None, rev=None, **opts):
3934 """output the current or given revision of the project manifest
3955 """output the current or given revision of the project manifest
3935
3956
3936 Print a list of version controlled files for the given revision.
3957 Print a list of version controlled files for the given revision.
3937 If no revision is given, the first parent of the working directory
3958 If no revision is given, the first parent of the working directory
3938 is used, or the null revision if no revision is checked out.
3959 is used, or the null revision if no revision is checked out.
3939
3960
3940 With -v, print file permissions, symlink and executable bits.
3961 With -v, print file permissions, symlink and executable bits.
3941 With --debug, print file revision hashes.
3962 With --debug, print file revision hashes.
3942
3963
3943 If option --all is specified, the list of all files from all revisions
3964 If option --all is specified, the list of all files from all revisions
3944 is printed. This includes deleted and renamed files.
3965 is printed. This includes deleted and renamed files.
3945
3966
3946 Returns 0 on success.
3967 Returns 0 on success.
3947 """
3968 """
3948 if opts.get('all'):
3969 if opts.get('all'):
3949 if rev or node:
3970 if rev or node:
3950 raise util.Abort(_("can't specify a revision with --all"))
3971 raise util.Abort(_("can't specify a revision with --all"))
3951
3972
3952 res = []
3973 res = []
3953 prefix = "data/"
3974 prefix = "data/"
3954 suffix = ".i"
3975 suffix = ".i"
3955 plen = len(prefix)
3976 plen = len(prefix)
3956 slen = len(suffix)
3977 slen = len(suffix)
3957 lock = repo.lock()
3978 lock = repo.lock()
3958 try:
3979 try:
3959 for fn, b, size in repo.store.datafiles():
3980 for fn, b, size in repo.store.datafiles():
3960 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3981 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3961 res.append(fn[plen:-slen])
3982 res.append(fn[plen:-slen])
3962 finally:
3983 finally:
3963 lock.release()
3984 lock.release()
3964 for f in sorted(res):
3985 for f in sorted(res):
3965 ui.write("%s\n" % f)
3986 ui.write("%s\n" % f)
3966 return
3987 return
3967
3988
3968 if rev and node:
3989 if rev and node:
3969 raise util.Abort(_("please specify just one revision"))
3990 raise util.Abort(_("please specify just one revision"))
3970
3991
3971 if not node:
3992 if not node:
3972 node = rev
3993 node = rev
3973
3994
3974 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3995 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3975 ctx = scmutil.revsingle(repo, node)
3996 ctx = scmutil.revsingle(repo, node)
3976 for f in ctx:
3997 for f in ctx:
3977 if ui.debugflag:
3998 if ui.debugflag:
3978 ui.write("%40s " % hex(ctx.manifest()[f]))
3999 ui.write("%40s " % hex(ctx.manifest()[f]))
3979 if ui.verbose:
4000 if ui.verbose:
3980 ui.write(decor[ctx.flags(f)])
4001 ui.write(decor[ctx.flags(f)])
3981 ui.write("%s\n" % f)
4002 ui.write("%s\n" % f)
3982
4003
3983 @command('^merge',
4004 @command('^merge',
3984 [('f', 'force', None, _('force a merge with outstanding changes')),
4005 [('f', 'force', None, _('force a merge with outstanding changes')),
3985 ('r', 'rev', '', _('revision to merge'), _('REV')),
4006 ('r', 'rev', '', _('revision to merge'), _('REV')),
3986 ('P', 'preview', None,
4007 ('P', 'preview', None,
3987 _('review revisions to merge (no merge is performed)'))
4008 _('review revisions to merge (no merge is performed)'))
3988 ] + mergetoolopts,
4009 ] + mergetoolopts,
3989 _('[-P] [-f] [[-r] REV]'))
4010 _('[-P] [-f] [[-r] REV]'))
3990 def merge(ui, repo, node=None, **opts):
4011 def merge(ui, repo, node=None, **opts):
3991 """merge working directory with another revision
4012 """merge working directory with another revision
3992
4013
3993 The current working directory is updated with all changes made in
4014 The current working directory is updated with all changes made in
3994 the requested revision since the last common predecessor revision.
4015 the requested revision since the last common predecessor revision.
3995
4016
3996 Files that changed between either parent are marked as changed for
4017 Files that changed between either parent are marked as changed for
3997 the next commit and a commit must be performed before any further
4018 the next commit and a commit must be performed before any further
3998 updates to the repository are allowed. The next commit will have
4019 updates to the repository are allowed. The next commit will have
3999 two parents.
4020 two parents.
4000
4021
4001 ``--tool`` can be used to specify the merge tool used for file
4022 ``--tool`` can be used to specify the merge tool used for file
4002 merges. It overrides the HGMERGE environment variable and your
4023 merges. It overrides the HGMERGE environment variable and your
4003 configuration files. See :hg:`help merge-tools` for options.
4024 configuration files. See :hg:`help merge-tools` for options.
4004
4025
4005 If no revision is specified, the working directory's parent is a
4026 If no revision is specified, the working directory's parent is a
4006 head revision, and the current branch contains exactly one other
4027 head revision, and the current branch contains exactly one other
4007 head, the other head is merged with by default. Otherwise, an
4028 head, the other head is merged with by default. Otherwise, an
4008 explicit revision with which to merge with must be provided.
4029 explicit revision with which to merge with must be provided.
4009
4030
4010 :hg:`resolve` must be used to resolve unresolved files.
4031 :hg:`resolve` must be used to resolve unresolved files.
4011
4032
4012 To undo an uncommitted merge, use :hg:`update --clean .` which
4033 To undo an uncommitted merge, use :hg:`update --clean .` which
4013 will check out a clean copy of the original merge parent, losing
4034 will check out a clean copy of the original merge parent, losing
4014 all changes.
4035 all changes.
4015
4036
4016 Returns 0 on success, 1 if there are unresolved files.
4037 Returns 0 on success, 1 if there are unresolved files.
4017 """
4038 """
4018
4039
4019 if opts.get('rev') and node:
4040 if opts.get('rev') and node:
4020 raise util.Abort(_("please specify just one revision"))
4041 raise util.Abort(_("please specify just one revision"))
4021 if not node:
4042 if not node:
4022 node = opts.get('rev')
4043 node = opts.get('rev')
4023
4044
4024 if not node:
4045 if not node:
4025 branch = repo[None].branch()
4046 branch = repo[None].branch()
4026 bheads = repo.branchheads(branch)
4047 bheads = repo.branchheads(branch)
4027 if len(bheads) > 2:
4048 if len(bheads) > 2:
4028 raise util.Abort(_("branch '%s' has %d heads - "
4049 raise util.Abort(_("branch '%s' has %d heads - "
4029 "please merge with an explicit rev")
4050 "please merge with an explicit rev")
4030 % (branch, len(bheads)),
4051 % (branch, len(bheads)),
4031 hint=_("run 'hg heads .' to see heads"))
4052 hint=_("run 'hg heads .' to see heads"))
4032
4053
4033 parent = repo.dirstate.p1()
4054 parent = repo.dirstate.p1()
4034 if len(bheads) == 1:
4055 if len(bheads) == 1:
4035 if len(repo.heads()) > 1:
4056 if len(repo.heads()) > 1:
4036 raise util.Abort(_("branch '%s' has one head - "
4057 raise util.Abort(_("branch '%s' has one head - "
4037 "please merge with an explicit rev")
4058 "please merge with an explicit rev")
4038 % branch,
4059 % branch,
4039 hint=_("run 'hg heads' to see all heads"))
4060 hint=_("run 'hg heads' to see all heads"))
4040 msg, hint = _('nothing to merge'), None
4061 msg, hint = _('nothing to merge'), None
4041 if parent != repo.lookup(branch):
4062 if parent != repo.lookup(branch):
4042 hint = _("use 'hg update' instead")
4063 hint = _("use 'hg update' instead")
4043 raise util.Abort(msg, hint=hint)
4064 raise util.Abort(msg, hint=hint)
4044
4065
4045 if parent not in bheads:
4066 if parent not in bheads:
4046 raise util.Abort(_('working directory not at a head revision'),
4067 raise util.Abort(_('working directory not at a head revision'),
4047 hint=_("use 'hg update' or merge with an "
4068 hint=_("use 'hg update' or merge with an "
4048 "explicit revision"))
4069 "explicit revision"))
4049 node = parent == bheads[0] and bheads[-1] or bheads[0]
4070 node = parent == bheads[0] and bheads[-1] or bheads[0]
4050 else:
4071 else:
4051 node = scmutil.revsingle(repo, node).node()
4072 node = scmutil.revsingle(repo, node).node()
4052
4073
4053 if opts.get('preview'):
4074 if opts.get('preview'):
4054 # find nodes that are ancestors of p2 but not of p1
4075 # find nodes that are ancestors of p2 but not of p1
4055 p1 = repo.lookup('.')
4076 p1 = repo.lookup('.')
4056 p2 = repo.lookup(node)
4077 p2 = repo.lookup(node)
4057 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4078 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4058
4079
4059 displayer = cmdutil.show_changeset(ui, repo, opts)
4080 displayer = cmdutil.show_changeset(ui, repo, opts)
4060 for node in nodes:
4081 for node in nodes:
4061 displayer.show(repo[node])
4082 displayer.show(repo[node])
4062 displayer.close()
4083 displayer.close()
4063 return 0
4084 return 0
4064
4085
4065 try:
4086 try:
4066 # ui.forcemerge is an internal variable, do not document
4087 # ui.forcemerge is an internal variable, do not document
4067 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4088 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4068 return hg.merge(repo, node, force=opts.get('force'))
4089 return hg.merge(repo, node, force=opts.get('force'))
4069 finally:
4090 finally:
4070 ui.setconfig('ui', 'forcemerge', '')
4091 ui.setconfig('ui', 'forcemerge', '')
4071
4092
4072 @command('outgoing|out',
4093 @command('outgoing|out',
4073 [('f', 'force', None, _('run even when the destination is unrelated')),
4094 [('f', 'force', None, _('run even when the destination is unrelated')),
4074 ('r', 'rev', [],
4095 ('r', 'rev', [],
4075 _('a changeset intended to be included in the destination'), _('REV')),
4096 _('a changeset intended to be included in the destination'), _('REV')),
4076 ('n', 'newest-first', None, _('show newest record first')),
4097 ('n', 'newest-first', None, _('show newest record first')),
4077 ('B', 'bookmarks', False, _('compare bookmarks')),
4098 ('B', 'bookmarks', False, _('compare bookmarks')),
4078 ('b', 'branch', [], _('a specific branch you would like to push'),
4099 ('b', 'branch', [], _('a specific branch you would like to push'),
4079 _('BRANCH')),
4100 _('BRANCH')),
4080 ] + logopts + remoteopts + subrepoopts,
4101 ] + logopts + remoteopts + subrepoopts,
4081 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4102 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4082 def outgoing(ui, repo, dest=None, **opts):
4103 def outgoing(ui, repo, dest=None, **opts):
4083 """show changesets not found in the destination
4104 """show changesets not found in the destination
4084
4105
4085 Show changesets not found in the specified destination repository
4106 Show changesets not found in the specified destination repository
4086 or the default push location. These are the changesets that would
4107 or the default push location. These are the changesets that would
4087 be pushed if a push was requested.
4108 be pushed if a push was requested.
4088
4109
4089 See pull for details of valid destination formats.
4110 See pull for details of valid destination formats.
4090
4111
4091 Returns 0 if there are outgoing changes, 1 otherwise.
4112 Returns 0 if there are outgoing changes, 1 otherwise.
4092 """
4113 """
4093
4114
4094 if opts.get('bookmarks'):
4115 if opts.get('bookmarks'):
4095 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4116 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4096 dest, branches = hg.parseurl(dest, opts.get('branch'))
4117 dest, branches = hg.parseurl(dest, opts.get('branch'))
4097 other = hg.peer(repo, opts, dest)
4118 other = hg.peer(repo, opts, dest)
4098 if 'bookmarks' not in other.listkeys('namespaces'):
4119 if 'bookmarks' not in other.listkeys('namespaces'):
4099 ui.warn(_("remote doesn't support bookmarks\n"))
4120 ui.warn(_("remote doesn't support bookmarks\n"))
4100 return 0
4121 return 0
4101 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4122 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4102 return bookmarks.diff(ui, other, repo)
4123 return bookmarks.diff(ui, other, repo)
4103
4124
4104 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4125 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4105 try:
4126 try:
4106 return hg.outgoing(ui, repo, dest, opts)
4127 return hg.outgoing(ui, repo, dest, opts)
4107 finally:
4128 finally:
4108 del repo._subtoppath
4129 del repo._subtoppath
4109
4130
4110 @command('parents',
4131 @command('parents',
4111 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4132 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4112 ] + templateopts,
4133 ] + templateopts,
4113 _('[-r REV] [FILE]'))
4134 _('[-r REV] [FILE]'))
4114 def parents(ui, repo, file_=None, **opts):
4135 def parents(ui, repo, file_=None, **opts):
4115 """show the parents of the working directory or revision
4136 """show the parents of the working directory or revision
4116
4137
4117 Print the working directory's parent revisions. If a revision is
4138 Print the working directory's parent revisions. If a revision is
4118 given via -r/--rev, the parent of that revision will be printed.
4139 given via -r/--rev, the parent of that revision will be printed.
4119 If a file argument is given, the revision in which the file was
4140 If a file argument is given, the revision in which the file was
4120 last changed (before the working directory revision or the
4141 last changed (before the working directory revision or the
4121 argument to --rev if given) is printed.
4142 argument to --rev if given) is printed.
4122
4143
4123 Returns 0 on success.
4144 Returns 0 on success.
4124 """
4145 """
4125
4146
4126 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4147 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4127
4148
4128 if file_:
4149 if file_:
4129 m = scmutil.match(ctx, (file_,), opts)
4150 m = scmutil.match(ctx, (file_,), opts)
4130 if m.anypats() or len(m.files()) != 1:
4151 if m.anypats() or len(m.files()) != 1:
4131 raise util.Abort(_('can only specify an explicit filename'))
4152 raise util.Abort(_('can only specify an explicit filename'))
4132 file_ = m.files()[0]
4153 file_ = m.files()[0]
4133 filenodes = []
4154 filenodes = []
4134 for cp in ctx.parents():
4155 for cp in ctx.parents():
4135 if not cp:
4156 if not cp:
4136 continue
4157 continue
4137 try:
4158 try:
4138 filenodes.append(cp.filenode(file_))
4159 filenodes.append(cp.filenode(file_))
4139 except error.LookupError:
4160 except error.LookupError:
4140 pass
4161 pass
4141 if not filenodes:
4162 if not filenodes:
4142 raise util.Abort(_("'%s' not found in manifest!") % file_)
4163 raise util.Abort(_("'%s' not found in manifest!") % file_)
4143 fl = repo.file(file_)
4164 fl = repo.file(file_)
4144 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4165 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4145 else:
4166 else:
4146 p = [cp.node() for cp in ctx.parents()]
4167 p = [cp.node() for cp in ctx.parents()]
4147
4168
4148 displayer = cmdutil.show_changeset(ui, repo, opts)
4169 displayer = cmdutil.show_changeset(ui, repo, opts)
4149 for n in p:
4170 for n in p:
4150 if n != nullid:
4171 if n != nullid:
4151 displayer.show(repo[n])
4172 displayer.show(repo[n])
4152 displayer.close()
4173 displayer.close()
4153
4174
4154 @command('paths', [], _('[NAME]'))
4175 @command('paths', [], _('[NAME]'))
4155 def paths(ui, repo, search=None):
4176 def paths(ui, repo, search=None):
4156 """show aliases for remote repositories
4177 """show aliases for remote repositories
4157
4178
4158 Show definition of symbolic path name NAME. If no name is given,
4179 Show definition of symbolic path name NAME. If no name is given,
4159 show definition of all available names.
4180 show definition of all available names.
4160
4181
4161 Option -q/--quiet suppresses all output when searching for NAME
4182 Option -q/--quiet suppresses all output when searching for NAME
4162 and shows only the path names when listing all definitions.
4183 and shows only the path names when listing all definitions.
4163
4184
4164 Path names are defined in the [paths] section of your
4185 Path names are defined in the [paths] section of your
4165 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4186 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4166 repository, ``.hg/hgrc`` is used, too.
4187 repository, ``.hg/hgrc`` is used, too.
4167
4188
4168 The path names ``default`` and ``default-push`` have a special
4189 The path names ``default`` and ``default-push`` have a special
4169 meaning. When performing a push or pull operation, they are used
4190 meaning. When performing a push or pull operation, they are used
4170 as fallbacks if no location is specified on the command-line.
4191 as fallbacks if no location is specified on the command-line.
4171 When ``default-push`` is set, it will be used for push and
4192 When ``default-push`` is set, it will be used for push and
4172 ``default`` will be used for pull; otherwise ``default`` is used
4193 ``default`` will be used for pull; otherwise ``default`` is used
4173 as the fallback for both. When cloning a repository, the clone
4194 as the fallback for both. When cloning a repository, the clone
4174 source is written as ``default`` in ``.hg/hgrc``. Note that
4195 source is written as ``default`` in ``.hg/hgrc``. Note that
4175 ``default`` and ``default-push`` apply to all inbound (e.g.
4196 ``default`` and ``default-push`` apply to all inbound (e.g.
4176 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4197 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4177 :hg:`bundle`) operations.
4198 :hg:`bundle`) operations.
4178
4199
4179 See :hg:`help urls` for more information.
4200 See :hg:`help urls` for more information.
4180
4201
4181 Returns 0 on success.
4202 Returns 0 on success.
4182 """
4203 """
4183 if search:
4204 if search:
4184 for name, path in ui.configitems("paths"):
4205 for name, path in ui.configitems("paths"):
4185 if name == search:
4206 if name == search:
4186 ui.status("%s\n" % util.hidepassword(path))
4207 ui.status("%s\n" % util.hidepassword(path))
4187 return
4208 return
4188 if not ui.quiet:
4209 if not ui.quiet:
4189 ui.warn(_("not found!\n"))
4210 ui.warn(_("not found!\n"))
4190 return 1
4211 return 1
4191 else:
4212 else:
4192 for name, path in ui.configitems("paths"):
4213 for name, path in ui.configitems("paths"):
4193 if ui.quiet:
4214 if ui.quiet:
4194 ui.write("%s\n" % name)
4215 ui.write("%s\n" % name)
4195 else:
4216 else:
4196 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4217 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4197
4218
4198 @command('^phase',
4219 @command('^phase',
4199 [('p', 'public', False, _('set changeset phase to public')),
4220 [('p', 'public', False, _('set changeset phase to public')),
4200 ('d', 'draft', False, _('set changeset phase to draft')),
4221 ('d', 'draft', False, _('set changeset phase to draft')),
4201 ('s', 'secret', False, _('set changeset phase to secret')),
4222 ('s', 'secret', False, _('set changeset phase to secret')),
4202 ('f', 'force', False, _('allow to move boundary backward')),
4223 ('f', 'force', False, _('allow to move boundary backward')),
4203 ('r', 'rev', [], _('target revision'), _('REV')),
4224 ('r', 'rev', [], _('target revision'), _('REV')),
4204 ],
4225 ],
4205 _('[-p|-d|-s] [-f] [-r] REV...'))
4226 _('[-p|-d|-s] [-f] [-r] REV...'))
4206 def phase(ui, repo, *revs, **opts):
4227 def phase(ui, repo, *revs, **opts):
4207 """set or show the current phase name
4228 """set or show the current phase name
4208
4229
4209 With no argument, show the phase name of specified revisions.
4230 With no argument, show the phase name of specified revisions.
4210
4231
4211 With one of -p/--public, -d/--draft or -s/--secret, change the
4232 With one of -p/--public, -d/--draft or -s/--secret, change the
4212 phase value of the specified revisions.
4233 phase value of the specified revisions.
4213
4234
4214 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4235 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4215 lower phase to an higher phase. Phases are ordered as follows::
4236 lower phase to an higher phase. Phases are ordered as follows::
4216
4237
4217 public < draft < secret
4238 public < draft < secret
4218
4239
4219 Return 0 on success, 1 if no phases were changed or some could not
4240 Return 0 on success, 1 if no phases were changed or some could not
4220 be changed.
4241 be changed.
4221 """
4242 """
4222 # search for a unique phase argument
4243 # search for a unique phase argument
4223 targetphase = None
4244 targetphase = None
4224 for idx, name in enumerate(phases.phasenames):
4245 for idx, name in enumerate(phases.phasenames):
4225 if opts[name]:
4246 if opts[name]:
4226 if targetphase is not None:
4247 if targetphase is not None:
4227 raise util.Abort(_('only one phase can be specified'))
4248 raise util.Abort(_('only one phase can be specified'))
4228 targetphase = idx
4249 targetphase = idx
4229
4250
4230 # look for specified revision
4251 # look for specified revision
4231 revs = list(revs)
4252 revs = list(revs)
4232 revs.extend(opts['rev'])
4253 revs.extend(opts['rev'])
4233 if not revs:
4254 if not revs:
4234 raise util.Abort(_('no revisions specified'))
4255 raise util.Abort(_('no revisions specified'))
4235
4256
4236 revs = scmutil.revrange(repo, revs)
4257 revs = scmutil.revrange(repo, revs)
4237
4258
4238 lock = None
4259 lock = None
4239 ret = 0
4260 ret = 0
4240 if targetphase is None:
4261 if targetphase is None:
4241 # display
4262 # display
4242 for r in revs:
4263 for r in revs:
4243 ctx = repo[r]
4264 ctx = repo[r]
4244 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4265 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4245 else:
4266 else:
4246 lock = repo.lock()
4267 lock = repo.lock()
4247 try:
4268 try:
4248 # set phase
4269 # set phase
4249 nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
4270 nodes = [ctx.node() for ctx in repo.set('%ld', revs)]
4250 if not nodes:
4271 if not nodes:
4251 raise util.Abort(_('empty revision set'))
4272 raise util.Abort(_('empty revision set'))
4252 olddata = repo._phaserev[:]
4273 olddata = repo._phaserev[:]
4253 phases.advanceboundary(repo, targetphase, nodes)
4274 phases.advanceboundary(repo, targetphase, nodes)
4254 if opts['force']:
4275 if opts['force']:
4255 phases.retractboundary(repo, targetphase, nodes)
4276 phases.retractboundary(repo, targetphase, nodes)
4256 finally:
4277 finally:
4257 lock.release()
4278 lock.release()
4258 if olddata is not None:
4279 if olddata is not None:
4259 changes = 0
4280 changes = 0
4260 newdata = repo._phaserev
4281 newdata = repo._phaserev
4261 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4282 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4262 rejected = [n for n in nodes
4283 rejected = [n for n in nodes
4263 if newdata[repo[n].rev()] < targetphase]
4284 if newdata[repo[n].rev()] < targetphase]
4264 if rejected:
4285 if rejected:
4265 ui.warn(_('cannot move %i changesets to a more permissive '
4286 ui.warn(_('cannot move %i changesets to a more permissive '
4266 'phase, use --force\n') % len(rejected))
4287 'phase, use --force\n') % len(rejected))
4267 ret = 1
4288 ret = 1
4268 if changes:
4289 if changes:
4269 msg = _('phase changed for %i changesets\n') % changes
4290 msg = _('phase changed for %i changesets\n') % changes
4270 if ret:
4291 if ret:
4271 ui.status(msg)
4292 ui.status(msg)
4272 else:
4293 else:
4273 ui.note(msg)
4294 ui.note(msg)
4274 else:
4295 else:
4275 ui.warn(_('no phases changed\n'))
4296 ui.warn(_('no phases changed\n'))
4276 ret = 1
4297 ret = 1
4277 return ret
4298 return ret
4278
4299
4279 def postincoming(ui, repo, modheads, optupdate, checkout):
4300 def postincoming(ui, repo, modheads, optupdate, checkout):
4280 if modheads == 0:
4301 if modheads == 0:
4281 return
4302 return
4282 if optupdate:
4303 if optupdate:
4283 movemarkfrom = repo['.'].node()
4304 movemarkfrom = repo['.'].node()
4284 try:
4305 try:
4285 ret = hg.update(repo, checkout)
4306 ret = hg.update(repo, checkout)
4286 except util.Abort, inst:
4307 except util.Abort, inst:
4287 ui.warn(_("not updating: %s\n") % str(inst))
4308 ui.warn(_("not updating: %s\n") % str(inst))
4288 return 0
4309 return 0
4289 if not ret and not checkout:
4310 if not ret and not checkout:
4290 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4311 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4291 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4312 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4292 return ret
4313 return ret
4293 if modheads > 1:
4314 if modheads > 1:
4294 currentbranchheads = len(repo.branchheads())
4315 currentbranchheads = len(repo.branchheads())
4295 if currentbranchheads == modheads:
4316 if currentbranchheads == modheads:
4296 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4317 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4297 elif currentbranchheads > 1:
4318 elif currentbranchheads > 1:
4298 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4319 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4299 else:
4320 else:
4300 ui.status(_("(run 'hg heads' to see heads)\n"))
4321 ui.status(_("(run 'hg heads' to see heads)\n"))
4301 else:
4322 else:
4302 ui.status(_("(run 'hg update' to get a working copy)\n"))
4323 ui.status(_("(run 'hg update' to get a working copy)\n"))
4303
4324
4304 @command('^pull',
4325 @command('^pull',
4305 [('u', 'update', None,
4326 [('u', 'update', None,
4306 _('update to new branch head if changesets were pulled')),
4327 _('update to new branch head if changesets were pulled')),
4307 ('f', 'force', None, _('run even when remote repository is unrelated')),
4328 ('f', 'force', None, _('run even when remote repository is unrelated')),
4308 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4329 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4309 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4330 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4310 ('b', 'branch', [], _('a specific branch you would like to pull'),
4331 ('b', 'branch', [], _('a specific branch you would like to pull'),
4311 _('BRANCH')),
4332 _('BRANCH')),
4312 ] + remoteopts,
4333 ] + remoteopts,
4313 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4334 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4314 def pull(ui, repo, source="default", **opts):
4335 def pull(ui, repo, source="default", **opts):
4315 """pull changes from the specified source
4336 """pull changes from the specified source
4316
4337
4317 Pull changes from a remote repository to a local one.
4338 Pull changes from a remote repository to a local one.
4318
4339
4319 This finds all changes from the repository at the specified path
4340 This finds all changes from the repository at the specified path
4320 or URL and adds them to a local repository (the current one unless
4341 or URL and adds them to a local repository (the current one unless
4321 -R is specified). By default, this does not update the copy of the
4342 -R is specified). By default, this does not update the copy of the
4322 project in the working directory.
4343 project in the working directory.
4323
4344
4324 Use :hg:`incoming` if you want to see what would have been added
4345 Use :hg:`incoming` if you want to see what would have been added
4325 by a pull at the time you issued this command. If you then decide
4346 by a pull at the time you issued this command. If you then decide
4326 to add those changes to the repository, you should use :hg:`pull
4347 to add those changes to the repository, you should use :hg:`pull
4327 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4348 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4328
4349
4329 If SOURCE is omitted, the 'default' path will be used.
4350 If SOURCE is omitted, the 'default' path will be used.
4330 See :hg:`help urls` for more information.
4351 See :hg:`help urls` for more information.
4331
4352
4332 Returns 0 on success, 1 if an update had unresolved files.
4353 Returns 0 on success, 1 if an update had unresolved files.
4333 """
4354 """
4334 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4355 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4335 other = hg.peer(repo, opts, source)
4356 other = hg.peer(repo, opts, source)
4336 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4357 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4337 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4358 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4338
4359
4339 if opts.get('bookmark'):
4360 if opts.get('bookmark'):
4340 if not revs:
4361 if not revs:
4341 revs = []
4362 revs = []
4342 rb = other.listkeys('bookmarks')
4363 rb = other.listkeys('bookmarks')
4343 for b in opts['bookmark']:
4364 for b in opts['bookmark']:
4344 if b not in rb:
4365 if b not in rb:
4345 raise util.Abort(_('remote bookmark %s not found!') % b)
4366 raise util.Abort(_('remote bookmark %s not found!') % b)
4346 revs.append(rb[b])
4367 revs.append(rb[b])
4347
4368
4348 if revs:
4369 if revs:
4349 try:
4370 try:
4350 revs = [other.lookup(rev) for rev in revs]
4371 revs = [other.lookup(rev) for rev in revs]
4351 except error.CapabilityError:
4372 except error.CapabilityError:
4352 err = _("other repository doesn't support revision lookup, "
4373 err = _("other repository doesn't support revision lookup, "
4353 "so a rev cannot be specified.")
4374 "so a rev cannot be specified.")
4354 raise util.Abort(err)
4375 raise util.Abort(err)
4355
4376
4356 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4377 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4357 bookmarks.updatefromremote(ui, repo, other, source)
4378 bookmarks.updatefromremote(ui, repo, other, source)
4358 if checkout:
4379 if checkout:
4359 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4380 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4360 repo._subtoppath = source
4381 repo._subtoppath = source
4361 try:
4382 try:
4362 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4383 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4363
4384
4364 finally:
4385 finally:
4365 del repo._subtoppath
4386 del repo._subtoppath
4366
4387
4367 # update specified bookmarks
4388 # update specified bookmarks
4368 if opts.get('bookmark'):
4389 if opts.get('bookmark'):
4369 for b in opts['bookmark']:
4390 for b in opts['bookmark']:
4370 # explicit pull overrides local bookmark if any
4391 # explicit pull overrides local bookmark if any
4371 ui.status(_("importing bookmark %s\n") % b)
4392 ui.status(_("importing bookmark %s\n") % b)
4372 repo._bookmarks[b] = repo[rb[b]].node()
4393 repo._bookmarks[b] = repo[rb[b]].node()
4373 bookmarks.write(repo)
4394 bookmarks.write(repo)
4374
4395
4375 return ret
4396 return ret
4376
4397
4377 @command('^push',
4398 @command('^push',
4378 [('f', 'force', None, _('force push')),
4399 [('f', 'force', None, _('force push')),
4379 ('r', 'rev', [],
4400 ('r', 'rev', [],
4380 _('a changeset intended to be included in the destination'),
4401 _('a changeset intended to be included in the destination'),
4381 _('REV')),
4402 _('REV')),
4382 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4403 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4383 ('b', 'branch', [],
4404 ('b', 'branch', [],
4384 _('a specific branch you would like to push'), _('BRANCH')),
4405 _('a specific branch you would like to push'), _('BRANCH')),
4385 ('', 'new-branch', False, _('allow pushing a new branch')),
4406 ('', 'new-branch', False, _('allow pushing a new branch')),
4386 ] + remoteopts,
4407 ] + remoteopts,
4387 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4408 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4388 def push(ui, repo, dest=None, **opts):
4409 def push(ui, repo, dest=None, **opts):
4389 """push changes to the specified destination
4410 """push changes to the specified destination
4390
4411
4391 Push changesets from the local repository to the specified
4412 Push changesets from the local repository to the specified
4392 destination.
4413 destination.
4393
4414
4394 This operation is symmetrical to pull: it is identical to a pull
4415 This operation is symmetrical to pull: it is identical to a pull
4395 in the destination repository from the current one.
4416 in the destination repository from the current one.
4396
4417
4397 By default, push will not allow creation of new heads at the
4418 By default, push will not allow creation of new heads at the
4398 destination, since multiple heads would make it unclear which head
4419 destination, since multiple heads would make it unclear which head
4399 to use. In this situation, it is recommended to pull and merge
4420 to use. In this situation, it is recommended to pull and merge
4400 before pushing.
4421 before pushing.
4401
4422
4402 Use --new-branch if you want to allow push to create a new named
4423 Use --new-branch if you want to allow push to create a new named
4403 branch that is not present at the destination. This allows you to
4424 branch that is not present at the destination. This allows you to
4404 only create a new branch without forcing other changes.
4425 only create a new branch without forcing other changes.
4405
4426
4406 Use -f/--force to override the default behavior and push all
4427 Use -f/--force to override the default behavior and push all
4407 changesets on all branches.
4428 changesets on all branches.
4408
4429
4409 If -r/--rev is used, the specified revision and all its ancestors
4430 If -r/--rev is used, the specified revision and all its ancestors
4410 will be pushed to the remote repository.
4431 will be pushed to the remote repository.
4411
4432
4412 Please see :hg:`help urls` for important details about ``ssh://``
4433 Please see :hg:`help urls` for important details about ``ssh://``
4413 URLs. If DESTINATION is omitted, a default path will be used.
4434 URLs. If DESTINATION is omitted, a default path will be used.
4414
4435
4415 Returns 0 if push was successful, 1 if nothing to push.
4436 Returns 0 if push was successful, 1 if nothing to push.
4416 """
4437 """
4417
4438
4418 if opts.get('bookmark'):
4439 if opts.get('bookmark'):
4419 for b in opts['bookmark']:
4440 for b in opts['bookmark']:
4420 # translate -B options to -r so changesets get pushed
4441 # translate -B options to -r so changesets get pushed
4421 if b in repo._bookmarks:
4442 if b in repo._bookmarks:
4422 opts.setdefault('rev', []).append(b)
4443 opts.setdefault('rev', []).append(b)
4423 else:
4444 else:
4424 # if we try to push a deleted bookmark, translate it to null
4445 # if we try to push a deleted bookmark, translate it to null
4425 # this lets simultaneous -r, -b options continue working
4446 # this lets simultaneous -r, -b options continue working
4426 opts.setdefault('rev', []).append("null")
4447 opts.setdefault('rev', []).append("null")
4427
4448
4428 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4449 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4429 dest, branches = hg.parseurl(dest, opts.get('branch'))
4450 dest, branches = hg.parseurl(dest, opts.get('branch'))
4430 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4451 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4431 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4452 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4432 other = hg.peer(repo, opts, dest)
4453 other = hg.peer(repo, opts, dest)
4433 if revs:
4454 if revs:
4434 revs = [repo.lookup(rev) for rev in revs]
4455 revs = [repo.lookup(rev) for rev in revs]
4435
4456
4436 repo._subtoppath = dest
4457 repo._subtoppath = dest
4437 try:
4458 try:
4438 # push subrepos depth-first for coherent ordering
4459 # push subrepos depth-first for coherent ordering
4439 c = repo['']
4460 c = repo['']
4440 subs = c.substate # only repos that are committed
4461 subs = c.substate # only repos that are committed
4441 for s in sorted(subs):
4462 for s in sorted(subs):
4442 if c.sub(s).push(opts) == 0:
4463 if c.sub(s).push(opts) == 0:
4443 return False
4464 return False
4444 finally:
4465 finally:
4445 del repo._subtoppath
4466 del repo._subtoppath
4446 result = repo.push(other, opts.get('force'), revs=revs,
4467 result = repo.push(other, opts.get('force'), revs=revs,
4447 newbranch=opts.get('new_branch'))
4468 newbranch=opts.get('new_branch'))
4448
4469
4449 result = not result
4470 result = not result
4450
4471
4451 if opts.get('bookmark'):
4472 if opts.get('bookmark'):
4452 rb = other.listkeys('bookmarks')
4473 rb = other.listkeys('bookmarks')
4453 for b in opts['bookmark']:
4474 for b in opts['bookmark']:
4454 # explicit push overrides remote bookmark if any
4475 # explicit push overrides remote bookmark if any
4455 if b in repo._bookmarks:
4476 if b in repo._bookmarks:
4456 ui.status(_("exporting bookmark %s\n") % b)
4477 ui.status(_("exporting bookmark %s\n") % b)
4457 new = repo[b].hex()
4478 new = repo[b].hex()
4458 elif b in rb:
4479 elif b in rb:
4459 ui.status(_("deleting remote bookmark %s\n") % b)
4480 ui.status(_("deleting remote bookmark %s\n") % b)
4460 new = '' # delete
4481 new = '' # delete
4461 else:
4482 else:
4462 ui.warn(_('bookmark %s does not exist on the local '
4483 ui.warn(_('bookmark %s does not exist on the local '
4463 'or remote repository!\n') % b)
4484 'or remote repository!\n') % b)
4464 return 2
4485 return 2
4465 old = rb.get(b, '')
4486 old = rb.get(b, '')
4466 r = other.pushkey('bookmarks', b, old, new)
4487 r = other.pushkey('bookmarks', b, old, new)
4467 if not r:
4488 if not r:
4468 ui.warn(_('updating bookmark %s failed!\n') % b)
4489 ui.warn(_('updating bookmark %s failed!\n') % b)
4469 if not result:
4490 if not result:
4470 result = 2
4491 result = 2
4471
4492
4472 return result
4493 return result
4473
4494
4474 @command('recover', [])
4495 @command('recover', [])
4475 def recover(ui, repo):
4496 def recover(ui, repo):
4476 """roll back an interrupted transaction
4497 """roll back an interrupted transaction
4477
4498
4478 Recover from an interrupted commit or pull.
4499 Recover from an interrupted commit or pull.
4479
4500
4480 This command tries to fix the repository status after an
4501 This command tries to fix the repository status after an
4481 interrupted operation. It should only be necessary when Mercurial
4502 interrupted operation. It should only be necessary when Mercurial
4482 suggests it.
4503 suggests it.
4483
4504
4484 Returns 0 if successful, 1 if nothing to recover or verify fails.
4505 Returns 0 if successful, 1 if nothing to recover or verify fails.
4485 """
4506 """
4486 if repo.recover():
4507 if repo.recover():
4487 return hg.verify(repo)
4508 return hg.verify(repo)
4488 return 1
4509 return 1
4489
4510
4490 @command('^remove|rm',
4511 @command('^remove|rm',
4491 [('A', 'after', None, _('record delete for missing files')),
4512 [('A', 'after', None, _('record delete for missing files')),
4492 ('f', 'force', None,
4513 ('f', 'force', None,
4493 _('remove (and delete) file even if added or modified')),
4514 _('remove (and delete) file even if added or modified')),
4494 ] + walkopts,
4515 ] + walkopts,
4495 _('[OPTION]... FILE...'))
4516 _('[OPTION]... FILE...'))
4496 def remove(ui, repo, *pats, **opts):
4517 def remove(ui, repo, *pats, **opts):
4497 """remove the specified files on the next commit
4518 """remove the specified files on the next commit
4498
4519
4499 Schedule the indicated files for removal from the current branch.
4520 Schedule the indicated files for removal from the current branch.
4500
4521
4501 This command schedules the files to be removed at the next commit.
4522 This command schedules the files to be removed at the next commit.
4502 To undo a remove before that, see :hg:`revert`. To undo added
4523 To undo a remove before that, see :hg:`revert`. To undo added
4503 files, see :hg:`forget`.
4524 files, see :hg:`forget`.
4504
4525
4505 .. container:: verbose
4526 .. container:: verbose
4506
4527
4507 -A/--after can be used to remove only files that have already
4528 -A/--after can be used to remove only files that have already
4508 been deleted, -f/--force can be used to force deletion, and -Af
4529 been deleted, -f/--force can be used to force deletion, and -Af
4509 can be used to remove files from the next revision without
4530 can be used to remove files from the next revision without
4510 deleting them from the working directory.
4531 deleting them from the working directory.
4511
4532
4512 The following table details the behavior of remove for different
4533 The following table details the behavior of remove for different
4513 file states (columns) and option combinations (rows). The file
4534 file states (columns) and option combinations (rows). The file
4514 states are Added [A], Clean [C], Modified [M] and Missing [!]
4535 states are Added [A], Clean [C], Modified [M] and Missing [!]
4515 (as reported by :hg:`status`). The actions are Warn, Remove
4536 (as reported by :hg:`status`). The actions are Warn, Remove
4516 (from branch) and Delete (from disk):
4537 (from branch) and Delete (from disk):
4517
4538
4518 ======= == == == ==
4539 ======= == == == ==
4519 A C M !
4540 A C M !
4520 ======= == == == ==
4541 ======= == == == ==
4521 none W RD W R
4542 none W RD W R
4522 -f R RD RD R
4543 -f R RD RD R
4523 -A W W W R
4544 -A W W W R
4524 -Af R R R R
4545 -Af R R R R
4525 ======= == == == ==
4546 ======= == == == ==
4526
4547
4527 Note that remove never deletes files in Added [A] state from the
4548 Note that remove never deletes files in Added [A] state from the
4528 working directory, not even if option --force is specified.
4549 working directory, not even if option --force is specified.
4529
4550
4530 Returns 0 on success, 1 if any warnings encountered.
4551 Returns 0 on success, 1 if any warnings encountered.
4531 """
4552 """
4532
4553
4533 ret = 0
4554 ret = 0
4534 after, force = opts.get('after'), opts.get('force')
4555 after, force = opts.get('after'), opts.get('force')
4535 if not pats and not after:
4556 if not pats and not after:
4536 raise util.Abort(_('no files specified'))
4557 raise util.Abort(_('no files specified'))
4537
4558
4538 m = scmutil.match(repo[None], pats, opts)
4559 m = scmutil.match(repo[None], pats, opts)
4539 s = repo.status(match=m, clean=True)
4560 s = repo.status(match=m, clean=True)
4540 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4561 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4541
4562
4542 for f in m.files():
4563 for f in m.files():
4543 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4564 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4544 if os.path.exists(m.rel(f)):
4565 if os.path.exists(m.rel(f)):
4545 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4566 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4546 ret = 1
4567 ret = 1
4547
4568
4548 if force:
4569 if force:
4549 list = modified + deleted + clean + added
4570 list = modified + deleted + clean + added
4550 elif after:
4571 elif after:
4551 list = deleted
4572 list = deleted
4552 for f in modified + added + clean:
4573 for f in modified + added + clean:
4553 ui.warn(_('not removing %s: file still exists (use -f'
4574 ui.warn(_('not removing %s: file still exists (use -f'
4554 ' to force removal)\n') % m.rel(f))
4575 ' to force removal)\n') % m.rel(f))
4555 ret = 1
4576 ret = 1
4556 else:
4577 else:
4557 list = deleted + clean
4578 list = deleted + clean
4558 for f in modified:
4579 for f in modified:
4559 ui.warn(_('not removing %s: file is modified (use -f'
4580 ui.warn(_('not removing %s: file is modified (use -f'
4560 ' to force removal)\n') % m.rel(f))
4581 ' to force removal)\n') % m.rel(f))
4561 ret = 1
4582 ret = 1
4562 for f in added:
4583 for f in added:
4563 ui.warn(_('not removing %s: file has been marked for add'
4584 ui.warn(_('not removing %s: file has been marked for add'
4564 ' (use forget to undo)\n') % m.rel(f))
4585 ' (use forget to undo)\n') % m.rel(f))
4565 ret = 1
4586 ret = 1
4566
4587
4567 for f in sorted(list):
4588 for f in sorted(list):
4568 if ui.verbose or not m.exact(f):
4589 if ui.verbose or not m.exact(f):
4569 ui.status(_('removing %s\n') % m.rel(f))
4590 ui.status(_('removing %s\n') % m.rel(f))
4570
4591
4571 wlock = repo.wlock()
4592 wlock = repo.wlock()
4572 try:
4593 try:
4573 if not after:
4594 if not after:
4574 for f in list:
4595 for f in list:
4575 if f in added:
4596 if f in added:
4576 continue # we never unlink added files on remove
4597 continue # we never unlink added files on remove
4577 try:
4598 try:
4578 util.unlinkpath(repo.wjoin(f))
4599 util.unlinkpath(repo.wjoin(f))
4579 except OSError, inst:
4600 except OSError, inst:
4580 if inst.errno != errno.ENOENT:
4601 if inst.errno != errno.ENOENT:
4581 raise
4602 raise
4582 repo[None].forget(list)
4603 repo[None].forget(list)
4583 finally:
4604 finally:
4584 wlock.release()
4605 wlock.release()
4585
4606
4586 return ret
4607 return ret
4587
4608
4588 @command('rename|move|mv',
4609 @command('rename|move|mv',
4589 [('A', 'after', None, _('record a rename that has already occurred')),
4610 [('A', 'after', None, _('record a rename that has already occurred')),
4590 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4611 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4591 ] + walkopts + dryrunopts,
4612 ] + walkopts + dryrunopts,
4592 _('[OPTION]... SOURCE... DEST'))
4613 _('[OPTION]... SOURCE... DEST'))
4593 def rename(ui, repo, *pats, **opts):
4614 def rename(ui, repo, *pats, **opts):
4594 """rename files; equivalent of copy + remove
4615 """rename files; equivalent of copy + remove
4595
4616
4596 Mark dest as copies of sources; mark sources for deletion. If dest
4617 Mark dest as copies of sources; mark sources for deletion. If dest
4597 is a directory, copies are put in that directory. If dest is a
4618 is a directory, copies are put in that directory. If dest is a
4598 file, there can only be one source.
4619 file, there can only be one source.
4599
4620
4600 By default, this command copies the contents of files as they
4621 By default, this command copies the contents of files as they
4601 exist in the working directory. If invoked with -A/--after, the
4622 exist in the working directory. If invoked with -A/--after, the
4602 operation is recorded, but no copying is performed.
4623 operation is recorded, but no copying is performed.
4603
4624
4604 This command takes effect at the next commit. To undo a rename
4625 This command takes effect at the next commit. To undo a rename
4605 before that, see :hg:`revert`.
4626 before that, see :hg:`revert`.
4606
4627
4607 Returns 0 on success, 1 if errors are encountered.
4628 Returns 0 on success, 1 if errors are encountered.
4608 """
4629 """
4609 wlock = repo.wlock(False)
4630 wlock = repo.wlock(False)
4610 try:
4631 try:
4611 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4632 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4612 finally:
4633 finally:
4613 wlock.release()
4634 wlock.release()
4614
4635
4615 @command('resolve',
4636 @command('resolve',
4616 [('a', 'all', None, _('select all unresolved files')),
4637 [('a', 'all', None, _('select all unresolved files')),
4617 ('l', 'list', None, _('list state of files needing merge')),
4638 ('l', 'list', None, _('list state of files needing merge')),
4618 ('m', 'mark', None, _('mark files as resolved')),
4639 ('m', 'mark', None, _('mark files as resolved')),
4619 ('u', 'unmark', None, _('mark files as unresolved')),
4640 ('u', 'unmark', None, _('mark files as unresolved')),
4620 ('n', 'no-status', None, _('hide status prefix'))]
4641 ('n', 'no-status', None, _('hide status prefix'))]
4621 + mergetoolopts + walkopts,
4642 + mergetoolopts + walkopts,
4622 _('[OPTION]... [FILE]...'))
4643 _('[OPTION]... [FILE]...'))
4623 def resolve(ui, repo, *pats, **opts):
4644 def resolve(ui, repo, *pats, **opts):
4624 """redo merges or set/view the merge status of files
4645 """redo merges or set/view the merge status of files
4625
4646
4626 Merges with unresolved conflicts are often the result of
4647 Merges with unresolved conflicts are often the result of
4627 non-interactive merging using the ``internal:merge`` configuration
4648 non-interactive merging using the ``internal:merge`` configuration
4628 setting, or a command-line merge tool like ``diff3``. The resolve
4649 setting, or a command-line merge tool like ``diff3``. The resolve
4629 command is used to manage the files involved in a merge, after
4650 command is used to manage the files involved in a merge, after
4630 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4651 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4631 working directory must have two parents). See :hg:`help
4652 working directory must have two parents). See :hg:`help
4632 merge-tools` for information on configuring merge tools.
4653 merge-tools` for information on configuring merge tools.
4633
4654
4634 The resolve command can be used in the following ways:
4655 The resolve command can be used in the following ways:
4635
4656
4636 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4657 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4637 files, discarding any previous merge attempts. Re-merging is not
4658 files, discarding any previous merge attempts. Re-merging is not
4638 performed for files already marked as resolved. Use ``--all/-a``
4659 performed for files already marked as resolved. Use ``--all/-a``
4639 to select all unresolved files. ``--tool`` can be used to specify
4660 to select all unresolved files. ``--tool`` can be used to specify
4640 the merge tool used for the given files. It overrides the HGMERGE
4661 the merge tool used for the given files. It overrides the HGMERGE
4641 environment variable and your configuration files. Previous file
4662 environment variable and your configuration files. Previous file
4642 contents are saved with a ``.orig`` suffix.
4663 contents are saved with a ``.orig`` suffix.
4643
4664
4644 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4665 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4645 (e.g. after having manually fixed-up the files). The default is
4666 (e.g. after having manually fixed-up the files). The default is
4646 to mark all unresolved files.
4667 to mark all unresolved files.
4647
4668
4648 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4669 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4649 default is to mark all resolved files.
4670 default is to mark all resolved files.
4650
4671
4651 - :hg:`resolve -l`: list files which had or still have conflicts.
4672 - :hg:`resolve -l`: list files which had or still have conflicts.
4652 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4673 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4653
4674
4654 Note that Mercurial will not let you commit files with unresolved
4675 Note that Mercurial will not let you commit files with unresolved
4655 merge conflicts. You must use :hg:`resolve -m ...` before you can
4676 merge conflicts. You must use :hg:`resolve -m ...` before you can
4656 commit after a conflicting merge.
4677 commit after a conflicting merge.
4657
4678
4658 Returns 0 on success, 1 if any files fail a resolve attempt.
4679 Returns 0 on success, 1 if any files fail a resolve attempt.
4659 """
4680 """
4660
4681
4661 all, mark, unmark, show, nostatus = \
4682 all, mark, unmark, show, nostatus = \
4662 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4683 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4663
4684
4664 if (show and (mark or unmark)) or (mark and unmark):
4685 if (show and (mark or unmark)) or (mark and unmark):
4665 raise util.Abort(_("too many options specified"))
4686 raise util.Abort(_("too many options specified"))
4666 if pats and all:
4687 if pats and all:
4667 raise util.Abort(_("can't specify --all and patterns"))
4688 raise util.Abort(_("can't specify --all and patterns"))
4668 if not (all or pats or show or mark or unmark):
4689 if not (all or pats or show or mark or unmark):
4669 raise util.Abort(_('no files or directories specified; '
4690 raise util.Abort(_('no files or directories specified; '
4670 'use --all to remerge all files'))
4691 'use --all to remerge all files'))
4671
4692
4672 ms = mergemod.mergestate(repo)
4693 ms = mergemod.mergestate(repo)
4673 m = scmutil.match(repo[None], pats, opts)
4694 m = scmutil.match(repo[None], pats, opts)
4674 ret = 0
4695 ret = 0
4675
4696
4676 for f in ms:
4697 for f in ms:
4677 if m(f):
4698 if m(f):
4678 if show:
4699 if show:
4679 if nostatus:
4700 if nostatus:
4680 ui.write("%s\n" % f)
4701 ui.write("%s\n" % f)
4681 else:
4702 else:
4682 ui.write("%s %s\n" % (ms[f].upper(), f),
4703 ui.write("%s %s\n" % (ms[f].upper(), f),
4683 label='resolve.' +
4704 label='resolve.' +
4684 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4705 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4685 elif mark:
4706 elif mark:
4686 ms.mark(f, "r")
4707 ms.mark(f, "r")
4687 elif unmark:
4708 elif unmark:
4688 ms.mark(f, "u")
4709 ms.mark(f, "u")
4689 else:
4710 else:
4690 wctx = repo[None]
4711 wctx = repo[None]
4691 mctx = wctx.parents()[-1]
4712 mctx = wctx.parents()[-1]
4692
4713
4693 # backup pre-resolve (merge uses .orig for its own purposes)
4714 # backup pre-resolve (merge uses .orig for its own purposes)
4694 a = repo.wjoin(f)
4715 a = repo.wjoin(f)
4695 util.copyfile(a, a + ".resolve")
4716 util.copyfile(a, a + ".resolve")
4696
4717
4697 try:
4718 try:
4698 # resolve file
4719 # resolve file
4699 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4720 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4700 if ms.resolve(f, wctx, mctx):
4721 if ms.resolve(f, wctx, mctx):
4701 ret = 1
4722 ret = 1
4702 finally:
4723 finally:
4703 ui.setconfig('ui', 'forcemerge', '')
4724 ui.setconfig('ui', 'forcemerge', '')
4704
4725
4705 # replace filemerge's .orig file with our resolve file
4726 # replace filemerge's .orig file with our resolve file
4706 util.rename(a + ".resolve", a + ".orig")
4727 util.rename(a + ".resolve", a + ".orig")
4707
4728
4708 ms.commit()
4729 ms.commit()
4709 return ret
4730 return ret
4710
4731
4711 @command('revert',
4732 @command('revert',
4712 [('a', 'all', None, _('revert all changes when no arguments given')),
4733 [('a', 'all', None, _('revert all changes when no arguments given')),
4713 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4734 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4714 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4735 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4715 ('C', 'no-backup', None, _('do not save backup copies of files')),
4736 ('C', 'no-backup', None, _('do not save backup copies of files')),
4716 ] + walkopts + dryrunopts,
4737 ] + walkopts + dryrunopts,
4717 _('[OPTION]... [-r REV] [NAME]...'))
4738 _('[OPTION]... [-r REV] [NAME]...'))
4718 def revert(ui, repo, *pats, **opts):
4739 def revert(ui, repo, *pats, **opts):
4719 """restore files to their checkout state
4740 """restore files to their checkout state
4720
4741
4721 .. note::
4742 .. note::
4722 To check out earlier revisions, you should use :hg:`update REV`.
4743 To check out earlier revisions, you should use :hg:`update REV`.
4723 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4744 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4724
4745
4725 With no revision specified, revert the specified files or directories
4746 With no revision specified, revert the specified files or directories
4726 to the contents they had in the parent of the working directory.
4747 to the contents they had in the parent of the working directory.
4727 This restores the contents of files to an unmodified
4748 This restores the contents of files to an unmodified
4728 state and unschedules adds, removes, copies, and renames. If the
4749 state and unschedules adds, removes, copies, and renames. If the
4729 working directory has two parents, you must explicitly specify a
4750 working directory has two parents, you must explicitly specify a
4730 revision.
4751 revision.
4731
4752
4732 Using the -r/--rev or -d/--date options, revert the given files or
4753 Using the -r/--rev or -d/--date options, revert the given files or
4733 directories to their states as of a specific revision. Because
4754 directories to their states as of a specific revision. Because
4734 revert does not change the working directory parents, this will
4755 revert does not change the working directory parents, this will
4735 cause these files to appear modified. This can be helpful to "back
4756 cause these files to appear modified. This can be helpful to "back
4736 out" some or all of an earlier change. See :hg:`backout` for a
4757 out" some or all of an earlier change. See :hg:`backout` for a
4737 related method.
4758 related method.
4738
4759
4739 Modified files are saved with a .orig suffix before reverting.
4760 Modified files are saved with a .orig suffix before reverting.
4740 To disable these backups, use --no-backup.
4761 To disable these backups, use --no-backup.
4741
4762
4742 See :hg:`help dates` for a list of formats valid for -d/--date.
4763 See :hg:`help dates` for a list of formats valid for -d/--date.
4743
4764
4744 Returns 0 on success.
4765 Returns 0 on success.
4745 """
4766 """
4746
4767
4747 if opts.get("date"):
4768 if opts.get("date"):
4748 if opts.get("rev"):
4769 if opts.get("rev"):
4749 raise util.Abort(_("you can't specify a revision and a date"))
4770 raise util.Abort(_("you can't specify a revision and a date"))
4750 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4771 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4751
4772
4752 parent, p2 = repo.dirstate.parents()
4773 parent, p2 = repo.dirstate.parents()
4753 if not opts.get('rev') and p2 != nullid:
4774 if not opts.get('rev') and p2 != nullid:
4754 # revert after merge is a trap for new users (issue2915)
4775 # revert after merge is a trap for new users (issue2915)
4755 raise util.Abort(_('uncommitted merge with no revision specified'),
4776 raise util.Abort(_('uncommitted merge with no revision specified'),
4756 hint=_('use "hg update" or see "hg help revert"'))
4777 hint=_('use "hg update" or see "hg help revert"'))
4757
4778
4758 ctx = scmutil.revsingle(repo, opts.get('rev'))
4779 ctx = scmutil.revsingle(repo, opts.get('rev'))
4759 node = ctx.node()
4780 node = ctx.node()
4760
4781
4761 if not pats and not opts.get('all'):
4782 if not pats and not opts.get('all'):
4762 msg = _("no files or directories specified")
4783 msg = _("no files or directories specified")
4763 if p2 != nullid:
4784 if p2 != nullid:
4764 hint = _("uncommitted merge, use --all to discard all changes,"
4785 hint = _("uncommitted merge, use --all to discard all changes,"
4765 " or 'hg update -C .' to abort the merge")
4786 " or 'hg update -C .' to abort the merge")
4766 raise util.Abort(msg, hint=hint)
4787 raise util.Abort(msg, hint=hint)
4767 dirty = util.any(repo.status())
4788 dirty = util.any(repo.status())
4768 if node != parent:
4789 if node != parent:
4769 if dirty:
4790 if dirty:
4770 hint = _("uncommitted changes, use --all to discard all"
4791 hint = _("uncommitted changes, use --all to discard all"
4771 " changes, or 'hg update %s' to update") % ctx.rev()
4792 " changes, or 'hg update %s' to update") % ctx.rev()
4772 else:
4793 else:
4773 hint = _("use --all to revert all files,"
4794 hint = _("use --all to revert all files,"
4774 " or 'hg update %s' to update") % ctx.rev()
4795 " or 'hg update %s' to update") % ctx.rev()
4775 elif dirty:
4796 elif dirty:
4776 hint = _("uncommitted changes, use --all to discard all changes")
4797 hint = _("uncommitted changes, use --all to discard all changes")
4777 else:
4798 else:
4778 hint = _("use --all to revert all files")
4799 hint = _("use --all to revert all files")
4779 raise util.Abort(msg, hint=hint)
4800 raise util.Abort(msg, hint=hint)
4780
4801
4781 mf = ctx.manifest()
4802 mf = ctx.manifest()
4782 if node == parent:
4803 if node == parent:
4783 pmf = mf
4804 pmf = mf
4784 else:
4805 else:
4785 pmf = None
4806 pmf = None
4786
4807
4787 # need all matching names in dirstate and manifest of target rev,
4808 # need all matching names in dirstate and manifest of target rev,
4788 # so have to walk both. do not print errors if files exist in one
4809 # so have to walk both. do not print errors if files exist in one
4789 # but not other.
4810 # but not other.
4790
4811
4791 names = {}
4812 names = {}
4792
4813
4793 wlock = repo.wlock()
4814 wlock = repo.wlock()
4794 try:
4815 try:
4795 # walk dirstate.
4816 # walk dirstate.
4796
4817
4797 m = scmutil.match(repo[None], pats, opts)
4818 m = scmutil.match(repo[None], pats, opts)
4798 m.bad = lambda x, y: False
4819 m.bad = lambda x, y: False
4799 for abs in repo.walk(m):
4820 for abs in repo.walk(m):
4800 names[abs] = m.rel(abs), m.exact(abs)
4821 names[abs] = m.rel(abs), m.exact(abs)
4801
4822
4802 # walk target manifest.
4823 # walk target manifest.
4803
4824
4804 def badfn(path, msg):
4825 def badfn(path, msg):
4805 if path in names:
4826 if path in names:
4806 return
4827 return
4807 if path in repo[node].substate:
4828 if path in repo[node].substate:
4808 ui.warn("%s: %s\n" % (m.rel(path),
4829 ui.warn("%s: %s\n" % (m.rel(path),
4809 'reverting subrepos is unsupported'))
4830 'reverting subrepos is unsupported'))
4810 return
4831 return
4811 path_ = path + '/'
4832 path_ = path + '/'
4812 for f in names:
4833 for f in names:
4813 if f.startswith(path_):
4834 if f.startswith(path_):
4814 return
4835 return
4815 ui.warn("%s: %s\n" % (m.rel(path), msg))
4836 ui.warn("%s: %s\n" % (m.rel(path), msg))
4816
4837
4817 m = scmutil.match(repo[node], pats, opts)
4838 m = scmutil.match(repo[node], pats, opts)
4818 m.bad = badfn
4839 m.bad = badfn
4819 for abs in repo[node].walk(m):
4840 for abs in repo[node].walk(m):
4820 if abs not in names:
4841 if abs not in names:
4821 names[abs] = m.rel(abs), m.exact(abs)
4842 names[abs] = m.rel(abs), m.exact(abs)
4822
4843
4823 m = scmutil.matchfiles(repo, names)
4844 m = scmutil.matchfiles(repo, names)
4824 changes = repo.status(match=m)[:4]
4845 changes = repo.status(match=m)[:4]
4825 modified, added, removed, deleted = map(set, changes)
4846 modified, added, removed, deleted = map(set, changes)
4826
4847
4827 # if f is a rename, also revert the source
4848 # if f is a rename, also revert the source
4828 cwd = repo.getcwd()
4849 cwd = repo.getcwd()
4829 for f in added:
4850 for f in added:
4830 src = repo.dirstate.copied(f)
4851 src = repo.dirstate.copied(f)
4831 if src and src not in names and repo.dirstate[src] == 'r':
4852 if src and src not in names and repo.dirstate[src] == 'r':
4832 removed.add(src)
4853 removed.add(src)
4833 names[src] = (repo.pathto(src, cwd), True)
4854 names[src] = (repo.pathto(src, cwd), True)
4834
4855
4835 def removeforget(abs):
4856 def removeforget(abs):
4836 if repo.dirstate[abs] == 'a':
4857 if repo.dirstate[abs] == 'a':
4837 return _('forgetting %s\n')
4858 return _('forgetting %s\n')
4838 return _('removing %s\n')
4859 return _('removing %s\n')
4839
4860
4840 revert = ([], _('reverting %s\n'))
4861 revert = ([], _('reverting %s\n'))
4841 add = ([], _('adding %s\n'))
4862 add = ([], _('adding %s\n'))
4842 remove = ([], removeforget)
4863 remove = ([], removeforget)
4843 undelete = ([], _('undeleting %s\n'))
4864 undelete = ([], _('undeleting %s\n'))
4844
4865
4845 disptable = (
4866 disptable = (
4846 # dispatch table:
4867 # dispatch table:
4847 # file state
4868 # file state
4848 # action if in target manifest
4869 # action if in target manifest
4849 # action if not in target manifest
4870 # action if not in target manifest
4850 # make backup if in target manifest
4871 # make backup if in target manifest
4851 # make backup if not in target manifest
4872 # make backup if not in target manifest
4852 (modified, revert, remove, True, True),
4873 (modified, revert, remove, True, True),
4853 (added, revert, remove, True, False),
4874 (added, revert, remove, True, False),
4854 (removed, undelete, None, False, False),
4875 (removed, undelete, None, False, False),
4855 (deleted, revert, remove, False, False),
4876 (deleted, revert, remove, False, False),
4856 )
4877 )
4857
4878
4858 for abs, (rel, exact) in sorted(names.items()):
4879 for abs, (rel, exact) in sorted(names.items()):
4859 mfentry = mf.get(abs)
4880 mfentry = mf.get(abs)
4860 target = repo.wjoin(abs)
4881 target = repo.wjoin(abs)
4861 def handle(xlist, dobackup):
4882 def handle(xlist, dobackup):
4862 xlist[0].append(abs)
4883 xlist[0].append(abs)
4863 if (dobackup and not opts.get('no_backup') and
4884 if (dobackup and not opts.get('no_backup') and
4864 os.path.lexists(target)):
4885 os.path.lexists(target)):
4865 bakname = "%s.orig" % rel
4886 bakname = "%s.orig" % rel
4866 ui.note(_('saving current version of %s as %s\n') %
4887 ui.note(_('saving current version of %s as %s\n') %
4867 (rel, bakname))
4888 (rel, bakname))
4868 if not opts.get('dry_run'):
4889 if not opts.get('dry_run'):
4869 util.rename(target, bakname)
4890 util.rename(target, bakname)
4870 if ui.verbose or not exact:
4891 if ui.verbose or not exact:
4871 msg = xlist[1]
4892 msg = xlist[1]
4872 if not isinstance(msg, basestring):
4893 if not isinstance(msg, basestring):
4873 msg = msg(abs)
4894 msg = msg(abs)
4874 ui.status(msg % rel)
4895 ui.status(msg % rel)
4875 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4896 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4876 if abs not in table:
4897 if abs not in table:
4877 continue
4898 continue
4878 # file has changed in dirstate
4899 # file has changed in dirstate
4879 if mfentry:
4900 if mfentry:
4880 handle(hitlist, backuphit)
4901 handle(hitlist, backuphit)
4881 elif misslist is not None:
4902 elif misslist is not None:
4882 handle(misslist, backupmiss)
4903 handle(misslist, backupmiss)
4883 break
4904 break
4884 else:
4905 else:
4885 if abs not in repo.dirstate:
4906 if abs not in repo.dirstate:
4886 if mfentry:
4907 if mfentry:
4887 handle(add, True)
4908 handle(add, True)
4888 elif exact:
4909 elif exact:
4889 ui.warn(_('file not managed: %s\n') % rel)
4910 ui.warn(_('file not managed: %s\n') % rel)
4890 continue
4911 continue
4891 # file has not changed in dirstate
4912 # file has not changed in dirstate
4892 if node == parent:
4913 if node == parent:
4893 if exact:
4914 if exact:
4894 ui.warn(_('no changes needed to %s\n') % rel)
4915 ui.warn(_('no changes needed to %s\n') % rel)
4895 continue
4916 continue
4896 if pmf is None:
4917 if pmf is None:
4897 # only need parent manifest in this unlikely case,
4918 # only need parent manifest in this unlikely case,
4898 # so do not read by default
4919 # so do not read by default
4899 pmf = repo[parent].manifest()
4920 pmf = repo[parent].manifest()
4900 if abs in pmf and mfentry:
4921 if abs in pmf and mfentry:
4901 # if version of file is same in parent and target
4922 # if version of file is same in parent and target
4902 # manifests, do nothing
4923 # manifests, do nothing
4903 if (pmf[abs] != mfentry or
4924 if (pmf[abs] != mfentry or
4904 pmf.flags(abs) != mf.flags(abs)):
4925 pmf.flags(abs) != mf.flags(abs)):
4905 handle(revert, False)
4926 handle(revert, False)
4906 else:
4927 else:
4907 handle(remove, False)
4928 handle(remove, False)
4908
4929
4909 if not opts.get('dry_run'):
4930 if not opts.get('dry_run'):
4910 def checkout(f):
4931 def checkout(f):
4911 fc = ctx[f]
4932 fc = ctx[f]
4912 repo.wwrite(f, fc.data(), fc.flags())
4933 repo.wwrite(f, fc.data(), fc.flags())
4913
4934
4914 audit_path = scmutil.pathauditor(repo.root)
4935 audit_path = scmutil.pathauditor(repo.root)
4915 for f in remove[0]:
4936 for f in remove[0]:
4916 if repo.dirstate[f] == 'a':
4937 if repo.dirstate[f] == 'a':
4917 repo.dirstate.drop(f)
4938 repo.dirstate.drop(f)
4918 continue
4939 continue
4919 audit_path(f)
4940 audit_path(f)
4920 try:
4941 try:
4921 util.unlinkpath(repo.wjoin(f))
4942 util.unlinkpath(repo.wjoin(f))
4922 except OSError:
4943 except OSError:
4923 pass
4944 pass
4924 repo.dirstate.remove(f)
4945 repo.dirstate.remove(f)
4925
4946
4926 normal = None
4947 normal = None
4927 if node == parent:
4948 if node == parent:
4928 # We're reverting to our parent. If possible, we'd like status
4949 # We're reverting to our parent. If possible, we'd like status
4929 # to report the file as clean. We have to use normallookup for
4950 # to report the file as clean. We have to use normallookup for
4930 # merges to avoid losing information about merged/dirty files.
4951 # merges to avoid losing information about merged/dirty files.
4931 if p2 != nullid:
4952 if p2 != nullid:
4932 normal = repo.dirstate.normallookup
4953 normal = repo.dirstate.normallookup
4933 else:
4954 else:
4934 normal = repo.dirstate.normal
4955 normal = repo.dirstate.normal
4935 for f in revert[0]:
4956 for f in revert[0]:
4936 checkout(f)
4957 checkout(f)
4937 if normal:
4958 if normal:
4938 normal(f)
4959 normal(f)
4939
4960
4940 for f in add[0]:
4961 for f in add[0]:
4941 checkout(f)
4962 checkout(f)
4942 repo.dirstate.add(f)
4963 repo.dirstate.add(f)
4943
4964
4944 normal = repo.dirstate.normallookup
4965 normal = repo.dirstate.normallookup
4945 if node == parent and p2 == nullid:
4966 if node == parent and p2 == nullid:
4946 normal = repo.dirstate.normal
4967 normal = repo.dirstate.normal
4947 for f in undelete[0]:
4968 for f in undelete[0]:
4948 checkout(f)
4969 checkout(f)
4949 normal(f)
4970 normal(f)
4950
4971
4951 finally:
4972 finally:
4952 wlock.release()
4973 wlock.release()
4953
4974
4954 @command('rollback', dryrunopts +
4975 @command('rollback', dryrunopts +
4955 [('f', 'force', False, _('ignore safety measures'))])
4976 [('f', 'force', False, _('ignore safety measures'))])
4956 def rollback(ui, repo, **opts):
4977 def rollback(ui, repo, **opts):
4957 """roll back the last transaction (dangerous)
4978 """roll back the last transaction (dangerous)
4958
4979
4959 This command should be used with care. There is only one level of
4980 This command should be used with care. There is only one level of
4960 rollback, and there is no way to undo a rollback. It will also
4981 rollback, and there is no way to undo a rollback. It will also
4961 restore the dirstate at the time of the last transaction, losing
4982 restore the dirstate at the time of the last transaction, losing
4962 any dirstate changes since that time. This command does not alter
4983 any dirstate changes since that time. This command does not alter
4963 the working directory.
4984 the working directory.
4964
4985
4965 Transactions are used to encapsulate the effects of all commands
4986 Transactions are used to encapsulate the effects of all commands
4966 that create new changesets or propagate existing changesets into a
4987 that create new changesets or propagate existing changesets into a
4967 repository. For example, the following commands are transactional,
4988 repository. For example, the following commands are transactional,
4968 and their effects can be rolled back:
4989 and their effects can be rolled back:
4969
4990
4970 - commit
4991 - commit
4971 - import
4992 - import
4972 - pull
4993 - pull
4973 - push (with this repository as the destination)
4994 - push (with this repository as the destination)
4974 - unbundle
4995 - unbundle
4975
4996
4976 To avoid permanent data loss, rollback will refuse to rollback a
4997 To avoid permanent data loss, rollback will refuse to rollback a
4977 commit transaction if it isn't checked out. Use --force to
4998 commit transaction if it isn't checked out. Use --force to
4978 override this protection.
4999 override this protection.
4979
5000
4980 This command is not intended for use on public repositories. Once
5001 This command is not intended for use on public repositories. Once
4981 changes are visible for pull by other users, rolling a transaction
5002 changes are visible for pull by other users, rolling a transaction
4982 back locally is ineffective (someone else may already have pulled
5003 back locally is ineffective (someone else may already have pulled
4983 the changes). Furthermore, a race is possible with readers of the
5004 the changes). Furthermore, a race is possible with readers of the
4984 repository; for example an in-progress pull from the repository
5005 repository; for example an in-progress pull from the repository
4985 may fail if a rollback is performed.
5006 may fail if a rollback is performed.
4986
5007
4987 Returns 0 on success, 1 if no rollback data is available.
5008 Returns 0 on success, 1 if no rollback data is available.
4988 """
5009 """
4989 return repo.rollback(dryrun=opts.get('dry_run'),
5010 return repo.rollback(dryrun=opts.get('dry_run'),
4990 force=opts.get('force'))
5011 force=opts.get('force'))
4991
5012
4992 @command('root', [])
5013 @command('root', [])
4993 def root(ui, repo):
5014 def root(ui, repo):
4994 """print the root (top) of the current working directory
5015 """print the root (top) of the current working directory
4995
5016
4996 Print the root directory of the current repository.
5017 Print the root directory of the current repository.
4997
5018
4998 Returns 0 on success.
5019 Returns 0 on success.
4999 """
5020 """
5000 ui.write(repo.root + "\n")
5021 ui.write(repo.root + "\n")
5001
5022
5002 @command('^serve',
5023 @command('^serve',
5003 [('A', 'accesslog', '', _('name of access log file to write to'),
5024 [('A', 'accesslog', '', _('name of access log file to write to'),
5004 _('FILE')),
5025 _('FILE')),
5005 ('d', 'daemon', None, _('run server in background')),
5026 ('d', 'daemon', None, _('run server in background')),
5006 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5027 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5007 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5028 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5008 # use string type, then we can check if something was passed
5029 # use string type, then we can check if something was passed
5009 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5030 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5010 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5031 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5011 _('ADDR')),
5032 _('ADDR')),
5012 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5033 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5013 _('PREFIX')),
5034 _('PREFIX')),
5014 ('n', 'name', '',
5035 ('n', 'name', '',
5015 _('name to show in web pages (default: working directory)'), _('NAME')),
5036 _('name to show in web pages (default: working directory)'), _('NAME')),
5016 ('', 'web-conf', '',
5037 ('', 'web-conf', '',
5017 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5038 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5018 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5039 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5019 _('FILE')),
5040 _('FILE')),
5020 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5041 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5021 ('', 'stdio', None, _('for remote clients')),
5042 ('', 'stdio', None, _('for remote clients')),
5022 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5043 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5023 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5044 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5024 ('', 'style', '', _('template style to use'), _('STYLE')),
5045 ('', 'style', '', _('template style to use'), _('STYLE')),
5025 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5046 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5026 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5047 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5027 _('[OPTION]...'))
5048 _('[OPTION]...'))
5028 def serve(ui, repo, **opts):
5049 def serve(ui, repo, **opts):
5029 """start stand-alone webserver
5050 """start stand-alone webserver
5030
5051
5031 Start a local HTTP repository browser and pull server. You can use
5052 Start a local HTTP repository browser and pull server. You can use
5032 this for ad-hoc sharing and browsing of repositories. It is
5053 this for ad-hoc sharing and browsing of repositories. It is
5033 recommended to use a real web server to serve a repository for
5054 recommended to use a real web server to serve a repository for
5034 longer periods of time.
5055 longer periods of time.
5035
5056
5036 Please note that the server does not implement access control.
5057 Please note that the server does not implement access control.
5037 This means that, by default, anybody can read from the server and
5058 This means that, by default, anybody can read from the server and
5038 nobody can write to it by default. Set the ``web.allow_push``
5059 nobody can write to it by default. Set the ``web.allow_push``
5039 option to ``*`` to allow everybody to push to the server. You
5060 option to ``*`` to allow everybody to push to the server. You
5040 should use a real web server if you need to authenticate users.
5061 should use a real web server if you need to authenticate users.
5041
5062
5042 By default, the server logs accesses to stdout and errors to
5063 By default, the server logs accesses to stdout and errors to
5043 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5064 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5044 files.
5065 files.
5045
5066
5046 To have the server choose a free port number to listen on, specify
5067 To have the server choose a free port number to listen on, specify
5047 a port number of 0; in this case, the server will print the port
5068 a port number of 0; in this case, the server will print the port
5048 number it uses.
5069 number it uses.
5049
5070
5050 Returns 0 on success.
5071 Returns 0 on success.
5051 """
5072 """
5052
5073
5053 if opts["stdio"] and opts["cmdserver"]:
5074 if opts["stdio"] and opts["cmdserver"]:
5054 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5075 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5055
5076
5056 def checkrepo():
5077 def checkrepo():
5057 if repo is None:
5078 if repo is None:
5058 raise error.RepoError(_("There is no Mercurial repository here"
5079 raise error.RepoError(_("There is no Mercurial repository here"
5059 " (.hg not found)"))
5080 " (.hg not found)"))
5060
5081
5061 if opts["stdio"]:
5082 if opts["stdio"]:
5062 checkrepo()
5083 checkrepo()
5063 s = sshserver.sshserver(ui, repo)
5084 s = sshserver.sshserver(ui, repo)
5064 s.serve_forever()
5085 s.serve_forever()
5065
5086
5066 if opts["cmdserver"]:
5087 if opts["cmdserver"]:
5067 checkrepo()
5088 checkrepo()
5068 s = commandserver.server(ui, repo, opts["cmdserver"])
5089 s = commandserver.server(ui, repo, opts["cmdserver"])
5069 return s.serve()
5090 return s.serve()
5070
5091
5071 # this way we can check if something was given in the command-line
5092 # this way we can check if something was given in the command-line
5072 if opts.get('port'):
5093 if opts.get('port'):
5073 opts['port'] = util.getport(opts.get('port'))
5094 opts['port'] = util.getport(opts.get('port'))
5074
5095
5075 baseui = repo and repo.baseui or ui
5096 baseui = repo and repo.baseui or ui
5076 optlist = ("name templates style address port prefix ipv6"
5097 optlist = ("name templates style address port prefix ipv6"
5077 " accesslog errorlog certificate encoding")
5098 " accesslog errorlog certificate encoding")
5078 for o in optlist.split():
5099 for o in optlist.split():
5079 val = opts.get(o, '')
5100 val = opts.get(o, '')
5080 if val in (None, ''): # should check against default options instead
5101 if val in (None, ''): # should check against default options instead
5081 continue
5102 continue
5082 baseui.setconfig("web", o, val)
5103 baseui.setconfig("web", o, val)
5083 if repo and repo.ui != baseui:
5104 if repo and repo.ui != baseui:
5084 repo.ui.setconfig("web", o, val)
5105 repo.ui.setconfig("web", o, val)
5085
5106
5086 o = opts.get('web_conf') or opts.get('webdir_conf')
5107 o = opts.get('web_conf') or opts.get('webdir_conf')
5087 if not o:
5108 if not o:
5088 if not repo:
5109 if not repo:
5089 raise error.RepoError(_("There is no Mercurial repository"
5110 raise error.RepoError(_("There is no Mercurial repository"
5090 " here (.hg not found)"))
5111 " here (.hg not found)"))
5091 o = repo.root
5112 o = repo.root
5092
5113
5093 app = hgweb.hgweb(o, baseui=ui)
5114 app = hgweb.hgweb(o, baseui=ui)
5094
5115
5095 class service(object):
5116 class service(object):
5096 def init(self):
5117 def init(self):
5097 util.setsignalhandler()
5118 util.setsignalhandler()
5098 self.httpd = hgweb.server.create_server(ui, app)
5119 self.httpd = hgweb.server.create_server(ui, app)
5099
5120
5100 if opts['port'] and not ui.verbose:
5121 if opts['port'] and not ui.verbose:
5101 return
5122 return
5102
5123
5103 if self.httpd.prefix:
5124 if self.httpd.prefix:
5104 prefix = self.httpd.prefix.strip('/') + '/'
5125 prefix = self.httpd.prefix.strip('/') + '/'
5105 else:
5126 else:
5106 prefix = ''
5127 prefix = ''
5107
5128
5108 port = ':%d' % self.httpd.port
5129 port = ':%d' % self.httpd.port
5109 if port == ':80':
5130 if port == ':80':
5110 port = ''
5131 port = ''
5111
5132
5112 bindaddr = self.httpd.addr
5133 bindaddr = self.httpd.addr
5113 if bindaddr == '0.0.0.0':
5134 if bindaddr == '0.0.0.0':
5114 bindaddr = '*'
5135 bindaddr = '*'
5115 elif ':' in bindaddr: # IPv6
5136 elif ':' in bindaddr: # IPv6
5116 bindaddr = '[%s]' % bindaddr
5137 bindaddr = '[%s]' % bindaddr
5117
5138
5118 fqaddr = self.httpd.fqaddr
5139 fqaddr = self.httpd.fqaddr
5119 if ':' in fqaddr:
5140 if ':' in fqaddr:
5120 fqaddr = '[%s]' % fqaddr
5141 fqaddr = '[%s]' % fqaddr
5121 if opts['port']:
5142 if opts['port']:
5122 write = ui.status
5143 write = ui.status
5123 else:
5144 else:
5124 write = ui.write
5145 write = ui.write
5125 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5146 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5126 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5147 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5127
5148
5128 def run(self):
5149 def run(self):
5129 self.httpd.serve_forever()
5150 self.httpd.serve_forever()
5130
5151
5131 service = service()
5152 service = service()
5132
5153
5133 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5154 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5134
5155
5135 @command('showconfig|debugconfig',
5156 @command('showconfig|debugconfig',
5136 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5157 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5137 _('[-u] [NAME]...'))
5158 _('[-u] [NAME]...'))
5138 def showconfig(ui, repo, *values, **opts):
5159 def showconfig(ui, repo, *values, **opts):
5139 """show combined config settings from all hgrc files
5160 """show combined config settings from all hgrc files
5140
5161
5141 With no arguments, print names and values of all config items.
5162 With no arguments, print names and values of all config items.
5142
5163
5143 With one argument of the form section.name, print just the value
5164 With one argument of the form section.name, print just the value
5144 of that config item.
5165 of that config item.
5145
5166
5146 With multiple arguments, print names and values of all config
5167 With multiple arguments, print names and values of all config
5147 items with matching section names.
5168 items with matching section names.
5148
5169
5149 With --debug, the source (filename and line number) is printed
5170 With --debug, the source (filename and line number) is printed
5150 for each config item.
5171 for each config item.
5151
5172
5152 Returns 0 on success.
5173 Returns 0 on success.
5153 """
5174 """
5154
5175
5155 for f in scmutil.rcpath():
5176 for f in scmutil.rcpath():
5156 ui.debug('read config from: %s\n' % f)
5177 ui.debug('read config from: %s\n' % f)
5157 untrusted = bool(opts.get('untrusted'))
5178 untrusted = bool(opts.get('untrusted'))
5158 if values:
5179 if values:
5159 sections = [v for v in values if '.' not in v]
5180 sections = [v for v in values if '.' not in v]
5160 items = [v for v in values if '.' in v]
5181 items = [v for v in values if '.' in v]
5161 if len(items) > 1 or items and sections:
5182 if len(items) > 1 or items and sections:
5162 raise util.Abort(_('only one config item permitted'))
5183 raise util.Abort(_('only one config item permitted'))
5163 for section, name, value in ui.walkconfig(untrusted=untrusted):
5184 for section, name, value in ui.walkconfig(untrusted=untrusted):
5164 value = str(value).replace('\n', '\\n')
5185 value = str(value).replace('\n', '\\n')
5165 sectname = section + '.' + name
5186 sectname = section + '.' + name
5166 if values:
5187 if values:
5167 for v in values:
5188 for v in values:
5168 if v == section:
5189 if v == section:
5169 ui.debug('%s: ' %
5190 ui.debug('%s: ' %
5170 ui.configsource(section, name, untrusted))
5191 ui.configsource(section, name, untrusted))
5171 ui.write('%s=%s\n' % (sectname, value))
5192 ui.write('%s=%s\n' % (sectname, value))
5172 elif v == sectname:
5193 elif v == sectname:
5173 ui.debug('%s: ' %
5194 ui.debug('%s: ' %
5174 ui.configsource(section, name, untrusted))
5195 ui.configsource(section, name, untrusted))
5175 ui.write(value, '\n')
5196 ui.write(value, '\n')
5176 else:
5197 else:
5177 ui.debug('%s: ' %
5198 ui.debug('%s: ' %
5178 ui.configsource(section, name, untrusted))
5199 ui.configsource(section, name, untrusted))
5179 ui.write('%s=%s\n' % (sectname, value))
5200 ui.write('%s=%s\n' % (sectname, value))
5180
5201
5181 @command('^status|st',
5202 @command('^status|st',
5182 [('A', 'all', None, _('show status of all files')),
5203 [('A', 'all', None, _('show status of all files')),
5183 ('m', 'modified', None, _('show only modified files')),
5204 ('m', 'modified', None, _('show only modified files')),
5184 ('a', 'added', None, _('show only added files')),
5205 ('a', 'added', None, _('show only added files')),
5185 ('r', 'removed', None, _('show only removed files')),
5206 ('r', 'removed', None, _('show only removed files')),
5186 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5207 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5187 ('c', 'clean', None, _('show only files without changes')),
5208 ('c', 'clean', None, _('show only files without changes')),
5188 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5209 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5189 ('i', 'ignored', None, _('show only ignored files')),
5210 ('i', 'ignored', None, _('show only ignored files')),
5190 ('n', 'no-status', None, _('hide status prefix')),
5211 ('n', 'no-status', None, _('hide status prefix')),
5191 ('C', 'copies', None, _('show source of copied files')),
5212 ('C', 'copies', None, _('show source of copied files')),
5192 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5193 ('', 'rev', [], _('show difference from revision'), _('REV')),
5214 ('', 'rev', [], _('show difference from revision'), _('REV')),
5194 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5215 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5195 ] + walkopts + subrepoopts,
5216 ] + walkopts + subrepoopts,
5196 _('[OPTION]... [FILE]...'))
5217 _('[OPTION]... [FILE]...'))
5197 def status(ui, repo, *pats, **opts):
5218 def status(ui, repo, *pats, **opts):
5198 """show changed files in the working directory
5219 """show changed files in the working directory
5199
5220
5200 Show status of files in the repository. If names are given, only
5221 Show status of files in the repository. If names are given, only
5201 files that match are shown. Files that are clean or ignored or
5222 files that match are shown. Files that are clean or ignored or
5202 the source of a copy/move operation, are not listed unless
5223 the source of a copy/move operation, are not listed unless
5203 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5224 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5204 Unless options described with "show only ..." are given, the
5225 Unless options described with "show only ..." are given, the
5205 options -mardu are used.
5226 options -mardu are used.
5206
5227
5207 Option -q/--quiet hides untracked (unknown and ignored) files
5228 Option -q/--quiet hides untracked (unknown and ignored) files
5208 unless explicitly requested with -u/--unknown or -i/--ignored.
5229 unless explicitly requested with -u/--unknown or -i/--ignored.
5209
5230
5210 .. note::
5231 .. note::
5211 status may appear to disagree with diff if permissions have
5232 status may appear to disagree with diff if permissions have
5212 changed or a merge has occurred. The standard diff format does
5233 changed or a merge has occurred. The standard diff format does
5213 not report permission changes and diff only reports changes
5234 not report permission changes and diff only reports changes
5214 relative to one merge parent.
5235 relative to one merge parent.
5215
5236
5216 If one revision is given, it is used as the base revision.
5237 If one revision is given, it is used as the base revision.
5217 If two revisions are given, the differences between them are
5238 If two revisions are given, the differences between them are
5218 shown. The --change option can also be used as a shortcut to list
5239 shown. The --change option can also be used as a shortcut to list
5219 the changed files of a revision from its first parent.
5240 the changed files of a revision from its first parent.
5220
5241
5221 The codes used to show the status of files are::
5242 The codes used to show the status of files are::
5222
5243
5223 M = modified
5244 M = modified
5224 A = added
5245 A = added
5225 R = removed
5246 R = removed
5226 C = clean
5247 C = clean
5227 ! = missing (deleted by non-hg command, but still tracked)
5248 ! = missing (deleted by non-hg command, but still tracked)
5228 ? = not tracked
5249 ? = not tracked
5229 I = ignored
5250 I = ignored
5230 = origin of the previous file listed as A (added)
5251 = origin of the previous file listed as A (added)
5231
5252
5232 .. container:: verbose
5253 .. container:: verbose
5233
5254
5234 Examples:
5255 Examples:
5235
5256
5236 - show changes in the working directory relative to a
5257 - show changes in the working directory relative to a
5237 changeset::
5258 changeset::
5238
5259
5239 hg status --rev 9353
5260 hg status --rev 9353
5240
5261
5241 - show all changes including copies in an existing changeset::
5262 - show all changes including copies in an existing changeset::
5242
5263
5243 hg status --copies --change 9353
5264 hg status --copies --change 9353
5244
5265
5245 - get a NUL separated list of added files, suitable for xargs::
5266 - get a NUL separated list of added files, suitable for xargs::
5246
5267
5247 hg status -an0
5268 hg status -an0
5248
5269
5249 Returns 0 on success.
5270 Returns 0 on success.
5250 """
5271 """
5251
5272
5252 revs = opts.get('rev')
5273 revs = opts.get('rev')
5253 change = opts.get('change')
5274 change = opts.get('change')
5254
5275
5255 if revs and change:
5276 if revs and change:
5256 msg = _('cannot specify --rev and --change at the same time')
5277 msg = _('cannot specify --rev and --change at the same time')
5257 raise util.Abort(msg)
5278 raise util.Abort(msg)
5258 elif change:
5279 elif change:
5259 node2 = scmutil.revsingle(repo, change, None).node()
5280 node2 = scmutil.revsingle(repo, change, None).node()
5260 node1 = repo[node2].p1().node()
5281 node1 = repo[node2].p1().node()
5261 else:
5282 else:
5262 node1, node2 = scmutil.revpair(repo, revs)
5283 node1, node2 = scmutil.revpair(repo, revs)
5263
5284
5264 cwd = (pats and repo.getcwd()) or ''
5285 cwd = (pats and repo.getcwd()) or ''
5265 end = opts.get('print0') and '\0' or '\n'
5286 end = opts.get('print0') and '\0' or '\n'
5266 copy = {}
5287 copy = {}
5267 states = 'modified added removed deleted unknown ignored clean'.split()
5288 states = 'modified added removed deleted unknown ignored clean'.split()
5268 show = [k for k in states if opts.get(k)]
5289 show = [k for k in states if opts.get(k)]
5269 if opts.get('all'):
5290 if opts.get('all'):
5270 show += ui.quiet and (states[:4] + ['clean']) or states
5291 show += ui.quiet and (states[:4] + ['clean']) or states
5271 if not show:
5292 if not show:
5272 show = ui.quiet and states[:4] or states[:5]
5293 show = ui.quiet and states[:4] or states[:5]
5273
5294
5274 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5295 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5275 'ignored' in show, 'clean' in show, 'unknown' in show,
5296 'ignored' in show, 'clean' in show, 'unknown' in show,
5276 opts.get('subrepos'))
5297 opts.get('subrepos'))
5277 changestates = zip(states, 'MAR!?IC', stat)
5298 changestates = zip(states, 'MAR!?IC', stat)
5278
5299
5279 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5300 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5280 copy = copies.pathcopies(repo[node1], repo[node2])
5301 copy = copies.pathcopies(repo[node1], repo[node2])
5281
5302
5282 fm = ui.formatter('status', opts)
5303 fm = ui.formatter('status', opts)
5283 format = '%s %s' + end
5304 format = '%s %s' + end
5284 if opts.get('no_status'):
5305 if opts.get('no_status'):
5285 format = '%.0s%s' + end
5306 format = '%.0s%s' + end
5286
5307
5287 for state, char, files in changestates:
5308 for state, char, files in changestates:
5288 if state in show:
5309 if state in show:
5289 label = 'status.' + state
5310 label = 'status.' + state
5290 for f in files:
5311 for f in files:
5291 fm.startitem()
5312 fm.startitem()
5292 fm.write("status path", format, char,
5313 fm.write("status path", format, char,
5293 repo.pathto(f, cwd), label=label)
5314 repo.pathto(f, cwd), label=label)
5294 if f in copy:
5315 if f in copy:
5295 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5316 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5296 label='status.copied')
5317 label='status.copied')
5297 fm.end()
5318 fm.end()
5298
5319
5299 @command('^summary|sum',
5320 @command('^summary|sum',
5300 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5321 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5301 def summary(ui, repo, **opts):
5322 def summary(ui, repo, **opts):
5302 """summarize working directory state
5323 """summarize working directory state
5303
5324
5304 This generates a brief summary of the working directory state,
5325 This generates a brief summary of the working directory state,
5305 including parents, branch, commit status, and available updates.
5326 including parents, branch, commit status, and available updates.
5306
5327
5307 With the --remote option, this will check the default paths for
5328 With the --remote option, this will check the default paths for
5308 incoming and outgoing changes. This can be time-consuming.
5329 incoming and outgoing changes. This can be time-consuming.
5309
5330
5310 Returns 0 on success.
5331 Returns 0 on success.
5311 """
5332 """
5312
5333
5313 ctx = repo[None]
5334 ctx = repo[None]
5314 parents = ctx.parents()
5335 parents = ctx.parents()
5315 pnode = parents[0].node()
5336 pnode = parents[0].node()
5316 marks = []
5337 marks = []
5317
5338
5318 for p in parents:
5339 for p in parents:
5319 # label with log.changeset (instead of log.parent) since this
5340 # label with log.changeset (instead of log.parent) since this
5320 # shows a working directory parent *changeset*:
5341 # shows a working directory parent *changeset*:
5321 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5342 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5322 label='log.changeset')
5343 label='log.changeset')
5323 ui.write(' '.join(p.tags()), label='log.tag')
5344 ui.write(' '.join(p.tags()), label='log.tag')
5324 if p.bookmarks():
5345 if p.bookmarks():
5325 marks.extend(p.bookmarks())
5346 marks.extend(p.bookmarks())
5326 if p.rev() == -1:
5347 if p.rev() == -1:
5327 if not len(repo):
5348 if not len(repo):
5328 ui.write(_(' (empty repository)'))
5349 ui.write(_(' (empty repository)'))
5329 else:
5350 else:
5330 ui.write(_(' (no revision checked out)'))
5351 ui.write(_(' (no revision checked out)'))
5331 ui.write('\n')
5352 ui.write('\n')
5332 if p.description():
5353 if p.description():
5333 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5354 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5334 label='log.summary')
5355 label='log.summary')
5335
5356
5336 branch = ctx.branch()
5357 branch = ctx.branch()
5337 bheads = repo.branchheads(branch)
5358 bheads = repo.branchheads(branch)
5338 m = _('branch: %s\n') % branch
5359 m = _('branch: %s\n') % branch
5339 if branch != 'default':
5360 if branch != 'default':
5340 ui.write(m, label='log.branch')
5361 ui.write(m, label='log.branch')
5341 else:
5362 else:
5342 ui.status(m, label='log.branch')
5363 ui.status(m, label='log.branch')
5343
5364
5344 if marks:
5365 if marks:
5345 current = repo._bookmarkcurrent
5366 current = repo._bookmarkcurrent
5346 ui.write(_('bookmarks:'), label='log.bookmark')
5367 ui.write(_('bookmarks:'), label='log.bookmark')
5347 if current is not None:
5368 if current is not None:
5348 try:
5369 try:
5349 marks.remove(current)
5370 marks.remove(current)
5350 ui.write(' *' + current, label='bookmarks.current')
5371 ui.write(' *' + current, label='bookmarks.current')
5351 except ValueError:
5372 except ValueError:
5352 # current bookmark not in parent ctx marks
5373 # current bookmark not in parent ctx marks
5353 pass
5374 pass
5354 for m in marks:
5375 for m in marks:
5355 ui.write(' ' + m, label='log.bookmark')
5376 ui.write(' ' + m, label='log.bookmark')
5356 ui.write('\n', label='log.bookmark')
5377 ui.write('\n', label='log.bookmark')
5357
5378
5358 st = list(repo.status(unknown=True))[:6]
5379 st = list(repo.status(unknown=True))[:6]
5359
5380
5360 c = repo.dirstate.copies()
5381 c = repo.dirstate.copies()
5361 copied, renamed = [], []
5382 copied, renamed = [], []
5362 for d, s in c.iteritems():
5383 for d, s in c.iteritems():
5363 if s in st[2]:
5384 if s in st[2]:
5364 st[2].remove(s)
5385 st[2].remove(s)
5365 renamed.append(d)
5386 renamed.append(d)
5366 else:
5387 else:
5367 copied.append(d)
5388 copied.append(d)
5368 if d in st[1]:
5389 if d in st[1]:
5369 st[1].remove(d)
5390 st[1].remove(d)
5370 st.insert(3, renamed)
5391 st.insert(3, renamed)
5371 st.insert(4, copied)
5392 st.insert(4, copied)
5372
5393
5373 ms = mergemod.mergestate(repo)
5394 ms = mergemod.mergestate(repo)
5374 st.append([f for f in ms if ms[f] == 'u'])
5395 st.append([f for f in ms if ms[f] == 'u'])
5375
5396
5376 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5397 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5377 st.append(subs)
5398 st.append(subs)
5378
5399
5379 labels = [ui.label(_('%d modified'), 'status.modified'),
5400 labels = [ui.label(_('%d modified'), 'status.modified'),
5380 ui.label(_('%d added'), 'status.added'),
5401 ui.label(_('%d added'), 'status.added'),
5381 ui.label(_('%d removed'), 'status.removed'),
5402 ui.label(_('%d removed'), 'status.removed'),
5382 ui.label(_('%d renamed'), 'status.copied'),
5403 ui.label(_('%d renamed'), 'status.copied'),
5383 ui.label(_('%d copied'), 'status.copied'),
5404 ui.label(_('%d copied'), 'status.copied'),
5384 ui.label(_('%d deleted'), 'status.deleted'),
5405 ui.label(_('%d deleted'), 'status.deleted'),
5385 ui.label(_('%d unknown'), 'status.unknown'),
5406 ui.label(_('%d unknown'), 'status.unknown'),
5386 ui.label(_('%d ignored'), 'status.ignored'),
5407 ui.label(_('%d ignored'), 'status.ignored'),
5387 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5408 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5388 ui.label(_('%d subrepos'), 'status.modified')]
5409 ui.label(_('%d subrepos'), 'status.modified')]
5389 t = []
5410 t = []
5390 for s, l in zip(st, labels):
5411 for s, l in zip(st, labels):
5391 if s:
5412 if s:
5392 t.append(l % len(s))
5413 t.append(l % len(s))
5393
5414
5394 t = ', '.join(t)
5415 t = ', '.join(t)
5395 cleanworkdir = False
5416 cleanworkdir = False
5396
5417
5397 if len(parents) > 1:
5418 if len(parents) > 1:
5398 t += _(' (merge)')
5419 t += _(' (merge)')
5399 elif branch != parents[0].branch():
5420 elif branch != parents[0].branch():
5400 t += _(' (new branch)')
5421 t += _(' (new branch)')
5401 elif (parents[0].extra().get('close') and
5422 elif (parents[0].extra().get('close') and
5402 pnode in repo.branchheads(branch, closed=True)):
5423 pnode in repo.branchheads(branch, closed=True)):
5403 t += _(' (head closed)')
5424 t += _(' (head closed)')
5404 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5425 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5405 t += _(' (clean)')
5426 t += _(' (clean)')
5406 cleanworkdir = True
5427 cleanworkdir = True
5407 elif pnode not in bheads:
5428 elif pnode not in bheads:
5408 t += _(' (new branch head)')
5429 t += _(' (new branch head)')
5409
5430
5410 if cleanworkdir:
5431 if cleanworkdir:
5411 ui.status(_('commit: %s\n') % t.strip())
5432 ui.status(_('commit: %s\n') % t.strip())
5412 else:
5433 else:
5413 ui.write(_('commit: %s\n') % t.strip())
5434 ui.write(_('commit: %s\n') % t.strip())
5414
5435
5415 # all ancestors of branch heads - all ancestors of parent = new csets
5436 # all ancestors of branch heads - all ancestors of parent = new csets
5416 new = [0] * len(repo)
5437 new = [0] * len(repo)
5417 cl = repo.changelog
5438 cl = repo.changelog
5418 for a in [cl.rev(n) for n in bheads]:
5439 for a in [cl.rev(n) for n in bheads]:
5419 new[a] = 1
5440 new[a] = 1
5420 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5441 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5421 new[a] = 1
5442 new[a] = 1
5422 for a in [p.rev() for p in parents]:
5443 for a in [p.rev() for p in parents]:
5423 if a >= 0:
5444 if a >= 0:
5424 new[a] = 0
5445 new[a] = 0
5425 for a in cl.ancestors(*[p.rev() for p in parents]):
5446 for a in cl.ancestors(*[p.rev() for p in parents]):
5426 new[a] = 0
5447 new[a] = 0
5427 new = sum(new)
5448 new = sum(new)
5428
5449
5429 if new == 0:
5450 if new == 0:
5430 ui.status(_('update: (current)\n'))
5451 ui.status(_('update: (current)\n'))
5431 elif pnode not in bheads:
5452 elif pnode not in bheads:
5432 ui.write(_('update: %d new changesets (update)\n') % new)
5453 ui.write(_('update: %d new changesets (update)\n') % new)
5433 else:
5454 else:
5434 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5455 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5435 (new, len(bheads)))
5456 (new, len(bheads)))
5436
5457
5437 if opts.get('remote'):
5458 if opts.get('remote'):
5438 t = []
5459 t = []
5439 source, branches = hg.parseurl(ui.expandpath('default'))
5460 source, branches = hg.parseurl(ui.expandpath('default'))
5440 other = hg.peer(repo, {}, source)
5461 other = hg.peer(repo, {}, source)
5441 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5462 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5442 ui.debug('comparing with %s\n' % util.hidepassword(source))
5463 ui.debug('comparing with %s\n' % util.hidepassword(source))
5443 repo.ui.pushbuffer()
5464 repo.ui.pushbuffer()
5444 commoninc = discovery.findcommonincoming(repo, other)
5465 commoninc = discovery.findcommonincoming(repo, other)
5445 _common, incoming, _rheads = commoninc
5466 _common, incoming, _rheads = commoninc
5446 repo.ui.popbuffer()
5467 repo.ui.popbuffer()
5447 if incoming:
5468 if incoming:
5448 t.append(_('1 or more incoming'))
5469 t.append(_('1 or more incoming'))
5449
5470
5450 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5471 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5451 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5472 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5452 if source != dest:
5473 if source != dest:
5453 other = hg.peer(repo, {}, dest)
5474 other = hg.peer(repo, {}, dest)
5454 commoninc = None
5475 commoninc = None
5455 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5476 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5456 repo.ui.pushbuffer()
5477 repo.ui.pushbuffer()
5457 outgoing = discovery.findcommonoutgoing(repo, other,
5478 outgoing = discovery.findcommonoutgoing(repo, other,
5458 commoninc=commoninc)
5479 commoninc=commoninc)
5459 repo.ui.popbuffer()
5480 repo.ui.popbuffer()
5460 o = outgoing.missing
5481 o = outgoing.missing
5461 if o:
5482 if o:
5462 t.append(_('%d outgoing') % len(o))
5483 t.append(_('%d outgoing') % len(o))
5463 if 'bookmarks' in other.listkeys('namespaces'):
5484 if 'bookmarks' in other.listkeys('namespaces'):
5464 lmarks = repo.listkeys('bookmarks')
5485 lmarks = repo.listkeys('bookmarks')
5465 rmarks = other.listkeys('bookmarks')
5486 rmarks = other.listkeys('bookmarks')
5466 diff = set(rmarks) - set(lmarks)
5487 diff = set(rmarks) - set(lmarks)
5467 if len(diff) > 0:
5488 if len(diff) > 0:
5468 t.append(_('%d incoming bookmarks') % len(diff))
5489 t.append(_('%d incoming bookmarks') % len(diff))
5469 diff = set(lmarks) - set(rmarks)
5490 diff = set(lmarks) - set(rmarks)
5470 if len(diff) > 0:
5491 if len(diff) > 0:
5471 t.append(_('%d outgoing bookmarks') % len(diff))
5492 t.append(_('%d outgoing bookmarks') % len(diff))
5472
5493
5473 if t:
5494 if t:
5474 ui.write(_('remote: %s\n') % (', '.join(t)))
5495 ui.write(_('remote: %s\n') % (', '.join(t)))
5475 else:
5496 else:
5476 ui.status(_('remote: (synced)\n'))
5497 ui.status(_('remote: (synced)\n'))
5477
5498
5478 @command('tag',
5499 @command('tag',
5479 [('f', 'force', None, _('force tag')),
5500 [('f', 'force', None, _('force tag')),
5480 ('l', 'local', None, _('make the tag local')),
5501 ('l', 'local', None, _('make the tag local')),
5481 ('r', 'rev', '', _('revision to tag'), _('REV')),
5502 ('r', 'rev', '', _('revision to tag'), _('REV')),
5482 ('', 'remove', None, _('remove a tag')),
5503 ('', 'remove', None, _('remove a tag')),
5483 # -l/--local is already there, commitopts cannot be used
5504 # -l/--local is already there, commitopts cannot be used
5484 ('e', 'edit', None, _('edit commit message')),
5505 ('e', 'edit', None, _('edit commit message')),
5485 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5506 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5486 ] + commitopts2,
5507 ] + commitopts2,
5487 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5508 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5488 def tag(ui, repo, name1, *names, **opts):
5509 def tag(ui, repo, name1, *names, **opts):
5489 """add one or more tags for the current or given revision
5510 """add one or more tags for the current or given revision
5490
5511
5491 Name a particular revision using <name>.
5512 Name a particular revision using <name>.
5492
5513
5493 Tags are used to name particular revisions of the repository and are
5514 Tags are used to name particular revisions of the repository and are
5494 very useful to compare different revisions, to go back to significant
5515 very useful to compare different revisions, to go back to significant
5495 earlier versions or to mark branch points as releases, etc. Changing
5516 earlier versions or to mark branch points as releases, etc. Changing
5496 an existing tag is normally disallowed; use -f/--force to override.
5517 an existing tag is normally disallowed; use -f/--force to override.
5497
5518
5498 If no revision is given, the parent of the working directory is
5519 If no revision is given, the parent of the working directory is
5499 used, or tip if no revision is checked out.
5520 used, or tip if no revision is checked out.
5500
5521
5501 To facilitate version control, distribution, and merging of tags,
5522 To facilitate version control, distribution, and merging of tags,
5502 they are stored as a file named ".hgtags" which is managed similarly
5523 they are stored as a file named ".hgtags" which is managed similarly
5503 to other project files and can be hand-edited if necessary. This
5524 to other project files and can be hand-edited if necessary. This
5504 also means that tagging creates a new commit. The file
5525 also means that tagging creates a new commit. The file
5505 ".hg/localtags" is used for local tags (not shared among
5526 ".hg/localtags" is used for local tags (not shared among
5506 repositories).
5527 repositories).
5507
5528
5508 Tag commits are usually made at the head of a branch. If the parent
5529 Tag commits are usually made at the head of a branch. If the parent
5509 of the working directory is not a branch head, :hg:`tag` aborts; use
5530 of the working directory is not a branch head, :hg:`tag` aborts; use
5510 -f/--force to force the tag commit to be based on a non-head
5531 -f/--force to force the tag commit to be based on a non-head
5511 changeset.
5532 changeset.
5512
5533
5513 See :hg:`help dates` for a list of formats valid for -d/--date.
5534 See :hg:`help dates` for a list of formats valid for -d/--date.
5514
5535
5515 Since tag names have priority over branch names during revision
5536 Since tag names have priority over branch names during revision
5516 lookup, using an existing branch name as a tag name is discouraged.
5537 lookup, using an existing branch name as a tag name is discouraged.
5517
5538
5518 Returns 0 on success.
5539 Returns 0 on success.
5519 """
5540 """
5520 wlock = lock = None
5541 wlock = lock = None
5521 try:
5542 try:
5522 wlock = repo.wlock()
5543 wlock = repo.wlock()
5523 lock = repo.lock()
5544 lock = repo.lock()
5524 rev_ = "."
5545 rev_ = "."
5525 names = [t.strip() for t in (name1,) + names]
5546 names = [t.strip() for t in (name1,) + names]
5526 if len(names) != len(set(names)):
5547 if len(names) != len(set(names)):
5527 raise util.Abort(_('tag names must be unique'))
5548 raise util.Abort(_('tag names must be unique'))
5528 for n in names:
5549 for n in names:
5529 if n in ['tip', '.', 'null']:
5550 if n in ['tip', '.', 'null']:
5530 raise util.Abort(_("the name '%s' is reserved") % n)
5551 raise util.Abort(_("the name '%s' is reserved") % n)
5531 if not n:
5552 if not n:
5532 raise util.Abort(_('tag names cannot consist entirely of '
5553 raise util.Abort(_('tag names cannot consist entirely of '
5533 'whitespace'))
5554 'whitespace'))
5534 if opts.get('rev') and opts.get('remove'):
5555 if opts.get('rev') and opts.get('remove'):
5535 raise util.Abort(_("--rev and --remove are incompatible"))
5556 raise util.Abort(_("--rev and --remove are incompatible"))
5536 if opts.get('rev'):
5557 if opts.get('rev'):
5537 rev_ = opts['rev']
5558 rev_ = opts['rev']
5538 message = opts.get('message')
5559 message = opts.get('message')
5539 if opts.get('remove'):
5560 if opts.get('remove'):
5540 expectedtype = opts.get('local') and 'local' or 'global'
5561 expectedtype = opts.get('local') and 'local' or 'global'
5541 for n in names:
5562 for n in names:
5542 if not repo.tagtype(n):
5563 if not repo.tagtype(n):
5543 raise util.Abort(_("tag '%s' does not exist") % n)
5564 raise util.Abort(_("tag '%s' does not exist") % n)
5544 if repo.tagtype(n) != expectedtype:
5565 if repo.tagtype(n) != expectedtype:
5545 if expectedtype == 'global':
5566 if expectedtype == 'global':
5546 raise util.Abort(_("tag '%s' is not a global tag") % n)
5567 raise util.Abort(_("tag '%s' is not a global tag") % n)
5547 else:
5568 else:
5548 raise util.Abort(_("tag '%s' is not a local tag") % n)
5569 raise util.Abort(_("tag '%s' is not a local tag") % n)
5549 rev_ = nullid
5570 rev_ = nullid
5550 if not message:
5571 if not message:
5551 # we don't translate commit messages
5572 # we don't translate commit messages
5552 message = 'Removed tag %s' % ', '.join(names)
5573 message = 'Removed tag %s' % ', '.join(names)
5553 elif not opts.get('force'):
5574 elif not opts.get('force'):
5554 for n in names:
5575 for n in names:
5555 if n in repo.tags():
5576 if n in repo.tags():
5556 raise util.Abort(_("tag '%s' already exists "
5577 raise util.Abort(_("tag '%s' already exists "
5557 "(use -f to force)") % n)
5578 "(use -f to force)") % n)
5558 if not opts.get('local'):
5579 if not opts.get('local'):
5559 p1, p2 = repo.dirstate.parents()
5580 p1, p2 = repo.dirstate.parents()
5560 if p2 != nullid:
5581 if p2 != nullid:
5561 raise util.Abort(_('uncommitted merge'))
5582 raise util.Abort(_('uncommitted merge'))
5562 bheads = repo.branchheads()
5583 bheads = repo.branchheads()
5563 if not opts.get('force') and bheads and p1 not in bheads:
5584 if not opts.get('force') and bheads and p1 not in bheads:
5564 raise util.Abort(_('not at a branch head (use -f to force)'))
5585 raise util.Abort(_('not at a branch head (use -f to force)'))
5565 r = scmutil.revsingle(repo, rev_).node()
5586 r = scmutil.revsingle(repo, rev_).node()
5566
5587
5567 if not message:
5588 if not message:
5568 # we don't translate commit messages
5589 # we don't translate commit messages
5569 message = ('Added tag %s for changeset %s' %
5590 message = ('Added tag %s for changeset %s' %
5570 (', '.join(names), short(r)))
5591 (', '.join(names), short(r)))
5571
5592
5572 date = opts.get('date')
5593 date = opts.get('date')
5573 if date:
5594 if date:
5574 date = util.parsedate(date)
5595 date = util.parsedate(date)
5575
5596
5576 if opts.get('edit'):
5597 if opts.get('edit'):
5577 message = ui.edit(message, ui.username())
5598 message = ui.edit(message, ui.username())
5578
5599
5579 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5600 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5580 finally:
5601 finally:
5581 release(lock, wlock)
5602 release(lock, wlock)
5582
5603
5583 @command('tags', [], '')
5604 @command('tags', [], '')
5584 def tags(ui, repo):
5605 def tags(ui, repo):
5585 """list repository tags
5606 """list repository tags
5586
5607
5587 This lists both regular and local tags. When the -v/--verbose
5608 This lists both regular and local tags. When the -v/--verbose
5588 switch is used, a third column "local" is printed for local tags.
5609 switch is used, a third column "local" is printed for local tags.
5589
5610
5590 Returns 0 on success.
5611 Returns 0 on success.
5591 """
5612 """
5592
5613
5593 hexfunc = ui.debugflag and hex or short
5614 hexfunc = ui.debugflag and hex or short
5594 tagtype = ""
5615 tagtype = ""
5595
5616
5596 for t, n in reversed(repo.tagslist()):
5617 for t, n in reversed(repo.tagslist()):
5597 if ui.quiet:
5618 if ui.quiet:
5598 ui.write("%s\n" % t, label='tags.normal')
5619 ui.write("%s\n" % t, label='tags.normal')
5599 continue
5620 continue
5600
5621
5601 hn = hexfunc(n)
5622 hn = hexfunc(n)
5602 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5623 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5603 rev = ui.label(r, 'log.changeset')
5624 rev = ui.label(r, 'log.changeset')
5604 spaces = " " * (30 - encoding.colwidth(t))
5625 spaces = " " * (30 - encoding.colwidth(t))
5605
5626
5606 tag = ui.label(t, 'tags.normal')
5627 tag = ui.label(t, 'tags.normal')
5607 if ui.verbose:
5628 if ui.verbose:
5608 if repo.tagtype(t) == 'local':
5629 if repo.tagtype(t) == 'local':
5609 tagtype = " local"
5630 tagtype = " local"
5610 tag = ui.label(t, 'tags.local')
5631 tag = ui.label(t, 'tags.local')
5611 else:
5632 else:
5612 tagtype = ""
5633 tagtype = ""
5613 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5634 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5614
5635
5615 @command('tip',
5636 @command('tip',
5616 [('p', 'patch', None, _('show patch')),
5637 [('p', 'patch', None, _('show patch')),
5617 ('g', 'git', None, _('use git extended diff format')),
5638 ('g', 'git', None, _('use git extended diff format')),
5618 ] + templateopts,
5639 ] + templateopts,
5619 _('[-p] [-g]'))
5640 _('[-p] [-g]'))
5620 def tip(ui, repo, **opts):
5641 def tip(ui, repo, **opts):
5621 """show the tip revision
5642 """show the tip revision
5622
5643
5623 The tip revision (usually just called the tip) is the changeset
5644 The tip revision (usually just called the tip) is the changeset
5624 most recently added to the repository (and therefore the most
5645 most recently added to the repository (and therefore the most
5625 recently changed head).
5646 recently changed head).
5626
5647
5627 If you have just made a commit, that commit will be the tip. If
5648 If you have just made a commit, that commit will be the tip. If
5628 you have just pulled changes from another repository, the tip of
5649 you have just pulled changes from another repository, the tip of
5629 that repository becomes the current tip. The "tip" tag is special
5650 that repository becomes the current tip. The "tip" tag is special
5630 and cannot be renamed or assigned to a different changeset.
5651 and cannot be renamed or assigned to a different changeset.
5631
5652
5632 Returns 0 on success.
5653 Returns 0 on success.
5633 """
5654 """
5634 displayer = cmdutil.show_changeset(ui, repo, opts)
5655 displayer = cmdutil.show_changeset(ui, repo, opts)
5635 displayer.show(repo[len(repo) - 1])
5656 displayer.show(repo[len(repo) - 1])
5636 displayer.close()
5657 displayer.close()
5637
5658
5638 @command('unbundle',
5659 @command('unbundle',
5639 [('u', 'update', None,
5660 [('u', 'update', None,
5640 _('update to new branch head if changesets were unbundled'))],
5661 _('update to new branch head if changesets were unbundled'))],
5641 _('[-u] FILE...'))
5662 _('[-u] FILE...'))
5642 def unbundle(ui, repo, fname1, *fnames, **opts):
5663 def unbundle(ui, repo, fname1, *fnames, **opts):
5643 """apply one or more changegroup files
5664 """apply one or more changegroup files
5644
5665
5645 Apply one or more compressed changegroup files generated by the
5666 Apply one or more compressed changegroup files generated by the
5646 bundle command.
5667 bundle command.
5647
5668
5648 Returns 0 on success, 1 if an update has unresolved files.
5669 Returns 0 on success, 1 if an update has unresolved files.
5649 """
5670 """
5650 fnames = (fname1,) + fnames
5671 fnames = (fname1,) + fnames
5651
5672
5652 lock = repo.lock()
5673 lock = repo.lock()
5653 wc = repo['.']
5674 wc = repo['.']
5654 try:
5675 try:
5655 for fname in fnames:
5676 for fname in fnames:
5656 f = url.open(ui, fname)
5677 f = url.open(ui, fname)
5657 gen = changegroup.readbundle(f, fname)
5678 gen = changegroup.readbundle(f, fname)
5658 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5679 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5659 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5680 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5660 finally:
5681 finally:
5661 lock.release()
5682 lock.release()
5662 return postincoming(ui, repo, modheads, opts.get('update'), None)
5683 return postincoming(ui, repo, modheads, opts.get('update'), None)
5663
5684
5664 @command('^update|up|checkout|co',
5685 @command('^update|up|checkout|co',
5665 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5686 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5666 ('c', 'check', None,
5687 ('c', 'check', None,
5667 _('update across branches if no uncommitted changes')),
5688 _('update across branches if no uncommitted changes')),
5668 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5689 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5669 ('r', 'rev', '', _('revision'), _('REV'))],
5690 ('r', 'rev', '', _('revision'), _('REV'))],
5670 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5691 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5671 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5692 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5672 """update working directory (or switch revisions)
5693 """update working directory (or switch revisions)
5673
5694
5674 Update the repository's working directory to the specified
5695 Update the repository's working directory to the specified
5675 changeset. If no changeset is specified, update to the tip of the
5696 changeset. If no changeset is specified, update to the tip of the
5676 current named branch and move the current bookmark (see :hg:`help
5697 current named branch and move the current bookmark (see :hg:`help
5677 bookmarks`).
5698 bookmarks`).
5678
5699
5679 If the changeset is not a descendant of the working directory's
5700 If the changeset is not a descendant of the working directory's
5680 parent, the update is aborted. With the -c/--check option, the
5701 parent, the update is aborted. With the -c/--check option, the
5681 working directory is checked for uncommitted changes; if none are
5702 working directory is checked for uncommitted changes; if none are
5682 found, the working directory is updated to the specified
5703 found, the working directory is updated to the specified
5683 changeset.
5704 changeset.
5684
5705
5685 Update sets the working directory's parent revison to the specified
5706 Update sets the working directory's parent revison to the specified
5686 changeset (see :hg:`help parents`).
5707 changeset (see :hg:`help parents`).
5687
5708
5688 The following rules apply when the working directory contains
5709 The following rules apply when the working directory contains
5689 uncommitted changes:
5710 uncommitted changes:
5690
5711
5691 1. If neither -c/--check nor -C/--clean is specified, and if
5712 1. If neither -c/--check nor -C/--clean is specified, and if
5692 the requested changeset is an ancestor or descendant of
5713 the requested changeset is an ancestor or descendant of
5693 the working directory's parent, the uncommitted changes
5714 the working directory's parent, the uncommitted changes
5694 are merged into the requested changeset and the merged
5715 are merged into the requested changeset and the merged
5695 result is left uncommitted. If the requested changeset is
5716 result is left uncommitted. If the requested changeset is
5696 not an ancestor or descendant (that is, it is on another
5717 not an ancestor or descendant (that is, it is on another
5697 branch), the update is aborted and the uncommitted changes
5718 branch), the update is aborted and the uncommitted changes
5698 are preserved.
5719 are preserved.
5699
5720
5700 2. With the -c/--check option, the update is aborted and the
5721 2. With the -c/--check option, the update is aborted and the
5701 uncommitted changes are preserved.
5722 uncommitted changes are preserved.
5702
5723
5703 3. With the -C/--clean option, uncommitted changes are discarded and
5724 3. With the -C/--clean option, uncommitted changes are discarded and
5704 the working directory is updated to the requested changeset.
5725 the working directory is updated to the requested changeset.
5705
5726
5706 Use null as the changeset to remove the working directory (like
5727 Use null as the changeset to remove the working directory (like
5707 :hg:`clone -U`).
5728 :hg:`clone -U`).
5708
5729
5709 If you want to revert just one file to an older revision, use
5730 If you want to revert just one file to an older revision, use
5710 :hg:`revert [-r REV] NAME`.
5731 :hg:`revert [-r REV] NAME`.
5711
5732
5712 See :hg:`help dates` for a list of formats valid for -d/--date.
5733 See :hg:`help dates` for a list of formats valid for -d/--date.
5713
5734
5714 Returns 0 on success, 1 if there are unresolved files.
5735 Returns 0 on success, 1 if there are unresolved files.
5715 """
5736 """
5716 if rev and node:
5737 if rev and node:
5717 raise util.Abort(_("please specify just one revision"))
5738 raise util.Abort(_("please specify just one revision"))
5718
5739
5719 if rev is None or rev == '':
5740 if rev is None or rev == '':
5720 rev = node
5741 rev = node
5721
5742
5722 # with no argument, we also move the current bookmark, if any
5743 # with no argument, we also move the current bookmark, if any
5723 movemarkfrom = None
5744 movemarkfrom = None
5724 if rev is None or node == '':
5745 if rev is None or node == '':
5725 movemarkfrom = repo['.'].node()
5746 movemarkfrom = repo['.'].node()
5726
5747
5727 # if we defined a bookmark, we have to remember the original bookmark name
5748 # if we defined a bookmark, we have to remember the original bookmark name
5728 brev = rev
5749 brev = rev
5729 rev = scmutil.revsingle(repo, rev, rev).rev()
5750 rev = scmutil.revsingle(repo, rev, rev).rev()
5730
5751
5731 if check and clean:
5752 if check and clean:
5732 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5753 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5733
5754
5734 if date:
5755 if date:
5735 if rev is not None:
5756 if rev is not None:
5736 raise util.Abort(_("you can't specify a revision and a date"))
5757 raise util.Abort(_("you can't specify a revision and a date"))
5737 rev = cmdutil.finddate(ui, repo, date)
5758 rev = cmdutil.finddate(ui, repo, date)
5738
5759
5739 if check:
5760 if check:
5740 # we could use dirty() but we can ignore merge and branch trivia
5761 # we could use dirty() but we can ignore merge and branch trivia
5741 c = repo[None]
5762 c = repo[None]
5742 if c.modified() or c.added() or c.removed():
5763 if c.modified() or c.added() or c.removed():
5743 raise util.Abort(_("uncommitted local changes"))
5764 raise util.Abort(_("uncommitted local changes"))
5744 if not rev:
5765 if not rev:
5745 rev = repo[repo[None].branch()].rev()
5766 rev = repo[repo[None].branch()].rev()
5746 mergemod._checkunknown(repo, repo[None], repo[rev])
5767 mergemod._checkunknown(repo, repo[None], repo[rev])
5747
5768
5748 if clean:
5769 if clean:
5749 ret = hg.clean(repo, rev)
5770 ret = hg.clean(repo, rev)
5750 else:
5771 else:
5751 ret = hg.update(repo, rev)
5772 ret = hg.update(repo, rev)
5752
5773
5753 if not ret and movemarkfrom:
5774 if not ret and movemarkfrom:
5754 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5775 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5755 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5776 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5756 elif brev in repo._bookmarks:
5777 elif brev in repo._bookmarks:
5757 bookmarks.setcurrent(repo, brev)
5778 bookmarks.setcurrent(repo, brev)
5758 elif brev:
5779 elif brev:
5759 bookmarks.unsetcurrent(repo)
5780 bookmarks.unsetcurrent(repo)
5760
5781
5761 return ret
5782 return ret
5762
5783
5763 @command('verify', [])
5784 @command('verify', [])
5764 def verify(ui, repo):
5785 def verify(ui, repo):
5765 """verify the integrity of the repository
5786 """verify the integrity of the repository
5766
5787
5767 Verify the integrity of the current repository.
5788 Verify the integrity of the current repository.
5768
5789
5769 This will perform an extensive check of the repository's
5790 This will perform an extensive check of the repository's
5770 integrity, validating the hashes and checksums of each entry in
5791 integrity, validating the hashes and checksums of each entry in
5771 the changelog, manifest, and tracked files, as well as the
5792 the changelog, manifest, and tracked files, as well as the
5772 integrity of their crosslinks and indices.
5793 integrity of their crosslinks and indices.
5773
5794
5774 Returns 0 on success, 1 if errors are encountered.
5795 Returns 0 on success, 1 if errors are encountered.
5775 """
5796 """
5776 return hg.verify(repo)
5797 return hg.verify(repo)
5777
5798
5778 @command('version', [])
5799 @command('version', [])
5779 def version_(ui):
5800 def version_(ui):
5780 """output version and copyright information"""
5801 """output version and copyright information"""
5781 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5802 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5782 % util.version())
5803 % util.version())
5783 ui.status(_(
5804 ui.status(_(
5784 "(see http://mercurial.selenic.com for more information)\n"
5805 "(see http://mercurial.selenic.com for more information)\n"
5785 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5806 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5786 "This is free software; see the source for copying conditions. "
5807 "This is free software; see the source for copying conditions. "
5787 "There is NO\nwarranty; "
5808 "There is NO\nwarranty; "
5788 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5809 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5789 ))
5810 ))
5790
5811
5791 norepo = ("clone init version help debugcommands debugcomplete"
5812 norepo = ("clone init version help debugcommands debugcomplete"
5792 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5813 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5793 " debugknown debuggetbundle debugbundle")
5814 " debugknown debuggetbundle debugbundle")
5794 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5815 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5795 " debugdata debugindex debugindexdot debugrevlog")
5816 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,272 +1,274 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 copy
16 copy
17 diff
17 diff
18 export
18 export
19 forget
19 forget
20 graft
20 graft
21 grep
21 grep
22 heads
22 heads
23 help
23 help
24 identify
24 identify
25 import
25 import
26 incoming
26 incoming
27 init
27 init
28 locate
28 locate
29 log
29 log
30 manifest
30 manifest
31 merge
31 merge
32 outgoing
32 outgoing
33 parents
33 parents
34 paths
34 paths
35 phase
35 phase
36 pull
36 pull
37 push
37 push
38 recover
38 recover
39 remove
39 remove
40 rename
40 rename
41 resolve
41 resolve
42 revert
42 revert
43 rollback
43 rollback
44 root
44 root
45 serve
45 serve
46 showconfig
46 showconfig
47 status
47 status
48 summary
48 summary
49 tag
49 tag
50 tags
50 tags
51 tip
51 tip
52 unbundle
52 unbundle
53 update
53 update
54 verify
54 verify
55 version
55 version
56
56
57 Show all commands that start with "a"
57 Show all commands that start with "a"
58 $ hg debugcomplete a
58 $ hg debugcomplete a
59 add
59 add
60 addremove
60 addremove
61 annotate
61 annotate
62 archive
62 archive
63
63
64 Do not show debug commands if there are other candidates
64 Do not show debug commands if there are other candidates
65 $ hg debugcomplete d
65 $ hg debugcomplete d
66 diff
66 diff
67
67
68 Show debug commands if there are no other candidates
68 Show debug commands if there are no other candidates
69 $ hg debugcomplete debug
69 $ hg debugcomplete debug
70 debugancestor
70 debugancestor
71 debugbuilddag
71 debugbuilddag
72 debugbundle
72 debugbundle
73 debugcheckstate
73 debugcheckstate
74 debugcommands
74 debugcommands
75 debugcomplete
75 debugcomplete
76 debugconfig
76 debugconfig
77 debugdag
77 debugdag
78 debugdata
78 debugdata
79 debugdate
79 debugdate
80 debugdiscovery
80 debugdiscovery
81 debugfileset
81 debugfileset
82 debugfsinfo
82 debugfsinfo
83 debuggetbundle
83 debuggetbundle
84 debugignore
84 debugignore
85 debugindex
85 debugindex
86 debugindexdot
86 debugindexdot
87 debuginstall
87 debuginstall
88 debugknown
88 debugknown
89 debugpushkey
89 debugpushkey
90 debugpvec
90 debugrebuildstate
91 debugrebuildstate
91 debugrename
92 debugrename
92 debugrevlog
93 debugrevlog
93 debugrevspec
94 debugrevspec
94 debugsetparents
95 debugsetparents
95 debugstate
96 debugstate
96 debugsub
97 debugsub
97 debugwalk
98 debugwalk
98 debugwireargs
99 debugwireargs
99
100
100 Do not show the alias of a debug command if there are other candidates
101 Do not show the alias of a debug command if there are other candidates
101 (this should hide rawcommit)
102 (this should hide rawcommit)
102 $ hg debugcomplete r
103 $ hg debugcomplete r
103 recover
104 recover
104 remove
105 remove
105 rename
106 rename
106 resolve
107 resolve
107 revert
108 revert
108 rollback
109 rollback
109 root
110 root
110 Show the alias of a debug command if there are no other candidates
111 Show the alias of a debug command if there are no other candidates
111 $ hg debugcomplete rawc
112 $ hg debugcomplete rawc
112
113
113
114
114 Show the global options
115 Show the global options
115 $ hg debugcomplete --options | sort
116 $ hg debugcomplete --options | sort
116 --config
117 --config
117 --cwd
118 --cwd
118 --debug
119 --debug
119 --debugger
120 --debugger
120 --encoding
121 --encoding
121 --encodingmode
122 --encodingmode
122 --help
123 --help
123 --noninteractive
124 --noninteractive
124 --profile
125 --profile
125 --quiet
126 --quiet
126 --repository
127 --repository
127 --time
128 --time
128 --traceback
129 --traceback
129 --verbose
130 --verbose
130 --version
131 --version
131 -R
132 -R
132 -h
133 -h
133 -q
134 -q
134 -v
135 -v
135 -y
136 -y
136
137
137 Show the options for the "serve" command
138 Show the options for the "serve" command
138 $ hg debugcomplete --options serve | sort
139 $ hg debugcomplete --options serve | sort
139 --accesslog
140 --accesslog
140 --address
141 --address
141 --certificate
142 --certificate
142 --cmdserver
143 --cmdserver
143 --config
144 --config
144 --cwd
145 --cwd
145 --daemon
146 --daemon
146 --daemon-pipefds
147 --daemon-pipefds
147 --debug
148 --debug
148 --debugger
149 --debugger
149 --encoding
150 --encoding
150 --encodingmode
151 --encodingmode
151 --errorlog
152 --errorlog
152 --help
153 --help
153 --ipv6
154 --ipv6
154 --name
155 --name
155 --noninteractive
156 --noninteractive
156 --pid-file
157 --pid-file
157 --port
158 --port
158 --prefix
159 --prefix
159 --profile
160 --profile
160 --quiet
161 --quiet
161 --repository
162 --repository
162 --stdio
163 --stdio
163 --style
164 --style
164 --templates
165 --templates
165 --time
166 --time
166 --traceback
167 --traceback
167 --verbose
168 --verbose
168 --version
169 --version
169 --web-conf
170 --web-conf
170 -6
171 -6
171 -A
172 -A
172 -E
173 -E
173 -R
174 -R
174 -a
175 -a
175 -d
176 -d
176 -h
177 -h
177 -n
178 -n
178 -p
179 -p
179 -q
180 -q
180 -t
181 -t
181 -v
182 -v
182 -y
183 -y
183
184
184 Show an error if we use --options with an ambiguous abbreviation
185 Show an error if we use --options with an ambiguous abbreviation
185 $ hg debugcomplete --options s
186 $ hg debugcomplete --options s
186 hg: command 's' is ambiguous:
187 hg: command 's' is ambiguous:
187 serve showconfig status summary
188 serve showconfig status summary
188 [255]
189 [255]
189
190
190 Show all commands + options
191 Show all commands + options
191 $ hg debugcommands
192 $ hg debugcommands
192 add: include, exclude, subrepos, dry-run
193 add: include, exclude, subrepos, dry-run
193 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
194 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
194 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
195 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
195 commit: addremove, close-branch, include, exclude, message, logfile, date, user, subrepos
196 commit: addremove, close-branch, include, exclude, message, logfile, date, user, subrepos
196 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
197 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
197 export: output, switch-parent, rev, text, git, nodates
198 export: output, switch-parent, rev, text, git, nodates
198 forget: include, exclude
199 forget: include, exclude
199 init: ssh, remotecmd, insecure
200 init: ssh, remotecmd, insecure
200 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, hidden, patch, git, limit, no-merges, stat, style, template, include, exclude
201 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, hidden, patch, git, limit, no-merges, stat, style, template, include, exclude
201 merge: force, rev, preview, tool
202 merge: force, rev, preview, tool
202 phase: public, draft, secret, force, rev
203 phase: public, draft, secret, force, rev
203 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
204 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
204 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
205 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
205 remove: after, force, include, exclude
206 remove: after, force, include, exclude
206 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
207 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
207 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
208 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
208 summary: remote
209 summary: remote
209 update: clean, check, date, rev
210 update: clean, check, date, rev
210 addremove: similarity, include, exclude, dry-run
211 addremove: similarity, include, exclude, dry-run
211 archive: no-decode, prefix, rev, type, subrepos, include, exclude
212 archive: no-decode, prefix, rev, type, subrepos, include, exclude
212 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
213 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
213 bisect: reset, good, bad, skip, extend, command, noupdate
214 bisect: reset, good, bad, skip, extend, command, noupdate
214 bookmarks: force, rev, delete, rename, inactive
215 bookmarks: force, rev, delete, rename, inactive
215 branch: force, clean
216 branch: force, clean
216 branches: active, closed
217 branches: active, closed
217 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
218 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
218 cat: output, rev, decode, include, exclude
219 cat: output, rev, decode, include, exclude
219 copy: after, force, include, exclude, dry-run
220 copy: after, force, include, exclude, dry-run
220 debugancestor:
221 debugancestor:
221 debugbuilddag: mergeable-file, overwritten-file, new-file
222 debugbuilddag: mergeable-file, overwritten-file, new-file
222 debugbundle: all
223 debugbundle: all
223 debugcheckstate:
224 debugcheckstate:
224 debugcommands:
225 debugcommands:
225 debugcomplete: options
226 debugcomplete: options
226 debugdag: tags, branches, dots, spaces
227 debugdag: tags, branches, dots, spaces
227 debugdata: changelog, manifest
228 debugdata: changelog, manifest
228 debugdate: extended
229 debugdate: extended
229 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
230 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
230 debugfileset:
231 debugfileset:
231 debugfsinfo:
232 debugfsinfo:
232 debuggetbundle: head, common, type
233 debuggetbundle: head, common, type
233 debugignore:
234 debugignore:
234 debugindex: changelog, manifest, format
235 debugindex: changelog, manifest, format
235 debugindexdot:
236 debugindexdot:
236 debuginstall:
237 debuginstall:
237 debugknown:
238 debugknown:
238 debugpushkey:
239 debugpushkey:
240 debugpvec:
239 debugrebuildstate: rev
241 debugrebuildstate: rev
240 debugrename: rev
242 debugrename: rev
241 debugrevlog: changelog, manifest, dump
243 debugrevlog: changelog, manifest, dump
242 debugrevspec:
244 debugrevspec:
243 debugsetparents:
245 debugsetparents:
244 debugstate: nodates, datesort
246 debugstate: nodates, datesort
245 debugsub: rev
247 debugsub: rev
246 debugwalk: include, exclude
248 debugwalk: include, exclude
247 debugwireargs: three, four, five, ssh, remotecmd, insecure
249 debugwireargs: three, four, five, ssh, remotecmd, insecure
248 graft: continue, edit, currentdate, currentuser, date, user, tool
250 graft: continue, edit, currentdate, currentuser, date, user, tool
249 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
251 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
250 heads: rev, topo, active, closed, style, template
252 heads: rev, topo, active, closed, style, template
251 help: extension, command
253 help: extension, command
252 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
254 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
253 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
255 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
254 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
256 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
255 locate: rev, print0, fullpath, include, exclude
257 locate: rev, print0, fullpath, include, exclude
256 manifest: rev, all
258 manifest: rev, all
257 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
259 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
258 parents: rev, style, template
260 parents: rev, style, template
259 paths:
261 paths:
260 recover:
262 recover:
261 rename: after, force, include, exclude, dry-run
263 rename: after, force, include, exclude, dry-run
262 resolve: all, list, mark, unmark, no-status, tool, include, exclude
264 resolve: all, list, mark, unmark, no-status, tool, include, exclude
263 revert: all, date, rev, no-backup, include, exclude, dry-run
265 revert: all, date, rev, no-backup, include, exclude, dry-run
264 rollback: dry-run, force
266 rollback: dry-run, force
265 root:
267 root:
266 showconfig: untrusted
268 showconfig: untrusted
267 tag: force, local, rev, remove, edit, message, date, user
269 tag: force, local, rev, remove, edit, message, date, user
268 tags:
270 tags:
269 tip: patch, git, style, template
271 tip: patch, git, style, template
270 unbundle: update
272 unbundle: update
271 verify:
273 verify:
272 version:
274 version:
General Comments 0
You need to be logged in to leave comments. Login now