##// END OF EJS Templates
Introduce templateopts and logopts to reduce duplicate option definitions.
Thomas Arendsen Hein -
r6192:cd65a67a default
parent child Browse files
Show More
@@ -1,41 +1,41 b''
1 # Mercurial extension to provide the 'hg children' command
1 # Mercurial extension to provide the 'hg children' command
2 #
2 #
3 # Copyright 2007 by Intevation GmbH <intevation@intevation.de>
3 # Copyright 2007 by Intevation GmbH <intevation@intevation.de>
4 # Author(s):
4 # Author(s):
5 # Thomas Arendsen Hein <thomas@intevation.de>
5 # Thomas Arendsen Hein <thomas@intevation.de>
6 #
6 #
7 # This software may be used and distributed according to the terms
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 from mercurial import cmdutil
10 from mercurial import cmdutil
11 from mercurial.commands import templateopts
11 from mercurial.i18n import _
12 from mercurial.i18n import _
12
13
13
14
14 def children(ui, repo, file_=None, **opts):
15 def children(ui, repo, file_=None, **opts):
15 """show the children of the given or working dir revision
16 """show the children of the given or working dir revision
16
17
17 Print the children of the working directory's revisions.
18 Print the children of the working directory's revisions.
18 If a revision is given via --rev, the children of that revision
19 If a revision is given via --rev, the children of that revision
19 will be printed. If a file argument is given, revision in
20 will be printed. If a file argument is given, revision in
20 which the file was last changed (after the working directory
21 which the file was last changed (after the working directory
21 revision or the argument to --rev if given) is printed.
22 revision or the argument to --rev if given) is printed.
22 """
23 """
23 rev = opts.get('rev')
24 rev = opts.get('rev')
24 if file_:
25 if file_:
25 ctx = repo.filectx(file_, changeid=rev)
26 ctx = repo.filectx(file_, changeid=rev)
26 else:
27 else:
27 ctx = repo.changectx(rev)
28 ctx = repo.changectx(rev)
28
29
29 displayer = cmdutil.show_changeset(ui, repo, opts)
30 displayer = cmdutil.show_changeset(ui, repo, opts)
30 for node in [cp.node() for cp in ctx.children()]:
31 for node in [cp.node() for cp in ctx.children()]:
31 displayer.show(changenode=node)
32 displayer.show(changenode=node)
32
33
33
34
34 cmdtable = {
35 cmdtable = {
35 "children":
36 "children":
36 (children,
37 (children,
37 [('r', 'rev', '', _('show children of the specified rev')),
38 [('r', 'rev', '', _('show children of the specified rev')),
38 ('', 'style', '', _('display using template map file')),
39 ] + templateopts,
39 ('', 'template', '', _('display with template'))],
40 _('hg children [-r REV] [FILE]')),
40 _('hg children [-r REV] [FILE]')),
41 }
41 }
@@ -1,326 +1,326 b''
1 # ASCII graph log extension for Mercurial
1 # ASCII graph log extension for Mercurial
2 #
2 #
3 # Copyright 2007 Joel Rosdahl <joel@rosdahl.net>
3 # Copyright 2007 Joel Rosdahl <joel@rosdahl.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of
5 # This software may be used and distributed according to the terms of
6 # the GNU General Public License, incorporated herein by reference.
6 # the GNU General Public License, incorporated herein by reference.
7
7
8 import os
8 import os
9 import sys
9 import sys
10 from mercurial.cmdutil import revrange, show_changeset
10 from mercurial.cmdutil import revrange, show_changeset
11 from mercurial.commands import templateopts
11 from mercurial.i18n import _
12 from mercurial.i18n import _
12 from mercurial.node import nullid, nullrev
13 from mercurial.node import nullid, nullrev
13 from mercurial.util import Abort, canonpath
14 from mercurial.util import Abort, canonpath
14
15
15 def revision_grapher(repo, start_rev, stop_rev):
16 def revision_grapher(repo, start_rev, stop_rev):
16 """incremental revision grapher
17 """incremental revision grapher
17
18
18 This generator function walks through the revision history from
19 This generator function walks through the revision history from
19 revision start_rev to revision stop_rev (which must be less than
20 revision start_rev to revision stop_rev (which must be less than
20 or equal to start_rev) and for each revision emits tuples with the
21 or equal to start_rev) and for each revision emits tuples with the
21 following elements:
22 following elements:
22
23
23 - Current revision.
24 - Current revision.
24 - Current node.
25 - Current node.
25 - Column of the current node in the set of ongoing edges.
26 - Column of the current node in the set of ongoing edges.
26 - Edges; a list of (col, next_col) indicating the edges between
27 - Edges; a list of (col, next_col) indicating the edges between
27 the current node and its parents.
28 the current node and its parents.
28 - Number of columns (ongoing edges) in the current revision.
29 - Number of columns (ongoing edges) in the current revision.
29 - The difference between the number of columns (ongoing edges)
30 - The difference between the number of columns (ongoing edges)
30 in the next revision and the number of columns (ongoing edges)
31 in the next revision and the number of columns (ongoing edges)
31 in the current revision. That is: -1 means one column removed;
32 in the current revision. That is: -1 means one column removed;
32 0 means no columns added or removed; 1 means one column added.
33 0 means no columns added or removed; 1 means one column added.
33 """
34 """
34
35
35 assert start_rev >= stop_rev
36 assert start_rev >= stop_rev
36 curr_rev = start_rev
37 curr_rev = start_rev
37 revs = []
38 revs = []
38 while curr_rev >= stop_rev:
39 while curr_rev >= stop_rev:
39 node = repo.changelog.node(curr_rev)
40 node = repo.changelog.node(curr_rev)
40
41
41 # Compute revs and next_revs.
42 # Compute revs and next_revs.
42 if curr_rev not in revs:
43 if curr_rev not in revs:
43 # New head.
44 # New head.
44 revs.append(curr_rev)
45 revs.append(curr_rev)
45 rev_index = revs.index(curr_rev)
46 rev_index = revs.index(curr_rev)
46 next_revs = revs[:]
47 next_revs = revs[:]
47
48
48 # Add parents to next_revs.
49 # Add parents to next_revs.
49 parents = get_rev_parents(repo, curr_rev)
50 parents = get_rev_parents(repo, curr_rev)
50 parents_to_add = []
51 parents_to_add = []
51 for parent in parents:
52 for parent in parents:
52 if parent not in next_revs:
53 if parent not in next_revs:
53 parents_to_add.append(parent)
54 parents_to_add.append(parent)
54 parents_to_add.sort()
55 parents_to_add.sort()
55 next_revs[rev_index:rev_index + 1] = parents_to_add
56 next_revs[rev_index:rev_index + 1] = parents_to_add
56
57
57 edges = []
58 edges = []
58 for parent in parents:
59 for parent in parents:
59 edges.append((rev_index, next_revs.index(parent)))
60 edges.append((rev_index, next_revs.index(parent)))
60
61
61 n_columns_diff = len(next_revs) - len(revs)
62 n_columns_diff = len(next_revs) - len(revs)
62 yield (curr_rev, node, rev_index, edges, len(revs), n_columns_diff)
63 yield (curr_rev, node, rev_index, edges, len(revs), n_columns_diff)
63
64
64 revs = next_revs
65 revs = next_revs
65 curr_rev -= 1
66 curr_rev -= 1
66
67
67 def filelog_grapher(repo, path, start_rev, stop_rev):
68 def filelog_grapher(repo, path, start_rev, stop_rev):
68 """incremental file log grapher
69 """incremental file log grapher
69
70
70 This generator function walks through the revision history of a
71 This generator function walks through the revision history of a
71 single file from revision start_rev to revision stop_rev (which must
72 single file from revision start_rev to revision stop_rev (which must
72 be less than or equal to start_rev) and for each revision emits
73 be less than or equal to start_rev) and for each revision emits
73 tuples with the following elements:
74 tuples with the following elements:
74
75
75 - Current revision.
76 - Current revision.
76 - Current node.
77 - Current node.
77 - Column of the current node in the set of ongoing edges.
78 - Column of the current node in the set of ongoing edges.
78 - Edges; a list of (col, next_col) indicating the edges between
79 - Edges; a list of (col, next_col) indicating the edges between
79 the current node and its parents.
80 the current node and its parents.
80 - Number of columns (ongoing edges) in the current revision.
81 - Number of columns (ongoing edges) in the current revision.
81 - The difference between the number of columns (ongoing edges)
82 - The difference between the number of columns (ongoing edges)
82 in the next revision and the number of columns (ongoing edges)
83 in the next revision and the number of columns (ongoing edges)
83 in the current revision. That is: -1 means one column removed;
84 in the current revision. That is: -1 means one column removed;
84 0 means no columns added or removed; 1 means one column added.
85 0 means no columns added or removed; 1 means one column added.
85 """
86 """
86
87
87 assert start_rev >= stop_rev
88 assert start_rev >= stop_rev
88 curr_rev = start_rev
89 curr_rev = start_rev
89 revs = []
90 revs = []
90 filerev = repo.file(path).count() - 1
91 filerev = repo.file(path).count() - 1
91 while filerev >= 0:
92 while filerev >= 0:
92 fctx = repo.filectx(path, fileid=filerev)
93 fctx = repo.filectx(path, fileid=filerev)
93
94
94 # Compute revs and next_revs.
95 # Compute revs and next_revs.
95 if filerev not in revs:
96 if filerev not in revs:
96 revs.append(filerev)
97 revs.append(filerev)
97 rev_index = revs.index(filerev)
98 rev_index = revs.index(filerev)
98 next_revs = revs[:]
99 next_revs = revs[:]
99
100
100 # Add parents to next_revs.
101 # Add parents to next_revs.
101 parents = [f.filerev() for f in fctx.parents() if f.path() == path]
102 parents = [f.filerev() for f in fctx.parents() if f.path() == path]
102 parents_to_add = []
103 parents_to_add = []
103 for parent in parents:
104 for parent in parents:
104 if parent not in next_revs:
105 if parent not in next_revs:
105 parents_to_add.append(parent)
106 parents_to_add.append(parent)
106 parents_to_add.sort()
107 parents_to_add.sort()
107 next_revs[rev_index:rev_index + 1] = parents_to_add
108 next_revs[rev_index:rev_index + 1] = parents_to_add
108
109
109 edges = []
110 edges = []
110 for parent in parents:
111 for parent in parents:
111 edges.append((rev_index, next_revs.index(parent)))
112 edges.append((rev_index, next_revs.index(parent)))
112
113
113 changerev = fctx.linkrev()
114 changerev = fctx.linkrev()
114 if changerev <= start_rev:
115 if changerev <= start_rev:
115 node = repo.changelog.node(changerev)
116 node = repo.changelog.node(changerev)
116 n_columns_diff = len(next_revs) - len(revs)
117 n_columns_diff = len(next_revs) - len(revs)
117 yield (changerev, node, rev_index, edges, len(revs), n_columns_diff)
118 yield (changerev, node, rev_index, edges, len(revs), n_columns_diff)
118 if changerev <= stop_rev:
119 if changerev <= stop_rev:
119 break
120 break
120 revs = next_revs
121 revs = next_revs
121 filerev -= 1
122 filerev -= 1
122
123
123 def get_rev_parents(repo, rev):
124 def get_rev_parents(repo, rev):
124 return [x for x in repo.changelog.parentrevs(rev) if x != nullrev]
125 return [x for x in repo.changelog.parentrevs(rev) if x != nullrev]
125
126
126 def fix_long_right_edges(edges):
127 def fix_long_right_edges(edges):
127 for (i, (start, end)) in enumerate(edges):
128 for (i, (start, end)) in enumerate(edges):
128 if end > start:
129 if end > start:
129 edges[i] = (start, end + 1)
130 edges[i] = (start, end + 1)
130
131
131 def draw_edges(edges, nodeline, interline):
132 def draw_edges(edges, nodeline, interline):
132 for (start, end) in edges:
133 for (start, end) in edges:
133 if start == end + 1:
134 if start == end + 1:
134 interline[2 * end + 1] = "/"
135 interline[2 * end + 1] = "/"
135 elif start == end - 1:
136 elif start == end - 1:
136 interline[2 * start + 1] = "\\"
137 interline[2 * start + 1] = "\\"
137 elif start == end:
138 elif start == end:
138 interline[2 * start] = "|"
139 interline[2 * start] = "|"
139 else:
140 else:
140 nodeline[2 * end] = "+"
141 nodeline[2 * end] = "+"
141 if start > end:
142 if start > end:
142 (start, end) = (end,start)
143 (start, end) = (end,start)
143 for i in range(2 * start + 1, 2 * end):
144 for i in range(2 * start + 1, 2 * end):
144 if nodeline[i] != "+":
145 if nodeline[i] != "+":
145 nodeline[i] = "-"
146 nodeline[i] = "-"
146
147
147 def format_line(line, level, logstr):
148 def format_line(line, level, logstr):
148 text = "%-*s %s" % (2 * level, "".join(line), logstr)
149 text = "%-*s %s" % (2 * level, "".join(line), logstr)
149 return "%s\n" % text.rstrip()
150 return "%s\n" % text.rstrip()
150
151
151 def get_nodeline_edges_tail(
152 def get_nodeline_edges_tail(
152 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
153 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
153 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
154 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
154 # Still going in the same non-vertical direction.
155 # Still going in the same non-vertical direction.
155 if n_columns_diff == -1:
156 if n_columns_diff == -1:
156 start = max(node_index + 1, p_node_index)
157 start = max(node_index + 1, p_node_index)
157 tail = ["|", " "] * (start - node_index - 1)
158 tail = ["|", " "] * (start - node_index - 1)
158 tail.extend(["/", " "] * (n_columns - start))
159 tail.extend(["/", " "] * (n_columns - start))
159 return tail
160 return tail
160 else:
161 else:
161 return ["\\", " "] * (n_columns - node_index - 1)
162 return ["\\", " "] * (n_columns - node_index - 1)
162 else:
163 else:
163 return ["|", " "] * (n_columns - node_index - 1)
164 return ["|", " "] * (n_columns - node_index - 1)
164
165
165 def get_padding_line(ni, n_columns, edges):
166 def get_padding_line(ni, n_columns, edges):
166 line = []
167 line = []
167 line.extend(["|", " "] * ni)
168 line.extend(["|", " "] * ni)
168 if (ni, ni - 1) in edges or (ni, ni) in edges:
169 if (ni, ni - 1) in edges or (ni, ni) in edges:
169 # (ni, ni - 1) (ni, ni)
170 # (ni, ni - 1) (ni, ni)
170 # | | | | | | | |
171 # | | | | | | | |
171 # +---o | | o---+
172 # +---o | | o---+
172 # | | c | | c | |
173 # | | c | | c | |
173 # | |/ / | |/ /
174 # | |/ / | |/ /
174 # | | | | | |
175 # | | | | | |
175 c = "|"
176 c = "|"
176 else:
177 else:
177 c = " "
178 c = " "
178 line.extend([c, " "])
179 line.extend([c, " "])
179 line.extend(["|", " "] * (n_columns - ni - 1))
180 line.extend(["|", " "] * (n_columns - ni - 1))
180 return line
181 return line
181
182
182 def get_limit(limit_opt):
183 def get_limit(limit_opt):
183 if limit_opt:
184 if limit_opt:
184 try:
185 try:
185 limit = int(limit_opt)
186 limit = int(limit_opt)
186 except ValueError:
187 except ValueError:
187 raise Abort(_("limit must be a positive integer"))
188 raise Abort(_("limit must be a positive integer"))
188 if limit <= 0:
189 if limit <= 0:
189 raise Abort(_("limit must be positive"))
190 raise Abort(_("limit must be positive"))
190 else:
191 else:
191 limit = sys.maxint
192 limit = sys.maxint
192 return limit
193 return limit
193
194
194 def get_revs(repo, rev_opt):
195 def get_revs(repo, rev_opt):
195 if rev_opt:
196 if rev_opt:
196 revs = revrange(repo, rev_opt)
197 revs = revrange(repo, rev_opt)
197 return (max(revs), min(revs))
198 return (max(revs), min(revs))
198 else:
199 else:
199 return (repo.changelog.count() - 1, 0)
200 return (repo.changelog.count() - 1, 0)
200
201
201 def graphlog(ui, repo, path=None, **opts):
202 def graphlog(ui, repo, path=None, **opts):
202 """show revision history alongside an ASCII revision graph
203 """show revision history alongside an ASCII revision graph
203
204
204 Print a revision history alongside a revision graph drawn with
205 Print a revision history alongside a revision graph drawn with
205 ASCII characters.
206 ASCII characters.
206
207
207 Nodes printed as an @ character are parents of the working
208 Nodes printed as an @ character are parents of the working
208 directory.
209 directory.
209 """
210 """
210
211
211 limit = get_limit(opts["limit"])
212 limit = get_limit(opts["limit"])
212 (start_rev, stop_rev) = get_revs(repo, opts["rev"])
213 (start_rev, stop_rev) = get_revs(repo, opts["rev"])
213 stop_rev = max(stop_rev, start_rev - limit + 1)
214 stop_rev = max(stop_rev, start_rev - limit + 1)
214 if start_rev == nullrev:
215 if start_rev == nullrev:
215 return
216 return
216 cs_printer = show_changeset(ui, repo, opts)
217 cs_printer = show_changeset(ui, repo, opts)
217 if path:
218 if path:
218 cpath = canonpath(repo.root, os.getcwd(), path)
219 cpath = canonpath(repo.root, os.getcwd(), path)
219 grapher = filelog_grapher(repo, cpath, start_rev, stop_rev)
220 grapher = filelog_grapher(repo, cpath, start_rev, stop_rev)
220 else:
221 else:
221 grapher = revision_grapher(repo, start_rev, stop_rev)
222 grapher = revision_grapher(repo, start_rev, stop_rev)
222 repo_parents = repo.dirstate.parents()
223 repo_parents = repo.dirstate.parents()
223 prev_n_columns_diff = 0
224 prev_n_columns_diff = 0
224 prev_node_index = 0
225 prev_node_index = 0
225
226
226 for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher:
227 for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher:
227 # log_strings is the list of all log strings to draw alongside
228 # log_strings is the list of all log strings to draw alongside
228 # the graph.
229 # the graph.
229 ui.pushbuffer()
230 ui.pushbuffer()
230 cs_printer.show(rev, node)
231 cs_printer.show(rev, node)
231 log_strings = ui.popbuffer().split("\n")[:-1]
232 log_strings = ui.popbuffer().split("\n")[:-1]
232
233
233 if n_columns_diff == -1:
234 if n_columns_diff == -1:
234 # Transform
235 # Transform
235 #
236 #
236 # | | | | | |
237 # | | | | | |
237 # o | | into o---+
238 # o | | into o---+
238 # |X / |/ /
239 # |X / |/ /
239 # | | | |
240 # | | | |
240 fix_long_right_edges(edges)
241 fix_long_right_edges(edges)
241
242
242 # add_padding_line says whether to rewrite
243 # add_padding_line says whether to rewrite
243 #
244 #
244 # | | | | | | | |
245 # | | | | | | | |
245 # | o---+ into | o---+
246 # | o---+ into | o---+
246 # | / / | | | # <--- padding line
247 # | / / | | | # <--- padding line
247 # o | | | / /
248 # o | | | / /
248 # o | |
249 # o | |
249 add_padding_line = (len(log_strings) > 2 and
250 add_padding_line = (len(log_strings) > 2 and
250 n_columns_diff == -1 and
251 n_columns_diff == -1 and
251 [x for (x, y) in edges if x + 1 < y])
252 [x for (x, y) in edges if x + 1 < y])
252
253
253 # fix_nodeline_tail says whether to rewrite
254 # fix_nodeline_tail says whether to rewrite
254 #
255 #
255 # | | o | | | | o | |
256 # | | o | | | | o | |
256 # | | |/ / | | |/ /
257 # | | |/ / | | |/ /
257 # | o | | into | o / / # <--- fixed nodeline tail
258 # | o | | into | o / / # <--- fixed nodeline tail
258 # | |/ / | |/ /
259 # | |/ / | |/ /
259 # o | | o | |
260 # o | | o | |
260 fix_nodeline_tail = len(log_strings) <= 2 and not add_padding_line
261 fix_nodeline_tail = len(log_strings) <= 2 and not add_padding_line
261
262
262 # nodeline is the line containing the node character (@ or o).
263 # nodeline is the line containing the node character (@ or o).
263 nodeline = ["|", " "] * node_index
264 nodeline = ["|", " "] * node_index
264 if node in repo_parents:
265 if node in repo_parents:
265 node_ch = "@"
266 node_ch = "@"
266 else:
267 else:
267 node_ch = "o"
268 node_ch = "o"
268 nodeline.extend([node_ch, " "])
269 nodeline.extend([node_ch, " "])
269
270
270 nodeline.extend(
271 nodeline.extend(
271 get_nodeline_edges_tail(
272 get_nodeline_edges_tail(
272 node_index, prev_node_index, n_columns, n_columns_diff,
273 node_index, prev_node_index, n_columns, n_columns_diff,
273 prev_n_columns_diff, fix_nodeline_tail))
274 prev_n_columns_diff, fix_nodeline_tail))
274
275
275 # shift_interline is the line containing the non-vertical
276 # shift_interline is the line containing the non-vertical
276 # edges between this entry and the next.
277 # edges between this entry and the next.
277 shift_interline = ["|", " "] * node_index
278 shift_interline = ["|", " "] * node_index
278 if n_columns_diff == -1:
279 if n_columns_diff == -1:
279 n_spaces = 1
280 n_spaces = 1
280 edge_ch = "/"
281 edge_ch = "/"
281 elif n_columns_diff == 0:
282 elif n_columns_diff == 0:
282 n_spaces = 2
283 n_spaces = 2
283 edge_ch = "|"
284 edge_ch = "|"
284 else:
285 else:
285 n_spaces = 3
286 n_spaces = 3
286 edge_ch = "\\"
287 edge_ch = "\\"
287 shift_interline.extend(n_spaces * [" "])
288 shift_interline.extend(n_spaces * [" "])
288 shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1))
289 shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1))
289
290
290 # Draw edges from the current node to its parents.
291 # Draw edges from the current node to its parents.
291 draw_edges(edges, nodeline, shift_interline)
292 draw_edges(edges, nodeline, shift_interline)
292
293
293 # lines is the list of all graph lines to print.
294 # lines is the list of all graph lines to print.
294 lines = [nodeline]
295 lines = [nodeline]
295 if add_padding_line:
296 if add_padding_line:
296 lines.append(get_padding_line(node_index, n_columns, edges))
297 lines.append(get_padding_line(node_index, n_columns, edges))
297 lines.append(shift_interline)
298 lines.append(shift_interline)
298
299
299 # Make sure that there are as many graph lines as there are
300 # Make sure that there are as many graph lines as there are
300 # log strings.
301 # log strings.
301 while len(log_strings) < len(lines):
302 while len(log_strings) < len(lines):
302 log_strings.append("")
303 log_strings.append("")
303 if len(lines) < len(log_strings):
304 if len(lines) < len(log_strings):
304 extra_interline = ["|", " "] * (n_columns + n_columns_diff)
305 extra_interline = ["|", " "] * (n_columns + n_columns_diff)
305 while len(lines) < len(log_strings):
306 while len(lines) < len(log_strings):
306 lines.append(extra_interline)
307 lines.append(extra_interline)
307
308
308 # Print lines.
309 # Print lines.
309 indentation_level = max(n_columns, n_columns + n_columns_diff)
310 indentation_level = max(n_columns, n_columns + n_columns_diff)
310 for (line, logstr) in zip(lines, log_strings):
311 for (line, logstr) in zip(lines, log_strings):
311 ui.write(format_line(line, indentation_level, logstr))
312 ui.write(format_line(line, indentation_level, logstr))
312
313
313 # ...and start over.
314 # ...and start over.
314 prev_node_index = node_index
315 prev_node_index = node_index
315 prev_n_columns_diff = n_columns_diff
316 prev_n_columns_diff = n_columns_diff
316
317
317 cmdtable = {
318 cmdtable = {
318 "glog":
319 "glog":
319 (graphlog,
320 (graphlog,
320 [('l', 'limit', '', _('limit number of changes displayed')),
321 [('l', 'limit', '', _('limit number of changes displayed')),
321 ('p', 'patch', False, _('show patch')),
322 ('p', 'patch', False, _('show patch')),
322 ('r', 'rev', [], _('show the specified revision or range')),
323 ('r', 'rev', [], _('show the specified revision or range')),
323 ('', 'style', '', _('display using template map file')),
324 ] + templateopts,
324 ('', 'template', '', _('display with template'))],
325 _('hg glog [OPTION]... [FILE]')),
325 _('hg glog [OPTION]... [FILE]')),
326 }
326 }
@@ -1,3174 +1,3167 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
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import *
8 from node import *
9 from i18n import _
9 from i18n import _
10 import os, re, sys, urllib
10 import os, re, sys, urllib
11 import hg, util, revlog, bundlerepo, extensions
11 import hg, util, revlog, bundlerepo, extensions
12 import difflib, patch, time, help, mdiff, tempfile
12 import difflib, patch, time, help, mdiff, tempfile
13 import errno, version, socket
13 import errno, version, socket
14 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
14 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
15
15
16 # Commands start here, listed alphabetically
16 # Commands start here, listed alphabetically
17
17
18 def add(ui, repo, *pats, **opts):
18 def add(ui, repo, *pats, **opts):
19 """add the specified files on the next commit
19 """add the specified files on the next commit
20
20
21 Schedule files to be version controlled and added to the repository.
21 Schedule files to be version controlled and added to the repository.
22
22
23 The files will be added to the repository at the next commit. To
23 The files will be added to the repository at the next commit. To
24 undo an add before that, see hg revert.
24 undo an add before that, see hg revert.
25
25
26 If no names are given, add all files in the repository.
26 If no names are given, add all files in the repository.
27 """
27 """
28
28
29 rejected = None
29 rejected = None
30 exacts = {}
30 exacts = {}
31 names = []
31 names = []
32 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
32 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
33 badmatch=util.always):
33 badmatch=util.always):
34 if exact:
34 if exact:
35 if ui.verbose:
35 if ui.verbose:
36 ui.status(_('adding %s\n') % rel)
36 ui.status(_('adding %s\n') % rel)
37 names.append(abs)
37 names.append(abs)
38 exacts[abs] = 1
38 exacts[abs] = 1
39 elif abs not in repo.dirstate:
39 elif abs not in repo.dirstate:
40 ui.status(_('adding %s\n') % rel)
40 ui.status(_('adding %s\n') % rel)
41 names.append(abs)
41 names.append(abs)
42 if not opts.get('dry_run'):
42 if not opts.get('dry_run'):
43 rejected = repo.add(names)
43 rejected = repo.add(names)
44 rejected = [p for p in rejected if p in exacts]
44 rejected = [p for p in rejected if p in exacts]
45 return rejected and 1 or 0
45 return rejected and 1 or 0
46
46
47 def addremove(ui, repo, *pats, **opts):
47 def addremove(ui, repo, *pats, **opts):
48 """add all new files, delete all missing files
48 """add all new files, delete all missing files
49
49
50 Add all new files and remove all missing files from the repository.
50 Add all new files and remove all missing files from the repository.
51
51
52 New files are ignored if they match any of the patterns in .hgignore. As
52 New files are ignored if they match any of the patterns in .hgignore. As
53 with add, these changes take effect at the next commit.
53 with add, these changes take effect at the next commit.
54
54
55 Use the -s option to detect renamed files. With a parameter > 0,
55 Use the -s option to detect renamed files. With a parameter > 0,
56 this compares every removed file with every added file and records
56 this compares every removed file with every added file and records
57 those similar enough as renames. This option takes a percentage
57 those similar enough as renames. This option takes a percentage
58 between 0 (disabled) and 100 (files must be identical) as its
58 between 0 (disabled) and 100 (files must be identical) as its
59 parameter. Detecting renamed files this way can be expensive.
59 parameter. Detecting renamed files this way can be expensive.
60 """
60 """
61 try:
61 try:
62 sim = float(opts.get('similarity') or 0)
62 sim = float(opts.get('similarity') or 0)
63 except ValueError:
63 except ValueError:
64 raise util.Abort(_('similarity must be a number'))
64 raise util.Abort(_('similarity must be a number'))
65 if sim < 0 or sim > 100:
65 if sim < 0 or sim > 100:
66 raise util.Abort(_('similarity must be between 0 and 100'))
66 raise util.Abort(_('similarity must be between 0 and 100'))
67 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
67 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
68
68
69 def annotate(ui, repo, *pats, **opts):
69 def annotate(ui, repo, *pats, **opts):
70 """show changeset information per file line
70 """show changeset information per file line
71
71
72 List changes in files, showing the revision id responsible for each line
72 List changes in files, showing the revision id responsible for each line
73
73
74 This command is useful to discover who did a change or when a change took
74 This command is useful to discover who did a change or when a change took
75 place.
75 place.
76
76
77 Without the -a option, annotate will avoid processing files it
77 Without the -a option, annotate will avoid processing files it
78 detects as binary. With -a, annotate will generate an annotation
78 detects as binary. With -a, annotate will generate an annotation
79 anyway, probably with undesirable results.
79 anyway, probably with undesirable results.
80 """
80 """
81 datefunc = ui.quiet and util.shortdate or util.datestr
81 datefunc = ui.quiet and util.shortdate or util.datestr
82 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
82 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
83
83
84 if not pats:
84 if not pats:
85 raise util.Abort(_('at least one file name or pattern required'))
85 raise util.Abort(_('at least one file name or pattern required'))
86
86
87 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
87 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
88 ('number', lambda x: str(x[0].rev())),
88 ('number', lambda x: str(x[0].rev())),
89 ('changeset', lambda x: short(x[0].node())),
89 ('changeset', lambda x: short(x[0].node())),
90 ('date', getdate),
90 ('date', getdate),
91 ('follow', lambda x: x[0].path()),
91 ('follow', lambda x: x[0].path()),
92 ]
92 ]
93
93
94 if (not opts['user'] and not opts['changeset'] and not opts['date']
94 if (not opts['user'] and not opts['changeset'] and not opts['date']
95 and not opts['follow']):
95 and not opts['follow']):
96 opts['number'] = 1
96 opts['number'] = 1
97
97
98 linenumber = opts.get('line_number') is not None
98 linenumber = opts.get('line_number') is not None
99 if (linenumber and (not opts['changeset']) and (not opts['number'])):
99 if (linenumber and (not opts['changeset']) and (not opts['number'])):
100 raise util.Abort(_('at least one of -n/-c is required for -l'))
100 raise util.Abort(_('at least one of -n/-c is required for -l'))
101
101
102 funcmap = [func for op, func in opmap if opts.get(op)]
102 funcmap = [func for op, func in opmap if opts.get(op)]
103 if linenumber:
103 if linenumber:
104 lastfunc = funcmap[-1]
104 lastfunc = funcmap[-1]
105 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
105 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
106
106
107 ctx = repo.changectx(opts['rev'])
107 ctx = repo.changectx(opts['rev'])
108
108
109 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
109 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
110 node=ctx.node()):
110 node=ctx.node()):
111 fctx = ctx.filectx(abs)
111 fctx = ctx.filectx(abs)
112 if not opts['text'] and util.binary(fctx.data()):
112 if not opts['text'] and util.binary(fctx.data()):
113 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
113 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
114 continue
114 continue
115
115
116 lines = fctx.annotate(follow=opts.get('follow'),
116 lines = fctx.annotate(follow=opts.get('follow'),
117 linenumber=linenumber)
117 linenumber=linenumber)
118 pieces = []
118 pieces = []
119
119
120 for f in funcmap:
120 for f in funcmap:
121 l = [f(n) for n, dummy in lines]
121 l = [f(n) for n, dummy in lines]
122 if l:
122 if l:
123 m = max(map(len, l))
123 m = max(map(len, l))
124 pieces.append(["%*s" % (m, x) for x in l])
124 pieces.append(["%*s" % (m, x) for x in l])
125
125
126 if pieces:
126 if pieces:
127 for p, l in zip(zip(*pieces), lines):
127 for p, l in zip(zip(*pieces), lines):
128 ui.write("%s: %s" % (" ".join(p), l[1]))
128 ui.write("%s: %s" % (" ".join(p), l[1]))
129
129
130 def archive(ui, repo, dest, **opts):
130 def archive(ui, repo, dest, **opts):
131 '''create unversioned archive of a repository revision
131 '''create unversioned archive of a repository revision
132
132
133 By default, the revision used is the parent of the working
133 By default, the revision used is the parent of the working
134 directory; use "-r" to specify a different revision.
134 directory; use "-r" to specify a different revision.
135
135
136 To specify the type of archive to create, use "-t". Valid
136 To specify the type of archive to create, use "-t". Valid
137 types are:
137 types are:
138
138
139 "files" (default): a directory full of files
139 "files" (default): a directory full of files
140 "tar": tar archive, uncompressed
140 "tar": tar archive, uncompressed
141 "tbz2": tar archive, compressed using bzip2
141 "tbz2": tar archive, compressed using bzip2
142 "tgz": tar archive, compressed using gzip
142 "tgz": tar archive, compressed using gzip
143 "uzip": zip archive, uncompressed
143 "uzip": zip archive, uncompressed
144 "zip": zip archive, compressed using deflate
144 "zip": zip archive, compressed using deflate
145
145
146 The exact name of the destination archive or directory is given
146 The exact name of the destination archive or directory is given
147 using a format string; see "hg help export" for details.
147 using a format string; see "hg help export" for details.
148
148
149 Each member added to an archive file has a directory prefix
149 Each member added to an archive file has a directory prefix
150 prepended. Use "-p" to specify a format string for the prefix.
150 prepended. Use "-p" to specify a format string for the prefix.
151 The default is the basename of the archive, with suffixes removed.
151 The default is the basename of the archive, with suffixes removed.
152 '''
152 '''
153
153
154 ctx = repo.changectx(opts['rev'])
154 ctx = repo.changectx(opts['rev'])
155 if not ctx:
155 if not ctx:
156 raise util.Abort(_('repository has no revisions'))
156 raise util.Abort(_('repository has no revisions'))
157 node = ctx.node()
157 node = ctx.node()
158 dest = cmdutil.make_filename(repo, dest, node)
158 dest = cmdutil.make_filename(repo, dest, node)
159 if os.path.realpath(dest) == repo.root:
159 if os.path.realpath(dest) == repo.root:
160 raise util.Abort(_('repository root cannot be destination'))
160 raise util.Abort(_('repository root cannot be destination'))
161 dummy, matchfn, dummy = cmdutil.matchpats(repo, [], opts)
161 dummy, matchfn, dummy = cmdutil.matchpats(repo, [], opts)
162 kind = opts.get('type') or 'files'
162 kind = opts.get('type') or 'files'
163 prefix = opts['prefix']
163 prefix = opts['prefix']
164 if dest == '-':
164 if dest == '-':
165 if kind == 'files':
165 if kind == 'files':
166 raise util.Abort(_('cannot archive plain files to stdout'))
166 raise util.Abort(_('cannot archive plain files to stdout'))
167 dest = sys.stdout
167 dest = sys.stdout
168 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
168 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
169 prefix = cmdutil.make_filename(repo, prefix, node)
169 prefix = cmdutil.make_filename(repo, prefix, node)
170 archival.archive(repo, dest, node, kind, not opts['no_decode'],
170 archival.archive(repo, dest, node, kind, not opts['no_decode'],
171 matchfn, prefix)
171 matchfn, prefix)
172
172
173 def backout(ui, repo, node=None, rev=None, **opts):
173 def backout(ui, repo, node=None, rev=None, **opts):
174 '''reverse effect of earlier changeset
174 '''reverse effect of earlier changeset
175
175
176 Commit the backed out changes as a new changeset. The new
176 Commit the backed out changes as a new changeset. The new
177 changeset is a child of the backed out changeset.
177 changeset is a child of the backed out changeset.
178
178
179 If you back out a changeset other than the tip, a new head is
179 If you back out a changeset other than the tip, a new head is
180 created. This head will be the new tip and you should merge this
180 created. This head will be the new tip and you should merge this
181 backout changeset with another head (current one by default).
181 backout changeset with another head (current one by default).
182
182
183 The --merge option remembers the parent of the working directory
183 The --merge option remembers the parent of the working directory
184 before starting the backout, then merges the new head with that
184 before starting the backout, then merges the new head with that
185 changeset afterwards. This saves you from doing the merge by
185 changeset afterwards. This saves you from doing the merge by
186 hand. The result of this merge is not committed, as for a normal
186 hand. The result of this merge is not committed, as for a normal
187 merge.
187 merge.
188
188
189 See 'hg help dates' for a list of formats valid for -d/--date.
189 See 'hg help dates' for a list of formats valid for -d/--date.
190 '''
190 '''
191 if rev and node:
191 if rev and node:
192 raise util.Abort(_("please specify just one revision"))
192 raise util.Abort(_("please specify just one revision"))
193
193
194 if not rev:
194 if not rev:
195 rev = node
195 rev = node
196
196
197 if not rev:
197 if not rev:
198 raise util.Abort(_("please specify a revision to backout"))
198 raise util.Abort(_("please specify a revision to backout"))
199
199
200 date = opts.get('date')
200 date = opts.get('date')
201 if date:
201 if date:
202 opts['date'] = util.parsedate(date)
202 opts['date'] = util.parsedate(date)
203
203
204 cmdutil.bail_if_changed(repo)
204 cmdutil.bail_if_changed(repo)
205 node = repo.lookup(rev)
205 node = repo.lookup(rev)
206
206
207 op1, op2 = repo.dirstate.parents()
207 op1, op2 = repo.dirstate.parents()
208 a = repo.changelog.ancestor(op1, node)
208 a = repo.changelog.ancestor(op1, node)
209 if a != node:
209 if a != node:
210 raise util.Abort(_('cannot back out change on a different branch'))
210 raise util.Abort(_('cannot back out change on a different branch'))
211
211
212 p1, p2 = repo.changelog.parents(node)
212 p1, p2 = repo.changelog.parents(node)
213 if p1 == nullid:
213 if p1 == nullid:
214 raise util.Abort(_('cannot back out a change with no parents'))
214 raise util.Abort(_('cannot back out a change with no parents'))
215 if p2 != nullid:
215 if p2 != nullid:
216 if not opts['parent']:
216 if not opts['parent']:
217 raise util.Abort(_('cannot back out a merge changeset without '
217 raise util.Abort(_('cannot back out a merge changeset without '
218 '--parent'))
218 '--parent'))
219 p = repo.lookup(opts['parent'])
219 p = repo.lookup(opts['parent'])
220 if p not in (p1, p2):
220 if p not in (p1, p2):
221 raise util.Abort(_('%s is not a parent of %s') %
221 raise util.Abort(_('%s is not a parent of %s') %
222 (short(p), short(node)))
222 (short(p), short(node)))
223 parent = p
223 parent = p
224 else:
224 else:
225 if opts['parent']:
225 if opts['parent']:
226 raise util.Abort(_('cannot use --parent on non-merge changeset'))
226 raise util.Abort(_('cannot use --parent on non-merge changeset'))
227 parent = p1
227 parent = p1
228
228
229 hg.clean(repo, node, show_stats=False)
229 hg.clean(repo, node, show_stats=False)
230 revert_opts = opts.copy()
230 revert_opts = opts.copy()
231 revert_opts['date'] = None
231 revert_opts['date'] = None
232 revert_opts['all'] = True
232 revert_opts['all'] = True
233 revert_opts['rev'] = hex(parent)
233 revert_opts['rev'] = hex(parent)
234 revert_opts['no_backup'] = None
234 revert_opts['no_backup'] = None
235 revert(ui, repo, **revert_opts)
235 revert(ui, repo, **revert_opts)
236 commit_opts = opts.copy()
236 commit_opts = opts.copy()
237 commit_opts['addremove'] = False
237 commit_opts['addremove'] = False
238 if not commit_opts['message'] and not commit_opts['logfile']:
238 if not commit_opts['message'] and not commit_opts['logfile']:
239 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
239 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
240 commit_opts['force_editor'] = True
240 commit_opts['force_editor'] = True
241 commit(ui, repo, **commit_opts)
241 commit(ui, repo, **commit_opts)
242 def nice(node):
242 def nice(node):
243 return '%d:%s' % (repo.changelog.rev(node), short(node))
243 return '%d:%s' % (repo.changelog.rev(node), short(node))
244 ui.status(_('changeset %s backs out changeset %s\n') %
244 ui.status(_('changeset %s backs out changeset %s\n') %
245 (nice(repo.changelog.tip()), nice(node)))
245 (nice(repo.changelog.tip()), nice(node)))
246 if op1 != node:
246 if op1 != node:
247 hg.clean(repo, op1, show_stats=False)
247 hg.clean(repo, op1, show_stats=False)
248 if opts['merge']:
248 if opts['merge']:
249 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
249 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
250 hg.merge(repo, hex(repo.changelog.tip()))
250 hg.merge(repo, hex(repo.changelog.tip()))
251 else:
251 else:
252 ui.status(_('the backout changeset is a new head - '
252 ui.status(_('the backout changeset is a new head - '
253 'do not forget to merge\n'))
253 'do not forget to merge\n'))
254 ui.status(_('(use "backout --merge" '
254 ui.status(_('(use "backout --merge" '
255 'if you want to auto-merge)\n'))
255 'if you want to auto-merge)\n'))
256
256
257 def bisect(ui, repo, rev=None, extra=None,
257 def bisect(ui, repo, rev=None, extra=None,
258 reset=None, good=None, bad=None, skip=None, noupdate=None):
258 reset=None, good=None, bad=None, skip=None, noupdate=None):
259 """subdivision search of changesets
259 """subdivision search of changesets
260
260
261 This command helps to find changesets which introduce problems.
261 This command helps to find changesets which introduce problems.
262 To use, mark the earliest changeset you know exhibits the problem
262 To use, mark the earliest changeset you know exhibits the problem
263 as bad, then mark the latest changeset which is free from the
263 as bad, then mark the latest changeset which is free from the
264 problem as good. Bisect will update your working directory to a
264 problem as good. Bisect will update your working directory to a
265 revision for testing. Once you have performed tests, mark the
265 revision for testing. Once you have performed tests, mark the
266 working directory as bad or good and bisect will either update to
266 working directory as bad or good and bisect will either update to
267 another candidate changeset or announce that it has found the bad
267 another candidate changeset or announce that it has found the bad
268 revision.
268 revision.
269 """
269 """
270 # backward compatibility
270 # backward compatibility
271 if rev in "good bad reset init".split():
271 if rev in "good bad reset init".split():
272 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
272 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
273 cmd, rev, extra = rev, extra, None
273 cmd, rev, extra = rev, extra, None
274 if cmd == "good":
274 if cmd == "good":
275 good = True
275 good = True
276 elif cmd == "bad":
276 elif cmd == "bad":
277 bad = True
277 bad = True
278 else:
278 else:
279 reset = True
279 reset = True
280 elif extra or good + bad + skip + reset > 1:
280 elif extra or good + bad + skip + reset > 1:
281 raise util.Abort("Incompatible arguments")
281 raise util.Abort("Incompatible arguments")
282
282
283 if reset:
283 if reset:
284 p = repo.join("bisect.state")
284 p = repo.join("bisect.state")
285 if os.path.exists(p):
285 if os.path.exists(p):
286 os.unlink(p)
286 os.unlink(p)
287 return
287 return
288
288
289 # load state
289 # load state
290 state = {'good': [], 'bad': [], 'skip': []}
290 state = {'good': [], 'bad': [], 'skip': []}
291 if os.path.exists(repo.join("bisect.state")):
291 if os.path.exists(repo.join("bisect.state")):
292 for l in repo.opener("bisect.state"):
292 for l in repo.opener("bisect.state"):
293 kind, node = l[:-1].split()
293 kind, node = l[:-1].split()
294 node = repo.lookup(node)
294 node = repo.lookup(node)
295 if kind not in state:
295 if kind not in state:
296 raise util.Abort(_("unknown bisect kind %s") % kind)
296 raise util.Abort(_("unknown bisect kind %s") % kind)
297 state[kind].append(node)
297 state[kind].append(node)
298
298
299 # update state
299 # update state
300 node = repo.lookup(rev or '.')
300 node = repo.lookup(rev or '.')
301 if good:
301 if good:
302 state['good'].append(node)
302 state['good'].append(node)
303 elif bad:
303 elif bad:
304 state['bad'].append(node)
304 state['bad'].append(node)
305 elif skip:
305 elif skip:
306 state['skip'].append(node)
306 state['skip'].append(node)
307
307
308 # save state
308 # save state
309 f = repo.opener("bisect.state", "w", atomictemp=True)
309 f = repo.opener("bisect.state", "w", atomictemp=True)
310 wlock = repo.wlock()
310 wlock = repo.wlock()
311 try:
311 try:
312 for kind in state:
312 for kind in state:
313 for node in state[kind]:
313 for node in state[kind]:
314 f.write("%s %s\n" % (kind, hg.hex(node)))
314 f.write("%s %s\n" % (kind, hg.hex(node)))
315 f.rename()
315 f.rename()
316 finally:
316 finally:
317 del wlock
317 del wlock
318
318
319 if not state['good'] or not state['bad']:
319 if not state['good'] or not state['bad']:
320 return
320 return
321
321
322 # actually bisect
322 # actually bisect
323 node, changesets, good = hbisect.bisect(repo.changelog, state)
323 node, changesets, good = hbisect.bisect(repo.changelog, state)
324 if changesets == 0:
324 if changesets == 0:
325 ui.write(_("The first %s revision is:\n") % (good and "good" or "bad"))
325 ui.write(_("The first %s revision is:\n") % (good and "good" or "bad"))
326 displayer = cmdutil.show_changeset(ui, repo, {})
326 displayer = cmdutil.show_changeset(ui, repo, {})
327 displayer.show(changenode=node)
327 displayer.show(changenode=node)
328 elif node is not None:
328 elif node is not None:
329 # compute the approximate number of remaining tests
329 # compute the approximate number of remaining tests
330 tests, size = 0, 2
330 tests, size = 0, 2
331 while size <= changesets:
331 while size <= changesets:
332 tests, size = tests + 1, size * 2
332 tests, size = tests + 1, size * 2
333 rev = repo.changelog.rev(node)
333 rev = repo.changelog.rev(node)
334 ui.write(_("Testing changeset %s:%s "
334 ui.write(_("Testing changeset %s:%s "
335 "(%s changesets remaining, ~%s tests)\n")
335 "(%s changesets remaining, ~%s tests)\n")
336 % (rev, hg.short(node), changesets, tests))
336 % (rev, hg.short(node), changesets, tests))
337 if not noupdate:
337 if not noupdate:
338 cmdutil.bail_if_changed(repo)
338 cmdutil.bail_if_changed(repo)
339 return hg.clean(repo, node)
339 return hg.clean(repo, node)
340
340
341 def branch(ui, repo, label=None, **opts):
341 def branch(ui, repo, label=None, **opts):
342 """set or show the current branch name
342 """set or show the current branch name
343
343
344 With no argument, show the current branch name. With one argument,
344 With no argument, show the current branch name. With one argument,
345 set the working directory branch name (the branch does not exist in
345 set the working directory branch name (the branch does not exist in
346 the repository until the next commit).
346 the repository until the next commit).
347
347
348 Unless --force is specified, branch will not let you set a
348 Unless --force is specified, branch will not let you set a
349 branch name that shadows an existing branch.
349 branch name that shadows an existing branch.
350
350
351 Use the command 'hg update' to switch to an existing branch.
351 Use the command 'hg update' to switch to an existing branch.
352 """
352 """
353
353
354 if label:
354 if label:
355 if not opts.get('force') and label in repo.branchtags():
355 if not opts.get('force') and label in repo.branchtags():
356 if label not in [p.branch() for p in repo.workingctx().parents()]:
356 if label not in [p.branch() for p in repo.workingctx().parents()]:
357 raise util.Abort(_('a branch of the same name already exists'
357 raise util.Abort(_('a branch of the same name already exists'
358 ' (use --force to override)'))
358 ' (use --force to override)'))
359 repo.dirstate.setbranch(util.fromlocal(label))
359 repo.dirstate.setbranch(util.fromlocal(label))
360 ui.status(_('marked working directory as branch %s\n') % label)
360 ui.status(_('marked working directory as branch %s\n') % label)
361 else:
361 else:
362 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
362 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
363
363
364 def branches(ui, repo, active=False):
364 def branches(ui, repo, active=False):
365 """list repository named branches
365 """list repository named branches
366
366
367 List the repository's named branches, indicating which ones are
367 List the repository's named branches, indicating which ones are
368 inactive. If active is specified, only show active branches.
368 inactive. If active is specified, only show active branches.
369
369
370 A branch is considered active if it contains unmerged heads.
370 A branch is considered active if it contains unmerged heads.
371
371
372 Use the command 'hg update' to switch to an existing branch.
372 Use the command 'hg update' to switch to an existing branch.
373 """
373 """
374 b = repo.branchtags()
374 b = repo.branchtags()
375 heads = dict.fromkeys(repo.heads(), 1)
375 heads = dict.fromkeys(repo.heads(), 1)
376 l = [((n in heads), repo.changelog.rev(n), n, t) for t, n in b.items()]
376 l = [((n in heads), repo.changelog.rev(n), n, t) for t, n in b.items()]
377 l.sort()
377 l.sort()
378 l.reverse()
378 l.reverse()
379 for ishead, r, n, t in l:
379 for ishead, r, n, t in l:
380 if active and not ishead:
380 if active and not ishead:
381 # If we're only displaying active branches, abort the loop on
381 # If we're only displaying active branches, abort the loop on
382 # encountering the first inactive head
382 # encountering the first inactive head
383 break
383 break
384 else:
384 else:
385 hexfunc = ui.debugflag and hex or short
385 hexfunc = ui.debugflag and hex or short
386 if ui.quiet:
386 if ui.quiet:
387 ui.write("%s\n" % t)
387 ui.write("%s\n" % t)
388 else:
388 else:
389 spaces = " " * (30 - util.locallen(t))
389 spaces = " " * (30 - util.locallen(t))
390 # The code only gets here if inactive branches are being
390 # The code only gets here if inactive branches are being
391 # displayed or the branch is active.
391 # displayed or the branch is active.
392 isinactive = ((not ishead) and " (inactive)") or ''
392 isinactive = ((not ishead) and " (inactive)") or ''
393 ui.write("%s%s %s:%s%s\n" % (t, spaces, r, hexfunc(n), isinactive))
393 ui.write("%s%s %s:%s%s\n" % (t, spaces, r, hexfunc(n), isinactive))
394
394
395 def bundle(ui, repo, fname, dest=None, **opts):
395 def bundle(ui, repo, fname, dest=None, **opts):
396 """create a changegroup file
396 """create a changegroup file
397
397
398 Generate a compressed changegroup file collecting changesets not
398 Generate a compressed changegroup file collecting changesets not
399 found in the other repository.
399 found in the other repository.
400
400
401 If no destination repository is specified the destination is
401 If no destination repository is specified the destination is
402 assumed to have all the nodes specified by one or more --base
402 assumed to have all the nodes specified by one or more --base
403 parameters. To create a bundle containing all changesets, use
403 parameters. To create a bundle containing all changesets, use
404 --all (or --base null).
404 --all (or --base null).
405
405
406 The bundle file can then be transferred using conventional means and
406 The bundle file can then be transferred using conventional means and
407 applied to another repository with the unbundle or pull command.
407 applied to another repository with the unbundle or pull command.
408 This is useful when direct push and pull are not available or when
408 This is useful when direct push and pull are not available or when
409 exporting an entire repository is undesirable.
409 exporting an entire repository is undesirable.
410
410
411 Applying bundles preserves all changeset contents including
411 Applying bundles preserves all changeset contents including
412 permissions, copy/rename information, and revision history.
412 permissions, copy/rename information, and revision history.
413 """
413 """
414 revs = opts.get('rev') or None
414 revs = opts.get('rev') or None
415 if revs:
415 if revs:
416 revs = [repo.lookup(rev) for rev in revs]
416 revs = [repo.lookup(rev) for rev in revs]
417 if opts.get('all'):
417 if opts.get('all'):
418 base = ['null']
418 base = ['null']
419 else:
419 else:
420 base = opts.get('base')
420 base = opts.get('base')
421 if base:
421 if base:
422 if dest:
422 if dest:
423 raise util.Abort(_("--base is incompatible with specifiying "
423 raise util.Abort(_("--base is incompatible with specifiying "
424 "a destination"))
424 "a destination"))
425 base = [repo.lookup(rev) for rev in base]
425 base = [repo.lookup(rev) for rev in base]
426 # create the right base
426 # create the right base
427 # XXX: nodesbetween / changegroup* should be "fixed" instead
427 # XXX: nodesbetween / changegroup* should be "fixed" instead
428 o = []
428 o = []
429 has = {nullid: None}
429 has = {nullid: None}
430 for n in base:
430 for n in base:
431 has.update(repo.changelog.reachable(n))
431 has.update(repo.changelog.reachable(n))
432 if revs:
432 if revs:
433 visit = list(revs)
433 visit = list(revs)
434 else:
434 else:
435 visit = repo.changelog.heads()
435 visit = repo.changelog.heads()
436 seen = {}
436 seen = {}
437 while visit:
437 while visit:
438 n = visit.pop(0)
438 n = visit.pop(0)
439 parents = [p for p in repo.changelog.parents(n) if p not in has]
439 parents = [p for p in repo.changelog.parents(n) if p not in has]
440 if len(parents) == 0:
440 if len(parents) == 0:
441 o.insert(0, n)
441 o.insert(0, n)
442 else:
442 else:
443 for p in parents:
443 for p in parents:
444 if p not in seen:
444 if p not in seen:
445 seen[p] = 1
445 seen[p] = 1
446 visit.append(p)
446 visit.append(p)
447 else:
447 else:
448 cmdutil.setremoteconfig(ui, opts)
448 cmdutil.setremoteconfig(ui, opts)
449 dest, revs, checkout = hg.parseurl(
449 dest, revs, checkout = hg.parseurl(
450 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
450 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
451 other = hg.repository(ui, dest)
451 other = hg.repository(ui, dest)
452 o = repo.findoutgoing(other, force=opts['force'])
452 o = repo.findoutgoing(other, force=opts['force'])
453
453
454 if revs:
454 if revs:
455 cg = repo.changegroupsubset(o, revs, 'bundle')
455 cg = repo.changegroupsubset(o, revs, 'bundle')
456 else:
456 else:
457 cg = repo.changegroup(o, 'bundle')
457 cg = repo.changegroup(o, 'bundle')
458 changegroup.writebundle(cg, fname, "HG10BZ")
458 changegroup.writebundle(cg, fname, "HG10BZ")
459
459
460 def cat(ui, repo, file1, *pats, **opts):
460 def cat(ui, repo, file1, *pats, **opts):
461 """output the current or given revision of files
461 """output the current or given revision of files
462
462
463 Print the specified files as they were at the given revision.
463 Print the specified files as they were at the given revision.
464 If no revision is given, the parent of the working directory is used,
464 If no revision is given, the parent of the working directory is used,
465 or tip if no revision is checked out.
465 or tip if no revision is checked out.
466
466
467 Output may be to a file, in which case the name of the file is
467 Output may be to a file, in which case the name of the file is
468 given using a format string. The formatting rules are the same as
468 given using a format string. The formatting rules are the same as
469 for the export command, with the following additions:
469 for the export command, with the following additions:
470
470
471 %s basename of file being printed
471 %s basename of file being printed
472 %d dirname of file being printed, or '.' if in repo root
472 %d dirname of file being printed, or '.' if in repo root
473 %p root-relative path name of file being printed
473 %p root-relative path name of file being printed
474 """
474 """
475 ctx = repo.changectx(opts['rev'])
475 ctx = repo.changectx(opts['rev'])
476 err = 1
476 err = 1
477 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
477 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
478 ctx.node()):
478 ctx.node()):
479 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
479 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
480 data = ctx.filectx(abs).data()
480 data = ctx.filectx(abs).data()
481 if opts.get('decode'):
481 if opts.get('decode'):
482 data = repo.wwritedata(abs, data)
482 data = repo.wwritedata(abs, data)
483 fp.write(data)
483 fp.write(data)
484 err = 0
484 err = 0
485 return err
485 return err
486
486
487 def clone(ui, source, dest=None, **opts):
487 def clone(ui, source, dest=None, **opts):
488 """make a copy of an existing repository
488 """make a copy of an existing repository
489
489
490 Create a copy of an existing repository in a new directory.
490 Create a copy of an existing repository in a new directory.
491
491
492 If no destination directory name is specified, it defaults to the
492 If no destination directory name is specified, it defaults to the
493 basename of the source.
493 basename of the source.
494
494
495 The location of the source is added to the new repository's
495 The location of the source is added to the new repository's
496 .hg/hgrc file, as the default to be used for future pulls.
496 .hg/hgrc file, as the default to be used for future pulls.
497
497
498 For efficiency, hardlinks are used for cloning whenever the source
498 For efficiency, hardlinks are used for cloning whenever the source
499 and destination are on the same filesystem (note this applies only
499 and destination are on the same filesystem (note this applies only
500 to the repository data, not to the checked out files). Some
500 to the repository data, not to the checked out files). Some
501 filesystems, such as AFS, implement hardlinking incorrectly, but
501 filesystems, such as AFS, implement hardlinking incorrectly, but
502 do not report errors. In these cases, use the --pull option to
502 do not report errors. In these cases, use the --pull option to
503 avoid hardlinking.
503 avoid hardlinking.
504
504
505 You can safely clone repositories and checked out files using full
505 You can safely clone repositories and checked out files using full
506 hardlinks with
506 hardlinks with
507
507
508 $ cp -al REPO REPOCLONE
508 $ cp -al REPO REPOCLONE
509
509
510 which is the fastest way to clone. However, the operation is not
510 which is the fastest way to clone. However, the operation is not
511 atomic (making sure REPO is not modified during the operation is
511 atomic (making sure REPO is not modified during the operation is
512 up to you) and you have to make sure your editor breaks hardlinks
512 up to you) and you have to make sure your editor breaks hardlinks
513 (Emacs and most Linux Kernel tools do so).
513 (Emacs and most Linux Kernel tools do so).
514
514
515 If you use the -r option to clone up to a specific revision, no
515 If you use the -r option to clone up to a specific revision, no
516 subsequent revisions will be present in the cloned repository.
516 subsequent revisions will be present in the cloned repository.
517 This option implies --pull, even on local repositories.
517 This option implies --pull, even on local repositories.
518
518
519 See pull for valid source format details.
519 See pull for valid source format details.
520
520
521 It is possible to specify an ssh:// URL as the destination, but no
521 It is possible to specify an ssh:// URL as the destination, but no
522 .hg/hgrc and working directory will be created on the remote side.
522 .hg/hgrc and working directory will be created on the remote side.
523 Look at the help text for the pull command for important details
523 Look at the help text for the pull command for important details
524 about ssh:// URLs.
524 about ssh:// URLs.
525 """
525 """
526 cmdutil.setremoteconfig(ui, opts)
526 cmdutil.setremoteconfig(ui, opts)
527 hg.clone(ui, source, dest,
527 hg.clone(ui, source, dest,
528 pull=opts['pull'],
528 pull=opts['pull'],
529 stream=opts['uncompressed'],
529 stream=opts['uncompressed'],
530 rev=opts['rev'],
530 rev=opts['rev'],
531 update=not opts['noupdate'])
531 update=not opts['noupdate'])
532
532
533 def commit(ui, repo, *pats, **opts):
533 def commit(ui, repo, *pats, **opts):
534 """commit the specified files or all outstanding changes
534 """commit the specified files or all outstanding changes
535
535
536 Commit changes to the given files into the repository.
536 Commit changes to the given files into the repository.
537
537
538 If a list of files is omitted, all changes reported by "hg status"
538 If a list of files is omitted, all changes reported by "hg status"
539 will be committed.
539 will be committed.
540
540
541 If no commit message is specified, the configured editor is started to
541 If no commit message is specified, the configured editor is started to
542 enter a message.
542 enter a message.
543
543
544 See 'hg help dates' for a list of formats valid for -d/--date.
544 See 'hg help dates' for a list of formats valid for -d/--date.
545 """
545 """
546 def commitfunc(ui, repo, files, message, match, opts):
546 def commitfunc(ui, repo, files, message, match, opts):
547 return repo.commit(files, message, opts['user'], opts['date'], match,
547 return repo.commit(files, message, opts['user'], opts['date'], match,
548 force_editor=opts.get('force_editor'))
548 force_editor=opts.get('force_editor'))
549 cmdutil.commit(ui, repo, commitfunc, pats, opts)
549 cmdutil.commit(ui, repo, commitfunc, pats, opts)
550
550
551 def copy(ui, repo, *pats, **opts):
551 def copy(ui, repo, *pats, **opts):
552 """mark files as copied for the next commit
552 """mark files as copied for the next commit
553
553
554 Mark dest as having copies of source files. If dest is a
554 Mark dest as having copies of source files. If dest is a
555 directory, copies are put in that directory. If dest is a file,
555 directory, copies are put in that directory. If dest is a file,
556 there can only be one source.
556 there can only be one source.
557
557
558 By default, this command copies the contents of files as they
558 By default, this command copies the contents of files as they
559 stand in the working directory. If invoked with --after, the
559 stand in the working directory. If invoked with --after, the
560 operation is recorded, but no copying is performed.
560 operation is recorded, but no copying is performed.
561
561
562 This command takes effect in the next commit. To undo a copy
562 This command takes effect in the next commit. To undo a copy
563 before that, see hg revert.
563 before that, see hg revert.
564 """
564 """
565 wlock = repo.wlock(False)
565 wlock = repo.wlock(False)
566 try:
566 try:
567 return cmdutil.copy(ui, repo, pats, opts)
567 return cmdutil.copy(ui, repo, pats, opts)
568 finally:
568 finally:
569 del wlock
569 del wlock
570
570
571 def debugancestor(ui, repo, *args):
571 def debugancestor(ui, repo, *args):
572 """find the ancestor revision of two revisions in a given index"""
572 """find the ancestor revision of two revisions in a given index"""
573 if len(args) == 3:
573 if len(args) == 3:
574 index, rev1, rev2 = args
574 index, rev1, rev2 = args
575 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
575 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
576 elif len(args) == 2:
576 elif len(args) == 2:
577 if not repo:
577 if not repo:
578 raise util.Abort(_("There is no Mercurial repository here "
578 raise util.Abort(_("There is no Mercurial repository here "
579 "(.hg not found)"))
579 "(.hg not found)"))
580 rev1, rev2 = args
580 rev1, rev2 = args
581 r = repo.changelog
581 r = repo.changelog
582 else:
582 else:
583 raise util.Abort(_('either two or three arguments required'))
583 raise util.Abort(_('either two or three arguments required'))
584 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
584 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
585 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
585 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
586
586
587 def debugcomplete(ui, cmd='', **opts):
587 def debugcomplete(ui, cmd='', **opts):
588 """returns the completion list associated with the given command"""
588 """returns the completion list associated with the given command"""
589
589
590 if opts['options']:
590 if opts['options']:
591 options = []
591 options = []
592 otables = [globalopts]
592 otables = [globalopts]
593 if cmd:
593 if cmd:
594 aliases, entry = cmdutil.findcmd(ui, cmd, table)
594 aliases, entry = cmdutil.findcmd(ui, cmd, table)
595 otables.append(entry[1])
595 otables.append(entry[1])
596 for t in otables:
596 for t in otables:
597 for o in t:
597 for o in t:
598 if o[0]:
598 if o[0]:
599 options.append('-%s' % o[0])
599 options.append('-%s' % o[0])
600 options.append('--%s' % o[1])
600 options.append('--%s' % o[1])
601 ui.write("%s\n" % "\n".join(options))
601 ui.write("%s\n" % "\n".join(options))
602 return
602 return
603
603
604 clist = cmdutil.findpossible(ui, cmd, table).keys()
604 clist = cmdutil.findpossible(ui, cmd, table).keys()
605 clist.sort()
605 clist.sort()
606 ui.write("%s\n" % "\n".join(clist))
606 ui.write("%s\n" % "\n".join(clist))
607
607
608 def debugfsinfo(ui, path = "."):
608 def debugfsinfo(ui, path = "."):
609 file('.debugfsinfo', 'w').write('')
609 file('.debugfsinfo', 'w').write('')
610 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
610 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
611 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
611 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
612 ui.write('case-sensitive: %s\n' % (util.checkfolding('.debugfsinfo')
612 ui.write('case-sensitive: %s\n' % (util.checkfolding('.debugfsinfo')
613 and 'yes' or 'no'))
613 and 'yes' or 'no'))
614 os.unlink('.debugfsinfo')
614 os.unlink('.debugfsinfo')
615
615
616 def debugrebuildstate(ui, repo, rev=""):
616 def debugrebuildstate(ui, repo, rev=""):
617 """rebuild the dirstate as it would look like for the given revision"""
617 """rebuild the dirstate as it would look like for the given revision"""
618 if rev == "":
618 if rev == "":
619 rev = repo.changelog.tip()
619 rev = repo.changelog.tip()
620 ctx = repo.changectx(rev)
620 ctx = repo.changectx(rev)
621 files = ctx.manifest()
621 files = ctx.manifest()
622 wlock = repo.wlock()
622 wlock = repo.wlock()
623 try:
623 try:
624 repo.dirstate.rebuild(rev, files)
624 repo.dirstate.rebuild(rev, files)
625 finally:
625 finally:
626 del wlock
626 del wlock
627
627
628 def debugcheckstate(ui, repo):
628 def debugcheckstate(ui, repo):
629 """validate the correctness of the current dirstate"""
629 """validate the correctness of the current dirstate"""
630 parent1, parent2 = repo.dirstate.parents()
630 parent1, parent2 = repo.dirstate.parents()
631 m1 = repo.changectx(parent1).manifest()
631 m1 = repo.changectx(parent1).manifest()
632 m2 = repo.changectx(parent2).manifest()
632 m2 = repo.changectx(parent2).manifest()
633 errors = 0
633 errors = 0
634 for f in repo.dirstate:
634 for f in repo.dirstate:
635 state = repo.dirstate[f]
635 state = repo.dirstate[f]
636 if state in "nr" and f not in m1:
636 if state in "nr" and f not in m1:
637 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
637 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
638 errors += 1
638 errors += 1
639 if state in "a" and f in m1:
639 if state in "a" and f in m1:
640 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
640 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
641 errors += 1
641 errors += 1
642 if state in "m" and f not in m1 and f not in m2:
642 if state in "m" and f not in m1 and f not in m2:
643 ui.warn(_("%s in state %s, but not in either manifest\n") %
643 ui.warn(_("%s in state %s, but not in either manifest\n") %
644 (f, state))
644 (f, state))
645 errors += 1
645 errors += 1
646 for f in m1:
646 for f in m1:
647 state = repo.dirstate[f]
647 state = repo.dirstate[f]
648 if state not in "nrm":
648 if state not in "nrm":
649 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
649 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
650 errors += 1
650 errors += 1
651 if errors:
651 if errors:
652 error = _(".hg/dirstate inconsistent with current parent's manifest")
652 error = _(".hg/dirstate inconsistent with current parent's manifest")
653 raise util.Abort(error)
653 raise util.Abort(error)
654
654
655 def showconfig(ui, repo, *values, **opts):
655 def showconfig(ui, repo, *values, **opts):
656 """show combined config settings from all hgrc files
656 """show combined config settings from all hgrc files
657
657
658 With no args, print names and values of all config items.
658 With no args, print names and values of all config items.
659
659
660 With one arg of the form section.name, print just the value of
660 With one arg of the form section.name, print just the value of
661 that config item.
661 that config item.
662
662
663 With multiple args, print names and values of all config items
663 With multiple args, print names and values of all config items
664 with matching section names."""
664 with matching section names."""
665
665
666 untrusted = bool(opts.get('untrusted'))
666 untrusted = bool(opts.get('untrusted'))
667 if values:
667 if values:
668 if len([v for v in values if '.' in v]) > 1:
668 if len([v for v in values if '.' in v]) > 1:
669 raise util.Abort(_('only one config item permitted'))
669 raise util.Abort(_('only one config item permitted'))
670 for section, name, value in ui.walkconfig(untrusted=untrusted):
670 for section, name, value in ui.walkconfig(untrusted=untrusted):
671 sectname = section + '.' + name
671 sectname = section + '.' + name
672 if values:
672 if values:
673 for v in values:
673 for v in values:
674 if v == section:
674 if v == section:
675 ui.write('%s=%s\n' % (sectname, value))
675 ui.write('%s=%s\n' % (sectname, value))
676 elif v == sectname:
676 elif v == sectname:
677 ui.write(value, '\n')
677 ui.write(value, '\n')
678 else:
678 else:
679 ui.write('%s=%s\n' % (sectname, value))
679 ui.write('%s=%s\n' % (sectname, value))
680
680
681 def debugsetparents(ui, repo, rev1, rev2=None):
681 def debugsetparents(ui, repo, rev1, rev2=None):
682 """manually set the parents of the current working directory
682 """manually set the parents of the current working directory
683
683
684 This is useful for writing repository conversion tools, but should
684 This is useful for writing repository conversion tools, but should
685 be used with care.
685 be used with care.
686 """
686 """
687
687
688 if not rev2:
688 if not rev2:
689 rev2 = hex(nullid)
689 rev2 = hex(nullid)
690
690
691 wlock = repo.wlock()
691 wlock = repo.wlock()
692 try:
692 try:
693 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
693 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
694 finally:
694 finally:
695 del wlock
695 del wlock
696
696
697 def debugstate(ui, repo):
697 def debugstate(ui, repo):
698 """show the contents of the current dirstate"""
698 """show the contents of the current dirstate"""
699 k = repo.dirstate._map.items()
699 k = repo.dirstate._map.items()
700 k.sort()
700 k.sort()
701 for file_, ent in k:
701 for file_, ent in k:
702 if ent[3] == -1:
702 if ent[3] == -1:
703 # Pad or slice to locale representation
703 # Pad or slice to locale representation
704 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(0)))
704 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(0)))
705 timestr = 'unset'
705 timestr = 'unset'
706 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
706 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
707 else:
707 else:
708 timestr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ent[3]))
708 timestr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ent[3]))
709 if ent[1] & 020000:
709 if ent[1] & 020000:
710 mode = 'lnk'
710 mode = 'lnk'
711 else:
711 else:
712 mode = '%3o' % (ent[1] & 0777)
712 mode = '%3o' % (ent[1] & 0777)
713 ui.write("%c %s %10d %s %s\n" % (ent[0], mode, ent[2], timestr, file_))
713 ui.write("%c %s %10d %s %s\n" % (ent[0], mode, ent[2], timestr, file_))
714 for f in repo.dirstate.copies():
714 for f in repo.dirstate.copies():
715 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
715 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
716
716
717 def debugdata(ui, file_, rev):
717 def debugdata(ui, file_, rev):
718 """dump the contents of a data file revision"""
718 """dump the contents of a data file revision"""
719 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
719 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
720 try:
720 try:
721 ui.write(r.revision(r.lookup(rev)))
721 ui.write(r.revision(r.lookup(rev)))
722 except KeyError:
722 except KeyError:
723 raise util.Abort(_('invalid revision identifier %s') % rev)
723 raise util.Abort(_('invalid revision identifier %s') % rev)
724
724
725 def debugdate(ui, date, range=None, **opts):
725 def debugdate(ui, date, range=None, **opts):
726 """parse and display a date"""
726 """parse and display a date"""
727 if opts["extended"]:
727 if opts["extended"]:
728 d = util.parsedate(date, util.extendeddateformats)
728 d = util.parsedate(date, util.extendeddateformats)
729 else:
729 else:
730 d = util.parsedate(date)
730 d = util.parsedate(date)
731 ui.write("internal: %s %s\n" % d)
731 ui.write("internal: %s %s\n" % d)
732 ui.write("standard: %s\n" % util.datestr(d))
732 ui.write("standard: %s\n" % util.datestr(d))
733 if range:
733 if range:
734 m = util.matchdate(range)
734 m = util.matchdate(range)
735 ui.write("match: %s\n" % m(d[0]))
735 ui.write("match: %s\n" % m(d[0]))
736
736
737 def debugindex(ui, file_):
737 def debugindex(ui, file_):
738 """dump the contents of an index file"""
738 """dump the contents of an index file"""
739 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
739 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
740 ui.write(" rev offset length base linkrev" +
740 ui.write(" rev offset length base linkrev" +
741 " nodeid p1 p2\n")
741 " nodeid p1 p2\n")
742 for i in xrange(r.count()):
742 for i in xrange(r.count()):
743 node = r.node(i)
743 node = r.node(i)
744 try:
744 try:
745 pp = r.parents(node)
745 pp = r.parents(node)
746 except:
746 except:
747 pp = [nullid, nullid]
747 pp = [nullid, nullid]
748 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
748 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
749 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
749 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
750 short(node), short(pp[0]), short(pp[1])))
750 short(node), short(pp[0]), short(pp[1])))
751
751
752 def debugindexdot(ui, file_):
752 def debugindexdot(ui, file_):
753 """dump an index DAG as a .dot file"""
753 """dump an index DAG as a .dot file"""
754 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
754 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
755 ui.write("digraph G {\n")
755 ui.write("digraph G {\n")
756 for i in xrange(r.count()):
756 for i in xrange(r.count()):
757 node = r.node(i)
757 node = r.node(i)
758 pp = r.parents(node)
758 pp = r.parents(node)
759 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
759 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
760 if pp[1] != nullid:
760 if pp[1] != nullid:
761 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
761 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
762 ui.write("}\n")
762 ui.write("}\n")
763
763
764 def debuginstall(ui):
764 def debuginstall(ui):
765 '''test Mercurial installation'''
765 '''test Mercurial installation'''
766
766
767 def writetemp(contents):
767 def writetemp(contents):
768 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
768 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
769 f = os.fdopen(fd, "wb")
769 f = os.fdopen(fd, "wb")
770 f.write(contents)
770 f.write(contents)
771 f.close()
771 f.close()
772 return name
772 return name
773
773
774 problems = 0
774 problems = 0
775
775
776 # encoding
776 # encoding
777 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
777 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
778 try:
778 try:
779 util.fromlocal("test")
779 util.fromlocal("test")
780 except util.Abort, inst:
780 except util.Abort, inst:
781 ui.write(" %s\n" % inst)
781 ui.write(" %s\n" % inst)
782 ui.write(_(" (check that your locale is properly set)\n"))
782 ui.write(_(" (check that your locale is properly set)\n"))
783 problems += 1
783 problems += 1
784
784
785 # compiled modules
785 # compiled modules
786 ui.status(_("Checking extensions...\n"))
786 ui.status(_("Checking extensions...\n"))
787 try:
787 try:
788 import bdiff, mpatch, base85
788 import bdiff, mpatch, base85
789 except Exception, inst:
789 except Exception, inst:
790 ui.write(" %s\n" % inst)
790 ui.write(" %s\n" % inst)
791 ui.write(_(" One or more extensions could not be found"))
791 ui.write(_(" One or more extensions could not be found"))
792 ui.write(_(" (check that you compiled the extensions)\n"))
792 ui.write(_(" (check that you compiled the extensions)\n"))
793 problems += 1
793 problems += 1
794
794
795 # templates
795 # templates
796 ui.status(_("Checking templates...\n"))
796 ui.status(_("Checking templates...\n"))
797 try:
797 try:
798 import templater
798 import templater
799 t = templater.templater(templater.templatepath("map-cmdline.default"))
799 t = templater.templater(templater.templatepath("map-cmdline.default"))
800 except Exception, inst:
800 except Exception, inst:
801 ui.write(" %s\n" % inst)
801 ui.write(" %s\n" % inst)
802 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
802 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
803 problems += 1
803 problems += 1
804
804
805 # patch
805 # patch
806 ui.status(_("Checking patch...\n"))
806 ui.status(_("Checking patch...\n"))
807 patchproblems = 0
807 patchproblems = 0
808 a = "1\n2\n3\n4\n"
808 a = "1\n2\n3\n4\n"
809 b = "1\n2\n3\ninsert\n4\n"
809 b = "1\n2\n3\ninsert\n4\n"
810 fa = writetemp(a)
810 fa = writetemp(a)
811 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
811 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
812 os.path.basename(fa))
812 os.path.basename(fa))
813 fd = writetemp(d)
813 fd = writetemp(d)
814
814
815 files = {}
815 files = {}
816 try:
816 try:
817 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
817 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
818 except util.Abort, e:
818 except util.Abort, e:
819 ui.write(_(" patch call failed:\n"))
819 ui.write(_(" patch call failed:\n"))
820 ui.write(" " + str(e) + "\n")
820 ui.write(" " + str(e) + "\n")
821 patchproblems += 1
821 patchproblems += 1
822 else:
822 else:
823 if list(files) != [os.path.basename(fa)]:
823 if list(files) != [os.path.basename(fa)]:
824 ui.write(_(" unexpected patch output!\n"))
824 ui.write(_(" unexpected patch output!\n"))
825 patchproblems += 1
825 patchproblems += 1
826 a = file(fa).read()
826 a = file(fa).read()
827 if a != b:
827 if a != b:
828 ui.write(_(" patch test failed!\n"))
828 ui.write(_(" patch test failed!\n"))
829 patchproblems += 1
829 patchproblems += 1
830
830
831 if patchproblems:
831 if patchproblems:
832 if ui.config('ui', 'patch'):
832 if ui.config('ui', 'patch'):
833 ui.write(_(" (Current patch tool may be incompatible with patch,"
833 ui.write(_(" (Current patch tool may be incompatible with patch,"
834 " or misconfigured. Please check your .hgrc file)\n"))
834 " or misconfigured. Please check your .hgrc file)\n"))
835 else:
835 else:
836 ui.write(_(" Internal patcher failure, please report this error"
836 ui.write(_(" Internal patcher failure, please report this error"
837 " to http://www.selenic.com/mercurial/bts\n"))
837 " to http://www.selenic.com/mercurial/bts\n"))
838 problems += patchproblems
838 problems += patchproblems
839
839
840 os.unlink(fa)
840 os.unlink(fa)
841 os.unlink(fd)
841 os.unlink(fd)
842
842
843 # editor
843 # editor
844 ui.status(_("Checking commit editor...\n"))
844 ui.status(_("Checking commit editor...\n"))
845 editor = ui.geteditor()
845 editor = ui.geteditor()
846 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
846 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
847 if not cmdpath:
847 if not cmdpath:
848 if editor == 'vi':
848 if editor == 'vi':
849 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
849 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
850 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
850 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
851 else:
851 else:
852 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
852 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
853 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
853 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
854 problems += 1
854 problems += 1
855
855
856 # check username
856 # check username
857 ui.status(_("Checking username...\n"))
857 ui.status(_("Checking username...\n"))
858 user = os.environ.get("HGUSER")
858 user = os.environ.get("HGUSER")
859 if user is None:
859 if user is None:
860 user = ui.config("ui", "username")
860 user = ui.config("ui", "username")
861 if user is None:
861 if user is None:
862 user = os.environ.get("EMAIL")
862 user = os.environ.get("EMAIL")
863 if not user:
863 if not user:
864 ui.warn(" ")
864 ui.warn(" ")
865 ui.username()
865 ui.username()
866 ui.write(_(" (specify a username in your .hgrc file)\n"))
866 ui.write(_(" (specify a username in your .hgrc file)\n"))
867
867
868 if not problems:
868 if not problems:
869 ui.status(_("No problems detected\n"))
869 ui.status(_("No problems detected\n"))
870 else:
870 else:
871 ui.write(_("%s problems detected,"
871 ui.write(_("%s problems detected,"
872 " please check your install!\n") % problems)
872 " please check your install!\n") % problems)
873
873
874 return problems
874 return problems
875
875
876 def debugrename(ui, repo, file1, *pats, **opts):
876 def debugrename(ui, repo, file1, *pats, **opts):
877 """dump rename information"""
877 """dump rename information"""
878
878
879 ctx = repo.changectx(opts.get('rev', 'tip'))
879 ctx = repo.changectx(opts.get('rev', 'tip'))
880 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
880 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
881 ctx.node()):
881 ctx.node()):
882 fctx = ctx.filectx(abs)
882 fctx = ctx.filectx(abs)
883 m = fctx.filelog().renamed(fctx.filenode())
883 m = fctx.filelog().renamed(fctx.filenode())
884 if m:
884 if m:
885 ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
885 ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
886 else:
886 else:
887 ui.write(_("%s not renamed\n") % rel)
887 ui.write(_("%s not renamed\n") % rel)
888
888
889 def debugwalk(ui, repo, *pats, **opts):
889 def debugwalk(ui, repo, *pats, **opts):
890 """show how files match on given patterns"""
890 """show how files match on given patterns"""
891 items = list(cmdutil.walk(repo, pats, opts))
891 items = list(cmdutil.walk(repo, pats, opts))
892 if not items:
892 if not items:
893 return
893 return
894 fmt = '%%s %%-%ds %%-%ds %%s' % (
894 fmt = '%%s %%-%ds %%-%ds %%s' % (
895 max([len(abs) for (src, abs, rel, exact) in items]),
895 max([len(abs) for (src, abs, rel, exact) in items]),
896 max([len(rel) for (src, abs, rel, exact) in items]))
896 max([len(rel) for (src, abs, rel, exact) in items]))
897 for src, abs, rel, exact in items:
897 for src, abs, rel, exact in items:
898 line = fmt % (src, abs, rel, exact and 'exact' or '')
898 line = fmt % (src, abs, rel, exact and 'exact' or '')
899 ui.write("%s\n" % line.rstrip())
899 ui.write("%s\n" % line.rstrip())
900
900
901 def diff(ui, repo, *pats, **opts):
901 def diff(ui, repo, *pats, **opts):
902 """diff repository (or selected files)
902 """diff repository (or selected files)
903
903
904 Show differences between revisions for the specified files.
904 Show differences between revisions for the specified files.
905
905
906 Differences between files are shown using the unified diff format.
906 Differences between files are shown using the unified diff format.
907
907
908 NOTE: diff may generate unexpected results for merges, as it will
908 NOTE: diff may generate unexpected results for merges, as it will
909 default to comparing against the working directory's first parent
909 default to comparing against the working directory's first parent
910 changeset if no revisions are specified.
910 changeset if no revisions are specified.
911
911
912 When two revision arguments are given, then changes are shown
912 When two revision arguments are given, then changes are shown
913 between those revisions. If only one revision is specified then
913 between those revisions. If only one revision is specified then
914 that revision is compared to the working directory, and, when no
914 that revision is compared to the working directory, and, when no
915 revisions are specified, the working directory files are compared
915 revisions are specified, the working directory files are compared
916 to its parent.
916 to its parent.
917
917
918 Without the -a option, diff will avoid generating diffs of files
918 Without the -a option, diff will avoid generating diffs of files
919 it detects as binary. With -a, diff will generate a diff anyway,
919 it detects as binary. With -a, diff will generate a diff anyway,
920 probably with undesirable results.
920 probably with undesirable results.
921 """
921 """
922 node1, node2 = cmdutil.revpair(repo, opts['rev'])
922 node1, node2 = cmdutil.revpair(repo, opts['rev'])
923
923
924 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
924 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
925
925
926 patch.diff(repo, node1, node2, fns, match=matchfn,
926 patch.diff(repo, node1, node2, fns, match=matchfn,
927 opts=patch.diffopts(ui, opts))
927 opts=patch.diffopts(ui, opts))
928
928
929 def export(ui, repo, *changesets, **opts):
929 def export(ui, repo, *changesets, **opts):
930 """dump the header and diffs for one or more changesets
930 """dump the header and diffs for one or more changesets
931
931
932 Print the changeset header and diffs for one or more revisions.
932 Print the changeset header and diffs for one or more revisions.
933
933
934 The information shown in the changeset header is: author,
934 The information shown in the changeset header is: author,
935 changeset hash, parent(s) and commit comment.
935 changeset hash, parent(s) and commit comment.
936
936
937 NOTE: export may generate unexpected diff output for merge changesets,
937 NOTE: export may generate unexpected diff output for merge changesets,
938 as it will compare the merge changeset against its first parent only.
938 as it will compare the merge changeset against its first parent only.
939
939
940 Output may be to a file, in which case the name of the file is
940 Output may be to a file, in which case the name of the file is
941 given using a format string. The formatting rules are as follows:
941 given using a format string. The formatting rules are as follows:
942
942
943 %% literal "%" character
943 %% literal "%" character
944 %H changeset hash (40 bytes of hexadecimal)
944 %H changeset hash (40 bytes of hexadecimal)
945 %N number of patches being generated
945 %N number of patches being generated
946 %R changeset revision number
946 %R changeset revision number
947 %b basename of the exporting repository
947 %b basename of the exporting repository
948 %h short-form changeset hash (12 bytes of hexadecimal)
948 %h short-form changeset hash (12 bytes of hexadecimal)
949 %n zero-padded sequence number, starting at 1
949 %n zero-padded sequence number, starting at 1
950 %r zero-padded changeset revision number
950 %r zero-padded changeset revision number
951
951
952 Without the -a option, export will avoid generating diffs of files
952 Without the -a option, export will avoid generating diffs of files
953 it detects as binary. With -a, export will generate a diff anyway,
953 it detects as binary. With -a, export will generate a diff anyway,
954 probably with undesirable results.
954 probably with undesirable results.
955
955
956 With the --switch-parent option, the diff will be against the second
956 With the --switch-parent option, the diff will be against the second
957 parent. It can be useful to review a merge.
957 parent. It can be useful to review a merge.
958 """
958 """
959 if not changesets:
959 if not changesets:
960 raise util.Abort(_("export requires at least one changeset"))
960 raise util.Abort(_("export requires at least one changeset"))
961 revs = cmdutil.revrange(repo, changesets)
961 revs = cmdutil.revrange(repo, changesets)
962 if len(revs) > 1:
962 if len(revs) > 1:
963 ui.note(_('exporting patches:\n'))
963 ui.note(_('exporting patches:\n'))
964 else:
964 else:
965 ui.note(_('exporting patch:\n'))
965 ui.note(_('exporting patch:\n'))
966 patch.export(repo, revs, template=opts['output'],
966 patch.export(repo, revs, template=opts['output'],
967 switch_parent=opts['switch_parent'],
967 switch_parent=opts['switch_parent'],
968 opts=patch.diffopts(ui, opts))
968 opts=patch.diffopts(ui, opts))
969
969
970 def grep(ui, repo, pattern, *pats, **opts):
970 def grep(ui, repo, pattern, *pats, **opts):
971 """search for a pattern in specified files and revisions
971 """search for a pattern in specified files and revisions
972
972
973 Search revisions of files for a regular expression.
973 Search revisions of files for a regular expression.
974
974
975 This command behaves differently than Unix grep. It only accepts
975 This command behaves differently than Unix grep. It only accepts
976 Python/Perl regexps. It searches repository history, not the
976 Python/Perl regexps. It searches repository history, not the
977 working directory. It always prints the revision number in which
977 working directory. It always prints the revision number in which
978 a match appears.
978 a match appears.
979
979
980 By default, grep only prints output for the first revision of a
980 By default, grep only prints output for the first revision of a
981 file in which it finds a match. To get it to print every revision
981 file in which it finds a match. To get it to print every revision
982 that contains a change in match status ("-" for a match that
982 that contains a change in match status ("-" for a match that
983 becomes a non-match, or "+" for a non-match that becomes a match),
983 becomes a non-match, or "+" for a non-match that becomes a match),
984 use the --all flag.
984 use the --all flag.
985 """
985 """
986 reflags = 0
986 reflags = 0
987 if opts['ignore_case']:
987 if opts['ignore_case']:
988 reflags |= re.I
988 reflags |= re.I
989 try:
989 try:
990 regexp = re.compile(pattern, reflags)
990 regexp = re.compile(pattern, reflags)
991 except Exception, inst:
991 except Exception, inst:
992 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
992 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
993 return None
993 return None
994 sep, eol = ':', '\n'
994 sep, eol = ':', '\n'
995 if opts['print0']:
995 if opts['print0']:
996 sep = eol = '\0'
996 sep = eol = '\0'
997
997
998 fcache = {}
998 fcache = {}
999 def getfile(fn):
999 def getfile(fn):
1000 if fn not in fcache:
1000 if fn not in fcache:
1001 fcache[fn] = repo.file(fn)
1001 fcache[fn] = repo.file(fn)
1002 return fcache[fn]
1002 return fcache[fn]
1003
1003
1004 def matchlines(body):
1004 def matchlines(body):
1005 begin = 0
1005 begin = 0
1006 linenum = 0
1006 linenum = 0
1007 while True:
1007 while True:
1008 match = regexp.search(body, begin)
1008 match = regexp.search(body, begin)
1009 if not match:
1009 if not match:
1010 break
1010 break
1011 mstart, mend = match.span()
1011 mstart, mend = match.span()
1012 linenum += body.count('\n', begin, mstart) + 1
1012 linenum += body.count('\n', begin, mstart) + 1
1013 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1013 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1014 lend = body.find('\n', mend)
1014 lend = body.find('\n', mend)
1015 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1015 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1016 begin = lend + 1
1016 begin = lend + 1
1017
1017
1018 class linestate(object):
1018 class linestate(object):
1019 def __init__(self, line, linenum, colstart, colend):
1019 def __init__(self, line, linenum, colstart, colend):
1020 self.line = line
1020 self.line = line
1021 self.linenum = linenum
1021 self.linenum = linenum
1022 self.colstart = colstart
1022 self.colstart = colstart
1023 self.colend = colend
1023 self.colend = colend
1024
1024
1025 def __eq__(self, other):
1025 def __eq__(self, other):
1026 return self.line == other.line
1026 return self.line == other.line
1027
1027
1028 matches = {}
1028 matches = {}
1029 copies = {}
1029 copies = {}
1030 def grepbody(fn, rev, body):
1030 def grepbody(fn, rev, body):
1031 matches[rev].setdefault(fn, [])
1031 matches[rev].setdefault(fn, [])
1032 m = matches[rev][fn]
1032 m = matches[rev][fn]
1033 for lnum, cstart, cend, line in matchlines(body):
1033 for lnum, cstart, cend, line in matchlines(body):
1034 s = linestate(line, lnum, cstart, cend)
1034 s = linestate(line, lnum, cstart, cend)
1035 m.append(s)
1035 m.append(s)
1036
1036
1037 def difflinestates(a, b):
1037 def difflinestates(a, b):
1038 sm = difflib.SequenceMatcher(None, a, b)
1038 sm = difflib.SequenceMatcher(None, a, b)
1039 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1039 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1040 if tag == 'insert':
1040 if tag == 'insert':
1041 for i in xrange(blo, bhi):
1041 for i in xrange(blo, bhi):
1042 yield ('+', b[i])
1042 yield ('+', b[i])
1043 elif tag == 'delete':
1043 elif tag == 'delete':
1044 for i in xrange(alo, ahi):
1044 for i in xrange(alo, ahi):
1045 yield ('-', a[i])
1045 yield ('-', a[i])
1046 elif tag == 'replace':
1046 elif tag == 'replace':
1047 for i in xrange(alo, ahi):
1047 for i in xrange(alo, ahi):
1048 yield ('-', a[i])
1048 yield ('-', a[i])
1049 for i in xrange(blo, bhi):
1049 for i in xrange(blo, bhi):
1050 yield ('+', b[i])
1050 yield ('+', b[i])
1051
1051
1052 prev = {}
1052 prev = {}
1053 def display(fn, rev, states, prevstates):
1053 def display(fn, rev, states, prevstates):
1054 datefunc = ui.quiet and util.shortdate or util.datestr
1054 datefunc = ui.quiet and util.shortdate or util.datestr
1055 found = False
1055 found = False
1056 filerevmatches = {}
1056 filerevmatches = {}
1057 r = prev.get(fn, -1)
1057 r = prev.get(fn, -1)
1058 if opts['all']:
1058 if opts['all']:
1059 iter = difflinestates(states, prevstates)
1059 iter = difflinestates(states, prevstates)
1060 else:
1060 else:
1061 iter = [('', l) for l in prevstates]
1061 iter = [('', l) for l in prevstates]
1062 for change, l in iter:
1062 for change, l in iter:
1063 cols = [fn, str(r)]
1063 cols = [fn, str(r)]
1064 if opts['line_number']:
1064 if opts['line_number']:
1065 cols.append(str(l.linenum))
1065 cols.append(str(l.linenum))
1066 if opts['all']:
1066 if opts['all']:
1067 cols.append(change)
1067 cols.append(change)
1068 if opts['user']:
1068 if opts['user']:
1069 cols.append(ui.shortuser(get(r)[1]))
1069 cols.append(ui.shortuser(get(r)[1]))
1070 if opts.get('date'):
1070 if opts.get('date'):
1071 cols.append(datefunc(get(r)[2]))
1071 cols.append(datefunc(get(r)[2]))
1072 if opts['files_with_matches']:
1072 if opts['files_with_matches']:
1073 c = (fn, r)
1073 c = (fn, r)
1074 if c in filerevmatches:
1074 if c in filerevmatches:
1075 continue
1075 continue
1076 filerevmatches[c] = 1
1076 filerevmatches[c] = 1
1077 else:
1077 else:
1078 cols.append(l.line)
1078 cols.append(l.line)
1079 ui.write(sep.join(cols), eol)
1079 ui.write(sep.join(cols), eol)
1080 found = True
1080 found = True
1081 return found
1081 return found
1082
1082
1083 fstate = {}
1083 fstate = {}
1084 skip = {}
1084 skip = {}
1085 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1085 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1086 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1086 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1087 found = False
1087 found = False
1088 follow = opts.get('follow')
1088 follow = opts.get('follow')
1089 for st, rev, fns in changeiter:
1089 for st, rev, fns in changeiter:
1090 if st == 'window':
1090 if st == 'window':
1091 matches.clear()
1091 matches.clear()
1092 elif st == 'add':
1092 elif st == 'add':
1093 ctx = repo.changectx(rev)
1093 ctx = repo.changectx(rev)
1094 matches[rev] = {}
1094 matches[rev] = {}
1095 for fn in fns:
1095 for fn in fns:
1096 if fn in skip:
1096 if fn in skip:
1097 continue
1097 continue
1098 try:
1098 try:
1099 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1099 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1100 fstate.setdefault(fn, [])
1100 fstate.setdefault(fn, [])
1101 if follow:
1101 if follow:
1102 copied = getfile(fn).renamed(ctx.filenode(fn))
1102 copied = getfile(fn).renamed(ctx.filenode(fn))
1103 if copied:
1103 if copied:
1104 copies.setdefault(rev, {})[fn] = copied[0]
1104 copies.setdefault(rev, {})[fn] = copied[0]
1105 except revlog.LookupError:
1105 except revlog.LookupError:
1106 pass
1106 pass
1107 elif st == 'iter':
1107 elif st == 'iter':
1108 states = matches[rev].items()
1108 states = matches[rev].items()
1109 states.sort()
1109 states.sort()
1110 for fn, m in states:
1110 for fn, m in states:
1111 copy = copies.get(rev, {}).get(fn)
1111 copy = copies.get(rev, {}).get(fn)
1112 if fn in skip:
1112 if fn in skip:
1113 if copy:
1113 if copy:
1114 skip[copy] = True
1114 skip[copy] = True
1115 continue
1115 continue
1116 if fn in prev or fstate[fn]:
1116 if fn in prev or fstate[fn]:
1117 r = display(fn, rev, m, fstate[fn])
1117 r = display(fn, rev, m, fstate[fn])
1118 found = found or r
1118 found = found or r
1119 if r and not opts['all']:
1119 if r and not opts['all']:
1120 skip[fn] = True
1120 skip[fn] = True
1121 if copy:
1121 if copy:
1122 skip[copy] = True
1122 skip[copy] = True
1123 fstate[fn] = m
1123 fstate[fn] = m
1124 if copy:
1124 if copy:
1125 fstate[copy] = m
1125 fstate[copy] = m
1126 prev[fn] = rev
1126 prev[fn] = rev
1127
1127
1128 fstate = fstate.items()
1128 fstate = fstate.items()
1129 fstate.sort()
1129 fstate.sort()
1130 for fn, state in fstate:
1130 for fn, state in fstate:
1131 if fn in skip:
1131 if fn in skip:
1132 continue
1132 continue
1133 if fn not in copies.get(prev[fn], {}):
1133 if fn not in copies.get(prev[fn], {}):
1134 found = display(fn, rev, {}, state) or found
1134 found = display(fn, rev, {}, state) or found
1135 return (not found and 1) or 0
1135 return (not found and 1) or 0
1136
1136
1137 def heads(ui, repo, *branchrevs, **opts):
1137 def heads(ui, repo, *branchrevs, **opts):
1138 """show current repository heads or show branch heads
1138 """show current repository heads or show branch heads
1139
1139
1140 With no arguments, show all repository head changesets.
1140 With no arguments, show all repository head changesets.
1141
1141
1142 If branch or revisions names are given this will show the heads of
1142 If branch or revisions names are given this will show the heads of
1143 the specified branches or the branches those revisions are tagged
1143 the specified branches or the branches those revisions are tagged
1144 with.
1144 with.
1145
1145
1146 Repository "heads" are changesets that don't have child
1146 Repository "heads" are changesets that don't have child
1147 changesets. They are where development generally takes place and
1147 changesets. They are where development generally takes place and
1148 are the usual targets for update and merge operations.
1148 are the usual targets for update and merge operations.
1149
1149
1150 Branch heads are changesets that have a given branch tag, but have
1150 Branch heads are changesets that have a given branch tag, but have
1151 no child changesets with that tag. They are usually where
1151 no child changesets with that tag. They are usually where
1152 development on the given branch takes place.
1152 development on the given branch takes place.
1153 """
1153 """
1154 if opts['rev']:
1154 if opts['rev']:
1155 start = repo.lookup(opts['rev'])
1155 start = repo.lookup(opts['rev'])
1156 else:
1156 else:
1157 start = None
1157 start = None
1158 if not branchrevs:
1158 if not branchrevs:
1159 # Assume we're looking repo-wide heads if no revs were specified.
1159 # Assume we're looking repo-wide heads if no revs were specified.
1160 heads = repo.heads(start)
1160 heads = repo.heads(start)
1161 else:
1161 else:
1162 heads = []
1162 heads = []
1163 visitedset = util.set()
1163 visitedset = util.set()
1164 for branchrev in branchrevs:
1164 for branchrev in branchrevs:
1165 branch = repo.changectx(branchrev).branch()
1165 branch = repo.changectx(branchrev).branch()
1166 if branch in visitedset:
1166 if branch in visitedset:
1167 continue
1167 continue
1168 visitedset.add(branch)
1168 visitedset.add(branch)
1169 bheads = repo.branchheads(branch, start)
1169 bheads = repo.branchheads(branch, start)
1170 if not bheads:
1170 if not bheads:
1171 if branch != branchrev:
1171 if branch != branchrev:
1172 ui.warn(_("no changes on branch %s containing %s are "
1172 ui.warn(_("no changes on branch %s containing %s are "
1173 "reachable from %s\n")
1173 "reachable from %s\n")
1174 % (branch, branchrev, opts['rev']))
1174 % (branch, branchrev, opts['rev']))
1175 else:
1175 else:
1176 ui.warn(_("no changes on branch %s are reachable from %s\n")
1176 ui.warn(_("no changes on branch %s are reachable from %s\n")
1177 % (branch, opts['rev']))
1177 % (branch, opts['rev']))
1178 heads.extend(bheads)
1178 heads.extend(bheads)
1179 if not heads:
1179 if not heads:
1180 return 1
1180 return 1
1181 displayer = cmdutil.show_changeset(ui, repo, opts)
1181 displayer = cmdutil.show_changeset(ui, repo, opts)
1182 for n in heads:
1182 for n in heads:
1183 displayer.show(changenode=n)
1183 displayer.show(changenode=n)
1184
1184
1185 def help_(ui, name=None, with_version=False):
1185 def help_(ui, name=None, with_version=False):
1186 """show help for a command, extension, or list of commands
1186 """show help for a command, extension, or list of commands
1187
1187
1188 With no arguments, print a list of commands and short help.
1188 With no arguments, print a list of commands and short help.
1189
1189
1190 Given a command name, print help for that command.
1190 Given a command name, print help for that command.
1191
1191
1192 Given an extension name, print help for that extension, and the
1192 Given an extension name, print help for that extension, and the
1193 commands it provides."""
1193 commands it provides."""
1194 option_lists = []
1194 option_lists = []
1195
1195
1196 def addglobalopts(aliases):
1196 def addglobalopts(aliases):
1197 if ui.verbose:
1197 if ui.verbose:
1198 option_lists.append((_("global options:"), globalopts))
1198 option_lists.append((_("global options:"), globalopts))
1199 if name == 'shortlist':
1199 if name == 'shortlist':
1200 option_lists.append((_('use "hg help" for the full list '
1200 option_lists.append((_('use "hg help" for the full list '
1201 'of commands'), ()))
1201 'of commands'), ()))
1202 else:
1202 else:
1203 if name == 'shortlist':
1203 if name == 'shortlist':
1204 msg = _('use "hg help" for the full list of commands '
1204 msg = _('use "hg help" for the full list of commands '
1205 'or "hg -v" for details')
1205 'or "hg -v" for details')
1206 elif aliases:
1206 elif aliases:
1207 msg = _('use "hg -v help%s" to show aliases and '
1207 msg = _('use "hg -v help%s" to show aliases and '
1208 'global options') % (name and " " + name or "")
1208 'global options') % (name and " " + name or "")
1209 else:
1209 else:
1210 msg = _('use "hg -v help %s" to show global options') % name
1210 msg = _('use "hg -v help %s" to show global options') % name
1211 option_lists.append((msg, ()))
1211 option_lists.append((msg, ()))
1212
1212
1213 def helpcmd(name):
1213 def helpcmd(name):
1214 if with_version:
1214 if with_version:
1215 version_(ui)
1215 version_(ui)
1216 ui.write('\n')
1216 ui.write('\n')
1217 aliases, i = cmdutil.findcmd(ui, name, table)
1217 aliases, i = cmdutil.findcmd(ui, name, table)
1218 # synopsis
1218 # synopsis
1219 ui.write("%s\n" % i[2])
1219 ui.write("%s\n" % i[2])
1220
1220
1221 # aliases
1221 # aliases
1222 if not ui.quiet and len(aliases) > 1:
1222 if not ui.quiet and len(aliases) > 1:
1223 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1223 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1224
1224
1225 # description
1225 # description
1226 doc = i[0].__doc__
1226 doc = i[0].__doc__
1227 if not doc:
1227 if not doc:
1228 doc = _("(No help text available)")
1228 doc = _("(No help text available)")
1229 if ui.quiet:
1229 if ui.quiet:
1230 doc = doc.splitlines(0)[0]
1230 doc = doc.splitlines(0)[0]
1231 ui.write("\n%s\n" % doc.rstrip())
1231 ui.write("\n%s\n" % doc.rstrip())
1232
1232
1233 if not ui.quiet:
1233 if not ui.quiet:
1234 # options
1234 # options
1235 if i[1]:
1235 if i[1]:
1236 option_lists.append((_("options:\n"), i[1]))
1236 option_lists.append((_("options:\n"), i[1]))
1237
1237
1238 addglobalopts(False)
1238 addglobalopts(False)
1239
1239
1240 def helplist(header, select=None):
1240 def helplist(header, select=None):
1241 h = {}
1241 h = {}
1242 cmds = {}
1242 cmds = {}
1243 for c, e in table.items():
1243 for c, e in table.items():
1244 f = c.split("|", 1)[0]
1244 f = c.split("|", 1)[0]
1245 if select and not select(f):
1245 if select and not select(f):
1246 continue
1246 continue
1247 if name == "shortlist" and not f.startswith("^"):
1247 if name == "shortlist" and not f.startswith("^"):
1248 continue
1248 continue
1249 f = f.lstrip("^")
1249 f = f.lstrip("^")
1250 if not ui.debugflag and f.startswith("debug"):
1250 if not ui.debugflag and f.startswith("debug"):
1251 continue
1251 continue
1252 doc = e[0].__doc__
1252 doc = e[0].__doc__
1253 if not doc:
1253 if not doc:
1254 doc = _("(No help text available)")
1254 doc = _("(No help text available)")
1255 h[f] = doc.splitlines(0)[0].rstrip()
1255 h[f] = doc.splitlines(0)[0].rstrip()
1256 cmds[f] = c.lstrip("^")
1256 cmds[f] = c.lstrip("^")
1257
1257
1258 if not h:
1258 if not h:
1259 ui.status(_('no commands defined\n'))
1259 ui.status(_('no commands defined\n'))
1260 return
1260 return
1261
1261
1262 ui.status(header)
1262 ui.status(header)
1263 fns = h.keys()
1263 fns = h.keys()
1264 fns.sort()
1264 fns.sort()
1265 m = max(map(len, fns))
1265 m = max(map(len, fns))
1266 for f in fns:
1266 for f in fns:
1267 if ui.verbose:
1267 if ui.verbose:
1268 commands = cmds[f].replace("|",", ")
1268 commands = cmds[f].replace("|",", ")
1269 ui.write(" %s:\n %s\n"%(commands, h[f]))
1269 ui.write(" %s:\n %s\n"%(commands, h[f]))
1270 else:
1270 else:
1271 ui.write(' %-*s %s\n' % (m, f, h[f]))
1271 ui.write(' %-*s %s\n' % (m, f, h[f]))
1272
1272
1273 if not ui.quiet:
1273 if not ui.quiet:
1274 addglobalopts(True)
1274 addglobalopts(True)
1275
1275
1276 def helptopic(name):
1276 def helptopic(name):
1277 v = None
1277 v = None
1278 for i in help.helptable:
1278 for i in help.helptable:
1279 l = i.split('|')
1279 l = i.split('|')
1280 if name in l:
1280 if name in l:
1281 v = i
1281 v = i
1282 header = l[-1]
1282 header = l[-1]
1283 if not v:
1283 if not v:
1284 raise cmdutil.UnknownCommand(name)
1284 raise cmdutil.UnknownCommand(name)
1285
1285
1286 # description
1286 # description
1287 doc = help.helptable[v]
1287 doc = help.helptable[v]
1288 if not doc:
1288 if not doc:
1289 doc = _("(No help text available)")
1289 doc = _("(No help text available)")
1290 if callable(doc):
1290 if callable(doc):
1291 doc = doc()
1291 doc = doc()
1292
1292
1293 ui.write("%s\n" % header)
1293 ui.write("%s\n" % header)
1294 ui.write("%s\n" % doc.rstrip())
1294 ui.write("%s\n" % doc.rstrip())
1295
1295
1296 def helpext(name):
1296 def helpext(name):
1297 try:
1297 try:
1298 mod = extensions.find(name)
1298 mod = extensions.find(name)
1299 except KeyError:
1299 except KeyError:
1300 raise cmdutil.UnknownCommand(name)
1300 raise cmdutil.UnknownCommand(name)
1301
1301
1302 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1302 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1303 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1303 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1304 for d in doc[1:]:
1304 for d in doc[1:]:
1305 ui.write(d, '\n')
1305 ui.write(d, '\n')
1306
1306
1307 ui.status('\n')
1307 ui.status('\n')
1308
1308
1309 try:
1309 try:
1310 ct = mod.cmdtable
1310 ct = mod.cmdtable
1311 except AttributeError:
1311 except AttributeError:
1312 ct = {}
1312 ct = {}
1313
1313
1314 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1314 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1315 helplist(_('list of commands:\n\n'), modcmds.has_key)
1315 helplist(_('list of commands:\n\n'), modcmds.has_key)
1316
1316
1317 if name and name != 'shortlist':
1317 if name and name != 'shortlist':
1318 i = None
1318 i = None
1319 for f in (helpcmd, helptopic, helpext):
1319 for f in (helpcmd, helptopic, helpext):
1320 try:
1320 try:
1321 f(name)
1321 f(name)
1322 i = None
1322 i = None
1323 break
1323 break
1324 except cmdutil.UnknownCommand, inst:
1324 except cmdutil.UnknownCommand, inst:
1325 i = inst
1325 i = inst
1326 if i:
1326 if i:
1327 raise i
1327 raise i
1328
1328
1329 else:
1329 else:
1330 # program name
1330 # program name
1331 if ui.verbose or with_version:
1331 if ui.verbose or with_version:
1332 version_(ui)
1332 version_(ui)
1333 else:
1333 else:
1334 ui.status(_("Mercurial Distributed SCM\n"))
1334 ui.status(_("Mercurial Distributed SCM\n"))
1335 ui.status('\n')
1335 ui.status('\n')
1336
1336
1337 # list of commands
1337 # list of commands
1338 if name == "shortlist":
1338 if name == "shortlist":
1339 header = _('basic commands:\n\n')
1339 header = _('basic commands:\n\n')
1340 else:
1340 else:
1341 header = _('list of commands:\n\n')
1341 header = _('list of commands:\n\n')
1342
1342
1343 helplist(header)
1343 helplist(header)
1344
1344
1345 # list all option lists
1345 # list all option lists
1346 opt_output = []
1346 opt_output = []
1347 for title, options in option_lists:
1347 for title, options in option_lists:
1348 opt_output.append(("\n%s" % title, None))
1348 opt_output.append(("\n%s" % title, None))
1349 for shortopt, longopt, default, desc in options:
1349 for shortopt, longopt, default, desc in options:
1350 if "DEPRECATED" in desc and not ui.verbose: continue
1350 if "DEPRECATED" in desc and not ui.verbose: continue
1351 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1351 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1352 longopt and " --%s" % longopt),
1352 longopt and " --%s" % longopt),
1353 "%s%s" % (desc,
1353 "%s%s" % (desc,
1354 default
1354 default
1355 and _(" (default: %s)") % default
1355 and _(" (default: %s)") % default
1356 or "")))
1356 or "")))
1357
1357
1358 if opt_output:
1358 if opt_output:
1359 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1359 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1360 for first, second in opt_output:
1360 for first, second in opt_output:
1361 if second:
1361 if second:
1362 ui.write(" %-*s %s\n" % (opts_len, first, second))
1362 ui.write(" %-*s %s\n" % (opts_len, first, second))
1363 else:
1363 else:
1364 ui.write("%s\n" % first)
1364 ui.write("%s\n" % first)
1365
1365
1366 def identify(ui, repo, source=None,
1366 def identify(ui, repo, source=None,
1367 rev=None, num=None, id=None, branch=None, tags=None):
1367 rev=None, num=None, id=None, branch=None, tags=None):
1368 """identify the working copy or specified revision
1368 """identify the working copy or specified revision
1369
1369
1370 With no revision, print a summary of the current state of the repo.
1370 With no revision, print a summary of the current state of the repo.
1371
1371
1372 With a path, do a lookup in another repository.
1372 With a path, do a lookup in another repository.
1373
1373
1374 This summary identifies the repository state using one or two parent
1374 This summary identifies the repository state using one or two parent
1375 hash identifiers, followed by a "+" if there are uncommitted changes
1375 hash identifiers, followed by a "+" if there are uncommitted changes
1376 in the working directory, a list of tags for this revision and a branch
1376 in the working directory, a list of tags for this revision and a branch
1377 name for non-default branches.
1377 name for non-default branches.
1378 """
1378 """
1379
1379
1380 if not repo and not source:
1380 if not repo and not source:
1381 raise util.Abort(_("There is no Mercurial repository here "
1381 raise util.Abort(_("There is no Mercurial repository here "
1382 "(.hg not found)"))
1382 "(.hg not found)"))
1383
1383
1384 hexfunc = ui.debugflag and hex or short
1384 hexfunc = ui.debugflag and hex or short
1385 default = not (num or id or branch or tags)
1385 default = not (num or id or branch or tags)
1386 output = []
1386 output = []
1387
1387
1388 if source:
1388 if source:
1389 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1389 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1390 srepo = hg.repository(ui, source)
1390 srepo = hg.repository(ui, source)
1391 if not rev and revs:
1391 if not rev and revs:
1392 rev = revs[0]
1392 rev = revs[0]
1393 if not rev:
1393 if not rev:
1394 rev = "tip"
1394 rev = "tip"
1395 if num or branch or tags:
1395 if num or branch or tags:
1396 raise util.Abort(
1396 raise util.Abort(
1397 "can't query remote revision number, branch, or tags")
1397 "can't query remote revision number, branch, or tags")
1398 output = [hexfunc(srepo.lookup(rev))]
1398 output = [hexfunc(srepo.lookup(rev))]
1399 elif not rev:
1399 elif not rev:
1400 ctx = repo.workingctx()
1400 ctx = repo.workingctx()
1401 parents = ctx.parents()
1401 parents = ctx.parents()
1402 changed = False
1402 changed = False
1403 if default or id or num:
1403 if default or id or num:
1404 changed = ctx.files() + ctx.deleted()
1404 changed = ctx.files() + ctx.deleted()
1405 if default or id:
1405 if default or id:
1406 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1406 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1407 (changed) and "+" or "")]
1407 (changed) and "+" or "")]
1408 if num:
1408 if num:
1409 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1409 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1410 (changed) and "+" or ""))
1410 (changed) and "+" or ""))
1411 else:
1411 else:
1412 ctx = repo.changectx(rev)
1412 ctx = repo.changectx(rev)
1413 if default or id:
1413 if default or id:
1414 output = [hexfunc(ctx.node())]
1414 output = [hexfunc(ctx.node())]
1415 if num:
1415 if num:
1416 output.append(str(ctx.rev()))
1416 output.append(str(ctx.rev()))
1417
1417
1418 if not source and default and not ui.quiet:
1418 if not source and default and not ui.quiet:
1419 b = util.tolocal(ctx.branch())
1419 b = util.tolocal(ctx.branch())
1420 if b != 'default':
1420 if b != 'default':
1421 output.append("(%s)" % b)
1421 output.append("(%s)" % b)
1422
1422
1423 # multiple tags for a single parent separated by '/'
1423 # multiple tags for a single parent separated by '/'
1424 t = "/".join(ctx.tags())
1424 t = "/".join(ctx.tags())
1425 if t:
1425 if t:
1426 output.append(t)
1426 output.append(t)
1427
1427
1428 if branch:
1428 if branch:
1429 output.append(util.tolocal(ctx.branch()))
1429 output.append(util.tolocal(ctx.branch()))
1430
1430
1431 if tags:
1431 if tags:
1432 output.extend(ctx.tags())
1432 output.extend(ctx.tags())
1433
1433
1434 ui.write("%s\n" % ' '.join(output))
1434 ui.write("%s\n" % ' '.join(output))
1435
1435
1436 def import_(ui, repo, patch1, *patches, **opts):
1436 def import_(ui, repo, patch1, *patches, **opts):
1437 """import an ordered set of patches
1437 """import an ordered set of patches
1438
1438
1439 Import a list of patches and commit them individually.
1439 Import a list of patches and commit them individually.
1440
1440
1441 If there are outstanding changes in the working directory, import
1441 If there are outstanding changes in the working directory, import
1442 will abort unless given the -f flag.
1442 will abort unless given the -f flag.
1443
1443
1444 You can import a patch straight from a mail message. Even patches
1444 You can import a patch straight from a mail message. Even patches
1445 as attachments work (body part must be type text/plain or
1445 as attachments work (body part must be type text/plain or
1446 text/x-patch to be used). From and Subject headers of email
1446 text/x-patch to be used). From and Subject headers of email
1447 message are used as default committer and commit message. All
1447 message are used as default committer and commit message. All
1448 text/plain body parts before first diff are added to commit
1448 text/plain body parts before first diff are added to commit
1449 message.
1449 message.
1450
1450
1451 If the imported patch was generated by hg export, user and description
1451 If the imported patch was generated by hg export, user and description
1452 from patch override values from message headers and body. Values
1452 from patch override values from message headers and body. Values
1453 given on command line with -m and -u override these.
1453 given on command line with -m and -u override these.
1454
1454
1455 If --exact is specified, import will set the working directory
1455 If --exact is specified, import will set the working directory
1456 to the parent of each patch before applying it, and will abort
1456 to the parent of each patch before applying it, and will abort
1457 if the resulting changeset has a different ID than the one
1457 if the resulting changeset has a different ID than the one
1458 recorded in the patch. This may happen due to character set
1458 recorded in the patch. This may happen due to character set
1459 problems or other deficiencies in the text patch format.
1459 problems or other deficiencies in the text patch format.
1460
1460
1461 To read a patch from standard input, use patch name "-".
1461 To read a patch from standard input, use patch name "-".
1462 See 'hg help dates' for a list of formats valid for -d/--date.
1462 See 'hg help dates' for a list of formats valid for -d/--date.
1463 """
1463 """
1464 patches = (patch1,) + patches
1464 patches = (patch1,) + patches
1465
1465
1466 date = opts.get('date')
1466 date = opts.get('date')
1467 if date:
1467 if date:
1468 opts['date'] = util.parsedate(date)
1468 opts['date'] = util.parsedate(date)
1469
1469
1470 if opts.get('exact') or not opts['force']:
1470 if opts.get('exact') or not opts['force']:
1471 cmdutil.bail_if_changed(repo)
1471 cmdutil.bail_if_changed(repo)
1472
1472
1473 d = opts["base"]
1473 d = opts["base"]
1474 strip = opts["strip"]
1474 strip = opts["strip"]
1475 wlock = lock = None
1475 wlock = lock = None
1476 try:
1476 try:
1477 wlock = repo.wlock()
1477 wlock = repo.wlock()
1478 lock = repo.lock()
1478 lock = repo.lock()
1479 for p in patches:
1479 for p in patches:
1480 pf = os.path.join(d, p)
1480 pf = os.path.join(d, p)
1481
1481
1482 if pf == '-':
1482 if pf == '-':
1483 ui.status(_("applying patch from stdin\n"))
1483 ui.status(_("applying patch from stdin\n"))
1484 data = patch.extract(ui, sys.stdin)
1484 data = patch.extract(ui, sys.stdin)
1485 else:
1485 else:
1486 ui.status(_("applying %s\n") % p)
1486 ui.status(_("applying %s\n") % p)
1487 if os.path.exists(pf):
1487 if os.path.exists(pf):
1488 data = patch.extract(ui, file(pf, 'rb'))
1488 data = patch.extract(ui, file(pf, 'rb'))
1489 else:
1489 else:
1490 data = patch.extract(ui, urllib.urlopen(pf))
1490 data = patch.extract(ui, urllib.urlopen(pf))
1491 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1491 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1492
1492
1493 if tmpname is None:
1493 if tmpname is None:
1494 raise util.Abort(_('no diffs found'))
1494 raise util.Abort(_('no diffs found'))
1495
1495
1496 try:
1496 try:
1497 cmdline_message = cmdutil.logmessage(opts)
1497 cmdline_message = cmdutil.logmessage(opts)
1498 if cmdline_message:
1498 if cmdline_message:
1499 # pickup the cmdline msg
1499 # pickup the cmdline msg
1500 message = cmdline_message
1500 message = cmdline_message
1501 elif message:
1501 elif message:
1502 # pickup the patch msg
1502 # pickup the patch msg
1503 message = message.strip()
1503 message = message.strip()
1504 else:
1504 else:
1505 # launch the editor
1505 # launch the editor
1506 message = None
1506 message = None
1507 ui.debug(_('message:\n%s\n') % message)
1507 ui.debug(_('message:\n%s\n') % message)
1508
1508
1509 wp = repo.workingctx().parents()
1509 wp = repo.workingctx().parents()
1510 if opts.get('exact'):
1510 if opts.get('exact'):
1511 if not nodeid or not p1:
1511 if not nodeid or not p1:
1512 raise util.Abort(_('not a mercurial patch'))
1512 raise util.Abort(_('not a mercurial patch'))
1513 p1 = repo.lookup(p1)
1513 p1 = repo.lookup(p1)
1514 p2 = repo.lookup(p2 or hex(nullid))
1514 p2 = repo.lookup(p2 or hex(nullid))
1515
1515
1516 if p1 != wp[0].node():
1516 if p1 != wp[0].node():
1517 hg.clean(repo, p1)
1517 hg.clean(repo, p1)
1518 repo.dirstate.setparents(p1, p2)
1518 repo.dirstate.setparents(p1, p2)
1519 elif p2:
1519 elif p2:
1520 try:
1520 try:
1521 p1 = repo.lookup(p1)
1521 p1 = repo.lookup(p1)
1522 p2 = repo.lookup(p2)
1522 p2 = repo.lookup(p2)
1523 if p1 == wp[0].node():
1523 if p1 == wp[0].node():
1524 repo.dirstate.setparents(p1, p2)
1524 repo.dirstate.setparents(p1, p2)
1525 except hg.RepoError:
1525 except hg.RepoError:
1526 pass
1526 pass
1527 if opts.get('exact') or opts.get('import_branch'):
1527 if opts.get('exact') or opts.get('import_branch'):
1528 repo.dirstate.setbranch(branch or 'default')
1528 repo.dirstate.setbranch(branch or 'default')
1529
1529
1530 files = {}
1530 files = {}
1531 try:
1531 try:
1532 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1532 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1533 files=files)
1533 files=files)
1534 finally:
1534 finally:
1535 files = patch.updatedir(ui, repo, files)
1535 files = patch.updatedir(ui, repo, files)
1536 if not opts.get('no_commit'):
1536 if not opts.get('no_commit'):
1537 n = repo.commit(files, message, opts.get('user') or user,
1537 n = repo.commit(files, message, opts.get('user') or user,
1538 opts.get('date') or date)
1538 opts.get('date') or date)
1539 if opts.get('exact'):
1539 if opts.get('exact'):
1540 if hex(n) != nodeid:
1540 if hex(n) != nodeid:
1541 repo.rollback()
1541 repo.rollback()
1542 raise util.Abort(_('patch is damaged'
1542 raise util.Abort(_('patch is damaged'
1543 ' or loses information'))
1543 ' or loses information'))
1544 # Force a dirstate write so that the next transaction
1544 # Force a dirstate write so that the next transaction
1545 # backups an up-do-date file.
1545 # backups an up-do-date file.
1546 repo.dirstate.write()
1546 repo.dirstate.write()
1547 finally:
1547 finally:
1548 os.unlink(tmpname)
1548 os.unlink(tmpname)
1549 finally:
1549 finally:
1550 del lock, wlock
1550 del lock, wlock
1551
1551
1552 def incoming(ui, repo, source="default", **opts):
1552 def incoming(ui, repo, source="default", **opts):
1553 """show new changesets found in source
1553 """show new changesets found in source
1554
1554
1555 Show new changesets found in the specified path/URL or the default
1555 Show new changesets found in the specified path/URL or the default
1556 pull location. These are the changesets that would be pulled if a pull
1556 pull location. These are the changesets that would be pulled if a pull
1557 was requested.
1557 was requested.
1558
1558
1559 For remote repository, using --bundle avoids downloading the changesets
1559 For remote repository, using --bundle avoids downloading the changesets
1560 twice if the incoming is followed by a pull.
1560 twice if the incoming is followed by a pull.
1561
1561
1562 See pull for valid source format details.
1562 See pull for valid source format details.
1563 """
1563 """
1564 limit = cmdutil.loglimit(opts)
1564 limit = cmdutil.loglimit(opts)
1565 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
1565 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
1566 cmdutil.setremoteconfig(ui, opts)
1566 cmdutil.setremoteconfig(ui, opts)
1567
1567
1568 other = hg.repository(ui, source)
1568 other = hg.repository(ui, source)
1569 ui.status(_('comparing with %s\n') % util.hidepassword(source))
1569 ui.status(_('comparing with %s\n') % util.hidepassword(source))
1570 if revs:
1570 if revs:
1571 revs = [other.lookup(rev) for rev in revs]
1571 revs = [other.lookup(rev) for rev in revs]
1572 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
1572 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
1573 if not incoming:
1573 if not incoming:
1574 try:
1574 try:
1575 os.unlink(opts["bundle"])
1575 os.unlink(opts["bundle"])
1576 except:
1576 except:
1577 pass
1577 pass
1578 ui.status(_("no changes found\n"))
1578 ui.status(_("no changes found\n"))
1579 return 1
1579 return 1
1580
1580
1581 cleanup = None
1581 cleanup = None
1582 try:
1582 try:
1583 fname = opts["bundle"]
1583 fname = opts["bundle"]
1584 if fname or not other.local():
1584 if fname or not other.local():
1585 # create a bundle (uncompressed if other repo is not local)
1585 # create a bundle (uncompressed if other repo is not local)
1586 if revs is None:
1586 if revs is None:
1587 cg = other.changegroup(incoming, "incoming")
1587 cg = other.changegroup(incoming, "incoming")
1588 else:
1588 else:
1589 cg = other.changegroupsubset(incoming, revs, 'incoming')
1589 cg = other.changegroupsubset(incoming, revs, 'incoming')
1590 bundletype = other.local() and "HG10BZ" or "HG10UN"
1590 bundletype = other.local() and "HG10BZ" or "HG10UN"
1591 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1591 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1592 # keep written bundle?
1592 # keep written bundle?
1593 if opts["bundle"]:
1593 if opts["bundle"]:
1594 cleanup = None
1594 cleanup = None
1595 if not other.local():
1595 if not other.local():
1596 # use the created uncompressed bundlerepo
1596 # use the created uncompressed bundlerepo
1597 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1597 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1598
1598
1599 o = other.changelog.nodesbetween(incoming, revs)[0]
1599 o = other.changelog.nodesbetween(incoming, revs)[0]
1600 if opts['newest_first']:
1600 if opts['newest_first']:
1601 o.reverse()
1601 o.reverse()
1602 displayer = cmdutil.show_changeset(ui, other, opts)
1602 displayer = cmdutil.show_changeset(ui, other, opts)
1603 count = 0
1603 count = 0
1604 for n in o:
1604 for n in o:
1605 if count >= limit:
1605 if count >= limit:
1606 break
1606 break
1607 parents = [p for p in other.changelog.parents(n) if p != nullid]
1607 parents = [p for p in other.changelog.parents(n) if p != nullid]
1608 if opts['no_merges'] and len(parents) == 2:
1608 if opts['no_merges'] and len(parents) == 2:
1609 continue
1609 continue
1610 count += 1
1610 count += 1
1611 displayer.show(changenode=n)
1611 displayer.show(changenode=n)
1612 finally:
1612 finally:
1613 if hasattr(other, 'close'):
1613 if hasattr(other, 'close'):
1614 other.close()
1614 other.close()
1615 if cleanup:
1615 if cleanup:
1616 os.unlink(cleanup)
1616 os.unlink(cleanup)
1617
1617
1618 def init(ui, dest=".", **opts):
1618 def init(ui, dest=".", **opts):
1619 """create a new repository in the given directory
1619 """create a new repository in the given directory
1620
1620
1621 Initialize a new repository in the given directory. If the given
1621 Initialize a new repository in the given directory. If the given
1622 directory does not exist, it is created.
1622 directory does not exist, it is created.
1623
1623
1624 If no directory is given, the current directory is used.
1624 If no directory is given, the current directory is used.
1625
1625
1626 It is possible to specify an ssh:// URL as the destination.
1626 It is possible to specify an ssh:// URL as the destination.
1627 Look at the help text for the pull command for important details
1627 Look at the help text for the pull command for important details
1628 about ssh:// URLs.
1628 about ssh:// URLs.
1629 """
1629 """
1630 cmdutil.setremoteconfig(ui, opts)
1630 cmdutil.setremoteconfig(ui, opts)
1631 hg.repository(ui, dest, create=1)
1631 hg.repository(ui, dest, create=1)
1632
1632
1633 def locate(ui, repo, *pats, **opts):
1633 def locate(ui, repo, *pats, **opts):
1634 """locate files matching specific patterns
1634 """locate files matching specific patterns
1635
1635
1636 Print all files under Mercurial control whose names match the
1636 Print all files under Mercurial control whose names match the
1637 given patterns.
1637 given patterns.
1638
1638
1639 This command searches the entire repository by default. To search
1639 This command searches the entire repository by default. To search
1640 just the current directory and its subdirectories, use
1640 just the current directory and its subdirectories, use
1641 "--include .".
1641 "--include .".
1642
1642
1643 If no patterns are given to match, this command prints all file
1643 If no patterns are given to match, this command prints all file
1644 names.
1644 names.
1645
1645
1646 If you want to feed the output of this command into the "xargs"
1646 If you want to feed the output of this command into the "xargs"
1647 command, use the "-0" option to both this command and "xargs".
1647 command, use the "-0" option to both this command and "xargs".
1648 This will avoid the problem of "xargs" treating single filenames
1648 This will avoid the problem of "xargs" treating single filenames
1649 that contain white space as multiple filenames.
1649 that contain white space as multiple filenames.
1650 """
1650 """
1651 end = opts['print0'] and '\0' or '\n'
1651 end = opts['print0'] and '\0' or '\n'
1652 rev = opts['rev']
1652 rev = opts['rev']
1653 if rev:
1653 if rev:
1654 node = repo.lookup(rev)
1654 node = repo.lookup(rev)
1655 else:
1655 else:
1656 node = None
1656 node = None
1657
1657
1658 ret = 1
1658 ret = 1
1659 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1659 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1660 badmatch=util.always,
1660 badmatch=util.always,
1661 default='relglob'):
1661 default='relglob'):
1662 if src == 'b':
1662 if src == 'b':
1663 continue
1663 continue
1664 if not node and abs not in repo.dirstate:
1664 if not node and abs not in repo.dirstate:
1665 continue
1665 continue
1666 if opts['fullpath']:
1666 if opts['fullpath']:
1667 ui.write(os.path.join(repo.root, abs), end)
1667 ui.write(os.path.join(repo.root, abs), end)
1668 else:
1668 else:
1669 ui.write(((pats and rel) or abs), end)
1669 ui.write(((pats and rel) or abs), end)
1670 ret = 0
1670 ret = 0
1671
1671
1672 return ret
1672 return ret
1673
1673
1674 def log(ui, repo, *pats, **opts):
1674 def log(ui, repo, *pats, **opts):
1675 """show revision history of entire repository or files
1675 """show revision history of entire repository or files
1676
1676
1677 Print the revision history of the specified files or the entire
1677 Print the revision history of the specified files or the entire
1678 project.
1678 project.
1679
1679
1680 File history is shown without following rename or copy history of
1680 File history is shown without following rename or copy history of
1681 files. Use -f/--follow with a file name to follow history across
1681 files. Use -f/--follow with a file name to follow history across
1682 renames and copies. --follow without a file name will only show
1682 renames and copies. --follow without a file name will only show
1683 ancestors or descendants of the starting revision. --follow-first
1683 ancestors or descendants of the starting revision. --follow-first
1684 only follows the first parent of merge revisions.
1684 only follows the first parent of merge revisions.
1685
1685
1686 If no revision range is specified, the default is tip:0 unless
1686 If no revision range is specified, the default is tip:0 unless
1687 --follow is set, in which case the working directory parent is
1687 --follow is set, in which case the working directory parent is
1688 used as the starting revision.
1688 used as the starting revision.
1689
1689
1690 See 'hg help dates' for a list of formats valid for -d/--date.
1690 See 'hg help dates' for a list of formats valid for -d/--date.
1691
1691
1692 By default this command outputs: changeset id and hash, tags,
1692 By default this command outputs: changeset id and hash, tags,
1693 non-trivial parents, user, date and time, and a summary for each
1693 non-trivial parents, user, date and time, and a summary for each
1694 commit. When the -v/--verbose switch is used, the list of changed
1694 commit. When the -v/--verbose switch is used, the list of changed
1695 files and full commit message is shown.
1695 files and full commit message is shown.
1696
1696
1697 NOTE: log -p may generate unexpected diff output for merge
1697 NOTE: log -p may generate unexpected diff output for merge
1698 changesets, as it will compare the merge changeset against its
1698 changesets, as it will compare the merge changeset against its
1699 first parent only. Also, the files: list will only reflect files
1699 first parent only. Also, the files: list will only reflect files
1700 that are different from BOTH parents.
1700 that are different from BOTH parents.
1701
1701
1702 """
1702 """
1703
1703
1704 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1704 get = util.cachefunc(lambda r: repo.changectx(r).changeset())
1705 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1705 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1706
1706
1707 limit = cmdutil.loglimit(opts)
1707 limit = cmdutil.loglimit(opts)
1708 count = 0
1708 count = 0
1709
1709
1710 if opts['copies'] and opts['rev']:
1710 if opts['copies'] and opts['rev']:
1711 endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
1711 endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
1712 else:
1712 else:
1713 endrev = repo.changelog.count()
1713 endrev = repo.changelog.count()
1714 rcache = {}
1714 rcache = {}
1715 ncache = {}
1715 ncache = {}
1716 def getrenamed(fn, rev):
1716 def getrenamed(fn, rev):
1717 '''looks up all renames for a file (up to endrev) the first
1717 '''looks up all renames for a file (up to endrev) the first
1718 time the file is given. It indexes on the changerev and only
1718 time the file is given. It indexes on the changerev and only
1719 parses the manifest if linkrev != changerev.
1719 parses the manifest if linkrev != changerev.
1720 Returns rename info for fn at changerev rev.'''
1720 Returns rename info for fn at changerev rev.'''
1721 if fn not in rcache:
1721 if fn not in rcache:
1722 rcache[fn] = {}
1722 rcache[fn] = {}
1723 ncache[fn] = {}
1723 ncache[fn] = {}
1724 fl = repo.file(fn)
1724 fl = repo.file(fn)
1725 for i in xrange(fl.count()):
1725 for i in xrange(fl.count()):
1726 node = fl.node(i)
1726 node = fl.node(i)
1727 lr = fl.linkrev(node)
1727 lr = fl.linkrev(node)
1728 renamed = fl.renamed(node)
1728 renamed = fl.renamed(node)
1729 rcache[fn][lr] = renamed
1729 rcache[fn][lr] = renamed
1730 if renamed:
1730 if renamed:
1731 ncache[fn][node] = renamed
1731 ncache[fn][node] = renamed
1732 if lr >= endrev:
1732 if lr >= endrev:
1733 break
1733 break
1734 if rev in rcache[fn]:
1734 if rev in rcache[fn]:
1735 return rcache[fn][rev]
1735 return rcache[fn][rev]
1736
1736
1737 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1737 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1738 # filectx logic.
1738 # filectx logic.
1739
1739
1740 try:
1740 try:
1741 return repo.changectx(rev).filectx(fn).renamed()
1741 return repo.changectx(rev).filectx(fn).renamed()
1742 except revlog.LookupError:
1742 except revlog.LookupError:
1743 pass
1743 pass
1744 return None
1744 return None
1745
1745
1746 df = False
1746 df = False
1747 if opts["date"]:
1747 if opts["date"]:
1748 df = util.matchdate(opts["date"])
1748 df = util.matchdate(opts["date"])
1749
1749
1750 only_branches = opts['only_branch']
1750 only_branches = opts['only_branch']
1751
1751
1752 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1752 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1753 for st, rev, fns in changeiter:
1753 for st, rev, fns in changeiter:
1754 if st == 'add':
1754 if st == 'add':
1755 changenode = repo.changelog.node(rev)
1755 changenode = repo.changelog.node(rev)
1756 parents = [p for p in repo.changelog.parentrevs(rev)
1756 parents = [p for p in repo.changelog.parentrevs(rev)
1757 if p != nullrev]
1757 if p != nullrev]
1758 if opts['no_merges'] and len(parents) == 2:
1758 if opts['no_merges'] and len(parents) == 2:
1759 continue
1759 continue
1760 if opts['only_merges'] and len(parents) != 2:
1760 if opts['only_merges'] and len(parents) != 2:
1761 continue
1761 continue
1762
1762
1763 if only_branches:
1763 if only_branches:
1764 revbranch = get(rev)[5]['branch']
1764 revbranch = get(rev)[5]['branch']
1765 if revbranch not in only_branches:
1765 if revbranch not in only_branches:
1766 continue
1766 continue
1767
1767
1768 if df:
1768 if df:
1769 changes = get(rev)
1769 changes = get(rev)
1770 if not df(changes[2][0]):
1770 if not df(changes[2][0]):
1771 continue
1771 continue
1772
1772
1773 if opts['keyword']:
1773 if opts['keyword']:
1774 changes = get(rev)
1774 changes = get(rev)
1775 miss = 0
1775 miss = 0
1776 for k in [kw.lower() for kw in opts['keyword']]:
1776 for k in [kw.lower() for kw in opts['keyword']]:
1777 if not (k in changes[1].lower() or
1777 if not (k in changes[1].lower() or
1778 k in changes[4].lower() or
1778 k in changes[4].lower() or
1779 k in " ".join(changes[3]).lower()):
1779 k in " ".join(changes[3]).lower()):
1780 miss = 1
1780 miss = 1
1781 break
1781 break
1782 if miss:
1782 if miss:
1783 continue
1783 continue
1784
1784
1785 copies = []
1785 copies = []
1786 if opts.get('copies') and rev:
1786 if opts.get('copies') and rev:
1787 for fn in get(rev)[3]:
1787 for fn in get(rev)[3]:
1788 rename = getrenamed(fn, rev)
1788 rename = getrenamed(fn, rev)
1789 if rename:
1789 if rename:
1790 copies.append((fn, rename[0]))
1790 copies.append((fn, rename[0]))
1791 displayer.show(rev, changenode, copies=copies)
1791 displayer.show(rev, changenode, copies=copies)
1792 elif st == 'iter':
1792 elif st == 'iter':
1793 if count == limit: break
1793 if count == limit: break
1794 if displayer.flush(rev):
1794 if displayer.flush(rev):
1795 count += 1
1795 count += 1
1796
1796
1797 def manifest(ui, repo, node=None, rev=None):
1797 def manifest(ui, repo, node=None, rev=None):
1798 """output the current or given revision of the project manifest
1798 """output the current or given revision of the project manifest
1799
1799
1800 Print a list of version controlled files for the given revision.
1800 Print a list of version controlled files for the given revision.
1801 If no revision is given, the parent of the working directory is used,
1801 If no revision is given, the parent of the working directory is used,
1802 or tip if no revision is checked out.
1802 or tip if no revision is checked out.
1803
1803
1804 The manifest is the list of files being version controlled. If no revision
1804 The manifest is the list of files being version controlled. If no revision
1805 is given then the first parent of the working directory is used.
1805 is given then the first parent of the working directory is used.
1806
1806
1807 With -v flag, print file permissions, symlink and executable bits. With
1807 With -v flag, print file permissions, symlink and executable bits. With
1808 --debug flag, print file revision hashes.
1808 --debug flag, print file revision hashes.
1809 """
1809 """
1810
1810
1811 if rev and node:
1811 if rev and node:
1812 raise util.Abort(_("please specify just one revision"))
1812 raise util.Abort(_("please specify just one revision"))
1813
1813
1814 if not node:
1814 if not node:
1815 node = rev
1815 node = rev
1816
1816
1817 m = repo.changectx(node).manifest()
1817 m = repo.changectx(node).manifest()
1818 files = m.keys()
1818 files = m.keys()
1819 files.sort()
1819 files.sort()
1820
1820
1821 for f in files:
1821 for f in files:
1822 if ui.debugflag:
1822 if ui.debugflag:
1823 ui.write("%40s " % hex(m[f]))
1823 ui.write("%40s " % hex(m[f]))
1824 if ui.verbose:
1824 if ui.verbose:
1825 type = m.execf(f) and "*" or m.linkf(f) and "@" or " "
1825 type = m.execf(f) and "*" or m.linkf(f) and "@" or " "
1826 perm = m.execf(f) and "755" or "644"
1826 perm = m.execf(f) and "755" or "644"
1827 ui.write("%3s %1s " % (perm, type))
1827 ui.write("%3s %1s " % (perm, type))
1828 ui.write("%s\n" % f)
1828 ui.write("%s\n" % f)
1829
1829
1830 def merge(ui, repo, node=None, force=None, rev=None):
1830 def merge(ui, repo, node=None, force=None, rev=None):
1831 """merge working directory with another revision
1831 """merge working directory with another revision
1832
1832
1833 Merge the contents of the current working directory and the
1833 Merge the contents of the current working directory and the
1834 requested revision. Files that changed between either parent are
1834 requested revision. Files that changed between either parent are
1835 marked as changed for the next commit and a commit must be
1835 marked as changed for the next commit and a commit must be
1836 performed before any further updates are allowed.
1836 performed before any further updates are allowed.
1837
1837
1838 If no revision is specified, the working directory's parent is a
1838 If no revision is specified, the working directory's parent is a
1839 head revision, and the repository contains exactly one other head,
1839 head revision, and the repository contains exactly one other head,
1840 the other head is merged with by default. Otherwise, an explicit
1840 the other head is merged with by default. Otherwise, an explicit
1841 revision to merge with must be provided.
1841 revision to merge with must be provided.
1842 """
1842 """
1843
1843
1844 if rev and node:
1844 if rev and node:
1845 raise util.Abort(_("please specify just one revision"))
1845 raise util.Abort(_("please specify just one revision"))
1846 if not node:
1846 if not node:
1847 node = rev
1847 node = rev
1848
1848
1849 if not node:
1849 if not node:
1850 heads = repo.heads()
1850 heads = repo.heads()
1851 if len(heads) > 2:
1851 if len(heads) > 2:
1852 raise util.Abort(_('repo has %d heads - '
1852 raise util.Abort(_('repo has %d heads - '
1853 'please merge with an explicit rev') %
1853 'please merge with an explicit rev') %
1854 len(heads))
1854 len(heads))
1855 parent = repo.dirstate.parents()[0]
1855 parent = repo.dirstate.parents()[0]
1856 if len(heads) == 1:
1856 if len(heads) == 1:
1857 msg = _('there is nothing to merge')
1857 msg = _('there is nothing to merge')
1858 if parent != repo.lookup(repo.workingctx().branch()):
1858 if parent != repo.lookup(repo.workingctx().branch()):
1859 msg = _('%s - use "hg update" instead') % msg
1859 msg = _('%s - use "hg update" instead') % msg
1860 raise util.Abort(msg)
1860 raise util.Abort(msg)
1861
1861
1862 if parent not in heads:
1862 if parent not in heads:
1863 raise util.Abort(_('working dir not at a head rev - '
1863 raise util.Abort(_('working dir not at a head rev - '
1864 'use "hg update" or merge with an explicit rev'))
1864 'use "hg update" or merge with an explicit rev'))
1865 node = parent == heads[0] and heads[-1] or heads[0]
1865 node = parent == heads[0] and heads[-1] or heads[0]
1866 return hg.merge(repo, node, force=force)
1866 return hg.merge(repo, node, force=force)
1867
1867
1868 def outgoing(ui, repo, dest=None, **opts):
1868 def outgoing(ui, repo, dest=None, **opts):
1869 """show changesets not found in destination
1869 """show changesets not found in destination
1870
1870
1871 Show changesets not found in the specified destination repository or
1871 Show changesets not found in the specified destination repository or
1872 the default push location. These are the changesets that would be pushed
1872 the default push location. These are the changesets that would be pushed
1873 if a push was requested.
1873 if a push was requested.
1874
1874
1875 See pull for valid destination format details.
1875 See pull for valid destination format details.
1876 """
1876 """
1877 limit = cmdutil.loglimit(opts)
1877 limit = cmdutil.loglimit(opts)
1878 dest, revs, checkout = hg.parseurl(
1878 dest, revs, checkout = hg.parseurl(
1879 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
1879 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
1880 cmdutil.setremoteconfig(ui, opts)
1880 cmdutil.setremoteconfig(ui, opts)
1881 if revs:
1881 if revs:
1882 revs = [repo.lookup(rev) for rev in revs]
1882 revs = [repo.lookup(rev) for rev in revs]
1883
1883
1884 other = hg.repository(ui, dest)
1884 other = hg.repository(ui, dest)
1885 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
1885 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
1886 o = repo.findoutgoing(other, force=opts['force'])
1886 o = repo.findoutgoing(other, force=opts['force'])
1887 if not o:
1887 if not o:
1888 ui.status(_("no changes found\n"))
1888 ui.status(_("no changes found\n"))
1889 return 1
1889 return 1
1890 o = repo.changelog.nodesbetween(o, revs)[0]
1890 o = repo.changelog.nodesbetween(o, revs)[0]
1891 if opts['newest_first']:
1891 if opts['newest_first']:
1892 o.reverse()
1892 o.reverse()
1893 displayer = cmdutil.show_changeset(ui, repo, opts)
1893 displayer = cmdutil.show_changeset(ui, repo, opts)
1894 count = 0
1894 count = 0
1895 for n in o:
1895 for n in o:
1896 if count >= limit:
1896 if count >= limit:
1897 break
1897 break
1898 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1898 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1899 if opts['no_merges'] and len(parents) == 2:
1899 if opts['no_merges'] and len(parents) == 2:
1900 continue
1900 continue
1901 count += 1
1901 count += 1
1902 displayer.show(changenode=n)
1902 displayer.show(changenode=n)
1903
1903
1904 def parents(ui, repo, file_=None, **opts):
1904 def parents(ui, repo, file_=None, **opts):
1905 """show the parents of the working dir or revision
1905 """show the parents of the working dir or revision
1906
1906
1907 Print the working directory's parent revisions. If a
1907 Print the working directory's parent revisions. If a
1908 revision is given via --rev, the parent of that revision
1908 revision is given via --rev, the parent of that revision
1909 will be printed. If a file argument is given, revision in
1909 will be printed. If a file argument is given, revision in
1910 which the file was last changed (before the working directory
1910 which the file was last changed (before the working directory
1911 revision or the argument to --rev if given) is printed.
1911 revision or the argument to --rev if given) is printed.
1912 """
1912 """
1913 rev = opts.get('rev')
1913 rev = opts.get('rev')
1914 if rev:
1914 if rev:
1915 ctx = repo.changectx(rev)
1915 ctx = repo.changectx(rev)
1916 else:
1916 else:
1917 ctx = repo.workingctx()
1917 ctx = repo.workingctx()
1918
1918
1919 if file_:
1919 if file_:
1920 files, match, anypats = cmdutil.matchpats(repo, (file_,), opts)
1920 files, match, anypats = cmdutil.matchpats(repo, (file_,), opts)
1921 if anypats or len(files) != 1:
1921 if anypats or len(files) != 1:
1922 raise util.Abort(_('can only specify an explicit file name'))
1922 raise util.Abort(_('can only specify an explicit file name'))
1923 file_ = files[0]
1923 file_ = files[0]
1924 filenodes = []
1924 filenodes = []
1925 for cp in ctx.parents():
1925 for cp in ctx.parents():
1926 if not cp:
1926 if not cp:
1927 continue
1927 continue
1928 try:
1928 try:
1929 filenodes.append(cp.filenode(file_))
1929 filenodes.append(cp.filenode(file_))
1930 except revlog.LookupError:
1930 except revlog.LookupError:
1931 pass
1931 pass
1932 if not filenodes:
1932 if not filenodes:
1933 raise util.Abort(_("'%s' not found in manifest!") % file_)
1933 raise util.Abort(_("'%s' not found in manifest!") % file_)
1934 fl = repo.file(file_)
1934 fl = repo.file(file_)
1935 p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
1935 p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
1936 else:
1936 else:
1937 p = [cp.node() for cp in ctx.parents()]
1937 p = [cp.node() for cp in ctx.parents()]
1938
1938
1939 displayer = cmdutil.show_changeset(ui, repo, opts)
1939 displayer = cmdutil.show_changeset(ui, repo, opts)
1940 for n in p:
1940 for n in p:
1941 if n != nullid:
1941 if n != nullid:
1942 displayer.show(changenode=n)
1942 displayer.show(changenode=n)
1943
1943
1944 def paths(ui, repo, search=None):
1944 def paths(ui, repo, search=None):
1945 """show definition of symbolic path names
1945 """show definition of symbolic path names
1946
1946
1947 Show definition of symbolic path name NAME. If no name is given, show
1947 Show definition of symbolic path name NAME. If no name is given, show
1948 definition of available names.
1948 definition of available names.
1949
1949
1950 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1950 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1951 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1951 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1952 """
1952 """
1953 if search:
1953 if search:
1954 for name, path in ui.configitems("paths"):
1954 for name, path in ui.configitems("paths"):
1955 if name == search:
1955 if name == search:
1956 ui.write("%s\n" % path)
1956 ui.write("%s\n" % path)
1957 return
1957 return
1958 ui.warn(_("not found!\n"))
1958 ui.warn(_("not found!\n"))
1959 return 1
1959 return 1
1960 else:
1960 else:
1961 for name, path in ui.configitems("paths"):
1961 for name, path in ui.configitems("paths"):
1962 ui.write("%s = %s\n" % (name, path))
1962 ui.write("%s = %s\n" % (name, path))
1963
1963
1964 def postincoming(ui, repo, modheads, optupdate, checkout):
1964 def postincoming(ui, repo, modheads, optupdate, checkout):
1965 if modheads == 0:
1965 if modheads == 0:
1966 return
1966 return
1967 if optupdate:
1967 if optupdate:
1968 if modheads <= 1 or checkout:
1968 if modheads <= 1 or checkout:
1969 return hg.update(repo, checkout)
1969 return hg.update(repo, checkout)
1970 else:
1970 else:
1971 ui.status(_("not updating, since new heads added\n"))
1971 ui.status(_("not updating, since new heads added\n"))
1972 if modheads > 1:
1972 if modheads > 1:
1973 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
1973 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
1974 else:
1974 else:
1975 ui.status(_("(run 'hg update' to get a working copy)\n"))
1975 ui.status(_("(run 'hg update' to get a working copy)\n"))
1976
1976
1977 def pull(ui, repo, source="default", **opts):
1977 def pull(ui, repo, source="default", **opts):
1978 """pull changes from the specified source
1978 """pull changes from the specified source
1979
1979
1980 Pull changes from a remote repository to a local one.
1980 Pull changes from a remote repository to a local one.
1981
1981
1982 This finds all changes from the repository at the specified path
1982 This finds all changes from the repository at the specified path
1983 or URL and adds them to the local repository. By default, this
1983 or URL and adds them to the local repository. By default, this
1984 does not update the copy of the project in the working directory.
1984 does not update the copy of the project in the working directory.
1985
1985
1986 Valid URLs are of the form:
1986 Valid URLs are of the form:
1987
1987
1988 local/filesystem/path (or file://local/filesystem/path)
1988 local/filesystem/path (or file://local/filesystem/path)
1989 http://[user@]host[:port]/[path]
1989 http://[user@]host[:port]/[path]
1990 https://[user@]host[:port]/[path]
1990 https://[user@]host[:port]/[path]
1991 ssh://[user@]host[:port]/[path]
1991 ssh://[user@]host[:port]/[path]
1992 static-http://host[:port]/[path]
1992 static-http://host[:port]/[path]
1993
1993
1994 Paths in the local filesystem can either point to Mercurial
1994 Paths in the local filesystem can either point to Mercurial
1995 repositories or to bundle files (as created by 'hg bundle' or
1995 repositories or to bundle files (as created by 'hg bundle' or
1996 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
1996 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
1997 allows access to a Mercurial repository where you simply use a web
1997 allows access to a Mercurial repository where you simply use a web
1998 server to publish the .hg directory as static content.
1998 server to publish the .hg directory as static content.
1999
1999
2000 An optional identifier after # indicates a particular branch, tag,
2000 An optional identifier after # indicates a particular branch, tag,
2001 or changeset to pull.
2001 or changeset to pull.
2002
2002
2003 Some notes about using SSH with Mercurial:
2003 Some notes about using SSH with Mercurial:
2004 - SSH requires an accessible shell account on the destination machine
2004 - SSH requires an accessible shell account on the destination machine
2005 and a copy of hg in the remote path or specified with as remotecmd.
2005 and a copy of hg in the remote path or specified with as remotecmd.
2006 - path is relative to the remote user's home directory by default.
2006 - path is relative to the remote user's home directory by default.
2007 Use an extra slash at the start of a path to specify an absolute path:
2007 Use an extra slash at the start of a path to specify an absolute path:
2008 ssh://example.com//tmp/repository
2008 ssh://example.com//tmp/repository
2009 - Mercurial doesn't use its own compression via SSH; the right thing
2009 - Mercurial doesn't use its own compression via SSH; the right thing
2010 to do is to configure it in your ~/.ssh/config, e.g.:
2010 to do is to configure it in your ~/.ssh/config, e.g.:
2011 Host *.mylocalnetwork.example.com
2011 Host *.mylocalnetwork.example.com
2012 Compression no
2012 Compression no
2013 Host *
2013 Host *
2014 Compression yes
2014 Compression yes
2015 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2015 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2016 with the --ssh command line option.
2016 with the --ssh command line option.
2017 """
2017 """
2018 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
2018 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
2019 cmdutil.setremoteconfig(ui, opts)
2019 cmdutil.setremoteconfig(ui, opts)
2020
2020
2021 other = hg.repository(ui, source)
2021 other = hg.repository(ui, source)
2022 ui.status(_('pulling from %s\n') % util.hidepassword(source))
2022 ui.status(_('pulling from %s\n') % util.hidepassword(source))
2023 if revs:
2023 if revs:
2024 try:
2024 try:
2025 revs = [other.lookup(rev) for rev in revs]
2025 revs = [other.lookup(rev) for rev in revs]
2026 except repo.NoCapability:
2026 except repo.NoCapability:
2027 error = _("Other repository doesn't support revision lookup, "
2027 error = _("Other repository doesn't support revision lookup, "
2028 "so a rev cannot be specified.")
2028 "so a rev cannot be specified.")
2029 raise util.Abort(error)
2029 raise util.Abort(error)
2030
2030
2031 modheads = repo.pull(other, heads=revs, force=opts['force'])
2031 modheads = repo.pull(other, heads=revs, force=opts['force'])
2032 return postincoming(ui, repo, modheads, opts['update'], checkout)
2032 return postincoming(ui, repo, modheads, opts['update'], checkout)
2033
2033
2034 def push(ui, repo, dest=None, **opts):
2034 def push(ui, repo, dest=None, **opts):
2035 """push changes to the specified destination
2035 """push changes to the specified destination
2036
2036
2037 Push changes from the local repository to the given destination.
2037 Push changes from the local repository to the given destination.
2038
2038
2039 This is the symmetrical operation for pull. It helps to move
2039 This is the symmetrical operation for pull. It helps to move
2040 changes from the current repository to a different one. If the
2040 changes from the current repository to a different one. If the
2041 destination is local this is identical to a pull in that directory
2041 destination is local this is identical to a pull in that directory
2042 from the current one.
2042 from the current one.
2043
2043
2044 By default, push will refuse to run if it detects the result would
2044 By default, push will refuse to run if it detects the result would
2045 increase the number of remote heads. This generally indicates the
2045 increase the number of remote heads. This generally indicates the
2046 the client has forgotten to sync and merge before pushing.
2046 the client has forgotten to sync and merge before pushing.
2047
2047
2048 Valid URLs are of the form:
2048 Valid URLs are of the form:
2049
2049
2050 local/filesystem/path (or file://local/filesystem/path)
2050 local/filesystem/path (or file://local/filesystem/path)
2051 ssh://[user@]host[:port]/[path]
2051 ssh://[user@]host[:port]/[path]
2052 http://[user@]host[:port]/[path]
2052 http://[user@]host[:port]/[path]
2053 https://[user@]host[:port]/[path]
2053 https://[user@]host[:port]/[path]
2054
2054
2055 An optional identifier after # indicates a particular branch, tag,
2055 An optional identifier after # indicates a particular branch, tag,
2056 or changeset to push.
2056 or changeset to push.
2057
2057
2058 Look at the help text for the pull command for important details
2058 Look at the help text for the pull command for important details
2059 about ssh:// URLs.
2059 about ssh:// URLs.
2060
2060
2061 Pushing to http:// and https:// URLs is only possible, if this
2061 Pushing to http:// and https:// URLs is only possible, if this
2062 feature is explicitly enabled on the remote Mercurial server.
2062 feature is explicitly enabled on the remote Mercurial server.
2063 """
2063 """
2064 dest, revs, checkout = hg.parseurl(
2064 dest, revs, checkout = hg.parseurl(
2065 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2065 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2066 cmdutil.setremoteconfig(ui, opts)
2066 cmdutil.setremoteconfig(ui, opts)
2067
2067
2068 other = hg.repository(ui, dest)
2068 other = hg.repository(ui, dest)
2069 ui.status('pushing to %s\n' % util.hidepassword(dest))
2069 ui.status('pushing to %s\n' % util.hidepassword(dest))
2070 if revs:
2070 if revs:
2071 revs = [repo.lookup(rev) for rev in revs]
2071 revs = [repo.lookup(rev) for rev in revs]
2072 r = repo.push(other, opts['force'], revs=revs)
2072 r = repo.push(other, opts['force'], revs=revs)
2073 return r == 0
2073 return r == 0
2074
2074
2075 def rawcommit(ui, repo, *pats, **opts):
2075 def rawcommit(ui, repo, *pats, **opts):
2076 """raw commit interface (DEPRECATED)
2076 """raw commit interface (DEPRECATED)
2077
2077
2078 (DEPRECATED)
2078 (DEPRECATED)
2079 Lowlevel commit, for use in helper scripts.
2079 Lowlevel commit, for use in helper scripts.
2080
2080
2081 This command is not intended to be used by normal users, as it is
2081 This command is not intended to be used by normal users, as it is
2082 primarily useful for importing from other SCMs.
2082 primarily useful for importing from other SCMs.
2083
2083
2084 This command is now deprecated and will be removed in a future
2084 This command is now deprecated and will be removed in a future
2085 release, please use debugsetparents and commit instead.
2085 release, please use debugsetparents and commit instead.
2086 """
2086 """
2087
2087
2088 ui.warn(_("(the rawcommit command is deprecated)\n"))
2088 ui.warn(_("(the rawcommit command is deprecated)\n"))
2089
2089
2090 message = cmdutil.logmessage(opts)
2090 message = cmdutil.logmessage(opts)
2091
2091
2092 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
2092 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
2093 if opts['files']:
2093 if opts['files']:
2094 files += open(opts['files']).read().splitlines()
2094 files += open(opts['files']).read().splitlines()
2095
2095
2096 parents = [repo.lookup(p) for p in opts['parent']]
2096 parents = [repo.lookup(p) for p in opts['parent']]
2097
2097
2098 try:
2098 try:
2099 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2099 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2100 except ValueError, inst:
2100 except ValueError, inst:
2101 raise util.Abort(str(inst))
2101 raise util.Abort(str(inst))
2102
2102
2103 def recover(ui, repo):
2103 def recover(ui, repo):
2104 """roll back an interrupted transaction
2104 """roll back an interrupted transaction
2105
2105
2106 Recover from an interrupted commit or pull.
2106 Recover from an interrupted commit or pull.
2107
2107
2108 This command tries to fix the repository status after an interrupted
2108 This command tries to fix the repository status after an interrupted
2109 operation. It should only be necessary when Mercurial suggests it.
2109 operation. It should only be necessary when Mercurial suggests it.
2110 """
2110 """
2111 if repo.recover():
2111 if repo.recover():
2112 return hg.verify(repo)
2112 return hg.verify(repo)
2113 return 1
2113 return 1
2114
2114
2115 def remove(ui, repo, *pats, **opts):
2115 def remove(ui, repo, *pats, **opts):
2116 """remove the specified files on the next commit
2116 """remove the specified files on the next commit
2117
2117
2118 Schedule the indicated files for removal from the repository.
2118 Schedule the indicated files for removal from the repository.
2119
2119
2120 This only removes files from the current branch, not from the
2120 This only removes files from the current branch, not from the
2121 entire project history. If the files still exist in the working
2121 entire project history. If the files still exist in the working
2122 directory, they will be deleted from it. If invoked with --after,
2122 directory, they will be deleted from it. If invoked with --after,
2123 files are marked as removed, but not actually unlinked unless --force
2123 files are marked as removed, but not actually unlinked unless --force
2124 is also given. Without exact file names, --after will only mark
2124 is also given. Without exact file names, --after will only mark
2125 files as removed if they are no longer in the working directory.
2125 files as removed if they are no longer in the working directory.
2126
2126
2127 This command schedules the files to be removed at the next commit.
2127 This command schedules the files to be removed at the next commit.
2128 To undo a remove before that, see hg revert.
2128 To undo a remove before that, see hg revert.
2129
2129
2130 Modified files and added files are not removed by default. To
2130 Modified files and added files are not removed by default. To
2131 remove them, use the -f/--force option.
2131 remove them, use the -f/--force option.
2132 """
2132 """
2133 if not opts['after'] and not pats:
2133 if not opts['after'] and not pats:
2134 raise util.Abort(_('no files specified'))
2134 raise util.Abort(_('no files specified'))
2135 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2135 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2136 exact = dict.fromkeys(files)
2136 exact = dict.fromkeys(files)
2137 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
2137 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
2138 modified, added, removed, deleted, unknown = mardu
2138 modified, added, removed, deleted, unknown = mardu
2139 remove, forget = [], []
2139 remove, forget = [], []
2140 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
2140 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
2141 reason = None
2141 reason = None
2142 if abs in modified and not opts['force']:
2142 if abs in modified and not opts['force']:
2143 reason = _('is modified (use -f to force removal)')
2143 reason = _('is modified (use -f to force removal)')
2144 elif abs in added:
2144 elif abs in added:
2145 if opts['force']:
2145 if opts['force']:
2146 forget.append(abs)
2146 forget.append(abs)
2147 continue
2147 continue
2148 reason = _('has been marked for add (use -f to force removal)')
2148 reason = _('has been marked for add (use -f to force removal)')
2149 exact = 1 # force the message
2149 exact = 1 # force the message
2150 elif abs not in repo.dirstate:
2150 elif abs not in repo.dirstate:
2151 reason = _('is not managed')
2151 reason = _('is not managed')
2152 elif opts['after'] and not exact and abs not in deleted:
2152 elif opts['after'] and not exact and abs not in deleted:
2153 continue
2153 continue
2154 elif abs in removed:
2154 elif abs in removed:
2155 continue
2155 continue
2156 if reason:
2156 if reason:
2157 if exact:
2157 if exact:
2158 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2158 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2159 else:
2159 else:
2160 if ui.verbose or not exact:
2160 if ui.verbose or not exact:
2161 ui.status(_('removing %s\n') % rel)
2161 ui.status(_('removing %s\n') % rel)
2162 remove.append(abs)
2162 remove.append(abs)
2163 repo.forget(forget)
2163 repo.forget(forget)
2164 repo.remove(remove, unlink=opts['force'] or not opts['after'])
2164 repo.remove(remove, unlink=opts['force'] or not opts['after'])
2165
2165
2166 def rename(ui, repo, *pats, **opts):
2166 def rename(ui, repo, *pats, **opts):
2167 """rename files; equivalent of copy + remove
2167 """rename files; equivalent of copy + remove
2168
2168
2169 Mark dest as copies of sources; mark sources for deletion. If
2169 Mark dest as copies of sources; mark sources for deletion. If
2170 dest is a directory, copies are put in that directory. If dest is
2170 dest is a directory, copies are put in that directory. If dest is
2171 a file, there can only be one source.
2171 a file, there can only be one source.
2172
2172
2173 By default, this command copies the contents of files as they
2173 By default, this command copies the contents of files as they
2174 stand in the working directory. If invoked with --after, the
2174 stand in the working directory. If invoked with --after, the
2175 operation is recorded, but no copying is performed.
2175 operation is recorded, but no copying is performed.
2176
2176
2177 This command takes effect in the next commit. To undo a rename
2177 This command takes effect in the next commit. To undo a rename
2178 before that, see hg revert.
2178 before that, see hg revert.
2179 """
2179 """
2180 wlock = repo.wlock(False)
2180 wlock = repo.wlock(False)
2181 try:
2181 try:
2182 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2182 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2183 finally:
2183 finally:
2184 del wlock
2184 del wlock
2185
2185
2186 def revert(ui, repo, *pats, **opts):
2186 def revert(ui, repo, *pats, **opts):
2187 """restore individual files or dirs to an earlier state
2187 """restore individual files or dirs to an earlier state
2188
2188
2189 (use update -r to check out earlier revisions, revert does not
2189 (use update -r to check out earlier revisions, revert does not
2190 change the working dir parents)
2190 change the working dir parents)
2191
2191
2192 With no revision specified, revert the named files or directories
2192 With no revision specified, revert the named files or directories
2193 to the contents they had in the parent of the working directory.
2193 to the contents they had in the parent of the working directory.
2194 This restores the contents of the affected files to an unmodified
2194 This restores the contents of the affected files to an unmodified
2195 state and unschedules adds, removes, copies, and renames. If the
2195 state and unschedules adds, removes, copies, and renames. If the
2196 working directory has two parents, you must explicitly specify the
2196 working directory has two parents, you must explicitly specify the
2197 revision to revert to.
2197 revision to revert to.
2198
2198
2199 Using the -r option, revert the given files or directories to their
2199 Using the -r option, revert the given files or directories to their
2200 contents as of a specific revision. This can be helpful to "roll
2200 contents as of a specific revision. This can be helpful to "roll
2201 back" some or all of an earlier change.
2201 back" some or all of an earlier change.
2202 See 'hg help dates' for a list of formats valid for -d/--date.
2202 See 'hg help dates' for a list of formats valid for -d/--date.
2203
2203
2204 Revert modifies the working directory. It does not commit any
2204 Revert modifies the working directory. It does not commit any
2205 changes, or change the parent of the working directory. If you
2205 changes, or change the parent of the working directory. If you
2206 revert to a revision other than the parent of the working
2206 revert to a revision other than the parent of the working
2207 directory, the reverted files will thus appear modified
2207 directory, the reverted files will thus appear modified
2208 afterwards.
2208 afterwards.
2209
2209
2210 If a file has been deleted, it is restored. If the executable
2210 If a file has been deleted, it is restored. If the executable
2211 mode of a file was changed, it is reset.
2211 mode of a file was changed, it is reset.
2212
2212
2213 If names are given, all files matching the names are reverted.
2213 If names are given, all files matching the names are reverted.
2214 If no arguments are given, no files are reverted.
2214 If no arguments are given, no files are reverted.
2215
2215
2216 Modified files are saved with a .orig suffix before reverting.
2216 Modified files are saved with a .orig suffix before reverting.
2217 To disable these backups, use --no-backup.
2217 To disable these backups, use --no-backup.
2218 """
2218 """
2219
2219
2220 if opts["date"]:
2220 if opts["date"]:
2221 if opts["rev"]:
2221 if opts["rev"]:
2222 raise util.Abort(_("you can't specify a revision and a date"))
2222 raise util.Abort(_("you can't specify a revision and a date"))
2223 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2223 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2224
2224
2225 if not pats and not opts['all']:
2225 if not pats and not opts['all']:
2226 raise util.Abort(_('no files or directories specified; '
2226 raise util.Abort(_('no files or directories specified; '
2227 'use --all to revert the whole repo'))
2227 'use --all to revert the whole repo'))
2228
2228
2229 parent, p2 = repo.dirstate.parents()
2229 parent, p2 = repo.dirstate.parents()
2230 if not opts['rev'] and p2 != nullid:
2230 if not opts['rev'] and p2 != nullid:
2231 raise util.Abort(_('uncommitted merge - please provide a '
2231 raise util.Abort(_('uncommitted merge - please provide a '
2232 'specific revision'))
2232 'specific revision'))
2233 ctx = repo.changectx(opts['rev'])
2233 ctx = repo.changectx(opts['rev'])
2234 node = ctx.node()
2234 node = ctx.node()
2235 mf = ctx.manifest()
2235 mf = ctx.manifest()
2236 if node == parent:
2236 if node == parent:
2237 pmf = mf
2237 pmf = mf
2238 else:
2238 else:
2239 pmf = None
2239 pmf = None
2240
2240
2241 # need all matching names in dirstate and manifest of target rev,
2241 # need all matching names in dirstate and manifest of target rev,
2242 # so have to walk both. do not print errors if files exist in one
2242 # so have to walk both. do not print errors if files exist in one
2243 # but not other.
2243 # but not other.
2244
2244
2245 names = {}
2245 names = {}
2246
2246
2247 wlock = repo.wlock()
2247 wlock = repo.wlock()
2248 try:
2248 try:
2249 # walk dirstate.
2249 # walk dirstate.
2250 files = []
2250 files = []
2251 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
2251 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
2252 badmatch=mf.has_key):
2252 badmatch=mf.has_key):
2253 names[abs] = (rel, exact)
2253 names[abs] = (rel, exact)
2254 if src != 'b':
2254 if src != 'b':
2255 files.append(abs)
2255 files.append(abs)
2256
2256
2257 # walk target manifest.
2257 # walk target manifest.
2258
2258
2259 def badmatch(path):
2259 def badmatch(path):
2260 if path in names:
2260 if path in names:
2261 return True
2261 return True
2262 path_ = path + '/'
2262 path_ = path + '/'
2263 for f in names:
2263 for f in names:
2264 if f.startswith(path_):
2264 if f.startswith(path_):
2265 return True
2265 return True
2266 return False
2266 return False
2267
2267
2268 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
2268 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
2269 badmatch=badmatch):
2269 badmatch=badmatch):
2270 if abs in names or src == 'b':
2270 if abs in names or src == 'b':
2271 continue
2271 continue
2272 names[abs] = (rel, exact)
2272 names[abs] = (rel, exact)
2273
2273
2274 changes = repo.status(files=files, match=names.has_key)[:4]
2274 changes = repo.status(files=files, match=names.has_key)[:4]
2275 modified, added, removed, deleted = map(dict.fromkeys, changes)
2275 modified, added, removed, deleted = map(dict.fromkeys, changes)
2276
2276
2277 # if f is a rename, also revert the source
2277 # if f is a rename, also revert the source
2278 cwd = repo.getcwd()
2278 cwd = repo.getcwd()
2279 for f in added:
2279 for f in added:
2280 src = repo.dirstate.copied(f)
2280 src = repo.dirstate.copied(f)
2281 if src and src not in names and repo.dirstate[src] == 'r':
2281 if src and src not in names and repo.dirstate[src] == 'r':
2282 removed[src] = None
2282 removed[src] = None
2283 names[src] = (repo.pathto(src, cwd), True)
2283 names[src] = (repo.pathto(src, cwd), True)
2284
2284
2285 def removeforget(abs):
2285 def removeforget(abs):
2286 if repo.dirstate[abs] == 'a':
2286 if repo.dirstate[abs] == 'a':
2287 return _('forgetting %s\n')
2287 return _('forgetting %s\n')
2288 return _('removing %s\n')
2288 return _('removing %s\n')
2289
2289
2290 revert = ([], _('reverting %s\n'))
2290 revert = ([], _('reverting %s\n'))
2291 add = ([], _('adding %s\n'))
2291 add = ([], _('adding %s\n'))
2292 remove = ([], removeforget)
2292 remove = ([], removeforget)
2293 undelete = ([], _('undeleting %s\n'))
2293 undelete = ([], _('undeleting %s\n'))
2294
2294
2295 disptable = (
2295 disptable = (
2296 # dispatch table:
2296 # dispatch table:
2297 # file state
2297 # file state
2298 # action if in target manifest
2298 # action if in target manifest
2299 # action if not in target manifest
2299 # action if not in target manifest
2300 # make backup if in target manifest
2300 # make backup if in target manifest
2301 # make backup if not in target manifest
2301 # make backup if not in target manifest
2302 (modified, revert, remove, True, True),
2302 (modified, revert, remove, True, True),
2303 (added, revert, remove, True, False),
2303 (added, revert, remove, True, False),
2304 (removed, undelete, None, False, False),
2304 (removed, undelete, None, False, False),
2305 (deleted, revert, remove, False, False),
2305 (deleted, revert, remove, False, False),
2306 )
2306 )
2307
2307
2308 entries = names.items()
2308 entries = names.items()
2309 entries.sort()
2309 entries.sort()
2310
2310
2311 for abs, (rel, exact) in entries:
2311 for abs, (rel, exact) in entries:
2312 mfentry = mf.get(abs)
2312 mfentry = mf.get(abs)
2313 target = repo.wjoin(abs)
2313 target = repo.wjoin(abs)
2314 def handle(xlist, dobackup):
2314 def handle(xlist, dobackup):
2315 xlist[0].append(abs)
2315 xlist[0].append(abs)
2316 if dobackup and not opts['no_backup'] and util.lexists(target):
2316 if dobackup and not opts['no_backup'] and util.lexists(target):
2317 bakname = "%s.orig" % rel
2317 bakname = "%s.orig" % rel
2318 ui.note(_('saving current version of %s as %s\n') %
2318 ui.note(_('saving current version of %s as %s\n') %
2319 (rel, bakname))
2319 (rel, bakname))
2320 if not opts.get('dry_run'):
2320 if not opts.get('dry_run'):
2321 util.copyfile(target, bakname)
2321 util.copyfile(target, bakname)
2322 if ui.verbose or not exact:
2322 if ui.verbose or not exact:
2323 msg = xlist[1]
2323 msg = xlist[1]
2324 if not isinstance(msg, basestring):
2324 if not isinstance(msg, basestring):
2325 msg = msg(abs)
2325 msg = msg(abs)
2326 ui.status(msg % rel)
2326 ui.status(msg % rel)
2327 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2327 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2328 if abs not in table: continue
2328 if abs not in table: continue
2329 # file has changed in dirstate
2329 # file has changed in dirstate
2330 if mfentry:
2330 if mfentry:
2331 handle(hitlist, backuphit)
2331 handle(hitlist, backuphit)
2332 elif misslist is not None:
2332 elif misslist is not None:
2333 handle(misslist, backupmiss)
2333 handle(misslist, backupmiss)
2334 break
2334 break
2335 else:
2335 else:
2336 if abs not in repo.dirstate:
2336 if abs not in repo.dirstate:
2337 if mfentry:
2337 if mfentry:
2338 handle(add, True)
2338 handle(add, True)
2339 elif exact:
2339 elif exact:
2340 ui.warn(_('file not managed: %s\n') % rel)
2340 ui.warn(_('file not managed: %s\n') % rel)
2341 continue
2341 continue
2342 # file has not changed in dirstate
2342 # file has not changed in dirstate
2343 if node == parent:
2343 if node == parent:
2344 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2344 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2345 continue
2345 continue
2346 if pmf is None:
2346 if pmf is None:
2347 # only need parent manifest in this unlikely case,
2347 # only need parent manifest in this unlikely case,
2348 # so do not read by default
2348 # so do not read by default
2349 pmf = repo.changectx(parent).manifest()
2349 pmf = repo.changectx(parent).manifest()
2350 if abs in pmf:
2350 if abs in pmf:
2351 if mfentry:
2351 if mfentry:
2352 # if version of file is same in parent and target
2352 # if version of file is same in parent and target
2353 # manifests, do nothing
2353 # manifests, do nothing
2354 if (pmf[abs] != mfentry or
2354 if (pmf[abs] != mfentry or
2355 pmf.flags(abs) != mf.flags(abs)):
2355 pmf.flags(abs) != mf.flags(abs)):
2356 handle(revert, False)
2356 handle(revert, False)
2357 else:
2357 else:
2358 handle(remove, False)
2358 handle(remove, False)
2359
2359
2360 if not opts.get('dry_run'):
2360 if not opts.get('dry_run'):
2361 def checkout(f):
2361 def checkout(f):
2362 fc = ctx[f]
2362 fc = ctx[f]
2363 repo.wwrite(f, fc.data(), fc.fileflags())
2363 repo.wwrite(f, fc.data(), fc.fileflags())
2364
2364
2365 audit_path = util.path_auditor(repo.root)
2365 audit_path = util.path_auditor(repo.root)
2366 for f in remove[0]:
2366 for f in remove[0]:
2367 if repo.dirstate[f] == 'a':
2367 if repo.dirstate[f] == 'a':
2368 repo.dirstate.forget(f)
2368 repo.dirstate.forget(f)
2369 continue
2369 continue
2370 audit_path(f)
2370 audit_path(f)
2371 try:
2371 try:
2372 util.unlink(repo.wjoin(f))
2372 util.unlink(repo.wjoin(f))
2373 except OSError:
2373 except OSError:
2374 pass
2374 pass
2375 repo.dirstate.remove(f)
2375 repo.dirstate.remove(f)
2376
2376
2377 for f in revert[0]:
2377 for f in revert[0]:
2378 checkout(f)
2378 checkout(f)
2379
2379
2380 for f in add[0]:
2380 for f in add[0]:
2381 checkout(f)
2381 checkout(f)
2382 repo.dirstate.add(f)
2382 repo.dirstate.add(f)
2383
2383
2384 normal = repo.dirstate.normallookup
2384 normal = repo.dirstate.normallookup
2385 if node == parent and p2 == nullid:
2385 if node == parent and p2 == nullid:
2386 normal = repo.dirstate.normal
2386 normal = repo.dirstate.normal
2387 for f in undelete[0]:
2387 for f in undelete[0]:
2388 checkout(f)
2388 checkout(f)
2389 normal(f)
2389 normal(f)
2390
2390
2391 finally:
2391 finally:
2392 del wlock
2392 del wlock
2393
2393
2394 def rollback(ui, repo):
2394 def rollback(ui, repo):
2395 """roll back the last transaction
2395 """roll back the last transaction
2396
2396
2397 This command should be used with care. There is only one level of
2397 This command should be used with care. There is only one level of
2398 rollback, and there is no way to undo a rollback. It will also
2398 rollback, and there is no way to undo a rollback. It will also
2399 restore the dirstate at the time of the last transaction, losing
2399 restore the dirstate at the time of the last transaction, losing
2400 any dirstate changes since that time.
2400 any dirstate changes since that time.
2401
2401
2402 Transactions are used to encapsulate the effects of all commands
2402 Transactions are used to encapsulate the effects of all commands
2403 that create new changesets or propagate existing changesets into a
2403 that create new changesets or propagate existing changesets into a
2404 repository. For example, the following commands are transactional,
2404 repository. For example, the following commands are transactional,
2405 and their effects can be rolled back:
2405 and their effects can be rolled back:
2406
2406
2407 commit
2407 commit
2408 import
2408 import
2409 pull
2409 pull
2410 push (with this repository as destination)
2410 push (with this repository as destination)
2411 unbundle
2411 unbundle
2412
2412
2413 This command is not intended for use on public repositories. Once
2413 This command is not intended for use on public repositories. Once
2414 changes are visible for pull by other users, rolling a transaction
2414 changes are visible for pull by other users, rolling a transaction
2415 back locally is ineffective (someone else may already have pulled
2415 back locally is ineffective (someone else may already have pulled
2416 the changes). Furthermore, a race is possible with readers of the
2416 the changes). Furthermore, a race is possible with readers of the
2417 repository; for example an in-progress pull from the repository
2417 repository; for example an in-progress pull from the repository
2418 may fail if a rollback is performed.
2418 may fail if a rollback is performed.
2419 """
2419 """
2420 repo.rollback()
2420 repo.rollback()
2421
2421
2422 def root(ui, repo):
2422 def root(ui, repo):
2423 """print the root (top) of the current working dir
2423 """print the root (top) of the current working dir
2424
2424
2425 Print the root directory of the current repository.
2425 Print the root directory of the current repository.
2426 """
2426 """
2427 ui.write(repo.root + "\n")
2427 ui.write(repo.root + "\n")
2428
2428
2429 def serve(ui, repo, **opts):
2429 def serve(ui, repo, **opts):
2430 """export the repository via HTTP
2430 """export the repository via HTTP
2431
2431
2432 Start a local HTTP repository browser and pull server.
2432 Start a local HTTP repository browser and pull server.
2433
2433
2434 By default, the server logs accesses to stdout and errors to
2434 By default, the server logs accesses to stdout and errors to
2435 stderr. Use the "-A" and "-E" options to log to files.
2435 stderr. Use the "-A" and "-E" options to log to files.
2436 """
2436 """
2437
2437
2438 if opts["stdio"]:
2438 if opts["stdio"]:
2439 if repo is None:
2439 if repo is None:
2440 raise hg.RepoError(_("There is no Mercurial repository here"
2440 raise hg.RepoError(_("There is no Mercurial repository here"
2441 " (.hg not found)"))
2441 " (.hg not found)"))
2442 s = sshserver.sshserver(ui, repo)
2442 s = sshserver.sshserver(ui, repo)
2443 s.serve_forever()
2443 s.serve_forever()
2444
2444
2445 parentui = ui.parentui or ui
2445 parentui = ui.parentui or ui
2446 optlist = ("name templates style address port prefix ipv6"
2446 optlist = ("name templates style address port prefix ipv6"
2447 " accesslog errorlog webdir_conf certificate")
2447 " accesslog errorlog webdir_conf certificate")
2448 for o in optlist.split():
2448 for o in optlist.split():
2449 if opts[o]:
2449 if opts[o]:
2450 parentui.setconfig("web", o, str(opts[o]))
2450 parentui.setconfig("web", o, str(opts[o]))
2451 if (repo is not None) and (repo.ui != parentui):
2451 if (repo is not None) and (repo.ui != parentui):
2452 repo.ui.setconfig("web", o, str(opts[o]))
2452 repo.ui.setconfig("web", o, str(opts[o]))
2453
2453
2454 if repo is None and not ui.config("web", "webdir_conf"):
2454 if repo is None and not ui.config("web", "webdir_conf"):
2455 raise hg.RepoError(_("There is no Mercurial repository here"
2455 raise hg.RepoError(_("There is no Mercurial repository here"
2456 " (.hg not found)"))
2456 " (.hg not found)"))
2457
2457
2458 class service:
2458 class service:
2459 def init(self):
2459 def init(self):
2460 util.set_signal_handler()
2460 util.set_signal_handler()
2461 try:
2461 try:
2462 self.httpd = hgweb.server.create_server(parentui, repo)
2462 self.httpd = hgweb.server.create_server(parentui, repo)
2463 except socket.error, inst:
2463 except socket.error, inst:
2464 raise util.Abort(_('cannot start server: ') + inst.args[1])
2464 raise util.Abort(_('cannot start server: ') + inst.args[1])
2465
2465
2466 if not ui.verbose: return
2466 if not ui.verbose: return
2467
2467
2468 if self.httpd.prefix:
2468 if self.httpd.prefix:
2469 prefix = self.httpd.prefix.strip('/') + '/'
2469 prefix = self.httpd.prefix.strip('/') + '/'
2470 else:
2470 else:
2471 prefix = ''
2471 prefix = ''
2472
2472
2473 if self.httpd.port != 80:
2473 if self.httpd.port != 80:
2474 ui.status(_('listening at http://%s:%d/%s\n') %
2474 ui.status(_('listening at http://%s:%d/%s\n') %
2475 (self.httpd.addr, self.httpd.port, prefix))
2475 (self.httpd.addr, self.httpd.port, prefix))
2476 else:
2476 else:
2477 ui.status(_('listening at http://%s/%s\n') %
2477 ui.status(_('listening at http://%s/%s\n') %
2478 (self.httpd.addr, prefix))
2478 (self.httpd.addr, prefix))
2479
2479
2480 def run(self):
2480 def run(self):
2481 self.httpd.serve_forever()
2481 self.httpd.serve_forever()
2482
2482
2483 service = service()
2483 service = service()
2484
2484
2485 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2485 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2486
2486
2487 def status(ui, repo, *pats, **opts):
2487 def status(ui, repo, *pats, **opts):
2488 """show changed files in the working directory
2488 """show changed files in the working directory
2489
2489
2490 Show status of files in the repository. If names are given, only
2490 Show status of files in the repository. If names are given, only
2491 files that match are shown. Files that are clean or ignored or
2491 files that match are shown. Files that are clean or ignored or
2492 source of a copy/move operation, are not listed unless -c (clean),
2492 source of a copy/move operation, are not listed unless -c (clean),
2493 -i (ignored), -C (copies) or -A is given. Unless options described
2493 -i (ignored), -C (copies) or -A is given. Unless options described
2494 with "show only ..." are given, the options -mardu are used.
2494 with "show only ..." are given, the options -mardu are used.
2495
2495
2496 NOTE: status may appear to disagree with diff if permissions have
2496 NOTE: status may appear to disagree with diff if permissions have
2497 changed or a merge has occurred. The standard diff format does not
2497 changed or a merge has occurred. The standard diff format does not
2498 report permission changes and diff only reports changes relative
2498 report permission changes and diff only reports changes relative
2499 to one merge parent.
2499 to one merge parent.
2500
2500
2501 If one revision is given, it is used as the base revision.
2501 If one revision is given, it is used as the base revision.
2502 If two revisions are given, the difference between them is shown.
2502 If two revisions are given, the difference between them is shown.
2503
2503
2504 The codes used to show the status of files are:
2504 The codes used to show the status of files are:
2505 M = modified
2505 M = modified
2506 A = added
2506 A = added
2507 R = removed
2507 R = removed
2508 C = clean
2508 C = clean
2509 ! = deleted, but still tracked
2509 ! = deleted, but still tracked
2510 ? = not tracked
2510 ? = not tracked
2511 I = ignored
2511 I = ignored
2512 = the previous added file was copied from here
2512 = the previous added file was copied from here
2513 """
2513 """
2514
2514
2515 all = opts['all']
2515 all = opts['all']
2516 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2516 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2517
2517
2518 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2518 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2519 cwd = (pats and repo.getcwd()) or ''
2519 cwd = (pats and repo.getcwd()) or ''
2520 modified, added, removed, deleted, unknown, ignored, clean = [
2520 modified, added, removed, deleted, unknown, ignored, clean = [
2521 n for n in repo.status(node1=node1, node2=node2, files=files,
2521 n for n in repo.status(node1=node1, node2=node2, files=files,
2522 match=matchfn,
2522 match=matchfn,
2523 list_ignored=all or opts['ignored'],
2523 list_ignored=all or opts['ignored'],
2524 list_clean=all or opts['clean'])]
2524 list_clean=all or opts['clean'])]
2525
2525
2526 changetypes = (('modified', 'M', modified),
2526 changetypes = (('modified', 'M', modified),
2527 ('added', 'A', added),
2527 ('added', 'A', added),
2528 ('removed', 'R', removed),
2528 ('removed', 'R', removed),
2529 ('deleted', '!', deleted),
2529 ('deleted', '!', deleted),
2530 ('unknown', '?', unknown),
2530 ('unknown', '?', unknown),
2531 ('ignored', 'I', ignored))
2531 ('ignored', 'I', ignored))
2532
2532
2533 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2533 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2534
2534
2535 end = opts['print0'] and '\0' or '\n'
2535 end = opts['print0'] and '\0' or '\n'
2536
2536
2537 for opt, char, changes in ([ct for ct in explicit_changetypes
2537 for opt, char, changes in ([ct for ct in explicit_changetypes
2538 if all or opts[ct[0]]]
2538 if all or opts[ct[0]]]
2539 or changetypes):
2539 or changetypes):
2540 if opts['no_status']:
2540 if opts['no_status']:
2541 format = "%%s%s" % end
2541 format = "%%s%s" % end
2542 else:
2542 else:
2543 format = "%s %%s%s" % (char, end)
2543 format = "%s %%s%s" % (char, end)
2544
2544
2545 for f in changes:
2545 for f in changes:
2546 ui.write(format % repo.pathto(f, cwd))
2546 ui.write(format % repo.pathto(f, cwd))
2547 if ((all or opts.get('copies')) and not opts.get('no_status')):
2547 if ((all or opts.get('copies')) and not opts.get('no_status')):
2548 copied = repo.dirstate.copied(f)
2548 copied = repo.dirstate.copied(f)
2549 if copied:
2549 if copied:
2550 ui.write(' %s%s' % (repo.pathto(copied, cwd), end))
2550 ui.write(' %s%s' % (repo.pathto(copied, cwd), end))
2551
2551
2552 def tag(ui, repo, name, rev_=None, **opts):
2552 def tag(ui, repo, name, rev_=None, **opts):
2553 """add a tag for the current or given revision
2553 """add a tag for the current or given revision
2554
2554
2555 Name a particular revision using <name>.
2555 Name a particular revision using <name>.
2556
2556
2557 Tags are used to name particular revisions of the repository and are
2557 Tags are used to name particular revisions of the repository and are
2558 very useful to compare different revision, to go back to significant
2558 very useful to compare different revision, to go back to significant
2559 earlier versions or to mark branch points as releases, etc.
2559 earlier versions or to mark branch points as releases, etc.
2560
2560
2561 If no revision is given, the parent of the working directory is used,
2561 If no revision is given, the parent of the working directory is used,
2562 or tip if no revision is checked out.
2562 or tip if no revision is checked out.
2563
2563
2564 To facilitate version control, distribution, and merging of tags,
2564 To facilitate version control, distribution, and merging of tags,
2565 they are stored as a file named ".hgtags" which is managed
2565 they are stored as a file named ".hgtags" which is managed
2566 similarly to other project files and can be hand-edited if
2566 similarly to other project files and can be hand-edited if
2567 necessary. The file '.hg/localtags' is used for local tags (not
2567 necessary. The file '.hg/localtags' is used for local tags (not
2568 shared among repositories).
2568 shared among repositories).
2569
2569
2570 See 'hg help dates' for a list of formats valid for -d/--date.
2570 See 'hg help dates' for a list of formats valid for -d/--date.
2571 """
2571 """
2572 if name in ['tip', '.', 'null']:
2572 if name in ['tip', '.', 'null']:
2573 raise util.Abort(_("the name '%s' is reserved") % name)
2573 raise util.Abort(_("the name '%s' is reserved") % name)
2574 if rev_ is not None:
2574 if rev_ is not None:
2575 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2575 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2576 "please use 'hg tag [-r REV] NAME' instead\n"))
2576 "please use 'hg tag [-r REV] NAME' instead\n"))
2577 if opts['rev']:
2577 if opts['rev']:
2578 raise util.Abort(_("use only one form to specify the revision"))
2578 raise util.Abort(_("use only one form to specify the revision"))
2579 if opts['rev'] and opts['remove']:
2579 if opts['rev'] and opts['remove']:
2580 raise util.Abort(_("--rev and --remove are incompatible"))
2580 raise util.Abort(_("--rev and --remove are incompatible"))
2581 if opts['rev']:
2581 if opts['rev']:
2582 rev_ = opts['rev']
2582 rev_ = opts['rev']
2583 message = opts['message']
2583 message = opts['message']
2584 if opts['remove']:
2584 if opts['remove']:
2585 tagtype = repo.tagtype(name)
2585 tagtype = repo.tagtype(name)
2586
2586
2587 if not tagtype:
2587 if not tagtype:
2588 raise util.Abort(_('tag %s does not exist') % name)
2588 raise util.Abort(_('tag %s does not exist') % name)
2589 if opts['local'] and tagtype == 'global':
2589 if opts['local'] and tagtype == 'global':
2590 raise util.Abort(_('%s tag is global') % name)
2590 raise util.Abort(_('%s tag is global') % name)
2591 if not opts['local'] and tagtype == 'local':
2591 if not opts['local'] and tagtype == 'local':
2592 raise util.Abort(_('%s tag is local') % name)
2592 raise util.Abort(_('%s tag is local') % name)
2593
2593
2594 rev_ = nullid
2594 rev_ = nullid
2595 if not message:
2595 if not message:
2596 message = _('Removed tag %s') % name
2596 message = _('Removed tag %s') % name
2597 elif name in repo.tags() and not opts['force']:
2597 elif name in repo.tags() and not opts['force']:
2598 raise util.Abort(_('a tag named %s already exists (use -f to force)')
2598 raise util.Abort(_('a tag named %s already exists (use -f to force)')
2599 % name)
2599 % name)
2600 if not rev_ and repo.dirstate.parents()[1] != nullid:
2600 if not rev_ and repo.dirstate.parents()[1] != nullid:
2601 raise util.Abort(_('uncommitted merge - please provide a '
2601 raise util.Abort(_('uncommitted merge - please provide a '
2602 'specific revision'))
2602 'specific revision'))
2603 r = repo.changectx(rev_).node()
2603 r = repo.changectx(rev_).node()
2604
2604
2605 if not message:
2605 if not message:
2606 message = _('Added tag %s for changeset %s') % (name, short(r))
2606 message = _('Added tag %s for changeset %s') % (name, short(r))
2607
2607
2608 repo.tag(name, r, message, opts['local'], opts['user'], opts['date'])
2608 repo.tag(name, r, message, opts['local'], opts['user'], opts['date'])
2609
2609
2610 def tags(ui, repo):
2610 def tags(ui, repo):
2611 """list repository tags
2611 """list repository tags
2612
2612
2613 List the repository tags.
2613 List the repository tags.
2614
2614
2615 This lists both regular and local tags. When the -v/--verbose switch
2615 This lists both regular and local tags. When the -v/--verbose switch
2616 is used, a third column "local" is printed for local tags.
2616 is used, a third column "local" is printed for local tags.
2617 """
2617 """
2618
2618
2619 l = repo.tagslist()
2619 l = repo.tagslist()
2620 l.reverse()
2620 l.reverse()
2621 hexfunc = ui.debugflag and hex or short
2621 hexfunc = ui.debugflag and hex or short
2622 tagtype = ""
2622 tagtype = ""
2623
2623
2624 for t, n in l:
2624 for t, n in l:
2625 if ui.quiet:
2625 if ui.quiet:
2626 ui.write("%s\n" % t)
2626 ui.write("%s\n" % t)
2627 continue
2627 continue
2628
2628
2629 try:
2629 try:
2630 hn = hexfunc(n)
2630 hn = hexfunc(n)
2631 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2631 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2632 except revlog.LookupError:
2632 except revlog.LookupError:
2633 r = " ?:%s" % hn
2633 r = " ?:%s" % hn
2634 else:
2634 else:
2635 spaces = " " * (30 - util.locallen(t))
2635 spaces = " " * (30 - util.locallen(t))
2636 if ui.verbose:
2636 if ui.verbose:
2637 if repo.tagtype(t) == 'local':
2637 if repo.tagtype(t) == 'local':
2638 tagtype = " local"
2638 tagtype = " local"
2639 else:
2639 else:
2640 tagtype = ""
2640 tagtype = ""
2641 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2641 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2642
2642
2643 def tip(ui, repo, **opts):
2643 def tip(ui, repo, **opts):
2644 """show the tip revision
2644 """show the tip revision
2645
2645
2646 Show the tip revision.
2646 Show the tip revision.
2647 """
2647 """
2648 cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count())
2648 cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count())
2649
2649
2650 def unbundle(ui, repo, fname1, *fnames, **opts):
2650 def unbundle(ui, repo, fname1, *fnames, **opts):
2651 """apply one or more changegroup files
2651 """apply one or more changegroup files
2652
2652
2653 Apply one or more compressed changegroup files generated by the
2653 Apply one or more compressed changegroup files generated by the
2654 bundle command.
2654 bundle command.
2655 """
2655 """
2656 fnames = (fname1,) + fnames
2656 fnames = (fname1,) + fnames
2657
2657
2658 lock = None
2658 lock = None
2659 try:
2659 try:
2660 lock = repo.lock()
2660 lock = repo.lock()
2661 for fname in fnames:
2661 for fname in fnames:
2662 if os.path.exists(fname):
2662 if os.path.exists(fname):
2663 f = open(fname, "rb")
2663 f = open(fname, "rb")
2664 else:
2664 else:
2665 f = urllib.urlopen(fname)
2665 f = urllib.urlopen(fname)
2666 gen = changegroup.readbundle(f, fname)
2666 gen = changegroup.readbundle(f, fname)
2667 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2667 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2668 finally:
2668 finally:
2669 del lock
2669 del lock
2670
2670
2671 return postincoming(ui, repo, modheads, opts['update'], None)
2671 return postincoming(ui, repo, modheads, opts['update'], None)
2672
2672
2673 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2673 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2674 """update working directory
2674 """update working directory
2675
2675
2676 Update the working directory to the specified revision, or the
2676 Update the working directory to the specified revision, or the
2677 tip of the current branch if none is specified.
2677 tip of the current branch if none is specified.
2678 See 'hg help dates' for a list of formats valid for -d/--date.
2678 See 'hg help dates' for a list of formats valid for -d/--date.
2679
2679
2680 If there are no outstanding changes in the working directory and
2680 If there are no outstanding changes in the working directory and
2681 there is a linear relationship between the current version and the
2681 there is a linear relationship between the current version and the
2682 requested version, the result is the requested version.
2682 requested version, the result is the requested version.
2683
2683
2684 To merge the working directory with another revision, use the
2684 To merge the working directory with another revision, use the
2685 merge command.
2685 merge command.
2686
2686
2687 By default, update will refuse to run if doing so would require
2687 By default, update will refuse to run if doing so would require
2688 discarding local changes.
2688 discarding local changes.
2689 """
2689 """
2690 if rev and node:
2690 if rev and node:
2691 raise util.Abort(_("please specify just one revision"))
2691 raise util.Abort(_("please specify just one revision"))
2692
2692
2693 if not rev:
2693 if not rev:
2694 rev = node
2694 rev = node
2695
2695
2696 if date:
2696 if date:
2697 if rev:
2697 if rev:
2698 raise util.Abort(_("you can't specify a revision and a date"))
2698 raise util.Abort(_("you can't specify a revision and a date"))
2699 rev = cmdutil.finddate(ui, repo, date)
2699 rev = cmdutil.finddate(ui, repo, date)
2700
2700
2701 if clean:
2701 if clean:
2702 return hg.clean(repo, rev)
2702 return hg.clean(repo, rev)
2703 else:
2703 else:
2704 return hg.update(repo, rev)
2704 return hg.update(repo, rev)
2705
2705
2706 def verify(ui, repo):
2706 def verify(ui, repo):
2707 """verify the integrity of the repository
2707 """verify the integrity of the repository
2708
2708
2709 Verify the integrity of the current repository.
2709 Verify the integrity of the current repository.
2710
2710
2711 This will perform an extensive check of the repository's
2711 This will perform an extensive check of the repository's
2712 integrity, validating the hashes and checksums of each entry in
2712 integrity, validating the hashes and checksums of each entry in
2713 the changelog, manifest, and tracked files, as well as the
2713 the changelog, manifest, and tracked files, as well as the
2714 integrity of their crosslinks and indices.
2714 integrity of their crosslinks and indices.
2715 """
2715 """
2716 return hg.verify(repo)
2716 return hg.verify(repo)
2717
2717
2718 def version_(ui):
2718 def version_(ui):
2719 """output version and copyright information"""
2719 """output version and copyright information"""
2720 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2720 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2721 % version.get_version())
2721 % version.get_version())
2722 ui.status(_(
2722 ui.status(_(
2723 "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
2723 "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
2724 "This is free software; see the source for copying conditions. "
2724 "This is free software; see the source for copying conditions. "
2725 "There is NO\nwarranty; "
2725 "There is NO\nwarranty; "
2726 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2726 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2727 ))
2727 ))
2728
2728
2729 # Command options and aliases are listed here, alphabetically
2729 # Command options and aliases are listed here, alphabetically
2730
2730
2731 globalopts = [
2731 globalopts = [
2732 ('R', 'repository', '',
2732 ('R', 'repository', '',
2733 _('repository root directory or symbolic path name')),
2733 _('repository root directory or symbolic path name')),
2734 ('', 'cwd', '', _('change working directory')),
2734 ('', 'cwd', '', _('change working directory')),
2735 ('y', 'noninteractive', None,
2735 ('y', 'noninteractive', None,
2736 _('do not prompt, assume \'yes\' for any required answers')),
2736 _('do not prompt, assume \'yes\' for any required answers')),
2737 ('q', 'quiet', None, _('suppress output')),
2737 ('q', 'quiet', None, _('suppress output')),
2738 ('v', 'verbose', None, _('enable additional output')),
2738 ('v', 'verbose', None, _('enable additional output')),
2739 ('', 'config', [], _('set/override config option')),
2739 ('', 'config', [], _('set/override config option')),
2740 ('', 'debug', None, _('enable debugging output')),
2740 ('', 'debug', None, _('enable debugging output')),
2741 ('', 'debugger', None, _('start debugger')),
2741 ('', 'debugger', None, _('start debugger')),
2742 ('', 'encoding', util._encoding, _('set the charset encoding')),
2742 ('', 'encoding', util._encoding, _('set the charset encoding')),
2743 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2743 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2744 ('', 'lsprof', None, _('print improved command execution profile')),
2744 ('', 'lsprof', None, _('print improved command execution profile')),
2745 ('', 'traceback', None, _('print traceback on exception')),
2745 ('', 'traceback', None, _('print traceback on exception')),
2746 ('', 'time', None, _('time how long the command takes')),
2746 ('', 'time', None, _('time how long the command takes')),
2747 ('', 'profile', None, _('print command execution profile')),
2747 ('', 'profile', None, _('print command execution profile')),
2748 ('', 'version', None, _('output version information and exit')),
2748 ('', 'version', None, _('output version information and exit')),
2749 ('h', 'help', None, _('display help and exit')),
2749 ('h', 'help', None, _('display help and exit')),
2750 ]
2750 ]
2751
2751
2752 dryrunopts = [('n', 'dry-run', None,
2752 dryrunopts = [('n', 'dry-run', None,
2753 _('do not perform actions, just print output'))]
2753 _('do not perform actions, just print output'))]
2754
2754
2755 remoteopts = [
2755 remoteopts = [
2756 ('e', 'ssh', '', _('specify ssh command to use')),
2756 ('e', 'ssh', '', _('specify ssh command to use')),
2757 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2757 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2758 ]
2758 ]
2759
2759
2760 walkopts = [
2760 walkopts = [
2761 ('I', 'include', [], _('include names matching the given patterns')),
2761 ('I', 'include', [], _('include names matching the given patterns')),
2762 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2762 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2763 ]
2763 ]
2764
2764
2765 commitopts = [
2765 commitopts = [
2766 ('m', 'message', '', _('use <text> as commit message')),
2766 ('m', 'message', '', _('use <text> as commit message')),
2767 ('l', 'logfile', '', _('read commit message from <file>')),
2767 ('l', 'logfile', '', _('read commit message from <file>')),
2768 ]
2768 ]
2769
2769
2770 commitopts2 = [
2770 commitopts2 = [
2771 ('d', 'date', '', _('record datecode as commit date')),
2771 ('d', 'date', '', _('record datecode as commit date')),
2772 ('u', 'user', '', _('record user as committer')),
2772 ('u', 'user', '', _('record user as committer')),
2773 ]
2773 ]
2774
2774
2775 templateopts = [
2776 ('', 'style', '', _('display using template map file')),
2777 ('', 'template', '', _('display with template')),
2778 ]
2779
2780 logopts = [
2781 ('p', 'patch', None, _('show patch')),
2782 ('l', 'limit', '', _('limit number of changes displayed')),
2783 ('M', 'no-merges', None, _('do not show merges')),
2784 ] + templateopts
2785
2775 table = {
2786 table = {
2776 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2787 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2777 "addremove":
2788 "addremove":
2778 (addremove,
2789 (addremove,
2779 [('s', 'similarity', '',
2790 [('s', 'similarity', '',
2780 _('guess renamed files by similarity (0<=s<=100)')),
2791 _('guess renamed files by similarity (0<=s<=100)')),
2781 ] + walkopts + dryrunopts,
2792 ] + walkopts + dryrunopts,
2782 _('hg addremove [OPTION]... [FILE]...')),
2793 _('hg addremove [OPTION]... [FILE]...')),
2783 "^annotate|blame":
2794 "^annotate|blame":
2784 (annotate,
2795 (annotate,
2785 [('r', 'rev', '', _('annotate the specified revision')),
2796 [('r', 'rev', '', _('annotate the specified revision')),
2786 ('f', 'follow', None, _('follow file copies and renames')),
2797 ('f', 'follow', None, _('follow file copies and renames')),
2787 ('a', 'text', None, _('treat all files as text')),
2798 ('a', 'text', None, _('treat all files as text')),
2788 ('u', 'user', None, _('list the author (long with -v)')),
2799 ('u', 'user', None, _('list the author (long with -v)')),
2789 ('d', 'date', None, _('list the date (short with -q)')),
2800 ('d', 'date', None, _('list the date (short with -q)')),
2790 ('n', 'number', None, _('list the revision number (default)')),
2801 ('n', 'number', None, _('list the revision number (default)')),
2791 ('c', 'changeset', None, _('list the changeset')),
2802 ('c', 'changeset', None, _('list the changeset')),
2792 ('l', 'line-number', None,
2803 ('l', 'line-number', None,
2793 _('show line number at the first appearance'))
2804 _('show line number at the first appearance'))
2794 ] + walkopts,
2805 ] + walkopts,
2795 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2806 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2796 "archive":
2807 "archive":
2797 (archive,
2808 (archive,
2798 [('', 'no-decode', None, _('do not pass files through decoders')),
2809 [('', 'no-decode', None, _('do not pass files through decoders')),
2799 ('p', 'prefix', '', _('directory prefix for files in archive')),
2810 ('p', 'prefix', '', _('directory prefix for files in archive')),
2800 ('r', 'rev', '', _('revision to distribute')),
2811 ('r', 'rev', '', _('revision to distribute')),
2801 ('t', 'type', '', _('type of distribution to create')),
2812 ('t', 'type', '', _('type of distribution to create')),
2802 ] + walkopts,
2813 ] + walkopts,
2803 _('hg archive [OPTION]... DEST')),
2814 _('hg archive [OPTION]... DEST')),
2804 "backout":
2815 "backout":
2805 (backout,
2816 (backout,
2806 [('', 'merge', None,
2817 [('', 'merge', None,
2807 _('merge with old dirstate parent after backout')),
2818 _('merge with old dirstate parent after backout')),
2808 ('', 'parent', '', _('parent to choose when backing out merge')),
2819 ('', 'parent', '', _('parent to choose when backing out merge')),
2809 ('r', 'rev', '', _('revision to backout')),
2820 ('r', 'rev', '', _('revision to backout')),
2810 ] + walkopts + commitopts + commitopts2,
2821 ] + walkopts + commitopts + commitopts2,
2811 _('hg backout [OPTION]... [-r] REV')),
2822 _('hg backout [OPTION]... [-r] REV')),
2812 "bisect":
2823 "bisect":
2813 (bisect,
2824 (bisect,
2814 [('r', 'reset', False, _('reset bisect state')),
2825 [('r', 'reset', False, _('reset bisect state')),
2815 ('g', 'good', False, _('mark changeset good')),
2826 ('g', 'good', False, _('mark changeset good')),
2816 ('b', 'bad', False, _('mark changeset bad')),
2827 ('b', 'bad', False, _('mark changeset bad')),
2817 ('s', 'skip', False, _('skip testing changeset')),
2828 ('s', 'skip', False, _('skip testing changeset')),
2818 ('U', 'noupdate', False, _('do not update to target'))],
2829 ('U', 'noupdate', False, _('do not update to target'))],
2819 _("hg bisect [-gbsr] [REV]")),
2830 _("hg bisect [-gbsr] [REV]")),
2820 "branch":
2831 "branch":
2821 (branch,
2832 (branch,
2822 [('f', 'force', None,
2833 [('f', 'force', None,
2823 _('set branch name even if it shadows an existing branch'))],
2834 _('set branch name even if it shadows an existing branch'))],
2824 _('hg branch [-f] [NAME]')),
2835 _('hg branch [-f] [NAME]')),
2825 "branches":
2836 "branches":
2826 (branches,
2837 (branches,
2827 [('a', 'active', False,
2838 [('a', 'active', False,
2828 _('show only branches that have unmerged heads'))],
2839 _('show only branches that have unmerged heads'))],
2829 _('hg branches [-a]')),
2840 _('hg branches [-a]')),
2830 "bundle":
2841 "bundle":
2831 (bundle,
2842 (bundle,
2832 [('f', 'force', None,
2843 [('f', 'force', None,
2833 _('run even when remote repository is unrelated')),
2844 _('run even when remote repository is unrelated')),
2834 ('r', 'rev', [],
2845 ('r', 'rev', [],
2835 _('a changeset you would like to bundle')),
2846 _('a changeset you would like to bundle')),
2836 ('', 'base', [],
2847 ('', 'base', [],
2837 _('a base changeset to specify instead of a destination')),
2848 _('a base changeset to specify instead of a destination')),
2838 ('a', 'all', None,
2849 ('a', 'all', None,
2839 _('bundle all changesets in the repository')),
2850 _('bundle all changesets in the repository')),
2840 ] + remoteopts,
2851 ] + remoteopts,
2841 _('hg bundle [-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
2852 _('hg bundle [-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
2842 "cat":
2853 "cat":
2843 (cat,
2854 (cat,
2844 [('o', 'output', '', _('print output to file with formatted name')),
2855 [('o', 'output', '', _('print output to file with formatted name')),
2845 ('r', 'rev', '', _('print the given revision')),
2856 ('r', 'rev', '', _('print the given revision')),
2846 ('', 'decode', None, _('apply any matching decode filter')),
2857 ('', 'decode', None, _('apply any matching decode filter')),
2847 ] + walkopts,
2858 ] + walkopts,
2848 _('hg cat [OPTION]... FILE...')),
2859 _('hg cat [OPTION]... FILE...')),
2849 "^clone":
2860 "^clone":
2850 (clone,
2861 (clone,
2851 [('U', 'noupdate', None, _('do not update the new working directory')),
2862 [('U', 'noupdate', None, _('do not update the new working directory')),
2852 ('r', 'rev', [],
2863 ('r', 'rev', [],
2853 _('a changeset you would like to have after cloning')),
2864 _('a changeset you would like to have after cloning')),
2854 ('', 'pull', None, _('use pull protocol to copy metadata')),
2865 ('', 'pull', None, _('use pull protocol to copy metadata')),
2855 ('', 'uncompressed', None,
2866 ('', 'uncompressed', None,
2856 _('use uncompressed transfer (fast over LAN)')),
2867 _('use uncompressed transfer (fast over LAN)')),
2857 ] + remoteopts,
2868 ] + remoteopts,
2858 _('hg clone [OPTION]... SOURCE [DEST]')),
2869 _('hg clone [OPTION]... SOURCE [DEST]')),
2859 "^commit|ci":
2870 "^commit|ci":
2860 (commit,
2871 (commit,
2861 [('A', 'addremove', None,
2872 [('A', 'addremove', None,
2862 _('mark new/missing files as added/removed before committing')),
2873 _('mark new/missing files as added/removed before committing')),
2863 ] + walkopts + commitopts + commitopts2,
2874 ] + walkopts + commitopts + commitopts2,
2864 _('hg commit [OPTION]... [FILE]...')),
2875 _('hg commit [OPTION]... [FILE]...')),
2865 "copy|cp":
2876 "copy|cp":
2866 (copy,
2877 (copy,
2867 [('A', 'after', None, _('record a copy that has already occurred')),
2878 [('A', 'after', None, _('record a copy that has already occurred')),
2868 ('f', 'force', None,
2879 ('f', 'force', None,
2869 _('forcibly copy over an existing managed file')),
2880 _('forcibly copy over an existing managed file')),
2870 ] + walkopts + dryrunopts,
2881 ] + walkopts + dryrunopts,
2871 _('hg copy [OPTION]... [SOURCE]... DEST')),
2882 _('hg copy [OPTION]... [SOURCE]... DEST')),
2872 "debugancestor": (debugancestor, [],
2883 "debugancestor": (debugancestor, [],
2873 _('hg debugancestor [INDEX] REV1 REV2')),
2884 _('hg debugancestor [INDEX] REV1 REV2')),
2874 "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
2885 "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
2875 "debugcomplete":
2886 "debugcomplete":
2876 (debugcomplete,
2887 (debugcomplete,
2877 [('o', 'options', None, _('show the command options'))],
2888 [('o', 'options', None, _('show the command options'))],
2878 _('hg debugcomplete [-o] CMD')),
2889 _('hg debugcomplete [-o] CMD')),
2879 "debugdate":
2890 "debugdate":
2880 (debugdate,
2891 (debugdate,
2881 [('e', 'extended', None, _('try extended date formats'))],
2892 [('e', 'extended', None, _('try extended date formats'))],
2882 _('hg debugdate [-e] DATE [RANGE]')),
2893 _('hg debugdate [-e] DATE [RANGE]')),
2883 "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
2894 "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
2884 "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
2895 "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
2885 "debugindex": (debugindex, [], _('hg debugindex FILE')),
2896 "debugindex": (debugindex, [], _('hg debugindex FILE')),
2886 "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
2897 "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
2887 "debuginstall": (debuginstall, [], _('hg debuginstall')),
2898 "debuginstall": (debuginstall, [], _('hg debuginstall')),
2888 "debugrawcommit|rawcommit":
2899 "debugrawcommit|rawcommit":
2889 (rawcommit,
2900 (rawcommit,
2890 [('p', 'parent', [], _('parent')),
2901 [('p', 'parent', [], _('parent')),
2891 ('F', 'files', '', _('file list'))
2902 ('F', 'files', '', _('file list'))
2892 ] + commitopts + commitopts2,
2903 ] + commitopts + commitopts2,
2893 _('hg debugrawcommit [OPTION]... [FILE]...')),
2904 _('hg debugrawcommit [OPTION]... [FILE]...')),
2894 "debugrebuildstate":
2905 "debugrebuildstate":
2895 (debugrebuildstate,
2906 (debugrebuildstate,
2896 [('r', 'rev', '', _('revision to rebuild to'))],
2907 [('r', 'rev', '', _('revision to rebuild to'))],
2897 _('hg debugrebuildstate [-r REV] [REV]')),
2908 _('hg debugrebuildstate [-r REV] [REV]')),
2898 "debugrename":
2909 "debugrename":
2899 (debugrename,
2910 (debugrename,
2900 [('r', 'rev', '', _('revision to debug'))],
2911 [('r', 'rev', '', _('revision to debug'))],
2901 _('hg debugrename [-r REV] FILE')),
2912 _('hg debugrename [-r REV] FILE')),
2902 "debugsetparents":
2913 "debugsetparents":
2903 (debugsetparents,
2914 (debugsetparents,
2904 [],
2915 [],
2905 _('hg debugsetparents REV1 [REV2]')),
2916 _('hg debugsetparents REV1 [REV2]')),
2906 "debugstate": (debugstate, [], _('hg debugstate')),
2917 "debugstate": (debugstate, [], _('hg debugstate')),
2907 "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
2918 "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
2908 "^diff":
2919 "^diff":
2909 (diff,
2920 (diff,
2910 [('r', 'rev', [], _('revision')),
2921 [('r', 'rev', [], _('revision')),
2911 ('a', 'text', None, _('treat all files as text')),
2922 ('a', 'text', None, _('treat all files as text')),
2912 ('p', 'show-function', None,
2923 ('p', 'show-function', None,
2913 _('show which function each change is in')),
2924 _('show which function each change is in')),
2914 ('g', 'git', None, _('use git extended diff format')),
2925 ('g', 'git', None, _('use git extended diff format')),
2915 ('', 'nodates', None, _("don't include dates in diff headers")),
2926 ('', 'nodates', None, _("don't include dates in diff headers")),
2916 ('w', 'ignore-all-space', None,
2927 ('w', 'ignore-all-space', None,
2917 _('ignore white space when comparing lines')),
2928 _('ignore white space when comparing lines')),
2918 ('b', 'ignore-space-change', None,
2929 ('b', 'ignore-space-change', None,
2919 _('ignore changes in the amount of white space')),
2930 _('ignore changes in the amount of white space')),
2920 ('B', 'ignore-blank-lines', None,
2931 ('B', 'ignore-blank-lines', None,
2921 _('ignore changes whose lines are all blank')),
2932 _('ignore changes whose lines are all blank')),
2922 ('U', 'unified', 3,
2933 ('U', 'unified', 3,
2923 _('number of lines of context to show'))
2934 _('number of lines of context to show'))
2924 ] + walkopts,
2935 ] + walkopts,
2925 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
2936 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
2926 "^export":
2937 "^export":
2927 (export,
2938 (export,
2928 [('o', 'output', '', _('print output to file with formatted name')),
2939 [('o', 'output', '', _('print output to file with formatted name')),
2929 ('a', 'text', None, _('treat all files as text')),
2940 ('a', 'text', None, _('treat all files as text')),
2930 ('g', 'git', None, _('use git extended diff format')),
2941 ('g', 'git', None, _('use git extended diff format')),
2931 ('', 'nodates', None, _("don't include dates in diff headers")),
2942 ('', 'nodates', None, _("don't include dates in diff headers")),
2932 ('', 'switch-parent', None, _('diff against the second parent'))],
2943 ('', 'switch-parent', None, _('diff against the second parent'))],
2933 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
2944 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
2934 "grep":
2945 "grep":
2935 (grep,
2946 (grep,
2936 [('0', 'print0', None, _('end fields with NUL')),
2947 [('0', 'print0', None, _('end fields with NUL')),
2937 ('', 'all', None, _('print all revisions that match')),
2948 ('', 'all', None, _('print all revisions that match')),
2938 ('f', 'follow', None,
2949 ('f', 'follow', None,
2939 _('follow changeset history, or file history across copies and renames')),
2950 _('follow changeset history, or file history across copies and renames')),
2940 ('i', 'ignore-case', None, _('ignore case when matching')),
2951 ('i', 'ignore-case', None, _('ignore case when matching')),
2941 ('l', 'files-with-matches', None,
2952 ('l', 'files-with-matches', None,
2942 _('print only filenames and revs that match')),
2953 _('print only filenames and revs that match')),
2943 ('n', 'line-number', None, _('print matching line numbers')),
2954 ('n', 'line-number', None, _('print matching line numbers')),
2944 ('r', 'rev', [], _('search in given revision range')),
2955 ('r', 'rev', [], _('search in given revision range')),
2945 ('u', 'user', None, _('list the author (long with -v)')),
2956 ('u', 'user', None, _('list the author (long with -v)')),
2946 ('d', 'date', None, _('list the date (short with -q)')),
2957 ('d', 'date', None, _('list the date (short with -q)')),
2947 ] + walkopts,
2958 ] + walkopts,
2948 _('hg grep [OPTION]... PATTERN [FILE]...')),
2959 _('hg grep [OPTION]... PATTERN [FILE]...')),
2949 "heads":
2960 "heads":
2950 (heads,
2961 (heads,
2951 [('', 'style', '', _('display using template map file')),
2962 [('r', 'rev', '', _('show only heads which are descendants of rev')),
2952 ('r', 'rev', '', _('show only heads which are descendants of rev')),
2963 ] + templateopts,
2953 ('', 'template', '', _('display with template'))],
2954 _('hg heads [-r REV] [REV]...')),
2964 _('hg heads [-r REV] [REV]...')),
2955 "help": (help_, [], _('hg help [COMMAND]')),
2965 "help": (help_, [], _('hg help [COMMAND]')),
2956 "identify|id":
2966 "identify|id":
2957 (identify,
2967 (identify,
2958 [('r', 'rev', '', _('identify the specified rev')),
2968 [('r', 'rev', '', _('identify the specified rev')),
2959 ('n', 'num', None, _('show local revision number')),
2969 ('n', 'num', None, _('show local revision number')),
2960 ('i', 'id', None, _('show global revision id')),
2970 ('i', 'id', None, _('show global revision id')),
2961 ('b', 'branch', None, _('show branch')),
2971 ('b', 'branch', None, _('show branch')),
2962 ('t', 'tags', None, _('show tags'))],
2972 ('t', 'tags', None, _('show tags'))],
2963 _('hg identify [-nibt] [-r REV] [SOURCE]')),
2973 _('hg identify [-nibt] [-r REV] [SOURCE]')),
2964 "import|patch":
2974 "import|patch":
2965 (import_,
2975 (import_,
2966 [('p', 'strip', 1,
2976 [('p', 'strip', 1,
2967 _('directory strip option for patch. This has the same\n'
2977 _('directory strip option for patch. This has the same\n'
2968 'meaning as the corresponding patch option')),
2978 'meaning as the corresponding patch option')),
2969 ('b', 'base', '', _('base path')),
2979 ('b', 'base', '', _('base path')),
2970 ('f', 'force', None,
2980 ('f', 'force', None,
2971 _('skip check for outstanding uncommitted changes')),
2981 _('skip check for outstanding uncommitted changes')),
2972 ('', 'no-commit', None, _("don't commit, just update the working directory")),
2982 ('', 'no-commit', None, _("don't commit, just update the working directory")),
2973 ('', 'exact', None,
2983 ('', 'exact', None,
2974 _('apply patch to the nodes from which it was generated')),
2984 _('apply patch to the nodes from which it was generated')),
2975 ('', 'import-branch', None,
2985 ('', 'import-branch', None,
2976 _('Use any branch information in patch (implied by --exact)'))] +
2986 _('Use any branch information in patch (implied by --exact)'))] +
2977 commitopts + commitopts2,
2987 commitopts + commitopts2,
2978 _('hg import [OPTION]... PATCH...')),
2988 _('hg import [OPTION]... PATCH...')),
2979 "incoming|in":
2989 "incoming|in":
2980 (incoming,
2990 (incoming,
2981 [('M', 'no-merges', None, _('do not show merges')),
2991 [('f', 'force', None,
2982 ('f', 'force', None,
2983 _('run even when remote repository is unrelated')),
2992 _('run even when remote repository is unrelated')),
2984 ('', 'style', '', _('display using template map file')),
2985 ('n', 'newest-first', None, _('show newest record first')),
2993 ('n', 'newest-first', None, _('show newest record first')),
2986 ('', 'bundle', '', _('file to store the bundles into')),
2994 ('', 'bundle', '', _('file to store the bundles into')),
2987 ('p', 'patch', None, _('show patch')),
2988 ('l', 'limit', '', _('limit number of changes displayed')),
2989 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2995 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2990 ('', 'template', '', _('display with template')),
2996 ] + logopts + remoteopts,
2991 ] + remoteopts,
2992 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
2997 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
2993 ' [--bundle FILENAME] [SOURCE]')),
2998 ' [--bundle FILENAME] [SOURCE]')),
2994 "^init":
2999 "^init":
2995 (init,
3000 (init,
2996 remoteopts,
3001 remoteopts,
2997 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
3002 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
2998 "locate":
3003 "locate":
2999 (locate,
3004 (locate,
3000 [('r', 'rev', '', _('search the repository as it stood at rev')),
3005 [('r', 'rev', '', _('search the repository as it stood at rev')),
3001 ('0', 'print0', None,
3006 ('0', 'print0', None,
3002 _('end filenames with NUL, for use with xargs')),
3007 _('end filenames with NUL, for use with xargs')),
3003 ('f', 'fullpath', None,
3008 ('f', 'fullpath', None,
3004 _('print complete paths from the filesystem root')),
3009 _('print complete paths from the filesystem root')),
3005 ] + walkopts,
3010 ] + walkopts,
3006 _('hg locate [OPTION]... [PATTERN]...')),
3011 _('hg locate [OPTION]... [PATTERN]...')),
3007 "^log|history":
3012 "^log|history":
3008 (log,
3013 (log,
3009 [('f', 'follow', None,
3014 [('f', 'follow', None,
3010 _('follow changeset history, or file history across copies and renames')),
3015 _('follow changeset history, or file history across copies and renames')),
3011 ('', 'follow-first', None,
3016 ('', 'follow-first', None,
3012 _('only follow the first parent of merge changesets')),
3017 _('only follow the first parent of merge changesets')),
3013 ('d', 'date', '', _('show revs matching date spec')),
3018 ('d', 'date', '', _('show revs matching date spec')),
3014 ('C', 'copies', None, _('show copied files')),
3019 ('C', 'copies', None, _('show copied files')),
3015 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3020 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3016 ('l', 'limit', '', _('limit number of changes displayed')),
3017 ('r', 'rev', [], _('show the specified revision or range')),
3021 ('r', 'rev', [], _('show the specified revision or range')),
3018 ('', 'removed', None, _('include revs where files were removed')),
3022 ('', 'removed', None, _('include revs where files were removed')),
3019 ('M', 'no-merges', None, _('do not show merges')),
3020 ('', 'style', '', _('display using template map file')),
3021 ('m', 'only-merges', None, _('show only merges')),
3023 ('m', 'only-merges', None, _('show only merges')),
3022 ('b', 'only-branch', [],
3024 ('b', 'only-branch', [],
3023 _('show only changesets within the given named branch')),
3025 _('show only changesets within the given named branch')),
3024 ('p', 'patch', None, _('show patch')),
3025 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3026 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3026 ('', 'template', '', _('display with template')),
3027 ] + logopts + walkopts,
3027 ] + walkopts,
3028 _('hg log [OPTION]... [FILE]')),
3028 _('hg log [OPTION]... [FILE]')),
3029 "manifest":
3029 "manifest":
3030 (manifest,
3030 (manifest,
3031 [('r', 'rev', '', _('revision to display'))],
3031 [('r', 'rev', '', _('revision to display'))],
3032 _('hg manifest [-r REV]')),
3032 _('hg manifest [-r REV]')),
3033 "^merge":
3033 "^merge":
3034 (merge,
3034 (merge,
3035 [('f', 'force', None, _('force a merge with outstanding changes')),
3035 [('f', 'force', None, _('force a merge with outstanding changes')),
3036 ('r', 'rev', '', _('revision to merge')),
3036 ('r', 'rev', '', _('revision to merge')),
3037 ],
3037 ],
3038 _('hg merge [-f] [[-r] REV]')),
3038 _('hg merge [-f] [[-r] REV]')),
3039 "outgoing|out":
3039 "outgoing|out":
3040 (outgoing,
3040 (outgoing,
3041 [('M', 'no-merges', None, _('do not show merges')),
3041 [('f', 'force', None,
3042 ('f', 'force', None,
3043 _('run even when remote repository is unrelated')),
3042 _('run even when remote repository is unrelated')),
3044 ('p', 'patch', None, _('show patch')),
3045 ('', 'style', '', _('display using template map file')),
3046 ('l', 'limit', '', _('limit number of changes displayed')),
3047 ('r', 'rev', [], _('a specific revision you would like to push')),
3043 ('r', 'rev', [], _('a specific revision you would like to push')),
3048 ('n', 'newest-first', None, _('show newest record first')),
3044 ('n', 'newest-first', None, _('show newest record first')),
3049 ('', 'template', '', _('display with template')),
3045 ] + logopts + remoteopts,
3050 ] + remoteopts,
3051 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3046 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3052 "^parents":
3047 "^parents":
3053 (parents,
3048 (parents,
3054 [('r', 'rev', '', _('show parents from the specified rev')),
3049 [('r', 'rev', '', _('show parents from the specified rev')),
3055 ('', 'style', '', _('display using template map file')),
3050 ] + templateopts,
3056 ('', 'template', '', _('display with template'))],
3057 _('hg parents [-r REV] [FILE]')),
3051 _('hg parents [-r REV] [FILE]')),
3058 "paths": (paths, [], _('hg paths [NAME]')),
3052 "paths": (paths, [], _('hg paths [NAME]')),
3059 "^pull":
3053 "^pull":
3060 (pull,
3054 (pull,
3061 [('u', 'update', None,
3055 [('u', 'update', None,
3062 _('update to new tip if changesets were pulled')),
3056 _('update to new tip if changesets were pulled')),
3063 ('f', 'force', None,
3057 ('f', 'force', None,
3064 _('run even when remote repository is unrelated')),
3058 _('run even when remote repository is unrelated')),
3065 ('r', 'rev', [],
3059 ('r', 'rev', [],
3066 _('a specific revision up to which you would like to pull')),
3060 _('a specific revision up to which you would like to pull')),
3067 ] + remoteopts,
3061 ] + remoteopts,
3068 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3062 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3069 "^push":
3063 "^push":
3070 (push,
3064 (push,
3071 [('f', 'force', None, _('force push')),
3065 [('f', 'force', None, _('force push')),
3072 ('r', 'rev', [], _('a specific revision you would like to push')),
3066 ('r', 'rev', [], _('a specific revision you would like to push')),
3073 ] + remoteopts,
3067 ] + remoteopts,
3074 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3068 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3075 "recover": (recover, [], _('hg recover')),
3069 "recover": (recover, [], _('hg recover')),
3076 "^remove|rm":
3070 "^remove|rm":
3077 (remove,
3071 (remove,
3078 [('A', 'after', None, _('record remove without deleting')),
3072 [('A', 'after', None, _('record remove without deleting')),
3079 ('f', 'force', None, _('remove file even if modified')),
3073 ('f', 'force', None, _('remove file even if modified')),
3080 ] + walkopts,
3074 ] + walkopts,
3081 _('hg remove [OPTION]... FILE...')),
3075 _('hg remove [OPTION]... FILE...')),
3082 "rename|mv":
3076 "rename|mv":
3083 (rename,
3077 (rename,
3084 [('A', 'after', None, _('record a rename that has already occurred')),
3078 [('A', 'after', None, _('record a rename that has already occurred')),
3085 ('f', 'force', None,
3079 ('f', 'force', None,
3086 _('forcibly copy over an existing managed file')),
3080 _('forcibly copy over an existing managed file')),
3087 ] + walkopts + dryrunopts,
3081 ] + walkopts + dryrunopts,
3088 _('hg rename [OPTION]... SOURCE... DEST')),
3082 _('hg rename [OPTION]... SOURCE... DEST')),
3089 "revert":
3083 "revert":
3090 (revert,
3084 (revert,
3091 [('a', 'all', None, _('revert all changes when no arguments given')),
3085 [('a', 'all', None, _('revert all changes when no arguments given')),
3092 ('d', 'date', '', _('tipmost revision matching date')),
3086 ('d', 'date', '', _('tipmost revision matching date')),
3093 ('r', 'rev', '', _('revision to revert to')),
3087 ('r', 'rev', '', _('revision to revert to')),
3094 ('', 'no-backup', None, _('do not save backup copies of files')),
3088 ('', 'no-backup', None, _('do not save backup copies of files')),
3095 ] + walkopts + dryrunopts,
3089 ] + walkopts + dryrunopts,
3096 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3090 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3097 "rollback": (rollback, [], _('hg rollback')),
3091 "rollback": (rollback, [], _('hg rollback')),
3098 "root": (root, [], _('hg root')),
3092 "root": (root, [], _('hg root')),
3099 "^serve":
3093 "^serve":
3100 (serve,
3094 (serve,
3101 [('A', 'accesslog', '', _('name of access log file to write to')),
3095 [('A', 'accesslog', '', _('name of access log file to write to')),
3102 ('d', 'daemon', None, _('run server in background')),
3096 ('d', 'daemon', None, _('run server in background')),
3103 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3097 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3104 ('E', 'errorlog', '', _('name of error log file to write to')),
3098 ('E', 'errorlog', '', _('name of error log file to write to')),
3105 ('p', 'port', 0, _('port to use (default: 8000)')),
3099 ('p', 'port', 0, _('port to use (default: 8000)')),
3106 ('a', 'address', '', _('address to use')),
3100 ('a', 'address', '', _('address to use')),
3107 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3101 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3108 ('n', 'name', '',
3102 ('n', 'name', '',
3109 _('name to show in web pages (default: working dir)')),
3103 _('name to show in web pages (default: working dir)')),
3110 ('', 'webdir-conf', '', _('name of the webdir config file'
3104 ('', 'webdir-conf', '', _('name of the webdir config file'
3111 ' (serve more than one repo)')),
3105 ' (serve more than one repo)')),
3112 ('', 'pid-file', '', _('name of file to write process ID to')),
3106 ('', 'pid-file', '', _('name of file to write process ID to')),
3113 ('', 'stdio', None, _('for remote clients')),
3107 ('', 'stdio', None, _('for remote clients')),
3114 ('t', 'templates', '', _('web templates to use')),
3108 ('t', 'templates', '', _('web templates to use')),
3115 ('', 'style', '', _('template style to use')),
3109 ('', 'style', '', _('template style to use')),
3116 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3110 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3117 ('', 'certificate', '', _('SSL certificate file'))],
3111 ('', 'certificate', '', _('SSL certificate file'))],
3118 _('hg serve [OPTION]...')),
3112 _('hg serve [OPTION]...')),
3119 "showconfig|debugconfig":
3113 "showconfig|debugconfig":
3120 (showconfig,
3114 (showconfig,
3121 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3115 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3122 _('hg showconfig [-u] [NAME]...')),
3116 _('hg showconfig [-u] [NAME]...')),
3123 "^status|st":
3117 "^status|st":
3124 (status,
3118 (status,
3125 [('A', 'all', None, _('show status of all files')),
3119 [('A', 'all', None, _('show status of all files')),
3126 ('m', 'modified', None, _('show only modified files')),
3120 ('m', 'modified', None, _('show only modified files')),
3127 ('a', 'added', None, _('show only added files')),
3121 ('a', 'added', None, _('show only added files')),
3128 ('r', 'removed', None, _('show only removed files')),
3122 ('r', 'removed', None, _('show only removed files')),
3129 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3123 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3130 ('c', 'clean', None, _('show only files without changes')),
3124 ('c', 'clean', None, _('show only files without changes')),
3131 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3125 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3132 ('i', 'ignored', None, _('show only ignored files')),
3126 ('i', 'ignored', None, _('show only ignored files')),
3133 ('n', 'no-status', None, _('hide status prefix')),
3127 ('n', 'no-status', None, _('hide status prefix')),
3134 ('C', 'copies', None, _('show source of copied files')),
3128 ('C', 'copies', None, _('show source of copied files')),
3135 ('0', 'print0', None,
3129 ('0', 'print0', None,
3136 _('end filenames with NUL, for use with xargs')),
3130 _('end filenames with NUL, for use with xargs')),
3137 ('', 'rev', [], _('show difference from revision')),
3131 ('', 'rev', [], _('show difference from revision')),
3138 ] + walkopts,
3132 ] + walkopts,
3139 _('hg status [OPTION]... [FILE]...')),
3133 _('hg status [OPTION]... [FILE]...')),
3140 "tag":
3134 "tag":
3141 (tag,
3135 (tag,
3142 [('f', 'force', None, _('replace existing tag')),
3136 [('f', 'force', None, _('replace existing tag')),
3143 ('l', 'local', None, _('make the tag local')),
3137 ('l', 'local', None, _('make the tag local')),
3144 ('r', 'rev', '', _('revision to tag')),
3138 ('r', 'rev', '', _('revision to tag')),
3145 ('', 'remove', None, _('remove a tag')),
3139 ('', 'remove', None, _('remove a tag')),
3146 # -l/--local is already there, commitopts cannot be used
3140 # -l/--local is already there, commitopts cannot be used
3147 ('m', 'message', '', _('use <text> as commit message')),
3141 ('m', 'message', '', _('use <text> as commit message')),
3148 ] + commitopts2,
3142 ] + commitopts2,
3149 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
3143 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
3150 "tags": (tags, [], _('hg tags')),
3144 "tags": (tags, [], _('hg tags')),
3151 "tip":
3145 "tip":
3152 (tip,
3146 (tip,
3153 [('', 'style', '', _('display using template map file')),
3147 [('p', 'patch', None, _('show patch')),
3154 ('p', 'patch', None, _('show patch')),
3148 ] + templateopts,
3155 ('', 'template', '', _('display with template'))],
3156 _('hg tip [-p]')),
3149 _('hg tip [-p]')),
3157 "unbundle":
3150 "unbundle":
3158 (unbundle,
3151 (unbundle,
3159 [('u', 'update', None,
3152 [('u', 'update', None,
3160 _('update to new tip if changesets were unbundled'))],
3153 _('update to new tip if changesets were unbundled'))],
3161 _('hg unbundle [-u] FILE...')),
3154 _('hg unbundle [-u] FILE...')),
3162 "^update|up|checkout|co":
3155 "^update|up|checkout|co":
3163 (update,
3156 (update,
3164 [('C', 'clean', None, _('overwrite locally modified files')),
3157 [('C', 'clean', None, _('overwrite locally modified files')),
3165 ('d', 'date', '', _('tipmost revision matching date')),
3158 ('d', 'date', '', _('tipmost revision matching date')),
3166 ('r', 'rev', '', _('revision'))],
3159 ('r', 'rev', '', _('revision'))],
3167 _('hg update [-C] [-d DATE] [[-r] REV]')),
3160 _('hg update [-C] [-d DATE] [[-r] REV]')),
3168 "verify": (verify, [], _('hg verify')),
3161 "verify": (verify, [], _('hg verify')),
3169 "version": (version_, [], _('hg version')),
3162 "version": (version_, [], _('hg version')),
3170 }
3163 }
3171
3164
3172 norepo = ("clone init version help debugcomplete debugdata"
3165 norepo = ("clone init version help debugcomplete debugdata"
3173 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3166 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3174 optionalrepo = ("identify paths serve showconfig debugancestor")
3167 optionalrepo = ("identify paths serve showconfig debugancestor")
General Comments 0
You need to be logged in to leave comments. Login now