##// END OF EJS Templates
add -b/--branch option to clone, bundle, incoming, outgoing, pull, push
Sune Foldager -
r10379:a78bfaf9 default
parent child Browse files
Show More
@@ -1,377 +1,377 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 the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''command to view revision graphs from a shell
8 '''command to view revision graphs from a shell
9
9
10 This extension adds a --graph option to the incoming, outgoing and log
10 This extension adds a --graph option to the incoming, outgoing and log
11 commands. When this options is given, an ASCII representation of the
11 commands. When this options is given, an ASCII representation of the
12 revision graph is also shown.
12 revision graph is also shown.
13 '''
13 '''
14
14
15 import os
15 import os
16 from mercurial.cmdutil import revrange, show_changeset
16 from mercurial.cmdutil import revrange, show_changeset
17 from mercurial.commands import templateopts
17 from mercurial.commands import templateopts
18 from mercurial.i18n import _
18 from mercurial.i18n import _
19 from mercurial.node import nullrev
19 from mercurial.node import nullrev
20 from mercurial import bundlerepo, changegroup, cmdutil, commands, extensions
20 from mercurial import bundlerepo, changegroup, cmdutil, commands, extensions
21 from mercurial import hg, url, util, graphmod
21 from mercurial import hg, url, util, graphmod
22
22
23 ASCIIDATA = 'ASC'
23 ASCIIDATA = 'ASC'
24
24
25 def asciiedges(seen, rev, parents):
25 def asciiedges(seen, rev, parents):
26 """adds edge info to changelog DAG walk suitable for ascii()"""
26 """adds edge info to changelog DAG walk suitable for ascii()"""
27 if rev not in seen:
27 if rev not in seen:
28 seen.append(rev)
28 seen.append(rev)
29 nodeidx = seen.index(rev)
29 nodeidx = seen.index(rev)
30
30
31 knownparents = []
31 knownparents = []
32 newparents = []
32 newparents = []
33 for parent in parents:
33 for parent in parents:
34 if parent in seen:
34 if parent in seen:
35 knownparents.append(parent)
35 knownparents.append(parent)
36 else:
36 else:
37 newparents.append(parent)
37 newparents.append(parent)
38
38
39 ncols = len(seen)
39 ncols = len(seen)
40 seen[nodeidx:nodeidx + 1] = newparents
40 seen[nodeidx:nodeidx + 1] = newparents
41 edges = [(nodeidx, seen.index(p)) for p in knownparents]
41 edges = [(nodeidx, seen.index(p)) for p in knownparents]
42
42
43 if len(newparents) > 0:
43 if len(newparents) > 0:
44 edges.append((nodeidx, nodeidx))
44 edges.append((nodeidx, nodeidx))
45 if len(newparents) > 1:
45 if len(newparents) > 1:
46 edges.append((nodeidx, nodeidx + 1))
46 edges.append((nodeidx, nodeidx + 1))
47
47
48 nmorecols = len(seen) - ncols
48 nmorecols = len(seen) - ncols
49 return nodeidx, edges, ncols, nmorecols
49 return nodeidx, edges, ncols, nmorecols
50
50
51 def fix_long_right_edges(edges):
51 def fix_long_right_edges(edges):
52 for (i, (start, end)) in enumerate(edges):
52 for (i, (start, end)) in enumerate(edges):
53 if end > start:
53 if end > start:
54 edges[i] = (start, end + 1)
54 edges[i] = (start, end + 1)
55
55
56 def get_nodeline_edges_tail(
56 def get_nodeline_edges_tail(
57 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
57 node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
58 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
58 if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
59 # Still going in the same non-vertical direction.
59 # Still going in the same non-vertical direction.
60 if n_columns_diff == -1:
60 if n_columns_diff == -1:
61 start = max(node_index + 1, p_node_index)
61 start = max(node_index + 1, p_node_index)
62 tail = ["|", " "] * (start - node_index - 1)
62 tail = ["|", " "] * (start - node_index - 1)
63 tail.extend(["/", " "] * (n_columns - start))
63 tail.extend(["/", " "] * (n_columns - start))
64 return tail
64 return tail
65 else:
65 else:
66 return ["\\", " "] * (n_columns - node_index - 1)
66 return ["\\", " "] * (n_columns - node_index - 1)
67 else:
67 else:
68 return ["|", " "] * (n_columns - node_index - 1)
68 return ["|", " "] * (n_columns - node_index - 1)
69
69
70 def draw_edges(edges, nodeline, interline):
70 def draw_edges(edges, nodeline, interline):
71 for (start, end) in edges:
71 for (start, end) in edges:
72 if start == end + 1:
72 if start == end + 1:
73 interline[2 * end + 1] = "/"
73 interline[2 * end + 1] = "/"
74 elif start == end - 1:
74 elif start == end - 1:
75 interline[2 * start + 1] = "\\"
75 interline[2 * start + 1] = "\\"
76 elif start == end:
76 elif start == end:
77 interline[2 * start] = "|"
77 interline[2 * start] = "|"
78 else:
78 else:
79 nodeline[2 * end] = "+"
79 nodeline[2 * end] = "+"
80 if start > end:
80 if start > end:
81 (start, end) = (end, start)
81 (start, end) = (end, start)
82 for i in range(2 * start + 1, 2 * end):
82 for i in range(2 * start + 1, 2 * end):
83 if nodeline[i] != "+":
83 if nodeline[i] != "+":
84 nodeline[i] = "-"
84 nodeline[i] = "-"
85
85
86 def get_padding_line(ni, n_columns, edges):
86 def get_padding_line(ni, n_columns, edges):
87 line = []
87 line = []
88 line.extend(["|", " "] * ni)
88 line.extend(["|", " "] * ni)
89 if (ni, ni - 1) in edges or (ni, ni) in edges:
89 if (ni, ni - 1) in edges or (ni, ni) in edges:
90 # (ni, ni - 1) (ni, ni)
90 # (ni, ni - 1) (ni, ni)
91 # | | | | | | | |
91 # | | | | | | | |
92 # +---o | | o---+
92 # +---o | | o---+
93 # | | c | | c | |
93 # | | c | | c | |
94 # | |/ / | |/ /
94 # | |/ / | |/ /
95 # | | | | | |
95 # | | | | | |
96 c = "|"
96 c = "|"
97 else:
97 else:
98 c = " "
98 c = " "
99 line.extend([c, " "])
99 line.extend([c, " "])
100 line.extend(["|", " "] * (n_columns - ni - 1))
100 line.extend(["|", " "] * (n_columns - ni - 1))
101 return line
101 return line
102
102
103 def asciistate():
103 def asciistate():
104 """returns the initial value for the "state" argument to ascii()"""
104 """returns the initial value for the "state" argument to ascii()"""
105 return [0, 0]
105 return [0, 0]
106
106
107 def ascii(ui, state, type, char, text, coldata):
107 def ascii(ui, state, type, char, text, coldata):
108 """prints an ASCII graph of the DAG
108 """prints an ASCII graph of the DAG
109
109
110 takes the following arguments (one call per node in the graph):
110 takes the following arguments (one call per node in the graph):
111
111
112 - ui to write to
112 - ui to write to
113 - Somewhere to keep the needed state in (init to asciistate())
113 - Somewhere to keep the needed state in (init to asciistate())
114 - Column of the current node in the set of ongoing edges.
114 - Column of the current node in the set of ongoing edges.
115 - Type indicator of node data == ASCIIDATA.
115 - Type indicator of node data == ASCIIDATA.
116 - Payload: (char, lines):
116 - Payload: (char, lines):
117 - Character to use as node's symbol.
117 - Character to use as node's symbol.
118 - List of lines to display as the node's text.
118 - List of lines to display as the node's text.
119 - Edges; a list of (col, next_col) indicating the edges between
119 - Edges; a list of (col, next_col) indicating the edges between
120 the current node and its parents.
120 the current node and its parents.
121 - Number of columns (ongoing edges) in the current revision.
121 - Number of columns (ongoing edges) in the current revision.
122 - The difference between the number of columns (ongoing edges)
122 - The difference between the number of columns (ongoing edges)
123 in the next revision and the number of columns (ongoing edges)
123 in the next revision and the number of columns (ongoing edges)
124 in the current revision. That is: -1 means one column removed;
124 in the current revision. That is: -1 means one column removed;
125 0 means no columns added or removed; 1 means one column added.
125 0 means no columns added or removed; 1 means one column added.
126 """
126 """
127
127
128 idx, edges, ncols, coldiff = coldata
128 idx, edges, ncols, coldiff = coldata
129 assert -2 < coldiff < 2
129 assert -2 < coldiff < 2
130 if coldiff == -1:
130 if coldiff == -1:
131 # Transform
131 # Transform
132 #
132 #
133 # | | | | | |
133 # | | | | | |
134 # o | | into o---+
134 # o | | into o---+
135 # |X / |/ /
135 # |X / |/ /
136 # | | | |
136 # | | | |
137 fix_long_right_edges(edges)
137 fix_long_right_edges(edges)
138
138
139 # add_padding_line says whether to rewrite
139 # add_padding_line says whether to rewrite
140 #
140 #
141 # | | | | | | | |
141 # | | | | | | | |
142 # | o---+ into | o---+
142 # | o---+ into | o---+
143 # | / / | | | # <--- padding line
143 # | / / | | | # <--- padding line
144 # o | | | / /
144 # o | | | / /
145 # o | |
145 # o | |
146 add_padding_line = (len(text) > 2 and coldiff == -1 and
146 add_padding_line = (len(text) > 2 and coldiff == -1 and
147 [x for (x, y) in edges if x + 1 < y])
147 [x for (x, y) in edges if x + 1 < y])
148
148
149 # fix_nodeline_tail says whether to rewrite
149 # fix_nodeline_tail says whether to rewrite
150 #
150 #
151 # | | o | | | | o | |
151 # | | o | | | | o | |
152 # | | |/ / | | |/ /
152 # | | |/ / | | |/ /
153 # | o | | into | o / / # <--- fixed nodeline tail
153 # | o | | into | o / / # <--- fixed nodeline tail
154 # | |/ / | |/ /
154 # | |/ / | |/ /
155 # o | | o | |
155 # o | | o | |
156 fix_nodeline_tail = len(text) <= 2 and not add_padding_line
156 fix_nodeline_tail = len(text) <= 2 and not add_padding_line
157
157
158 # nodeline is the line containing the node character (typically o)
158 # nodeline is the line containing the node character (typically o)
159 nodeline = ["|", " "] * idx
159 nodeline = ["|", " "] * idx
160 nodeline.extend([char, " "])
160 nodeline.extend([char, " "])
161
161
162 nodeline.extend(
162 nodeline.extend(
163 get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
163 get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
164 state[0], fix_nodeline_tail))
164 state[0], fix_nodeline_tail))
165
165
166 # shift_interline is the line containing the non-vertical
166 # shift_interline is the line containing the non-vertical
167 # edges between this entry and the next
167 # edges between this entry and the next
168 shift_interline = ["|", " "] * idx
168 shift_interline = ["|", " "] * idx
169 if coldiff == -1:
169 if coldiff == -1:
170 n_spaces = 1
170 n_spaces = 1
171 edge_ch = "/"
171 edge_ch = "/"
172 elif coldiff == 0:
172 elif coldiff == 0:
173 n_spaces = 2
173 n_spaces = 2
174 edge_ch = "|"
174 edge_ch = "|"
175 else:
175 else:
176 n_spaces = 3
176 n_spaces = 3
177 edge_ch = "\\"
177 edge_ch = "\\"
178 shift_interline.extend(n_spaces * [" "])
178 shift_interline.extend(n_spaces * [" "])
179 shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
179 shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
180
180
181 # draw edges from the current node to its parents
181 # draw edges from the current node to its parents
182 draw_edges(edges, nodeline, shift_interline)
182 draw_edges(edges, nodeline, shift_interline)
183
183
184 # lines is the list of all graph lines to print
184 # lines is the list of all graph lines to print
185 lines = [nodeline]
185 lines = [nodeline]
186 if add_padding_line:
186 if add_padding_line:
187 lines.append(get_padding_line(idx, ncols, edges))
187 lines.append(get_padding_line(idx, ncols, edges))
188 lines.append(shift_interline)
188 lines.append(shift_interline)
189
189
190 # make sure that there are as many graph lines as there are
190 # make sure that there are as many graph lines as there are
191 # log strings
191 # log strings
192 while len(text) < len(lines):
192 while len(text) < len(lines):
193 text.append("")
193 text.append("")
194 if len(lines) < len(text):
194 if len(lines) < len(text):
195 extra_interline = ["|", " "] * (ncols + coldiff)
195 extra_interline = ["|", " "] * (ncols + coldiff)
196 while len(lines) < len(text):
196 while len(lines) < len(text):
197 lines.append(extra_interline)
197 lines.append(extra_interline)
198
198
199 # print lines
199 # print lines
200 indentation_level = max(ncols, ncols + coldiff)
200 indentation_level = max(ncols, ncols + coldiff)
201 for (line, logstr) in zip(lines, text):
201 for (line, logstr) in zip(lines, text):
202 ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
202 ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
203 ui.write(ln.rstrip() + '\n')
203 ui.write(ln.rstrip() + '\n')
204
204
205 # ... and start over
205 # ... and start over
206 state[0] = coldiff
206 state[0] = coldiff
207 state[1] = idx
207 state[1] = idx
208
208
209 def get_revs(repo, rev_opt):
209 def get_revs(repo, rev_opt):
210 if rev_opt:
210 if rev_opt:
211 revs = revrange(repo, rev_opt)
211 revs = revrange(repo, rev_opt)
212 return (max(revs), min(revs))
212 return (max(revs), min(revs))
213 else:
213 else:
214 return (len(repo) - 1, 0)
214 return (len(repo) - 1, 0)
215
215
216 def check_unsupported_flags(opts):
216 def check_unsupported_flags(opts):
217 for op in ["follow", "follow_first", "date", "copies", "keyword", "remove",
217 for op in ["follow", "follow_first", "date", "copies", "keyword", "remove",
218 "only_merges", "user", "only_branch", "prune", "newest_first",
218 "only_merges", "user", "only_branch", "prune", "newest_first",
219 "no_merges", "include", "exclude"]:
219 "no_merges", "include", "exclude"]:
220 if op in opts and opts[op]:
220 if op in opts and opts[op]:
221 raise util.Abort(_("--graph option is incompatible with --%s")
221 raise util.Abort(_("--graph option is incompatible with --%s")
222 % op.replace("_", "-"))
222 % op.replace("_", "-"))
223
223
224 def generate(ui, dag, displayer, showparents, edgefn):
224 def generate(ui, dag, displayer, showparents, edgefn):
225 seen, state = [], asciistate()
225 seen, state = [], asciistate()
226 for rev, type, ctx, parents in dag:
226 for rev, type, ctx, parents in dag:
227 char = ctx.node() in showparents and '@' or 'o'
227 char = ctx.node() in showparents and '@' or 'o'
228 displayer.show(ctx)
228 displayer.show(ctx)
229 lines = displayer.hunk.pop(rev).split('\n')[:-1]
229 lines = displayer.hunk.pop(rev).split('\n')[:-1]
230 ascii(ui, state, type, char, lines, edgefn(seen, rev, parents))
230 ascii(ui, state, type, char, lines, edgefn(seen, rev, parents))
231
231
232 def graphlog(ui, repo, path=None, **opts):
232 def graphlog(ui, repo, path=None, **opts):
233 """show revision history alongside an ASCII revision graph
233 """show revision history alongside an ASCII revision graph
234
234
235 Print a revision history alongside a revision graph drawn with
235 Print a revision history alongside a revision graph drawn with
236 ASCII characters.
236 ASCII characters.
237
237
238 Nodes printed as an @ character are parents of the working
238 Nodes printed as an @ character are parents of the working
239 directory.
239 directory.
240 """
240 """
241
241
242 check_unsupported_flags(opts)
242 check_unsupported_flags(opts)
243 limit = cmdutil.loglimit(opts)
243 limit = cmdutil.loglimit(opts)
244 start, stop = get_revs(repo, opts["rev"])
244 start, stop = get_revs(repo, opts["rev"])
245 if start == nullrev:
245 if start == nullrev:
246 return
246 return
247
247
248 if path:
248 if path:
249 path = util.canonpath(repo.root, os.getcwd(), path)
249 path = util.canonpath(repo.root, os.getcwd(), path)
250 if path: # could be reset in canonpath
250 if path: # could be reset in canonpath
251 revdag = graphmod.filerevs(repo, path, start, stop, limit)
251 revdag = graphmod.filerevs(repo, path, start, stop, limit)
252 else:
252 else:
253 if limit is not None:
253 if limit is not None:
254 stop = max(stop, start - limit + 1)
254 stop = max(stop, start - limit + 1)
255 revdag = graphmod.revisions(repo, start, stop)
255 revdag = graphmod.revisions(repo, start, stop)
256
256
257 displayer = show_changeset(ui, repo, opts, buffered=True)
257 displayer = show_changeset(ui, repo, opts, buffered=True)
258 showparents = [ctx.node() for ctx in repo[None].parents()]
258 showparents = [ctx.node() for ctx in repo[None].parents()]
259 generate(ui, revdag, displayer, showparents, asciiedges)
259 generate(ui, revdag, displayer, showparents, asciiedges)
260
260
261 def graphrevs(repo, nodes, opts):
261 def graphrevs(repo, nodes, opts):
262 limit = cmdutil.loglimit(opts)
262 limit = cmdutil.loglimit(opts)
263 nodes.reverse()
263 nodes.reverse()
264 if limit is not None:
264 if limit is not None:
265 nodes = nodes[:limit]
265 nodes = nodes[:limit]
266 return graphmod.nodes(repo, nodes)
266 return graphmod.nodes(repo, nodes)
267
267
268 def goutgoing(ui, repo, dest=None, **opts):
268 def goutgoing(ui, repo, dest=None, **opts):
269 """show the outgoing changesets alongside an ASCII revision graph
269 """show the outgoing changesets alongside an ASCII revision graph
270
270
271 Print the outgoing changesets alongside a revision graph drawn with
271 Print the outgoing changesets alongside a revision graph drawn with
272 ASCII characters.
272 ASCII characters.
273
273
274 Nodes printed as an @ character are parents of the working
274 Nodes printed as an @ character are parents of the working
275 directory.
275 directory.
276 """
276 """
277
277
278 check_unsupported_flags(opts)
278 check_unsupported_flags(opts)
279 dest = ui.expandpath(dest or 'default-push', dest or 'default')
279 dest = ui.expandpath(dest or 'default-push', dest or 'default')
280 dest, branches = hg.parseurl(dest)
280 dest, branches = hg.parseurl(dest, opts.get('branch'))
281 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
281 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
282 other = hg.repository(cmdutil.remoteui(ui, opts), dest)
282 other = hg.repository(cmdutil.remoteui(ui, opts), dest)
283 if revs:
283 if revs:
284 revs = [repo.lookup(rev) for rev in revs]
284 revs = [repo.lookup(rev) for rev in revs]
285 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
285 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
286 o = repo.findoutgoing(other, force=opts.get('force'))
286 o = repo.findoutgoing(other, force=opts.get('force'))
287 if not o:
287 if not o:
288 ui.status(_("no changes found\n"))
288 ui.status(_("no changes found\n"))
289 return
289 return
290
290
291 o = repo.changelog.nodesbetween(o, revs)[0]
291 o = repo.changelog.nodesbetween(o, revs)[0]
292 revdag = graphrevs(repo, o, opts)
292 revdag = graphrevs(repo, o, opts)
293 displayer = show_changeset(ui, repo, opts, buffered=True)
293 displayer = show_changeset(ui, repo, opts, buffered=True)
294 showparents = [ctx.node() for ctx in repo[None].parents()]
294 showparents = [ctx.node() for ctx in repo[None].parents()]
295 generate(ui, revdag, displayer, showparents, asciiedges)
295 generate(ui, revdag, displayer, showparents, asciiedges)
296
296
297 def gincoming(ui, repo, source="default", **opts):
297 def gincoming(ui, repo, source="default", **opts):
298 """show the incoming changesets alongside an ASCII revision graph
298 """show the incoming changesets alongside an ASCII revision graph
299
299
300 Print the incoming changesets alongside a revision graph drawn with
300 Print the incoming changesets alongside a revision graph drawn with
301 ASCII characters.
301 ASCII characters.
302
302
303 Nodes printed as an @ character are parents of the working
303 Nodes printed as an @ character are parents of the working
304 directory.
304 directory.
305 """
305 """
306
306
307 check_unsupported_flags(opts)
307 check_unsupported_flags(opts)
308 source, branches = hg.parseurl(ui.expandpath(source))
308 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
309 other = hg.repository(cmdutil.remoteui(repo, opts), source)
309 other = hg.repository(cmdutil.remoteui(repo, opts), source)
310 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
310 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
311 ui.status(_('comparing with %s\n') % url.hidepassword(source))
311 ui.status(_('comparing with %s\n') % url.hidepassword(source))
312 if revs:
312 if revs:
313 revs = [other.lookup(rev) for rev in revs]
313 revs = [other.lookup(rev) for rev in revs]
314 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
314 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
315 if not incoming:
315 if not incoming:
316 try:
316 try:
317 os.unlink(opts["bundle"])
317 os.unlink(opts["bundle"])
318 except:
318 except:
319 pass
319 pass
320 ui.status(_("no changes found\n"))
320 ui.status(_("no changes found\n"))
321 return
321 return
322
322
323 cleanup = None
323 cleanup = None
324 try:
324 try:
325
325
326 fname = opts["bundle"]
326 fname = opts["bundle"]
327 if fname or not other.local():
327 if fname or not other.local():
328 # create a bundle (uncompressed if other repo is not local)
328 # create a bundle (uncompressed if other repo is not local)
329 if revs is None:
329 if revs is None:
330 cg = other.changegroup(incoming, "incoming")
330 cg = other.changegroup(incoming, "incoming")
331 else:
331 else:
332 cg = other.changegroupsubset(incoming, revs, 'incoming')
332 cg = other.changegroupsubset(incoming, revs, 'incoming')
333 bundletype = other.local() and "HG10BZ" or "HG10UN"
333 bundletype = other.local() and "HG10BZ" or "HG10UN"
334 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
334 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
335 # keep written bundle?
335 # keep written bundle?
336 if opts["bundle"]:
336 if opts["bundle"]:
337 cleanup = None
337 cleanup = None
338 if not other.local():
338 if not other.local():
339 # use the created uncompressed bundlerepo
339 # use the created uncompressed bundlerepo
340 other = bundlerepo.bundlerepository(ui, repo.root, fname)
340 other = bundlerepo.bundlerepository(ui, repo.root, fname)
341
341
342 chlist = other.changelog.nodesbetween(incoming, revs)[0]
342 chlist = other.changelog.nodesbetween(incoming, revs)[0]
343 revdag = graphrevs(other, chlist, opts)
343 revdag = graphrevs(other, chlist, opts)
344 displayer = show_changeset(ui, other, opts, buffered=True)
344 displayer = show_changeset(ui, other, opts, buffered=True)
345 showparents = [ctx.node() for ctx in repo[None].parents()]
345 showparents = [ctx.node() for ctx in repo[None].parents()]
346 generate(ui, revdag, displayer, showparents, asciiedges)
346 generate(ui, revdag, displayer, showparents, asciiedges)
347
347
348 finally:
348 finally:
349 if hasattr(other, 'close'):
349 if hasattr(other, 'close'):
350 other.close()
350 other.close()
351 if cleanup:
351 if cleanup:
352 os.unlink(cleanup)
352 os.unlink(cleanup)
353
353
354 def uisetup(ui):
354 def uisetup(ui):
355 '''Initialize the extension.'''
355 '''Initialize the extension.'''
356 _wrapcmd(ui, 'log', commands.table, graphlog)
356 _wrapcmd(ui, 'log', commands.table, graphlog)
357 _wrapcmd(ui, 'incoming', commands.table, gincoming)
357 _wrapcmd(ui, 'incoming', commands.table, gincoming)
358 _wrapcmd(ui, 'outgoing', commands.table, goutgoing)
358 _wrapcmd(ui, 'outgoing', commands.table, goutgoing)
359
359
360 def _wrapcmd(ui, cmd, table, wrapfn):
360 def _wrapcmd(ui, cmd, table, wrapfn):
361 '''wrap the command'''
361 '''wrap the command'''
362 def graph(orig, *args, **kwargs):
362 def graph(orig, *args, **kwargs):
363 if kwargs['graph']:
363 if kwargs['graph']:
364 return wrapfn(*args, **kwargs)
364 return wrapfn(*args, **kwargs)
365 return orig(*args, **kwargs)
365 return orig(*args, **kwargs)
366 entry = extensions.wrapcommand(table, cmd, graph)
366 entry = extensions.wrapcommand(table, cmd, graph)
367 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
367 entry[1].append(('G', 'graph', None, _("show the revision DAG")))
368
368
369 cmdtable = {
369 cmdtable = {
370 "glog":
370 "glog":
371 (graphlog,
371 (graphlog,
372 [('l', 'limit', '', _('limit number of changes displayed')),
372 [('l', 'limit', '', _('limit number of changes displayed')),
373 ('p', 'patch', False, _('show patch')),
373 ('p', 'patch', False, _('show patch')),
374 ('r', 'rev', [], _('show the specified revision or range')),
374 ('r', 'rev', [], _('show the specified revision or range')),
375 ] + templateopts,
375 ] + templateopts,
376 _('hg glog [OPTION]... [FILE]')),
376 _('hg glog [OPTION]... [FILE]')),
377 }
377 }
@@ -1,3765 +1,3779 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, bundlerepo, extensions, copies, error
12 import hg, util, revlog, bundlerepo, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw
13 import patch, help, mdiff, url, encoding, templatekw
14 import archival, changegroup, cmdutil, sshserver, hbisect
14 import archival, changegroup, cmdutil, sshserver, hbisect
15 from hgweb import server
15 from hgweb import server
16 import merge as merge_
16 import merge as merge_
17 import minirst
17 import minirst
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see hg forget.
28 undo an add before that, see hg forget.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31 """
31 """
32
32
33 bad = []
33 bad = []
34 names = []
34 names = []
35 m = cmdutil.match(repo, pats, opts)
35 m = cmdutil.match(repo, pats, opts)
36 oldbad = m.bad
36 oldbad = m.bad
37 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
37 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
38
38
39 for f in repo.walk(m):
39 for f in repo.walk(m):
40 exact = m.exact(f)
40 exact = m.exact(f)
41 if exact or f not in repo.dirstate:
41 if exact or f not in repo.dirstate:
42 names.append(f)
42 names.append(f)
43 if ui.verbose or not exact:
43 if ui.verbose or not exact:
44 ui.status(_('adding %s\n') % m.rel(f))
44 ui.status(_('adding %s\n') % m.rel(f))
45 if not opts.get('dry_run'):
45 if not opts.get('dry_run'):
46 bad += [f for f in repo.add(names) if f in m.files()]
46 bad += [f for f in repo.add(names) if f in m.files()]
47 return bad and 1 or 0
47 return bad and 1 or 0
48
48
49 def addremove(ui, repo, *pats, **opts):
49 def addremove(ui, repo, *pats, **opts):
50 """add all new files, delete all missing files
50 """add all new files, delete all missing files
51
51
52 Add all new files and remove all missing files from the
52 Add all new files and remove all missing files from the
53 repository.
53 repository.
54
54
55 New files are ignored if they match any of the patterns in
55 New files are ignored if they match any of the patterns in
56 .hgignore. As with add, these changes take effect at the next
56 .hgignore. As with add, these changes take effect at the next
57 commit.
57 commit.
58
58
59 Use the -s/--similarity option to detect renamed files. With a
59 Use the -s/--similarity option to detect renamed files. With a
60 parameter greater than 0, this compares every removed file with
60 parameter greater than 0, this compares every removed file with
61 every added file and records those similar enough as renames. This
61 every added file and records those similar enough as renames. This
62 option takes a percentage between 0 (disabled) and 100 (files must
62 option takes a percentage between 0 (disabled) and 100 (files must
63 be identical) as its parameter. Detecting renamed files this way
63 be identical) as its parameter. Detecting renamed files this way
64 can be expensive.
64 can be expensive.
65 """
65 """
66 try:
66 try:
67 sim = float(opts.get('similarity') or 0)
67 sim = float(opts.get('similarity') or 0)
68 except ValueError:
68 except ValueError:
69 raise util.Abort(_('similarity must be a number'))
69 raise util.Abort(_('similarity must be a number'))
70 if sim < 0 or sim > 100:
70 if sim < 0 or sim > 100:
71 raise util.Abort(_('similarity must be between 0 and 100'))
71 raise util.Abort(_('similarity must be between 0 and 100'))
72 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
72 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
73
73
74 def annotate(ui, repo, *pats, **opts):
74 def annotate(ui, repo, *pats, **opts):
75 """show changeset information by line for each file
75 """show changeset information by line for each file
76
76
77 List changes in files, showing the revision id responsible for
77 List changes in files, showing the revision id responsible for
78 each line
78 each line
79
79
80 This command is useful for discovering when a change was made and
80 This command is useful for discovering when a change was made and
81 by whom.
81 by whom.
82
82
83 Without the -a/--text option, annotate will avoid processing files
83 Without the -a/--text option, annotate will avoid processing files
84 it detects as binary. With -a, annotate will annotate the file
84 it detects as binary. With -a, annotate will annotate the file
85 anyway, although the results will probably be neither useful
85 anyway, although the results will probably be neither useful
86 nor desirable.
86 nor desirable.
87 """
87 """
88 datefunc = ui.quiet and util.shortdate or util.datestr
88 datefunc = ui.quiet and util.shortdate or util.datestr
89 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
89 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
90
90
91 if not pats:
91 if not pats:
92 raise util.Abort(_('at least one filename or pattern is required'))
92 raise util.Abort(_('at least one filename or pattern is required'))
93
93
94 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
94 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
95 ('number', lambda x: str(x[0].rev())),
95 ('number', lambda x: str(x[0].rev())),
96 ('changeset', lambda x: short(x[0].node())),
96 ('changeset', lambda x: short(x[0].node())),
97 ('date', getdate),
97 ('date', getdate),
98 ('file', lambda x: x[0].path()),
98 ('file', lambda x: x[0].path()),
99 ]
99 ]
100
100
101 if (not opts.get('user') and not opts.get('changeset')
101 if (not opts.get('user') and not opts.get('changeset')
102 and not opts.get('date') and not opts.get('file')):
102 and not opts.get('date') and not opts.get('file')):
103 opts['number'] = 1
103 opts['number'] = 1
104
104
105 linenumber = opts.get('line_number') is not None
105 linenumber = opts.get('line_number') is not None
106 if (linenumber and (not opts.get('changeset')) and (not opts.get('number'))):
106 if (linenumber and (not opts.get('changeset')) and (not opts.get('number'))):
107 raise util.Abort(_('at least one of -n/-c is required for -l'))
107 raise util.Abort(_('at least one of -n/-c is required for -l'))
108
108
109 funcmap = [func for op, func in opmap if opts.get(op)]
109 funcmap = [func for op, func in opmap if opts.get(op)]
110 if linenumber:
110 if linenumber:
111 lastfunc = funcmap[-1]
111 lastfunc = funcmap[-1]
112 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
112 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
113
113
114 ctx = repo[opts.get('rev')]
114 ctx = repo[opts.get('rev')]
115 m = cmdutil.match(repo, pats, opts)
115 m = cmdutil.match(repo, pats, opts)
116 follow = not opts.get('no_follow')
116 follow = not opts.get('no_follow')
117 for abs in ctx.walk(m):
117 for abs in ctx.walk(m):
118 fctx = ctx[abs]
118 fctx = ctx[abs]
119 if not opts.get('text') and util.binary(fctx.data()):
119 if not opts.get('text') and util.binary(fctx.data()):
120 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
120 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
121 continue
121 continue
122
122
123 lines = fctx.annotate(follow=follow, linenumber=linenumber)
123 lines = fctx.annotate(follow=follow, linenumber=linenumber)
124 pieces = []
124 pieces = []
125
125
126 for f in funcmap:
126 for f in funcmap:
127 l = [f(n) for n, dummy in lines]
127 l = [f(n) for n, dummy in lines]
128 if l:
128 if l:
129 ml = max(map(len, l))
129 ml = max(map(len, l))
130 pieces.append(["%*s" % (ml, x) for x in l])
130 pieces.append(["%*s" % (ml, x) for x in l])
131
131
132 if pieces:
132 if pieces:
133 for p, l in zip(zip(*pieces), lines):
133 for p, l in zip(zip(*pieces), lines):
134 ui.write("%s: %s" % (" ".join(p), l[1]))
134 ui.write("%s: %s" % (" ".join(p), l[1]))
135
135
136 def archive(ui, repo, dest, **opts):
136 def archive(ui, repo, dest, **opts):
137 '''create an unversioned archive of a repository revision
137 '''create an unversioned archive of a repository revision
138
138
139 By default, the revision used is the parent of the working
139 By default, the revision used is the parent of the working
140 directory; use -r/--rev to specify a different revision.
140 directory; use -r/--rev to specify a different revision.
141
141
142 To specify the type of archive to create, use -t/--type. Valid
142 To specify the type of archive to create, use -t/--type. Valid
143 types are:
143 types are:
144
144
145 :``files``: a directory full of files (default)
145 :``files``: a directory full of files (default)
146 :``tar``: tar archive, uncompressed
146 :``tar``: tar archive, uncompressed
147 :``tbz2``: tar archive, compressed using bzip2
147 :``tbz2``: tar archive, compressed using bzip2
148 :``tgz``: tar archive, compressed using gzip
148 :``tgz``: tar archive, compressed using gzip
149 :``uzip``: zip archive, uncompressed
149 :``uzip``: zip archive, uncompressed
150 :``zip``: zip archive, compressed using deflate
150 :``zip``: zip archive, compressed using deflate
151
151
152 The exact name of the destination archive or directory is given
152 The exact name of the destination archive or directory is given
153 using a format string; see 'hg help export' for details.
153 using a format string; see 'hg help export' for details.
154
154
155 Each member added to an archive file has a directory prefix
155 Each member added to an archive file has a directory prefix
156 prepended. Use -p/--prefix to specify a format string for the
156 prepended. Use -p/--prefix to specify a format string for the
157 prefix. The default is the basename of the archive, with suffixes
157 prefix. The default is the basename of the archive, with suffixes
158 removed.
158 removed.
159 '''
159 '''
160
160
161 ctx = repo[opts.get('rev')]
161 ctx = repo[opts.get('rev')]
162 if not ctx:
162 if not ctx:
163 raise util.Abort(_('no working directory: please specify a revision'))
163 raise util.Abort(_('no working directory: please specify a revision'))
164 node = ctx.node()
164 node = ctx.node()
165 dest = cmdutil.make_filename(repo, dest, node)
165 dest = cmdutil.make_filename(repo, dest, node)
166 if os.path.realpath(dest) == repo.root:
166 if os.path.realpath(dest) == repo.root:
167 raise util.Abort(_('repository root cannot be destination'))
167 raise util.Abort(_('repository root cannot be destination'))
168 matchfn = cmdutil.match(repo, [], opts)
168 matchfn = cmdutil.match(repo, [], opts)
169 kind = opts.get('type') or 'files'
169 kind = opts.get('type') or 'files'
170 prefix = opts.get('prefix')
170 prefix = opts.get('prefix')
171 if dest == '-':
171 if dest == '-':
172 if kind == 'files':
172 if kind == 'files':
173 raise util.Abort(_('cannot archive plain files to stdout'))
173 raise util.Abort(_('cannot archive plain files to stdout'))
174 dest = sys.stdout
174 dest = sys.stdout
175 if not prefix:
175 if not prefix:
176 prefix = os.path.basename(repo.root) + '-%h'
176 prefix = os.path.basename(repo.root) + '-%h'
177 prefix = cmdutil.make_filename(repo, prefix, node)
177 prefix = cmdutil.make_filename(repo, prefix, node)
178 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
178 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
179 matchfn, prefix)
179 matchfn, prefix)
180
180
181 def backout(ui, repo, node=None, rev=None, **opts):
181 def backout(ui, repo, node=None, rev=None, **opts):
182 '''reverse effect of earlier changeset
182 '''reverse effect of earlier changeset
183
183
184 Commit the backed out changes as a new changeset. The new
184 Commit the backed out changes as a new changeset. The new
185 changeset is a child of the backed out changeset.
185 changeset is a child of the backed out changeset.
186
186
187 If you backout a changeset other than the tip, a new head is
187 If you backout a changeset other than the tip, a new head is
188 created. This head will be the new tip and you should merge this
188 created. This head will be the new tip and you should merge this
189 backout changeset with another head.
189 backout changeset with another head.
190
190
191 The --merge option remembers the parent of the working directory
191 The --merge option remembers the parent of the working directory
192 before starting the backout, then merges the new head with that
192 before starting the backout, then merges the new head with that
193 changeset afterwards. This saves you from doing the merge by hand.
193 changeset afterwards. This saves you from doing the merge by hand.
194 The result of this merge is not committed, as with a normal merge.
194 The result of this merge is not committed, as with a normal merge.
195
195
196 See 'hg help dates' for a list of formats valid for -d/--date.
196 See 'hg help dates' for a list of formats valid for -d/--date.
197 '''
197 '''
198 if rev and node:
198 if rev and node:
199 raise util.Abort(_("please specify just one revision"))
199 raise util.Abort(_("please specify just one revision"))
200
200
201 if not rev:
201 if not rev:
202 rev = node
202 rev = node
203
203
204 if not rev:
204 if not rev:
205 raise util.Abort(_("please specify a revision to backout"))
205 raise util.Abort(_("please specify a revision to backout"))
206
206
207 date = opts.get('date')
207 date = opts.get('date')
208 if date:
208 if date:
209 opts['date'] = util.parsedate(date)
209 opts['date'] = util.parsedate(date)
210
210
211 cmdutil.bail_if_changed(repo)
211 cmdutil.bail_if_changed(repo)
212 node = repo.lookup(rev)
212 node = repo.lookup(rev)
213
213
214 op1, op2 = repo.dirstate.parents()
214 op1, op2 = repo.dirstate.parents()
215 a = repo.changelog.ancestor(op1, node)
215 a = repo.changelog.ancestor(op1, node)
216 if a != node:
216 if a != node:
217 raise util.Abort(_('cannot backout change on a different branch'))
217 raise util.Abort(_('cannot backout change on a different branch'))
218
218
219 p1, p2 = repo.changelog.parents(node)
219 p1, p2 = repo.changelog.parents(node)
220 if p1 == nullid:
220 if p1 == nullid:
221 raise util.Abort(_('cannot backout a change with no parents'))
221 raise util.Abort(_('cannot backout a change with no parents'))
222 if p2 != nullid:
222 if p2 != nullid:
223 if not opts.get('parent'):
223 if not opts.get('parent'):
224 raise util.Abort(_('cannot backout a merge changeset without '
224 raise util.Abort(_('cannot backout a merge changeset without '
225 '--parent'))
225 '--parent'))
226 p = repo.lookup(opts['parent'])
226 p = repo.lookup(opts['parent'])
227 if p not in (p1, p2):
227 if p not in (p1, p2):
228 raise util.Abort(_('%s is not a parent of %s') %
228 raise util.Abort(_('%s is not a parent of %s') %
229 (short(p), short(node)))
229 (short(p), short(node)))
230 parent = p
230 parent = p
231 else:
231 else:
232 if opts.get('parent'):
232 if opts.get('parent'):
233 raise util.Abort(_('cannot use --parent on non-merge changeset'))
233 raise util.Abort(_('cannot use --parent on non-merge changeset'))
234 parent = p1
234 parent = p1
235
235
236 # the backout should appear on the same branch
236 # the backout should appear on the same branch
237 branch = repo.dirstate.branch()
237 branch = repo.dirstate.branch()
238 hg.clean(repo, node, show_stats=False)
238 hg.clean(repo, node, show_stats=False)
239 repo.dirstate.setbranch(branch)
239 repo.dirstate.setbranch(branch)
240 revert_opts = opts.copy()
240 revert_opts = opts.copy()
241 revert_opts['date'] = None
241 revert_opts['date'] = None
242 revert_opts['all'] = True
242 revert_opts['all'] = True
243 revert_opts['rev'] = hex(parent)
243 revert_opts['rev'] = hex(parent)
244 revert_opts['no_backup'] = None
244 revert_opts['no_backup'] = None
245 revert(ui, repo, **revert_opts)
245 revert(ui, repo, **revert_opts)
246 commit_opts = opts.copy()
246 commit_opts = opts.copy()
247 commit_opts['addremove'] = False
247 commit_opts['addremove'] = False
248 if not commit_opts['message'] and not commit_opts['logfile']:
248 if not commit_opts['message'] and not commit_opts['logfile']:
249 # we don't translate commit messages
249 # we don't translate commit messages
250 commit_opts['message'] = "Backed out changeset %s" % short(node)
250 commit_opts['message'] = "Backed out changeset %s" % short(node)
251 commit_opts['force_editor'] = True
251 commit_opts['force_editor'] = True
252 commit(ui, repo, **commit_opts)
252 commit(ui, repo, **commit_opts)
253 def nice(node):
253 def nice(node):
254 return '%d:%s' % (repo.changelog.rev(node), short(node))
254 return '%d:%s' % (repo.changelog.rev(node), short(node))
255 ui.status(_('changeset %s backs out changeset %s\n') %
255 ui.status(_('changeset %s backs out changeset %s\n') %
256 (nice(repo.changelog.tip()), nice(node)))
256 (nice(repo.changelog.tip()), nice(node)))
257 if op1 != node:
257 if op1 != node:
258 hg.clean(repo, op1, show_stats=False)
258 hg.clean(repo, op1, show_stats=False)
259 if opts.get('merge'):
259 if opts.get('merge'):
260 ui.status(_('merging with changeset %s\n')
260 ui.status(_('merging with changeset %s\n')
261 % nice(repo.changelog.tip()))
261 % nice(repo.changelog.tip()))
262 hg.merge(repo, hex(repo.changelog.tip()))
262 hg.merge(repo, hex(repo.changelog.tip()))
263 else:
263 else:
264 ui.status(_('the backout changeset is a new head - '
264 ui.status(_('the backout changeset is a new head - '
265 'do not forget to merge\n'))
265 'do not forget to merge\n'))
266 ui.status(_('(use "backout --merge" '
266 ui.status(_('(use "backout --merge" '
267 'if you want to auto-merge)\n'))
267 'if you want to auto-merge)\n'))
268
268
269 def bisect(ui, repo, rev=None, extra=None, command=None,
269 def bisect(ui, repo, rev=None, extra=None, command=None,
270 reset=None, good=None, bad=None, skip=None, noupdate=None):
270 reset=None, good=None, bad=None, skip=None, noupdate=None):
271 """subdivision search of changesets
271 """subdivision search of changesets
272
272
273 This command helps to find changesets which introduce problems. To
273 This command helps to find changesets which introduce problems. To
274 use, mark the earliest changeset you know exhibits the problem as
274 use, mark the earliest changeset you know exhibits the problem as
275 bad, then mark the latest changeset which is free from the problem
275 bad, then mark the latest changeset which is free from the problem
276 as good. Bisect will update your working directory to a revision
276 as good. Bisect will update your working directory to a revision
277 for testing (unless the -U/--noupdate option is specified). Once
277 for testing (unless the -U/--noupdate option is specified). Once
278 you have performed tests, mark the working directory as good or
278 you have performed tests, mark the working directory as good or
279 bad, and bisect will either update to another candidate changeset
279 bad, and bisect will either update to another candidate changeset
280 or announce that it has found the bad revision.
280 or announce that it has found the bad revision.
281
281
282 As a shortcut, you can also use the revision argument to mark a
282 As a shortcut, you can also use the revision argument to mark a
283 revision as good or bad without checking it out first.
283 revision as good or bad without checking it out first.
284
284
285 If you supply a command, it will be used for automatic bisection.
285 If you supply a command, it will be used for automatic bisection.
286 Its exit status will be used to mark revisions as good or bad:
286 Its exit status will be used to mark revisions as good or bad:
287 status 0 means good, 125 means to skip the revision, 127
287 status 0 means good, 125 means to skip the revision, 127
288 (command not found) will abort the bisection, and any other
288 (command not found) will abort the bisection, and any other
289 non-zero exit status means the revision is bad.
289 non-zero exit status means the revision is bad.
290 """
290 """
291 def print_result(nodes, good):
291 def print_result(nodes, good):
292 displayer = cmdutil.show_changeset(ui, repo, {})
292 displayer = cmdutil.show_changeset(ui, repo, {})
293 if len(nodes) == 1:
293 if len(nodes) == 1:
294 # narrowed it down to a single revision
294 # narrowed it down to a single revision
295 if good:
295 if good:
296 ui.write(_("The first good revision is:\n"))
296 ui.write(_("The first good revision is:\n"))
297 else:
297 else:
298 ui.write(_("The first bad revision is:\n"))
298 ui.write(_("The first bad revision is:\n"))
299 displayer.show(repo[nodes[0]])
299 displayer.show(repo[nodes[0]])
300 else:
300 else:
301 # multiple possible revisions
301 # multiple possible revisions
302 if good:
302 if good:
303 ui.write(_("Due to skipped revisions, the first "
303 ui.write(_("Due to skipped revisions, the first "
304 "good revision could be any of:\n"))
304 "good revision could be any of:\n"))
305 else:
305 else:
306 ui.write(_("Due to skipped revisions, the first "
306 ui.write(_("Due to skipped revisions, the first "
307 "bad revision could be any of:\n"))
307 "bad revision could be any of:\n"))
308 for n in nodes:
308 for n in nodes:
309 displayer.show(repo[n])
309 displayer.show(repo[n])
310 displayer.close()
310 displayer.close()
311
311
312 def check_state(state, interactive=True):
312 def check_state(state, interactive=True):
313 if not state['good'] or not state['bad']:
313 if not state['good'] or not state['bad']:
314 if (good or bad or skip or reset) and interactive:
314 if (good or bad or skip or reset) and interactive:
315 return
315 return
316 if not state['good']:
316 if not state['good']:
317 raise util.Abort(_('cannot bisect (no known good revisions)'))
317 raise util.Abort(_('cannot bisect (no known good revisions)'))
318 else:
318 else:
319 raise util.Abort(_('cannot bisect (no known bad revisions)'))
319 raise util.Abort(_('cannot bisect (no known bad revisions)'))
320 return True
320 return True
321
321
322 # backward compatibility
322 # backward compatibility
323 if rev in "good bad reset init".split():
323 if rev in "good bad reset init".split():
324 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
324 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
325 cmd, rev, extra = rev, extra, None
325 cmd, rev, extra = rev, extra, None
326 if cmd == "good":
326 if cmd == "good":
327 good = True
327 good = True
328 elif cmd == "bad":
328 elif cmd == "bad":
329 bad = True
329 bad = True
330 else:
330 else:
331 reset = True
331 reset = True
332 elif extra or good + bad + skip + reset + bool(command) > 1:
332 elif extra or good + bad + skip + reset + bool(command) > 1:
333 raise util.Abort(_('incompatible arguments'))
333 raise util.Abort(_('incompatible arguments'))
334
334
335 if reset:
335 if reset:
336 p = repo.join("bisect.state")
336 p = repo.join("bisect.state")
337 if os.path.exists(p):
337 if os.path.exists(p):
338 os.unlink(p)
338 os.unlink(p)
339 return
339 return
340
340
341 state = hbisect.load_state(repo)
341 state = hbisect.load_state(repo)
342
342
343 if command:
343 if command:
344 changesets = 1
344 changesets = 1
345 try:
345 try:
346 while changesets:
346 while changesets:
347 # update state
347 # update state
348 status = util.system(command)
348 status = util.system(command)
349 if status == 125:
349 if status == 125:
350 transition = "skip"
350 transition = "skip"
351 elif status == 0:
351 elif status == 0:
352 transition = "good"
352 transition = "good"
353 # status < 0 means process was killed
353 # status < 0 means process was killed
354 elif status == 127:
354 elif status == 127:
355 raise util.Abort(_("failed to execute %s") % command)
355 raise util.Abort(_("failed to execute %s") % command)
356 elif status < 0:
356 elif status < 0:
357 raise util.Abort(_("%s killed") % command)
357 raise util.Abort(_("%s killed") % command)
358 else:
358 else:
359 transition = "bad"
359 transition = "bad"
360 ctx = repo[rev or '.']
360 ctx = repo[rev or '.']
361 state[transition].append(ctx.node())
361 state[transition].append(ctx.node())
362 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
362 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
363 check_state(state, interactive=False)
363 check_state(state, interactive=False)
364 # bisect
364 # bisect
365 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
365 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
366 # update to next check
366 # update to next check
367 cmdutil.bail_if_changed(repo)
367 cmdutil.bail_if_changed(repo)
368 hg.clean(repo, nodes[0], show_stats=False)
368 hg.clean(repo, nodes[0], show_stats=False)
369 finally:
369 finally:
370 hbisect.save_state(repo, state)
370 hbisect.save_state(repo, state)
371 return print_result(nodes, good)
371 return print_result(nodes, good)
372
372
373 # update state
373 # update state
374 node = repo.lookup(rev or '.')
374 node = repo.lookup(rev or '.')
375 if good or bad or skip:
375 if good or bad or skip:
376 if good:
376 if good:
377 state['good'].append(node)
377 state['good'].append(node)
378 elif bad:
378 elif bad:
379 state['bad'].append(node)
379 state['bad'].append(node)
380 elif skip:
380 elif skip:
381 state['skip'].append(node)
381 state['skip'].append(node)
382 hbisect.save_state(repo, state)
382 hbisect.save_state(repo, state)
383
383
384 if not check_state(state):
384 if not check_state(state):
385 return
385 return
386
386
387 # actually bisect
387 # actually bisect
388 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
388 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
389 if changesets == 0:
389 if changesets == 0:
390 print_result(nodes, good)
390 print_result(nodes, good)
391 else:
391 else:
392 assert len(nodes) == 1 # only a single node can be tested next
392 assert len(nodes) == 1 # only a single node can be tested next
393 node = nodes[0]
393 node = nodes[0]
394 # compute the approximate number of remaining tests
394 # compute the approximate number of remaining tests
395 tests, size = 0, 2
395 tests, size = 0, 2
396 while size <= changesets:
396 while size <= changesets:
397 tests, size = tests + 1, size * 2
397 tests, size = tests + 1, size * 2
398 rev = repo.changelog.rev(node)
398 rev = repo.changelog.rev(node)
399 ui.write(_("Testing changeset %d:%s "
399 ui.write(_("Testing changeset %d:%s "
400 "(%d changesets remaining, ~%d tests)\n")
400 "(%d changesets remaining, ~%d tests)\n")
401 % (rev, short(node), changesets, tests))
401 % (rev, short(node), changesets, tests))
402 if not noupdate:
402 if not noupdate:
403 cmdutil.bail_if_changed(repo)
403 cmdutil.bail_if_changed(repo)
404 return hg.clean(repo, node)
404 return hg.clean(repo, node)
405
405
406 def branch(ui, repo, label=None, **opts):
406 def branch(ui, repo, label=None, **opts):
407 """set or show the current branch name
407 """set or show the current branch name
408
408
409 With no argument, show the current branch name. With one argument,
409 With no argument, show the current branch name. With one argument,
410 set the working directory branch name (the branch will not exist
410 set the working directory branch name (the branch will not exist
411 in the repository until the next commit). Standard practice
411 in the repository until the next commit). Standard practice
412 recommends that primary development take place on the 'default'
412 recommends that primary development take place on the 'default'
413 branch.
413 branch.
414
414
415 Unless -f/--force is specified, branch will not let you set a
415 Unless -f/--force is specified, branch will not let you set a
416 branch name that already exists, even if it's inactive.
416 branch name that already exists, even if it's inactive.
417
417
418 Use -C/--clean to reset the working directory branch to that of
418 Use -C/--clean to reset the working directory branch to that of
419 the parent of the working directory, negating a previous branch
419 the parent of the working directory, negating a previous branch
420 change.
420 change.
421
421
422 Use the command 'hg update' to switch to an existing branch. Use
422 Use the command 'hg update' to switch to an existing branch. Use
423 'hg commit --close-branch' to mark this branch as closed.
423 'hg commit --close-branch' to mark this branch as closed.
424 """
424 """
425
425
426 if opts.get('clean'):
426 if opts.get('clean'):
427 label = repo[None].parents()[0].branch()
427 label = repo[None].parents()[0].branch()
428 repo.dirstate.setbranch(label)
428 repo.dirstate.setbranch(label)
429 ui.status(_('reset working directory to branch %s\n') % label)
429 ui.status(_('reset working directory to branch %s\n') % label)
430 elif label:
430 elif label:
431 utflabel = encoding.fromlocal(label)
431 utflabel = encoding.fromlocal(label)
432 if not opts.get('force') and utflabel in repo.branchtags():
432 if not opts.get('force') and utflabel in repo.branchtags():
433 if label not in [p.branch() for p in repo.parents()]:
433 if label not in [p.branch() for p in repo.parents()]:
434 raise util.Abort(_('a branch of the same name already exists'
434 raise util.Abort(_('a branch of the same name already exists'
435 ' (use --force to override)'))
435 ' (use --force to override)'))
436 repo.dirstate.setbranch(utflabel)
436 repo.dirstate.setbranch(utflabel)
437 ui.status(_('marked working directory as branch %s\n') % label)
437 ui.status(_('marked working directory as branch %s\n') % label)
438 else:
438 else:
439 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
439 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
440
440
441 def branches(ui, repo, active=False, closed=False):
441 def branches(ui, repo, active=False, closed=False):
442 """list repository named branches
442 """list repository named branches
443
443
444 List the repository's named branches, indicating which ones are
444 List the repository's named branches, indicating which ones are
445 inactive. If -c/--closed is specified, also list branches which have
445 inactive. If -c/--closed is specified, also list branches which have
446 been marked closed (see hg commit --close-branch).
446 been marked closed (see hg commit --close-branch).
447
447
448 If -a/--active is specified, only show active branches. A branch
448 If -a/--active is specified, only show active branches. A branch
449 is considered active if it contains repository heads.
449 is considered active if it contains repository heads.
450
450
451 Use the command 'hg update' to switch to an existing branch.
451 Use the command 'hg update' to switch to an existing branch.
452 """
452 """
453
453
454 hexfunc = ui.debugflag and hex or short
454 hexfunc = ui.debugflag and hex or short
455 activebranches = [repo[n].branch() for n in repo.heads()]
455 activebranches = [repo[n].branch() for n in repo.heads()]
456 def testactive(tag, node):
456 def testactive(tag, node):
457 realhead = tag in activebranches
457 realhead = tag in activebranches
458 open = node in repo.branchheads(tag, closed=False)
458 open = node in repo.branchheads(tag, closed=False)
459 return realhead and open
459 return realhead and open
460 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
460 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
461 for tag, node in repo.branchtags().items()],
461 for tag, node in repo.branchtags().items()],
462 reverse=True)
462 reverse=True)
463
463
464 for isactive, node, tag in branches:
464 for isactive, node, tag in branches:
465 if (not active) or isactive:
465 if (not active) or isactive:
466 encodedtag = encoding.tolocal(tag)
466 encodedtag = encoding.tolocal(tag)
467 if ui.quiet:
467 if ui.quiet:
468 ui.write("%s\n" % encodedtag)
468 ui.write("%s\n" % encodedtag)
469 else:
469 else:
470 hn = repo.lookup(node)
470 hn = repo.lookup(node)
471 if isactive:
471 if isactive:
472 notice = ''
472 notice = ''
473 elif hn not in repo.branchheads(tag, closed=False):
473 elif hn not in repo.branchheads(tag, closed=False):
474 if not closed:
474 if not closed:
475 continue
475 continue
476 notice = _(' (closed)')
476 notice = _(' (closed)')
477 else:
477 else:
478 notice = _(' (inactive)')
478 notice = _(' (inactive)')
479 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
479 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
480 data = encodedtag, rev, hexfunc(hn), notice
480 data = encodedtag, rev, hexfunc(hn), notice
481 ui.write("%s %s:%s%s\n" % data)
481 ui.write("%s %s:%s%s\n" % data)
482
482
483 def bundle(ui, repo, fname, dest=None, **opts):
483 def bundle(ui, repo, fname, dest=None, **opts):
484 """create a changegroup file
484 """create a changegroup file
485
485
486 Generate a compressed changegroup file collecting changesets not
486 Generate a compressed changegroup file collecting changesets not
487 known to be in another repository.
487 known to be in another repository.
488
488
489 If you omit the destination repository, then hg assumes the
489 If you omit the destination repository, then hg assumes the
490 destination will have all the nodes you specify with --base
490 destination will have all the nodes you specify with --base
491 parameters. To create a bundle containing all changesets, use
491 parameters. To create a bundle containing all changesets, use
492 -a/--all (or --base null).
492 -a/--all (or --base null).
493
493
494 You can change compression method with the -t/--type option.
494 You can change compression method with the -t/--type option.
495 The available compression methods are: none, bzip2, and
495 The available compression methods are: none, bzip2, and
496 gzip (by default, bundles are compressed using bzip2).
496 gzip (by default, bundles are compressed using bzip2).
497
497
498 The bundle file can then be transferred using conventional means
498 The bundle file can then be transferred using conventional means
499 and applied to another repository with the unbundle or pull
499 and applied to another repository with the unbundle or pull
500 command. This is useful when direct push and pull are not
500 command. This is useful when direct push and pull are not
501 available or when exporting an entire repository is undesirable.
501 available or when exporting an entire repository is undesirable.
502
502
503 Applying bundles preserves all changeset contents including
503 Applying bundles preserves all changeset contents including
504 permissions, copy/rename information, and revision history.
504 permissions, copy/rename information, and revision history.
505 """
505 """
506 revs = opts.get('rev') or None
506 revs = opts.get('rev') or None
507 if revs:
507 if revs:
508 revs = [repo.lookup(rev) for rev in revs]
508 revs = [repo.lookup(rev) for rev in revs]
509 if opts.get('all'):
509 if opts.get('all'):
510 base = ['null']
510 base = ['null']
511 else:
511 else:
512 base = opts.get('base')
512 base = opts.get('base')
513 if base:
513 if base:
514 if dest:
514 if dest:
515 raise util.Abort(_("--base is incompatible with specifying "
515 raise util.Abort(_("--base is incompatible with specifying "
516 "a destination"))
516 "a destination"))
517 base = [repo.lookup(rev) for rev in base]
517 base = [repo.lookup(rev) for rev in base]
518 # create the right base
518 # create the right base
519 # XXX: nodesbetween / changegroup* should be "fixed" instead
519 # XXX: nodesbetween / changegroup* should be "fixed" instead
520 o = []
520 o = []
521 has = set((nullid,))
521 has = set((nullid,))
522 for n in base:
522 for n in base:
523 has.update(repo.changelog.reachable(n))
523 has.update(repo.changelog.reachable(n))
524 if revs:
524 if revs:
525 visit = list(revs)
525 visit = list(revs)
526 else:
526 else:
527 visit = repo.changelog.heads()
527 visit = repo.changelog.heads()
528 seen = {}
528 seen = {}
529 while visit:
529 while visit:
530 n = visit.pop(0)
530 n = visit.pop(0)
531 parents = [p for p in repo.changelog.parents(n) if p not in has]
531 parents = [p for p in repo.changelog.parents(n) if p not in has]
532 if len(parents) == 0:
532 if len(parents) == 0:
533 o.insert(0, n)
533 o.insert(0, n)
534 else:
534 else:
535 for p in parents:
535 for p in parents:
536 if p not in seen:
536 if p not in seen:
537 seen[p] = 1
537 seen[p] = 1
538 visit.append(p)
538 visit.append(p)
539 else:
539 else:
540 dest = ui.expandpath(dest or 'default-push', dest or 'default')
540 dest = ui.expandpath(dest or 'default-push', dest or 'default')
541 dest, branches = hg.parseurl(dest)
541 dest, branches = hg.parseurl(dest, opts.get('branch'))
542 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
542 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
543 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
543 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
544 o = repo.findoutgoing(other, force=opts.get('force'))
544 o = repo.findoutgoing(other, force=opts.get('force'))
545
545
546 if revs:
546 if revs:
547 cg = repo.changegroupsubset(o, revs, 'bundle')
547 cg = repo.changegroupsubset(o, revs, 'bundle')
548 else:
548 else:
549 cg = repo.changegroup(o, 'bundle')
549 cg = repo.changegroup(o, 'bundle')
550
550
551 bundletype = opts.get('type', 'bzip2').lower()
551 bundletype = opts.get('type', 'bzip2').lower()
552 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
552 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
553 bundletype = btypes.get(bundletype)
553 bundletype = btypes.get(bundletype)
554 if bundletype not in changegroup.bundletypes:
554 if bundletype not in changegroup.bundletypes:
555 raise util.Abort(_('unknown bundle type specified with --type'))
555 raise util.Abort(_('unknown bundle type specified with --type'))
556
556
557 changegroup.writebundle(cg, fname, bundletype)
557 changegroup.writebundle(cg, fname, bundletype)
558
558
559 def cat(ui, repo, file1, *pats, **opts):
559 def cat(ui, repo, file1, *pats, **opts):
560 """output the current or given revision of files
560 """output the current or given revision of files
561
561
562 Print the specified files as they were at the given revision. If
562 Print the specified files as they were at the given revision. If
563 no revision is given, the parent of the working directory is used,
563 no revision is given, the parent of the working directory is used,
564 or tip if no revision is checked out.
564 or tip if no revision is checked out.
565
565
566 Output may be to a file, in which case the name of the file is
566 Output may be to a file, in which case the name of the file is
567 given using a format string. The formatting rules are the same as
567 given using a format string. The formatting rules are the same as
568 for the export command, with the following additions:
568 for the export command, with the following additions:
569
569
570 :``%s``: basename of file being printed
570 :``%s``: basename of file being printed
571 :``%d``: dirname of file being printed, or '.' if in repository root
571 :``%d``: dirname of file being printed, or '.' if in repository root
572 :``%p``: root-relative path name of file being printed
572 :``%p``: root-relative path name of file being printed
573 """
573 """
574 ctx = repo[opts.get('rev')]
574 ctx = repo[opts.get('rev')]
575 err = 1
575 err = 1
576 m = cmdutil.match(repo, (file1,) + pats, opts)
576 m = cmdutil.match(repo, (file1,) + pats, opts)
577 for abs in ctx.walk(m):
577 for abs in ctx.walk(m):
578 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
578 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
579 data = ctx[abs].data()
579 data = ctx[abs].data()
580 if opts.get('decode'):
580 if opts.get('decode'):
581 data = repo.wwritedata(abs, data)
581 data = repo.wwritedata(abs, data)
582 fp.write(data)
582 fp.write(data)
583 err = 0
583 err = 0
584 return err
584 return err
585
585
586 def clone(ui, source, dest=None, **opts):
586 def clone(ui, source, dest=None, **opts):
587 """make a copy of an existing repository
587 """make a copy of an existing repository
588
588
589 Create a copy of an existing repository in a new directory.
589 Create a copy of an existing repository in a new directory.
590
590
591 If no destination directory name is specified, it defaults to the
591 If no destination directory name is specified, it defaults to the
592 basename of the source.
592 basename of the source.
593
593
594 The location of the source is added to the new repository's
594 The location of the source is added to the new repository's
595 .hg/hgrc file, as the default to be used for future pulls.
595 .hg/hgrc file, as the default to be used for future pulls.
596
596
597 See 'hg help urls' for valid source format details.
597 See 'hg help urls' for valid source format details.
598
598
599 It is possible to specify an ``ssh://`` URL as the destination, but no
599 It is possible to specify an ``ssh://`` URL as the destination, but no
600 .hg/hgrc and working directory will be created on the remote side.
600 .hg/hgrc and working directory will be created on the remote side.
601 Please see 'hg help urls' for important details about ``ssh://`` URLs.
601 Please see 'hg help urls' for important details about ``ssh://`` URLs.
602
602
603 If the -U/--noupdate option is specified, the new clone will contain
603 If the -U/--noupdate option is specified, the new clone will contain
604 only a repository (.hg) and no working copy (the working copy parent
604 only a repository (.hg) and no working copy (the working copy parent
605 will be the null changeset). Otherwise, clone will initially check
605 will be the null changeset). Otherwise, clone will initially check
606 out (in order of precedence):
606 out (in order of precedence):
607
607
608 a) the changeset, tag or branch specified with -u/--updaterev
608 a) the changeset, tag or branch specified with -u/--updaterev
609 b) the changeset, tag or branch given with the first -r/--rev
609 b) the changeset, tag or branch given with the first -r/--rev
610 c) the branch given with the url#branch source syntax
610 c) the branch given with the first -b/--branch
611 d) the head of the default branch
611 d) the branch given with the url#branch source syntax
612 e) the head of the default branch
612
613
613 Use 'hg clone -u . src dst' to checkout the source repository's
614 Use 'hg clone -u . src dst' to checkout the source repository's
614 parent changeset (applicable for local source repositories only).
615 parent changeset (applicable for local source repositories only).
615
616
616 A set of changesets (tags, or branch names) to pull may be specified
617 A set of changesets (tags, or branch names) to pull may be specified
617 by listing each changeset (tag, or branch name) with -r/--rev.
618 by listing each changeset (tag, or branch name) with -r/--rev.
618 If -r/--rev is used, the cloned repository will contain only a subset
619 If -r/--rev is used, the cloned repository will contain only a subset
619 of the changesets of the source repository. Only the set of changesets
620 of the changesets of the source repository. Only the set of changesets
620 defined by all -r/--rev options (including all their ancestors)
621 defined by all -r/--rev options (including all their ancestors)
621 will be pulled into the destination repository.
622 will be pulled into the destination repository.
622 No subsequent changesets (including subsequent tags) will be present
623 No subsequent changesets (including subsequent tags) will be present
623 in the destination.
624 in the destination.
624
625
625 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
626 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
626 local source repositories.
627 local source repositories.
627
628
628 For efficiency, hardlinks are used for cloning whenever the source
629 For efficiency, hardlinks are used for cloning whenever the source
629 and destination are on the same filesystem (note this applies only
630 and destination are on the same filesystem (note this applies only
630 to the repository data, not to the checked out files). Some
631 to the repository data, not to the checked out files). Some
631 filesystems, such as AFS, implement hardlinking incorrectly, but
632 filesystems, such as AFS, implement hardlinking incorrectly, but
632 do not report errors. In these cases, use the --pull option to
633 do not report errors. In these cases, use the --pull option to
633 avoid hardlinking.
634 avoid hardlinking.
634
635
635 In some cases, you can clone repositories and checked out files
636 In some cases, you can clone repositories and checked out files
636 using full hardlinks with ::
637 using full hardlinks with ::
637
638
638 $ cp -al REPO REPOCLONE
639 $ cp -al REPO REPOCLONE
639
640
640 This is the fastest way to clone, but it is not always safe. The
641 This is the fastest way to clone, but it is not always safe. The
641 operation is not atomic (making sure REPO is not modified during
642 operation is not atomic (making sure REPO is not modified during
642 the operation is up to you) and you have to make sure your editor
643 the operation is up to you) and you have to make sure your editor
643 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
644 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
644 this is not compatible with certain extensions that place their
645 this is not compatible with certain extensions that place their
645 metadata under the .hg directory, such as mq.
646 metadata under the .hg directory, such as mq.
646 """
647 """
647 if opts.get('noupdate') and opts.get('updaterev'):
648 if opts.get('noupdate') and opts.get('updaterev'):
648 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
649 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
649
650
650 hg.clone(cmdutil.remoteui(ui, opts), source, dest,
651 hg.clone(cmdutil.remoteui(ui, opts), source, dest,
651 pull=opts.get('pull'),
652 pull=opts.get('pull'),
652 stream=opts.get('uncompressed'),
653 stream=opts.get('uncompressed'),
653 rev=opts.get('rev'),
654 rev=opts.get('rev'),
654 update=opts.get('updaterev') or not opts.get('noupdate'))
655 update=opts.get('updaterev') or not opts.get('noupdate'),
656 branch=opts.get('branch'))
655
657
656 def commit(ui, repo, *pats, **opts):
658 def commit(ui, repo, *pats, **opts):
657 """commit the specified files or all outstanding changes
659 """commit the specified files or all outstanding changes
658
660
659 Commit changes to the given files into the repository. Unlike a
661 Commit changes to the given files into the repository. Unlike a
660 centralized RCS, this operation is a local operation. See hg push
662 centralized RCS, this operation is a local operation. See hg push
661 for a way to actively distribute your changes.
663 for a way to actively distribute your changes.
662
664
663 If a list of files is omitted, all changes reported by "hg status"
665 If a list of files is omitted, all changes reported by "hg status"
664 will be committed.
666 will be committed.
665
667
666 If you are committing the result of a merge, do not provide any
668 If you are committing the result of a merge, do not provide any
667 filenames or -I/-X filters.
669 filenames or -I/-X filters.
668
670
669 If no commit message is specified, the configured editor is
671 If no commit message is specified, the configured editor is
670 started to prompt you for a message.
672 started to prompt you for a message.
671
673
672 See 'hg help dates' for a list of formats valid for -d/--date.
674 See 'hg help dates' for a list of formats valid for -d/--date.
673 """
675 """
674 extra = {}
676 extra = {}
675 if opts.get('close_branch'):
677 if opts.get('close_branch'):
676 extra['close'] = 1
678 extra['close'] = 1
677 e = cmdutil.commiteditor
679 e = cmdutil.commiteditor
678 if opts.get('force_editor'):
680 if opts.get('force_editor'):
679 e = cmdutil.commitforceeditor
681 e = cmdutil.commitforceeditor
680
682
681 def commitfunc(ui, repo, message, match, opts):
683 def commitfunc(ui, repo, message, match, opts):
682 return repo.commit(message, opts.get('user'), opts.get('date'), match,
684 return repo.commit(message, opts.get('user'), opts.get('date'), match,
683 editor=e, extra=extra)
685 editor=e, extra=extra)
684
686
685 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
687 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
686 if not node:
688 if not node:
687 ui.status(_("nothing changed\n"))
689 ui.status(_("nothing changed\n"))
688 return
690 return
689 cl = repo.changelog
691 cl = repo.changelog
690 rev = cl.rev(node)
692 rev = cl.rev(node)
691 parents = cl.parentrevs(rev)
693 parents = cl.parentrevs(rev)
692 if rev - 1 in parents:
694 if rev - 1 in parents:
693 # one of the parents was the old tip
695 # one of the parents was the old tip
694 pass
696 pass
695 elif (parents == (nullrev, nullrev) or
697 elif (parents == (nullrev, nullrev) or
696 len(cl.heads(cl.node(parents[0]))) > 1 and
698 len(cl.heads(cl.node(parents[0]))) > 1 and
697 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
699 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
698 ui.status(_('created new head\n'))
700 ui.status(_('created new head\n'))
699
701
700 if ui.debugflag:
702 if ui.debugflag:
701 ui.write(_('committed changeset %d:%s\n') % (rev, hex(node)))
703 ui.write(_('committed changeset %d:%s\n') % (rev, hex(node)))
702 elif ui.verbose:
704 elif ui.verbose:
703 ui.write(_('committed changeset %d:%s\n') % (rev, short(node)))
705 ui.write(_('committed changeset %d:%s\n') % (rev, short(node)))
704
706
705 def copy(ui, repo, *pats, **opts):
707 def copy(ui, repo, *pats, **opts):
706 """mark files as copied for the next commit
708 """mark files as copied for the next commit
707
709
708 Mark dest as having copies of source files. If dest is a
710 Mark dest as having copies of source files. If dest is a
709 directory, copies are put in that directory. If dest is a file,
711 directory, copies are put in that directory. If dest is a file,
710 the source must be a single file.
712 the source must be a single file.
711
713
712 By default, this command copies the contents of files as they
714 By default, this command copies the contents of files as they
713 exist in the working directory. If invoked with -A/--after, the
715 exist in the working directory. If invoked with -A/--after, the
714 operation is recorded, but no copying is performed.
716 operation is recorded, but no copying is performed.
715
717
716 This command takes effect with the next commit. To undo a copy
718 This command takes effect with the next commit. To undo a copy
717 before that, see hg revert.
719 before that, see hg revert.
718 """
720 """
719 wlock = repo.wlock(False)
721 wlock = repo.wlock(False)
720 try:
722 try:
721 return cmdutil.copy(ui, repo, pats, opts)
723 return cmdutil.copy(ui, repo, pats, opts)
722 finally:
724 finally:
723 wlock.release()
725 wlock.release()
724
726
725 def debugancestor(ui, repo, *args):
727 def debugancestor(ui, repo, *args):
726 """find the ancestor revision of two revisions in a given index"""
728 """find the ancestor revision of two revisions in a given index"""
727 if len(args) == 3:
729 if len(args) == 3:
728 index, rev1, rev2 = args
730 index, rev1, rev2 = args
729 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
731 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
730 lookup = r.lookup
732 lookup = r.lookup
731 elif len(args) == 2:
733 elif len(args) == 2:
732 if not repo:
734 if not repo:
733 raise util.Abort(_("There is no Mercurial repository here "
735 raise util.Abort(_("There is no Mercurial repository here "
734 "(.hg not found)"))
736 "(.hg not found)"))
735 rev1, rev2 = args
737 rev1, rev2 = args
736 r = repo.changelog
738 r = repo.changelog
737 lookup = repo.lookup
739 lookup = repo.lookup
738 else:
740 else:
739 raise util.Abort(_('either two or three arguments required'))
741 raise util.Abort(_('either two or three arguments required'))
740 a = r.ancestor(lookup(rev1), lookup(rev2))
742 a = r.ancestor(lookup(rev1), lookup(rev2))
741 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
743 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
742
744
743 def debugcommands(ui, cmd='', *args):
745 def debugcommands(ui, cmd='', *args):
744 for cmd, vals in sorted(table.iteritems()):
746 for cmd, vals in sorted(table.iteritems()):
745 cmd = cmd.split('|')[0].strip('^')
747 cmd = cmd.split('|')[0].strip('^')
746 opts = ', '.join([i[1] for i in vals[1]])
748 opts = ', '.join([i[1] for i in vals[1]])
747 ui.write('%s: %s\n' % (cmd, opts))
749 ui.write('%s: %s\n' % (cmd, opts))
748
750
749 def debugcomplete(ui, cmd='', **opts):
751 def debugcomplete(ui, cmd='', **opts):
750 """returns the completion list associated with the given command"""
752 """returns the completion list associated with the given command"""
751
753
752 if opts.get('options'):
754 if opts.get('options'):
753 options = []
755 options = []
754 otables = [globalopts]
756 otables = [globalopts]
755 if cmd:
757 if cmd:
756 aliases, entry = cmdutil.findcmd(cmd, table, False)
758 aliases, entry = cmdutil.findcmd(cmd, table, False)
757 otables.append(entry[1])
759 otables.append(entry[1])
758 for t in otables:
760 for t in otables:
759 for o in t:
761 for o in t:
760 if o[0]:
762 if o[0]:
761 options.append('-%s' % o[0])
763 options.append('-%s' % o[0])
762 options.append('--%s' % o[1])
764 options.append('--%s' % o[1])
763 ui.write("%s\n" % "\n".join(options))
765 ui.write("%s\n" % "\n".join(options))
764 return
766 return
765
767
766 cmdlist = cmdutil.findpossible(cmd, table)
768 cmdlist = cmdutil.findpossible(cmd, table)
767 if ui.verbose:
769 if ui.verbose:
768 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
770 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
769 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
771 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
770
772
771 def debugfsinfo(ui, path = "."):
773 def debugfsinfo(ui, path = "."):
772 open('.debugfsinfo', 'w').write('')
774 open('.debugfsinfo', 'w').write('')
773 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
775 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
774 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
776 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
775 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
777 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
776 and 'yes' or 'no'))
778 and 'yes' or 'no'))
777 os.unlink('.debugfsinfo')
779 os.unlink('.debugfsinfo')
778
780
779 def debugrebuildstate(ui, repo, rev="tip"):
781 def debugrebuildstate(ui, repo, rev="tip"):
780 """rebuild the dirstate as it would look like for the given revision"""
782 """rebuild the dirstate as it would look like for the given revision"""
781 ctx = repo[rev]
783 ctx = repo[rev]
782 wlock = repo.wlock()
784 wlock = repo.wlock()
783 try:
785 try:
784 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
786 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
785 finally:
787 finally:
786 wlock.release()
788 wlock.release()
787
789
788 def debugcheckstate(ui, repo):
790 def debugcheckstate(ui, repo):
789 """validate the correctness of the current dirstate"""
791 """validate the correctness of the current dirstate"""
790 parent1, parent2 = repo.dirstate.parents()
792 parent1, parent2 = repo.dirstate.parents()
791 m1 = repo[parent1].manifest()
793 m1 = repo[parent1].manifest()
792 m2 = repo[parent2].manifest()
794 m2 = repo[parent2].manifest()
793 errors = 0
795 errors = 0
794 for f in repo.dirstate:
796 for f in repo.dirstate:
795 state = repo.dirstate[f]
797 state = repo.dirstate[f]
796 if state in "nr" and f not in m1:
798 if state in "nr" and f not in m1:
797 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
799 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
798 errors += 1
800 errors += 1
799 if state in "a" and f in m1:
801 if state in "a" and f in m1:
800 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
802 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
801 errors += 1
803 errors += 1
802 if state in "m" and f not in m1 and f not in m2:
804 if state in "m" and f not in m1 and f not in m2:
803 ui.warn(_("%s in state %s, but not in either manifest\n") %
805 ui.warn(_("%s in state %s, but not in either manifest\n") %
804 (f, state))
806 (f, state))
805 errors += 1
807 errors += 1
806 for f in m1:
808 for f in m1:
807 state = repo.dirstate[f]
809 state = repo.dirstate[f]
808 if state not in "nrm":
810 if state not in "nrm":
809 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
811 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
810 errors += 1
812 errors += 1
811 if errors:
813 if errors:
812 error = _(".hg/dirstate inconsistent with current parent's manifest")
814 error = _(".hg/dirstate inconsistent with current parent's manifest")
813 raise util.Abort(error)
815 raise util.Abort(error)
814
816
815 def showconfig(ui, repo, *values, **opts):
817 def showconfig(ui, repo, *values, **opts):
816 """show combined config settings from all hgrc files
818 """show combined config settings from all hgrc files
817
819
818 With no arguments, print names and values of all config items.
820 With no arguments, print names and values of all config items.
819
821
820 With one argument of the form section.name, print just the value
822 With one argument of the form section.name, print just the value
821 of that config item.
823 of that config item.
822
824
823 With multiple arguments, print names and values of all config
825 With multiple arguments, print names and values of all config
824 items with matching section names.
826 items with matching section names.
825
827
826 With --debug, the source (filename and line number) is printed
828 With --debug, the source (filename and line number) is printed
827 for each config item.
829 for each config item.
828 """
830 """
829
831
830 untrusted = bool(opts.get('untrusted'))
832 untrusted = bool(opts.get('untrusted'))
831 if values:
833 if values:
832 if len([v for v in values if '.' in v]) > 1:
834 if len([v for v in values if '.' in v]) > 1:
833 raise util.Abort(_('only one config item permitted'))
835 raise util.Abort(_('only one config item permitted'))
834 for section, name, value in ui.walkconfig(untrusted=untrusted):
836 for section, name, value in ui.walkconfig(untrusted=untrusted):
835 sectname = section + '.' + name
837 sectname = section + '.' + name
836 if values:
838 if values:
837 for v in values:
839 for v in values:
838 if v == section:
840 if v == section:
839 ui.debug('%s: ' %
841 ui.debug('%s: ' %
840 ui.configsource(section, name, untrusted))
842 ui.configsource(section, name, untrusted))
841 ui.write('%s=%s\n' % (sectname, value))
843 ui.write('%s=%s\n' % (sectname, value))
842 elif v == sectname:
844 elif v == sectname:
843 ui.debug('%s: ' %
845 ui.debug('%s: ' %
844 ui.configsource(section, name, untrusted))
846 ui.configsource(section, name, untrusted))
845 ui.write(value, '\n')
847 ui.write(value, '\n')
846 else:
848 else:
847 ui.debug('%s: ' %
849 ui.debug('%s: ' %
848 ui.configsource(section, name, untrusted))
850 ui.configsource(section, name, untrusted))
849 ui.write('%s=%s\n' % (sectname, value))
851 ui.write('%s=%s\n' % (sectname, value))
850
852
851 def debugsetparents(ui, repo, rev1, rev2=None):
853 def debugsetparents(ui, repo, rev1, rev2=None):
852 """manually set the parents of the current working directory
854 """manually set the parents of the current working directory
853
855
854 This is useful for writing repository conversion tools, but should
856 This is useful for writing repository conversion tools, but should
855 be used with care.
857 be used with care.
856 """
858 """
857
859
858 if not rev2:
860 if not rev2:
859 rev2 = hex(nullid)
861 rev2 = hex(nullid)
860
862
861 wlock = repo.wlock()
863 wlock = repo.wlock()
862 try:
864 try:
863 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
865 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
864 finally:
866 finally:
865 wlock.release()
867 wlock.release()
866
868
867 def debugstate(ui, repo, nodates=None):
869 def debugstate(ui, repo, nodates=None):
868 """show the contents of the current dirstate"""
870 """show the contents of the current dirstate"""
869 timestr = ""
871 timestr = ""
870 showdate = not nodates
872 showdate = not nodates
871 for file_, ent in sorted(repo.dirstate._map.iteritems()):
873 for file_, ent in sorted(repo.dirstate._map.iteritems()):
872 if showdate:
874 if showdate:
873 if ent[3] == -1:
875 if ent[3] == -1:
874 # Pad or slice to locale representation
876 # Pad or slice to locale representation
875 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
877 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
876 time.localtime(0)))
878 time.localtime(0)))
877 timestr = 'unset'
879 timestr = 'unset'
878 timestr = (timestr[:locale_len] +
880 timestr = (timestr[:locale_len] +
879 ' ' * (locale_len - len(timestr)))
881 ' ' * (locale_len - len(timestr)))
880 else:
882 else:
881 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
883 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
882 time.localtime(ent[3]))
884 time.localtime(ent[3]))
883 if ent[1] & 020000:
885 if ent[1] & 020000:
884 mode = 'lnk'
886 mode = 'lnk'
885 else:
887 else:
886 mode = '%3o' % (ent[1] & 0777)
888 mode = '%3o' % (ent[1] & 0777)
887 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
889 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
888 for f in repo.dirstate.copies():
890 for f in repo.dirstate.copies():
889 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
891 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
890
892
891 def debugsub(ui, repo, rev=None):
893 def debugsub(ui, repo, rev=None):
892 if rev == '':
894 if rev == '':
893 rev = None
895 rev = None
894 for k, v in sorted(repo[rev].substate.items()):
896 for k, v in sorted(repo[rev].substate.items()):
895 ui.write('path %s\n' % k)
897 ui.write('path %s\n' % k)
896 ui.write(' source %s\n' % v[0])
898 ui.write(' source %s\n' % v[0])
897 ui.write(' revision %s\n' % v[1])
899 ui.write(' revision %s\n' % v[1])
898
900
899 def debugdata(ui, file_, rev):
901 def debugdata(ui, file_, rev):
900 """dump the contents of a data file revision"""
902 """dump the contents of a data file revision"""
901 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
903 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
902 try:
904 try:
903 ui.write(r.revision(r.lookup(rev)))
905 ui.write(r.revision(r.lookup(rev)))
904 except KeyError:
906 except KeyError:
905 raise util.Abort(_('invalid revision identifier %s') % rev)
907 raise util.Abort(_('invalid revision identifier %s') % rev)
906
908
907 def debugdate(ui, date, range=None, **opts):
909 def debugdate(ui, date, range=None, **opts):
908 """parse and display a date"""
910 """parse and display a date"""
909 if opts["extended"]:
911 if opts["extended"]:
910 d = util.parsedate(date, util.extendeddateformats)
912 d = util.parsedate(date, util.extendeddateformats)
911 else:
913 else:
912 d = util.parsedate(date)
914 d = util.parsedate(date)
913 ui.write("internal: %s %s\n" % d)
915 ui.write("internal: %s %s\n" % d)
914 ui.write("standard: %s\n" % util.datestr(d))
916 ui.write("standard: %s\n" % util.datestr(d))
915 if range:
917 if range:
916 m = util.matchdate(range)
918 m = util.matchdate(range)
917 ui.write("match: %s\n" % m(d[0]))
919 ui.write("match: %s\n" % m(d[0]))
918
920
919 def debugindex(ui, file_):
921 def debugindex(ui, file_):
920 """dump the contents of an index file"""
922 """dump the contents of an index file"""
921 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
923 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
922 ui.write(" rev offset length base linkrev"
924 ui.write(" rev offset length base linkrev"
923 " nodeid p1 p2\n")
925 " nodeid p1 p2\n")
924 for i in r:
926 for i in r:
925 node = r.node(i)
927 node = r.node(i)
926 try:
928 try:
927 pp = r.parents(node)
929 pp = r.parents(node)
928 except:
930 except:
929 pp = [nullid, nullid]
931 pp = [nullid, nullid]
930 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
932 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
931 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
933 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
932 short(node), short(pp[0]), short(pp[1])))
934 short(node), short(pp[0]), short(pp[1])))
933
935
934 def debugindexdot(ui, file_):
936 def debugindexdot(ui, file_):
935 """dump an index DAG as a graphviz dot file"""
937 """dump an index DAG as a graphviz dot file"""
936 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
938 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
937 ui.write("digraph G {\n")
939 ui.write("digraph G {\n")
938 for i in r:
940 for i in r:
939 node = r.node(i)
941 node = r.node(i)
940 pp = r.parents(node)
942 pp = r.parents(node)
941 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
943 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
942 if pp[1] != nullid:
944 if pp[1] != nullid:
943 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
945 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
944 ui.write("}\n")
946 ui.write("}\n")
945
947
946 def debuginstall(ui):
948 def debuginstall(ui):
947 '''test Mercurial installation'''
949 '''test Mercurial installation'''
948
950
949 def writetemp(contents):
951 def writetemp(contents):
950 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
952 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
951 f = os.fdopen(fd, "wb")
953 f = os.fdopen(fd, "wb")
952 f.write(contents)
954 f.write(contents)
953 f.close()
955 f.close()
954 return name
956 return name
955
957
956 problems = 0
958 problems = 0
957
959
958 # encoding
960 # encoding
959 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
961 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
960 try:
962 try:
961 encoding.fromlocal("test")
963 encoding.fromlocal("test")
962 except util.Abort, inst:
964 except util.Abort, inst:
963 ui.write(" %s\n" % inst)
965 ui.write(" %s\n" % inst)
964 ui.write(_(" (check that your locale is properly set)\n"))
966 ui.write(_(" (check that your locale is properly set)\n"))
965 problems += 1
967 problems += 1
966
968
967 # compiled modules
969 # compiled modules
968 ui.status(_("Checking extensions...\n"))
970 ui.status(_("Checking extensions...\n"))
969 try:
971 try:
970 import bdiff, mpatch, base85
972 import bdiff, mpatch, base85
971 except Exception, inst:
973 except Exception, inst:
972 ui.write(" %s\n" % inst)
974 ui.write(" %s\n" % inst)
973 ui.write(_(" One or more extensions could not be found"))
975 ui.write(_(" One or more extensions could not be found"))
974 ui.write(_(" (check that you compiled the extensions)\n"))
976 ui.write(_(" (check that you compiled the extensions)\n"))
975 problems += 1
977 problems += 1
976
978
977 # templates
979 # templates
978 ui.status(_("Checking templates...\n"))
980 ui.status(_("Checking templates...\n"))
979 try:
981 try:
980 import templater
982 import templater
981 templater.templater(templater.templatepath("map-cmdline.default"))
983 templater.templater(templater.templatepath("map-cmdline.default"))
982 except Exception, inst:
984 except Exception, inst:
983 ui.write(" %s\n" % inst)
985 ui.write(" %s\n" % inst)
984 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
986 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
985 problems += 1
987 problems += 1
986
988
987 # patch
989 # patch
988 ui.status(_("Checking patch...\n"))
990 ui.status(_("Checking patch...\n"))
989 patchproblems = 0
991 patchproblems = 0
990 a = "1\n2\n3\n4\n"
992 a = "1\n2\n3\n4\n"
991 b = "1\n2\n3\ninsert\n4\n"
993 b = "1\n2\n3\ninsert\n4\n"
992 fa = writetemp(a)
994 fa = writetemp(a)
993 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
995 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
994 os.path.basename(fa))
996 os.path.basename(fa))
995 fd = writetemp(d)
997 fd = writetemp(d)
996
998
997 files = {}
999 files = {}
998 try:
1000 try:
999 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1001 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1000 except util.Abort, e:
1002 except util.Abort, e:
1001 ui.write(_(" patch call failed:\n"))
1003 ui.write(_(" patch call failed:\n"))
1002 ui.write(" " + str(e) + "\n")
1004 ui.write(" " + str(e) + "\n")
1003 patchproblems += 1
1005 patchproblems += 1
1004 else:
1006 else:
1005 if list(files) != [os.path.basename(fa)]:
1007 if list(files) != [os.path.basename(fa)]:
1006 ui.write(_(" unexpected patch output!\n"))
1008 ui.write(_(" unexpected patch output!\n"))
1007 patchproblems += 1
1009 patchproblems += 1
1008 a = open(fa).read()
1010 a = open(fa).read()
1009 if a != b:
1011 if a != b:
1010 ui.write(_(" patch test failed!\n"))
1012 ui.write(_(" patch test failed!\n"))
1011 patchproblems += 1
1013 patchproblems += 1
1012
1014
1013 if patchproblems:
1015 if patchproblems:
1014 if ui.config('ui', 'patch'):
1016 if ui.config('ui', 'patch'):
1015 ui.write(_(" (Current patch tool may be incompatible with patch,"
1017 ui.write(_(" (Current patch tool may be incompatible with patch,"
1016 " or misconfigured. Please check your .hgrc file)\n"))
1018 " or misconfigured. Please check your .hgrc file)\n"))
1017 else:
1019 else:
1018 ui.write(_(" Internal patcher failure, please report this error"
1020 ui.write(_(" Internal patcher failure, please report this error"
1019 " to http://mercurial.selenic.com/bts/\n"))
1021 " to http://mercurial.selenic.com/bts/\n"))
1020 problems += patchproblems
1022 problems += patchproblems
1021
1023
1022 os.unlink(fa)
1024 os.unlink(fa)
1023 os.unlink(fd)
1025 os.unlink(fd)
1024
1026
1025 # editor
1027 # editor
1026 ui.status(_("Checking commit editor...\n"))
1028 ui.status(_("Checking commit editor...\n"))
1027 editor = ui.geteditor()
1029 editor = ui.geteditor()
1028 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1030 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1029 if not cmdpath:
1031 if not cmdpath:
1030 if editor == 'vi':
1032 if editor == 'vi':
1031 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1033 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1032 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1034 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1033 else:
1035 else:
1034 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1036 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1035 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1037 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1036 problems += 1
1038 problems += 1
1037
1039
1038 # check username
1040 # check username
1039 ui.status(_("Checking username...\n"))
1041 ui.status(_("Checking username...\n"))
1040 try:
1042 try:
1041 user = ui.username()
1043 user = ui.username()
1042 except util.Abort, e:
1044 except util.Abort, e:
1043 ui.write(" %s\n" % e)
1045 ui.write(" %s\n" % e)
1044 ui.write(_(" (specify a username in your .hgrc file)\n"))
1046 ui.write(_(" (specify a username in your .hgrc file)\n"))
1045 problems += 1
1047 problems += 1
1046
1048
1047 if not problems:
1049 if not problems:
1048 ui.status(_("No problems detected\n"))
1050 ui.status(_("No problems detected\n"))
1049 else:
1051 else:
1050 ui.write(_("%s problems detected,"
1052 ui.write(_("%s problems detected,"
1051 " please check your install!\n") % problems)
1053 " please check your install!\n") % problems)
1052
1054
1053 return problems
1055 return problems
1054
1056
1055 def debugrename(ui, repo, file1, *pats, **opts):
1057 def debugrename(ui, repo, file1, *pats, **opts):
1056 """dump rename information"""
1058 """dump rename information"""
1057
1059
1058 ctx = repo[opts.get('rev')]
1060 ctx = repo[opts.get('rev')]
1059 m = cmdutil.match(repo, (file1,) + pats, opts)
1061 m = cmdutil.match(repo, (file1,) + pats, opts)
1060 for abs in ctx.walk(m):
1062 for abs in ctx.walk(m):
1061 fctx = ctx[abs]
1063 fctx = ctx[abs]
1062 o = fctx.filelog().renamed(fctx.filenode())
1064 o = fctx.filelog().renamed(fctx.filenode())
1063 rel = m.rel(abs)
1065 rel = m.rel(abs)
1064 if o:
1066 if o:
1065 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1067 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1066 else:
1068 else:
1067 ui.write(_("%s not renamed\n") % rel)
1069 ui.write(_("%s not renamed\n") % rel)
1068
1070
1069 def debugwalk(ui, repo, *pats, **opts):
1071 def debugwalk(ui, repo, *pats, **opts):
1070 """show how files match on given patterns"""
1072 """show how files match on given patterns"""
1071 m = cmdutil.match(repo, pats, opts)
1073 m = cmdutil.match(repo, pats, opts)
1072 items = list(repo.walk(m))
1074 items = list(repo.walk(m))
1073 if not items:
1075 if not items:
1074 return
1076 return
1075 fmt = 'f %%-%ds %%-%ds %%s' % (
1077 fmt = 'f %%-%ds %%-%ds %%s' % (
1076 max([len(abs) for abs in items]),
1078 max([len(abs) for abs in items]),
1077 max([len(m.rel(abs)) for abs in items]))
1079 max([len(m.rel(abs)) for abs in items]))
1078 for abs in items:
1080 for abs in items:
1079 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1081 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1080 ui.write("%s\n" % line.rstrip())
1082 ui.write("%s\n" % line.rstrip())
1081
1083
1082 def diff(ui, repo, *pats, **opts):
1084 def diff(ui, repo, *pats, **opts):
1083 """diff repository (or selected files)
1085 """diff repository (or selected files)
1084
1086
1085 Show differences between revisions for the specified files.
1087 Show differences between revisions for the specified files.
1086
1088
1087 Differences between files are shown using the unified diff format.
1089 Differences between files are shown using the unified diff format.
1088
1090
1089 NOTE: diff may generate unexpected results for merges, as it will
1091 NOTE: diff may generate unexpected results for merges, as it will
1090 default to comparing against the working directory's first parent
1092 default to comparing against the working directory's first parent
1091 changeset if no revisions are specified.
1093 changeset if no revisions are specified.
1092
1094
1093 When two revision arguments are given, then changes are shown
1095 When two revision arguments are given, then changes are shown
1094 between those revisions. If only one revision is specified then
1096 between those revisions. If only one revision is specified then
1095 that revision is compared to the working directory, and, when no
1097 that revision is compared to the working directory, and, when no
1096 revisions are specified, the working directory files are compared
1098 revisions are specified, the working directory files are compared
1097 to its parent.
1099 to its parent.
1098
1100
1099 Without the -a/--text option, diff will avoid generating diffs of
1101 Without the -a/--text option, diff will avoid generating diffs of
1100 files it detects as binary. With -a, diff will generate a diff
1102 files it detects as binary. With -a, diff will generate a diff
1101 anyway, probably with undesirable results.
1103 anyway, probably with undesirable results.
1102
1104
1103 Use the -g/--git option to generate diffs in the git extended diff
1105 Use the -g/--git option to generate diffs in the git extended diff
1104 format. For more information, read 'hg help diffs'.
1106 format. For more information, read 'hg help diffs'.
1105 """
1107 """
1106
1108
1107 revs = opts.get('rev')
1109 revs = opts.get('rev')
1108 change = opts.get('change')
1110 change = opts.get('change')
1109 stat = opts.get('stat')
1111 stat = opts.get('stat')
1110 reverse = opts.get('reverse')
1112 reverse = opts.get('reverse')
1111
1113
1112 if revs and change:
1114 if revs and change:
1113 msg = _('cannot specify --rev and --change at the same time')
1115 msg = _('cannot specify --rev and --change at the same time')
1114 raise util.Abort(msg)
1116 raise util.Abort(msg)
1115 elif change:
1117 elif change:
1116 node2 = repo.lookup(change)
1118 node2 = repo.lookup(change)
1117 node1 = repo[node2].parents()[0].node()
1119 node1 = repo[node2].parents()[0].node()
1118 else:
1120 else:
1119 node1, node2 = cmdutil.revpair(repo, revs)
1121 node1, node2 = cmdutil.revpair(repo, revs)
1120
1122
1121 if reverse:
1123 if reverse:
1122 node1, node2 = node2, node1
1124 node1, node2 = node2, node1
1123
1125
1124 if stat:
1126 if stat:
1125 opts['unified'] = '0'
1127 opts['unified'] = '0'
1126 diffopts = patch.diffopts(ui, opts)
1128 diffopts = patch.diffopts(ui, opts)
1127
1129
1128 m = cmdutil.match(repo, pats, opts)
1130 m = cmdutil.match(repo, pats, opts)
1129 it = patch.diff(repo, node1, node2, match=m, opts=diffopts)
1131 it = patch.diff(repo, node1, node2, match=m, opts=diffopts)
1130 if stat:
1132 if stat:
1131 width = ui.interactive() and util.termwidth() or 80
1133 width = ui.interactive() and util.termwidth() or 80
1132 ui.write(patch.diffstat(util.iterlines(it), width=width,
1134 ui.write(patch.diffstat(util.iterlines(it), width=width,
1133 git=diffopts.git))
1135 git=diffopts.git))
1134 else:
1136 else:
1135 for chunk in it:
1137 for chunk in it:
1136 ui.write(chunk)
1138 ui.write(chunk)
1137
1139
1138 def export(ui, repo, *changesets, **opts):
1140 def export(ui, repo, *changesets, **opts):
1139 """dump the header and diffs for one or more changesets
1141 """dump the header and diffs for one or more changesets
1140
1142
1141 Print the changeset header and diffs for one or more revisions.
1143 Print the changeset header and diffs for one or more revisions.
1142
1144
1143 The information shown in the changeset header is: author, date,
1145 The information shown in the changeset header is: author, date,
1144 branch name (if non-default), changeset hash, parent(s) and commit
1146 branch name (if non-default), changeset hash, parent(s) and commit
1145 comment.
1147 comment.
1146
1148
1147 NOTE: export may generate unexpected diff output for merge
1149 NOTE: export may generate unexpected diff output for merge
1148 changesets, as it will compare the merge changeset against its
1150 changesets, as it will compare the merge changeset against its
1149 first parent only.
1151 first parent only.
1150
1152
1151 Output may be to a file, in which case the name of the file is
1153 Output may be to a file, in which case the name of the file is
1152 given using a format string. The formatting rules are as follows:
1154 given using a format string. The formatting rules are as follows:
1153
1155
1154 :``%%``: literal "%" character
1156 :``%%``: literal "%" character
1155 :``%H``: changeset hash (40 bytes of hexadecimal)
1157 :``%H``: changeset hash (40 bytes of hexadecimal)
1156 :``%N``: number of patches being generated
1158 :``%N``: number of patches being generated
1157 :``%R``: changeset revision number
1159 :``%R``: changeset revision number
1158 :``%b``: basename of the exporting repository
1160 :``%b``: basename of the exporting repository
1159 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1161 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1160 :``%n``: zero-padded sequence number, starting at 1
1162 :``%n``: zero-padded sequence number, starting at 1
1161 :``%r``: zero-padded changeset revision number
1163 :``%r``: zero-padded changeset revision number
1162
1164
1163 Without the -a/--text option, export will avoid generating diffs
1165 Without the -a/--text option, export will avoid generating diffs
1164 of files it detects as binary. With -a, export will generate a
1166 of files it detects as binary. With -a, export will generate a
1165 diff anyway, probably with undesirable results.
1167 diff anyway, probably with undesirable results.
1166
1168
1167 Use the -g/--git option to generate diffs in the git extended diff
1169 Use the -g/--git option to generate diffs in the git extended diff
1168 format. See 'hg help diffs' for more information.
1170 format. See 'hg help diffs' for more information.
1169
1171
1170 With the --switch-parent option, the diff will be against the
1172 With the --switch-parent option, the diff will be against the
1171 second parent. It can be useful to review a merge.
1173 second parent. It can be useful to review a merge.
1172 """
1174 """
1173 changesets += tuple(opts.get('rev', []))
1175 changesets += tuple(opts.get('rev', []))
1174 if not changesets:
1176 if not changesets:
1175 raise util.Abort(_("export requires at least one changeset"))
1177 raise util.Abort(_("export requires at least one changeset"))
1176 revs = cmdutil.revrange(repo, changesets)
1178 revs = cmdutil.revrange(repo, changesets)
1177 if len(revs) > 1:
1179 if len(revs) > 1:
1178 ui.note(_('exporting patches:\n'))
1180 ui.note(_('exporting patches:\n'))
1179 else:
1181 else:
1180 ui.note(_('exporting patch:\n'))
1182 ui.note(_('exporting patch:\n'))
1181 patch.export(repo, revs, template=opts.get('output'),
1183 patch.export(repo, revs, template=opts.get('output'),
1182 switch_parent=opts.get('switch_parent'),
1184 switch_parent=opts.get('switch_parent'),
1183 opts=patch.diffopts(ui, opts))
1185 opts=patch.diffopts(ui, opts))
1184
1186
1185 def forget(ui, repo, *pats, **opts):
1187 def forget(ui, repo, *pats, **opts):
1186 """forget the specified files on the next commit
1188 """forget the specified files on the next commit
1187
1189
1188 Mark the specified files so they will no longer be tracked
1190 Mark the specified files so they will no longer be tracked
1189 after the next commit.
1191 after the next commit.
1190
1192
1191 This only removes files from the current branch, not from the
1193 This only removes files from the current branch, not from the
1192 entire project history, and it does not delete them from the
1194 entire project history, and it does not delete them from the
1193 working directory.
1195 working directory.
1194
1196
1195 To undo a forget before the next commit, see hg add.
1197 To undo a forget before the next commit, see hg add.
1196 """
1198 """
1197
1199
1198 if not pats:
1200 if not pats:
1199 raise util.Abort(_('no files specified'))
1201 raise util.Abort(_('no files specified'))
1200
1202
1201 m = cmdutil.match(repo, pats, opts)
1203 m = cmdutil.match(repo, pats, opts)
1202 s = repo.status(match=m, clean=True)
1204 s = repo.status(match=m, clean=True)
1203 forget = sorted(s[0] + s[1] + s[3] + s[6])
1205 forget = sorted(s[0] + s[1] + s[3] + s[6])
1204
1206
1205 for f in m.files():
1207 for f in m.files():
1206 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1208 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1207 ui.warn(_('not removing %s: file is already untracked\n')
1209 ui.warn(_('not removing %s: file is already untracked\n')
1208 % m.rel(f))
1210 % m.rel(f))
1209
1211
1210 for f in forget:
1212 for f in forget:
1211 if ui.verbose or not m.exact(f):
1213 if ui.verbose or not m.exact(f):
1212 ui.status(_('removing %s\n') % m.rel(f))
1214 ui.status(_('removing %s\n') % m.rel(f))
1213
1215
1214 repo.remove(forget, unlink=False)
1216 repo.remove(forget, unlink=False)
1215
1217
1216 def grep(ui, repo, pattern, *pats, **opts):
1218 def grep(ui, repo, pattern, *pats, **opts):
1217 """search for a pattern in specified files and revisions
1219 """search for a pattern in specified files and revisions
1218
1220
1219 Search revisions of files for a regular expression.
1221 Search revisions of files for a regular expression.
1220
1222
1221 This command behaves differently than Unix grep. It only accepts
1223 This command behaves differently than Unix grep. It only accepts
1222 Python/Perl regexps. It searches repository history, not the
1224 Python/Perl regexps. It searches repository history, not the
1223 working directory. It always prints the revision number in which a
1225 working directory. It always prints the revision number in which a
1224 match appears.
1226 match appears.
1225
1227
1226 By default, grep only prints output for the first revision of a
1228 By default, grep only prints output for the first revision of a
1227 file in which it finds a match. To get it to print every revision
1229 file in which it finds a match. To get it to print every revision
1228 that contains a change in match status ("-" for a match that
1230 that contains a change in match status ("-" for a match that
1229 becomes a non-match, or "+" for a non-match that becomes a match),
1231 becomes a non-match, or "+" for a non-match that becomes a match),
1230 use the --all flag.
1232 use the --all flag.
1231 """
1233 """
1232 reflags = 0
1234 reflags = 0
1233 if opts.get('ignore_case'):
1235 if opts.get('ignore_case'):
1234 reflags |= re.I
1236 reflags |= re.I
1235 try:
1237 try:
1236 regexp = re.compile(pattern, reflags)
1238 regexp = re.compile(pattern, reflags)
1237 except Exception, inst:
1239 except Exception, inst:
1238 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1240 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1239 return None
1241 return None
1240 sep, eol = ':', '\n'
1242 sep, eol = ':', '\n'
1241 if opts.get('print0'):
1243 if opts.get('print0'):
1242 sep = eol = '\0'
1244 sep = eol = '\0'
1243
1245
1244 getfile = util.lrucachefunc(repo.file)
1246 getfile = util.lrucachefunc(repo.file)
1245
1247
1246 def matchlines(body):
1248 def matchlines(body):
1247 begin = 0
1249 begin = 0
1248 linenum = 0
1250 linenum = 0
1249 while True:
1251 while True:
1250 match = regexp.search(body, begin)
1252 match = regexp.search(body, begin)
1251 if not match:
1253 if not match:
1252 break
1254 break
1253 mstart, mend = match.span()
1255 mstart, mend = match.span()
1254 linenum += body.count('\n', begin, mstart) + 1
1256 linenum += body.count('\n', begin, mstart) + 1
1255 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1257 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1256 begin = body.find('\n', mend) + 1 or len(body)
1258 begin = body.find('\n', mend) + 1 or len(body)
1257 lend = begin - 1
1259 lend = begin - 1
1258 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1260 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1259
1261
1260 class linestate(object):
1262 class linestate(object):
1261 def __init__(self, line, linenum, colstart, colend):
1263 def __init__(self, line, linenum, colstart, colend):
1262 self.line = line
1264 self.line = line
1263 self.linenum = linenum
1265 self.linenum = linenum
1264 self.colstart = colstart
1266 self.colstart = colstart
1265 self.colend = colend
1267 self.colend = colend
1266
1268
1267 def __hash__(self):
1269 def __hash__(self):
1268 return hash((self.linenum, self.line))
1270 return hash((self.linenum, self.line))
1269
1271
1270 def __eq__(self, other):
1272 def __eq__(self, other):
1271 return self.line == other.line
1273 return self.line == other.line
1272
1274
1273 matches = {}
1275 matches = {}
1274 copies = {}
1276 copies = {}
1275 def grepbody(fn, rev, body):
1277 def grepbody(fn, rev, body):
1276 matches[rev].setdefault(fn, [])
1278 matches[rev].setdefault(fn, [])
1277 m = matches[rev][fn]
1279 m = matches[rev][fn]
1278 for lnum, cstart, cend, line in matchlines(body):
1280 for lnum, cstart, cend, line in matchlines(body):
1279 s = linestate(line, lnum, cstart, cend)
1281 s = linestate(line, lnum, cstart, cend)
1280 m.append(s)
1282 m.append(s)
1281
1283
1282 def difflinestates(a, b):
1284 def difflinestates(a, b):
1283 sm = difflib.SequenceMatcher(None, a, b)
1285 sm = difflib.SequenceMatcher(None, a, b)
1284 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1286 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1285 if tag == 'insert':
1287 if tag == 'insert':
1286 for i in xrange(blo, bhi):
1288 for i in xrange(blo, bhi):
1287 yield ('+', b[i])
1289 yield ('+', b[i])
1288 elif tag == 'delete':
1290 elif tag == 'delete':
1289 for i in xrange(alo, ahi):
1291 for i in xrange(alo, ahi):
1290 yield ('-', a[i])
1292 yield ('-', a[i])
1291 elif tag == 'replace':
1293 elif tag == 'replace':
1292 for i in xrange(alo, ahi):
1294 for i in xrange(alo, ahi):
1293 yield ('-', a[i])
1295 yield ('-', a[i])
1294 for i in xrange(blo, bhi):
1296 for i in xrange(blo, bhi):
1295 yield ('+', b[i])
1297 yield ('+', b[i])
1296
1298
1297 def display(fn, ctx, pstates, states):
1299 def display(fn, ctx, pstates, states):
1298 rev = ctx.rev()
1300 rev = ctx.rev()
1299 datefunc = ui.quiet and util.shortdate or util.datestr
1301 datefunc = ui.quiet and util.shortdate or util.datestr
1300 found = False
1302 found = False
1301 filerevmatches = {}
1303 filerevmatches = {}
1302 if opts.get('all'):
1304 if opts.get('all'):
1303 iter = difflinestates(pstates, states)
1305 iter = difflinestates(pstates, states)
1304 else:
1306 else:
1305 iter = [('', l) for l in states]
1307 iter = [('', l) for l in states]
1306 for change, l in iter:
1308 for change, l in iter:
1307 cols = [fn, str(rev)]
1309 cols = [fn, str(rev)]
1308 if opts.get('line_number'):
1310 if opts.get('line_number'):
1309 cols.append(str(l.linenum))
1311 cols.append(str(l.linenum))
1310 if opts.get('all'):
1312 if opts.get('all'):
1311 cols.append(change)
1313 cols.append(change)
1312 if opts.get('user'):
1314 if opts.get('user'):
1313 cols.append(ui.shortuser(ctx.user()))
1315 cols.append(ui.shortuser(ctx.user()))
1314 if opts.get('date'):
1316 if opts.get('date'):
1315 cols.append(datefunc(ctx.date()))
1317 cols.append(datefunc(ctx.date()))
1316 if opts.get('files_with_matches'):
1318 if opts.get('files_with_matches'):
1317 c = (fn, rev)
1319 c = (fn, rev)
1318 if c in filerevmatches:
1320 if c in filerevmatches:
1319 continue
1321 continue
1320 filerevmatches[c] = 1
1322 filerevmatches[c] = 1
1321 else:
1323 else:
1322 cols.append(l.line)
1324 cols.append(l.line)
1323 ui.write(sep.join(cols), eol)
1325 ui.write(sep.join(cols), eol)
1324 found = True
1326 found = True
1325 return found
1327 return found
1326
1328
1327 skip = {}
1329 skip = {}
1328 revfiles = {}
1330 revfiles = {}
1329 matchfn = cmdutil.match(repo, pats, opts)
1331 matchfn = cmdutil.match(repo, pats, opts)
1330 found = False
1332 found = False
1331 follow = opts.get('follow')
1333 follow = opts.get('follow')
1332
1334
1333 def prep(ctx, fns):
1335 def prep(ctx, fns):
1334 rev = ctx.rev()
1336 rev = ctx.rev()
1335 pctx = ctx.parents()[0]
1337 pctx = ctx.parents()[0]
1336 parent = pctx.rev()
1338 parent = pctx.rev()
1337 matches.setdefault(rev, {})
1339 matches.setdefault(rev, {})
1338 matches.setdefault(parent, {})
1340 matches.setdefault(parent, {})
1339 files = revfiles.setdefault(rev, [])
1341 files = revfiles.setdefault(rev, [])
1340 for fn in fns:
1342 for fn in fns:
1341 flog = getfile(fn)
1343 flog = getfile(fn)
1342 try:
1344 try:
1343 fnode = ctx.filenode(fn)
1345 fnode = ctx.filenode(fn)
1344 except error.LookupError:
1346 except error.LookupError:
1345 continue
1347 continue
1346
1348
1347 copied = flog.renamed(fnode)
1349 copied = flog.renamed(fnode)
1348 copy = follow and copied and copied[0]
1350 copy = follow and copied and copied[0]
1349 if copy:
1351 if copy:
1350 copies.setdefault(rev, {})[fn] = copy
1352 copies.setdefault(rev, {})[fn] = copy
1351 if fn in skip:
1353 if fn in skip:
1352 if copy:
1354 if copy:
1353 skip[copy] = True
1355 skip[copy] = True
1354 continue
1356 continue
1355 files.append(fn)
1357 files.append(fn)
1356
1358
1357 if fn not in matches[rev]:
1359 if fn not in matches[rev]:
1358 grepbody(fn, rev, flog.read(fnode))
1360 grepbody(fn, rev, flog.read(fnode))
1359
1361
1360 pfn = copy or fn
1362 pfn = copy or fn
1361 if pfn not in matches[parent]:
1363 if pfn not in matches[parent]:
1362 try:
1364 try:
1363 fnode = pctx.filenode(pfn)
1365 fnode = pctx.filenode(pfn)
1364 grepbody(pfn, parent, flog.read(fnode))
1366 grepbody(pfn, parent, flog.read(fnode))
1365 except error.LookupError:
1367 except error.LookupError:
1366 pass
1368 pass
1367
1369
1368 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1370 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1369 rev = ctx.rev()
1371 rev = ctx.rev()
1370 parent = ctx.parents()[0].rev()
1372 parent = ctx.parents()[0].rev()
1371 for fn in sorted(revfiles.get(rev, [])):
1373 for fn in sorted(revfiles.get(rev, [])):
1372 states = matches[rev][fn]
1374 states = matches[rev][fn]
1373 copy = copies.get(rev, {}).get(fn)
1375 copy = copies.get(rev, {}).get(fn)
1374 if fn in skip:
1376 if fn in skip:
1375 if copy:
1377 if copy:
1376 skip[copy] = True
1378 skip[copy] = True
1377 continue
1379 continue
1378 pstates = matches.get(parent, {}).get(copy or fn, [])
1380 pstates = matches.get(parent, {}).get(copy or fn, [])
1379 if pstates or states:
1381 if pstates or states:
1380 r = display(fn, ctx, pstates, states)
1382 r = display(fn, ctx, pstates, states)
1381 found = found or r
1383 found = found or r
1382 if r and not opts.get('all'):
1384 if r and not opts.get('all'):
1383 skip[fn] = True
1385 skip[fn] = True
1384 if copy:
1386 if copy:
1385 skip[copy] = True
1387 skip[copy] = True
1386 del matches[rev]
1388 del matches[rev]
1387 del revfiles[rev]
1389 del revfiles[rev]
1388
1390
1389 def heads(ui, repo, *branchrevs, **opts):
1391 def heads(ui, repo, *branchrevs, **opts):
1390 """show current repository heads or show branch heads
1392 """show current repository heads or show branch heads
1391
1393
1392 With no arguments, show all repository branch heads.
1394 With no arguments, show all repository branch heads.
1393
1395
1394 Repository "heads" are changesets with no child changesets. They are
1396 Repository "heads" are changesets with no child changesets. They are
1395 where development generally takes place and are the usual targets
1397 where development generally takes place and are the usual targets
1396 for update and merge operations. Branch heads are changesets that have
1398 for update and merge operations. Branch heads are changesets that have
1397 no child changeset on the same branch.
1399 no child changeset on the same branch.
1398
1400
1399 If one or more REVs are given, only branch heads on the branches
1401 If one or more REVs are given, only branch heads on the branches
1400 associated with the specified changesets are shown.
1402 associated with the specified changesets are shown.
1401
1403
1402 If -c/--closed is specified, also show branch heads marked closed
1404 If -c/--closed is specified, also show branch heads marked closed
1403 (see hg commit --close-branch).
1405 (see hg commit --close-branch).
1404
1406
1405 If STARTREV is specified, only those heads that are descendants of
1407 If STARTREV is specified, only those heads that are descendants of
1406 STARTREV will be displayed.
1408 STARTREV will be displayed.
1407
1409
1408 If -t/--topo is specified, named branch mechanics will be ignored and only
1410 If -t/--topo is specified, named branch mechanics will be ignored and only
1409 changesets without children will be shown.
1411 changesets without children will be shown.
1410 """
1412 """
1411
1413
1412 if opts.get('rev'):
1414 if opts.get('rev'):
1413 start = repo.lookup(opts['rev'])
1415 start = repo.lookup(opts['rev'])
1414 else:
1416 else:
1415 start = None
1417 start = None
1416
1418
1417 if opts.get('topo'):
1419 if opts.get('topo'):
1418 heads = [repo[h] for h in repo.heads(start)]
1420 heads = [repo[h] for h in repo.heads(start)]
1419 else:
1421 else:
1420 heads = []
1422 heads = []
1421 for b, ls in repo.branchmap().iteritems():
1423 for b, ls in repo.branchmap().iteritems():
1422 if start is None:
1424 if start is None:
1423 heads += [repo[h] for h in ls]
1425 heads += [repo[h] for h in ls]
1424 continue
1426 continue
1425 startrev = repo.changelog.rev(start)
1427 startrev = repo.changelog.rev(start)
1426 descendants = set(repo.changelog.descendants(startrev))
1428 descendants = set(repo.changelog.descendants(startrev))
1427 descendants.add(startrev)
1429 descendants.add(startrev)
1428 rev = repo.changelog.rev
1430 rev = repo.changelog.rev
1429 heads += [repo[h] for h in ls if rev(h) in descendants]
1431 heads += [repo[h] for h in ls if rev(h) in descendants]
1430
1432
1431 if branchrevs:
1433 if branchrevs:
1432 decode, encode = encoding.fromlocal, encoding.tolocal
1434 decode, encode = encoding.fromlocal, encoding.tolocal
1433 branches = set(repo[decode(br)].branch() for br in branchrevs)
1435 branches = set(repo[decode(br)].branch() for br in branchrevs)
1434 heads = [h for h in heads if h.branch() in branches]
1436 heads = [h for h in heads if h.branch() in branches]
1435
1437
1436 if not opts.get('closed'):
1438 if not opts.get('closed'):
1437 heads = [h for h in heads if not h.extra().get('close')]
1439 heads = [h for h in heads if not h.extra().get('close')]
1438
1440
1439 if opts.get('active') and branchrevs:
1441 if opts.get('active') and branchrevs:
1440 dagheads = repo.heads(start)
1442 dagheads = repo.heads(start)
1441 heads = [h for h in heads if h.node() in dagheads]
1443 heads = [h for h in heads if h.node() in dagheads]
1442
1444
1443 if branchrevs:
1445 if branchrevs:
1444 haveheads = set(h.branch() for h in heads)
1446 haveheads = set(h.branch() for h in heads)
1445 if branches - haveheads:
1447 if branches - haveheads:
1446 headless = ', '.join(encode(b) for b in branches - haveheads)
1448 headless = ', '.join(encode(b) for b in branches - haveheads)
1447 msg = _('no open branch heads found on branches %s')
1449 msg = _('no open branch heads found on branches %s')
1448 if opts.get('rev'):
1450 if opts.get('rev'):
1449 msg += _(' (started at %s)' % opts['rev'])
1451 msg += _(' (started at %s)' % opts['rev'])
1450 ui.warn((msg + '\n') % headless)
1452 ui.warn((msg + '\n') % headless)
1451
1453
1452 if not heads:
1454 if not heads:
1453 return 1
1455 return 1
1454
1456
1455 heads = sorted(heads, key=lambda x: -x.rev())
1457 heads = sorted(heads, key=lambda x: -x.rev())
1456 displayer = cmdutil.show_changeset(ui, repo, opts)
1458 displayer = cmdutil.show_changeset(ui, repo, opts)
1457 for ctx in heads:
1459 for ctx in heads:
1458 displayer.show(ctx)
1460 displayer.show(ctx)
1459 displayer.close()
1461 displayer.close()
1460
1462
1461 def help_(ui, name=None, with_version=False, unknowncmd=False):
1463 def help_(ui, name=None, with_version=False, unknowncmd=False):
1462 """show help for a given topic or a help overview
1464 """show help for a given topic or a help overview
1463
1465
1464 With no arguments, print a list of commands with short help messages.
1466 With no arguments, print a list of commands with short help messages.
1465
1467
1466 Given a topic, extension, or command name, print help for that
1468 Given a topic, extension, or command name, print help for that
1467 topic."""
1469 topic."""
1468 option_lists = []
1470 option_lists = []
1469 textwidth = util.termwidth() - 2
1471 textwidth = util.termwidth() - 2
1470
1472
1471 def addglobalopts(aliases):
1473 def addglobalopts(aliases):
1472 if ui.verbose:
1474 if ui.verbose:
1473 option_lists.append((_("global options:"), globalopts))
1475 option_lists.append((_("global options:"), globalopts))
1474 if name == 'shortlist':
1476 if name == 'shortlist':
1475 option_lists.append((_('use "hg help" for the full list '
1477 option_lists.append((_('use "hg help" for the full list '
1476 'of commands'), ()))
1478 'of commands'), ()))
1477 else:
1479 else:
1478 if name == 'shortlist':
1480 if name == 'shortlist':
1479 msg = _('use "hg help" for the full list of commands '
1481 msg = _('use "hg help" for the full list of commands '
1480 'or "hg -v" for details')
1482 'or "hg -v" for details')
1481 elif aliases:
1483 elif aliases:
1482 msg = _('use "hg -v help%s" to show aliases and '
1484 msg = _('use "hg -v help%s" to show aliases and '
1483 'global options') % (name and " " + name or "")
1485 'global options') % (name and " " + name or "")
1484 else:
1486 else:
1485 msg = _('use "hg -v help %s" to show global options') % name
1487 msg = _('use "hg -v help %s" to show global options') % name
1486 option_lists.append((msg, ()))
1488 option_lists.append((msg, ()))
1487
1489
1488 def helpcmd(name):
1490 def helpcmd(name):
1489 if with_version:
1491 if with_version:
1490 version_(ui)
1492 version_(ui)
1491 ui.write('\n')
1493 ui.write('\n')
1492
1494
1493 try:
1495 try:
1494 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1496 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1495 except error.AmbiguousCommand, inst:
1497 except error.AmbiguousCommand, inst:
1496 # py3k fix: except vars can't be used outside the scope of the
1498 # py3k fix: except vars can't be used outside the scope of the
1497 # except block, nor can be used inside a lambda. python issue4617
1499 # except block, nor can be used inside a lambda. python issue4617
1498 prefix = inst.args[0]
1500 prefix = inst.args[0]
1499 select = lambda c: c.lstrip('^').startswith(prefix)
1501 select = lambda c: c.lstrip('^').startswith(prefix)
1500 helplist(_('list of commands:\n\n'), select)
1502 helplist(_('list of commands:\n\n'), select)
1501 return
1503 return
1502
1504
1503 # check if it's an invalid alias and display its error if it is
1505 # check if it's an invalid alias and display its error if it is
1504 if getattr(entry[0], 'badalias', False):
1506 if getattr(entry[0], 'badalias', False):
1505 if not unknowncmd:
1507 if not unknowncmd:
1506 entry[0](ui)
1508 entry[0](ui)
1507 return
1509 return
1508
1510
1509 # synopsis
1511 # synopsis
1510 if len(entry) > 2:
1512 if len(entry) > 2:
1511 if entry[2].startswith('hg'):
1513 if entry[2].startswith('hg'):
1512 ui.write("%s\n" % entry[2])
1514 ui.write("%s\n" % entry[2])
1513 else:
1515 else:
1514 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1516 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1515 else:
1517 else:
1516 ui.write('hg %s\n' % aliases[0])
1518 ui.write('hg %s\n' % aliases[0])
1517
1519
1518 # aliases
1520 # aliases
1519 if not ui.quiet and len(aliases) > 1:
1521 if not ui.quiet and len(aliases) > 1:
1520 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1522 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1521
1523
1522 # description
1524 # description
1523 doc = gettext(entry[0].__doc__)
1525 doc = gettext(entry[0].__doc__)
1524 if not doc:
1526 if not doc:
1525 doc = _("(no help text available)")
1527 doc = _("(no help text available)")
1526 if ui.quiet:
1528 if ui.quiet:
1527 doc = doc.splitlines()[0]
1529 doc = doc.splitlines()[0]
1528 ui.write("\n%s\n" % minirst.format(doc, textwidth))
1530 ui.write("\n%s\n" % minirst.format(doc, textwidth))
1529
1531
1530 if not ui.quiet:
1532 if not ui.quiet:
1531 # options
1533 # options
1532 if entry[1]:
1534 if entry[1]:
1533 option_lists.append((_("options:\n"), entry[1]))
1535 option_lists.append((_("options:\n"), entry[1]))
1534
1536
1535 addglobalopts(False)
1537 addglobalopts(False)
1536
1538
1537 def helplist(header, select=None):
1539 def helplist(header, select=None):
1538 h = {}
1540 h = {}
1539 cmds = {}
1541 cmds = {}
1540 for c, e in table.iteritems():
1542 for c, e in table.iteritems():
1541 f = c.split("|", 1)[0]
1543 f = c.split("|", 1)[0]
1542 if select and not select(f):
1544 if select and not select(f):
1543 continue
1545 continue
1544 if (not select and name != 'shortlist' and
1546 if (not select and name != 'shortlist' and
1545 e[0].__module__ != __name__):
1547 e[0].__module__ != __name__):
1546 continue
1548 continue
1547 if name == "shortlist" and not f.startswith("^"):
1549 if name == "shortlist" and not f.startswith("^"):
1548 continue
1550 continue
1549 f = f.lstrip("^")
1551 f = f.lstrip("^")
1550 if not ui.debugflag and f.startswith("debug"):
1552 if not ui.debugflag and f.startswith("debug"):
1551 continue
1553 continue
1552 doc = e[0].__doc__
1554 doc = e[0].__doc__
1553 if doc and 'DEPRECATED' in doc and not ui.verbose:
1555 if doc and 'DEPRECATED' in doc and not ui.verbose:
1554 continue
1556 continue
1555 doc = gettext(doc)
1557 doc = gettext(doc)
1556 if not doc:
1558 if not doc:
1557 doc = _("(no help text available)")
1559 doc = _("(no help text available)")
1558 h[f] = doc.splitlines()[0].rstrip()
1560 h[f] = doc.splitlines()[0].rstrip()
1559 cmds[f] = c.lstrip("^")
1561 cmds[f] = c.lstrip("^")
1560
1562
1561 if not h:
1563 if not h:
1562 ui.status(_('no commands defined\n'))
1564 ui.status(_('no commands defined\n'))
1563 return
1565 return
1564
1566
1565 ui.status(header)
1567 ui.status(header)
1566 fns = sorted(h)
1568 fns = sorted(h)
1567 m = max(map(len, fns))
1569 m = max(map(len, fns))
1568 for f in fns:
1570 for f in fns:
1569 if ui.verbose:
1571 if ui.verbose:
1570 commands = cmds[f].replace("|",", ")
1572 commands = cmds[f].replace("|",", ")
1571 ui.write(" %s:\n %s\n"%(commands, h[f]))
1573 ui.write(" %s:\n %s\n"%(commands, h[f]))
1572 else:
1574 else:
1573 ui.write(' %-*s %s\n' % (m, f, util.wrap(h[f], m + 4)))
1575 ui.write(' %-*s %s\n' % (m, f, util.wrap(h[f], m + 4)))
1574
1576
1575 if not ui.quiet:
1577 if not ui.quiet:
1576 addglobalopts(True)
1578 addglobalopts(True)
1577
1579
1578 def helptopic(name):
1580 def helptopic(name):
1579 for names, header, doc in help.helptable:
1581 for names, header, doc in help.helptable:
1580 if name in names:
1582 if name in names:
1581 break
1583 break
1582 else:
1584 else:
1583 raise error.UnknownCommand(name)
1585 raise error.UnknownCommand(name)
1584
1586
1585 # description
1587 # description
1586 if not doc:
1588 if not doc:
1587 doc = _("(no help text available)")
1589 doc = _("(no help text available)")
1588 if hasattr(doc, '__call__'):
1590 if hasattr(doc, '__call__'):
1589 doc = doc()
1591 doc = doc()
1590
1592
1591 ui.write("%s\n\n" % header)
1593 ui.write("%s\n\n" % header)
1592 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1594 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1593
1595
1594 def helpext(name):
1596 def helpext(name):
1595 try:
1597 try:
1596 mod = extensions.find(name)
1598 mod = extensions.find(name)
1597 doc = gettext(mod.__doc__) or _('no help text available')
1599 doc = gettext(mod.__doc__) or _('no help text available')
1598 except KeyError:
1600 except KeyError:
1599 mod = None
1601 mod = None
1600 doc = extensions.disabledext(name)
1602 doc = extensions.disabledext(name)
1601 if not doc:
1603 if not doc:
1602 raise error.UnknownCommand(name)
1604 raise error.UnknownCommand(name)
1603
1605
1604 if '\n' not in doc:
1606 if '\n' not in doc:
1605 head, tail = doc, ""
1607 head, tail = doc, ""
1606 else:
1608 else:
1607 head, tail = doc.split('\n', 1)
1609 head, tail = doc.split('\n', 1)
1608 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1610 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1609 if tail:
1611 if tail:
1610 ui.write(minirst.format(tail, textwidth))
1612 ui.write(minirst.format(tail, textwidth))
1611 ui.status('\n\n')
1613 ui.status('\n\n')
1612
1614
1613 if mod:
1615 if mod:
1614 try:
1616 try:
1615 ct = mod.cmdtable
1617 ct = mod.cmdtable
1616 except AttributeError:
1618 except AttributeError:
1617 ct = {}
1619 ct = {}
1618 modcmds = set([c.split('|', 1)[0] for c in ct])
1620 modcmds = set([c.split('|', 1)[0] for c in ct])
1619 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1621 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1620 else:
1622 else:
1621 ui.write(_('use "hg help extensions" for information on enabling '
1623 ui.write(_('use "hg help extensions" for information on enabling '
1622 'extensions\n'))
1624 'extensions\n'))
1623
1625
1624 def helpextcmd(name):
1626 def helpextcmd(name):
1625 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1627 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1626 doc = gettext(mod.__doc__).splitlines()[0]
1628 doc = gettext(mod.__doc__).splitlines()[0]
1627
1629
1628 msg = help.listexts(_("'%s' is provided by the following "
1630 msg = help.listexts(_("'%s' is provided by the following "
1629 "extension:") % cmd, {ext: doc}, len(ext),
1631 "extension:") % cmd, {ext: doc}, len(ext),
1630 indent=4)
1632 indent=4)
1631 ui.write(minirst.format(msg, textwidth))
1633 ui.write(minirst.format(msg, textwidth))
1632 ui.write('\n\n')
1634 ui.write('\n\n')
1633 ui.write(_('use "hg help extensions" for information on enabling '
1635 ui.write(_('use "hg help extensions" for information on enabling '
1634 'extensions\n'))
1636 'extensions\n'))
1635
1637
1636 if name and name != 'shortlist':
1638 if name and name != 'shortlist':
1637 i = None
1639 i = None
1638 if unknowncmd:
1640 if unknowncmd:
1639 queries = (helpextcmd,)
1641 queries = (helpextcmd,)
1640 else:
1642 else:
1641 queries = (helptopic, helpcmd, helpext, helpextcmd)
1643 queries = (helptopic, helpcmd, helpext, helpextcmd)
1642 for f in queries:
1644 for f in queries:
1643 try:
1645 try:
1644 f(name)
1646 f(name)
1645 i = None
1647 i = None
1646 break
1648 break
1647 except error.UnknownCommand, inst:
1649 except error.UnknownCommand, inst:
1648 i = inst
1650 i = inst
1649 if i:
1651 if i:
1650 raise i
1652 raise i
1651
1653
1652 else:
1654 else:
1653 # program name
1655 # program name
1654 if ui.verbose or with_version:
1656 if ui.verbose or with_version:
1655 version_(ui)
1657 version_(ui)
1656 else:
1658 else:
1657 ui.status(_("Mercurial Distributed SCM\n"))
1659 ui.status(_("Mercurial Distributed SCM\n"))
1658 ui.status('\n')
1660 ui.status('\n')
1659
1661
1660 # list of commands
1662 # list of commands
1661 if name == "shortlist":
1663 if name == "shortlist":
1662 header = _('basic commands:\n\n')
1664 header = _('basic commands:\n\n')
1663 else:
1665 else:
1664 header = _('list of commands:\n\n')
1666 header = _('list of commands:\n\n')
1665
1667
1666 helplist(header)
1668 helplist(header)
1667 if name != 'shortlist':
1669 if name != 'shortlist':
1668 exts, maxlength = extensions.enabled()
1670 exts, maxlength = extensions.enabled()
1669 text = help.listexts(_('enabled extensions:'), exts, maxlength)
1671 text = help.listexts(_('enabled extensions:'), exts, maxlength)
1670 if text:
1672 if text:
1671 ui.write("\n%s\n" % minirst.format(text, textwidth))
1673 ui.write("\n%s\n" % minirst.format(text, textwidth))
1672
1674
1673 # list all option lists
1675 # list all option lists
1674 opt_output = []
1676 opt_output = []
1675 for title, options in option_lists:
1677 for title, options in option_lists:
1676 opt_output.append(("\n%s" % title, None))
1678 opt_output.append(("\n%s" % title, None))
1677 for shortopt, longopt, default, desc in options:
1679 for shortopt, longopt, default, desc in options:
1678 if _("DEPRECATED") in desc and not ui.verbose:
1680 if _("DEPRECATED") in desc and not ui.verbose:
1679 continue
1681 continue
1680 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1682 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1681 longopt and " --%s" % longopt),
1683 longopt and " --%s" % longopt),
1682 "%s%s" % (desc,
1684 "%s%s" % (desc,
1683 default
1685 default
1684 and _(" (default: %s)") % default
1686 and _(" (default: %s)") % default
1685 or "")))
1687 or "")))
1686
1688
1687 if not name:
1689 if not name:
1688 ui.write(_("\nadditional help topics:\n\n"))
1690 ui.write(_("\nadditional help topics:\n\n"))
1689 topics = []
1691 topics = []
1690 for names, header, doc in help.helptable:
1692 for names, header, doc in help.helptable:
1691 topics.append((sorted(names, key=len, reverse=True)[0], header))
1693 topics.append((sorted(names, key=len, reverse=True)[0], header))
1692 topics_len = max([len(s[0]) for s in topics])
1694 topics_len = max([len(s[0]) for s in topics])
1693 for t, desc in topics:
1695 for t, desc in topics:
1694 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1696 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1695
1697
1696 if opt_output:
1698 if opt_output:
1697 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1699 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1698 for first, second in opt_output:
1700 for first, second in opt_output:
1699 if second:
1701 if second:
1700 second = util.wrap(second, opts_len + 3)
1702 second = util.wrap(second, opts_len + 3)
1701 ui.write(" %-*s %s\n" % (opts_len, first, second))
1703 ui.write(" %-*s %s\n" % (opts_len, first, second))
1702 else:
1704 else:
1703 ui.write("%s\n" % first)
1705 ui.write("%s\n" % first)
1704
1706
1705 def identify(ui, repo, source=None,
1707 def identify(ui, repo, source=None,
1706 rev=None, num=None, id=None, branch=None, tags=None):
1708 rev=None, num=None, id=None, branch=None, tags=None):
1707 """identify the working copy or specified revision
1709 """identify the working copy or specified revision
1708
1710
1709 With no revision, print a summary of the current state of the
1711 With no revision, print a summary of the current state of the
1710 repository.
1712 repository.
1711
1713
1712 Specifying a path to a repository root or Mercurial bundle will
1714 Specifying a path to a repository root or Mercurial bundle will
1713 cause lookup to operate on that repository/bundle.
1715 cause lookup to operate on that repository/bundle.
1714
1716
1715 This summary identifies the repository state using one or two
1717 This summary identifies the repository state using one or two
1716 parent hash identifiers, followed by a "+" if there are
1718 parent hash identifiers, followed by a "+" if there are
1717 uncommitted changes in the working directory, a list of tags for
1719 uncommitted changes in the working directory, a list of tags for
1718 this revision and a branch name for non-default branches.
1720 this revision and a branch name for non-default branches.
1719 """
1721 """
1720
1722
1721 if not repo and not source:
1723 if not repo and not source:
1722 raise util.Abort(_("There is no Mercurial repository here "
1724 raise util.Abort(_("There is no Mercurial repository here "
1723 "(.hg not found)"))
1725 "(.hg not found)"))
1724
1726
1725 hexfunc = ui.debugflag and hex or short
1727 hexfunc = ui.debugflag and hex or short
1726 default = not (num or id or branch or tags)
1728 default = not (num or id or branch or tags)
1727 output = []
1729 output = []
1728
1730
1729 revs = []
1731 revs = []
1730 if source:
1732 if source:
1731 source, branches = hg.parseurl(ui.expandpath(source))
1733 source, branches = hg.parseurl(ui.expandpath(source))
1732 repo = hg.repository(ui, source)
1734 repo = hg.repository(ui, source)
1733 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
1735 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
1734
1736
1735 if not repo.local():
1737 if not repo.local():
1736 if not rev and revs:
1738 if not rev and revs:
1737 rev = revs[0]
1739 rev = revs[0]
1738 if not rev:
1740 if not rev:
1739 rev = "tip"
1741 rev = "tip"
1740 if num or branch or tags:
1742 if num or branch or tags:
1741 raise util.Abort(
1743 raise util.Abort(
1742 "can't query remote revision number, branch, or tags")
1744 "can't query remote revision number, branch, or tags")
1743 output = [hexfunc(repo.lookup(rev))]
1745 output = [hexfunc(repo.lookup(rev))]
1744 elif not rev:
1746 elif not rev:
1745 ctx = repo[None]
1747 ctx = repo[None]
1746 parents = ctx.parents()
1748 parents = ctx.parents()
1747 changed = False
1749 changed = False
1748 if default or id or num:
1750 if default or id or num:
1749 changed = ctx.files() + ctx.deleted()
1751 changed = ctx.files() + ctx.deleted()
1750 if default or id:
1752 if default or id:
1751 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1753 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1752 (changed) and "+" or "")]
1754 (changed) and "+" or "")]
1753 if num:
1755 if num:
1754 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1756 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1755 (changed) and "+" or ""))
1757 (changed) and "+" or ""))
1756 else:
1758 else:
1757 ctx = repo[rev]
1759 ctx = repo[rev]
1758 if default or id:
1760 if default or id:
1759 output = [hexfunc(ctx.node())]
1761 output = [hexfunc(ctx.node())]
1760 if num:
1762 if num:
1761 output.append(str(ctx.rev()))
1763 output.append(str(ctx.rev()))
1762
1764
1763 if repo.local() and default and not ui.quiet:
1765 if repo.local() and default and not ui.quiet:
1764 b = encoding.tolocal(ctx.branch())
1766 b = encoding.tolocal(ctx.branch())
1765 if b != 'default':
1767 if b != 'default':
1766 output.append("(%s)" % b)
1768 output.append("(%s)" % b)
1767
1769
1768 # multiple tags for a single parent separated by '/'
1770 # multiple tags for a single parent separated by '/'
1769 t = "/".join(ctx.tags())
1771 t = "/".join(ctx.tags())
1770 if t:
1772 if t:
1771 output.append(t)
1773 output.append(t)
1772
1774
1773 if branch:
1775 if branch:
1774 output.append(encoding.tolocal(ctx.branch()))
1776 output.append(encoding.tolocal(ctx.branch()))
1775
1777
1776 if tags:
1778 if tags:
1777 output.extend(ctx.tags())
1779 output.extend(ctx.tags())
1778
1780
1779 ui.write("%s\n" % ' '.join(output))
1781 ui.write("%s\n" % ' '.join(output))
1780
1782
1781 def import_(ui, repo, patch1, *patches, **opts):
1783 def import_(ui, repo, patch1, *patches, **opts):
1782 """import an ordered set of patches
1784 """import an ordered set of patches
1783
1785
1784 Import a list of patches and commit them individually (unless
1786 Import a list of patches and commit them individually (unless
1785 --no-commit is specified).
1787 --no-commit is specified).
1786
1788
1787 If there are outstanding changes in the working directory, import
1789 If there are outstanding changes in the working directory, import
1788 will abort unless given the -f/--force flag.
1790 will abort unless given the -f/--force flag.
1789
1791
1790 You can import a patch straight from a mail message. Even patches
1792 You can import a patch straight from a mail message. Even patches
1791 as attachments work (to use the body part, it must have type
1793 as attachments work (to use the body part, it must have type
1792 text/plain or text/x-patch). From and Subject headers of email
1794 text/plain or text/x-patch). From and Subject headers of email
1793 message are used as default committer and commit message. All
1795 message are used as default committer and commit message. All
1794 text/plain body parts before first diff are added to commit
1796 text/plain body parts before first diff are added to commit
1795 message.
1797 message.
1796
1798
1797 If the imported patch was generated by hg export, user and
1799 If the imported patch was generated by hg export, user and
1798 description from patch override values from message headers and
1800 description from patch override values from message headers and
1799 body. Values given on command line with -m/--message and -u/--user
1801 body. Values given on command line with -m/--message and -u/--user
1800 override these.
1802 override these.
1801
1803
1802 If --exact is specified, import will set the working directory to
1804 If --exact is specified, import will set the working directory to
1803 the parent of each patch before applying it, and will abort if the
1805 the parent of each patch before applying it, and will abort if the
1804 resulting changeset has a different ID than the one recorded in
1806 resulting changeset has a different ID than the one recorded in
1805 the patch. This may happen due to character set problems or other
1807 the patch. This may happen due to character set problems or other
1806 deficiencies in the text patch format.
1808 deficiencies in the text patch format.
1807
1809
1808 With -s/--similarity, hg will attempt to discover renames and
1810 With -s/--similarity, hg will attempt to discover renames and
1809 copies in the patch in the same way as 'addremove'.
1811 copies in the patch in the same way as 'addremove'.
1810
1812
1811 To read a patch from standard input, use "-" as the patch name. If
1813 To read a patch from standard input, use "-" as the patch name. If
1812 a URL is specified, the patch will be downloaded from it.
1814 a URL is specified, the patch will be downloaded from it.
1813 See 'hg help dates' for a list of formats valid for -d/--date.
1815 See 'hg help dates' for a list of formats valid for -d/--date.
1814 """
1816 """
1815 patches = (patch1,) + patches
1817 patches = (patch1,) + patches
1816
1818
1817 date = opts.get('date')
1819 date = opts.get('date')
1818 if date:
1820 if date:
1819 opts['date'] = util.parsedate(date)
1821 opts['date'] = util.parsedate(date)
1820
1822
1821 try:
1823 try:
1822 sim = float(opts.get('similarity') or 0)
1824 sim = float(opts.get('similarity') or 0)
1823 except ValueError:
1825 except ValueError:
1824 raise util.Abort(_('similarity must be a number'))
1826 raise util.Abort(_('similarity must be a number'))
1825 if sim < 0 or sim > 100:
1827 if sim < 0 or sim > 100:
1826 raise util.Abort(_('similarity must be between 0 and 100'))
1828 raise util.Abort(_('similarity must be between 0 and 100'))
1827
1829
1828 if opts.get('exact') or not opts.get('force'):
1830 if opts.get('exact') or not opts.get('force'):
1829 cmdutil.bail_if_changed(repo)
1831 cmdutil.bail_if_changed(repo)
1830
1832
1831 d = opts["base"]
1833 d = opts["base"]
1832 strip = opts["strip"]
1834 strip = opts["strip"]
1833 wlock = lock = None
1835 wlock = lock = None
1834 try:
1836 try:
1835 wlock = repo.wlock()
1837 wlock = repo.wlock()
1836 lock = repo.lock()
1838 lock = repo.lock()
1837 for p in patches:
1839 for p in patches:
1838 pf = os.path.join(d, p)
1840 pf = os.path.join(d, p)
1839
1841
1840 if pf == '-':
1842 if pf == '-':
1841 ui.status(_("applying patch from stdin\n"))
1843 ui.status(_("applying patch from stdin\n"))
1842 pf = sys.stdin
1844 pf = sys.stdin
1843 else:
1845 else:
1844 ui.status(_("applying %s\n") % p)
1846 ui.status(_("applying %s\n") % p)
1845 pf = url.open(ui, pf)
1847 pf = url.open(ui, pf)
1846 data = patch.extract(ui, pf)
1848 data = patch.extract(ui, pf)
1847 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1849 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1848
1850
1849 if tmpname is None:
1851 if tmpname is None:
1850 raise util.Abort(_('no diffs found'))
1852 raise util.Abort(_('no diffs found'))
1851
1853
1852 try:
1854 try:
1853 cmdline_message = cmdutil.logmessage(opts)
1855 cmdline_message = cmdutil.logmessage(opts)
1854 if cmdline_message:
1856 if cmdline_message:
1855 # pickup the cmdline msg
1857 # pickup the cmdline msg
1856 message = cmdline_message
1858 message = cmdline_message
1857 elif message:
1859 elif message:
1858 # pickup the patch msg
1860 # pickup the patch msg
1859 message = message.strip()
1861 message = message.strip()
1860 else:
1862 else:
1861 # launch the editor
1863 # launch the editor
1862 message = None
1864 message = None
1863 ui.debug('message:\n%s\n' % message)
1865 ui.debug('message:\n%s\n' % message)
1864
1866
1865 wp = repo.parents()
1867 wp = repo.parents()
1866 if opts.get('exact'):
1868 if opts.get('exact'):
1867 if not nodeid or not p1:
1869 if not nodeid or not p1:
1868 raise util.Abort(_('not a Mercurial patch'))
1870 raise util.Abort(_('not a Mercurial patch'))
1869 p1 = repo.lookup(p1)
1871 p1 = repo.lookup(p1)
1870 p2 = repo.lookup(p2 or hex(nullid))
1872 p2 = repo.lookup(p2 or hex(nullid))
1871
1873
1872 if p1 != wp[0].node():
1874 if p1 != wp[0].node():
1873 hg.clean(repo, p1)
1875 hg.clean(repo, p1)
1874 repo.dirstate.setparents(p1, p2)
1876 repo.dirstate.setparents(p1, p2)
1875 elif p2:
1877 elif p2:
1876 try:
1878 try:
1877 p1 = repo.lookup(p1)
1879 p1 = repo.lookup(p1)
1878 p2 = repo.lookup(p2)
1880 p2 = repo.lookup(p2)
1879 if p1 == wp[0].node():
1881 if p1 == wp[0].node():
1880 repo.dirstate.setparents(p1, p2)
1882 repo.dirstate.setparents(p1, p2)
1881 except error.RepoError:
1883 except error.RepoError:
1882 pass
1884 pass
1883 if opts.get('exact') or opts.get('import_branch'):
1885 if opts.get('exact') or opts.get('import_branch'):
1884 repo.dirstate.setbranch(branch or 'default')
1886 repo.dirstate.setbranch(branch or 'default')
1885
1887
1886 files = {}
1888 files = {}
1887 try:
1889 try:
1888 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1890 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1889 files=files, eolmode=None)
1891 files=files, eolmode=None)
1890 finally:
1892 finally:
1891 files = patch.updatedir(ui, repo, files,
1893 files = patch.updatedir(ui, repo, files,
1892 similarity=sim / 100.0)
1894 similarity=sim / 100.0)
1893 if not opts.get('no_commit'):
1895 if not opts.get('no_commit'):
1894 m = cmdutil.matchfiles(repo, files or [])
1896 m = cmdutil.matchfiles(repo, files or [])
1895 n = repo.commit(message, opts.get('user') or user,
1897 n = repo.commit(message, opts.get('user') or user,
1896 opts.get('date') or date, match=m,
1898 opts.get('date') or date, match=m,
1897 editor=cmdutil.commiteditor)
1899 editor=cmdutil.commiteditor)
1898 if opts.get('exact'):
1900 if opts.get('exact'):
1899 if hex(n) != nodeid:
1901 if hex(n) != nodeid:
1900 repo.rollback()
1902 repo.rollback()
1901 raise util.Abort(_('patch is damaged'
1903 raise util.Abort(_('patch is damaged'
1902 ' or loses information'))
1904 ' or loses information'))
1903 # Force a dirstate write so that the next transaction
1905 # Force a dirstate write so that the next transaction
1904 # backups an up-do-date file.
1906 # backups an up-do-date file.
1905 repo.dirstate.write()
1907 repo.dirstate.write()
1906 finally:
1908 finally:
1907 os.unlink(tmpname)
1909 os.unlink(tmpname)
1908 finally:
1910 finally:
1909 release(lock, wlock)
1911 release(lock, wlock)
1910
1912
1911 def incoming(ui, repo, source="default", **opts):
1913 def incoming(ui, repo, source="default", **opts):
1912 """show new changesets found in source
1914 """show new changesets found in source
1913
1915
1914 Show new changesets found in the specified path/URL or the default
1916 Show new changesets found in the specified path/URL or the default
1915 pull location. These are the changesets that would have been pulled
1917 pull location. These are the changesets that would have been pulled
1916 if a pull at the time you issued this command.
1918 if a pull at the time you issued this command.
1917
1919
1918 For remote repository, using --bundle avoids downloading the
1920 For remote repository, using --bundle avoids downloading the
1919 changesets twice if the incoming is followed by a pull.
1921 changesets twice if the incoming is followed by a pull.
1920
1922
1921 See pull for valid source format details.
1923 See pull for valid source format details.
1922 """
1924 """
1923 limit = cmdutil.loglimit(opts)
1925 limit = cmdutil.loglimit(opts)
1924 source, branches = hg.parseurl(ui.expandpath(source))
1926 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
1925 other = hg.repository(cmdutil.remoteui(repo, opts), source)
1927 other = hg.repository(cmdutil.remoteui(repo, opts), source)
1926 ui.status(_('comparing with %s\n') % url.hidepassword(source))
1928 ui.status(_('comparing with %s\n') % url.hidepassword(source))
1927 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
1929 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
1928 if revs:
1930 if revs:
1929 revs = [other.lookup(rev) for rev in revs]
1931 revs = [other.lookup(rev) for rev in revs]
1930 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
1932 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
1931 force=opts["force"])
1933 force=opts["force"])
1932 if not incoming:
1934 if not incoming:
1933 try:
1935 try:
1934 os.unlink(opts["bundle"])
1936 os.unlink(opts["bundle"])
1935 except:
1937 except:
1936 pass
1938 pass
1937 ui.status(_("no changes found\n"))
1939 ui.status(_("no changes found\n"))
1938 return 1
1940 return 1
1939
1941
1940 cleanup = None
1942 cleanup = None
1941 try:
1943 try:
1942 fname = opts["bundle"]
1944 fname = opts["bundle"]
1943 if fname or not other.local():
1945 if fname or not other.local():
1944 # create a bundle (uncompressed if other repo is not local)
1946 # create a bundle (uncompressed if other repo is not local)
1945
1947
1946 if revs is None and other.capable('changegroupsubset'):
1948 if revs is None and other.capable('changegroupsubset'):
1947 revs = rheads
1949 revs = rheads
1948
1950
1949 if revs is None:
1951 if revs is None:
1950 cg = other.changegroup(incoming, "incoming")
1952 cg = other.changegroup(incoming, "incoming")
1951 else:
1953 else:
1952 cg = other.changegroupsubset(incoming, revs, 'incoming')
1954 cg = other.changegroupsubset(incoming, revs, 'incoming')
1953 bundletype = other.local() and "HG10BZ" or "HG10UN"
1955 bundletype = other.local() and "HG10BZ" or "HG10UN"
1954 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1956 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1955 # keep written bundle?
1957 # keep written bundle?
1956 if opts["bundle"]:
1958 if opts["bundle"]:
1957 cleanup = None
1959 cleanup = None
1958 if not other.local():
1960 if not other.local():
1959 # use the created uncompressed bundlerepo
1961 # use the created uncompressed bundlerepo
1960 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1962 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1961
1963
1962 o = other.changelog.nodesbetween(incoming, revs)[0]
1964 o = other.changelog.nodesbetween(incoming, revs)[0]
1963 if opts.get('newest_first'):
1965 if opts.get('newest_first'):
1964 o.reverse()
1966 o.reverse()
1965 displayer = cmdutil.show_changeset(ui, other, opts)
1967 displayer = cmdutil.show_changeset(ui, other, opts)
1966 count = 0
1968 count = 0
1967 for n in o:
1969 for n in o:
1968 if limit is not None and count >= limit:
1970 if limit is not None and count >= limit:
1969 break
1971 break
1970 parents = [p for p in other.changelog.parents(n) if p != nullid]
1972 parents = [p for p in other.changelog.parents(n) if p != nullid]
1971 if opts.get('no_merges') and len(parents) == 2:
1973 if opts.get('no_merges') and len(parents) == 2:
1972 continue
1974 continue
1973 count += 1
1975 count += 1
1974 displayer.show(other[n])
1976 displayer.show(other[n])
1975 displayer.close()
1977 displayer.close()
1976 finally:
1978 finally:
1977 if hasattr(other, 'close'):
1979 if hasattr(other, 'close'):
1978 other.close()
1980 other.close()
1979 if cleanup:
1981 if cleanup:
1980 os.unlink(cleanup)
1982 os.unlink(cleanup)
1981
1983
1982 def init(ui, dest=".", **opts):
1984 def init(ui, dest=".", **opts):
1983 """create a new repository in the given directory
1985 """create a new repository in the given directory
1984
1986
1985 Initialize a new repository in the given directory. If the given
1987 Initialize a new repository in the given directory. If the given
1986 directory does not exist, it will be created.
1988 directory does not exist, it will be created.
1987
1989
1988 If no directory is given, the current directory is used.
1990 If no directory is given, the current directory is used.
1989
1991
1990 It is possible to specify an ``ssh://`` URL as the destination.
1992 It is possible to specify an ``ssh://`` URL as the destination.
1991 See 'hg help urls' for more information.
1993 See 'hg help urls' for more information.
1992 """
1994 """
1993 hg.repository(cmdutil.remoteui(ui, opts), dest, create=1)
1995 hg.repository(cmdutil.remoteui(ui, opts), dest, create=1)
1994
1996
1995 def locate(ui, repo, *pats, **opts):
1997 def locate(ui, repo, *pats, **opts):
1996 """locate files matching specific patterns
1998 """locate files matching specific patterns
1997
1999
1998 Print files under Mercurial control in the working directory whose
2000 Print files under Mercurial control in the working directory whose
1999 names match the given patterns.
2001 names match the given patterns.
2000
2002
2001 By default, this command searches all directories in the working
2003 By default, this command searches all directories in the working
2002 directory. To search just the current directory and its
2004 directory. To search just the current directory and its
2003 subdirectories, use "--include .".
2005 subdirectories, use "--include .".
2004
2006
2005 If no patterns are given to match, this command prints the names
2007 If no patterns are given to match, this command prints the names
2006 of all files under Mercurial control in the working directory.
2008 of all files under Mercurial control in the working directory.
2007
2009
2008 If you want to feed the output of this command into the "xargs"
2010 If you want to feed the output of this command into the "xargs"
2009 command, use the -0 option to both this command and "xargs". This
2011 command, use the -0 option to both this command and "xargs". This
2010 will avoid the problem of "xargs" treating single filenames that
2012 will avoid the problem of "xargs" treating single filenames that
2011 contain whitespace as multiple filenames.
2013 contain whitespace as multiple filenames.
2012 """
2014 """
2013 end = opts.get('print0') and '\0' or '\n'
2015 end = opts.get('print0') and '\0' or '\n'
2014 rev = opts.get('rev') or None
2016 rev = opts.get('rev') or None
2015
2017
2016 ret = 1
2018 ret = 1
2017 m = cmdutil.match(repo, pats, opts, default='relglob')
2019 m = cmdutil.match(repo, pats, opts, default='relglob')
2018 m.bad = lambda x, y: False
2020 m.bad = lambda x, y: False
2019 for abs in repo[rev].walk(m):
2021 for abs in repo[rev].walk(m):
2020 if not rev and abs not in repo.dirstate:
2022 if not rev and abs not in repo.dirstate:
2021 continue
2023 continue
2022 if opts.get('fullpath'):
2024 if opts.get('fullpath'):
2023 ui.write(repo.wjoin(abs), end)
2025 ui.write(repo.wjoin(abs), end)
2024 else:
2026 else:
2025 ui.write(((pats and m.rel(abs)) or abs), end)
2027 ui.write(((pats and m.rel(abs)) or abs), end)
2026 ret = 0
2028 ret = 0
2027
2029
2028 return ret
2030 return ret
2029
2031
2030 def log(ui, repo, *pats, **opts):
2032 def log(ui, repo, *pats, **opts):
2031 """show revision history of entire repository or files
2033 """show revision history of entire repository or files
2032
2034
2033 Print the revision history of the specified files or the entire
2035 Print the revision history of the specified files or the entire
2034 project.
2036 project.
2035
2037
2036 File history is shown without following rename or copy history of
2038 File history is shown without following rename or copy history of
2037 files. Use -f/--follow with a filename to follow history across
2039 files. Use -f/--follow with a filename to follow history across
2038 renames and copies. --follow without a filename will only show
2040 renames and copies. --follow without a filename will only show
2039 ancestors or descendants of the starting revision. --follow-first
2041 ancestors or descendants of the starting revision. --follow-first
2040 only follows the first parent of merge revisions.
2042 only follows the first parent of merge revisions.
2041
2043
2042 If no revision range is specified, the default is tip:0 unless
2044 If no revision range is specified, the default is tip:0 unless
2043 --follow is set, in which case the working directory parent is
2045 --follow is set, in which case the working directory parent is
2044 used as the starting revision.
2046 used as the starting revision.
2045
2047
2046 See 'hg help dates' for a list of formats valid for -d/--date.
2048 See 'hg help dates' for a list of formats valid for -d/--date.
2047
2049
2048 By default this command prints revision number and changeset id,
2050 By default this command prints revision number and changeset id,
2049 tags, non-trivial parents, user, date and time, and a summary for
2051 tags, non-trivial parents, user, date and time, and a summary for
2050 each commit. When the -v/--verbose switch is used, the list of
2052 each commit. When the -v/--verbose switch is used, the list of
2051 changed files and full commit message are shown.
2053 changed files and full commit message are shown.
2052
2054
2053 NOTE: log -p/--patch may generate unexpected diff output for merge
2055 NOTE: log -p/--patch may generate unexpected diff output for merge
2054 changesets, as it will only compare the merge changeset against
2056 changesets, as it will only compare the merge changeset against
2055 its first parent. Also, only files different from BOTH parents
2057 its first parent. Also, only files different from BOTH parents
2056 will appear in files:.
2058 will appear in files:.
2057 """
2059 """
2058
2060
2059 matchfn = cmdutil.match(repo, pats, opts)
2061 matchfn = cmdutil.match(repo, pats, opts)
2060 limit = cmdutil.loglimit(opts)
2062 limit = cmdutil.loglimit(opts)
2061 count = 0
2063 count = 0
2062
2064
2063 endrev = None
2065 endrev = None
2064 if opts.get('copies') and opts.get('rev'):
2066 if opts.get('copies') and opts.get('rev'):
2065 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2067 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2066
2068
2067 df = False
2069 df = False
2068 if opts["date"]:
2070 if opts["date"]:
2069 df = util.matchdate(opts["date"])
2071 df = util.matchdate(opts["date"])
2070
2072
2071 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
2073 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
2072 def prep(ctx, fns):
2074 def prep(ctx, fns):
2073 rev = ctx.rev()
2075 rev = ctx.rev()
2074 parents = [p for p in repo.changelog.parentrevs(rev)
2076 parents = [p for p in repo.changelog.parentrevs(rev)
2075 if p != nullrev]
2077 if p != nullrev]
2076 if opts.get('no_merges') and len(parents) == 2:
2078 if opts.get('no_merges') and len(parents) == 2:
2077 return
2079 return
2078 if opts.get('only_merges') and len(parents) != 2:
2080 if opts.get('only_merges') and len(parents) != 2:
2079 return
2081 return
2080 if opts.get('only_branch') and ctx.branch() not in opts['only_branch']:
2082 if opts.get('only_branch') and ctx.branch() not in opts['only_branch']:
2081 return
2083 return
2082 if df and not df(ctx.date()[0]):
2084 if df and not df(ctx.date()[0]):
2083 return
2085 return
2084 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2086 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2085 return
2087 return
2086 if opts.get('keyword'):
2088 if opts.get('keyword'):
2087 for k in [kw.lower() for kw in opts['keyword']]:
2089 for k in [kw.lower() for kw in opts['keyword']]:
2088 if (k in ctx.user().lower() or
2090 if (k in ctx.user().lower() or
2089 k in ctx.description().lower() or
2091 k in ctx.description().lower() or
2090 k in " ".join(ctx.files()).lower()):
2092 k in " ".join(ctx.files()).lower()):
2091 break
2093 break
2092 else:
2094 else:
2093 return
2095 return
2094
2096
2095 copies = None
2097 copies = None
2096 if opts.get('copies') and rev:
2098 if opts.get('copies') and rev:
2097 copies = []
2099 copies = []
2098 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2100 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2099 for fn in ctx.files():
2101 for fn in ctx.files():
2100 rename = getrenamed(fn, rev)
2102 rename = getrenamed(fn, rev)
2101 if rename:
2103 if rename:
2102 copies.append((fn, rename[0]))
2104 copies.append((fn, rename[0]))
2103
2105
2104 displayer.show(ctx, copies=copies)
2106 displayer.show(ctx, copies=copies)
2105
2107
2106 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2108 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2107 if count == limit:
2109 if count == limit:
2108 break
2110 break
2109 if displayer.flush(ctx.rev()):
2111 if displayer.flush(ctx.rev()):
2110 count += 1
2112 count += 1
2111 displayer.close()
2113 displayer.close()
2112
2114
2113 def manifest(ui, repo, node=None, rev=None):
2115 def manifest(ui, repo, node=None, rev=None):
2114 """output the current or given revision of the project manifest
2116 """output the current or given revision of the project manifest
2115
2117
2116 Print a list of version controlled files for the given revision.
2118 Print a list of version controlled files for the given revision.
2117 If no revision is given, the first parent of the working directory
2119 If no revision is given, the first parent of the working directory
2118 is used, or the null revision if no revision is checked out.
2120 is used, or the null revision if no revision is checked out.
2119
2121
2120 With -v, print file permissions, symlink and executable bits.
2122 With -v, print file permissions, symlink and executable bits.
2121 With --debug, print file revision hashes.
2123 With --debug, print file revision hashes.
2122 """
2124 """
2123
2125
2124 if rev and node:
2126 if rev and node:
2125 raise util.Abort(_("please specify just one revision"))
2127 raise util.Abort(_("please specify just one revision"))
2126
2128
2127 if not node:
2129 if not node:
2128 node = rev
2130 node = rev
2129
2131
2130 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2132 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2131 ctx = repo[node]
2133 ctx = repo[node]
2132 for f in ctx:
2134 for f in ctx:
2133 if ui.debugflag:
2135 if ui.debugflag:
2134 ui.write("%40s " % hex(ctx.manifest()[f]))
2136 ui.write("%40s " % hex(ctx.manifest()[f]))
2135 if ui.verbose:
2137 if ui.verbose:
2136 ui.write(decor[ctx.flags(f)])
2138 ui.write(decor[ctx.flags(f)])
2137 ui.write("%s\n" % f)
2139 ui.write("%s\n" % f)
2138
2140
2139 def merge(ui, repo, node=None, **opts):
2141 def merge(ui, repo, node=None, **opts):
2140 """merge working directory with another revision
2142 """merge working directory with another revision
2141
2143
2142 The current working directory is updated with all changes made in
2144 The current working directory is updated with all changes made in
2143 the requested revision since the last common predecessor revision.
2145 the requested revision since the last common predecessor revision.
2144
2146
2145 Files that changed between either parent are marked as changed for
2147 Files that changed between either parent are marked as changed for
2146 the next commit and a commit must be performed before any further
2148 the next commit and a commit must be performed before any further
2147 updates to the repository are allowed. The next commit will have
2149 updates to the repository are allowed. The next commit will have
2148 two parents.
2150 two parents.
2149
2151
2150 If no revision is specified, the working directory's parent is a
2152 If no revision is specified, the working directory's parent is a
2151 head revision, and the current branch contains exactly one other
2153 head revision, and the current branch contains exactly one other
2152 head, the other head is merged with by default. Otherwise, an
2154 head, the other head is merged with by default. Otherwise, an
2153 explicit revision with which to merge with must be provided.
2155 explicit revision with which to merge with must be provided.
2154 """
2156 """
2155
2157
2156 if opts.get('rev') and node:
2158 if opts.get('rev') and node:
2157 raise util.Abort(_("please specify just one revision"))
2159 raise util.Abort(_("please specify just one revision"))
2158 if not node:
2160 if not node:
2159 node = opts.get('rev')
2161 node = opts.get('rev')
2160
2162
2161 if not node:
2163 if not node:
2162 branch = repo.changectx(None).branch()
2164 branch = repo.changectx(None).branch()
2163 bheads = repo.branchheads(branch)
2165 bheads = repo.branchheads(branch)
2164 if len(bheads) > 2:
2166 if len(bheads) > 2:
2165 ui.warn(_("abort: branch '%s' has %d heads - "
2167 ui.warn(_("abort: branch '%s' has %d heads - "
2166 "please merge with an explicit rev\n")
2168 "please merge with an explicit rev\n")
2167 % (branch, len(bheads)))
2169 % (branch, len(bheads)))
2168 ui.status(_("(run 'hg heads .' to see heads)\n"))
2170 ui.status(_("(run 'hg heads .' to see heads)\n"))
2169 return False
2171 return False
2170
2172
2171 parent = repo.dirstate.parents()[0]
2173 parent = repo.dirstate.parents()[0]
2172 if len(bheads) == 1:
2174 if len(bheads) == 1:
2173 if len(repo.heads()) > 1:
2175 if len(repo.heads()) > 1:
2174 ui.warn(_("abort: branch '%s' has one head - "
2176 ui.warn(_("abort: branch '%s' has one head - "
2175 "please merge with an explicit rev\n" % branch))
2177 "please merge with an explicit rev\n" % branch))
2176 ui.status(_("(run 'hg heads' to see all heads)\n"))
2178 ui.status(_("(run 'hg heads' to see all heads)\n"))
2177 return False
2179 return False
2178 msg = _('there is nothing to merge')
2180 msg = _('there is nothing to merge')
2179 if parent != repo.lookup(repo[None].branch()):
2181 if parent != repo.lookup(repo[None].branch()):
2180 msg = _('%s - use "hg update" instead') % msg
2182 msg = _('%s - use "hg update" instead') % msg
2181 raise util.Abort(msg)
2183 raise util.Abort(msg)
2182
2184
2183 if parent not in bheads:
2185 if parent not in bheads:
2184 raise util.Abort(_('working dir not at a head rev - '
2186 raise util.Abort(_('working dir not at a head rev - '
2185 'use "hg update" or merge with an explicit rev'))
2187 'use "hg update" or merge with an explicit rev'))
2186 node = parent == bheads[0] and bheads[-1] or bheads[0]
2188 node = parent == bheads[0] and bheads[-1] or bheads[0]
2187
2189
2188 if opts.get('preview'):
2190 if opts.get('preview'):
2189 p1 = repo['.']
2191 p1 = repo['.']
2190 p2 = repo[node]
2192 p2 = repo[node]
2191 common = p1.ancestor(p2)
2193 common = p1.ancestor(p2)
2192 roots, heads = [common.node()], [p2.node()]
2194 roots, heads = [common.node()], [p2.node()]
2193 displayer = cmdutil.show_changeset(ui, repo, opts)
2195 displayer = cmdutil.show_changeset(ui, repo, opts)
2194 for node in repo.changelog.nodesbetween(roots=roots, heads=heads)[0]:
2196 for node in repo.changelog.nodesbetween(roots=roots, heads=heads)[0]:
2195 if node not in roots:
2197 if node not in roots:
2196 displayer.show(repo[node])
2198 displayer.show(repo[node])
2197 displayer.close()
2199 displayer.close()
2198 return 0
2200 return 0
2199
2201
2200 return hg.merge(repo, node, force=opts.get('force'))
2202 return hg.merge(repo, node, force=opts.get('force'))
2201
2203
2202 def outgoing(ui, repo, dest=None, **opts):
2204 def outgoing(ui, repo, dest=None, **opts):
2203 """show changesets not found in the destination
2205 """show changesets not found in the destination
2204
2206
2205 Show changesets not found in the specified destination repository
2207 Show changesets not found in the specified destination repository
2206 or the default push location. These are the changesets that would
2208 or the default push location. These are the changesets that would
2207 be pushed if a push was requested.
2209 be pushed if a push was requested.
2208
2210
2209 See pull for details of valid destination formats.
2211 See pull for details of valid destination formats.
2210 """
2212 """
2211 limit = cmdutil.loglimit(opts)
2213 limit = cmdutil.loglimit(opts)
2212 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2214 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2213 dest, branches = hg.parseurl(dest)
2215 dest, branches = hg.parseurl(dest, opts.get('branch'))
2214 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2216 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2215 if revs:
2217 if revs:
2216 revs = [repo.lookup(rev) for rev in revs]
2218 revs = [repo.lookup(rev) for rev in revs]
2217
2219
2218 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2220 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2219 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2221 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2220 o = repo.findoutgoing(other, force=opts.get('force'))
2222 o = repo.findoutgoing(other, force=opts.get('force'))
2221 if not o:
2223 if not o:
2222 ui.status(_("no changes found\n"))
2224 ui.status(_("no changes found\n"))
2223 return 1
2225 return 1
2224 o = repo.changelog.nodesbetween(o, revs)[0]
2226 o = repo.changelog.nodesbetween(o, revs)[0]
2225 if opts.get('newest_first'):
2227 if opts.get('newest_first'):
2226 o.reverse()
2228 o.reverse()
2227 displayer = cmdutil.show_changeset(ui, repo, opts)
2229 displayer = cmdutil.show_changeset(ui, repo, opts)
2228 count = 0
2230 count = 0
2229 for n in o:
2231 for n in o:
2230 if limit is not None and count >= limit:
2232 if limit is not None and count >= limit:
2231 break
2233 break
2232 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2234 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2233 if opts.get('no_merges') and len(parents) == 2:
2235 if opts.get('no_merges') and len(parents) == 2:
2234 continue
2236 continue
2235 count += 1
2237 count += 1
2236 displayer.show(repo[n])
2238 displayer.show(repo[n])
2237 displayer.close()
2239 displayer.close()
2238
2240
2239 def parents(ui, repo, file_=None, **opts):
2241 def parents(ui, repo, file_=None, **opts):
2240 """show the parents of the working directory or revision
2242 """show the parents of the working directory or revision
2241
2243
2242 Print the working directory's parent revisions. If a revision is
2244 Print the working directory's parent revisions. If a revision is
2243 given via -r/--rev, the parent of that revision will be printed.
2245 given via -r/--rev, the parent of that revision will be printed.
2244 If a file argument is given, the revision in which the file was
2246 If a file argument is given, the revision in which the file was
2245 last changed (before the working directory revision or the
2247 last changed (before the working directory revision or the
2246 argument to --rev if given) is printed.
2248 argument to --rev if given) is printed.
2247 """
2249 """
2248 rev = opts.get('rev')
2250 rev = opts.get('rev')
2249 if rev:
2251 if rev:
2250 ctx = repo[rev]
2252 ctx = repo[rev]
2251 else:
2253 else:
2252 ctx = repo[None]
2254 ctx = repo[None]
2253
2255
2254 if file_:
2256 if file_:
2255 m = cmdutil.match(repo, (file_,), opts)
2257 m = cmdutil.match(repo, (file_,), opts)
2256 if m.anypats() or len(m.files()) != 1:
2258 if m.anypats() or len(m.files()) != 1:
2257 raise util.Abort(_('can only specify an explicit filename'))
2259 raise util.Abort(_('can only specify an explicit filename'))
2258 file_ = m.files()[0]
2260 file_ = m.files()[0]
2259 filenodes = []
2261 filenodes = []
2260 for cp in ctx.parents():
2262 for cp in ctx.parents():
2261 if not cp:
2263 if not cp:
2262 continue
2264 continue
2263 try:
2265 try:
2264 filenodes.append(cp.filenode(file_))
2266 filenodes.append(cp.filenode(file_))
2265 except error.LookupError:
2267 except error.LookupError:
2266 pass
2268 pass
2267 if not filenodes:
2269 if not filenodes:
2268 raise util.Abort(_("'%s' not found in manifest!") % file_)
2270 raise util.Abort(_("'%s' not found in manifest!") % file_)
2269 fl = repo.file(file_)
2271 fl = repo.file(file_)
2270 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2272 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2271 else:
2273 else:
2272 p = [cp.node() for cp in ctx.parents()]
2274 p = [cp.node() for cp in ctx.parents()]
2273
2275
2274 displayer = cmdutil.show_changeset(ui, repo, opts)
2276 displayer = cmdutil.show_changeset(ui, repo, opts)
2275 for n in p:
2277 for n in p:
2276 if n != nullid:
2278 if n != nullid:
2277 displayer.show(repo[n])
2279 displayer.show(repo[n])
2278 displayer.close()
2280 displayer.close()
2279
2281
2280 def paths(ui, repo, search=None):
2282 def paths(ui, repo, search=None):
2281 """show aliases for remote repositories
2283 """show aliases for remote repositories
2282
2284
2283 Show definition of symbolic path name NAME. If no name is given,
2285 Show definition of symbolic path name NAME. If no name is given,
2284 show definition of all available names.
2286 show definition of all available names.
2285
2287
2286 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2288 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2287 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2289 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2288
2290
2289 See 'hg help urls' for more information.
2291 See 'hg help urls' for more information.
2290 """
2292 """
2291 if search:
2293 if search:
2292 for name, path in ui.configitems("paths"):
2294 for name, path in ui.configitems("paths"):
2293 if name == search:
2295 if name == search:
2294 ui.write("%s\n" % url.hidepassword(path))
2296 ui.write("%s\n" % url.hidepassword(path))
2295 return
2297 return
2296 ui.warn(_("not found!\n"))
2298 ui.warn(_("not found!\n"))
2297 return 1
2299 return 1
2298 else:
2300 else:
2299 for name, path in ui.configitems("paths"):
2301 for name, path in ui.configitems("paths"):
2300 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2302 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2301
2303
2302 def postincoming(ui, repo, modheads, optupdate, checkout):
2304 def postincoming(ui, repo, modheads, optupdate, checkout):
2303 if modheads == 0:
2305 if modheads == 0:
2304 return
2306 return
2305 if optupdate:
2307 if optupdate:
2306 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2308 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2307 return hg.update(repo, checkout)
2309 return hg.update(repo, checkout)
2308 else:
2310 else:
2309 ui.status(_("not updating, since new heads added\n"))
2311 ui.status(_("not updating, since new heads added\n"))
2310 if modheads > 1:
2312 if modheads > 1:
2311 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2313 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2312 else:
2314 else:
2313 ui.status(_("(run 'hg update' to get a working copy)\n"))
2315 ui.status(_("(run 'hg update' to get a working copy)\n"))
2314
2316
2315 def pull(ui, repo, source="default", **opts):
2317 def pull(ui, repo, source="default", **opts):
2316 """pull changes from the specified source
2318 """pull changes from the specified source
2317
2319
2318 Pull changes from a remote repository to a local one.
2320 Pull changes from a remote repository to a local one.
2319
2321
2320 This finds all changes from the repository at the specified path
2322 This finds all changes from the repository at the specified path
2321 or URL and adds them to a local repository (the current one unless
2323 or URL and adds them to a local repository (the current one unless
2322 -R is specified). By default, this does not update the copy of the
2324 -R is specified). By default, this does not update the copy of the
2323 project in the working directory.
2325 project in the working directory.
2324
2326
2325 Use hg incoming if you want to see what would have been added by a
2327 Use hg incoming if you want to see what would have been added by a
2326 pull at the time you issued this command. If you then decide to
2328 pull at the time you issued this command. If you then decide to
2327 added those changes to the repository, you should use pull -r X
2329 added those changes to the repository, you should use pull -r X
2328 where X is the last changeset listed by hg incoming.
2330 where X is the last changeset listed by hg incoming.
2329
2331
2330 If SOURCE is omitted, the 'default' path will be used.
2332 If SOURCE is omitted, the 'default' path will be used.
2331 See 'hg help urls' for more information.
2333 See 'hg help urls' for more information.
2332 """
2334 """
2333 source, branches = hg.parseurl(ui.expandpath(source))
2335 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2334 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2336 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2335 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2337 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2336 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2338 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2337 if revs:
2339 if revs:
2338 try:
2340 try:
2339 revs = [other.lookup(rev) for rev in revs]
2341 revs = [other.lookup(rev) for rev in revs]
2340 except error.CapabilityError:
2342 except error.CapabilityError:
2341 err = _("Other repository doesn't support revision lookup, "
2343 err = _("Other repository doesn't support revision lookup, "
2342 "so a rev cannot be specified.")
2344 "so a rev cannot be specified.")
2343 raise util.Abort(err)
2345 raise util.Abort(err)
2344
2346
2345 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2347 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2346 if checkout:
2348 if checkout:
2347 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2349 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2348 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2350 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2349
2351
2350 def push(ui, repo, dest=None, **opts):
2352 def push(ui, repo, dest=None, **opts):
2351 """push changes to the specified destination
2353 """push changes to the specified destination
2352
2354
2353 Push changes from the local repository to the specified destination.
2355 Push changes from the local repository to the specified destination.
2354
2356
2355 This is the symmetrical operation for pull. It moves changes from
2357 This is the symmetrical operation for pull. It moves changes from
2356 the current repository to a different one. If the destination is
2358 the current repository to a different one. If the destination is
2357 local this is identical to a pull in that directory from the
2359 local this is identical to a pull in that directory from the
2358 current one.
2360 current one.
2359
2361
2360 By default, push will refuse to run if it detects the result would
2362 By default, push will refuse to run if it detects the result would
2361 increase the number of remote heads. This generally indicates the
2363 increase the number of remote heads. This generally indicates the
2362 user forgot to pull and merge before pushing.
2364 user forgot to pull and merge before pushing.
2363
2365
2364 If -r/--rev is used, the named revision and all its ancestors will
2366 If -r/--rev is used, the named revision and all its ancestors will
2365 be pushed to the remote repository.
2367 be pushed to the remote repository.
2366
2368
2367 Please see 'hg help urls' for important details about ``ssh://``
2369 Please see 'hg help urls' for important details about ``ssh://``
2368 URLs. If DESTINATION is omitted, a default path will be used.
2370 URLs. If DESTINATION is omitted, a default path will be used.
2369 """
2371 """
2370 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2371 dest, branches = hg.parseurl(dest)
2373 dest, branches = hg.parseurl(dest, opts.get('branch'))
2372 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2374 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2373 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2375 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2374 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2376 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2375 if revs:
2377 if revs:
2376 revs = [repo.lookup(rev) for rev in revs]
2378 revs = [repo.lookup(rev) for rev in revs]
2377
2379
2378 # push subrepos depth-first for coherent ordering
2380 # push subrepos depth-first for coherent ordering
2379 c = repo['']
2381 c = repo['']
2380 subs = c.substate # only repos that are committed
2382 subs = c.substate # only repos that are committed
2381 for s in sorted(subs):
2383 for s in sorted(subs):
2382 c.sub(s).push(opts.get('force'))
2384 c.sub(s).push(opts.get('force'))
2383
2385
2384 r = repo.push(other, opts.get('force'), revs=revs)
2386 r = repo.push(other, opts.get('force'), revs=revs)
2385 return r == 0
2387 return r == 0
2386
2388
2387 def recover(ui, repo):
2389 def recover(ui, repo):
2388 """roll back an interrupted transaction
2390 """roll back an interrupted transaction
2389
2391
2390 Recover from an interrupted commit or pull.
2392 Recover from an interrupted commit or pull.
2391
2393
2392 This command tries to fix the repository status after an
2394 This command tries to fix the repository status after an
2393 interrupted operation. It should only be necessary when Mercurial
2395 interrupted operation. It should only be necessary when Mercurial
2394 suggests it.
2396 suggests it.
2395 """
2397 """
2396 if repo.recover():
2398 if repo.recover():
2397 return hg.verify(repo)
2399 return hg.verify(repo)
2398 return 1
2400 return 1
2399
2401
2400 def remove(ui, repo, *pats, **opts):
2402 def remove(ui, repo, *pats, **opts):
2401 """remove the specified files on the next commit
2403 """remove the specified files on the next commit
2402
2404
2403 Schedule the indicated files for removal from the repository.
2405 Schedule the indicated files for removal from the repository.
2404
2406
2405 This only removes files from the current branch, not from the
2407 This only removes files from the current branch, not from the
2406 entire project history. -A/--after can be used to remove only
2408 entire project history. -A/--after can be used to remove only
2407 files that have already been deleted, -f/--force can be used to
2409 files that have already been deleted, -f/--force can be used to
2408 force deletion, and -Af can be used to remove files from the next
2410 force deletion, and -Af can be used to remove files from the next
2409 revision without deleting them from the working directory.
2411 revision without deleting them from the working directory.
2410
2412
2411 The following table details the behavior of remove for different
2413 The following table details the behavior of remove for different
2412 file states (columns) and option combinations (rows). The file
2414 file states (columns) and option combinations (rows). The file
2413 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2415 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2414 reported by hg status). The actions are Warn, Remove (from branch)
2416 reported by hg status). The actions are Warn, Remove (from branch)
2415 and Delete (from disk)::
2417 and Delete (from disk)::
2416
2418
2417 A C M !
2419 A C M !
2418 none W RD W R
2420 none W RD W R
2419 -f R RD RD R
2421 -f R RD RD R
2420 -A W W W R
2422 -A W W W R
2421 -Af R R R R
2423 -Af R R R R
2422
2424
2423 This command schedules the files to be removed at the next commit.
2425 This command schedules the files to be removed at the next commit.
2424 To undo a remove before that, see hg revert.
2426 To undo a remove before that, see hg revert.
2425 """
2427 """
2426
2428
2427 after, force = opts.get('after'), opts.get('force')
2429 after, force = opts.get('after'), opts.get('force')
2428 if not pats and not after:
2430 if not pats and not after:
2429 raise util.Abort(_('no files specified'))
2431 raise util.Abort(_('no files specified'))
2430
2432
2431 m = cmdutil.match(repo, pats, opts)
2433 m = cmdutil.match(repo, pats, opts)
2432 s = repo.status(match=m, clean=True)
2434 s = repo.status(match=m, clean=True)
2433 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2435 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2434
2436
2435 for f in m.files():
2437 for f in m.files():
2436 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2438 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2437 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2439 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2438
2440
2439 def warn(files, reason):
2441 def warn(files, reason):
2440 for f in files:
2442 for f in files:
2441 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2443 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2442 % (m.rel(f), reason))
2444 % (m.rel(f), reason))
2443
2445
2444 if force:
2446 if force:
2445 remove, forget = modified + deleted + clean, added
2447 remove, forget = modified + deleted + clean, added
2446 elif after:
2448 elif after:
2447 remove, forget = deleted, []
2449 remove, forget = deleted, []
2448 warn(modified + added + clean, _('still exists'))
2450 warn(modified + added + clean, _('still exists'))
2449 else:
2451 else:
2450 remove, forget = deleted + clean, []
2452 remove, forget = deleted + clean, []
2451 warn(modified, _('is modified'))
2453 warn(modified, _('is modified'))
2452 warn(added, _('has been marked for add'))
2454 warn(added, _('has been marked for add'))
2453
2455
2454 for f in sorted(remove + forget):
2456 for f in sorted(remove + forget):
2455 if ui.verbose or not m.exact(f):
2457 if ui.verbose or not m.exact(f):
2456 ui.status(_('removing %s\n') % m.rel(f))
2458 ui.status(_('removing %s\n') % m.rel(f))
2457
2459
2458 repo.forget(forget)
2460 repo.forget(forget)
2459 repo.remove(remove, unlink=not after)
2461 repo.remove(remove, unlink=not after)
2460
2462
2461 def rename(ui, repo, *pats, **opts):
2463 def rename(ui, repo, *pats, **opts):
2462 """rename files; equivalent of copy + remove
2464 """rename files; equivalent of copy + remove
2463
2465
2464 Mark dest as copies of sources; mark sources for deletion. If dest
2466 Mark dest as copies of sources; mark sources for deletion. If dest
2465 is a directory, copies are put in that directory. If dest is a
2467 is a directory, copies are put in that directory. If dest is a
2466 file, there can only be one source.
2468 file, there can only be one source.
2467
2469
2468 By default, this command copies the contents of files as they
2470 By default, this command copies the contents of files as they
2469 exist in the working directory. If invoked with -A/--after, the
2471 exist in the working directory. If invoked with -A/--after, the
2470 operation is recorded, but no copying is performed.
2472 operation is recorded, but no copying is performed.
2471
2473
2472 This command takes effect at the next commit. To undo a rename
2474 This command takes effect at the next commit. To undo a rename
2473 before that, see hg revert.
2475 before that, see hg revert.
2474 """
2476 """
2475 wlock = repo.wlock(False)
2477 wlock = repo.wlock(False)
2476 try:
2478 try:
2477 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2479 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2478 finally:
2480 finally:
2479 wlock.release()
2481 wlock.release()
2480
2482
2481 def resolve(ui, repo, *pats, **opts):
2483 def resolve(ui, repo, *pats, **opts):
2482 """retry file merges from a merge or update
2484 """retry file merges from a merge or update
2483
2485
2484 This command can cleanly retry unresolved file merges using file
2486 This command can cleanly retry unresolved file merges using file
2485 revisions preserved from the last update or merge.
2487 revisions preserved from the last update or merge.
2486
2488
2487 If a conflict is resolved manually, please note that the changes
2489 If a conflict is resolved manually, please note that the changes
2488 will be overwritten if the merge is retried with resolve. The
2490 will be overwritten if the merge is retried with resolve. The
2489 -m/--mark switch should be used to mark the file as resolved.
2491 -m/--mark switch should be used to mark the file as resolved.
2490
2492
2491 You can specify a set of files to operate on, or use the -a/--all
2493 You can specify a set of files to operate on, or use the -a/--all
2492 switch to select all unresolved files.
2494 switch to select all unresolved files.
2493
2495
2494 This command also allows listing resolved files and manually
2496 This command also allows listing resolved files and manually
2495 indicating whether or not files are resolved. All files must be
2497 indicating whether or not files are resolved. All files must be
2496 marked as resolved before a commit is permitted.
2498 marked as resolved before a commit is permitted.
2497
2499
2498 The codes used to show the status of files are::
2500 The codes used to show the status of files are::
2499
2501
2500 U = unresolved
2502 U = unresolved
2501 R = resolved
2503 R = resolved
2502 """
2504 """
2503
2505
2504 all, mark, unmark, show, nostatus = \
2506 all, mark, unmark, show, nostatus = \
2505 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2507 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2506
2508
2507 if (show and (mark or unmark)) or (mark and unmark):
2509 if (show and (mark or unmark)) or (mark and unmark):
2508 raise util.Abort(_("too many options specified"))
2510 raise util.Abort(_("too many options specified"))
2509 if pats and all:
2511 if pats and all:
2510 raise util.Abort(_("can't specify --all and patterns"))
2512 raise util.Abort(_("can't specify --all and patterns"))
2511 if not (all or pats or show or mark or unmark):
2513 if not (all or pats or show or mark or unmark):
2512 raise util.Abort(_('no files or directories specified; '
2514 raise util.Abort(_('no files or directories specified; '
2513 'use --all to remerge all files'))
2515 'use --all to remerge all files'))
2514
2516
2515 ms = merge_.mergestate(repo)
2517 ms = merge_.mergestate(repo)
2516 m = cmdutil.match(repo, pats, opts)
2518 m = cmdutil.match(repo, pats, opts)
2517
2519
2518 for f in ms:
2520 for f in ms:
2519 if m(f):
2521 if m(f):
2520 if show:
2522 if show:
2521 if nostatus:
2523 if nostatus:
2522 ui.write("%s\n" % f)
2524 ui.write("%s\n" % f)
2523 else:
2525 else:
2524 ui.write("%s %s\n" % (ms[f].upper(), f))
2526 ui.write("%s %s\n" % (ms[f].upper(), f))
2525 elif mark:
2527 elif mark:
2526 ms.mark(f, "r")
2528 ms.mark(f, "r")
2527 elif unmark:
2529 elif unmark:
2528 ms.mark(f, "u")
2530 ms.mark(f, "u")
2529 else:
2531 else:
2530 wctx = repo[None]
2532 wctx = repo[None]
2531 mctx = wctx.parents()[-1]
2533 mctx = wctx.parents()[-1]
2532
2534
2533 # backup pre-resolve (merge uses .orig for its own purposes)
2535 # backup pre-resolve (merge uses .orig for its own purposes)
2534 a = repo.wjoin(f)
2536 a = repo.wjoin(f)
2535 util.copyfile(a, a + ".resolve")
2537 util.copyfile(a, a + ".resolve")
2536
2538
2537 # resolve file
2539 # resolve file
2538 ms.resolve(f, wctx, mctx)
2540 ms.resolve(f, wctx, mctx)
2539
2541
2540 # replace filemerge's .orig file with our resolve file
2542 # replace filemerge's .orig file with our resolve file
2541 util.rename(a + ".resolve", a + ".orig")
2543 util.rename(a + ".resolve", a + ".orig")
2542
2544
2543 def revert(ui, repo, *pats, **opts):
2545 def revert(ui, repo, *pats, **opts):
2544 """restore individual files or directories to an earlier state
2546 """restore individual files or directories to an earlier state
2545
2547
2546 (Use update -r to check out earlier revisions, revert does not
2548 (Use update -r to check out earlier revisions, revert does not
2547 change the working directory parents.)
2549 change the working directory parents.)
2548
2550
2549 With no revision specified, revert the named files or directories
2551 With no revision specified, revert the named files or directories
2550 to the contents they had in the parent of the working directory.
2552 to the contents they had in the parent of the working directory.
2551 This restores the contents of the affected files to an unmodified
2553 This restores the contents of the affected files to an unmodified
2552 state and unschedules adds, removes, copies, and renames. If the
2554 state and unschedules adds, removes, copies, and renames. If the
2553 working directory has two parents, you must explicitly specify a
2555 working directory has two parents, you must explicitly specify a
2554 revision.
2556 revision.
2555
2557
2556 Using the -r/--rev option, revert the given files or directories
2558 Using the -r/--rev option, revert the given files or directories
2557 to their contents as of a specific revision. This can be helpful
2559 to their contents as of a specific revision. This can be helpful
2558 to "roll back" some or all of an earlier change. See 'hg help
2560 to "roll back" some or all of an earlier change. See 'hg help
2559 dates' for a list of formats valid for -d/--date.
2561 dates' for a list of formats valid for -d/--date.
2560
2562
2561 Revert modifies the working directory. It does not commit any
2563 Revert modifies the working directory. It does not commit any
2562 changes, or change the parent of the working directory. If you
2564 changes, or change the parent of the working directory. If you
2563 revert to a revision other than the parent of the working
2565 revert to a revision other than the parent of the working
2564 directory, the reverted files will thus appear modified
2566 directory, the reverted files will thus appear modified
2565 afterwards.
2567 afterwards.
2566
2568
2567 If a file has been deleted, it is restored. If the executable mode
2569 If a file has been deleted, it is restored. If the executable mode
2568 of a file was changed, it is reset.
2570 of a file was changed, it is reset.
2569
2571
2570 If names are given, all files matching the names are reverted.
2572 If names are given, all files matching the names are reverted.
2571 If no arguments are given, no files are reverted.
2573 If no arguments are given, no files are reverted.
2572
2574
2573 Modified files are saved with a .orig suffix before reverting.
2575 Modified files are saved with a .orig suffix before reverting.
2574 To disable these backups, use --no-backup.
2576 To disable these backups, use --no-backup.
2575 """
2577 """
2576
2578
2577 if opts["date"]:
2579 if opts["date"]:
2578 if opts["rev"]:
2580 if opts["rev"]:
2579 raise util.Abort(_("you can't specify a revision and a date"))
2581 raise util.Abort(_("you can't specify a revision and a date"))
2580 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2582 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2581
2583
2582 if not pats and not opts.get('all'):
2584 if not pats and not opts.get('all'):
2583 raise util.Abort(_('no files or directories specified; '
2585 raise util.Abort(_('no files or directories specified; '
2584 'use --all to revert the whole repo'))
2586 'use --all to revert the whole repo'))
2585
2587
2586 parent, p2 = repo.dirstate.parents()
2588 parent, p2 = repo.dirstate.parents()
2587 if not opts.get('rev') and p2 != nullid:
2589 if not opts.get('rev') and p2 != nullid:
2588 raise util.Abort(_('uncommitted merge - please provide a '
2590 raise util.Abort(_('uncommitted merge - please provide a '
2589 'specific revision'))
2591 'specific revision'))
2590 ctx = repo[opts.get('rev')]
2592 ctx = repo[opts.get('rev')]
2591 node = ctx.node()
2593 node = ctx.node()
2592 mf = ctx.manifest()
2594 mf = ctx.manifest()
2593 if node == parent:
2595 if node == parent:
2594 pmf = mf
2596 pmf = mf
2595 else:
2597 else:
2596 pmf = None
2598 pmf = None
2597
2599
2598 # need all matching names in dirstate and manifest of target rev,
2600 # need all matching names in dirstate and manifest of target rev,
2599 # so have to walk both. do not print errors if files exist in one
2601 # so have to walk both. do not print errors if files exist in one
2600 # but not other.
2602 # but not other.
2601
2603
2602 names = {}
2604 names = {}
2603
2605
2604 wlock = repo.wlock()
2606 wlock = repo.wlock()
2605 try:
2607 try:
2606 # walk dirstate.
2608 # walk dirstate.
2607
2609
2608 m = cmdutil.match(repo, pats, opts)
2610 m = cmdutil.match(repo, pats, opts)
2609 m.bad = lambda x, y: False
2611 m.bad = lambda x, y: False
2610 for abs in repo.walk(m):
2612 for abs in repo.walk(m):
2611 names[abs] = m.rel(abs), m.exact(abs)
2613 names[abs] = m.rel(abs), m.exact(abs)
2612
2614
2613 # walk target manifest.
2615 # walk target manifest.
2614
2616
2615 def badfn(path, msg):
2617 def badfn(path, msg):
2616 if path in names:
2618 if path in names:
2617 return
2619 return
2618 path_ = path + '/'
2620 path_ = path + '/'
2619 for f in names:
2621 for f in names:
2620 if f.startswith(path_):
2622 if f.startswith(path_):
2621 return
2623 return
2622 ui.warn("%s: %s\n" % (m.rel(path), msg))
2624 ui.warn("%s: %s\n" % (m.rel(path), msg))
2623
2625
2624 m = cmdutil.match(repo, pats, opts)
2626 m = cmdutil.match(repo, pats, opts)
2625 m.bad = badfn
2627 m.bad = badfn
2626 for abs in repo[node].walk(m):
2628 for abs in repo[node].walk(m):
2627 if abs not in names:
2629 if abs not in names:
2628 names[abs] = m.rel(abs), m.exact(abs)
2630 names[abs] = m.rel(abs), m.exact(abs)
2629
2631
2630 m = cmdutil.matchfiles(repo, names)
2632 m = cmdutil.matchfiles(repo, names)
2631 changes = repo.status(match=m)[:4]
2633 changes = repo.status(match=m)[:4]
2632 modified, added, removed, deleted = map(set, changes)
2634 modified, added, removed, deleted = map(set, changes)
2633
2635
2634 # if f is a rename, also revert the source
2636 # if f is a rename, also revert the source
2635 cwd = repo.getcwd()
2637 cwd = repo.getcwd()
2636 for f in added:
2638 for f in added:
2637 src = repo.dirstate.copied(f)
2639 src = repo.dirstate.copied(f)
2638 if src and src not in names and repo.dirstate[src] == 'r':
2640 if src and src not in names and repo.dirstate[src] == 'r':
2639 removed.add(src)
2641 removed.add(src)
2640 names[src] = (repo.pathto(src, cwd), True)
2642 names[src] = (repo.pathto(src, cwd), True)
2641
2643
2642 def removeforget(abs):
2644 def removeforget(abs):
2643 if repo.dirstate[abs] == 'a':
2645 if repo.dirstate[abs] == 'a':
2644 return _('forgetting %s\n')
2646 return _('forgetting %s\n')
2645 return _('removing %s\n')
2647 return _('removing %s\n')
2646
2648
2647 revert = ([], _('reverting %s\n'))
2649 revert = ([], _('reverting %s\n'))
2648 add = ([], _('adding %s\n'))
2650 add = ([], _('adding %s\n'))
2649 remove = ([], removeforget)
2651 remove = ([], removeforget)
2650 undelete = ([], _('undeleting %s\n'))
2652 undelete = ([], _('undeleting %s\n'))
2651
2653
2652 disptable = (
2654 disptable = (
2653 # dispatch table:
2655 # dispatch table:
2654 # file state
2656 # file state
2655 # action if in target manifest
2657 # action if in target manifest
2656 # action if not in target manifest
2658 # action if not in target manifest
2657 # make backup if in target manifest
2659 # make backup if in target manifest
2658 # make backup if not in target manifest
2660 # make backup if not in target manifest
2659 (modified, revert, remove, True, True),
2661 (modified, revert, remove, True, True),
2660 (added, revert, remove, True, False),
2662 (added, revert, remove, True, False),
2661 (removed, undelete, None, False, False),
2663 (removed, undelete, None, False, False),
2662 (deleted, revert, remove, False, False),
2664 (deleted, revert, remove, False, False),
2663 )
2665 )
2664
2666
2665 for abs, (rel, exact) in sorted(names.items()):
2667 for abs, (rel, exact) in sorted(names.items()):
2666 mfentry = mf.get(abs)
2668 mfentry = mf.get(abs)
2667 target = repo.wjoin(abs)
2669 target = repo.wjoin(abs)
2668 def handle(xlist, dobackup):
2670 def handle(xlist, dobackup):
2669 xlist[0].append(abs)
2671 xlist[0].append(abs)
2670 if dobackup and not opts.get('no_backup') and util.lexists(target):
2672 if dobackup and not opts.get('no_backup') and util.lexists(target):
2671 bakname = "%s.orig" % rel
2673 bakname = "%s.orig" % rel
2672 ui.note(_('saving current version of %s as %s\n') %
2674 ui.note(_('saving current version of %s as %s\n') %
2673 (rel, bakname))
2675 (rel, bakname))
2674 if not opts.get('dry_run'):
2676 if not opts.get('dry_run'):
2675 util.copyfile(target, bakname)
2677 util.copyfile(target, bakname)
2676 if ui.verbose or not exact:
2678 if ui.verbose or not exact:
2677 msg = xlist[1]
2679 msg = xlist[1]
2678 if not isinstance(msg, basestring):
2680 if not isinstance(msg, basestring):
2679 msg = msg(abs)
2681 msg = msg(abs)
2680 ui.status(msg % rel)
2682 ui.status(msg % rel)
2681 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2683 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2682 if abs not in table:
2684 if abs not in table:
2683 continue
2685 continue
2684 # file has changed in dirstate
2686 # file has changed in dirstate
2685 if mfentry:
2687 if mfentry:
2686 handle(hitlist, backuphit)
2688 handle(hitlist, backuphit)
2687 elif misslist is not None:
2689 elif misslist is not None:
2688 handle(misslist, backupmiss)
2690 handle(misslist, backupmiss)
2689 break
2691 break
2690 else:
2692 else:
2691 if abs not in repo.dirstate:
2693 if abs not in repo.dirstate:
2692 if mfentry:
2694 if mfentry:
2693 handle(add, True)
2695 handle(add, True)
2694 elif exact:
2696 elif exact:
2695 ui.warn(_('file not managed: %s\n') % rel)
2697 ui.warn(_('file not managed: %s\n') % rel)
2696 continue
2698 continue
2697 # file has not changed in dirstate
2699 # file has not changed in dirstate
2698 if node == parent:
2700 if node == parent:
2699 if exact:
2701 if exact:
2700 ui.warn(_('no changes needed to %s\n') % rel)
2702 ui.warn(_('no changes needed to %s\n') % rel)
2701 continue
2703 continue
2702 if pmf is None:
2704 if pmf is None:
2703 # only need parent manifest in this unlikely case,
2705 # only need parent manifest in this unlikely case,
2704 # so do not read by default
2706 # so do not read by default
2705 pmf = repo[parent].manifest()
2707 pmf = repo[parent].manifest()
2706 if abs in pmf:
2708 if abs in pmf:
2707 if mfentry:
2709 if mfentry:
2708 # if version of file is same in parent and target
2710 # if version of file is same in parent and target
2709 # manifests, do nothing
2711 # manifests, do nothing
2710 if (pmf[abs] != mfentry or
2712 if (pmf[abs] != mfentry or
2711 pmf.flags(abs) != mf.flags(abs)):
2713 pmf.flags(abs) != mf.flags(abs)):
2712 handle(revert, False)
2714 handle(revert, False)
2713 else:
2715 else:
2714 handle(remove, False)
2716 handle(remove, False)
2715
2717
2716 if not opts.get('dry_run'):
2718 if not opts.get('dry_run'):
2717 def checkout(f):
2719 def checkout(f):
2718 fc = ctx[f]
2720 fc = ctx[f]
2719 repo.wwrite(f, fc.data(), fc.flags())
2721 repo.wwrite(f, fc.data(), fc.flags())
2720
2722
2721 audit_path = util.path_auditor(repo.root)
2723 audit_path = util.path_auditor(repo.root)
2722 for f in remove[0]:
2724 for f in remove[0]:
2723 if repo.dirstate[f] == 'a':
2725 if repo.dirstate[f] == 'a':
2724 repo.dirstate.forget(f)
2726 repo.dirstate.forget(f)
2725 continue
2727 continue
2726 audit_path(f)
2728 audit_path(f)
2727 try:
2729 try:
2728 util.unlink(repo.wjoin(f))
2730 util.unlink(repo.wjoin(f))
2729 except OSError:
2731 except OSError:
2730 pass
2732 pass
2731 repo.dirstate.remove(f)
2733 repo.dirstate.remove(f)
2732
2734
2733 normal = None
2735 normal = None
2734 if node == parent:
2736 if node == parent:
2735 # We're reverting to our parent. If possible, we'd like status
2737 # We're reverting to our parent. If possible, we'd like status
2736 # to report the file as clean. We have to use normallookup for
2738 # to report the file as clean. We have to use normallookup for
2737 # merges to avoid losing information about merged/dirty files.
2739 # merges to avoid losing information about merged/dirty files.
2738 if p2 != nullid:
2740 if p2 != nullid:
2739 normal = repo.dirstate.normallookup
2741 normal = repo.dirstate.normallookup
2740 else:
2742 else:
2741 normal = repo.dirstate.normal
2743 normal = repo.dirstate.normal
2742 for f in revert[0]:
2744 for f in revert[0]:
2743 checkout(f)
2745 checkout(f)
2744 if normal:
2746 if normal:
2745 normal(f)
2747 normal(f)
2746
2748
2747 for f in add[0]:
2749 for f in add[0]:
2748 checkout(f)
2750 checkout(f)
2749 repo.dirstate.add(f)
2751 repo.dirstate.add(f)
2750
2752
2751 normal = repo.dirstate.normallookup
2753 normal = repo.dirstate.normallookup
2752 if node == parent and p2 == nullid:
2754 if node == parent and p2 == nullid:
2753 normal = repo.dirstate.normal
2755 normal = repo.dirstate.normal
2754 for f in undelete[0]:
2756 for f in undelete[0]:
2755 checkout(f)
2757 checkout(f)
2756 normal(f)
2758 normal(f)
2757
2759
2758 finally:
2760 finally:
2759 wlock.release()
2761 wlock.release()
2760
2762
2761 def rollback(ui, repo):
2763 def rollback(ui, repo):
2762 """roll back the last transaction
2764 """roll back the last transaction
2763
2765
2764 This command should be used with care. There is only one level of
2766 This command should be used with care. There is only one level of
2765 rollback, and there is no way to undo a rollback. It will also
2767 rollback, and there is no way to undo a rollback. It will also
2766 restore the dirstate at the time of the last transaction, losing
2768 restore the dirstate at the time of the last transaction, losing
2767 any dirstate changes since that time. This command does not alter
2769 any dirstate changes since that time. This command does not alter
2768 the working directory.
2770 the working directory.
2769
2771
2770 Transactions are used to encapsulate the effects of all commands
2772 Transactions are used to encapsulate the effects of all commands
2771 that create new changesets or propagate existing changesets into a
2773 that create new changesets or propagate existing changesets into a
2772 repository. For example, the following commands are transactional,
2774 repository. For example, the following commands are transactional,
2773 and their effects can be rolled back:
2775 and their effects can be rolled back:
2774
2776
2775 - commit
2777 - commit
2776 - import
2778 - import
2777 - pull
2779 - pull
2778 - push (with this repository as the destination)
2780 - push (with this repository as the destination)
2779 - unbundle
2781 - unbundle
2780
2782
2781 This command is not intended for use on public repositories. Once
2783 This command is not intended for use on public repositories. Once
2782 changes are visible for pull by other users, rolling a transaction
2784 changes are visible for pull by other users, rolling a transaction
2783 back locally is ineffective (someone else may already have pulled
2785 back locally is ineffective (someone else may already have pulled
2784 the changes). Furthermore, a race is possible with readers of the
2786 the changes). Furthermore, a race is possible with readers of the
2785 repository; for example an in-progress pull from the repository
2787 repository; for example an in-progress pull from the repository
2786 may fail if a rollback is performed.
2788 may fail if a rollback is performed.
2787 """
2789 """
2788 repo.rollback()
2790 repo.rollback()
2789
2791
2790 def root(ui, repo):
2792 def root(ui, repo):
2791 """print the root (top) of the current working directory
2793 """print the root (top) of the current working directory
2792
2794
2793 Print the root directory of the current repository.
2795 Print the root directory of the current repository.
2794 """
2796 """
2795 ui.write(repo.root + "\n")
2797 ui.write(repo.root + "\n")
2796
2798
2797 def serve(ui, repo, **opts):
2799 def serve(ui, repo, **opts):
2798 """export the repository via HTTP
2800 """export the repository via HTTP
2799
2801
2800 Start a local HTTP repository browser and pull server.
2802 Start a local HTTP repository browser and pull server.
2801
2803
2802 By default, the server logs accesses to stdout and errors to
2804 By default, the server logs accesses to stdout and errors to
2803 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
2805 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
2804 files.
2806 files.
2805 """
2807 """
2806
2808
2807 if opts["stdio"]:
2809 if opts["stdio"]:
2808 if repo is None:
2810 if repo is None:
2809 raise error.RepoError(_("There is no Mercurial repository here"
2811 raise error.RepoError(_("There is no Mercurial repository here"
2810 " (.hg not found)"))
2812 " (.hg not found)"))
2811 s = sshserver.sshserver(ui, repo)
2813 s = sshserver.sshserver(ui, repo)
2812 s.serve_forever()
2814 s.serve_forever()
2813
2815
2814 baseui = repo and repo.baseui or ui
2816 baseui = repo and repo.baseui or ui
2815 optlist = ("name templates style address port prefix ipv6"
2817 optlist = ("name templates style address port prefix ipv6"
2816 " accesslog errorlog webdir_conf certificate encoding")
2818 " accesslog errorlog webdir_conf certificate encoding")
2817 for o in optlist.split():
2819 for o in optlist.split():
2818 if opts.get(o, None):
2820 if opts.get(o, None):
2819 baseui.setconfig("web", o, str(opts[o]))
2821 baseui.setconfig("web", o, str(opts[o]))
2820 if (repo is not None) and (repo.ui != baseui):
2822 if (repo is not None) and (repo.ui != baseui):
2821 repo.ui.setconfig("web", o, str(opts[o]))
2823 repo.ui.setconfig("web", o, str(opts[o]))
2822
2824
2823 if repo is None and not ui.config("web", "webdir_conf"):
2825 if repo is None and not ui.config("web", "webdir_conf"):
2824 raise error.RepoError(_("There is no Mercurial repository here"
2826 raise error.RepoError(_("There is no Mercurial repository here"
2825 " (.hg not found)"))
2827 " (.hg not found)"))
2826
2828
2827 class service(object):
2829 class service(object):
2828 def init(self):
2830 def init(self):
2829 util.set_signal_handler()
2831 util.set_signal_handler()
2830 self.httpd = server.create_server(baseui, repo)
2832 self.httpd = server.create_server(baseui, repo)
2831
2833
2832 if not ui.verbose:
2834 if not ui.verbose:
2833 return
2835 return
2834
2836
2835 if self.httpd.prefix:
2837 if self.httpd.prefix:
2836 prefix = self.httpd.prefix.strip('/') + '/'
2838 prefix = self.httpd.prefix.strip('/') + '/'
2837 else:
2839 else:
2838 prefix = ''
2840 prefix = ''
2839
2841
2840 port = ':%d' % self.httpd.port
2842 port = ':%d' % self.httpd.port
2841 if port == ':80':
2843 if port == ':80':
2842 port = ''
2844 port = ''
2843
2845
2844 bindaddr = self.httpd.addr
2846 bindaddr = self.httpd.addr
2845 if bindaddr == '0.0.0.0':
2847 if bindaddr == '0.0.0.0':
2846 bindaddr = '*'
2848 bindaddr = '*'
2847 elif ':' in bindaddr: # IPv6
2849 elif ':' in bindaddr: # IPv6
2848 bindaddr = '[%s]' % bindaddr
2850 bindaddr = '[%s]' % bindaddr
2849
2851
2850 fqaddr = self.httpd.fqaddr
2852 fqaddr = self.httpd.fqaddr
2851 if ':' in fqaddr:
2853 if ':' in fqaddr:
2852 fqaddr = '[%s]' % fqaddr
2854 fqaddr = '[%s]' % fqaddr
2853 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2855 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2854 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2856 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2855
2857
2856 def run(self):
2858 def run(self):
2857 self.httpd.serve_forever()
2859 self.httpd.serve_forever()
2858
2860
2859 service = service()
2861 service = service()
2860
2862
2861 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2863 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2862
2864
2863 def status(ui, repo, *pats, **opts):
2865 def status(ui, repo, *pats, **opts):
2864 """show changed files in the working directory
2866 """show changed files in the working directory
2865
2867
2866 Show status of files in the repository. If names are given, only
2868 Show status of files in the repository. If names are given, only
2867 files that match are shown. Files that are clean or ignored or
2869 files that match are shown. Files that are clean or ignored or
2868 the source of a copy/move operation, are not listed unless
2870 the source of a copy/move operation, are not listed unless
2869 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
2871 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
2870 Unless options described with "show only ..." are given, the
2872 Unless options described with "show only ..." are given, the
2871 options -mardu are used.
2873 options -mardu are used.
2872
2874
2873 Option -q/--quiet hides untracked (unknown and ignored) files
2875 Option -q/--quiet hides untracked (unknown and ignored) files
2874 unless explicitly requested with -u/--unknown or -i/--ignored.
2876 unless explicitly requested with -u/--unknown or -i/--ignored.
2875
2877
2876 NOTE: status may appear to disagree with diff if permissions have
2878 NOTE: status may appear to disagree with diff if permissions have
2877 changed or a merge has occurred. The standard diff format does not
2879 changed or a merge has occurred. The standard diff format does not
2878 report permission changes and diff only reports changes relative
2880 report permission changes and diff only reports changes relative
2879 to one merge parent.
2881 to one merge parent.
2880
2882
2881 If one revision is given, it is used as the base revision.
2883 If one revision is given, it is used as the base revision.
2882 If two revisions are given, the differences between them are
2884 If two revisions are given, the differences between them are
2883 shown. The --change option can also be used as a shortcut to list
2885 shown. The --change option can also be used as a shortcut to list
2884 the changed files of a revision from its first parent.
2886 the changed files of a revision from its first parent.
2885
2887
2886 The codes used to show the status of files are::
2888 The codes used to show the status of files are::
2887
2889
2888 M = modified
2890 M = modified
2889 A = added
2891 A = added
2890 R = removed
2892 R = removed
2891 C = clean
2893 C = clean
2892 ! = missing (deleted by non-hg command, but still tracked)
2894 ! = missing (deleted by non-hg command, but still tracked)
2893 ? = not tracked
2895 ? = not tracked
2894 I = ignored
2896 I = ignored
2895 = origin of the previous file listed as A (added)
2897 = origin of the previous file listed as A (added)
2896 """
2898 """
2897
2899
2898 revs = opts.get('rev')
2900 revs = opts.get('rev')
2899 change = opts.get('change')
2901 change = opts.get('change')
2900
2902
2901 if revs and change:
2903 if revs and change:
2902 msg = _('cannot specify --rev and --change at the same time')
2904 msg = _('cannot specify --rev and --change at the same time')
2903 raise util.Abort(msg)
2905 raise util.Abort(msg)
2904 elif change:
2906 elif change:
2905 node2 = repo.lookup(change)
2907 node2 = repo.lookup(change)
2906 node1 = repo[node2].parents()[0].node()
2908 node1 = repo[node2].parents()[0].node()
2907 else:
2909 else:
2908 node1, node2 = cmdutil.revpair(repo, revs)
2910 node1, node2 = cmdutil.revpair(repo, revs)
2909
2911
2910 cwd = (pats and repo.getcwd()) or ''
2912 cwd = (pats and repo.getcwd()) or ''
2911 end = opts.get('print0') and '\0' or '\n'
2913 end = opts.get('print0') and '\0' or '\n'
2912 copy = {}
2914 copy = {}
2913 states = 'modified added removed deleted unknown ignored clean'.split()
2915 states = 'modified added removed deleted unknown ignored clean'.split()
2914 show = [k for k in states if opts.get(k)]
2916 show = [k for k in states if opts.get(k)]
2915 if opts.get('all'):
2917 if opts.get('all'):
2916 show += ui.quiet and (states[:4] + ['clean']) or states
2918 show += ui.quiet and (states[:4] + ['clean']) or states
2917 if not show:
2919 if not show:
2918 show = ui.quiet and states[:4] or states[:5]
2920 show = ui.quiet and states[:4] or states[:5]
2919
2921
2920 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2922 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2921 'ignored' in show, 'clean' in show, 'unknown' in show)
2923 'ignored' in show, 'clean' in show, 'unknown' in show)
2922 changestates = zip(states, 'MAR!?IC', stat)
2924 changestates = zip(states, 'MAR!?IC', stat)
2923
2925
2924 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
2926 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
2925 ctxn = repo[nullid]
2927 ctxn = repo[nullid]
2926 ctx1 = repo[node1]
2928 ctx1 = repo[node1]
2927 ctx2 = repo[node2]
2929 ctx2 = repo[node2]
2928 added = stat[1]
2930 added = stat[1]
2929 if node2 is None:
2931 if node2 is None:
2930 added = stat[0] + stat[1] # merged?
2932 added = stat[0] + stat[1] # merged?
2931
2933
2932 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
2934 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
2933 if k in added:
2935 if k in added:
2934 copy[k] = v
2936 copy[k] = v
2935 elif v in added:
2937 elif v in added:
2936 copy[v] = k
2938 copy[v] = k
2937
2939
2938 for state, char, files in changestates:
2940 for state, char, files in changestates:
2939 if state in show:
2941 if state in show:
2940 format = "%s %%s%s" % (char, end)
2942 format = "%s %%s%s" % (char, end)
2941 if opts.get('no_status'):
2943 if opts.get('no_status'):
2942 format = "%%s%s" % end
2944 format = "%%s%s" % end
2943
2945
2944 for f in files:
2946 for f in files:
2945 ui.write(format % repo.pathto(f, cwd))
2947 ui.write(format % repo.pathto(f, cwd))
2946 if f in copy:
2948 if f in copy:
2947 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2949 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2948
2950
2949 def summary(ui, repo, **opts):
2951 def summary(ui, repo, **opts):
2950 """summarize working directory state
2952 """summarize working directory state
2951
2953
2952 This generates a brief summary of the working directory state,
2954 This generates a brief summary of the working directory state,
2953 including parents, branch, commit status, and available updates.
2955 including parents, branch, commit status, and available updates.
2954
2956
2955 With the --remote option, this will check the default paths for
2957 With the --remote option, this will check the default paths for
2956 incoming and outgoing changes. This can be time-consuming.
2958 incoming and outgoing changes. This can be time-consuming.
2957 """
2959 """
2958
2960
2959 ctx = repo[None]
2961 ctx = repo[None]
2960 parents = ctx.parents()
2962 parents = ctx.parents()
2961 pnode = parents[0].node()
2963 pnode = parents[0].node()
2962 tags = repo.tags()
2964 tags = repo.tags()
2963
2965
2964 for p in parents:
2966 for p in parents:
2965 t = ' '.join([t for t in tags if tags[t] == p.node()])
2967 t = ' '.join([t for t in tags if tags[t] == p.node()])
2966 if p.rev() == -1:
2968 if p.rev() == -1:
2967 if not len(repo):
2969 if not len(repo):
2968 t += _(' (empty repository)')
2970 t += _(' (empty repository)')
2969 else:
2971 else:
2970 t += _(' (no revision checked out)')
2972 t += _(' (no revision checked out)')
2971 ui.write(_('parent: %d:%s %s\n') % (p.rev(), str(p), t))
2973 ui.write(_('parent: %d:%s %s\n') % (p.rev(), str(p), t))
2972 if p.description():
2974 if p.description():
2973 ui.status(' ' + p.description().splitlines()[0].strip() + '\n')
2975 ui.status(' ' + p.description().splitlines()[0].strip() + '\n')
2974
2976
2975 branch = ctx.branch()
2977 branch = ctx.branch()
2976 bheads = repo.branchheads(branch)
2978 bheads = repo.branchheads(branch)
2977 m = _('branch: %s\n') % branch
2979 m = _('branch: %s\n') % branch
2978 if branch != 'default':
2980 if branch != 'default':
2979 ui.write(m)
2981 ui.write(m)
2980 else:
2982 else:
2981 ui.status(m)
2983 ui.status(m)
2982
2984
2983 st = list(repo.status(unknown=True))[:7]
2985 st = list(repo.status(unknown=True))[:7]
2984 ms = merge_.mergestate(repo)
2986 ms = merge_.mergestate(repo)
2985 st.append([f for f in ms if f == 'u'])
2987 st.append([f for f in ms if f == 'u'])
2986 labels = [_('%d modified'), _('%d added'), _('%d removed'),
2988 labels = [_('%d modified'), _('%d added'), _('%d removed'),
2987 _('%d deleted'), _('%d unknown'), _('%d ignored'),
2989 _('%d deleted'), _('%d unknown'), _('%d ignored'),
2988 _('%d unresolved')]
2990 _('%d unresolved')]
2989 t = []
2991 t = []
2990 for s, l in zip(st, labels):
2992 for s, l in zip(st, labels):
2991 if s:
2993 if s:
2992 t.append(l % len(s))
2994 t.append(l % len(s))
2993
2995
2994 t = ', '.join(t)
2996 t = ', '.join(t)
2995 cleanworkdir = False
2997 cleanworkdir = False
2996
2998
2997 if len(parents) > 1:
2999 if len(parents) > 1:
2998 t += _(' (merge)')
3000 t += _(' (merge)')
2999 elif branch != parents[0].branch():
3001 elif branch != parents[0].branch():
3000 t += _(' (new branch)')
3002 t += _(' (new branch)')
3001 elif (not st[0] and not st[1] and not st[2]):
3003 elif (not st[0] and not st[1] and not st[2]):
3002 t += _(' (clean)')
3004 t += _(' (clean)')
3003 cleanworkdir = True
3005 cleanworkdir = True
3004 elif pnode not in bheads:
3006 elif pnode not in bheads:
3005 t += _(' (new branch head)')
3007 t += _(' (new branch head)')
3006
3008
3007 if cleanworkdir:
3009 if cleanworkdir:
3008 ui.status(_('commit: %s\n') % t.strip())
3010 ui.status(_('commit: %s\n') % t.strip())
3009 else:
3011 else:
3010 ui.write(_('commit: %s\n') % t.strip())
3012 ui.write(_('commit: %s\n') % t.strip())
3011
3013
3012 # all ancestors of branch heads - all ancestors of parent = new csets
3014 # all ancestors of branch heads - all ancestors of parent = new csets
3013 new = [0] * len(repo)
3015 new = [0] * len(repo)
3014 cl = repo.changelog
3016 cl = repo.changelog
3015 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3017 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3016 new[a] = 1
3018 new[a] = 1
3017 for a in cl.ancestors(*[p.rev() for p in parents]):
3019 for a in cl.ancestors(*[p.rev() for p in parents]):
3018 new[a] = 0
3020 new[a] = 0
3019 new = sum(new)
3021 new = sum(new)
3020
3022
3021 if new == 0:
3023 if new == 0:
3022 ui.status(_('update: (current)\n'))
3024 ui.status(_('update: (current)\n'))
3023 elif pnode not in bheads:
3025 elif pnode not in bheads:
3024 ui.write(_('update: %d new changesets (update)\n') % new)
3026 ui.write(_('update: %d new changesets (update)\n') % new)
3025 else:
3027 else:
3026 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3028 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3027 (new, len(bheads)))
3029 (new, len(bheads)))
3028
3030
3029 if opts.get('remote'):
3031 if opts.get('remote'):
3030 t = []
3032 t = []
3031 source, revs, checkout = hg.parseurl(ui.expandpath('default'),
3033 source, revs, checkout = hg.parseurl(ui.expandpath('default'),
3032 opts.get('rev'))
3034 opts.get('rev'))
3033 other = hg.repository(cmdutil.remoteui(repo, {}), source)
3035 other = hg.repository(cmdutil.remoteui(repo, {}), source)
3034 ui.debug('comparing with %s\n' % url.hidepassword(source))
3036 ui.debug('comparing with %s\n' % url.hidepassword(source))
3035 repo.ui.pushbuffer()
3037 repo.ui.pushbuffer()
3036 common, incoming, rheads = repo.findcommonincoming(other)
3038 common, incoming, rheads = repo.findcommonincoming(other)
3037 repo.ui.popbuffer()
3039 repo.ui.popbuffer()
3038 if incoming:
3040 if incoming:
3039 t.append(_('1 or more incoming'))
3041 t.append(_('1 or more incoming'))
3040
3042
3041 dest, revs, checkout = hg.parseurl(
3043 dest, revs, checkout = hg.parseurl(
3042 ui.expandpath('default-push', 'default'))
3044 ui.expandpath('default-push', 'default'))
3043 other = hg.repository(cmdutil.remoteui(repo, {}), dest)
3045 other = hg.repository(cmdutil.remoteui(repo, {}), dest)
3044 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3046 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3045 repo.ui.pushbuffer()
3047 repo.ui.pushbuffer()
3046 o = repo.findoutgoing(other)
3048 o = repo.findoutgoing(other)
3047 repo.ui.popbuffer()
3049 repo.ui.popbuffer()
3048 o = repo.changelog.nodesbetween(o, revs)[0]
3050 o = repo.changelog.nodesbetween(o, revs)[0]
3049 if o:
3051 if o:
3050 t.append(_('%d outgoing') % len(o))
3052 t.append(_('%d outgoing') % len(o))
3051
3053
3052 if t:
3054 if t:
3053 ui.write(_('remote: %s\n') % (', '.join(t)))
3055 ui.write(_('remote: %s\n') % (', '.join(t)))
3054 else:
3056 else:
3055 ui.status(_('remote: (synced)\n'))
3057 ui.status(_('remote: (synced)\n'))
3056
3058
3057 def tag(ui, repo, name1, *names, **opts):
3059 def tag(ui, repo, name1, *names, **opts):
3058 """add one or more tags for the current or given revision
3060 """add one or more tags for the current or given revision
3059
3061
3060 Name a particular revision using <name>.
3062 Name a particular revision using <name>.
3061
3063
3062 Tags are used to name particular revisions of the repository and are
3064 Tags are used to name particular revisions of the repository and are
3063 very useful to compare different revisions, to go back to significant
3065 very useful to compare different revisions, to go back to significant
3064 earlier versions or to mark branch points as releases, etc.
3066 earlier versions or to mark branch points as releases, etc.
3065
3067
3066 If no revision is given, the parent of the working directory is
3068 If no revision is given, the parent of the working directory is
3067 used, or tip if no revision is checked out.
3069 used, or tip if no revision is checked out.
3068
3070
3069 To facilitate version control, distribution, and merging of tags,
3071 To facilitate version control, distribution, and merging of tags,
3070 they are stored as a file named ".hgtags" which is managed
3072 they are stored as a file named ".hgtags" which is managed
3071 similarly to other project files and can be hand-edited if
3073 similarly to other project files and can be hand-edited if
3072 necessary. The file '.hg/localtags' is used for local tags (not
3074 necessary. The file '.hg/localtags' is used for local tags (not
3073 shared among repositories).
3075 shared among repositories).
3074
3076
3075 See 'hg help dates' for a list of formats valid for -d/--date.
3077 See 'hg help dates' for a list of formats valid for -d/--date.
3076 """
3078 """
3077
3079
3078 rev_ = "."
3080 rev_ = "."
3079 names = (name1,) + names
3081 names = (name1,) + names
3080 if len(names) != len(set(names)):
3082 if len(names) != len(set(names)):
3081 raise util.Abort(_('tag names must be unique'))
3083 raise util.Abort(_('tag names must be unique'))
3082 for n in names:
3084 for n in names:
3083 if n in ['tip', '.', 'null']:
3085 if n in ['tip', '.', 'null']:
3084 raise util.Abort(_('the name \'%s\' is reserved') % n)
3086 raise util.Abort(_('the name \'%s\' is reserved') % n)
3085 if opts.get('rev') and opts.get('remove'):
3087 if opts.get('rev') and opts.get('remove'):
3086 raise util.Abort(_("--rev and --remove are incompatible"))
3088 raise util.Abort(_("--rev and --remove are incompatible"))
3087 if opts.get('rev'):
3089 if opts.get('rev'):
3088 rev_ = opts['rev']
3090 rev_ = opts['rev']
3089 message = opts.get('message')
3091 message = opts.get('message')
3090 if opts.get('remove'):
3092 if opts.get('remove'):
3091 expectedtype = opts.get('local') and 'local' or 'global'
3093 expectedtype = opts.get('local') and 'local' or 'global'
3092 for n in names:
3094 for n in names:
3093 if not repo.tagtype(n):
3095 if not repo.tagtype(n):
3094 raise util.Abort(_('tag \'%s\' does not exist') % n)
3096 raise util.Abort(_('tag \'%s\' does not exist') % n)
3095 if repo.tagtype(n) != expectedtype:
3097 if repo.tagtype(n) != expectedtype:
3096 if expectedtype == 'global':
3098 if expectedtype == 'global':
3097 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3099 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3098 else:
3100 else:
3099 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3101 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3100 rev_ = nullid
3102 rev_ = nullid
3101 if not message:
3103 if not message:
3102 # we don't translate commit messages
3104 # we don't translate commit messages
3103 message = 'Removed tag %s' % ', '.join(names)
3105 message = 'Removed tag %s' % ', '.join(names)
3104 elif not opts.get('force'):
3106 elif not opts.get('force'):
3105 for n in names:
3107 for n in names:
3106 if n in repo.tags():
3108 if n in repo.tags():
3107 raise util.Abort(_('tag \'%s\' already exists '
3109 raise util.Abort(_('tag \'%s\' already exists '
3108 '(use -f to force)') % n)
3110 '(use -f to force)') % n)
3109 if not rev_ and repo.dirstate.parents()[1] != nullid:
3111 if not rev_ and repo.dirstate.parents()[1] != nullid:
3110 raise util.Abort(_('uncommitted merge - please provide a '
3112 raise util.Abort(_('uncommitted merge - please provide a '
3111 'specific revision'))
3113 'specific revision'))
3112 r = repo[rev_].node()
3114 r = repo[rev_].node()
3113
3115
3114 if not message:
3116 if not message:
3115 # we don't translate commit messages
3117 # we don't translate commit messages
3116 message = ('Added tag %s for changeset %s' %
3118 message = ('Added tag %s for changeset %s' %
3117 (', '.join(names), short(r)))
3119 (', '.join(names), short(r)))
3118
3120
3119 date = opts.get('date')
3121 date = opts.get('date')
3120 if date:
3122 if date:
3121 date = util.parsedate(date)
3123 date = util.parsedate(date)
3122
3124
3123 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3125 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3124
3126
3125 def tags(ui, repo):
3127 def tags(ui, repo):
3126 """list repository tags
3128 """list repository tags
3127
3129
3128 This lists both regular and local tags. When the -v/--verbose
3130 This lists both regular and local tags. When the -v/--verbose
3129 switch is used, a third column "local" is printed for local tags.
3131 switch is used, a third column "local" is printed for local tags.
3130 """
3132 """
3131
3133
3132 hexfunc = ui.debugflag and hex or short
3134 hexfunc = ui.debugflag and hex or short
3133 tagtype = ""
3135 tagtype = ""
3134
3136
3135 for t, n in reversed(repo.tagslist()):
3137 for t, n in reversed(repo.tagslist()):
3136 if ui.quiet:
3138 if ui.quiet:
3137 ui.write("%s\n" % t)
3139 ui.write("%s\n" % t)
3138 continue
3140 continue
3139
3141
3140 try:
3142 try:
3141 hn = hexfunc(n)
3143 hn = hexfunc(n)
3142 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3144 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3143 except error.LookupError:
3145 except error.LookupError:
3144 r = " ?:%s" % hn
3146 r = " ?:%s" % hn
3145 else:
3147 else:
3146 spaces = " " * (30 - encoding.colwidth(t))
3148 spaces = " " * (30 - encoding.colwidth(t))
3147 if ui.verbose:
3149 if ui.verbose:
3148 if repo.tagtype(t) == 'local':
3150 if repo.tagtype(t) == 'local':
3149 tagtype = " local"
3151 tagtype = " local"
3150 else:
3152 else:
3151 tagtype = ""
3153 tagtype = ""
3152 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3154 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3153
3155
3154 def tip(ui, repo, **opts):
3156 def tip(ui, repo, **opts):
3155 """show the tip revision
3157 """show the tip revision
3156
3158
3157 The tip revision (usually just called the tip) is the changeset
3159 The tip revision (usually just called the tip) is the changeset
3158 most recently added to the repository (and therefore the most
3160 most recently added to the repository (and therefore the most
3159 recently changed head).
3161 recently changed head).
3160
3162
3161 If you have just made a commit, that commit will be the tip. If
3163 If you have just made a commit, that commit will be the tip. If
3162 you have just pulled changes from another repository, the tip of
3164 you have just pulled changes from another repository, the tip of
3163 that repository becomes the current tip. The "tip" tag is special
3165 that repository becomes the current tip. The "tip" tag is special
3164 and cannot be renamed or assigned to a different changeset.
3166 and cannot be renamed or assigned to a different changeset.
3165 """
3167 """
3166 displayer = cmdutil.show_changeset(ui, repo, opts)
3168 displayer = cmdutil.show_changeset(ui, repo, opts)
3167 displayer.show(repo[len(repo) - 1])
3169 displayer.show(repo[len(repo) - 1])
3168 displayer.close()
3170 displayer.close()
3169
3171
3170 def unbundle(ui, repo, fname1, *fnames, **opts):
3172 def unbundle(ui, repo, fname1, *fnames, **opts):
3171 """apply one or more changegroup files
3173 """apply one or more changegroup files
3172
3174
3173 Apply one or more compressed changegroup files generated by the
3175 Apply one or more compressed changegroup files generated by the
3174 bundle command.
3176 bundle command.
3175 """
3177 """
3176 fnames = (fname1,) + fnames
3178 fnames = (fname1,) + fnames
3177
3179
3178 lock = repo.lock()
3180 lock = repo.lock()
3179 try:
3181 try:
3180 for fname in fnames:
3182 for fname in fnames:
3181 f = url.open(ui, fname)
3183 f = url.open(ui, fname)
3182 gen = changegroup.readbundle(f, fname)
3184 gen = changegroup.readbundle(f, fname)
3183 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
3185 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
3184 finally:
3186 finally:
3185 lock.release()
3187 lock.release()
3186
3188
3187 return postincoming(ui, repo, modheads, opts.get('update'), None)
3189 return postincoming(ui, repo, modheads, opts.get('update'), None)
3188
3190
3189 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3191 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3190 """update working directory
3192 """update working directory
3191
3193
3192 Update the repository's working directory to the specified
3194 Update the repository's working directory to the specified
3193 changeset.
3195 changeset.
3194
3196
3195 If no changeset is specified, attempt to update to the head of the
3197 If no changeset is specified, attempt to update to the head of the
3196 current branch. If this head is a descendant of the working
3198 current branch. If this head is a descendant of the working
3197 directory's parent, update to it, otherwise abort.
3199 directory's parent, update to it, otherwise abort.
3198
3200
3199 The following rules apply when the working directory contains
3201 The following rules apply when the working directory contains
3200 uncommitted changes:
3202 uncommitted changes:
3201
3203
3202 1. If neither -c/--check nor -C/--clean is specified, and if
3204 1. If neither -c/--check nor -C/--clean is specified, and if
3203 the requested changeset is an ancestor or descendant of
3205 the requested changeset is an ancestor or descendant of
3204 the working directory's parent, the uncommitted changes
3206 the working directory's parent, the uncommitted changes
3205 are merged into the requested changeset and the merged
3207 are merged into the requested changeset and the merged
3206 result is left uncommitted. If the requested changeset is
3208 result is left uncommitted. If the requested changeset is
3207 not an ancestor or descendant (that is, it is on another
3209 not an ancestor or descendant (that is, it is on another
3208 branch), the update is aborted and the uncommitted changes
3210 branch), the update is aborted and the uncommitted changes
3209 are preserved.
3211 are preserved.
3210
3212
3211 2. With the -c/--check option, the update is aborted and the
3213 2. With the -c/--check option, the update is aborted and the
3212 uncommitted changes are preserved.
3214 uncommitted changes are preserved.
3213
3215
3214 3. With the -C/--clean option, uncommitted changes are discarded and
3216 3. With the -C/--clean option, uncommitted changes are discarded and
3215 the working directory is updated to the requested changeset.
3217 the working directory is updated to the requested changeset.
3216
3218
3217 Use null as the changeset to remove the working directory (like 'hg
3219 Use null as the changeset to remove the working directory (like 'hg
3218 clone -U').
3220 clone -U').
3219
3221
3220 If you want to update just one file to an older changeset, use 'hg revert'.
3222 If you want to update just one file to an older changeset, use 'hg revert'.
3221
3223
3222 See 'hg help dates' for a list of formats valid for -d/--date.
3224 See 'hg help dates' for a list of formats valid for -d/--date.
3223 """
3225 """
3224 if rev and node:
3226 if rev and node:
3225 raise util.Abort(_("please specify just one revision"))
3227 raise util.Abort(_("please specify just one revision"))
3226
3228
3227 if not rev:
3229 if not rev:
3228 rev = node
3230 rev = node
3229
3231
3230 if check and clean:
3232 if check and clean:
3231 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3233 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3232
3234
3233 if check:
3235 if check:
3234 # we could use dirty() but we can ignore merge and branch trivia
3236 # we could use dirty() but we can ignore merge and branch trivia
3235 c = repo[None]
3237 c = repo[None]
3236 if c.modified() or c.added() or c.removed():
3238 if c.modified() or c.added() or c.removed():
3237 raise util.Abort(_("uncommitted local changes"))
3239 raise util.Abort(_("uncommitted local changes"))
3238
3240
3239 if date:
3241 if date:
3240 if rev:
3242 if rev:
3241 raise util.Abort(_("you can't specify a revision and a date"))
3243 raise util.Abort(_("you can't specify a revision and a date"))
3242 rev = cmdutil.finddate(ui, repo, date)
3244 rev = cmdutil.finddate(ui, repo, date)
3243
3245
3244 if clean or check:
3246 if clean or check:
3245 return hg.clean(repo, rev)
3247 return hg.clean(repo, rev)
3246 else:
3248 else:
3247 return hg.update(repo, rev)
3249 return hg.update(repo, rev)
3248
3250
3249 def verify(ui, repo):
3251 def verify(ui, repo):
3250 """verify the integrity of the repository
3252 """verify the integrity of the repository
3251
3253
3252 Verify the integrity of the current repository.
3254 Verify the integrity of the current repository.
3253
3255
3254 This will perform an extensive check of the repository's
3256 This will perform an extensive check of the repository's
3255 integrity, validating the hashes and checksums of each entry in
3257 integrity, validating the hashes and checksums of each entry in
3256 the changelog, manifest, and tracked files, as well as the
3258 the changelog, manifest, and tracked files, as well as the
3257 integrity of their crosslinks and indices.
3259 integrity of their crosslinks and indices.
3258 """
3260 """
3259 return hg.verify(repo)
3261 return hg.verify(repo)
3260
3262
3261 def version_(ui):
3263 def version_(ui):
3262 """output version and copyright information"""
3264 """output version and copyright information"""
3263 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3265 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3264 % util.version())
3266 % util.version())
3265 ui.status(_(
3267 ui.status(_(
3266 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3268 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3267 "This is free software; see the source for copying conditions. "
3269 "This is free software; see the source for copying conditions. "
3268 "There is NO\nwarranty; "
3270 "There is NO\nwarranty; "
3269 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3271 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3270 ))
3272 ))
3271
3273
3272 # Command options and aliases are listed here, alphabetically
3274 # Command options and aliases are listed here, alphabetically
3273
3275
3274 globalopts = [
3276 globalopts = [
3275 ('R', 'repository', '',
3277 ('R', 'repository', '',
3276 _('repository root directory or name of overlay bundle file')),
3278 _('repository root directory or name of overlay bundle file')),
3277 ('', 'cwd', '', _('change working directory')),
3279 ('', 'cwd', '', _('change working directory')),
3278 ('y', 'noninteractive', None,
3280 ('y', 'noninteractive', None,
3279 _('do not prompt, assume \'yes\' for any required answers')),
3281 _('do not prompt, assume \'yes\' for any required answers')),
3280 ('q', 'quiet', None, _('suppress output')),
3282 ('q', 'quiet', None, _('suppress output')),
3281 ('v', 'verbose', None, _('enable additional output')),
3283 ('v', 'verbose', None, _('enable additional output')),
3282 ('', 'config', [], _('set/override config option')),
3284 ('', 'config', [], _('set/override config option')),
3283 ('', 'debug', None, _('enable debugging output')),
3285 ('', 'debug', None, _('enable debugging output')),
3284 ('', 'debugger', None, _('start debugger')),
3286 ('', 'debugger', None, _('start debugger')),
3285 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3287 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3286 ('', 'encodingmode', encoding.encodingmode,
3288 ('', 'encodingmode', encoding.encodingmode,
3287 _('set the charset encoding mode')),
3289 _('set the charset encoding mode')),
3288 ('', 'traceback', None, _('always print a traceback on exception')),
3290 ('', 'traceback', None, _('always print a traceback on exception')),
3289 ('', 'time', None, _('time how long the command takes')),
3291 ('', 'time', None, _('time how long the command takes')),
3290 ('', 'profile', None, _('print command execution profile')),
3292 ('', 'profile', None, _('print command execution profile')),
3291 ('', 'version', None, _('output version information and exit')),
3293 ('', 'version', None, _('output version information and exit')),
3292 ('h', 'help', None, _('display help and exit')),
3294 ('h', 'help', None, _('display help and exit')),
3293 ]
3295 ]
3294
3296
3295 dryrunopts = [('n', 'dry-run', None,
3297 dryrunopts = [('n', 'dry-run', None,
3296 _('do not perform actions, just print output'))]
3298 _('do not perform actions, just print output'))]
3297
3299
3298 remoteopts = [
3300 remoteopts = [
3299 ('e', 'ssh', '', _('specify ssh command to use')),
3301 ('e', 'ssh', '', _('specify ssh command to use')),
3300 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3302 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3301 ]
3303 ]
3302
3304
3303 walkopts = [
3305 walkopts = [
3304 ('I', 'include', [], _('include names matching the given patterns')),
3306 ('I', 'include', [], _('include names matching the given patterns')),
3305 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3307 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3306 ]
3308 ]
3307
3309
3308 commitopts = [
3310 commitopts = [
3309 ('m', 'message', '', _('use <text> as commit message')),
3311 ('m', 'message', '', _('use <text> as commit message')),
3310 ('l', 'logfile', '', _('read commit message from <file>')),
3312 ('l', 'logfile', '', _('read commit message from <file>')),
3311 ]
3313 ]
3312
3314
3313 commitopts2 = [
3315 commitopts2 = [
3314 ('d', 'date', '', _('record datecode as commit date')),
3316 ('d', 'date', '', _('record datecode as commit date')),
3315 ('u', 'user', '', _('record the specified user as committer')),
3317 ('u', 'user', '', _('record the specified user as committer')),
3316 ]
3318 ]
3317
3319
3318 templateopts = [
3320 templateopts = [
3319 ('', 'style', '', _('display using template map file')),
3321 ('', 'style', '', _('display using template map file')),
3320 ('', 'template', '', _('display with template')),
3322 ('', 'template', '', _('display with template')),
3321 ]
3323 ]
3322
3324
3323 logopts = [
3325 logopts = [
3324 ('p', 'patch', None, _('show patch')),
3326 ('p', 'patch', None, _('show patch')),
3325 ('g', 'git', None, _('use git extended diff format')),
3327 ('g', 'git', None, _('use git extended diff format')),
3326 ('l', 'limit', '', _('limit number of changes displayed')),
3328 ('l', 'limit', '', _('limit number of changes displayed')),
3327 ('M', 'no-merges', None, _('do not show merges')),
3329 ('M', 'no-merges', None, _('do not show merges')),
3328 ] + templateopts
3330 ] + templateopts
3329
3331
3330 diffopts = [
3332 diffopts = [
3331 ('a', 'text', None, _('treat all files as text')),
3333 ('a', 'text', None, _('treat all files as text')),
3332 ('g', 'git', None, _('use git extended diff format')),
3334 ('g', 'git', None, _('use git extended diff format')),
3333 ('', 'nodates', None, _('omit dates from diff headers'))
3335 ('', 'nodates', None, _('omit dates from diff headers'))
3334 ]
3336 ]
3335
3337
3336 diffopts2 = [
3338 diffopts2 = [
3337 ('p', 'show-function', None, _('show which function each change is in')),
3339 ('p', 'show-function', None, _('show which function each change is in')),
3338 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3340 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3339 ('w', 'ignore-all-space', None,
3341 ('w', 'ignore-all-space', None,
3340 _('ignore white space when comparing lines')),
3342 _('ignore white space when comparing lines')),
3341 ('b', 'ignore-space-change', None,
3343 ('b', 'ignore-space-change', None,
3342 _('ignore changes in the amount of white space')),
3344 _('ignore changes in the amount of white space')),
3343 ('B', 'ignore-blank-lines', None,
3345 ('B', 'ignore-blank-lines', None,
3344 _('ignore changes whose lines are all blank')),
3346 _('ignore changes whose lines are all blank')),
3345 ('U', 'unified', '', _('number of lines of context to show')),
3347 ('U', 'unified', '', _('number of lines of context to show')),
3346 ('', 'stat', None, _('output diffstat-style summary of changes')),
3348 ('', 'stat', None, _('output diffstat-style summary of changes')),
3347 ]
3349 ]
3348
3350
3349 similarityopts = [
3351 similarityopts = [
3350 ('s', 'similarity', '',
3352 ('s', 'similarity', '',
3351 _('guess renamed files by similarity (0<=s<=100)'))
3353 _('guess renamed files by similarity (0<=s<=100)'))
3352 ]
3354 ]
3353
3355
3354 table = {
3356 table = {
3355 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3357 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3356 "addremove":
3358 "addremove":
3357 (addremove, similarityopts + walkopts + dryrunopts,
3359 (addremove, similarityopts + walkopts + dryrunopts,
3358 _('[OPTION]... [FILE]...')),
3360 _('[OPTION]... [FILE]...')),
3359 "^annotate|blame":
3361 "^annotate|blame":
3360 (annotate,
3362 (annotate,
3361 [('r', 'rev', '', _('annotate the specified revision')),
3363 [('r', 'rev', '', _('annotate the specified revision')),
3362 ('', 'follow', None, _('follow copies and renames (DEPRECATED)')),
3364 ('', 'follow', None, _('follow copies and renames (DEPRECATED)')),
3363 ('', 'no-follow', None, _("don't follow copies and renames")),
3365 ('', 'no-follow', None, _("don't follow copies and renames")),
3364 ('a', 'text', None, _('treat all files as text')),
3366 ('a', 'text', None, _('treat all files as text')),
3365 ('u', 'user', None, _('list the author (long with -v)')),
3367 ('u', 'user', None, _('list the author (long with -v)')),
3366 ('f', 'file', None, _('list the filename')),
3368 ('f', 'file', None, _('list the filename')),
3367 ('d', 'date', None, _('list the date (short with -q)')),
3369 ('d', 'date', None, _('list the date (short with -q)')),
3368 ('n', 'number', None, _('list the revision number (default)')),
3370 ('n', 'number', None, _('list the revision number (default)')),
3369 ('c', 'changeset', None, _('list the changeset')),
3371 ('c', 'changeset', None, _('list the changeset')),
3370 ('l', 'line-number', None,
3372 ('l', 'line-number', None,
3371 _('show line number at the first appearance'))
3373 _('show line number at the first appearance'))
3372 ] + walkopts,
3374 ] + walkopts,
3373 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3375 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3374 "archive":
3376 "archive":
3375 (archive,
3377 (archive,
3376 [('', 'no-decode', None, _('do not pass files through decoders')),
3378 [('', 'no-decode', None, _('do not pass files through decoders')),
3377 ('p', 'prefix', '', _('directory prefix for files in archive')),
3379 ('p', 'prefix', '', _('directory prefix for files in archive')),
3378 ('r', 'rev', '', _('revision to distribute')),
3380 ('r', 'rev', '', _('revision to distribute')),
3379 ('t', 'type', '', _('type of distribution to create')),
3381 ('t', 'type', '', _('type of distribution to create')),
3380 ] + walkopts,
3382 ] + walkopts,
3381 _('[OPTION]... DEST')),
3383 _('[OPTION]... DEST')),
3382 "backout":
3384 "backout":
3383 (backout,
3385 (backout,
3384 [('', 'merge', None,
3386 [('', 'merge', None,
3385 _('merge with old dirstate parent after backout')),
3387 _('merge with old dirstate parent after backout')),
3386 ('', 'parent', '', _('parent to choose when backing out merge')),
3388 ('', 'parent', '', _('parent to choose when backing out merge')),
3387 ('r', 'rev', '', _('revision to backout')),
3389 ('r', 'rev', '', _('revision to backout')),
3388 ] + walkopts + commitopts + commitopts2,
3390 ] + walkopts + commitopts + commitopts2,
3389 _('[OPTION]... [-r] REV')),
3391 _('[OPTION]... [-r] REV')),
3390 "bisect":
3392 "bisect":
3391 (bisect,
3393 (bisect,
3392 [('r', 'reset', False, _('reset bisect state')),
3394 [('r', 'reset', False, _('reset bisect state')),
3393 ('g', 'good', False, _('mark changeset good')),
3395 ('g', 'good', False, _('mark changeset good')),
3394 ('b', 'bad', False, _('mark changeset bad')),
3396 ('b', 'bad', False, _('mark changeset bad')),
3395 ('s', 'skip', False, _('skip testing changeset')),
3397 ('s', 'skip', False, _('skip testing changeset')),
3396 ('c', 'command', '', _('use command to check changeset state')),
3398 ('c', 'command', '', _('use command to check changeset state')),
3397 ('U', 'noupdate', False, _('do not update to target'))],
3399 ('U', 'noupdate', False, _('do not update to target'))],
3398 _("[-gbsr] [-U] [-c CMD] [REV]")),
3400 _("[-gbsr] [-U] [-c CMD] [REV]")),
3399 "branch":
3401 "branch":
3400 (branch,
3402 (branch,
3401 [('f', 'force', None,
3403 [('f', 'force', None,
3402 _('set branch name even if it shadows an existing branch')),
3404 _('set branch name even if it shadows an existing branch')),
3403 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3405 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3404 _('[-fC] [NAME]')),
3406 _('[-fC] [NAME]')),
3405 "branches":
3407 "branches":
3406 (branches,
3408 (branches,
3407 [('a', 'active', False,
3409 [('a', 'active', False,
3408 _('show only branches that have unmerged heads')),
3410 _('show only branches that have unmerged heads')),
3409 ('c', 'closed', False,
3411 ('c', 'closed', False,
3410 _('show normal and closed branches'))],
3412 _('show normal and closed branches'))],
3411 _('[-ac]')),
3413 _('[-ac]')),
3412 "bundle":
3414 "bundle":
3413 (bundle,
3415 (bundle,
3414 [('f', 'force', None,
3416 [('f', 'force', None,
3415 _('run even when the destination is unrelated')),
3417 _('run even when the destination is unrelated')),
3416 ('r', 'rev', [],
3418 ('r', 'rev', [],
3417 _('a changeset intended to be added to the destination')),
3419 _('a changeset intended to be added to the destination')),
3420 ('b', 'branch', [],
3421 _('a specific branch you would like to bundle')),
3418 ('', 'base', [],
3422 ('', 'base', [],
3419 _('a base changeset assumed to be available at the destination')),
3423 _('a base changeset assumed to be available at the destination')),
3420 ('a', 'all', None, _('bundle all changesets in the repository')),
3424 ('a', 'all', None, _('bundle all changesets in the repository')),
3421 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3425 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3422 ] + remoteopts,
3426 ] + remoteopts,
3423 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3427 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3424 "cat":
3428 "cat":
3425 (cat,
3429 (cat,
3426 [('o', 'output', '', _('print output to file with formatted name')),
3430 [('o', 'output', '', _('print output to file with formatted name')),
3427 ('r', 'rev', '', _('print the given revision')),
3431 ('r', 'rev', '', _('print the given revision')),
3428 ('', 'decode', None, _('apply any matching decode filter')),
3432 ('', 'decode', None, _('apply any matching decode filter')),
3429 ] + walkopts,
3433 ] + walkopts,
3430 _('[OPTION]... FILE...')),
3434 _('[OPTION]... FILE...')),
3431 "^clone":
3435 "^clone":
3432 (clone,
3436 (clone,
3433 [('U', 'noupdate', None,
3437 [('U', 'noupdate', None,
3434 _('the clone will include an empty working copy (only a repository)')),
3438 _('the clone will include an empty working copy (only a repository)')),
3435 ('u', 'updaterev', '',
3439 ('u', 'updaterev', '',
3436 _('revision, tag or branch to check out')),
3440 _('revision, tag or branch to check out')),
3437 ('r', 'rev', [],
3441 ('r', 'rev', [],
3438 _('include the specified changeset')),
3442 _('include the specified changeset')),
3443 ('b', 'branch', [],
3444 _('clone only the specified branch')),
3439 ('', 'pull', None, _('use pull protocol to copy metadata')),
3445 ('', 'pull', None, _('use pull protocol to copy metadata')),
3440 ('', 'uncompressed', None,
3446 ('', 'uncompressed', None,
3441 _('use uncompressed transfer (fast over LAN)')),
3447 _('use uncompressed transfer (fast over LAN)')),
3442 ] + remoteopts,
3448 ] + remoteopts,
3443 _('[OPTION]... SOURCE [DEST]')),
3449 _('[OPTION]... SOURCE [DEST]')),
3444 "^commit|ci":
3450 "^commit|ci":
3445 (commit,
3451 (commit,
3446 [('A', 'addremove', None,
3452 [('A', 'addremove', None,
3447 _('mark new/missing files as added/removed before committing')),
3453 _('mark new/missing files as added/removed before committing')),
3448 ('', 'close-branch', None,
3454 ('', 'close-branch', None,
3449 _('mark a branch as closed, hiding it from the branch list')),
3455 _('mark a branch as closed, hiding it from the branch list')),
3450 ] + walkopts + commitopts + commitopts2,
3456 ] + walkopts + commitopts + commitopts2,
3451 _('[OPTION]... [FILE]...')),
3457 _('[OPTION]... [FILE]...')),
3452 "copy|cp":
3458 "copy|cp":
3453 (copy,
3459 (copy,
3454 [('A', 'after', None, _('record a copy that has already occurred')),
3460 [('A', 'after', None, _('record a copy that has already occurred')),
3455 ('f', 'force', None,
3461 ('f', 'force', None,
3456 _('forcibly copy over an existing managed file')),
3462 _('forcibly copy over an existing managed file')),
3457 ] + walkopts + dryrunopts,
3463 ] + walkopts + dryrunopts,
3458 _('[OPTION]... [SOURCE]... DEST')),
3464 _('[OPTION]... [SOURCE]... DEST')),
3459 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3465 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3460 "debugcheckstate": (debugcheckstate, [], ''),
3466 "debugcheckstate": (debugcheckstate, [], ''),
3461 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3467 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3462 "debugcomplete":
3468 "debugcomplete":
3463 (debugcomplete,
3469 (debugcomplete,
3464 [('o', 'options', None, _('show the command options'))],
3470 [('o', 'options', None, _('show the command options'))],
3465 _('[-o] CMD')),
3471 _('[-o] CMD')),
3466 "debugdate":
3472 "debugdate":
3467 (debugdate,
3473 (debugdate,
3468 [('e', 'extended', None, _('try extended date formats'))],
3474 [('e', 'extended', None, _('try extended date formats'))],
3469 _('[-e] DATE [RANGE]')),
3475 _('[-e] DATE [RANGE]')),
3470 "debugdata": (debugdata, [], _('FILE REV')),
3476 "debugdata": (debugdata, [], _('FILE REV')),
3471 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3477 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3472 "debugindex": (debugindex, [], _('FILE')),
3478 "debugindex": (debugindex, [], _('FILE')),
3473 "debugindexdot": (debugindexdot, [], _('FILE')),
3479 "debugindexdot": (debugindexdot, [], _('FILE')),
3474 "debuginstall": (debuginstall, [], ''),
3480 "debuginstall": (debuginstall, [], ''),
3475 "debugrebuildstate":
3481 "debugrebuildstate":
3476 (debugrebuildstate,
3482 (debugrebuildstate,
3477 [('r', 'rev', '', _('revision to rebuild to'))],
3483 [('r', 'rev', '', _('revision to rebuild to'))],
3478 _('[-r REV] [REV]')),
3484 _('[-r REV] [REV]')),
3479 "debugrename":
3485 "debugrename":
3480 (debugrename,
3486 (debugrename,
3481 [('r', 'rev', '', _('revision to debug'))],
3487 [('r', 'rev', '', _('revision to debug'))],
3482 _('[-r REV] FILE')),
3488 _('[-r REV] FILE')),
3483 "debugsetparents":
3489 "debugsetparents":
3484 (debugsetparents, [], _('REV1 [REV2]')),
3490 (debugsetparents, [], _('REV1 [REV2]')),
3485 "debugstate":
3491 "debugstate":
3486 (debugstate,
3492 (debugstate,
3487 [('', 'nodates', None, _('do not display the saved mtime'))],
3493 [('', 'nodates', None, _('do not display the saved mtime'))],
3488 _('[OPTION]...')),
3494 _('[OPTION]...')),
3489 "debugsub":
3495 "debugsub":
3490 (debugsub,
3496 (debugsub,
3491 [('r', 'rev', '', _('revision to check'))],
3497 [('r', 'rev', '', _('revision to check'))],
3492 _('[-r REV] [REV]')),
3498 _('[-r REV] [REV]')),
3493 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3499 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3494 "^diff":
3500 "^diff":
3495 (diff,
3501 (diff,
3496 [('r', 'rev', [], _('revision')),
3502 [('r', 'rev', [], _('revision')),
3497 ('c', 'change', '', _('change made by revision'))
3503 ('c', 'change', '', _('change made by revision'))
3498 ] + diffopts + diffopts2 + walkopts,
3504 ] + diffopts + diffopts2 + walkopts,
3499 _('[OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3505 _('[OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3500 "^export":
3506 "^export":
3501 (export,
3507 (export,
3502 [('o', 'output', '', _('print output to file with formatted name')),
3508 [('o', 'output', '', _('print output to file with formatted name')),
3503 ('', 'switch-parent', None, _('diff against the second parent')),
3509 ('', 'switch-parent', None, _('diff against the second parent')),
3504 ('r', 'rev', [], _('revisions to export')),
3510 ('r', 'rev', [], _('revisions to export')),
3505 ] + diffopts,
3511 ] + diffopts,
3506 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3512 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3507 "^forget":
3513 "^forget":
3508 (forget,
3514 (forget,
3509 [] + walkopts,
3515 [] + walkopts,
3510 _('[OPTION]... FILE...')),
3516 _('[OPTION]... FILE...')),
3511 "grep":
3517 "grep":
3512 (grep,
3518 (grep,
3513 [('0', 'print0', None, _('end fields with NUL')),
3519 [('0', 'print0', None, _('end fields with NUL')),
3514 ('', 'all', None, _('print all revisions that match')),
3520 ('', 'all', None, _('print all revisions that match')),
3515 ('f', 'follow', None,
3521 ('f', 'follow', None,
3516 _('follow changeset history,'
3522 _('follow changeset history,'
3517 ' or file history across copies and renames')),
3523 ' or file history across copies and renames')),
3518 ('i', 'ignore-case', None, _('ignore case when matching')),
3524 ('i', 'ignore-case', None, _('ignore case when matching')),
3519 ('l', 'files-with-matches', None,
3525 ('l', 'files-with-matches', None,
3520 _('print only filenames and revisions that match')),
3526 _('print only filenames and revisions that match')),
3521 ('n', 'line-number', None, _('print matching line numbers')),
3527 ('n', 'line-number', None, _('print matching line numbers')),
3522 ('r', 'rev', [], _('search in given revision range')),
3528 ('r', 'rev', [], _('search in given revision range')),
3523 ('u', 'user', None, _('list the author (long with -v)')),
3529 ('u', 'user', None, _('list the author (long with -v)')),
3524 ('d', 'date', None, _('list the date (short with -q)')),
3530 ('d', 'date', None, _('list the date (short with -q)')),
3525 ] + walkopts,
3531 ] + walkopts,
3526 _('[OPTION]... PATTERN [FILE]...')),
3532 _('[OPTION]... PATTERN [FILE]...')),
3527 "heads":
3533 "heads":
3528 (heads,
3534 (heads,
3529 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3535 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3530 ('t', 'topo', False, _('show topological heads only')),
3536 ('t', 'topo', False, _('show topological heads only')),
3531 ('a', 'active', False,
3537 ('a', 'active', False,
3532 _('show active branchheads only [DEPRECATED]')),
3538 _('show active branchheads only [DEPRECATED]')),
3533 ('c', 'closed', False,
3539 ('c', 'closed', False,
3534 _('show normal and closed branch heads')),
3540 _('show normal and closed branch heads')),
3535 ] + templateopts,
3541 ] + templateopts,
3536 _('[-ac] [-r STARTREV] [REV]...')),
3542 _('[-ac] [-r STARTREV] [REV]...')),
3537 "help": (help_, [], _('[TOPIC]')),
3543 "help": (help_, [], _('[TOPIC]')),
3538 "identify|id":
3544 "identify|id":
3539 (identify,
3545 (identify,
3540 [('r', 'rev', '', _('identify the specified revision')),
3546 [('r', 'rev', '', _('identify the specified revision')),
3541 ('n', 'num', None, _('show local revision number')),
3547 ('n', 'num', None, _('show local revision number')),
3542 ('i', 'id', None, _('show global revision id')),
3548 ('i', 'id', None, _('show global revision id')),
3543 ('b', 'branch', None, _('show branch')),
3549 ('b', 'branch', None, _('show branch')),
3544 ('t', 'tags', None, _('show tags'))],
3550 ('t', 'tags', None, _('show tags'))],
3545 _('[-nibt] [-r REV] [SOURCE]')),
3551 _('[-nibt] [-r REV] [SOURCE]')),
3546 "import|patch":
3552 "import|patch":
3547 (import_,
3553 (import_,
3548 [('p', 'strip', 1,
3554 [('p', 'strip', 1,
3549 _('directory strip option for patch. This has the same '
3555 _('directory strip option for patch. This has the same '
3550 'meaning as the corresponding patch option')),
3556 'meaning as the corresponding patch option')),
3551 ('b', 'base', '', _('base path')),
3557 ('b', 'base', '', _('base path')),
3552 ('f', 'force', None,
3558 ('f', 'force', None,
3553 _('skip check for outstanding uncommitted changes')),
3559 _('skip check for outstanding uncommitted changes')),
3554 ('', 'no-commit', None,
3560 ('', 'no-commit', None,
3555 _("don't commit, just update the working directory")),
3561 _("don't commit, just update the working directory")),
3556 ('', 'exact', None,
3562 ('', 'exact', None,
3557 _('apply patch to the nodes from which it was generated')),
3563 _('apply patch to the nodes from which it was generated')),
3558 ('', 'import-branch', None,
3564 ('', 'import-branch', None,
3559 _('use any branch information in patch (implied by --exact)'))] +
3565 _('use any branch information in patch (implied by --exact)'))] +
3560 commitopts + commitopts2 + similarityopts,
3566 commitopts + commitopts2 + similarityopts,
3561 _('[OPTION]... PATCH...')),
3567 _('[OPTION]... PATCH...')),
3562 "incoming|in":
3568 "incoming|in":
3563 (incoming,
3569 (incoming,
3564 [('f', 'force', None,
3570 [('f', 'force', None,
3565 _('run even if remote repository is unrelated')),
3571 _('run even if remote repository is unrelated')),
3566 ('n', 'newest-first', None, _('show newest record first')),
3572 ('n', 'newest-first', None, _('show newest record first')),
3567 ('', 'bundle', '', _('file to store the bundles into')),
3573 ('', 'bundle', '', _('file to store the bundles into')),
3568 ('r', 'rev', [],
3574 ('r', 'rev', [],
3569 _('a remote changeset intended to be added')),
3575 _('a remote changeset intended to be added')),
3576 ('b', 'branch', [],
3577 _('a specific branch you would like to pull')),
3570 ] + logopts + remoteopts,
3578 ] + logopts + remoteopts,
3571 _('[-p] [-n] [-M] [-f] [-r REV]...'
3579 _('[-p] [-n] [-M] [-f] [-r REV]...'
3572 ' [--bundle FILENAME] [SOURCE]')),
3580 ' [--bundle FILENAME] [SOURCE]')),
3573 "^init":
3581 "^init":
3574 (init,
3582 (init,
3575 remoteopts,
3583 remoteopts,
3576 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3584 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3577 "locate":
3585 "locate":
3578 (locate,
3586 (locate,
3579 [('r', 'rev', '', _('search the repository as it is in REV')),
3587 [('r', 'rev', '', _('search the repository as it is in REV')),
3580 ('0', 'print0', None,
3588 ('0', 'print0', None,
3581 _('end filenames with NUL, for use with xargs')),
3589 _('end filenames with NUL, for use with xargs')),
3582 ('f', 'fullpath', None,
3590 ('f', 'fullpath', None,
3583 _('print complete paths from the filesystem root')),
3591 _('print complete paths from the filesystem root')),
3584 ] + walkopts,
3592 ] + walkopts,
3585 _('[OPTION]... [PATTERN]...')),
3593 _('[OPTION]... [PATTERN]...')),
3586 "^log|history":
3594 "^log|history":
3587 (log,
3595 (log,
3588 [('f', 'follow', None,
3596 [('f', 'follow', None,
3589 _('follow changeset history,'
3597 _('follow changeset history,'
3590 ' or file history across copies and renames')),
3598 ' or file history across copies and renames')),
3591 ('', 'follow-first', None,
3599 ('', 'follow-first', None,
3592 _('only follow the first parent of merge changesets')),
3600 _('only follow the first parent of merge changesets')),
3593 ('d', 'date', '', _('show revisions matching date spec')),
3601 ('d', 'date', '', _('show revisions matching date spec')),
3594 ('C', 'copies', None, _('show copied files')),
3602 ('C', 'copies', None, _('show copied files')),
3595 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3603 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3596 ('r', 'rev', [], _('show the specified revision or range')),
3604 ('r', 'rev', [], _('show the specified revision or range')),
3597 ('', 'removed', None, _('include revisions where files were removed')),
3605 ('', 'removed', None, _('include revisions where files were removed')),
3598 ('m', 'only-merges', None, _('show only merges')),
3606 ('m', 'only-merges', None, _('show only merges')),
3599 ('u', 'user', [], _('revisions committed by user')),
3607 ('u', 'user', [], _('revisions committed by user')),
3600 ('b', 'only-branch', [],
3608 ('b', 'only-branch', [],
3601 _('show only changesets within the given named branch')),
3609 _('show only changesets within the given named branch')),
3602 ('P', 'prune', [],
3610 ('P', 'prune', [],
3603 _('do not display revision or any of its ancestors')),
3611 _('do not display revision or any of its ancestors')),
3604 ] + logopts + walkopts,
3612 ] + logopts + walkopts,
3605 _('[OPTION]... [FILE]')),
3613 _('[OPTION]... [FILE]')),
3606 "manifest":
3614 "manifest":
3607 (manifest,
3615 (manifest,
3608 [('r', 'rev', '', _('revision to display'))],
3616 [('r', 'rev', '', _('revision to display'))],
3609 _('[-r REV]')),
3617 _('[-r REV]')),
3610 "^merge":
3618 "^merge":
3611 (merge,
3619 (merge,
3612 [('f', 'force', None, _('force a merge with outstanding changes')),
3620 [('f', 'force', None, _('force a merge with outstanding changes')),
3613 ('r', 'rev', '', _('revision to merge')),
3621 ('r', 'rev', '', _('revision to merge')),
3614 ('P', 'preview', None,
3622 ('P', 'preview', None,
3615 _('review revisions to merge (no merge is performed)'))],
3623 _('review revisions to merge (no merge is performed)'))],
3616 _('[-P] [-f] [[-r] REV]')),
3624 _('[-P] [-f] [[-r] REV]')),
3617 "outgoing|out":
3625 "outgoing|out":
3618 (outgoing,
3626 (outgoing,
3619 [('f', 'force', None,
3627 [('f', 'force', None,
3620 _('run even when the destination is unrelated')),
3628 _('run even when the destination is unrelated')),
3621 ('r', 'rev', [],
3629 ('r', 'rev', [],
3622 _('a changeset intended to be included in the destination')),
3630 _('a changeset intended to be included in the destination')),
3623 ('n', 'newest-first', None, _('show newest record first')),
3631 ('n', 'newest-first', None, _('show newest record first')),
3632 ('b', 'branch', [],
3633 _('a specific branch you would like to push')),
3624 ] + logopts + remoteopts,
3634 ] + logopts + remoteopts,
3625 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3635 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3626 "parents":
3636 "parents":
3627 (parents,
3637 (parents,
3628 [('r', 'rev', '', _('show parents of the specified revision')),
3638 [('r', 'rev', '', _('show parents of the specified revision')),
3629 ] + templateopts,
3639 ] + templateopts,
3630 _('[-r REV] [FILE]')),
3640 _('[-r REV] [FILE]')),
3631 "paths": (paths, [], _('[NAME]')),
3641 "paths": (paths, [], _('[NAME]')),
3632 "^pull":
3642 "^pull":
3633 (pull,
3643 (pull,
3634 [('u', 'update', None,
3644 [('u', 'update', None,
3635 _('update to new branch head if changesets were pulled')),
3645 _('update to new branch head if changesets were pulled')),
3636 ('f', 'force', None,
3646 ('f', 'force', None,
3637 _('run even when remote repository is unrelated')),
3647 _('run even when remote repository is unrelated')),
3638 ('r', 'rev', [],
3648 ('r', 'rev', [],
3639 _('a remote changeset intended to be added')),
3649 _('a remote changeset intended to be added')),
3650 ('b', 'branch', [],
3651 _('a specific branch you would like to pull')),
3640 ] + remoteopts,
3652 ] + remoteopts,
3641 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3653 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3642 "^push":
3654 "^push":
3643 (push,
3655 (push,
3644 [('f', 'force', None, _('force push')),
3656 [('f', 'force', None, _('force push')),
3645 ('r', 'rev', [],
3657 ('r', 'rev', [],
3646 _('a changeset intended to be included in the destination')),
3658 _('a changeset intended to be included in the destination')),
3659 ('b', 'branch', [],
3660 _('a specific branch you would like to push')),
3647 ] + remoteopts,
3661 ] + remoteopts,
3648 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3662 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3649 "recover": (recover, []),
3663 "recover": (recover, []),
3650 "^remove|rm":
3664 "^remove|rm":
3651 (remove,
3665 (remove,
3652 [('A', 'after', None, _('record delete for missing files')),
3666 [('A', 'after', None, _('record delete for missing files')),
3653 ('f', 'force', None,
3667 ('f', 'force', None,
3654 _('remove (and delete) file even if added or modified')),
3668 _('remove (and delete) file even if added or modified')),
3655 ] + walkopts,
3669 ] + walkopts,
3656 _('[OPTION]... FILE...')),
3670 _('[OPTION]... FILE...')),
3657 "rename|mv":
3671 "rename|mv":
3658 (rename,
3672 (rename,
3659 [('A', 'after', None, _('record a rename that has already occurred')),
3673 [('A', 'after', None, _('record a rename that has already occurred')),
3660 ('f', 'force', None,
3674 ('f', 'force', None,
3661 _('forcibly copy over an existing managed file')),
3675 _('forcibly copy over an existing managed file')),
3662 ] + walkopts + dryrunopts,
3676 ] + walkopts + dryrunopts,
3663 _('[OPTION]... SOURCE... DEST')),
3677 _('[OPTION]... SOURCE... DEST')),
3664 "resolve":
3678 "resolve":
3665 (resolve,
3679 (resolve,
3666 [('a', 'all', None, _('select all unresolved files')),
3680 [('a', 'all', None, _('select all unresolved files')),
3667 ('l', 'list', None, _('list state of files needing merge')),
3681 ('l', 'list', None, _('list state of files needing merge')),
3668 ('m', 'mark', None, _('mark files as resolved')),
3682 ('m', 'mark', None, _('mark files as resolved')),
3669 ('u', 'unmark', None, _('unmark files as resolved')),
3683 ('u', 'unmark', None, _('unmark files as resolved')),
3670 ('n', 'no-status', None, _('hide status prefix'))]
3684 ('n', 'no-status', None, _('hide status prefix'))]
3671 + walkopts,
3685 + walkopts,
3672 _('[OPTION]... [FILE]...')),
3686 _('[OPTION]... [FILE]...')),
3673 "revert":
3687 "revert":
3674 (revert,
3688 (revert,
3675 [('a', 'all', None, _('revert all changes when no arguments given')),
3689 [('a', 'all', None, _('revert all changes when no arguments given')),
3676 ('d', 'date', '', _('tipmost revision matching date')),
3690 ('d', 'date', '', _('tipmost revision matching date')),
3677 ('r', 'rev', '', _('revert to the specified revision')),
3691 ('r', 'rev', '', _('revert to the specified revision')),
3678 ('', 'no-backup', None, _('do not save backup copies of files')),
3692 ('', 'no-backup', None, _('do not save backup copies of files')),
3679 ] + walkopts + dryrunopts,
3693 ] + walkopts + dryrunopts,
3680 _('[OPTION]... [-r REV] [NAME]...')),
3694 _('[OPTION]... [-r REV] [NAME]...')),
3681 "rollback": (rollback, []),
3695 "rollback": (rollback, []),
3682 "root": (root, []),
3696 "root": (root, []),
3683 "^serve":
3697 "^serve":
3684 (serve,
3698 (serve,
3685 [('A', 'accesslog', '', _('name of access log file to write to')),
3699 [('A', 'accesslog', '', _('name of access log file to write to')),
3686 ('d', 'daemon', None, _('run server in background')),
3700 ('d', 'daemon', None, _('run server in background')),
3687 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3701 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3688 ('E', 'errorlog', '', _('name of error log file to write to')),
3702 ('E', 'errorlog', '', _('name of error log file to write to')),
3689 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3703 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3690 ('a', 'address', '',
3704 ('a', 'address', '',
3691 _('address to listen on (default: all interfaces)')),
3705 _('address to listen on (default: all interfaces)')),
3692 ('', 'prefix', '',
3706 ('', 'prefix', '',
3693 _('prefix path to serve from (default: server root)')),
3707 _('prefix path to serve from (default: server root)')),
3694 ('n', 'name', '',
3708 ('n', 'name', '',
3695 _('name to show in web pages (default: working directory)')),
3709 _('name to show in web pages (default: working directory)')),
3696 ('', 'webdir-conf', '', _('name of the webdir config file'
3710 ('', 'webdir-conf', '', _('name of the webdir config file'
3697 ' (serve more than one repository)')),
3711 ' (serve more than one repository)')),
3698 ('', 'pid-file', '', _('name of file to write process ID to')),
3712 ('', 'pid-file', '', _('name of file to write process ID to')),
3699 ('', 'stdio', None, _('for remote clients')),
3713 ('', 'stdio', None, _('for remote clients')),
3700 ('t', 'templates', '', _('web templates to use')),
3714 ('t', 'templates', '', _('web templates to use')),
3701 ('', 'style', '', _('template style to use')),
3715 ('', 'style', '', _('template style to use')),
3702 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3716 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3703 ('', 'certificate', '', _('SSL certificate file'))],
3717 ('', 'certificate', '', _('SSL certificate file'))],
3704 _('[OPTION]...')),
3718 _('[OPTION]...')),
3705 "showconfig|debugconfig":
3719 "showconfig|debugconfig":
3706 (showconfig,
3720 (showconfig,
3707 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3721 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3708 _('[-u] [NAME]...')),
3722 _('[-u] [NAME]...')),
3709 "^summary|sum":
3723 "^summary|sum":
3710 (summary,
3724 (summary,
3711 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
3725 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
3712 "^status|st":
3726 "^status|st":
3713 (status,
3727 (status,
3714 [('A', 'all', None, _('show status of all files')),
3728 [('A', 'all', None, _('show status of all files')),
3715 ('m', 'modified', None, _('show only modified files')),
3729 ('m', 'modified', None, _('show only modified files')),
3716 ('a', 'added', None, _('show only added files')),
3730 ('a', 'added', None, _('show only added files')),
3717 ('r', 'removed', None, _('show only removed files')),
3731 ('r', 'removed', None, _('show only removed files')),
3718 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3732 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3719 ('c', 'clean', None, _('show only files without changes')),
3733 ('c', 'clean', None, _('show only files without changes')),
3720 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3734 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3721 ('i', 'ignored', None, _('show only ignored files')),
3735 ('i', 'ignored', None, _('show only ignored files')),
3722 ('n', 'no-status', None, _('hide status prefix')),
3736 ('n', 'no-status', None, _('hide status prefix')),
3723 ('C', 'copies', None, _('show source of copied files')),
3737 ('C', 'copies', None, _('show source of copied files')),
3724 ('0', 'print0', None,
3738 ('0', 'print0', None,
3725 _('end filenames with NUL, for use with xargs')),
3739 _('end filenames with NUL, for use with xargs')),
3726 ('', 'rev', [], _('show difference from revision')),
3740 ('', 'rev', [], _('show difference from revision')),
3727 ('', 'change', '', _('list the changed files of a revision')),
3741 ('', 'change', '', _('list the changed files of a revision')),
3728 ] + walkopts,
3742 ] + walkopts,
3729 _('[OPTION]... [FILE]...')),
3743 _('[OPTION]... [FILE]...')),
3730 "tag":
3744 "tag":
3731 (tag,
3745 (tag,
3732 [('f', 'force', None, _('replace existing tag')),
3746 [('f', 'force', None, _('replace existing tag')),
3733 ('l', 'local', None, _('make the tag local')),
3747 ('l', 'local', None, _('make the tag local')),
3734 ('r', 'rev', '', _('revision to tag')),
3748 ('r', 'rev', '', _('revision to tag')),
3735 ('', 'remove', None, _('remove a tag')),
3749 ('', 'remove', None, _('remove a tag')),
3736 # -l/--local is already there, commitopts cannot be used
3750 # -l/--local is already there, commitopts cannot be used
3737 ('m', 'message', '', _('use <text> as commit message')),
3751 ('m', 'message', '', _('use <text> as commit message')),
3738 ] + commitopts2,
3752 ] + commitopts2,
3739 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3753 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3740 "tags": (tags, [], ''),
3754 "tags": (tags, [], ''),
3741 "tip":
3755 "tip":
3742 (tip,
3756 (tip,
3743 [('p', 'patch', None, _('show patch')),
3757 [('p', 'patch', None, _('show patch')),
3744 ('g', 'git', None, _('use git extended diff format')),
3758 ('g', 'git', None, _('use git extended diff format')),
3745 ] + templateopts,
3759 ] + templateopts,
3746 _('[-p] [-g]')),
3760 _('[-p] [-g]')),
3747 "unbundle":
3761 "unbundle":
3748 (unbundle,
3762 (unbundle,
3749 [('u', 'update', None,
3763 [('u', 'update', None,
3750 _('update to new branch head if changesets were unbundled'))],
3764 _('update to new branch head if changesets were unbundled'))],
3751 _('[-u] FILE...')),
3765 _('[-u] FILE...')),
3752 "^update|up|checkout|co":
3766 "^update|up|checkout|co":
3753 (update,
3767 (update,
3754 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
3768 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
3755 ('c', 'check', None, _('check for uncommitted changes')),
3769 ('c', 'check', None, _('check for uncommitted changes')),
3756 ('d', 'date', '', _('tipmost revision matching date')),
3770 ('d', 'date', '', _('tipmost revision matching date')),
3757 ('r', 'rev', '', _('revision'))],
3771 ('r', 'rev', '', _('revision'))],
3758 _('[-c] [-C] [-d DATE] [[-r] REV]')),
3772 _('[-c] [-C] [-d DATE] [[-r] REV]')),
3759 "verify": (verify, []),
3773 "verify": (verify, []),
3760 "version": (version_, []),
3774 "version": (version_, []),
3761 }
3775 }
3762
3776
3763 norepo = ("clone init version help debugcommands debugcomplete debugdata"
3777 norepo = ("clone init version help debugcommands debugcomplete debugdata"
3764 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3778 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3765 optionalrepo = ("identify paths serve showconfig debugancestor")
3779 optionalrepo = ("identify paths serve showconfig debugancestor")
@@ -1,389 +1,391 b''
1 # hg.py - repository classes for mercurial
1 # hg.py - repository classes for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from i18n import _
9 from i18n import _
10 from lock import release
10 from lock import release
11 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
11 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
12 import lock, util, extensions, error, encoding, node
12 import lock, util, extensions, error, encoding, node
13 import merge as _merge
13 import merge as _merge
14 import verify as _verify
14 import verify as _verify
15 import errno, os, shutil
15 import errno, os, shutil
16
16
17 def _local(path):
17 def _local(path):
18 return (os.path.isfile(util.drop_scheme('file', path)) and
18 return (os.path.isfile(util.drop_scheme('file', path)) and
19 bundlerepo or localrepo)
19 bundlerepo or localrepo)
20
20
21 def addbranchrevs(lrepo, repo, branches, revs):
21 def addbranchrevs(lrepo, repo, branches, revs):
22 if not branches:
22 if not branches:
23 return revs or None, revs and revs[0] or None
23 return revs or None, revs and revs[0] or None
24 branchmap = repo.branchmap()
24 branchmap = repo.branchmap()
25 revs = revs and list(revs) or []
25 revs = revs and list(revs) or []
26 for branch in branches:
26 for branch in branches:
27 if branch == '.':
27 if branch == '.':
28 if not lrepo or not lrepo.local():
28 if not lrepo or not lrepo.local():
29 raise util.Abort(_("dirstate branch not accessible"))
29 raise util.Abort(_("dirstate branch not accessible"))
30 revs.append(lrepo.dirstate.branch())
30 revs.append(lrepo.dirstate.branch())
31 else:
31 else:
32 butf8 = encoding.fromlocal(branch)
32 butf8 = encoding.fromlocal(branch)
33 if butf8 in branchmap:
33 if butf8 in branchmap:
34 revs.extend(node.hex(r) for r in reversed(branchmap[butf8]))
34 revs.extend(node.hex(r) for r in reversed(branchmap[butf8]))
35 else:
35 else:
36 revs.append(branch)
36 revs.append(branch)
37 return revs, revs[0]
37 return revs, revs[0]
38
38
39 def parseurl(url, branches=None):
39 def parseurl(url, branches=None):
40 '''parse url#branch, returning url, branches+[branch]'''
40 '''parse url#branch, returning url, branches+[branch]'''
41
41
42 if '#' not in url:
42 if '#' not in url:
43 return url, branches or []
43 return url, branches or []
44 url, branch = url.split('#', 1)
44 url, branch = url.split('#', 1)
45 return url, (branches or []) + [branch]
45 return url, (branches or []) + [branch]
46
46
47 schemes = {
47 schemes = {
48 'bundle': bundlerepo,
48 'bundle': bundlerepo,
49 'file': _local,
49 'file': _local,
50 'http': httprepo,
50 'http': httprepo,
51 'https': httprepo,
51 'https': httprepo,
52 'ssh': sshrepo,
52 'ssh': sshrepo,
53 'static-http': statichttprepo,
53 'static-http': statichttprepo,
54 }
54 }
55
55
56 def _lookup(path):
56 def _lookup(path):
57 scheme = 'file'
57 scheme = 'file'
58 if path:
58 if path:
59 c = path.find(':')
59 c = path.find(':')
60 if c > 0:
60 if c > 0:
61 scheme = path[:c]
61 scheme = path[:c]
62 thing = schemes.get(scheme) or schemes['file']
62 thing = schemes.get(scheme) or schemes['file']
63 try:
63 try:
64 return thing(path)
64 return thing(path)
65 except TypeError:
65 except TypeError:
66 return thing
66 return thing
67
67
68 def islocal(repo):
68 def islocal(repo):
69 '''return true if repo or path is local'''
69 '''return true if repo or path is local'''
70 if isinstance(repo, str):
70 if isinstance(repo, str):
71 try:
71 try:
72 return _lookup(repo).islocal(repo)
72 return _lookup(repo).islocal(repo)
73 except AttributeError:
73 except AttributeError:
74 return False
74 return False
75 return repo.local()
75 return repo.local()
76
76
77 def repository(ui, path='', create=False):
77 def repository(ui, path='', create=False):
78 """return a repository object for the specified path"""
78 """return a repository object for the specified path"""
79 repo = _lookup(path).instance(ui, path, create)
79 repo = _lookup(path).instance(ui, path, create)
80 ui = getattr(repo, "ui", ui)
80 ui = getattr(repo, "ui", ui)
81 for name, module in extensions.extensions():
81 for name, module in extensions.extensions():
82 hook = getattr(module, 'reposetup', None)
82 hook = getattr(module, 'reposetup', None)
83 if hook:
83 if hook:
84 hook(ui, repo)
84 hook(ui, repo)
85 return repo
85 return repo
86
86
87 def defaultdest(source):
87 def defaultdest(source):
88 '''return default destination of clone if none is given'''
88 '''return default destination of clone if none is given'''
89 return os.path.basename(os.path.normpath(source))
89 return os.path.basename(os.path.normpath(source))
90
90
91 def localpath(path):
91 def localpath(path):
92 if path.startswith('file://localhost/'):
92 if path.startswith('file://localhost/'):
93 return path[16:]
93 return path[16:]
94 if path.startswith('file://'):
94 if path.startswith('file://'):
95 return path[7:]
95 return path[7:]
96 if path.startswith('file:'):
96 if path.startswith('file:'):
97 return path[5:]
97 return path[5:]
98 return path
98 return path
99
99
100 def share(ui, source, dest=None, update=True):
100 def share(ui, source, dest=None, update=True):
101 '''create a shared repository'''
101 '''create a shared repository'''
102
102
103 if not islocal(source):
103 if not islocal(source):
104 raise util.Abort(_('can only share local repositories'))
104 raise util.Abort(_('can only share local repositories'))
105
105
106 if not dest:
106 if not dest:
107 dest = defaultdest(source)
107 dest = defaultdest(source)
108 else:
108 else:
109 dest = ui.expandpath(dest)
109 dest = ui.expandpath(dest)
110
110
111 if isinstance(source, str):
111 if isinstance(source, str):
112 origsource = ui.expandpath(source)
112 origsource = ui.expandpath(source)
113 source, branches = parseurl(origsource)
113 source, branches = parseurl(origsource)
114 srcrepo = repository(ui, source)
114 srcrepo = repository(ui, source)
115 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
115 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
116 else:
116 else:
117 srcrepo = source
117 srcrepo = source
118 origsource = source = srcrepo.url()
118 origsource = source = srcrepo.url()
119 checkout = None
119 checkout = None
120
120
121 sharedpath = srcrepo.sharedpath # if our source is already sharing
121 sharedpath = srcrepo.sharedpath # if our source is already sharing
122
122
123 root = os.path.realpath(dest)
123 root = os.path.realpath(dest)
124 roothg = os.path.join(root, '.hg')
124 roothg = os.path.join(root, '.hg')
125
125
126 if os.path.exists(roothg):
126 if os.path.exists(roothg):
127 raise util.Abort(_('destination already exists'))
127 raise util.Abort(_('destination already exists'))
128
128
129 if not os.path.isdir(root):
129 if not os.path.isdir(root):
130 os.mkdir(root)
130 os.mkdir(root)
131 os.mkdir(roothg)
131 os.mkdir(roothg)
132
132
133 requirements = ''
133 requirements = ''
134 try:
134 try:
135 requirements = srcrepo.opener('requires').read()
135 requirements = srcrepo.opener('requires').read()
136 except IOError, inst:
136 except IOError, inst:
137 if inst.errno != errno.ENOENT:
137 if inst.errno != errno.ENOENT:
138 raise
138 raise
139
139
140 requirements += 'shared\n'
140 requirements += 'shared\n'
141 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
141 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
142 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
142 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
143
143
144 default = srcrepo.ui.config('paths', 'default')
144 default = srcrepo.ui.config('paths', 'default')
145 if default:
145 if default:
146 f = file(os.path.join(roothg, 'hgrc'), 'w')
146 f = file(os.path.join(roothg, 'hgrc'), 'w')
147 f.write('[paths]\ndefault = %s\n' % default)
147 f.write('[paths]\ndefault = %s\n' % default)
148 f.close()
148 f.close()
149
149
150 r = repository(ui, root)
150 r = repository(ui, root)
151
151
152 if update:
152 if update:
153 r.ui.status(_("updating working directory\n"))
153 r.ui.status(_("updating working directory\n"))
154 if update is not True:
154 if update is not True:
155 checkout = update
155 checkout = update
156 for test in (checkout, 'default', 'tip'):
156 for test in (checkout, 'default', 'tip'):
157 if test is None:
157 if test is None:
158 continue
158 continue
159 try:
159 try:
160 uprev = r.lookup(test)
160 uprev = r.lookup(test)
161 break
161 break
162 except error.RepoLookupError:
162 except error.RepoLookupError:
163 continue
163 continue
164 _update(r, uprev)
164 _update(r, uprev)
165
165
166 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
166 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
167 stream=False):
167 stream=False, branch=None):
168 """Make a copy of an existing repository.
168 """Make a copy of an existing repository.
169
169
170 Create a copy of an existing repository in a new directory. The
170 Create a copy of an existing repository in a new directory. The
171 source and destination are URLs, as passed to the repository
171 source and destination are URLs, as passed to the repository
172 function. Returns a pair of repository objects, the source and
172 function. Returns a pair of repository objects, the source and
173 newly created destination.
173 newly created destination.
174
174
175 The location of the source is added to the new repository's
175 The location of the source is added to the new repository's
176 .hg/hgrc file, as the default to be used for future pulls and
176 .hg/hgrc file, as the default to be used for future pulls and
177 pushes.
177 pushes.
178
178
179 If an exception is raised, the partly cloned/updated destination
179 If an exception is raised, the partly cloned/updated destination
180 repository will be deleted.
180 repository will be deleted.
181
181
182 Arguments:
182 Arguments:
183
183
184 source: repository object or URL
184 source: repository object or URL
185
185
186 dest: URL of destination repository to create (defaults to base
186 dest: URL of destination repository to create (defaults to base
187 name of source repository)
187 name of source repository)
188
188
189 pull: always pull from source repository, even in local case
189 pull: always pull from source repository, even in local case
190
190
191 stream: stream raw data uncompressed from repository (fast over
191 stream: stream raw data uncompressed from repository (fast over
192 LAN, slow over WAN)
192 LAN, slow over WAN)
193
193
194 rev: revision to clone up to (implies pull=True)
194 rev: revision to clone up to (implies pull=True)
195
195
196 update: update working directory after clone completes, if
196 update: update working directory after clone completes, if
197 destination is local repository (True means update to default rev,
197 destination is local repository (True means update to default rev,
198 anything else is treated as a revision)
198 anything else is treated as a revision)
199
200 branch: branches to clone
199 """
201 """
200
202
201 if isinstance(source, str):
203 if isinstance(source, str):
202 origsource = ui.expandpath(source)
204 origsource = ui.expandpath(source)
203 source, branch = parseurl(origsource)
205 source, branch = parseurl(origsource, branch)
204 src_repo = repository(ui, source)
206 src_repo = repository(ui, source)
205 else:
207 else:
206 src_repo = source
208 src_repo = source
207 origsource = source = src_repo.url()
209 origsource = source = src_repo.url()
208 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
210 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
209
211
210 if dest is None:
212 if dest is None:
211 dest = defaultdest(source)
213 dest = defaultdest(source)
212 ui.status(_("destination directory: %s\n") % dest)
214 ui.status(_("destination directory: %s\n") % dest)
213 else:
215 else:
214 dest = ui.expandpath(dest)
216 dest = ui.expandpath(dest)
215
217
216 dest = localpath(dest)
218 dest = localpath(dest)
217 source = localpath(source)
219 source = localpath(source)
218
220
219 if os.path.exists(dest):
221 if os.path.exists(dest):
220 if not os.path.isdir(dest):
222 if not os.path.isdir(dest):
221 raise util.Abort(_("destination '%s' already exists") % dest)
223 raise util.Abort(_("destination '%s' already exists") % dest)
222 elif os.listdir(dest):
224 elif os.listdir(dest):
223 raise util.Abort(_("destination '%s' is not empty") % dest)
225 raise util.Abort(_("destination '%s' is not empty") % dest)
224
226
225 class DirCleanup(object):
227 class DirCleanup(object):
226 def __init__(self, dir_):
228 def __init__(self, dir_):
227 self.rmtree = shutil.rmtree
229 self.rmtree = shutil.rmtree
228 self.dir_ = dir_
230 self.dir_ = dir_
229 def close(self):
231 def close(self):
230 self.dir_ = None
232 self.dir_ = None
231 def cleanup(self):
233 def cleanup(self):
232 if self.dir_:
234 if self.dir_:
233 self.rmtree(self.dir_, True)
235 self.rmtree(self.dir_, True)
234
236
235 src_lock = dest_lock = dir_cleanup = None
237 src_lock = dest_lock = dir_cleanup = None
236 try:
238 try:
237 if islocal(dest):
239 if islocal(dest):
238 dir_cleanup = DirCleanup(dest)
240 dir_cleanup = DirCleanup(dest)
239
241
240 abspath = origsource
242 abspath = origsource
241 copy = False
243 copy = False
242 if src_repo.cancopy() and islocal(dest):
244 if src_repo.cancopy() and islocal(dest):
243 abspath = os.path.abspath(util.drop_scheme('file', origsource))
245 abspath = os.path.abspath(util.drop_scheme('file', origsource))
244 copy = not pull and not rev
246 copy = not pull and not rev
245
247
246 if copy:
248 if copy:
247 try:
249 try:
248 # we use a lock here because if we race with commit, we
250 # we use a lock here because if we race with commit, we
249 # can end up with extra data in the cloned revlogs that's
251 # can end up with extra data in the cloned revlogs that's
250 # not pointed to by changesets, thus causing verify to
252 # not pointed to by changesets, thus causing verify to
251 # fail
253 # fail
252 src_lock = src_repo.lock(wait=False)
254 src_lock = src_repo.lock(wait=False)
253 except error.LockError:
255 except error.LockError:
254 copy = False
256 copy = False
255
257
256 if copy:
258 if copy:
257 src_repo.hook('preoutgoing', throw=True, source='clone')
259 src_repo.hook('preoutgoing', throw=True, source='clone')
258 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
260 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
259 if not os.path.exists(dest):
261 if not os.path.exists(dest):
260 os.mkdir(dest)
262 os.mkdir(dest)
261 else:
263 else:
262 # only clean up directories we create ourselves
264 # only clean up directories we create ourselves
263 dir_cleanup.dir_ = hgdir
265 dir_cleanup.dir_ = hgdir
264 try:
266 try:
265 dest_path = hgdir
267 dest_path = hgdir
266 os.mkdir(dest_path)
268 os.mkdir(dest_path)
267 except OSError, inst:
269 except OSError, inst:
268 if inst.errno == errno.EEXIST:
270 if inst.errno == errno.EEXIST:
269 dir_cleanup.close()
271 dir_cleanup.close()
270 raise util.Abort(_("destination '%s' already exists")
272 raise util.Abort(_("destination '%s' already exists")
271 % dest)
273 % dest)
272 raise
274 raise
273
275
274 for f in src_repo.store.copylist():
276 for f in src_repo.store.copylist():
275 src = os.path.join(src_repo.sharedpath, f)
277 src = os.path.join(src_repo.sharedpath, f)
276 dst = os.path.join(dest_path, f)
278 dst = os.path.join(dest_path, f)
277 dstbase = os.path.dirname(dst)
279 dstbase = os.path.dirname(dst)
278 if dstbase and not os.path.exists(dstbase):
280 if dstbase and not os.path.exists(dstbase):
279 os.mkdir(dstbase)
281 os.mkdir(dstbase)
280 if os.path.exists(src):
282 if os.path.exists(src):
281 if dst.endswith('data'):
283 if dst.endswith('data'):
282 # lock to avoid premature writing to the target
284 # lock to avoid premature writing to the target
283 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
285 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
284 util.copyfiles(src, dst)
286 util.copyfiles(src, dst)
285
287
286 # we need to re-init the repo after manually copying the data
288 # we need to re-init the repo after manually copying the data
287 # into it
289 # into it
288 dest_repo = repository(ui, dest)
290 dest_repo = repository(ui, dest)
289 src_repo.hook('outgoing', source='clone', node='0'*40)
291 src_repo.hook('outgoing', source='clone', node='0'*40)
290 else:
292 else:
291 try:
293 try:
292 dest_repo = repository(ui, dest, create=True)
294 dest_repo = repository(ui, dest, create=True)
293 except OSError, inst:
295 except OSError, inst:
294 if inst.errno == errno.EEXIST:
296 if inst.errno == errno.EEXIST:
295 dir_cleanup.close()
297 dir_cleanup.close()
296 raise util.Abort(_("destination '%s' already exists")
298 raise util.Abort(_("destination '%s' already exists")
297 % dest)
299 % dest)
298 raise
300 raise
299
301
300 revs = None
302 revs = None
301 if rev:
303 if rev:
302 if 'lookup' not in src_repo.capabilities:
304 if 'lookup' not in src_repo.capabilities:
303 raise util.Abort(_("src repository does not support "
305 raise util.Abort(_("src repository does not support "
304 "revision lookup and so doesn't "
306 "revision lookup and so doesn't "
305 "support clone by revision"))
307 "support clone by revision"))
306 revs = [src_repo.lookup(r) for r in rev]
308 revs = [src_repo.lookup(r) for r in rev]
307 checkout = revs[0]
309 checkout = revs[0]
308 if dest_repo.local():
310 if dest_repo.local():
309 dest_repo.clone(src_repo, heads=revs, stream=stream)
311 dest_repo.clone(src_repo, heads=revs, stream=stream)
310 elif src_repo.local():
312 elif src_repo.local():
311 src_repo.push(dest_repo, revs=revs)
313 src_repo.push(dest_repo, revs=revs)
312 else:
314 else:
313 raise util.Abort(_("clone from remote to remote not supported"))
315 raise util.Abort(_("clone from remote to remote not supported"))
314
316
315 if dir_cleanup:
317 if dir_cleanup:
316 dir_cleanup.close()
318 dir_cleanup.close()
317
319
318 if dest_repo.local():
320 if dest_repo.local():
319 fp = dest_repo.opener("hgrc", "w", text=True)
321 fp = dest_repo.opener("hgrc", "w", text=True)
320 fp.write("[paths]\n")
322 fp.write("[paths]\n")
321 fp.write("default = %s\n" % abspath)
323 fp.write("default = %s\n" % abspath)
322 fp.close()
324 fp.close()
323
325
324 dest_repo.ui.setconfig('paths', 'default', abspath)
326 dest_repo.ui.setconfig('paths', 'default', abspath)
325
327
326 if update:
328 if update:
327 if update is not True:
329 if update is not True:
328 checkout = update
330 checkout = update
329 if src_repo.local():
331 if src_repo.local():
330 checkout = src_repo.lookup(update)
332 checkout = src_repo.lookup(update)
331 for test in (checkout, 'default', 'tip'):
333 for test in (checkout, 'default', 'tip'):
332 if test is None:
334 if test is None:
333 continue
335 continue
334 try:
336 try:
335 uprev = dest_repo.lookup(test)
337 uprev = dest_repo.lookup(test)
336 break
338 break
337 except error.RepoLookupError:
339 except error.RepoLookupError:
338 continue
340 continue
339 bn = dest_repo[uprev].branch()
341 bn = dest_repo[uprev].branch()
340 dest_repo.ui.status(_("updating to branch %s\n")
342 dest_repo.ui.status(_("updating to branch %s\n")
341 % encoding.tolocal(bn))
343 % encoding.tolocal(bn))
342 _update(dest_repo, uprev)
344 _update(dest_repo, uprev)
343
345
344 return src_repo, dest_repo
346 return src_repo, dest_repo
345 finally:
347 finally:
346 release(src_lock, dest_lock)
348 release(src_lock, dest_lock)
347 if dir_cleanup is not None:
349 if dir_cleanup is not None:
348 dir_cleanup.cleanup()
350 dir_cleanup.cleanup()
349
351
350 def _showstats(repo, stats):
352 def _showstats(repo, stats):
351 repo.ui.status(_("%d files updated, %d files merged, "
353 repo.ui.status(_("%d files updated, %d files merged, "
352 "%d files removed, %d files unresolved\n") % stats)
354 "%d files removed, %d files unresolved\n") % stats)
353
355
354 def update(repo, node):
356 def update(repo, node):
355 """update the working directory to node, merging linear changes"""
357 """update the working directory to node, merging linear changes"""
356 stats = _merge.update(repo, node, False, False, None)
358 stats = _merge.update(repo, node, False, False, None)
357 _showstats(repo, stats)
359 _showstats(repo, stats)
358 if stats[3]:
360 if stats[3]:
359 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
361 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
360 return stats[3] > 0
362 return stats[3] > 0
361
363
362 # naming conflict in clone()
364 # naming conflict in clone()
363 _update = update
365 _update = update
364
366
365 def clean(repo, node, show_stats=True):
367 def clean(repo, node, show_stats=True):
366 """forcibly switch the working directory to node, clobbering changes"""
368 """forcibly switch the working directory to node, clobbering changes"""
367 stats = _merge.update(repo, node, False, True, None)
369 stats = _merge.update(repo, node, False, True, None)
368 if show_stats:
370 if show_stats:
369 _showstats(repo, stats)
371 _showstats(repo, stats)
370 return stats[3] > 0
372 return stats[3] > 0
371
373
372 def merge(repo, node, force=None, remind=True):
374 def merge(repo, node, force=None, remind=True):
373 """branch merge with node, resolving changes"""
375 """branch merge with node, resolving changes"""
374 stats = _merge.update(repo, node, True, force, False)
376 stats = _merge.update(repo, node, True, force, False)
375 _showstats(repo, stats)
377 _showstats(repo, stats)
376 if stats[3]:
378 if stats[3]:
377 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
379 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
378 "or 'hg update -C' to abandon\n"))
380 "or 'hg update -C' to abandon\n"))
379 elif remind:
381 elif remind:
380 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
382 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
381 return stats[3] > 0
383 return stats[3] > 0
382
384
383 def revert(repo, node, choose):
385 def revert(repo, node, choose):
384 """revert changes to revision in node without updating dirstate"""
386 """revert changes to revision in node without updating dirstate"""
385 return _merge.update(repo, node, False, True, choose)[3] > 0
387 return _merge.update(repo, node, False, True, choose)[3] > 0
386
388
387 def verify(repo):
389 def verify(repo):
388 """verify the consistency of a repository"""
390 """verify the consistency of a repository"""
389 return _verify.verify(repo)
391 return _verify.verify(repo)
@@ -1,41 +1,43 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 # test branch selection options
3 # test branch selection options
4 hg init branch
4 hg init branch
5 cd branch
5 cd branch
6 hg branch a
6 hg branch a
7 echo a > foo
7 echo a > foo
8 hg ci -d '0 0' -Ama
8 hg ci -d '0 0' -Ama
9 echo a2 > foo
9 echo a2 > foo
10 hg ci -d '0 0' -ma2
10 hg ci -d '0 0' -ma2
11 hg up 0
11 hg up 0
12 hg branch c
12 hg branch c
13 echo c > foo
13 echo c > foo
14 hg ci -d '0 0' -mc
14 hg ci -d '0 0' -mc
15 cd ..
15 cd ..
16 hg clone -r 0 branch branch2
16 hg clone -r 0 branch branch2
17 cd branch2
17 cd branch2
18 hg up 0
18 hg up 0
19 hg branch b
19 hg branch b
20 echo b > foo
20 echo b > foo
21 hg ci -d '0 0' -mb
21 hg ci -d '0 0' -mb
22 hg up 0
22 hg up 0
23 hg branch -f b
23 hg branch -f b
24 echo b2 > foo
24 echo b2 > foo
25 hg ci -d '0 0' -mb2
25 hg ci -d '0 0' -mb2
26
26
27 echo in rev c branch a
27 echo in rev c branch a
28 hg in -qr c ../branch#a
28 hg in -qr c ../branch#a
29 hg in -qr c -b a
29 echo out branch .
30 echo out branch .
30 hg out -q ../branch#.
31 hg out -q ../branch#.
32 hg out -q -b .
31 echo clone branch b
33 echo clone branch b
32 cd ..
34 cd ..
33 hg clone branch2#b branch3
35 hg clone branch2#b branch3
34 hg -q -R branch3 heads b
36 hg -q -R branch3 heads b
35 hg -q -R branch3 parents
37 hg -q -R branch3 parents
36 rm -rf branch3
38 rm -rf branch3
37 echo clone rev a branch b
39 echo clone rev a branch b
38 hg clone -r a branch2#b branch3
40 hg clone -r a branch2#b branch3
39 hg -q -R branch3 heads b
41 hg -q -R branch3 heads b
40 hg -q -R branch3 parents
42 hg -q -R branch3 parents
41 rm -rf branch3
43 rm -rf branch3
@@ -1,44 +1,47 b''
1 marked working directory as branch a
1 marked working directory as branch a
2 adding foo
2 adding foo
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 marked working directory as branch c
4 marked working directory as branch c
5 created new head
5 created new head
6 requesting all changes
6 requesting all changes
7 adding changesets
7 adding changesets
8 adding manifests
8 adding manifests
9 adding file changes
9 adding file changes
10 added 1 changesets with 1 changes to 1 files
10 added 1 changesets with 1 changes to 1 files
11 updating to branch a
11 updating to branch a
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 marked working directory as branch b
14 marked working directory as branch b
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 marked working directory as branch b
16 marked working directory as branch b
17 created new head
17 created new head
18 in rev c branch a
18 in rev c branch a
19 1:dd6e60a716c6
19 1:dd6e60a716c6
20 2:f25d57ab0566
20 2:f25d57ab0566
21 1:dd6e60a716c6
22 2:f25d57ab0566
21 out branch .
23 out branch .
22 2:65511d0e2b55
24 2:65511d0e2b55
25 2:65511d0e2b55
23 clone branch b
26 clone branch b
24 requesting all changes
27 requesting all changes
25 adding changesets
28 adding changesets
26 adding manifests
29 adding manifests
27 adding file changes
30 adding file changes
28 added 3 changesets with 3 changes to 1 files (+1 heads)
31 added 3 changesets with 3 changes to 1 files (+1 heads)
29 updating to branch b
32 updating to branch b
30 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 2:65511d0e2b55
34 2:65511d0e2b55
32 1:b84708d77ab7
35 1:b84708d77ab7
33 2:65511d0e2b55
36 2:65511d0e2b55
34 clone rev a branch b
37 clone rev a branch b
35 requesting all changes
38 requesting all changes
36 adding changesets
39 adding changesets
37 adding manifests
40 adding manifests
38 adding file changes
41 adding file changes
39 added 3 changesets with 3 changes to 1 files (+1 heads)
42 added 3 changesets with 3 changes to 1 files (+1 heads)
40 updating to branch a
43 updating to branch a
41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 2:65511d0e2b55
45 2:65511d0e2b55
43 1:b84708d77ab7
46 1:b84708d77ab7
44 0:5b65ba7c951d
47 0:5b65ba7c951d
@@ -1,231 +1,231 b''
1 % Show all commands except debug commands
1 % Show all commands except debug commands
2 add
2 add
3 addremove
3 addremove
4 annotate
4 annotate
5 archive
5 archive
6 backout
6 backout
7 bisect
7 bisect
8 branch
8 branch
9 branches
9 branches
10 bundle
10 bundle
11 cat
11 cat
12 clone
12 clone
13 commit
13 commit
14 copy
14 copy
15 diff
15 diff
16 export
16 export
17 forget
17 forget
18 grep
18 grep
19 heads
19 heads
20 help
20 help
21 identify
21 identify
22 import
22 import
23 incoming
23 incoming
24 init
24 init
25 locate
25 locate
26 log
26 log
27 manifest
27 manifest
28 merge
28 merge
29 outgoing
29 outgoing
30 parents
30 parents
31 paths
31 paths
32 pull
32 pull
33 push
33 push
34 recover
34 recover
35 remove
35 remove
36 rename
36 rename
37 resolve
37 resolve
38 revert
38 revert
39 rollback
39 rollback
40 root
40 root
41 serve
41 serve
42 showconfig
42 showconfig
43 status
43 status
44 summary
44 summary
45 tag
45 tag
46 tags
46 tags
47 tip
47 tip
48 unbundle
48 unbundle
49 update
49 update
50 verify
50 verify
51 version
51 version
52
52
53 % Show all commands that start with "a"
53 % Show all commands that start with "a"
54 add
54 add
55 addremove
55 addremove
56 annotate
56 annotate
57 archive
57 archive
58
58
59 % Do not show debug commands if there are other candidates
59 % Do not show debug commands if there are other candidates
60 diff
60 diff
61
61
62 % Show debug commands if there are no other candidates
62 % Show debug commands if there are no other candidates
63 debugancestor
63 debugancestor
64 debugcheckstate
64 debugcheckstate
65 debugcommands
65 debugcommands
66 debugcomplete
66 debugcomplete
67 debugconfig
67 debugconfig
68 debugdata
68 debugdata
69 debugdate
69 debugdate
70 debugfsinfo
70 debugfsinfo
71 debugindex
71 debugindex
72 debugindexdot
72 debugindexdot
73 debuginstall
73 debuginstall
74 debugrebuildstate
74 debugrebuildstate
75 debugrename
75 debugrename
76 debugsetparents
76 debugsetparents
77 debugstate
77 debugstate
78 debugsub
78 debugsub
79 debugwalk
79 debugwalk
80
80
81 % Do not show the alias of a debug command if there are other candidates
81 % Do not show the alias of a debug command if there are other candidates
82 % (this should hide rawcommit)
82 % (this should hide rawcommit)
83 recover
83 recover
84 remove
84 remove
85 rename
85 rename
86 resolve
86 resolve
87 revert
87 revert
88 rollback
88 rollback
89 root
89 root
90
90
91 % Show the alias of a debug command if there are no other candidates
91 % Show the alias of a debug command if there are no other candidates
92
92
93
93
94 % Show the global options
94 % Show the global options
95 --config
95 --config
96 --cwd
96 --cwd
97 --debug
97 --debug
98 --debugger
98 --debugger
99 --encoding
99 --encoding
100 --encodingmode
100 --encodingmode
101 --help
101 --help
102 --noninteractive
102 --noninteractive
103 --profile
103 --profile
104 --quiet
104 --quiet
105 --repository
105 --repository
106 --time
106 --time
107 --traceback
107 --traceback
108 --verbose
108 --verbose
109 --version
109 --version
110 -R
110 -R
111 -h
111 -h
112 -q
112 -q
113 -v
113 -v
114 -y
114 -y
115
115
116 % Show the options for the "serve" command
116 % Show the options for the "serve" command
117 --accesslog
117 --accesslog
118 --address
118 --address
119 --certificate
119 --certificate
120 --config
120 --config
121 --cwd
121 --cwd
122 --daemon
122 --daemon
123 --daemon-pipefds
123 --daemon-pipefds
124 --debug
124 --debug
125 --debugger
125 --debugger
126 --encoding
126 --encoding
127 --encodingmode
127 --encodingmode
128 --errorlog
128 --errorlog
129 --help
129 --help
130 --ipv6
130 --ipv6
131 --name
131 --name
132 --noninteractive
132 --noninteractive
133 --pid-file
133 --pid-file
134 --port
134 --port
135 --prefix
135 --prefix
136 --profile
136 --profile
137 --quiet
137 --quiet
138 --repository
138 --repository
139 --stdio
139 --stdio
140 --style
140 --style
141 --templates
141 --templates
142 --time
142 --time
143 --traceback
143 --traceback
144 --verbose
144 --verbose
145 --version
145 --version
146 --webdir-conf
146 --webdir-conf
147 -6
147 -6
148 -A
148 -A
149 -E
149 -E
150 -R
150 -R
151 -a
151 -a
152 -d
152 -d
153 -h
153 -h
154 -n
154 -n
155 -p
155 -p
156 -q
156 -q
157 -t
157 -t
158 -v
158 -v
159 -y
159 -y
160
160
161 % Show an error if we use --options with an ambiguous abbreviation
161 % Show an error if we use --options with an ambiguous abbreviation
162 hg: command 's' is ambiguous:
162 hg: command 's' is ambiguous:
163 serve showconfig status summary
163 serve showconfig status summary
164
164
165 % Show all commands + options
165 % Show all commands + options
166 add: include, exclude, dry-run
166 add: include, exclude, dry-run
167 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
167 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
168 clone: noupdate, updaterev, rev, pull, uncompressed, ssh, remotecmd
168 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
169 commit: addremove, close-branch, include, exclude, message, logfile, date, user
169 commit: addremove, close-branch, include, exclude, message, logfile, date, user
170 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
170 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
171 export: output, switch-parent, rev, text, git, nodates
171 export: output, switch-parent, rev, text, git, nodates
172 forget: include, exclude
172 forget: include, exclude
173 init: ssh, remotecmd
173 init: ssh, remotecmd
174 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, prune, patch, git, limit, no-merges, style, template, include, exclude
174 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, prune, patch, git, limit, no-merges, style, template, include, exclude
175 merge: force, rev, preview
175 merge: force, rev, preview
176 pull: update, force, rev, ssh, remotecmd
176 pull: update, force, rev, branch, ssh, remotecmd
177 push: force, rev, ssh, remotecmd
177 push: force, rev, branch, ssh, remotecmd
178 remove: after, force, include, exclude
178 remove: after, force, include, exclude
179 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
179 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
180 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
180 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
181 summary: remote
181 summary: remote
182 update: clean, check, date, rev
182 update: clean, check, date, rev
183 addremove: similarity, include, exclude, dry-run
183 addremove: similarity, include, exclude, dry-run
184 archive: no-decode, prefix, rev, type, include, exclude
184 archive: no-decode, prefix, rev, type, include, exclude
185 backout: merge, parent, rev, include, exclude, message, logfile, date, user
185 backout: merge, parent, rev, include, exclude, message, logfile, date, user
186 bisect: reset, good, bad, skip, command, noupdate
186 bisect: reset, good, bad, skip, command, noupdate
187 branch: force, clean
187 branch: force, clean
188 branches: active, closed
188 branches: active, closed
189 bundle: force, rev, base, all, type, ssh, remotecmd
189 bundle: force, rev, branch, base, all, type, ssh, remotecmd
190 cat: output, rev, decode, include, exclude
190 cat: output, rev, decode, include, exclude
191 copy: after, force, include, exclude, dry-run
191 copy: after, force, include, exclude, dry-run
192 debugancestor:
192 debugancestor:
193 debugcheckstate:
193 debugcheckstate:
194 debugcommands:
194 debugcommands:
195 debugcomplete: options
195 debugcomplete: options
196 debugdata:
196 debugdata:
197 debugdate: extended
197 debugdate: extended
198 debugfsinfo:
198 debugfsinfo:
199 debugindex:
199 debugindex:
200 debugindexdot:
200 debugindexdot:
201 debuginstall:
201 debuginstall:
202 debugrebuildstate: rev
202 debugrebuildstate: rev
203 debugrename: rev
203 debugrename: rev
204 debugsetparents:
204 debugsetparents:
205 debugstate: nodates
205 debugstate: nodates
206 debugsub: rev
206 debugsub: rev
207 debugwalk: include, exclude
207 debugwalk: include, exclude
208 grep: print0, all, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
208 grep: print0, all, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
209 heads: rev, topo, active, closed, style, template
209 heads: rev, topo, active, closed, style, template
210 help:
210 help:
211 identify: rev, num, id, branch, tags
211 identify: rev, num, id, branch, tags
212 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
212 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
213 incoming: force, newest-first, bundle, rev, patch, git, limit, no-merges, style, template, ssh, remotecmd
213 incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, style, template, ssh, remotecmd
214 locate: rev, print0, fullpath, include, exclude
214 locate: rev, print0, fullpath, include, exclude
215 manifest: rev
215 manifest: rev
216 outgoing: force, rev, newest-first, patch, git, limit, no-merges, style, template, ssh, remotecmd
216 outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, style, template, ssh, remotecmd
217 parents: rev, style, template
217 parents: rev, style, template
218 paths:
218 paths:
219 recover:
219 recover:
220 rename: after, force, include, exclude, dry-run
220 rename: after, force, include, exclude, dry-run
221 resolve: all, list, mark, unmark, no-status, include, exclude
221 resolve: all, list, mark, unmark, no-status, include, exclude
222 revert: all, date, rev, no-backup, include, exclude, dry-run
222 revert: all, date, rev, no-backup, include, exclude, dry-run
223 rollback:
223 rollback:
224 root:
224 root:
225 showconfig: untrusted
225 showconfig: untrusted
226 tag: force, local, rev, remove, message, date, user
226 tag: force, local, rev, remove, message, date, user
227 tags:
227 tags:
228 tip: patch, git, style, template
228 tip: patch, git, style, template
229 unbundle: update
229 unbundle: update
230 verify:
230 verify:
231 version:
231 version:
General Comments 0
You need to be logged in to leave comments. Login now