##// END OF EJS Templates
graft: refuse to commit an interrupted graft (issue3667)
Simon King -
r19253:e078ea9b stable
parent child Browse files
Show More
@@ -1,5864 +1,5868 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 divs = [repo[b].node() for b in marks
819 divs = [repo[b].node() for b in marks
820 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
820 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
821
821
822 # allow resolving a single divergent bookmark even if moving
822 # allow resolving a single divergent bookmark even if moving
823 # the bookmark across branches when a revision is specified
823 # the bookmark across branches when a revision is specified
824 # that contains a divergent bookmark
824 # that contains a divergent bookmark
825 if bmctx.rev() not in anc and target in divs:
825 if bmctx.rev() not in anc and target in divs:
826 bookmarks.deletedivergent(repo, [target], mark)
826 bookmarks.deletedivergent(repo, [target], mark)
827 return
827 return
828
828
829 deletefrom = [b for b in divs
829 deletefrom = [b for b in divs
830 if repo[b].rev() in anc or b == target]
830 if repo[b].rev() in anc or b == target]
831 bookmarks.deletedivergent(repo, deletefrom, mark)
831 bookmarks.deletedivergent(repo, deletefrom, mark)
832 if bmctx.rev() in anc:
832 if bmctx.rev() in anc:
833 ui.status(_("moving bookmark '%s' forward from %s\n") %
833 ui.status(_("moving bookmark '%s' forward from %s\n") %
834 (mark, short(bmctx.node())))
834 (mark, short(bmctx.node())))
835 return
835 return
836 raise util.Abort(_("bookmark '%s' already exists "
836 raise util.Abort(_("bookmark '%s' already exists "
837 "(use -f to force)") % mark)
837 "(use -f to force)") % mark)
838 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
838 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
839 and not force):
839 and not force):
840 raise util.Abort(
840 raise util.Abort(
841 _("a bookmark cannot have the name of an existing branch"))
841 _("a bookmark cannot have the name of an existing branch"))
842
842
843 if delete and rename:
843 if delete and rename:
844 raise util.Abort(_("--delete and --rename are incompatible"))
844 raise util.Abort(_("--delete and --rename are incompatible"))
845 if delete and rev:
845 if delete and rev:
846 raise util.Abort(_("--rev is incompatible with --delete"))
846 raise util.Abort(_("--rev is incompatible with --delete"))
847 if rename and rev:
847 if rename and rev:
848 raise util.Abort(_("--rev is incompatible with --rename"))
848 raise util.Abort(_("--rev is incompatible with --rename"))
849 if mark is None and (delete or rev):
849 if mark is None and (delete or rev):
850 raise util.Abort(_("bookmark name required"))
850 raise util.Abort(_("bookmark name required"))
851
851
852 if delete:
852 if delete:
853 if mark not in marks:
853 if mark not in marks:
854 raise util.Abort(_("bookmark '%s' does not exist") % mark)
854 raise util.Abort(_("bookmark '%s' does not exist") % mark)
855 if mark == repo._bookmarkcurrent:
855 if mark == repo._bookmarkcurrent:
856 bookmarks.setcurrent(repo, None)
856 bookmarks.setcurrent(repo, None)
857 del marks[mark]
857 del marks[mark]
858 marks.write()
858 marks.write()
859
859
860 elif rename:
860 elif rename:
861 if mark is None:
861 if mark is None:
862 raise util.Abort(_("new bookmark name required"))
862 raise util.Abort(_("new bookmark name required"))
863 mark = checkformat(mark)
863 mark = checkformat(mark)
864 if rename not in marks:
864 if rename not in marks:
865 raise util.Abort(_("bookmark '%s' does not exist") % rename)
865 raise util.Abort(_("bookmark '%s' does not exist") % rename)
866 checkconflict(repo, mark, force)
866 checkconflict(repo, mark, force)
867 marks[mark] = marks[rename]
867 marks[mark] = marks[rename]
868 if repo._bookmarkcurrent == rename and not inactive:
868 if repo._bookmarkcurrent == rename and not inactive:
869 bookmarks.setcurrent(repo, mark)
869 bookmarks.setcurrent(repo, mark)
870 del marks[rename]
870 del marks[rename]
871 marks.write()
871 marks.write()
872
872
873 elif mark is not None:
873 elif mark is not None:
874 mark = checkformat(mark)
874 mark = checkformat(mark)
875 if inactive and mark == repo._bookmarkcurrent:
875 if inactive and mark == repo._bookmarkcurrent:
876 bookmarks.setcurrent(repo, None)
876 bookmarks.setcurrent(repo, None)
877 return
877 return
878 tgt = cur
878 tgt = cur
879 if rev:
879 if rev:
880 tgt = scmutil.revsingle(repo, rev).node()
880 tgt = scmutil.revsingle(repo, rev).node()
881 checkconflict(repo, mark, force, tgt)
881 checkconflict(repo, mark, force, tgt)
882 marks[mark] = tgt
882 marks[mark] = tgt
883 if not inactive and cur == marks[mark] and not rev:
883 if not inactive and cur == marks[mark] and not rev:
884 bookmarks.setcurrent(repo, mark)
884 bookmarks.setcurrent(repo, mark)
885 elif cur != tgt and mark == repo._bookmarkcurrent:
885 elif cur != tgt and mark == repo._bookmarkcurrent:
886 bookmarks.setcurrent(repo, None)
886 bookmarks.setcurrent(repo, None)
887 marks.write()
887 marks.write()
888
888
889 # Same message whether trying to deactivate the current bookmark (-i
889 # Same message whether trying to deactivate the current bookmark (-i
890 # with no NAME) or listing bookmarks
890 # with no NAME) or listing bookmarks
891 elif len(marks) == 0:
891 elif len(marks) == 0:
892 ui.status(_("no bookmarks set\n"))
892 ui.status(_("no bookmarks set\n"))
893
893
894 elif inactive:
894 elif inactive:
895 if not repo._bookmarkcurrent:
895 if not repo._bookmarkcurrent:
896 ui.status(_("no active bookmark\n"))
896 ui.status(_("no active bookmark\n"))
897 else:
897 else:
898 bookmarks.setcurrent(repo, None)
898 bookmarks.setcurrent(repo, None)
899
899
900 else: # show bookmarks
900 else: # show bookmarks
901 for bmark, n in sorted(marks.iteritems()):
901 for bmark, n in sorted(marks.iteritems()):
902 current = repo._bookmarkcurrent
902 current = repo._bookmarkcurrent
903 if bmark == current:
903 if bmark == current:
904 prefix, label = '*', 'bookmarks.current'
904 prefix, label = '*', 'bookmarks.current'
905 else:
905 else:
906 prefix, label = ' ', ''
906 prefix, label = ' ', ''
907
907
908 if ui.quiet:
908 if ui.quiet:
909 ui.write("%s\n" % bmark, label=label)
909 ui.write("%s\n" % bmark, label=label)
910 else:
910 else:
911 ui.write(" %s %-25s %d:%s\n" % (
911 ui.write(" %s %-25s %d:%s\n" % (
912 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
912 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
913 label=label)
913 label=label)
914
914
915 @command('branch',
915 @command('branch',
916 [('f', 'force', None,
916 [('f', 'force', None,
917 _('set branch name even if it shadows an existing branch')),
917 _('set branch name even if it shadows an existing branch')),
918 ('C', 'clean', None, _('reset branch name to parent branch name'))],
918 ('C', 'clean', None, _('reset branch name to parent branch name'))],
919 _('[-fC] [NAME]'))
919 _('[-fC] [NAME]'))
920 def branch(ui, repo, label=None, **opts):
920 def branch(ui, repo, label=None, **opts):
921 """set or show the current branch name
921 """set or show the current branch name
922
922
923 .. note::
923 .. note::
924 Branch names are permanent and global. Use :hg:`bookmark` to create a
924 Branch names are permanent and global. Use :hg:`bookmark` to create a
925 light-weight bookmark instead. See :hg:`help glossary` for more
925 light-weight bookmark instead. See :hg:`help glossary` for more
926 information about named branches and bookmarks.
926 information about named branches and bookmarks.
927
927
928 With no argument, show the current branch name. With one argument,
928 With no argument, show the current branch name. With one argument,
929 set the working directory branch name (the branch will not exist
929 set the working directory branch name (the branch will not exist
930 in the repository until the next commit). Standard practice
930 in the repository until the next commit). Standard practice
931 recommends that primary development take place on the 'default'
931 recommends that primary development take place on the 'default'
932 branch.
932 branch.
933
933
934 Unless -f/--force is specified, branch will not let you set a
934 Unless -f/--force is specified, branch will not let you set a
935 branch name that already exists, even if it's inactive.
935 branch name that already exists, even if it's inactive.
936
936
937 Use -C/--clean to reset the working directory branch to that of
937 Use -C/--clean to reset the working directory branch to that of
938 the parent of the working directory, negating a previous branch
938 the parent of the working directory, negating a previous branch
939 change.
939 change.
940
940
941 Use the command :hg:`update` to switch to an existing branch. Use
941 Use the command :hg:`update` to switch to an existing branch. Use
942 :hg:`commit --close-branch` to mark this branch as closed.
942 :hg:`commit --close-branch` to mark this branch as closed.
943
943
944 Returns 0 on success.
944 Returns 0 on success.
945 """
945 """
946 if label:
946 if label:
947 label = label.strip()
947 label = label.strip()
948
948
949 if not opts.get('clean') and not label:
949 if not opts.get('clean') and not label:
950 ui.write("%s\n" % repo.dirstate.branch())
950 ui.write("%s\n" % repo.dirstate.branch())
951 return
951 return
952
952
953 wlock = repo.wlock()
953 wlock = repo.wlock()
954 try:
954 try:
955 if opts.get('clean'):
955 if opts.get('clean'):
956 label = repo[None].p1().branch()
956 label = repo[None].p1().branch()
957 repo.dirstate.setbranch(label)
957 repo.dirstate.setbranch(label)
958 ui.status(_('reset working directory to branch %s\n') % label)
958 ui.status(_('reset working directory to branch %s\n') % label)
959 elif label:
959 elif label:
960 if not opts.get('force') and label in repo.branchmap():
960 if not opts.get('force') and label in repo.branchmap():
961 if label not in [p.branch() for p in repo.parents()]:
961 if label not in [p.branch() for p in repo.parents()]:
962 raise util.Abort(_('a branch of the same name already'
962 raise util.Abort(_('a branch of the same name already'
963 ' exists'),
963 ' exists'),
964 # i18n: "it" refers to an existing branch
964 # i18n: "it" refers to an existing branch
965 hint=_("use 'hg update' to switch to it"))
965 hint=_("use 'hg update' to switch to it"))
966 scmutil.checknewlabel(repo, label, 'branch')
966 scmutil.checknewlabel(repo, label, 'branch')
967 repo.dirstate.setbranch(label)
967 repo.dirstate.setbranch(label)
968 ui.status(_('marked working directory as branch %s\n') % label)
968 ui.status(_('marked working directory as branch %s\n') % label)
969 ui.status(_('(branches are permanent and global, '
969 ui.status(_('(branches are permanent and global, '
970 'did you want a bookmark?)\n'))
970 'did you want a bookmark?)\n'))
971 finally:
971 finally:
972 wlock.release()
972 wlock.release()
973
973
974 @command('branches',
974 @command('branches',
975 [('a', 'active', False, _('show only branches that have unmerged heads')),
975 [('a', 'active', False, _('show only branches that have unmerged heads')),
976 ('c', 'closed', False, _('show normal and closed branches'))],
976 ('c', 'closed', False, _('show normal and closed branches'))],
977 _('[-ac]'))
977 _('[-ac]'))
978 def branches(ui, repo, active=False, closed=False):
978 def branches(ui, repo, active=False, closed=False):
979 """list repository named branches
979 """list repository named branches
980
980
981 List the repository's named branches, indicating which ones are
981 List the repository's named branches, indicating which ones are
982 inactive. If -c/--closed is specified, also list branches which have
982 inactive. If -c/--closed is specified, also list branches which have
983 been marked closed (see :hg:`commit --close-branch`).
983 been marked closed (see :hg:`commit --close-branch`).
984
984
985 If -a/--active is specified, only show active branches. A branch
985 If -a/--active is specified, only show active branches. A branch
986 is considered active if it contains repository heads.
986 is considered active if it contains repository heads.
987
987
988 Use the command :hg:`update` to switch to an existing branch.
988 Use the command :hg:`update` to switch to an existing branch.
989
989
990 Returns 0.
990 Returns 0.
991 """
991 """
992
992
993 hexfunc = ui.debugflag and hex or short
993 hexfunc = ui.debugflag and hex or short
994
994
995 activebranches = set([repo[n].branch() for n in repo.heads()])
995 activebranches = set([repo[n].branch() for n in repo.heads()])
996 branches = []
996 branches = []
997 for tag, heads in repo.branchmap().iteritems():
997 for tag, heads in repo.branchmap().iteritems():
998 for h in reversed(heads):
998 for h in reversed(heads):
999 ctx = repo[h]
999 ctx = repo[h]
1000 isopen = not ctx.closesbranch()
1000 isopen = not ctx.closesbranch()
1001 if isopen:
1001 if isopen:
1002 tip = ctx
1002 tip = ctx
1003 break
1003 break
1004 else:
1004 else:
1005 tip = repo[heads[-1]]
1005 tip = repo[heads[-1]]
1006 isactive = tag in activebranches and isopen
1006 isactive = tag in activebranches and isopen
1007 branches.append((tip, isactive, isopen))
1007 branches.append((tip, isactive, isopen))
1008 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1008 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1009 reverse=True)
1009 reverse=True)
1010
1010
1011 for ctx, isactive, isopen in branches:
1011 for ctx, isactive, isopen in branches:
1012 if (not active) or isactive:
1012 if (not active) or isactive:
1013 if isactive:
1013 if isactive:
1014 label = 'branches.active'
1014 label = 'branches.active'
1015 notice = ''
1015 notice = ''
1016 elif not isopen:
1016 elif not isopen:
1017 if not closed:
1017 if not closed:
1018 continue
1018 continue
1019 label = 'branches.closed'
1019 label = 'branches.closed'
1020 notice = _(' (closed)')
1020 notice = _(' (closed)')
1021 else:
1021 else:
1022 label = 'branches.inactive'
1022 label = 'branches.inactive'
1023 notice = _(' (inactive)')
1023 notice = _(' (inactive)')
1024 if ctx.branch() == repo.dirstate.branch():
1024 if ctx.branch() == repo.dirstate.branch():
1025 label = 'branches.current'
1025 label = 'branches.current'
1026 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1026 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1027 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1027 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1028 'log.changeset changeset.%s' % ctx.phasestr())
1028 'log.changeset changeset.%s' % ctx.phasestr())
1029 tag = ui.label(ctx.branch(), label)
1029 tag = ui.label(ctx.branch(), label)
1030 if ui.quiet:
1030 if ui.quiet:
1031 ui.write("%s\n" % tag)
1031 ui.write("%s\n" % tag)
1032 else:
1032 else:
1033 ui.write("%s %s%s\n" % (tag, rev, notice))
1033 ui.write("%s %s%s\n" % (tag, rev, notice))
1034
1034
1035 @command('bundle',
1035 @command('bundle',
1036 [('f', 'force', None, _('run even when the destination is unrelated')),
1036 [('f', 'force', None, _('run even when the destination is unrelated')),
1037 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1037 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1038 _('REV')),
1038 _('REV')),
1039 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1039 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1040 _('BRANCH')),
1040 _('BRANCH')),
1041 ('', 'base', [],
1041 ('', 'base', [],
1042 _('a base changeset assumed to be available at the destination'),
1042 _('a base changeset assumed to be available at the destination'),
1043 _('REV')),
1043 _('REV')),
1044 ('a', 'all', None, _('bundle all changesets in the repository')),
1044 ('a', 'all', None, _('bundle all changesets in the repository')),
1045 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1045 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1046 ] + remoteopts,
1046 ] + remoteopts,
1047 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1047 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1048 def bundle(ui, repo, fname, dest=None, **opts):
1048 def bundle(ui, repo, fname, dest=None, **opts):
1049 """create a changegroup file
1049 """create a changegroup file
1050
1050
1051 Generate a compressed changegroup file collecting changesets not
1051 Generate a compressed changegroup file collecting changesets not
1052 known to be in another repository.
1052 known to be in another repository.
1053
1053
1054 If you omit the destination repository, then hg assumes the
1054 If you omit the destination repository, then hg assumes the
1055 destination will have all the nodes you specify with --base
1055 destination will have all the nodes you specify with --base
1056 parameters. To create a bundle containing all changesets, use
1056 parameters. To create a bundle containing all changesets, use
1057 -a/--all (or --base null).
1057 -a/--all (or --base null).
1058
1058
1059 You can change compression method with the -t/--type option.
1059 You can change compression method with the -t/--type option.
1060 The available compression methods are: none, bzip2, and
1060 The available compression methods are: none, bzip2, and
1061 gzip (by default, bundles are compressed using bzip2).
1061 gzip (by default, bundles are compressed using bzip2).
1062
1062
1063 The bundle file can then be transferred using conventional means
1063 The bundle file can then be transferred using conventional means
1064 and applied to another repository with the unbundle or pull
1064 and applied to another repository with the unbundle or pull
1065 command. This is useful when direct push and pull are not
1065 command. This is useful when direct push and pull are not
1066 available or when exporting an entire repository is undesirable.
1066 available or when exporting an entire repository is undesirable.
1067
1067
1068 Applying bundles preserves all changeset contents including
1068 Applying bundles preserves all changeset contents including
1069 permissions, copy/rename information, and revision history.
1069 permissions, copy/rename information, and revision history.
1070
1070
1071 Returns 0 on success, 1 if no changes found.
1071 Returns 0 on success, 1 if no changes found.
1072 """
1072 """
1073 revs = None
1073 revs = None
1074 if 'rev' in opts:
1074 if 'rev' in opts:
1075 revs = scmutil.revrange(repo, opts['rev'])
1075 revs = scmutil.revrange(repo, opts['rev'])
1076
1076
1077 bundletype = opts.get('type', 'bzip2').lower()
1077 bundletype = opts.get('type', 'bzip2').lower()
1078 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1078 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1079 bundletype = btypes.get(bundletype)
1079 bundletype = btypes.get(bundletype)
1080 if bundletype not in changegroup.bundletypes:
1080 if bundletype not in changegroup.bundletypes:
1081 raise util.Abort(_('unknown bundle type specified with --type'))
1081 raise util.Abort(_('unknown bundle type specified with --type'))
1082
1082
1083 if opts.get('all'):
1083 if opts.get('all'):
1084 base = ['null']
1084 base = ['null']
1085 else:
1085 else:
1086 base = scmutil.revrange(repo, opts.get('base'))
1086 base = scmutil.revrange(repo, opts.get('base'))
1087 if base:
1087 if base:
1088 if dest:
1088 if dest:
1089 raise util.Abort(_("--base is incompatible with specifying "
1089 raise util.Abort(_("--base is incompatible with specifying "
1090 "a destination"))
1090 "a destination"))
1091 common = [repo.lookup(rev) for rev in base]
1091 common = [repo.lookup(rev) for rev in base]
1092 heads = revs and map(repo.lookup, revs) or revs
1092 heads = revs and map(repo.lookup, revs) or revs
1093 cg = repo.getbundle('bundle', heads=heads, common=common)
1093 cg = repo.getbundle('bundle', heads=heads, common=common)
1094 outgoing = None
1094 outgoing = None
1095 else:
1095 else:
1096 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1096 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1097 dest, branches = hg.parseurl(dest, opts.get('branch'))
1097 dest, branches = hg.parseurl(dest, opts.get('branch'))
1098 other = hg.peer(repo, opts, dest)
1098 other = hg.peer(repo, opts, dest)
1099 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1099 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1100 heads = revs and map(repo.lookup, revs) or revs
1100 heads = revs and map(repo.lookup, revs) or revs
1101 outgoing = discovery.findcommonoutgoing(repo, other,
1101 outgoing = discovery.findcommonoutgoing(repo, other,
1102 onlyheads=heads,
1102 onlyheads=heads,
1103 force=opts.get('force'),
1103 force=opts.get('force'),
1104 portable=True)
1104 portable=True)
1105 cg = repo.getlocalbundle('bundle', outgoing)
1105 cg = repo.getlocalbundle('bundle', outgoing)
1106 if not cg:
1106 if not cg:
1107 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1107 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1108 return 1
1108 return 1
1109
1109
1110 changegroup.writebundle(cg, fname, bundletype)
1110 changegroup.writebundle(cg, fname, bundletype)
1111
1111
1112 @command('cat',
1112 @command('cat',
1113 [('o', 'output', '',
1113 [('o', 'output', '',
1114 _('print output to file with formatted name'), _('FORMAT')),
1114 _('print output to file with formatted name'), _('FORMAT')),
1115 ('r', 'rev', '', _('print the given revision'), _('REV')),
1115 ('r', 'rev', '', _('print the given revision'), _('REV')),
1116 ('', 'decode', None, _('apply any matching decode filter')),
1116 ('', 'decode', None, _('apply any matching decode filter')),
1117 ] + walkopts,
1117 ] + walkopts,
1118 _('[OPTION]... FILE...'))
1118 _('[OPTION]... FILE...'))
1119 def cat(ui, repo, file1, *pats, **opts):
1119 def cat(ui, repo, file1, *pats, **opts):
1120 """output the current or given revision of files
1120 """output the current or given revision of files
1121
1121
1122 Print the specified files as they were at the given revision. If
1122 Print the specified files as they were at the given revision. If
1123 no revision is given, the parent of the working directory is used,
1123 no revision is given, the parent of the working directory is used,
1124 or tip if no revision is checked out.
1124 or tip if no revision is checked out.
1125
1125
1126 Output may be to a file, in which case the name of the file is
1126 Output may be to a file, in which case the name of the file is
1127 given using a format string. The formatting rules are the same as
1127 given using a format string. The formatting rules are the same as
1128 for the export command, with the following additions:
1128 for the export command, with the following additions:
1129
1129
1130 :``%s``: basename of file being printed
1130 :``%s``: basename of file being printed
1131 :``%d``: dirname of file being printed, or '.' if in repository root
1131 :``%d``: dirname of file being printed, or '.' if in repository root
1132 :``%p``: root-relative path name of file being printed
1132 :``%p``: root-relative path name of file being printed
1133
1133
1134 Returns 0 on success.
1134 Returns 0 on success.
1135 """
1135 """
1136 ctx = scmutil.revsingle(repo, opts.get('rev'))
1136 ctx = scmutil.revsingle(repo, opts.get('rev'))
1137 err = 1
1137 err = 1
1138 m = scmutil.match(ctx, (file1,) + pats, opts)
1138 m = scmutil.match(ctx, (file1,) + pats, opts)
1139 for abs in ctx.walk(m):
1139 for abs in ctx.walk(m):
1140 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1140 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1141 pathname=abs)
1141 pathname=abs)
1142 data = ctx[abs].data()
1142 data = ctx[abs].data()
1143 if opts.get('decode'):
1143 if opts.get('decode'):
1144 data = repo.wwritedata(abs, data)
1144 data = repo.wwritedata(abs, data)
1145 fp.write(data)
1145 fp.write(data)
1146 fp.close()
1146 fp.close()
1147 err = 0
1147 err = 0
1148 return err
1148 return err
1149
1149
1150 @command('^clone',
1150 @command('^clone',
1151 [('U', 'noupdate', None,
1151 [('U', 'noupdate', None,
1152 _('the clone will include an empty working copy (only a repository)')),
1152 _('the clone will include an empty working copy (only a repository)')),
1153 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1153 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1154 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1154 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1155 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1155 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1156 ('', 'pull', None, _('use pull protocol to copy metadata')),
1156 ('', 'pull', None, _('use pull protocol to copy metadata')),
1157 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1157 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1158 ] + remoteopts,
1158 ] + remoteopts,
1159 _('[OPTION]... SOURCE [DEST]'))
1159 _('[OPTION]... SOURCE [DEST]'))
1160 def clone(ui, source, dest=None, **opts):
1160 def clone(ui, source, dest=None, **opts):
1161 """make a copy of an existing repository
1161 """make a copy of an existing repository
1162
1162
1163 Create a copy of an existing repository in a new directory.
1163 Create a copy of an existing repository in a new directory.
1164
1164
1165 If no destination directory name is specified, it defaults to the
1165 If no destination directory name is specified, it defaults to the
1166 basename of the source.
1166 basename of the source.
1167
1167
1168 The location of the source is added to the new repository's
1168 The location of the source is added to the new repository's
1169 ``.hg/hgrc`` file, as the default to be used for future pulls.
1169 ``.hg/hgrc`` file, as the default to be used for future pulls.
1170
1170
1171 Only local paths and ``ssh://`` URLs are supported as
1171 Only local paths and ``ssh://`` URLs are supported as
1172 destinations. For ``ssh://`` destinations, no working directory or
1172 destinations. For ``ssh://`` destinations, no working directory or
1173 ``.hg/hgrc`` will be created on the remote side.
1173 ``.hg/hgrc`` will be created on the remote side.
1174
1174
1175 To pull only a subset of changesets, specify one or more revisions
1175 To pull only a subset of changesets, specify one or more revisions
1176 identifiers with -r/--rev or branches with -b/--branch. The
1176 identifiers with -r/--rev or branches with -b/--branch. The
1177 resulting clone will contain only the specified changesets and
1177 resulting clone will contain only the specified changesets and
1178 their ancestors. These options (or 'clone src#rev dest') imply
1178 their ancestors. These options (or 'clone src#rev dest') imply
1179 --pull, even for local source repositories. Note that specifying a
1179 --pull, even for local source repositories. Note that specifying a
1180 tag will include the tagged changeset but not the changeset
1180 tag will include the tagged changeset but not the changeset
1181 containing the tag.
1181 containing the tag.
1182
1182
1183 If the source repository has a bookmark called '@' set, that
1183 If the source repository has a bookmark called '@' set, that
1184 revision will be checked out in the new repository by default.
1184 revision will be checked out in the new repository by default.
1185
1185
1186 To check out a particular version, use -u/--update, or
1186 To check out a particular version, use -u/--update, or
1187 -U/--noupdate to create a clone with no working directory.
1187 -U/--noupdate to create a clone with no working directory.
1188
1188
1189 .. container:: verbose
1189 .. container:: verbose
1190
1190
1191 For efficiency, hardlinks are used for cloning whenever the
1191 For efficiency, hardlinks are used for cloning whenever the
1192 source and destination are on the same filesystem (note this
1192 source and destination are on the same filesystem (note this
1193 applies only to the repository data, not to the working
1193 applies only to the repository data, not to the working
1194 directory). Some filesystems, such as AFS, implement hardlinking
1194 directory). Some filesystems, such as AFS, implement hardlinking
1195 incorrectly, but do not report errors. In these cases, use the
1195 incorrectly, but do not report errors. In these cases, use the
1196 --pull option to avoid hardlinking.
1196 --pull option to avoid hardlinking.
1197
1197
1198 In some cases, you can clone repositories and the working
1198 In some cases, you can clone repositories and the working
1199 directory using full hardlinks with ::
1199 directory using full hardlinks with ::
1200
1200
1201 $ cp -al REPO REPOCLONE
1201 $ cp -al REPO REPOCLONE
1202
1202
1203 This is the fastest way to clone, but it is not always safe. The
1203 This is the fastest way to clone, but it is not always safe. The
1204 operation is not atomic (making sure REPO is not modified during
1204 operation is not atomic (making sure REPO is not modified during
1205 the operation is up to you) and you have to make sure your
1205 the operation is up to you) and you have to make sure your
1206 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1206 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1207 so). Also, this is not compatible with certain extensions that
1207 so). Also, this is not compatible with certain extensions that
1208 place their metadata under the .hg directory, such as mq.
1208 place their metadata under the .hg directory, such as mq.
1209
1209
1210 Mercurial will update the working directory to the first applicable
1210 Mercurial will update the working directory to the first applicable
1211 revision from this list:
1211 revision from this list:
1212
1212
1213 a) null if -U or the source repository has no changesets
1213 a) null if -U or the source repository has no changesets
1214 b) if -u . and the source repository is local, the first parent of
1214 b) if -u . and the source repository is local, the first parent of
1215 the source repository's working directory
1215 the source repository's working directory
1216 c) the changeset specified with -u (if a branch name, this means the
1216 c) the changeset specified with -u (if a branch name, this means the
1217 latest head of that branch)
1217 latest head of that branch)
1218 d) the changeset specified with -r
1218 d) the changeset specified with -r
1219 e) the tipmost head specified with -b
1219 e) the tipmost head specified with -b
1220 f) the tipmost head specified with the url#branch source syntax
1220 f) the tipmost head specified with the url#branch source syntax
1221 g) the revision marked with the '@' bookmark, if present
1221 g) the revision marked with the '@' bookmark, if present
1222 h) the tipmost head of the default branch
1222 h) the tipmost head of the default branch
1223 i) tip
1223 i) tip
1224
1224
1225 Examples:
1225 Examples:
1226
1226
1227 - clone a remote repository to a new directory named hg/::
1227 - clone a remote repository to a new directory named hg/::
1228
1228
1229 hg clone http://selenic.com/hg
1229 hg clone http://selenic.com/hg
1230
1230
1231 - create a lightweight local clone::
1231 - create a lightweight local clone::
1232
1232
1233 hg clone project/ project-feature/
1233 hg clone project/ project-feature/
1234
1234
1235 - clone from an absolute path on an ssh server (note double-slash)::
1235 - clone from an absolute path on an ssh server (note double-slash)::
1236
1236
1237 hg clone ssh://user@server//home/projects/alpha/
1237 hg clone ssh://user@server//home/projects/alpha/
1238
1238
1239 - do a high-speed clone over a LAN while checking out a
1239 - do a high-speed clone over a LAN while checking out a
1240 specified version::
1240 specified version::
1241
1241
1242 hg clone --uncompressed http://server/repo -u 1.5
1242 hg clone --uncompressed http://server/repo -u 1.5
1243
1243
1244 - create a repository without changesets after a particular revision::
1244 - create a repository without changesets after a particular revision::
1245
1245
1246 hg clone -r 04e544 experimental/ good/
1246 hg clone -r 04e544 experimental/ good/
1247
1247
1248 - clone (and track) a particular named branch::
1248 - clone (and track) a particular named branch::
1249
1249
1250 hg clone http://selenic.com/hg#stable
1250 hg clone http://selenic.com/hg#stable
1251
1251
1252 See :hg:`help urls` for details on specifying URLs.
1252 See :hg:`help urls` for details on specifying URLs.
1253
1253
1254 Returns 0 on success.
1254 Returns 0 on success.
1255 """
1255 """
1256 if opts.get('noupdate') and opts.get('updaterev'):
1256 if opts.get('noupdate') and opts.get('updaterev'):
1257 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1257 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1258
1258
1259 r = hg.clone(ui, opts, source, dest,
1259 r = hg.clone(ui, opts, source, dest,
1260 pull=opts.get('pull'),
1260 pull=opts.get('pull'),
1261 stream=opts.get('uncompressed'),
1261 stream=opts.get('uncompressed'),
1262 rev=opts.get('rev'),
1262 rev=opts.get('rev'),
1263 update=opts.get('updaterev') or not opts.get('noupdate'),
1263 update=opts.get('updaterev') or not opts.get('noupdate'),
1264 branch=opts.get('branch'))
1264 branch=opts.get('branch'))
1265
1265
1266 return r is None
1266 return r is None
1267
1267
1268 @command('^commit|ci',
1268 @command('^commit|ci',
1269 [('A', 'addremove', None,
1269 [('A', 'addremove', None,
1270 _('mark new/missing files as added/removed before committing')),
1270 _('mark new/missing files as added/removed before committing')),
1271 ('', 'close-branch', None,
1271 ('', 'close-branch', None,
1272 _('mark a branch as closed, hiding it from the branch list')),
1272 _('mark a branch as closed, hiding it from the branch list')),
1273 ('', 'amend', None, _('amend the parent of the working dir')),
1273 ('', 'amend', None, _('amend the parent of the working dir')),
1274 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1274 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1275 _('[OPTION]... [FILE]...'))
1275 _('[OPTION]... [FILE]...'))
1276 def commit(ui, repo, *pats, **opts):
1276 def commit(ui, repo, *pats, **opts):
1277 """commit the specified files or all outstanding changes
1277 """commit the specified files or all outstanding changes
1278
1278
1279 Commit changes to the given files into the repository. Unlike a
1279 Commit changes to the given files into the repository. Unlike a
1280 centralized SCM, this operation is a local operation. See
1280 centralized SCM, this operation is a local operation. See
1281 :hg:`push` for a way to actively distribute your changes.
1281 :hg:`push` for a way to actively distribute your changes.
1282
1282
1283 If a list of files is omitted, all changes reported by :hg:`status`
1283 If a list of files is omitted, all changes reported by :hg:`status`
1284 will be committed.
1284 will be committed.
1285
1285
1286 If you are committing the result of a merge, do not provide any
1286 If you are committing the result of a merge, do not provide any
1287 filenames or -I/-X filters.
1287 filenames or -I/-X filters.
1288
1288
1289 If no commit message is specified, Mercurial starts your
1289 If no commit message is specified, Mercurial starts your
1290 configured editor where you can enter a message. In case your
1290 configured editor where you can enter a message. In case your
1291 commit fails, you will find a backup of your message in
1291 commit fails, you will find a backup of your message in
1292 ``.hg/last-message.txt``.
1292 ``.hg/last-message.txt``.
1293
1293
1294 The --amend flag can be used to amend the parent of the
1294 The --amend flag can be used to amend the parent of the
1295 working directory with a new commit that contains the changes
1295 working directory with a new commit that contains the changes
1296 in the parent in addition to those currently reported by :hg:`status`,
1296 in the parent in addition to those currently reported by :hg:`status`,
1297 if there are any. The old commit is stored in a backup bundle in
1297 if there are any. The old commit is stored in a backup bundle in
1298 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1298 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1299 on how to restore it).
1299 on how to restore it).
1300
1300
1301 Message, user and date are taken from the amended commit unless
1301 Message, user and date are taken from the amended commit unless
1302 specified. When a message isn't specified on the command line,
1302 specified. When a message isn't specified on the command line,
1303 the editor will open with the message of the amended commit.
1303 the editor will open with the message of the amended commit.
1304
1304
1305 It is not possible to amend public changesets (see :hg:`help phases`)
1305 It is not possible to amend public changesets (see :hg:`help phases`)
1306 or changesets that have children.
1306 or changesets that have children.
1307
1307
1308 See :hg:`help dates` for a list of formats valid for -d/--date.
1308 See :hg:`help dates` for a list of formats valid for -d/--date.
1309
1309
1310 Returns 0 on success, 1 if nothing changed.
1310 Returns 0 on success, 1 if nothing changed.
1311 """
1311 """
1312 if opts.get('subrepos'):
1312 if opts.get('subrepos'):
1313 if opts.get('amend'):
1313 if opts.get('amend'):
1314 raise util.Abort(_('cannot amend with --subrepos'))
1314 raise util.Abort(_('cannot amend with --subrepos'))
1315 # Let --subrepos on the command line override config setting.
1315 # Let --subrepos on the command line override config setting.
1316 ui.setconfig('ui', 'commitsubrepos', True)
1316 ui.setconfig('ui', 'commitsubrepos', True)
1317
1317
1318 if repo.vfs.exists('graftstate'):
1319 raise util.Abort(_('cannot commit an interrupted graft operation'),
1320 hint=_('use "hg graft -c" to continue graft'))
1321
1318 extra = {}
1322 extra = {}
1319 if opts.get('close_branch'):
1323 if opts.get('close_branch'):
1320 extra['close'] = 1
1324 extra['close'] = 1
1321
1325
1322 branch = repo[None].branch()
1326 branch = repo[None].branch()
1323 bheads = repo.branchheads(branch)
1327 bheads = repo.branchheads(branch)
1324
1328
1325 if opts.get('amend'):
1329 if opts.get('amend'):
1326 if ui.configbool('ui', 'commitsubrepos'):
1330 if ui.configbool('ui', 'commitsubrepos'):
1327 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1331 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1328
1332
1329 old = repo['.']
1333 old = repo['.']
1330 if old.phase() == phases.public:
1334 if old.phase() == phases.public:
1331 raise util.Abort(_('cannot amend public changesets'))
1335 raise util.Abort(_('cannot amend public changesets'))
1332 if len(repo[None].parents()) > 1:
1336 if len(repo[None].parents()) > 1:
1333 raise util.Abort(_('cannot amend while merging'))
1337 raise util.Abort(_('cannot amend while merging'))
1334 if (not obsolete._enabled) and old.children():
1338 if (not obsolete._enabled) and old.children():
1335 raise util.Abort(_('cannot amend changeset with children'))
1339 raise util.Abort(_('cannot amend changeset with children'))
1336
1340
1337 e = cmdutil.commiteditor
1341 e = cmdutil.commiteditor
1338 if opts.get('force_editor'):
1342 if opts.get('force_editor'):
1339 e = cmdutil.commitforceeditor
1343 e = cmdutil.commitforceeditor
1340
1344
1341 def commitfunc(ui, repo, message, match, opts):
1345 def commitfunc(ui, repo, message, match, opts):
1342 editor = e
1346 editor = e
1343 # message contains text from -m or -l, if it's empty,
1347 # message contains text from -m or -l, if it's empty,
1344 # open the editor with the old message
1348 # open the editor with the old message
1345 if not message:
1349 if not message:
1346 message = old.description()
1350 message = old.description()
1347 editor = cmdutil.commitforceeditor
1351 editor = cmdutil.commitforceeditor
1348 return repo.commit(message,
1352 return repo.commit(message,
1349 opts.get('user') or old.user(),
1353 opts.get('user') or old.user(),
1350 opts.get('date') or old.date(),
1354 opts.get('date') or old.date(),
1351 match,
1355 match,
1352 editor=editor,
1356 editor=editor,
1353 extra=extra)
1357 extra=extra)
1354
1358
1355 current = repo._bookmarkcurrent
1359 current = repo._bookmarkcurrent
1356 marks = old.bookmarks()
1360 marks = old.bookmarks()
1357 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1361 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1358 if node == old.node():
1362 if node == old.node():
1359 ui.status(_("nothing changed\n"))
1363 ui.status(_("nothing changed\n"))
1360 return 1
1364 return 1
1361 elif marks:
1365 elif marks:
1362 ui.debug('moving bookmarks %r from %s to %s\n' %
1366 ui.debug('moving bookmarks %r from %s to %s\n' %
1363 (marks, old.hex(), hex(node)))
1367 (marks, old.hex(), hex(node)))
1364 newmarks = repo._bookmarks
1368 newmarks = repo._bookmarks
1365 for bm in marks:
1369 for bm in marks:
1366 newmarks[bm] = node
1370 newmarks[bm] = node
1367 if bm == current:
1371 if bm == current:
1368 bookmarks.setcurrent(repo, bm)
1372 bookmarks.setcurrent(repo, bm)
1369 newmarks.write()
1373 newmarks.write()
1370 else:
1374 else:
1371 e = cmdutil.commiteditor
1375 e = cmdutil.commiteditor
1372 if opts.get('force_editor'):
1376 if opts.get('force_editor'):
1373 e = cmdutil.commitforceeditor
1377 e = cmdutil.commitforceeditor
1374
1378
1375 def commitfunc(ui, repo, message, match, opts):
1379 def commitfunc(ui, repo, message, match, opts):
1376 return repo.commit(message, opts.get('user'), opts.get('date'),
1380 return repo.commit(message, opts.get('user'), opts.get('date'),
1377 match, editor=e, extra=extra)
1381 match, editor=e, extra=extra)
1378
1382
1379 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1383 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1380
1384
1381 if not node:
1385 if not node:
1382 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1386 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1383 if stat[3]:
1387 if stat[3]:
1384 ui.status(_("nothing changed (%d missing files, see "
1388 ui.status(_("nothing changed (%d missing files, see "
1385 "'hg status')\n") % len(stat[3]))
1389 "'hg status')\n") % len(stat[3]))
1386 else:
1390 else:
1387 ui.status(_("nothing changed\n"))
1391 ui.status(_("nothing changed\n"))
1388 return 1
1392 return 1
1389
1393
1390 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1394 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1391
1395
1392 @command('copy|cp',
1396 @command('copy|cp',
1393 [('A', 'after', None, _('record a copy that has already occurred')),
1397 [('A', 'after', None, _('record a copy that has already occurred')),
1394 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1398 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1395 ] + walkopts + dryrunopts,
1399 ] + walkopts + dryrunopts,
1396 _('[OPTION]... [SOURCE]... DEST'))
1400 _('[OPTION]... [SOURCE]... DEST'))
1397 def copy(ui, repo, *pats, **opts):
1401 def copy(ui, repo, *pats, **opts):
1398 """mark files as copied for the next commit
1402 """mark files as copied for the next commit
1399
1403
1400 Mark dest as having copies of source files. If dest is a
1404 Mark dest as having copies of source files. If dest is a
1401 directory, copies are put in that directory. If dest is a file,
1405 directory, copies are put in that directory. If dest is a file,
1402 the source must be a single file.
1406 the source must be a single file.
1403
1407
1404 By default, this command copies the contents of files as they
1408 By default, this command copies the contents of files as they
1405 exist in the working directory. If invoked with -A/--after, the
1409 exist in the working directory. If invoked with -A/--after, the
1406 operation is recorded, but no copying is performed.
1410 operation is recorded, but no copying is performed.
1407
1411
1408 This command takes effect with the next commit. To undo a copy
1412 This command takes effect with the next commit. To undo a copy
1409 before that, see :hg:`revert`.
1413 before that, see :hg:`revert`.
1410
1414
1411 Returns 0 on success, 1 if errors are encountered.
1415 Returns 0 on success, 1 if errors are encountered.
1412 """
1416 """
1413 wlock = repo.wlock(False)
1417 wlock = repo.wlock(False)
1414 try:
1418 try:
1415 return cmdutil.copy(ui, repo, pats, opts)
1419 return cmdutil.copy(ui, repo, pats, opts)
1416 finally:
1420 finally:
1417 wlock.release()
1421 wlock.release()
1418
1422
1419 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1423 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1420 def debugancestor(ui, repo, *args):
1424 def debugancestor(ui, repo, *args):
1421 """find the ancestor revision of two revisions in a given index"""
1425 """find the ancestor revision of two revisions in a given index"""
1422 if len(args) == 3:
1426 if len(args) == 3:
1423 index, rev1, rev2 = args
1427 index, rev1, rev2 = args
1424 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1428 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1425 lookup = r.lookup
1429 lookup = r.lookup
1426 elif len(args) == 2:
1430 elif len(args) == 2:
1427 if not repo:
1431 if not repo:
1428 raise util.Abort(_("there is no Mercurial repository here "
1432 raise util.Abort(_("there is no Mercurial repository here "
1429 "(.hg not found)"))
1433 "(.hg not found)"))
1430 rev1, rev2 = args
1434 rev1, rev2 = args
1431 r = repo.changelog
1435 r = repo.changelog
1432 lookup = repo.lookup
1436 lookup = repo.lookup
1433 else:
1437 else:
1434 raise util.Abort(_('either two or three arguments required'))
1438 raise util.Abort(_('either two or three arguments required'))
1435 a = r.ancestor(lookup(rev1), lookup(rev2))
1439 a = r.ancestor(lookup(rev1), lookup(rev2))
1436 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1440 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1437
1441
1438 @command('debugbuilddag',
1442 @command('debugbuilddag',
1439 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1443 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1440 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1444 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1441 ('n', 'new-file', None, _('add new file at each rev'))],
1445 ('n', 'new-file', None, _('add new file at each rev'))],
1442 _('[OPTION]... [TEXT]'))
1446 _('[OPTION]... [TEXT]'))
1443 def debugbuilddag(ui, repo, text=None,
1447 def debugbuilddag(ui, repo, text=None,
1444 mergeable_file=False,
1448 mergeable_file=False,
1445 overwritten_file=False,
1449 overwritten_file=False,
1446 new_file=False):
1450 new_file=False):
1447 """builds a repo with a given DAG from scratch in the current empty repo
1451 """builds a repo with a given DAG from scratch in the current empty repo
1448
1452
1449 The description of the DAG is read from stdin if not given on the
1453 The description of the DAG is read from stdin if not given on the
1450 command line.
1454 command line.
1451
1455
1452 Elements:
1456 Elements:
1453
1457
1454 - "+n" is a linear run of n nodes based on the current default parent
1458 - "+n" is a linear run of n nodes based on the current default parent
1455 - "." is a single node based on the current default parent
1459 - "." is a single node based on the current default parent
1456 - "$" resets the default parent to null (implied at the start);
1460 - "$" resets the default parent to null (implied at the start);
1457 otherwise the default parent is always the last node created
1461 otherwise the default parent is always the last node created
1458 - "<p" sets the default parent to the backref p
1462 - "<p" sets the default parent to the backref p
1459 - "*p" is a fork at parent p, which is a backref
1463 - "*p" is a fork at parent p, which is a backref
1460 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1464 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1461 - "/p2" is a merge of the preceding node and p2
1465 - "/p2" is a merge of the preceding node and p2
1462 - ":tag" defines a local tag for the preceding node
1466 - ":tag" defines a local tag for the preceding node
1463 - "@branch" sets the named branch for subsequent nodes
1467 - "@branch" sets the named branch for subsequent nodes
1464 - "#...\\n" is a comment up to the end of the line
1468 - "#...\\n" is a comment up to the end of the line
1465
1469
1466 Whitespace between the above elements is ignored.
1470 Whitespace between the above elements is ignored.
1467
1471
1468 A backref is either
1472 A backref is either
1469
1473
1470 - a number n, which references the node curr-n, where curr is the current
1474 - a number n, which references the node curr-n, where curr is the current
1471 node, or
1475 node, or
1472 - the name of a local tag you placed earlier using ":tag", or
1476 - the name of a local tag you placed earlier using ":tag", or
1473 - empty to denote the default parent.
1477 - empty to denote the default parent.
1474
1478
1475 All string valued-elements are either strictly alphanumeric, or must
1479 All string valued-elements are either strictly alphanumeric, or must
1476 be enclosed in double quotes ("..."), with "\\" as escape character.
1480 be enclosed in double quotes ("..."), with "\\" as escape character.
1477 """
1481 """
1478
1482
1479 if text is None:
1483 if text is None:
1480 ui.status(_("reading DAG from stdin\n"))
1484 ui.status(_("reading DAG from stdin\n"))
1481 text = ui.fin.read()
1485 text = ui.fin.read()
1482
1486
1483 cl = repo.changelog
1487 cl = repo.changelog
1484 if len(cl) > 0:
1488 if len(cl) > 0:
1485 raise util.Abort(_('repository is not empty'))
1489 raise util.Abort(_('repository is not empty'))
1486
1490
1487 # determine number of revs in DAG
1491 # determine number of revs in DAG
1488 total = 0
1492 total = 0
1489 for type, data in dagparser.parsedag(text):
1493 for type, data in dagparser.parsedag(text):
1490 if type == 'n':
1494 if type == 'n':
1491 total += 1
1495 total += 1
1492
1496
1493 if mergeable_file:
1497 if mergeable_file:
1494 linesperrev = 2
1498 linesperrev = 2
1495 # make a file with k lines per rev
1499 # make a file with k lines per rev
1496 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1500 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1497 initialmergedlines.append("")
1501 initialmergedlines.append("")
1498
1502
1499 tags = []
1503 tags = []
1500
1504
1501 lock = tr = None
1505 lock = tr = None
1502 try:
1506 try:
1503 lock = repo.lock()
1507 lock = repo.lock()
1504 tr = repo.transaction("builddag")
1508 tr = repo.transaction("builddag")
1505
1509
1506 at = -1
1510 at = -1
1507 atbranch = 'default'
1511 atbranch = 'default'
1508 nodeids = []
1512 nodeids = []
1509 id = 0
1513 id = 0
1510 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1514 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1511 for type, data in dagparser.parsedag(text):
1515 for type, data in dagparser.parsedag(text):
1512 if type == 'n':
1516 if type == 'n':
1513 ui.note(('node %s\n' % str(data)))
1517 ui.note(('node %s\n' % str(data)))
1514 id, ps = data
1518 id, ps = data
1515
1519
1516 files = []
1520 files = []
1517 fctxs = {}
1521 fctxs = {}
1518
1522
1519 p2 = None
1523 p2 = None
1520 if mergeable_file:
1524 if mergeable_file:
1521 fn = "mf"
1525 fn = "mf"
1522 p1 = repo[ps[0]]
1526 p1 = repo[ps[0]]
1523 if len(ps) > 1:
1527 if len(ps) > 1:
1524 p2 = repo[ps[1]]
1528 p2 = repo[ps[1]]
1525 pa = p1.ancestor(p2)
1529 pa = p1.ancestor(p2)
1526 base, local, other = [x[fn].data() for x in (pa, p1,
1530 base, local, other = [x[fn].data() for x in (pa, p1,
1527 p2)]
1531 p2)]
1528 m3 = simplemerge.Merge3Text(base, local, other)
1532 m3 = simplemerge.Merge3Text(base, local, other)
1529 ml = [l.strip() for l in m3.merge_lines()]
1533 ml = [l.strip() for l in m3.merge_lines()]
1530 ml.append("")
1534 ml.append("")
1531 elif at > 0:
1535 elif at > 0:
1532 ml = p1[fn].data().split("\n")
1536 ml = p1[fn].data().split("\n")
1533 else:
1537 else:
1534 ml = initialmergedlines
1538 ml = initialmergedlines
1535 ml[id * linesperrev] += " r%i" % id
1539 ml[id * linesperrev] += " r%i" % id
1536 mergedtext = "\n".join(ml)
1540 mergedtext = "\n".join(ml)
1537 files.append(fn)
1541 files.append(fn)
1538 fctxs[fn] = context.memfilectx(fn, mergedtext)
1542 fctxs[fn] = context.memfilectx(fn, mergedtext)
1539
1543
1540 if overwritten_file:
1544 if overwritten_file:
1541 fn = "of"
1545 fn = "of"
1542 files.append(fn)
1546 files.append(fn)
1543 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1547 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1544
1548
1545 if new_file:
1549 if new_file:
1546 fn = "nf%i" % id
1550 fn = "nf%i" % id
1547 files.append(fn)
1551 files.append(fn)
1548 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1552 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1549 if len(ps) > 1:
1553 if len(ps) > 1:
1550 if not p2:
1554 if not p2:
1551 p2 = repo[ps[1]]
1555 p2 = repo[ps[1]]
1552 for fn in p2:
1556 for fn in p2:
1553 if fn.startswith("nf"):
1557 if fn.startswith("nf"):
1554 files.append(fn)
1558 files.append(fn)
1555 fctxs[fn] = p2[fn]
1559 fctxs[fn] = p2[fn]
1556
1560
1557 def fctxfn(repo, cx, path):
1561 def fctxfn(repo, cx, path):
1558 return fctxs.get(path)
1562 return fctxs.get(path)
1559
1563
1560 if len(ps) == 0 or ps[0] < 0:
1564 if len(ps) == 0 or ps[0] < 0:
1561 pars = [None, None]
1565 pars = [None, None]
1562 elif len(ps) == 1:
1566 elif len(ps) == 1:
1563 pars = [nodeids[ps[0]], None]
1567 pars = [nodeids[ps[0]], None]
1564 else:
1568 else:
1565 pars = [nodeids[p] for p in ps]
1569 pars = [nodeids[p] for p in ps]
1566 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1570 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1567 date=(id, 0),
1571 date=(id, 0),
1568 user="debugbuilddag",
1572 user="debugbuilddag",
1569 extra={'branch': atbranch})
1573 extra={'branch': atbranch})
1570 nodeid = repo.commitctx(cx)
1574 nodeid = repo.commitctx(cx)
1571 nodeids.append(nodeid)
1575 nodeids.append(nodeid)
1572 at = id
1576 at = id
1573 elif type == 'l':
1577 elif type == 'l':
1574 id, name = data
1578 id, name = data
1575 ui.note(('tag %s\n' % name))
1579 ui.note(('tag %s\n' % name))
1576 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1580 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1577 elif type == 'a':
1581 elif type == 'a':
1578 ui.note(('branch %s\n' % data))
1582 ui.note(('branch %s\n' % data))
1579 atbranch = data
1583 atbranch = data
1580 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1584 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1581 tr.close()
1585 tr.close()
1582
1586
1583 if tags:
1587 if tags:
1584 repo.opener.write("localtags", "".join(tags))
1588 repo.opener.write("localtags", "".join(tags))
1585 finally:
1589 finally:
1586 ui.progress(_('building'), None)
1590 ui.progress(_('building'), None)
1587 release(tr, lock)
1591 release(tr, lock)
1588
1592
1589 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1593 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1590 def debugbundle(ui, bundlepath, all=None, **opts):
1594 def debugbundle(ui, bundlepath, all=None, **opts):
1591 """lists the contents of a bundle"""
1595 """lists the contents of a bundle"""
1592 f = hg.openpath(ui, bundlepath)
1596 f = hg.openpath(ui, bundlepath)
1593 try:
1597 try:
1594 gen = changegroup.readbundle(f, bundlepath)
1598 gen = changegroup.readbundle(f, bundlepath)
1595 if all:
1599 if all:
1596 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1600 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1597
1601
1598 def showchunks(named):
1602 def showchunks(named):
1599 ui.write("\n%s\n" % named)
1603 ui.write("\n%s\n" % named)
1600 chain = None
1604 chain = None
1601 while True:
1605 while True:
1602 chunkdata = gen.deltachunk(chain)
1606 chunkdata = gen.deltachunk(chain)
1603 if not chunkdata:
1607 if not chunkdata:
1604 break
1608 break
1605 node = chunkdata['node']
1609 node = chunkdata['node']
1606 p1 = chunkdata['p1']
1610 p1 = chunkdata['p1']
1607 p2 = chunkdata['p2']
1611 p2 = chunkdata['p2']
1608 cs = chunkdata['cs']
1612 cs = chunkdata['cs']
1609 deltabase = chunkdata['deltabase']
1613 deltabase = chunkdata['deltabase']
1610 delta = chunkdata['delta']
1614 delta = chunkdata['delta']
1611 ui.write("%s %s %s %s %s %s\n" %
1615 ui.write("%s %s %s %s %s %s\n" %
1612 (hex(node), hex(p1), hex(p2),
1616 (hex(node), hex(p1), hex(p2),
1613 hex(cs), hex(deltabase), len(delta)))
1617 hex(cs), hex(deltabase), len(delta)))
1614 chain = node
1618 chain = node
1615
1619
1616 chunkdata = gen.changelogheader()
1620 chunkdata = gen.changelogheader()
1617 showchunks("changelog")
1621 showchunks("changelog")
1618 chunkdata = gen.manifestheader()
1622 chunkdata = gen.manifestheader()
1619 showchunks("manifest")
1623 showchunks("manifest")
1620 while True:
1624 while True:
1621 chunkdata = gen.filelogheader()
1625 chunkdata = gen.filelogheader()
1622 if not chunkdata:
1626 if not chunkdata:
1623 break
1627 break
1624 fname = chunkdata['filename']
1628 fname = chunkdata['filename']
1625 showchunks(fname)
1629 showchunks(fname)
1626 else:
1630 else:
1627 chunkdata = gen.changelogheader()
1631 chunkdata = gen.changelogheader()
1628 chain = None
1632 chain = None
1629 while True:
1633 while True:
1630 chunkdata = gen.deltachunk(chain)
1634 chunkdata = gen.deltachunk(chain)
1631 if not chunkdata:
1635 if not chunkdata:
1632 break
1636 break
1633 node = chunkdata['node']
1637 node = chunkdata['node']
1634 ui.write("%s\n" % hex(node))
1638 ui.write("%s\n" % hex(node))
1635 chain = node
1639 chain = node
1636 finally:
1640 finally:
1637 f.close()
1641 f.close()
1638
1642
1639 @command('debugcheckstate', [], '')
1643 @command('debugcheckstate', [], '')
1640 def debugcheckstate(ui, repo):
1644 def debugcheckstate(ui, repo):
1641 """validate the correctness of the current dirstate"""
1645 """validate the correctness of the current dirstate"""
1642 parent1, parent2 = repo.dirstate.parents()
1646 parent1, parent2 = repo.dirstate.parents()
1643 m1 = repo[parent1].manifest()
1647 m1 = repo[parent1].manifest()
1644 m2 = repo[parent2].manifest()
1648 m2 = repo[parent2].manifest()
1645 errors = 0
1649 errors = 0
1646 for f in repo.dirstate:
1650 for f in repo.dirstate:
1647 state = repo.dirstate[f]
1651 state = repo.dirstate[f]
1648 if state in "nr" and f not in m1:
1652 if state in "nr" and f not in m1:
1649 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1653 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1650 errors += 1
1654 errors += 1
1651 if state in "a" and f in m1:
1655 if state in "a" and f in m1:
1652 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1656 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1653 errors += 1
1657 errors += 1
1654 if state in "m" and f not in m1 and f not in m2:
1658 if state in "m" and f not in m1 and f not in m2:
1655 ui.warn(_("%s in state %s, but not in either manifest\n") %
1659 ui.warn(_("%s in state %s, but not in either manifest\n") %
1656 (f, state))
1660 (f, state))
1657 errors += 1
1661 errors += 1
1658 for f in m1:
1662 for f in m1:
1659 state = repo.dirstate[f]
1663 state = repo.dirstate[f]
1660 if state not in "nrm":
1664 if state not in "nrm":
1661 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1665 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1662 errors += 1
1666 errors += 1
1663 if errors:
1667 if errors:
1664 error = _(".hg/dirstate inconsistent with current parent's manifest")
1668 error = _(".hg/dirstate inconsistent with current parent's manifest")
1665 raise util.Abort(error)
1669 raise util.Abort(error)
1666
1670
1667 @command('debugcommands', [], _('[COMMAND]'))
1671 @command('debugcommands', [], _('[COMMAND]'))
1668 def debugcommands(ui, cmd='', *args):
1672 def debugcommands(ui, cmd='', *args):
1669 """list all available commands and options"""
1673 """list all available commands and options"""
1670 for cmd, vals in sorted(table.iteritems()):
1674 for cmd, vals in sorted(table.iteritems()):
1671 cmd = cmd.split('|')[0].strip('^')
1675 cmd = cmd.split('|')[0].strip('^')
1672 opts = ', '.join([i[1] for i in vals[1]])
1676 opts = ', '.join([i[1] for i in vals[1]])
1673 ui.write('%s: %s\n' % (cmd, opts))
1677 ui.write('%s: %s\n' % (cmd, opts))
1674
1678
1675 @command('debugcomplete',
1679 @command('debugcomplete',
1676 [('o', 'options', None, _('show the command options'))],
1680 [('o', 'options', None, _('show the command options'))],
1677 _('[-o] CMD'))
1681 _('[-o] CMD'))
1678 def debugcomplete(ui, cmd='', **opts):
1682 def debugcomplete(ui, cmd='', **opts):
1679 """returns the completion list associated with the given command"""
1683 """returns the completion list associated with the given command"""
1680
1684
1681 if opts.get('options'):
1685 if opts.get('options'):
1682 options = []
1686 options = []
1683 otables = [globalopts]
1687 otables = [globalopts]
1684 if cmd:
1688 if cmd:
1685 aliases, entry = cmdutil.findcmd(cmd, table, False)
1689 aliases, entry = cmdutil.findcmd(cmd, table, False)
1686 otables.append(entry[1])
1690 otables.append(entry[1])
1687 for t in otables:
1691 for t in otables:
1688 for o in t:
1692 for o in t:
1689 if "(DEPRECATED)" in o[3]:
1693 if "(DEPRECATED)" in o[3]:
1690 continue
1694 continue
1691 if o[0]:
1695 if o[0]:
1692 options.append('-%s' % o[0])
1696 options.append('-%s' % o[0])
1693 options.append('--%s' % o[1])
1697 options.append('--%s' % o[1])
1694 ui.write("%s\n" % "\n".join(options))
1698 ui.write("%s\n" % "\n".join(options))
1695 return
1699 return
1696
1700
1697 cmdlist = cmdutil.findpossible(cmd, table)
1701 cmdlist = cmdutil.findpossible(cmd, table)
1698 if ui.verbose:
1702 if ui.verbose:
1699 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1703 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1700 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1704 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1701
1705
1702 @command('debugdag',
1706 @command('debugdag',
1703 [('t', 'tags', None, _('use tags as labels')),
1707 [('t', 'tags', None, _('use tags as labels')),
1704 ('b', 'branches', None, _('annotate with branch names')),
1708 ('b', 'branches', None, _('annotate with branch names')),
1705 ('', 'dots', None, _('use dots for runs')),
1709 ('', 'dots', None, _('use dots for runs')),
1706 ('s', 'spaces', None, _('separate elements by spaces'))],
1710 ('s', 'spaces', None, _('separate elements by spaces'))],
1707 _('[OPTION]... [FILE [REV]...]'))
1711 _('[OPTION]... [FILE [REV]...]'))
1708 def debugdag(ui, repo, file_=None, *revs, **opts):
1712 def debugdag(ui, repo, file_=None, *revs, **opts):
1709 """format the changelog or an index DAG as a concise textual description
1713 """format the changelog or an index DAG as a concise textual description
1710
1714
1711 If you pass a revlog index, the revlog's DAG is emitted. If you list
1715 If you pass a revlog index, the revlog's DAG is emitted. If you list
1712 revision numbers, they get labeled in the output as rN.
1716 revision numbers, they get labeled in the output as rN.
1713
1717
1714 Otherwise, the changelog DAG of the current repo is emitted.
1718 Otherwise, the changelog DAG of the current repo is emitted.
1715 """
1719 """
1716 spaces = opts.get('spaces')
1720 spaces = opts.get('spaces')
1717 dots = opts.get('dots')
1721 dots = opts.get('dots')
1718 if file_:
1722 if file_:
1719 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1723 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1720 revs = set((int(r) for r in revs))
1724 revs = set((int(r) for r in revs))
1721 def events():
1725 def events():
1722 for r in rlog:
1726 for r in rlog:
1723 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1727 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1724 if p != -1)))
1728 if p != -1)))
1725 if r in revs:
1729 if r in revs:
1726 yield 'l', (r, "r%i" % r)
1730 yield 'l', (r, "r%i" % r)
1727 elif repo:
1731 elif repo:
1728 cl = repo.changelog
1732 cl = repo.changelog
1729 tags = opts.get('tags')
1733 tags = opts.get('tags')
1730 branches = opts.get('branches')
1734 branches = opts.get('branches')
1731 if tags:
1735 if tags:
1732 labels = {}
1736 labels = {}
1733 for l, n in repo.tags().items():
1737 for l, n in repo.tags().items():
1734 labels.setdefault(cl.rev(n), []).append(l)
1738 labels.setdefault(cl.rev(n), []).append(l)
1735 def events():
1739 def events():
1736 b = "default"
1740 b = "default"
1737 for r in cl:
1741 for r in cl:
1738 if branches:
1742 if branches:
1739 newb = cl.read(cl.node(r))[5]['branch']
1743 newb = cl.read(cl.node(r))[5]['branch']
1740 if newb != b:
1744 if newb != b:
1741 yield 'a', newb
1745 yield 'a', newb
1742 b = newb
1746 b = newb
1743 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1747 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1744 if p != -1)))
1748 if p != -1)))
1745 if tags:
1749 if tags:
1746 ls = labels.get(r)
1750 ls = labels.get(r)
1747 if ls:
1751 if ls:
1748 for l in ls:
1752 for l in ls:
1749 yield 'l', (r, l)
1753 yield 'l', (r, l)
1750 else:
1754 else:
1751 raise util.Abort(_('need repo for changelog dag'))
1755 raise util.Abort(_('need repo for changelog dag'))
1752
1756
1753 for line in dagparser.dagtextlines(events(),
1757 for line in dagparser.dagtextlines(events(),
1754 addspaces=spaces,
1758 addspaces=spaces,
1755 wraplabels=True,
1759 wraplabels=True,
1756 wrapannotations=True,
1760 wrapannotations=True,
1757 wrapnonlinear=dots,
1761 wrapnonlinear=dots,
1758 usedots=dots,
1762 usedots=dots,
1759 maxlinewidth=70):
1763 maxlinewidth=70):
1760 ui.write(line)
1764 ui.write(line)
1761 ui.write("\n")
1765 ui.write("\n")
1762
1766
1763 @command('debugdata',
1767 @command('debugdata',
1764 [('c', 'changelog', False, _('open changelog')),
1768 [('c', 'changelog', False, _('open changelog')),
1765 ('m', 'manifest', False, _('open manifest'))],
1769 ('m', 'manifest', False, _('open manifest'))],
1766 _('-c|-m|FILE REV'))
1770 _('-c|-m|FILE REV'))
1767 def debugdata(ui, repo, file_, rev = None, **opts):
1771 def debugdata(ui, repo, file_, rev = None, **opts):
1768 """dump the contents of a data file revision"""
1772 """dump the contents of a data file revision"""
1769 if opts.get('changelog') or opts.get('manifest'):
1773 if opts.get('changelog') or opts.get('manifest'):
1770 file_, rev = None, file_
1774 file_, rev = None, file_
1771 elif rev is None:
1775 elif rev is None:
1772 raise error.CommandError('debugdata', _('invalid arguments'))
1776 raise error.CommandError('debugdata', _('invalid arguments'))
1773 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1777 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1774 try:
1778 try:
1775 ui.write(r.revision(r.lookup(rev)))
1779 ui.write(r.revision(r.lookup(rev)))
1776 except KeyError:
1780 except KeyError:
1777 raise util.Abort(_('invalid revision identifier %s') % rev)
1781 raise util.Abort(_('invalid revision identifier %s') % rev)
1778
1782
1779 @command('debugdate',
1783 @command('debugdate',
1780 [('e', 'extended', None, _('try extended date formats'))],
1784 [('e', 'extended', None, _('try extended date formats'))],
1781 _('[-e] DATE [RANGE]'))
1785 _('[-e] DATE [RANGE]'))
1782 def debugdate(ui, date, range=None, **opts):
1786 def debugdate(ui, date, range=None, **opts):
1783 """parse and display a date"""
1787 """parse and display a date"""
1784 if opts["extended"]:
1788 if opts["extended"]:
1785 d = util.parsedate(date, util.extendeddateformats)
1789 d = util.parsedate(date, util.extendeddateformats)
1786 else:
1790 else:
1787 d = util.parsedate(date)
1791 d = util.parsedate(date)
1788 ui.write(("internal: %s %s\n") % d)
1792 ui.write(("internal: %s %s\n") % d)
1789 ui.write(("standard: %s\n") % util.datestr(d))
1793 ui.write(("standard: %s\n") % util.datestr(d))
1790 if range:
1794 if range:
1791 m = util.matchdate(range)
1795 m = util.matchdate(range)
1792 ui.write(("match: %s\n") % m(d[0]))
1796 ui.write(("match: %s\n") % m(d[0]))
1793
1797
1794 @command('debugdiscovery',
1798 @command('debugdiscovery',
1795 [('', 'old', None, _('use old-style discovery')),
1799 [('', 'old', None, _('use old-style discovery')),
1796 ('', 'nonheads', None,
1800 ('', 'nonheads', None,
1797 _('use old-style discovery with non-heads included')),
1801 _('use old-style discovery with non-heads included')),
1798 ] + remoteopts,
1802 ] + remoteopts,
1799 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1803 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1800 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1804 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1801 """runs the changeset discovery protocol in isolation"""
1805 """runs the changeset discovery protocol in isolation"""
1802 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1806 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1803 opts.get('branch'))
1807 opts.get('branch'))
1804 remote = hg.peer(repo, opts, remoteurl)
1808 remote = hg.peer(repo, opts, remoteurl)
1805 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1809 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1806
1810
1807 # make sure tests are repeatable
1811 # make sure tests are repeatable
1808 random.seed(12323)
1812 random.seed(12323)
1809
1813
1810 def doit(localheads, remoteheads, remote=remote):
1814 def doit(localheads, remoteheads, remote=remote):
1811 if opts.get('old'):
1815 if opts.get('old'):
1812 if localheads:
1816 if localheads:
1813 raise util.Abort('cannot use localheads with old style '
1817 raise util.Abort('cannot use localheads with old style '
1814 'discovery')
1818 'discovery')
1815 if not util.safehasattr(remote, 'branches'):
1819 if not util.safehasattr(remote, 'branches'):
1816 # enable in-client legacy support
1820 # enable in-client legacy support
1817 remote = localrepo.locallegacypeer(remote.local())
1821 remote = localrepo.locallegacypeer(remote.local())
1818 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1822 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1819 force=True)
1823 force=True)
1820 common = set(common)
1824 common = set(common)
1821 if not opts.get('nonheads'):
1825 if not opts.get('nonheads'):
1822 ui.write(("unpruned common: %s\n") %
1826 ui.write(("unpruned common: %s\n") %
1823 " ".join(sorted(short(n) for n in common)))
1827 " ".join(sorted(short(n) for n in common)))
1824 dag = dagutil.revlogdag(repo.changelog)
1828 dag = dagutil.revlogdag(repo.changelog)
1825 all = dag.ancestorset(dag.internalizeall(common))
1829 all = dag.ancestorset(dag.internalizeall(common))
1826 common = dag.externalizeall(dag.headsetofconnecteds(all))
1830 common = dag.externalizeall(dag.headsetofconnecteds(all))
1827 else:
1831 else:
1828 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1832 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1829 common = set(common)
1833 common = set(common)
1830 rheads = set(hds)
1834 rheads = set(hds)
1831 lheads = set(repo.heads())
1835 lheads = set(repo.heads())
1832 ui.write(("common heads: %s\n") %
1836 ui.write(("common heads: %s\n") %
1833 " ".join(sorted(short(n) for n in common)))
1837 " ".join(sorted(short(n) for n in common)))
1834 if lheads <= common:
1838 if lheads <= common:
1835 ui.write(("local is subset\n"))
1839 ui.write(("local is subset\n"))
1836 elif rheads <= common:
1840 elif rheads <= common:
1837 ui.write(("remote is subset\n"))
1841 ui.write(("remote is subset\n"))
1838
1842
1839 serverlogs = opts.get('serverlog')
1843 serverlogs = opts.get('serverlog')
1840 if serverlogs:
1844 if serverlogs:
1841 for filename in serverlogs:
1845 for filename in serverlogs:
1842 logfile = open(filename, 'r')
1846 logfile = open(filename, 'r')
1843 try:
1847 try:
1844 line = logfile.readline()
1848 line = logfile.readline()
1845 while line:
1849 while line:
1846 parts = line.strip().split(';')
1850 parts = line.strip().split(';')
1847 op = parts[1]
1851 op = parts[1]
1848 if op == 'cg':
1852 if op == 'cg':
1849 pass
1853 pass
1850 elif op == 'cgss':
1854 elif op == 'cgss':
1851 doit(parts[2].split(' '), parts[3].split(' '))
1855 doit(parts[2].split(' '), parts[3].split(' '))
1852 elif op == 'unb':
1856 elif op == 'unb':
1853 doit(parts[3].split(' '), parts[2].split(' '))
1857 doit(parts[3].split(' '), parts[2].split(' '))
1854 line = logfile.readline()
1858 line = logfile.readline()
1855 finally:
1859 finally:
1856 logfile.close()
1860 logfile.close()
1857
1861
1858 else:
1862 else:
1859 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1863 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1860 opts.get('remote_head'))
1864 opts.get('remote_head'))
1861 localrevs = opts.get('local_head')
1865 localrevs = opts.get('local_head')
1862 doit(localrevs, remoterevs)
1866 doit(localrevs, remoterevs)
1863
1867
1864 @command('debugfileset',
1868 @command('debugfileset',
1865 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1869 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1866 _('[-r REV] FILESPEC'))
1870 _('[-r REV] FILESPEC'))
1867 def debugfileset(ui, repo, expr, **opts):
1871 def debugfileset(ui, repo, expr, **opts):
1868 '''parse and apply a fileset specification'''
1872 '''parse and apply a fileset specification'''
1869 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1873 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1870 if ui.verbose:
1874 if ui.verbose:
1871 tree = fileset.parse(expr)[0]
1875 tree = fileset.parse(expr)[0]
1872 ui.note(tree, "\n")
1876 ui.note(tree, "\n")
1873
1877
1874 for f in fileset.getfileset(ctx, expr):
1878 for f in fileset.getfileset(ctx, expr):
1875 ui.write("%s\n" % f)
1879 ui.write("%s\n" % f)
1876
1880
1877 @command('debugfsinfo', [], _('[PATH]'))
1881 @command('debugfsinfo', [], _('[PATH]'))
1878 def debugfsinfo(ui, path = "."):
1882 def debugfsinfo(ui, path = "."):
1879 """show information detected about current filesystem"""
1883 """show information detected about current filesystem"""
1880 util.writefile('.debugfsinfo', '')
1884 util.writefile('.debugfsinfo', '')
1881 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1885 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1882 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1886 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1883 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1887 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1884 and 'yes' or 'no'))
1888 and 'yes' or 'no'))
1885 os.unlink('.debugfsinfo')
1889 os.unlink('.debugfsinfo')
1886
1890
1887 @command('debuggetbundle',
1891 @command('debuggetbundle',
1888 [('H', 'head', [], _('id of head node'), _('ID')),
1892 [('H', 'head', [], _('id of head node'), _('ID')),
1889 ('C', 'common', [], _('id of common node'), _('ID')),
1893 ('C', 'common', [], _('id of common node'), _('ID')),
1890 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1894 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1891 _('REPO FILE [-H|-C ID]...'))
1895 _('REPO FILE [-H|-C ID]...'))
1892 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1896 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1893 """retrieves a bundle from a repo
1897 """retrieves a bundle from a repo
1894
1898
1895 Every ID must be a full-length hex node id string. Saves the bundle to the
1899 Every ID must be a full-length hex node id string. Saves the bundle to the
1896 given file.
1900 given file.
1897 """
1901 """
1898 repo = hg.peer(ui, opts, repopath)
1902 repo = hg.peer(ui, opts, repopath)
1899 if not repo.capable('getbundle'):
1903 if not repo.capable('getbundle'):
1900 raise util.Abort("getbundle() not supported by target repository")
1904 raise util.Abort("getbundle() not supported by target repository")
1901 args = {}
1905 args = {}
1902 if common:
1906 if common:
1903 args['common'] = [bin(s) for s in common]
1907 args['common'] = [bin(s) for s in common]
1904 if head:
1908 if head:
1905 args['heads'] = [bin(s) for s in head]
1909 args['heads'] = [bin(s) for s in head]
1906 bundle = repo.getbundle('debug', **args)
1910 bundle = repo.getbundle('debug', **args)
1907
1911
1908 bundletype = opts.get('type', 'bzip2').lower()
1912 bundletype = opts.get('type', 'bzip2').lower()
1909 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1913 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1910 bundletype = btypes.get(bundletype)
1914 bundletype = btypes.get(bundletype)
1911 if bundletype not in changegroup.bundletypes:
1915 if bundletype not in changegroup.bundletypes:
1912 raise util.Abort(_('unknown bundle type specified with --type'))
1916 raise util.Abort(_('unknown bundle type specified with --type'))
1913 changegroup.writebundle(bundle, bundlepath, bundletype)
1917 changegroup.writebundle(bundle, bundlepath, bundletype)
1914
1918
1915 @command('debugignore', [], '')
1919 @command('debugignore', [], '')
1916 def debugignore(ui, repo, *values, **opts):
1920 def debugignore(ui, repo, *values, **opts):
1917 """display the combined ignore pattern"""
1921 """display the combined ignore pattern"""
1918 ignore = repo.dirstate._ignore
1922 ignore = repo.dirstate._ignore
1919 includepat = getattr(ignore, 'includepat', None)
1923 includepat = getattr(ignore, 'includepat', None)
1920 if includepat is not None:
1924 if includepat is not None:
1921 ui.write("%s\n" % includepat)
1925 ui.write("%s\n" % includepat)
1922 else:
1926 else:
1923 raise util.Abort(_("no ignore patterns found"))
1927 raise util.Abort(_("no ignore patterns found"))
1924
1928
1925 @command('debugindex',
1929 @command('debugindex',
1926 [('c', 'changelog', False, _('open changelog')),
1930 [('c', 'changelog', False, _('open changelog')),
1927 ('m', 'manifest', False, _('open manifest')),
1931 ('m', 'manifest', False, _('open manifest')),
1928 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1932 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1929 _('[-f FORMAT] -c|-m|FILE'))
1933 _('[-f FORMAT] -c|-m|FILE'))
1930 def debugindex(ui, repo, file_ = None, **opts):
1934 def debugindex(ui, repo, file_ = None, **opts):
1931 """dump the contents of an index file"""
1935 """dump the contents of an index file"""
1932 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1936 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1933 format = opts.get('format', 0)
1937 format = opts.get('format', 0)
1934 if format not in (0, 1):
1938 if format not in (0, 1):
1935 raise util.Abort(_("unknown format %d") % format)
1939 raise util.Abort(_("unknown format %d") % format)
1936
1940
1937 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1941 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1938 if generaldelta:
1942 if generaldelta:
1939 basehdr = ' delta'
1943 basehdr = ' delta'
1940 else:
1944 else:
1941 basehdr = ' base'
1945 basehdr = ' base'
1942
1946
1943 if format == 0:
1947 if format == 0:
1944 ui.write(" rev offset length " + basehdr + " linkrev"
1948 ui.write(" rev offset length " + basehdr + " linkrev"
1945 " nodeid p1 p2\n")
1949 " nodeid p1 p2\n")
1946 elif format == 1:
1950 elif format == 1:
1947 ui.write(" rev flag offset length"
1951 ui.write(" rev flag offset length"
1948 " size " + basehdr + " link p1 p2"
1952 " size " + basehdr + " link p1 p2"
1949 " nodeid\n")
1953 " nodeid\n")
1950
1954
1951 for i in r:
1955 for i in r:
1952 node = r.node(i)
1956 node = r.node(i)
1953 if generaldelta:
1957 if generaldelta:
1954 base = r.deltaparent(i)
1958 base = r.deltaparent(i)
1955 else:
1959 else:
1956 base = r.chainbase(i)
1960 base = r.chainbase(i)
1957 if format == 0:
1961 if format == 0:
1958 try:
1962 try:
1959 pp = r.parents(node)
1963 pp = r.parents(node)
1960 except Exception:
1964 except Exception:
1961 pp = [nullid, nullid]
1965 pp = [nullid, nullid]
1962 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1966 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1963 i, r.start(i), r.length(i), base, r.linkrev(i),
1967 i, r.start(i), r.length(i), base, r.linkrev(i),
1964 short(node), short(pp[0]), short(pp[1])))
1968 short(node), short(pp[0]), short(pp[1])))
1965 elif format == 1:
1969 elif format == 1:
1966 pr = r.parentrevs(i)
1970 pr = r.parentrevs(i)
1967 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1971 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1968 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1972 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1969 base, r.linkrev(i), pr[0], pr[1], short(node)))
1973 base, r.linkrev(i), pr[0], pr[1], short(node)))
1970
1974
1971 @command('debugindexdot', [], _('FILE'))
1975 @command('debugindexdot', [], _('FILE'))
1972 def debugindexdot(ui, repo, file_):
1976 def debugindexdot(ui, repo, file_):
1973 """dump an index DAG as a graphviz dot file"""
1977 """dump an index DAG as a graphviz dot file"""
1974 r = None
1978 r = None
1975 if repo:
1979 if repo:
1976 filelog = repo.file(file_)
1980 filelog = repo.file(file_)
1977 if len(filelog):
1981 if len(filelog):
1978 r = filelog
1982 r = filelog
1979 if not r:
1983 if not r:
1980 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1984 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1981 ui.write(("digraph G {\n"))
1985 ui.write(("digraph G {\n"))
1982 for i in r:
1986 for i in r:
1983 node = r.node(i)
1987 node = r.node(i)
1984 pp = r.parents(node)
1988 pp = r.parents(node)
1985 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1989 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1986 if pp[1] != nullid:
1990 if pp[1] != nullid:
1987 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1991 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1988 ui.write("}\n")
1992 ui.write("}\n")
1989
1993
1990 @command('debuginstall', [], '')
1994 @command('debuginstall', [], '')
1991 def debuginstall(ui):
1995 def debuginstall(ui):
1992 '''test Mercurial installation
1996 '''test Mercurial installation
1993
1997
1994 Returns 0 on success.
1998 Returns 0 on success.
1995 '''
1999 '''
1996
2000
1997 def writetemp(contents):
2001 def writetemp(contents):
1998 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2002 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1999 f = os.fdopen(fd, "wb")
2003 f = os.fdopen(fd, "wb")
2000 f.write(contents)
2004 f.write(contents)
2001 f.close()
2005 f.close()
2002 return name
2006 return name
2003
2007
2004 problems = 0
2008 problems = 0
2005
2009
2006 # encoding
2010 # encoding
2007 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2011 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2008 try:
2012 try:
2009 encoding.fromlocal("test")
2013 encoding.fromlocal("test")
2010 except util.Abort, inst:
2014 except util.Abort, inst:
2011 ui.write(" %s\n" % inst)
2015 ui.write(" %s\n" % inst)
2012 ui.write(_(" (check that your locale is properly set)\n"))
2016 ui.write(_(" (check that your locale is properly set)\n"))
2013 problems += 1
2017 problems += 1
2014
2018
2015 # Python lib
2019 # Python lib
2016 ui.status(_("checking Python lib (%s)...\n")
2020 ui.status(_("checking Python lib (%s)...\n")
2017 % os.path.dirname(os.__file__))
2021 % os.path.dirname(os.__file__))
2018
2022
2019 # compiled modules
2023 # compiled modules
2020 ui.status(_("checking installed modules (%s)...\n")
2024 ui.status(_("checking installed modules (%s)...\n")
2021 % os.path.dirname(__file__))
2025 % os.path.dirname(__file__))
2022 try:
2026 try:
2023 import bdiff, mpatch, base85, osutil
2027 import bdiff, mpatch, base85, osutil
2024 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2028 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2025 except Exception, inst:
2029 except Exception, inst:
2026 ui.write(" %s\n" % inst)
2030 ui.write(" %s\n" % inst)
2027 ui.write(_(" One or more extensions could not be found"))
2031 ui.write(_(" One or more extensions could not be found"))
2028 ui.write(_(" (check that you compiled the extensions)\n"))
2032 ui.write(_(" (check that you compiled the extensions)\n"))
2029 problems += 1
2033 problems += 1
2030
2034
2031 # templates
2035 # templates
2032 import templater
2036 import templater
2033 p = templater.templatepath()
2037 p = templater.templatepath()
2034 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2038 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2035 try:
2039 try:
2036 templater.templater(templater.templatepath("map-cmdline.default"))
2040 templater.templater(templater.templatepath("map-cmdline.default"))
2037 except Exception, inst:
2041 except Exception, inst:
2038 ui.write(" %s\n" % inst)
2042 ui.write(" %s\n" % inst)
2039 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2043 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2040 problems += 1
2044 problems += 1
2041
2045
2042 # editor
2046 # editor
2043 ui.status(_("checking commit editor...\n"))
2047 ui.status(_("checking commit editor...\n"))
2044 editor = ui.geteditor()
2048 editor = ui.geteditor()
2045 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2049 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2046 if not cmdpath:
2050 if not cmdpath:
2047 if editor == 'vi':
2051 if editor == 'vi':
2048 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2052 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2049 ui.write(_(" (specify a commit editor in your configuration"
2053 ui.write(_(" (specify a commit editor in your configuration"
2050 " file)\n"))
2054 " file)\n"))
2051 else:
2055 else:
2052 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2056 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2053 ui.write(_(" (specify a commit editor in your configuration"
2057 ui.write(_(" (specify a commit editor in your configuration"
2054 " file)\n"))
2058 " file)\n"))
2055 problems += 1
2059 problems += 1
2056
2060
2057 # check username
2061 # check username
2058 ui.status(_("checking username...\n"))
2062 ui.status(_("checking username...\n"))
2059 try:
2063 try:
2060 ui.username()
2064 ui.username()
2061 except util.Abort, e:
2065 except util.Abort, e:
2062 ui.write(" %s\n" % e)
2066 ui.write(" %s\n" % e)
2063 ui.write(_(" (specify a username in your configuration file)\n"))
2067 ui.write(_(" (specify a username in your configuration file)\n"))
2064 problems += 1
2068 problems += 1
2065
2069
2066 if not problems:
2070 if not problems:
2067 ui.status(_("no problems detected\n"))
2071 ui.status(_("no problems detected\n"))
2068 else:
2072 else:
2069 ui.write(_("%s problems detected,"
2073 ui.write(_("%s problems detected,"
2070 " please check your install!\n") % problems)
2074 " please check your install!\n") % problems)
2071
2075
2072 return problems
2076 return problems
2073
2077
2074 @command('debugknown', [], _('REPO ID...'))
2078 @command('debugknown', [], _('REPO ID...'))
2075 def debugknown(ui, repopath, *ids, **opts):
2079 def debugknown(ui, repopath, *ids, **opts):
2076 """test whether node ids are known to a repo
2080 """test whether node ids are known to a repo
2077
2081
2078 Every ID must be a full-length hex node id string. Returns a list of 0s
2082 Every ID must be a full-length hex node id string. Returns a list of 0s
2079 and 1s indicating unknown/known.
2083 and 1s indicating unknown/known.
2080 """
2084 """
2081 repo = hg.peer(ui, opts, repopath)
2085 repo = hg.peer(ui, opts, repopath)
2082 if not repo.capable('known'):
2086 if not repo.capable('known'):
2083 raise util.Abort("known() not supported by target repository")
2087 raise util.Abort("known() not supported by target repository")
2084 flags = repo.known([bin(s) for s in ids])
2088 flags = repo.known([bin(s) for s in ids])
2085 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2089 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2086
2090
2087 @command('debuglabelcomplete', [], _('LABEL...'))
2091 @command('debuglabelcomplete', [], _('LABEL...'))
2088 def debuglabelcomplete(ui, repo, *args):
2092 def debuglabelcomplete(ui, repo, *args):
2089 '''complete "labels" - tags, open branch names, bookmark names'''
2093 '''complete "labels" - tags, open branch names, bookmark names'''
2090
2094
2091 labels = set()
2095 labels = set()
2092 labels.update(t[0] for t in repo.tagslist())
2096 labels.update(t[0] for t in repo.tagslist())
2093 labels.update(repo._bookmarks.keys())
2097 labels.update(repo._bookmarks.keys())
2094 for heads in repo.branchmap().itervalues():
2098 for heads in repo.branchmap().itervalues():
2095 for h in heads:
2099 for h in heads:
2096 ctx = repo[h]
2100 ctx = repo[h]
2097 if not ctx.closesbranch():
2101 if not ctx.closesbranch():
2098 labels.add(ctx.branch())
2102 labels.add(ctx.branch())
2099 completions = set()
2103 completions = set()
2100 if not args:
2104 if not args:
2101 args = ['']
2105 args = ['']
2102 for a in args:
2106 for a in args:
2103 completions.update(l for l in labels if l.startswith(a))
2107 completions.update(l for l in labels if l.startswith(a))
2104 ui.write('\n'.join(sorted(completions)))
2108 ui.write('\n'.join(sorted(completions)))
2105 ui.write('\n')
2109 ui.write('\n')
2106
2110
2107 @command('debugobsolete',
2111 @command('debugobsolete',
2108 [('', 'flags', 0, _('markers flag')),
2112 [('', 'flags', 0, _('markers flag')),
2109 ] + commitopts2,
2113 ] + commitopts2,
2110 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2114 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2111 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2115 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2112 """create arbitrary obsolete marker
2116 """create arbitrary obsolete marker
2113
2117
2114 With no arguments, displays the list of obsolescence markers."""
2118 With no arguments, displays the list of obsolescence markers."""
2115 def parsenodeid(s):
2119 def parsenodeid(s):
2116 try:
2120 try:
2117 # We do not use revsingle/revrange functions here to accept
2121 # We do not use revsingle/revrange functions here to accept
2118 # arbitrary node identifiers, possibly not present in the
2122 # arbitrary node identifiers, possibly not present in the
2119 # local repository.
2123 # local repository.
2120 n = bin(s)
2124 n = bin(s)
2121 if len(n) != len(nullid):
2125 if len(n) != len(nullid):
2122 raise TypeError()
2126 raise TypeError()
2123 return n
2127 return n
2124 except TypeError:
2128 except TypeError:
2125 raise util.Abort('changeset references must be full hexadecimal '
2129 raise util.Abort('changeset references must be full hexadecimal '
2126 'node identifiers')
2130 'node identifiers')
2127
2131
2128 if precursor is not None:
2132 if precursor is not None:
2129 metadata = {}
2133 metadata = {}
2130 if 'date' in opts:
2134 if 'date' in opts:
2131 metadata['date'] = opts['date']
2135 metadata['date'] = opts['date']
2132 metadata['user'] = opts['user'] or ui.username()
2136 metadata['user'] = opts['user'] or ui.username()
2133 succs = tuple(parsenodeid(succ) for succ in successors)
2137 succs = tuple(parsenodeid(succ) for succ in successors)
2134 l = repo.lock()
2138 l = repo.lock()
2135 try:
2139 try:
2136 tr = repo.transaction('debugobsolete')
2140 tr = repo.transaction('debugobsolete')
2137 try:
2141 try:
2138 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2142 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2139 opts['flags'], metadata)
2143 opts['flags'], metadata)
2140 tr.close()
2144 tr.close()
2141 finally:
2145 finally:
2142 tr.release()
2146 tr.release()
2143 finally:
2147 finally:
2144 l.release()
2148 l.release()
2145 else:
2149 else:
2146 for m in obsolete.allmarkers(repo):
2150 for m in obsolete.allmarkers(repo):
2147 ui.write(hex(m.precnode()))
2151 ui.write(hex(m.precnode()))
2148 for repl in m.succnodes():
2152 for repl in m.succnodes():
2149 ui.write(' ')
2153 ui.write(' ')
2150 ui.write(hex(repl))
2154 ui.write(hex(repl))
2151 ui.write(' %X ' % m._data[2])
2155 ui.write(' %X ' % m._data[2])
2152 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2156 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2153 sorted(m.metadata().items()))))
2157 sorted(m.metadata().items()))))
2154 ui.write('\n')
2158 ui.write('\n')
2155
2159
2156 @command('debugpathcomplete',
2160 @command('debugpathcomplete',
2157 [('f', 'full', None, _('complete an entire path')),
2161 [('f', 'full', None, _('complete an entire path')),
2158 ('n', 'normal', None, _('show only normal files')),
2162 ('n', 'normal', None, _('show only normal files')),
2159 ('a', 'added', None, _('show only added files')),
2163 ('a', 'added', None, _('show only added files')),
2160 ('r', 'removed', None, _('show only removed files'))],
2164 ('r', 'removed', None, _('show only removed files'))],
2161 _('FILESPEC...'))
2165 _('FILESPEC...'))
2162 def debugpathcomplete(ui, repo, *specs, **opts):
2166 def debugpathcomplete(ui, repo, *specs, **opts):
2163 '''complete part or all of a tracked path
2167 '''complete part or all of a tracked path
2164
2168
2165 This command supports shells that offer path name completion. It
2169 This command supports shells that offer path name completion. It
2166 currently completes only files already known to the dirstate.
2170 currently completes only files already known to the dirstate.
2167
2171
2168 Completion extends only to the next path segment unless
2172 Completion extends only to the next path segment unless
2169 --full is specified, in which case entire paths are used.'''
2173 --full is specified, in which case entire paths are used.'''
2170
2174
2171 def complete(path, acceptable):
2175 def complete(path, acceptable):
2172 dirstate = repo.dirstate
2176 dirstate = repo.dirstate
2173 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2177 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2174 rootdir = repo.root + os.sep
2178 rootdir = repo.root + os.sep
2175 if spec != repo.root and not spec.startswith(rootdir):
2179 if spec != repo.root and not spec.startswith(rootdir):
2176 return [], []
2180 return [], []
2177 if os.path.isdir(spec):
2181 if os.path.isdir(spec):
2178 spec += '/'
2182 spec += '/'
2179 spec = spec[len(rootdir):]
2183 spec = spec[len(rootdir):]
2180 fixpaths = os.sep != '/'
2184 fixpaths = os.sep != '/'
2181 if fixpaths:
2185 if fixpaths:
2182 spec = spec.replace(os.sep, '/')
2186 spec = spec.replace(os.sep, '/')
2183 speclen = len(spec)
2187 speclen = len(spec)
2184 fullpaths = opts['full']
2188 fullpaths = opts['full']
2185 files, dirs = set(), set()
2189 files, dirs = set(), set()
2186 adddir, addfile = dirs.add, files.add
2190 adddir, addfile = dirs.add, files.add
2187 for f, st in dirstate.iteritems():
2191 for f, st in dirstate.iteritems():
2188 if f.startswith(spec) and st[0] in acceptable:
2192 if f.startswith(spec) and st[0] in acceptable:
2189 if fixpaths:
2193 if fixpaths:
2190 f = f.replace('/', os.sep)
2194 f = f.replace('/', os.sep)
2191 if fullpaths:
2195 if fullpaths:
2192 addfile(f)
2196 addfile(f)
2193 continue
2197 continue
2194 s = f.find(os.sep, speclen)
2198 s = f.find(os.sep, speclen)
2195 if s >= 0:
2199 if s >= 0:
2196 adddir(f[:s + 1])
2200 adddir(f[:s + 1])
2197 else:
2201 else:
2198 addfile(f)
2202 addfile(f)
2199 return files, dirs
2203 return files, dirs
2200
2204
2201 acceptable = ''
2205 acceptable = ''
2202 if opts['normal']:
2206 if opts['normal']:
2203 acceptable += 'nm'
2207 acceptable += 'nm'
2204 if opts['added']:
2208 if opts['added']:
2205 acceptable += 'a'
2209 acceptable += 'a'
2206 if opts['removed']:
2210 if opts['removed']:
2207 acceptable += 'r'
2211 acceptable += 'r'
2208 cwd = repo.getcwd()
2212 cwd = repo.getcwd()
2209 if not specs:
2213 if not specs:
2210 specs = ['.']
2214 specs = ['.']
2211
2215
2212 files, dirs = set(), set()
2216 files, dirs = set(), set()
2213 for spec in specs:
2217 for spec in specs:
2214 f, d = complete(spec, acceptable or 'nmar')
2218 f, d = complete(spec, acceptable or 'nmar')
2215 files.update(f)
2219 files.update(f)
2216 dirs.update(d)
2220 dirs.update(d)
2217 if not files and len(dirs) == 1:
2221 if not files and len(dirs) == 1:
2218 # force the shell to consider a completion that matches one
2222 # force the shell to consider a completion that matches one
2219 # directory and zero files to be ambiguous
2223 # directory and zero files to be ambiguous
2220 dirs.add(iter(dirs).next() + '.')
2224 dirs.add(iter(dirs).next() + '.')
2221 files.update(dirs)
2225 files.update(dirs)
2222 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2226 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2223 ui.write('\n')
2227 ui.write('\n')
2224
2228
2225 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2229 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2226 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2230 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2227 '''access the pushkey key/value protocol
2231 '''access the pushkey key/value protocol
2228
2232
2229 With two args, list the keys in the given namespace.
2233 With two args, list the keys in the given namespace.
2230
2234
2231 With five args, set a key to new if it currently is set to old.
2235 With five args, set a key to new if it currently is set to old.
2232 Reports success or failure.
2236 Reports success or failure.
2233 '''
2237 '''
2234
2238
2235 target = hg.peer(ui, {}, repopath)
2239 target = hg.peer(ui, {}, repopath)
2236 if keyinfo:
2240 if keyinfo:
2237 key, old, new = keyinfo
2241 key, old, new = keyinfo
2238 r = target.pushkey(namespace, key, old, new)
2242 r = target.pushkey(namespace, key, old, new)
2239 ui.status(str(r) + '\n')
2243 ui.status(str(r) + '\n')
2240 return not r
2244 return not r
2241 else:
2245 else:
2242 for k, v in sorted(target.listkeys(namespace).iteritems()):
2246 for k, v in sorted(target.listkeys(namespace).iteritems()):
2243 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2247 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2244 v.encode('string-escape')))
2248 v.encode('string-escape')))
2245
2249
2246 @command('debugpvec', [], _('A B'))
2250 @command('debugpvec', [], _('A B'))
2247 def debugpvec(ui, repo, a, b=None):
2251 def debugpvec(ui, repo, a, b=None):
2248 ca = scmutil.revsingle(repo, a)
2252 ca = scmutil.revsingle(repo, a)
2249 cb = scmutil.revsingle(repo, b)
2253 cb = scmutil.revsingle(repo, b)
2250 pa = pvec.ctxpvec(ca)
2254 pa = pvec.ctxpvec(ca)
2251 pb = pvec.ctxpvec(cb)
2255 pb = pvec.ctxpvec(cb)
2252 if pa == pb:
2256 if pa == pb:
2253 rel = "="
2257 rel = "="
2254 elif pa > pb:
2258 elif pa > pb:
2255 rel = ">"
2259 rel = ">"
2256 elif pa < pb:
2260 elif pa < pb:
2257 rel = "<"
2261 rel = "<"
2258 elif pa | pb:
2262 elif pa | pb:
2259 rel = "|"
2263 rel = "|"
2260 ui.write(_("a: %s\n") % pa)
2264 ui.write(_("a: %s\n") % pa)
2261 ui.write(_("b: %s\n") % pb)
2265 ui.write(_("b: %s\n") % pb)
2262 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2266 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2263 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2267 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2264 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2268 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2265 pa.distance(pb), rel))
2269 pa.distance(pb), rel))
2266
2270
2267 @command('debugrebuilddirstate|debugrebuildstate',
2271 @command('debugrebuilddirstate|debugrebuildstate',
2268 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2272 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2269 _('[-r REV]'))
2273 _('[-r REV]'))
2270 def debugrebuilddirstate(ui, repo, rev):
2274 def debugrebuilddirstate(ui, repo, rev):
2271 """rebuild the dirstate as it would look like for the given revision
2275 """rebuild the dirstate as it would look like for the given revision
2272
2276
2273 If no revision is specified the first current parent will be used.
2277 If no revision is specified the first current parent will be used.
2274
2278
2275 The dirstate will be set to the files of the given revision.
2279 The dirstate will be set to the files of the given revision.
2276 The actual working directory content or existing dirstate
2280 The actual working directory content or existing dirstate
2277 information such as adds or removes is not considered.
2281 information such as adds or removes is not considered.
2278
2282
2279 One use of this command is to make the next :hg:`status` invocation
2283 One use of this command is to make the next :hg:`status` invocation
2280 check the actual file content.
2284 check the actual file content.
2281 """
2285 """
2282 ctx = scmutil.revsingle(repo, rev)
2286 ctx = scmutil.revsingle(repo, rev)
2283 wlock = repo.wlock()
2287 wlock = repo.wlock()
2284 try:
2288 try:
2285 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2289 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2286 finally:
2290 finally:
2287 wlock.release()
2291 wlock.release()
2288
2292
2289 @command('debugrename',
2293 @command('debugrename',
2290 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2294 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2291 _('[-r REV] FILE'))
2295 _('[-r REV] FILE'))
2292 def debugrename(ui, repo, file1, *pats, **opts):
2296 def debugrename(ui, repo, file1, *pats, **opts):
2293 """dump rename information"""
2297 """dump rename information"""
2294
2298
2295 ctx = scmutil.revsingle(repo, opts.get('rev'))
2299 ctx = scmutil.revsingle(repo, opts.get('rev'))
2296 m = scmutil.match(ctx, (file1,) + pats, opts)
2300 m = scmutil.match(ctx, (file1,) + pats, opts)
2297 for abs in ctx.walk(m):
2301 for abs in ctx.walk(m):
2298 fctx = ctx[abs]
2302 fctx = ctx[abs]
2299 o = fctx.filelog().renamed(fctx.filenode())
2303 o = fctx.filelog().renamed(fctx.filenode())
2300 rel = m.rel(abs)
2304 rel = m.rel(abs)
2301 if o:
2305 if o:
2302 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2306 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2303 else:
2307 else:
2304 ui.write(_("%s not renamed\n") % rel)
2308 ui.write(_("%s not renamed\n") % rel)
2305
2309
2306 @command('debugrevlog',
2310 @command('debugrevlog',
2307 [('c', 'changelog', False, _('open changelog')),
2311 [('c', 'changelog', False, _('open changelog')),
2308 ('m', 'manifest', False, _('open manifest')),
2312 ('m', 'manifest', False, _('open manifest')),
2309 ('d', 'dump', False, _('dump index data'))],
2313 ('d', 'dump', False, _('dump index data'))],
2310 _('-c|-m|FILE'))
2314 _('-c|-m|FILE'))
2311 def debugrevlog(ui, repo, file_ = None, **opts):
2315 def debugrevlog(ui, repo, file_ = None, **opts):
2312 """show data and statistics about a revlog"""
2316 """show data and statistics about a revlog"""
2313 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2317 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2314
2318
2315 if opts.get("dump"):
2319 if opts.get("dump"):
2316 numrevs = len(r)
2320 numrevs = len(r)
2317 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2321 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2318 " rawsize totalsize compression heads\n")
2322 " rawsize totalsize compression heads\n")
2319 ts = 0
2323 ts = 0
2320 heads = set()
2324 heads = set()
2321 for rev in xrange(numrevs):
2325 for rev in xrange(numrevs):
2322 dbase = r.deltaparent(rev)
2326 dbase = r.deltaparent(rev)
2323 if dbase == -1:
2327 if dbase == -1:
2324 dbase = rev
2328 dbase = rev
2325 cbase = r.chainbase(rev)
2329 cbase = r.chainbase(rev)
2326 p1, p2 = r.parentrevs(rev)
2330 p1, p2 = r.parentrevs(rev)
2327 rs = r.rawsize(rev)
2331 rs = r.rawsize(rev)
2328 ts = ts + rs
2332 ts = ts + rs
2329 heads -= set(r.parentrevs(rev))
2333 heads -= set(r.parentrevs(rev))
2330 heads.add(rev)
2334 heads.add(rev)
2331 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2335 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2332 (rev, p1, p2, r.start(rev), r.end(rev),
2336 (rev, p1, p2, r.start(rev), r.end(rev),
2333 r.start(dbase), r.start(cbase),
2337 r.start(dbase), r.start(cbase),
2334 r.start(p1), r.start(p2),
2338 r.start(p1), r.start(p2),
2335 rs, ts, ts / r.end(rev), len(heads)))
2339 rs, ts, ts / r.end(rev), len(heads)))
2336 return 0
2340 return 0
2337
2341
2338 v = r.version
2342 v = r.version
2339 format = v & 0xFFFF
2343 format = v & 0xFFFF
2340 flags = []
2344 flags = []
2341 gdelta = False
2345 gdelta = False
2342 if v & revlog.REVLOGNGINLINEDATA:
2346 if v & revlog.REVLOGNGINLINEDATA:
2343 flags.append('inline')
2347 flags.append('inline')
2344 if v & revlog.REVLOGGENERALDELTA:
2348 if v & revlog.REVLOGGENERALDELTA:
2345 gdelta = True
2349 gdelta = True
2346 flags.append('generaldelta')
2350 flags.append('generaldelta')
2347 if not flags:
2351 if not flags:
2348 flags = ['(none)']
2352 flags = ['(none)']
2349
2353
2350 nummerges = 0
2354 nummerges = 0
2351 numfull = 0
2355 numfull = 0
2352 numprev = 0
2356 numprev = 0
2353 nump1 = 0
2357 nump1 = 0
2354 nump2 = 0
2358 nump2 = 0
2355 numother = 0
2359 numother = 0
2356 nump1prev = 0
2360 nump1prev = 0
2357 nump2prev = 0
2361 nump2prev = 0
2358 chainlengths = []
2362 chainlengths = []
2359
2363
2360 datasize = [None, 0, 0L]
2364 datasize = [None, 0, 0L]
2361 fullsize = [None, 0, 0L]
2365 fullsize = [None, 0, 0L]
2362 deltasize = [None, 0, 0L]
2366 deltasize = [None, 0, 0L]
2363
2367
2364 def addsize(size, l):
2368 def addsize(size, l):
2365 if l[0] is None or size < l[0]:
2369 if l[0] is None or size < l[0]:
2366 l[0] = size
2370 l[0] = size
2367 if size > l[1]:
2371 if size > l[1]:
2368 l[1] = size
2372 l[1] = size
2369 l[2] += size
2373 l[2] += size
2370
2374
2371 numrevs = len(r)
2375 numrevs = len(r)
2372 for rev in xrange(numrevs):
2376 for rev in xrange(numrevs):
2373 p1, p2 = r.parentrevs(rev)
2377 p1, p2 = r.parentrevs(rev)
2374 delta = r.deltaparent(rev)
2378 delta = r.deltaparent(rev)
2375 if format > 0:
2379 if format > 0:
2376 addsize(r.rawsize(rev), datasize)
2380 addsize(r.rawsize(rev), datasize)
2377 if p2 != nullrev:
2381 if p2 != nullrev:
2378 nummerges += 1
2382 nummerges += 1
2379 size = r.length(rev)
2383 size = r.length(rev)
2380 if delta == nullrev:
2384 if delta == nullrev:
2381 chainlengths.append(0)
2385 chainlengths.append(0)
2382 numfull += 1
2386 numfull += 1
2383 addsize(size, fullsize)
2387 addsize(size, fullsize)
2384 else:
2388 else:
2385 chainlengths.append(chainlengths[delta] + 1)
2389 chainlengths.append(chainlengths[delta] + 1)
2386 addsize(size, deltasize)
2390 addsize(size, deltasize)
2387 if delta == rev - 1:
2391 if delta == rev - 1:
2388 numprev += 1
2392 numprev += 1
2389 if delta == p1:
2393 if delta == p1:
2390 nump1prev += 1
2394 nump1prev += 1
2391 elif delta == p2:
2395 elif delta == p2:
2392 nump2prev += 1
2396 nump2prev += 1
2393 elif delta == p1:
2397 elif delta == p1:
2394 nump1 += 1
2398 nump1 += 1
2395 elif delta == p2:
2399 elif delta == p2:
2396 nump2 += 1
2400 nump2 += 1
2397 elif delta != nullrev:
2401 elif delta != nullrev:
2398 numother += 1
2402 numother += 1
2399
2403
2400 # Adjust size min value for empty cases
2404 # Adjust size min value for empty cases
2401 for size in (datasize, fullsize, deltasize):
2405 for size in (datasize, fullsize, deltasize):
2402 if size[0] is None:
2406 if size[0] is None:
2403 size[0] = 0
2407 size[0] = 0
2404
2408
2405 numdeltas = numrevs - numfull
2409 numdeltas = numrevs - numfull
2406 numoprev = numprev - nump1prev - nump2prev
2410 numoprev = numprev - nump1prev - nump2prev
2407 totalrawsize = datasize[2]
2411 totalrawsize = datasize[2]
2408 datasize[2] /= numrevs
2412 datasize[2] /= numrevs
2409 fulltotal = fullsize[2]
2413 fulltotal = fullsize[2]
2410 fullsize[2] /= numfull
2414 fullsize[2] /= numfull
2411 deltatotal = deltasize[2]
2415 deltatotal = deltasize[2]
2412 if numrevs - numfull > 0:
2416 if numrevs - numfull > 0:
2413 deltasize[2] /= numrevs - numfull
2417 deltasize[2] /= numrevs - numfull
2414 totalsize = fulltotal + deltatotal
2418 totalsize = fulltotal + deltatotal
2415 avgchainlen = sum(chainlengths) / numrevs
2419 avgchainlen = sum(chainlengths) / numrevs
2416 compratio = totalrawsize / totalsize
2420 compratio = totalrawsize / totalsize
2417
2421
2418 basedfmtstr = '%%%dd\n'
2422 basedfmtstr = '%%%dd\n'
2419 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2423 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2420
2424
2421 def dfmtstr(max):
2425 def dfmtstr(max):
2422 return basedfmtstr % len(str(max))
2426 return basedfmtstr % len(str(max))
2423 def pcfmtstr(max, padding=0):
2427 def pcfmtstr(max, padding=0):
2424 return basepcfmtstr % (len(str(max)), ' ' * padding)
2428 return basepcfmtstr % (len(str(max)), ' ' * padding)
2425
2429
2426 def pcfmt(value, total):
2430 def pcfmt(value, total):
2427 return (value, 100 * float(value) / total)
2431 return (value, 100 * float(value) / total)
2428
2432
2429 ui.write(('format : %d\n') % format)
2433 ui.write(('format : %d\n') % format)
2430 ui.write(('flags : %s\n') % ', '.join(flags))
2434 ui.write(('flags : %s\n') % ', '.join(flags))
2431
2435
2432 ui.write('\n')
2436 ui.write('\n')
2433 fmt = pcfmtstr(totalsize)
2437 fmt = pcfmtstr(totalsize)
2434 fmt2 = dfmtstr(totalsize)
2438 fmt2 = dfmtstr(totalsize)
2435 ui.write(('revisions : ') + fmt2 % numrevs)
2439 ui.write(('revisions : ') + fmt2 % numrevs)
2436 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2440 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2437 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2441 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2438 ui.write(('revisions : ') + fmt2 % numrevs)
2442 ui.write(('revisions : ') + fmt2 % numrevs)
2439 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2443 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2440 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2444 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2441 ui.write(('revision size : ') + fmt2 % totalsize)
2445 ui.write(('revision size : ') + fmt2 % totalsize)
2442 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2446 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2443 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2447 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2444
2448
2445 ui.write('\n')
2449 ui.write('\n')
2446 fmt = dfmtstr(max(avgchainlen, compratio))
2450 fmt = dfmtstr(max(avgchainlen, compratio))
2447 ui.write(('avg chain length : ') + fmt % avgchainlen)
2451 ui.write(('avg chain length : ') + fmt % avgchainlen)
2448 ui.write(('compression ratio : ') + fmt % compratio)
2452 ui.write(('compression ratio : ') + fmt % compratio)
2449
2453
2450 if format > 0:
2454 if format > 0:
2451 ui.write('\n')
2455 ui.write('\n')
2452 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2456 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2453 % tuple(datasize))
2457 % tuple(datasize))
2454 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2458 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2455 % tuple(fullsize))
2459 % tuple(fullsize))
2456 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2460 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2457 % tuple(deltasize))
2461 % tuple(deltasize))
2458
2462
2459 if numdeltas > 0:
2463 if numdeltas > 0:
2460 ui.write('\n')
2464 ui.write('\n')
2461 fmt = pcfmtstr(numdeltas)
2465 fmt = pcfmtstr(numdeltas)
2462 fmt2 = pcfmtstr(numdeltas, 4)
2466 fmt2 = pcfmtstr(numdeltas, 4)
2463 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2467 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2464 if numprev > 0:
2468 if numprev > 0:
2465 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2469 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2466 numprev))
2470 numprev))
2467 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2471 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2468 numprev))
2472 numprev))
2469 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2473 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2470 numprev))
2474 numprev))
2471 if gdelta:
2475 if gdelta:
2472 ui.write(('deltas against p1 : ')
2476 ui.write(('deltas against p1 : ')
2473 + fmt % pcfmt(nump1, numdeltas))
2477 + fmt % pcfmt(nump1, numdeltas))
2474 ui.write(('deltas against p2 : ')
2478 ui.write(('deltas against p2 : ')
2475 + fmt % pcfmt(nump2, numdeltas))
2479 + fmt % pcfmt(nump2, numdeltas))
2476 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2480 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2477 numdeltas))
2481 numdeltas))
2478
2482
2479 @command('debugrevspec', [], ('REVSPEC'))
2483 @command('debugrevspec', [], ('REVSPEC'))
2480 def debugrevspec(ui, repo, expr):
2484 def debugrevspec(ui, repo, expr):
2481 """parse and apply a revision specification
2485 """parse and apply a revision specification
2482
2486
2483 Use --verbose to print the parsed tree before and after aliases
2487 Use --verbose to print the parsed tree before and after aliases
2484 expansion.
2488 expansion.
2485 """
2489 """
2486 if ui.verbose:
2490 if ui.verbose:
2487 tree = revset.parse(expr)[0]
2491 tree = revset.parse(expr)[0]
2488 ui.note(revset.prettyformat(tree), "\n")
2492 ui.note(revset.prettyformat(tree), "\n")
2489 newtree = revset.findaliases(ui, tree)
2493 newtree = revset.findaliases(ui, tree)
2490 if newtree != tree:
2494 if newtree != tree:
2491 ui.note(revset.prettyformat(newtree), "\n")
2495 ui.note(revset.prettyformat(newtree), "\n")
2492 func = revset.match(ui, expr)
2496 func = revset.match(ui, expr)
2493 for c in func(repo, range(len(repo))):
2497 for c in func(repo, range(len(repo))):
2494 ui.write("%s\n" % c)
2498 ui.write("%s\n" % c)
2495
2499
2496 @command('debugsetparents', [], _('REV1 [REV2]'))
2500 @command('debugsetparents', [], _('REV1 [REV2]'))
2497 def debugsetparents(ui, repo, rev1, rev2=None):
2501 def debugsetparents(ui, repo, rev1, rev2=None):
2498 """manually set the parents of the current working directory
2502 """manually set the parents of the current working directory
2499
2503
2500 This is useful for writing repository conversion tools, but should
2504 This is useful for writing repository conversion tools, but should
2501 be used with care.
2505 be used with care.
2502
2506
2503 Returns 0 on success.
2507 Returns 0 on success.
2504 """
2508 """
2505
2509
2506 r1 = scmutil.revsingle(repo, rev1).node()
2510 r1 = scmutil.revsingle(repo, rev1).node()
2507 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2511 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2508
2512
2509 wlock = repo.wlock()
2513 wlock = repo.wlock()
2510 try:
2514 try:
2511 repo.setparents(r1, r2)
2515 repo.setparents(r1, r2)
2512 finally:
2516 finally:
2513 wlock.release()
2517 wlock.release()
2514
2518
2515 @command('debugdirstate|debugstate',
2519 @command('debugdirstate|debugstate',
2516 [('', 'nodates', None, _('do not display the saved mtime')),
2520 [('', 'nodates', None, _('do not display the saved mtime')),
2517 ('', 'datesort', None, _('sort by saved mtime'))],
2521 ('', 'datesort', None, _('sort by saved mtime'))],
2518 _('[OPTION]...'))
2522 _('[OPTION]...'))
2519 def debugstate(ui, repo, nodates=None, datesort=None):
2523 def debugstate(ui, repo, nodates=None, datesort=None):
2520 """show the contents of the current dirstate"""
2524 """show the contents of the current dirstate"""
2521 timestr = ""
2525 timestr = ""
2522 showdate = not nodates
2526 showdate = not nodates
2523 if datesort:
2527 if datesort:
2524 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2528 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2525 else:
2529 else:
2526 keyfunc = None # sort by filename
2530 keyfunc = None # sort by filename
2527 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2531 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2528 if showdate:
2532 if showdate:
2529 if ent[3] == -1:
2533 if ent[3] == -1:
2530 # Pad or slice to locale representation
2534 # Pad or slice to locale representation
2531 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2535 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2532 time.localtime(0)))
2536 time.localtime(0)))
2533 timestr = 'unset'
2537 timestr = 'unset'
2534 timestr = (timestr[:locale_len] +
2538 timestr = (timestr[:locale_len] +
2535 ' ' * (locale_len - len(timestr)))
2539 ' ' * (locale_len - len(timestr)))
2536 else:
2540 else:
2537 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2541 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2538 time.localtime(ent[3]))
2542 time.localtime(ent[3]))
2539 if ent[1] & 020000:
2543 if ent[1] & 020000:
2540 mode = 'lnk'
2544 mode = 'lnk'
2541 else:
2545 else:
2542 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2546 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2543 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2547 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2544 for f in repo.dirstate.copies():
2548 for f in repo.dirstate.copies():
2545 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2549 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2546
2550
2547 @command('debugsub',
2551 @command('debugsub',
2548 [('r', 'rev', '',
2552 [('r', 'rev', '',
2549 _('revision to check'), _('REV'))],
2553 _('revision to check'), _('REV'))],
2550 _('[-r REV] [REV]'))
2554 _('[-r REV] [REV]'))
2551 def debugsub(ui, repo, rev=None):
2555 def debugsub(ui, repo, rev=None):
2552 ctx = scmutil.revsingle(repo, rev, None)
2556 ctx = scmutil.revsingle(repo, rev, None)
2553 for k, v in sorted(ctx.substate.items()):
2557 for k, v in sorted(ctx.substate.items()):
2554 ui.write(('path %s\n') % k)
2558 ui.write(('path %s\n') % k)
2555 ui.write((' source %s\n') % v[0])
2559 ui.write((' source %s\n') % v[0])
2556 ui.write((' revision %s\n') % v[1])
2560 ui.write((' revision %s\n') % v[1])
2557
2561
2558 @command('debugsuccessorssets',
2562 @command('debugsuccessorssets',
2559 [],
2563 [],
2560 _('[REV]'))
2564 _('[REV]'))
2561 def debugsuccessorssets(ui, repo, *revs):
2565 def debugsuccessorssets(ui, repo, *revs):
2562 """show set of successors for revision
2566 """show set of successors for revision
2563
2567
2564 A successors set of changeset A is a consistent group of revisions that
2568 A successors set of changeset A is a consistent group of revisions that
2565 succeed A. It contains non-obsolete changesets only.
2569 succeed A. It contains non-obsolete changesets only.
2566
2570
2567 In most cases a changeset A has a single successors set containing a single
2571 In most cases a changeset A has a single successors set containing a single
2568 successor (changeset A replaced by A').
2572 successor (changeset A replaced by A').
2569
2573
2570 A changeset that is made obsolete with no successors are called "pruned".
2574 A changeset that is made obsolete with no successors are called "pruned".
2571 Such changesets have no successors sets at all.
2575 Such changesets have no successors sets at all.
2572
2576
2573 A changeset that has been "split" will have a successors set containing
2577 A changeset that has been "split" will have a successors set containing
2574 more than one successor.
2578 more than one successor.
2575
2579
2576 A changeset that has been rewritten in multiple different ways is called
2580 A changeset that has been rewritten in multiple different ways is called
2577 "divergent". Such changesets have multiple successor sets (each of which
2581 "divergent". Such changesets have multiple successor sets (each of which
2578 may also be split, i.e. have multiple successors).
2582 may also be split, i.e. have multiple successors).
2579
2583
2580 Results are displayed as follows::
2584 Results are displayed as follows::
2581
2585
2582 <rev1>
2586 <rev1>
2583 <successors-1A>
2587 <successors-1A>
2584 <rev2>
2588 <rev2>
2585 <successors-2A>
2589 <successors-2A>
2586 <successors-2B1> <successors-2B2> <successors-2B3>
2590 <successors-2B1> <successors-2B2> <successors-2B3>
2587
2591
2588 Here rev2 has two possible (i.e. divergent) successors sets. The first
2592 Here rev2 has two possible (i.e. divergent) successors sets. The first
2589 holds one element, whereas the second holds three (i.e. the changeset has
2593 holds one element, whereas the second holds three (i.e. the changeset has
2590 been split).
2594 been split).
2591 """
2595 """
2592 # passed to successorssets caching computation from one call to another
2596 # passed to successorssets caching computation from one call to another
2593 cache = {}
2597 cache = {}
2594 ctx2str = str
2598 ctx2str = str
2595 node2str = short
2599 node2str = short
2596 if ui.debug():
2600 if ui.debug():
2597 def ctx2str(ctx):
2601 def ctx2str(ctx):
2598 return ctx.hex()
2602 return ctx.hex()
2599 node2str = hex
2603 node2str = hex
2600 for rev in scmutil.revrange(repo, revs):
2604 for rev in scmutil.revrange(repo, revs):
2601 ctx = repo[rev]
2605 ctx = repo[rev]
2602 ui.write('%s\n'% ctx2str(ctx))
2606 ui.write('%s\n'% ctx2str(ctx))
2603 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2607 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2604 if succsset:
2608 if succsset:
2605 ui.write(' ')
2609 ui.write(' ')
2606 ui.write(node2str(succsset[0]))
2610 ui.write(node2str(succsset[0]))
2607 for node in succsset[1:]:
2611 for node in succsset[1:]:
2608 ui.write(' ')
2612 ui.write(' ')
2609 ui.write(node2str(node))
2613 ui.write(node2str(node))
2610 ui.write('\n')
2614 ui.write('\n')
2611
2615
2612 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2616 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2613 def debugwalk(ui, repo, *pats, **opts):
2617 def debugwalk(ui, repo, *pats, **opts):
2614 """show how files match on given patterns"""
2618 """show how files match on given patterns"""
2615 m = scmutil.match(repo[None], pats, opts)
2619 m = scmutil.match(repo[None], pats, opts)
2616 items = list(repo.walk(m))
2620 items = list(repo.walk(m))
2617 if not items:
2621 if not items:
2618 return
2622 return
2619 f = lambda fn: fn
2623 f = lambda fn: fn
2620 if ui.configbool('ui', 'slash') and os.sep != '/':
2624 if ui.configbool('ui', 'slash') and os.sep != '/':
2621 f = lambda fn: util.normpath(fn)
2625 f = lambda fn: util.normpath(fn)
2622 fmt = 'f %%-%ds %%-%ds %%s' % (
2626 fmt = 'f %%-%ds %%-%ds %%s' % (
2623 max([len(abs) for abs in items]),
2627 max([len(abs) for abs in items]),
2624 max([len(m.rel(abs)) for abs in items]))
2628 max([len(m.rel(abs)) for abs in items]))
2625 for abs in items:
2629 for abs in items:
2626 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2630 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2627 ui.write("%s\n" % line.rstrip())
2631 ui.write("%s\n" % line.rstrip())
2628
2632
2629 @command('debugwireargs',
2633 @command('debugwireargs',
2630 [('', 'three', '', 'three'),
2634 [('', 'three', '', 'three'),
2631 ('', 'four', '', 'four'),
2635 ('', 'four', '', 'four'),
2632 ('', 'five', '', 'five'),
2636 ('', 'five', '', 'five'),
2633 ] + remoteopts,
2637 ] + remoteopts,
2634 _('REPO [OPTIONS]... [ONE [TWO]]'))
2638 _('REPO [OPTIONS]... [ONE [TWO]]'))
2635 def debugwireargs(ui, repopath, *vals, **opts):
2639 def debugwireargs(ui, repopath, *vals, **opts):
2636 repo = hg.peer(ui, opts, repopath)
2640 repo = hg.peer(ui, opts, repopath)
2637 for opt in remoteopts:
2641 for opt in remoteopts:
2638 del opts[opt[1]]
2642 del opts[opt[1]]
2639 args = {}
2643 args = {}
2640 for k, v in opts.iteritems():
2644 for k, v in opts.iteritems():
2641 if v:
2645 if v:
2642 args[k] = v
2646 args[k] = v
2643 # run twice to check that we don't mess up the stream for the next command
2647 # run twice to check that we don't mess up the stream for the next command
2644 res1 = repo.debugwireargs(*vals, **args)
2648 res1 = repo.debugwireargs(*vals, **args)
2645 res2 = repo.debugwireargs(*vals, **args)
2649 res2 = repo.debugwireargs(*vals, **args)
2646 ui.write("%s\n" % res1)
2650 ui.write("%s\n" % res1)
2647 if res1 != res2:
2651 if res1 != res2:
2648 ui.warn("%s\n" % res2)
2652 ui.warn("%s\n" % res2)
2649
2653
2650 @command('^diff',
2654 @command('^diff',
2651 [('r', 'rev', [], _('revision'), _('REV')),
2655 [('r', 'rev', [], _('revision'), _('REV')),
2652 ('c', 'change', '', _('change made by revision'), _('REV'))
2656 ('c', 'change', '', _('change made by revision'), _('REV'))
2653 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2657 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2654 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2658 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2655 def diff(ui, repo, *pats, **opts):
2659 def diff(ui, repo, *pats, **opts):
2656 """diff repository (or selected files)
2660 """diff repository (or selected files)
2657
2661
2658 Show differences between revisions for the specified files.
2662 Show differences between revisions for the specified files.
2659
2663
2660 Differences between files are shown using the unified diff format.
2664 Differences between files are shown using the unified diff format.
2661
2665
2662 .. note::
2666 .. note::
2663 diff may generate unexpected results for merges, as it will
2667 diff may generate unexpected results for merges, as it will
2664 default to comparing against the working directory's first
2668 default to comparing against the working directory's first
2665 parent changeset if no revisions are specified.
2669 parent changeset if no revisions are specified.
2666
2670
2667 When two revision arguments are given, then changes are shown
2671 When two revision arguments are given, then changes are shown
2668 between those revisions. If only one revision is specified then
2672 between those revisions. If only one revision is specified then
2669 that revision is compared to the working directory, and, when no
2673 that revision is compared to the working directory, and, when no
2670 revisions are specified, the working directory files are compared
2674 revisions are specified, the working directory files are compared
2671 to its parent.
2675 to its parent.
2672
2676
2673 Alternatively you can specify -c/--change with a revision to see
2677 Alternatively you can specify -c/--change with a revision to see
2674 the changes in that changeset relative to its first parent.
2678 the changes in that changeset relative to its first parent.
2675
2679
2676 Without the -a/--text option, diff will avoid generating diffs of
2680 Without the -a/--text option, diff will avoid generating diffs of
2677 files it detects as binary. With -a, diff will generate a diff
2681 files it detects as binary. With -a, diff will generate a diff
2678 anyway, probably with undesirable results.
2682 anyway, probably with undesirable results.
2679
2683
2680 Use the -g/--git option to generate diffs in the git extended diff
2684 Use the -g/--git option to generate diffs in the git extended diff
2681 format. For more information, read :hg:`help diffs`.
2685 format. For more information, read :hg:`help diffs`.
2682
2686
2683 .. container:: verbose
2687 .. container:: verbose
2684
2688
2685 Examples:
2689 Examples:
2686
2690
2687 - compare a file in the current working directory to its parent::
2691 - compare a file in the current working directory to its parent::
2688
2692
2689 hg diff foo.c
2693 hg diff foo.c
2690
2694
2691 - compare two historical versions of a directory, with rename info::
2695 - compare two historical versions of a directory, with rename info::
2692
2696
2693 hg diff --git -r 1.0:1.2 lib/
2697 hg diff --git -r 1.0:1.2 lib/
2694
2698
2695 - get change stats relative to the last change on some date::
2699 - get change stats relative to the last change on some date::
2696
2700
2697 hg diff --stat -r "date('may 2')"
2701 hg diff --stat -r "date('may 2')"
2698
2702
2699 - diff all newly-added files that contain a keyword::
2703 - diff all newly-added files that contain a keyword::
2700
2704
2701 hg diff "set:added() and grep(GNU)"
2705 hg diff "set:added() and grep(GNU)"
2702
2706
2703 - compare a revision and its parents::
2707 - compare a revision and its parents::
2704
2708
2705 hg diff -c 9353 # compare against first parent
2709 hg diff -c 9353 # compare against first parent
2706 hg diff -r 9353^:9353 # same using revset syntax
2710 hg diff -r 9353^:9353 # same using revset syntax
2707 hg diff -r 9353^2:9353 # compare against the second parent
2711 hg diff -r 9353^2:9353 # compare against the second parent
2708
2712
2709 Returns 0 on success.
2713 Returns 0 on success.
2710 """
2714 """
2711
2715
2712 revs = opts.get('rev')
2716 revs = opts.get('rev')
2713 change = opts.get('change')
2717 change = opts.get('change')
2714 stat = opts.get('stat')
2718 stat = opts.get('stat')
2715 reverse = opts.get('reverse')
2719 reverse = opts.get('reverse')
2716
2720
2717 if revs and change:
2721 if revs and change:
2718 msg = _('cannot specify --rev and --change at the same time')
2722 msg = _('cannot specify --rev and --change at the same time')
2719 raise util.Abort(msg)
2723 raise util.Abort(msg)
2720 elif change:
2724 elif change:
2721 node2 = scmutil.revsingle(repo, change, None).node()
2725 node2 = scmutil.revsingle(repo, change, None).node()
2722 node1 = repo[node2].p1().node()
2726 node1 = repo[node2].p1().node()
2723 else:
2727 else:
2724 node1, node2 = scmutil.revpair(repo, revs)
2728 node1, node2 = scmutil.revpair(repo, revs)
2725
2729
2726 if reverse:
2730 if reverse:
2727 node1, node2 = node2, node1
2731 node1, node2 = node2, node1
2728
2732
2729 diffopts = patch.diffopts(ui, opts)
2733 diffopts = patch.diffopts(ui, opts)
2730 m = scmutil.match(repo[node2], pats, opts)
2734 m = scmutil.match(repo[node2], pats, opts)
2731 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2735 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2732 listsubrepos=opts.get('subrepos'))
2736 listsubrepos=opts.get('subrepos'))
2733
2737
2734 @command('^export',
2738 @command('^export',
2735 [('o', 'output', '',
2739 [('o', 'output', '',
2736 _('print output to file with formatted name'), _('FORMAT')),
2740 _('print output to file with formatted name'), _('FORMAT')),
2737 ('', 'switch-parent', None, _('diff against the second parent')),
2741 ('', 'switch-parent', None, _('diff against the second parent')),
2738 ('r', 'rev', [], _('revisions to export'), _('REV')),
2742 ('r', 'rev', [], _('revisions to export'), _('REV')),
2739 ] + diffopts,
2743 ] + diffopts,
2740 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2744 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2741 def export(ui, repo, *changesets, **opts):
2745 def export(ui, repo, *changesets, **opts):
2742 """dump the header and diffs for one or more changesets
2746 """dump the header and diffs for one or more changesets
2743
2747
2744 Print the changeset header and diffs for one or more revisions.
2748 Print the changeset header and diffs for one or more revisions.
2745 If no revision is given, the parent of the working directory is used.
2749 If no revision is given, the parent of the working directory is used.
2746
2750
2747 The information shown in the changeset header is: author, date,
2751 The information shown in the changeset header is: author, date,
2748 branch name (if non-default), changeset hash, parent(s) and commit
2752 branch name (if non-default), changeset hash, parent(s) and commit
2749 comment.
2753 comment.
2750
2754
2751 .. note::
2755 .. note::
2752 export may generate unexpected diff output for merge
2756 export may generate unexpected diff output for merge
2753 changesets, as it will compare the merge changeset against its
2757 changesets, as it will compare the merge changeset against its
2754 first parent only.
2758 first parent only.
2755
2759
2756 Output may be to a file, in which case the name of the file is
2760 Output may be to a file, in which case the name of the file is
2757 given using a format string. The formatting rules are as follows:
2761 given using a format string. The formatting rules are as follows:
2758
2762
2759 :``%%``: literal "%" character
2763 :``%%``: literal "%" character
2760 :``%H``: changeset hash (40 hexadecimal digits)
2764 :``%H``: changeset hash (40 hexadecimal digits)
2761 :``%N``: number of patches being generated
2765 :``%N``: number of patches being generated
2762 :``%R``: changeset revision number
2766 :``%R``: changeset revision number
2763 :``%b``: basename of the exporting repository
2767 :``%b``: basename of the exporting repository
2764 :``%h``: short-form changeset hash (12 hexadecimal digits)
2768 :``%h``: short-form changeset hash (12 hexadecimal digits)
2765 :``%m``: first line of the commit message (only alphanumeric characters)
2769 :``%m``: first line of the commit message (only alphanumeric characters)
2766 :``%n``: zero-padded sequence number, starting at 1
2770 :``%n``: zero-padded sequence number, starting at 1
2767 :``%r``: zero-padded changeset revision number
2771 :``%r``: zero-padded changeset revision number
2768
2772
2769 Without the -a/--text option, export will avoid generating diffs
2773 Without the -a/--text option, export will avoid generating diffs
2770 of files it detects as binary. With -a, export will generate a
2774 of files it detects as binary. With -a, export will generate a
2771 diff anyway, probably with undesirable results.
2775 diff anyway, probably with undesirable results.
2772
2776
2773 Use the -g/--git option to generate diffs in the git extended diff
2777 Use the -g/--git option to generate diffs in the git extended diff
2774 format. See :hg:`help diffs` for more information.
2778 format. See :hg:`help diffs` for more information.
2775
2779
2776 With the --switch-parent option, the diff will be against the
2780 With the --switch-parent option, the diff will be against the
2777 second parent. It can be useful to review a merge.
2781 second parent. It can be useful to review a merge.
2778
2782
2779 .. container:: verbose
2783 .. container:: verbose
2780
2784
2781 Examples:
2785 Examples:
2782
2786
2783 - use export and import to transplant a bugfix to the current
2787 - use export and import to transplant a bugfix to the current
2784 branch::
2788 branch::
2785
2789
2786 hg export -r 9353 | hg import -
2790 hg export -r 9353 | hg import -
2787
2791
2788 - export all the changesets between two revisions to a file with
2792 - export all the changesets between two revisions to a file with
2789 rename information::
2793 rename information::
2790
2794
2791 hg export --git -r 123:150 > changes.txt
2795 hg export --git -r 123:150 > changes.txt
2792
2796
2793 - split outgoing changes into a series of patches with
2797 - split outgoing changes into a series of patches with
2794 descriptive names::
2798 descriptive names::
2795
2799
2796 hg export -r "outgoing()" -o "%n-%m.patch"
2800 hg export -r "outgoing()" -o "%n-%m.patch"
2797
2801
2798 Returns 0 on success.
2802 Returns 0 on success.
2799 """
2803 """
2800 changesets += tuple(opts.get('rev', []))
2804 changesets += tuple(opts.get('rev', []))
2801 if not changesets:
2805 if not changesets:
2802 changesets = ['.']
2806 changesets = ['.']
2803 revs = scmutil.revrange(repo, changesets)
2807 revs = scmutil.revrange(repo, changesets)
2804 if not revs:
2808 if not revs:
2805 raise util.Abort(_("export requires at least one changeset"))
2809 raise util.Abort(_("export requires at least one changeset"))
2806 if len(revs) > 1:
2810 if len(revs) > 1:
2807 ui.note(_('exporting patches:\n'))
2811 ui.note(_('exporting patches:\n'))
2808 else:
2812 else:
2809 ui.note(_('exporting patch:\n'))
2813 ui.note(_('exporting patch:\n'))
2810 cmdutil.export(repo, revs, template=opts.get('output'),
2814 cmdutil.export(repo, revs, template=opts.get('output'),
2811 switch_parent=opts.get('switch_parent'),
2815 switch_parent=opts.get('switch_parent'),
2812 opts=patch.diffopts(ui, opts))
2816 opts=patch.diffopts(ui, opts))
2813
2817
2814 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2818 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2815 def forget(ui, repo, *pats, **opts):
2819 def forget(ui, repo, *pats, **opts):
2816 """forget the specified files on the next commit
2820 """forget the specified files on the next commit
2817
2821
2818 Mark the specified files so they will no longer be tracked
2822 Mark the specified files so they will no longer be tracked
2819 after the next commit.
2823 after the next commit.
2820
2824
2821 This only removes files from the current branch, not from the
2825 This only removes files from the current branch, not from the
2822 entire project history, and it does not delete them from the
2826 entire project history, and it does not delete them from the
2823 working directory.
2827 working directory.
2824
2828
2825 To undo a forget before the next commit, see :hg:`add`.
2829 To undo a forget before the next commit, see :hg:`add`.
2826
2830
2827 .. container:: verbose
2831 .. container:: verbose
2828
2832
2829 Examples:
2833 Examples:
2830
2834
2831 - forget newly-added binary files::
2835 - forget newly-added binary files::
2832
2836
2833 hg forget "set:added() and binary()"
2837 hg forget "set:added() and binary()"
2834
2838
2835 - forget files that would be excluded by .hgignore::
2839 - forget files that would be excluded by .hgignore::
2836
2840
2837 hg forget "set:hgignore()"
2841 hg forget "set:hgignore()"
2838
2842
2839 Returns 0 on success.
2843 Returns 0 on success.
2840 """
2844 """
2841
2845
2842 if not pats:
2846 if not pats:
2843 raise util.Abort(_('no files specified'))
2847 raise util.Abort(_('no files specified'))
2844
2848
2845 m = scmutil.match(repo[None], pats, opts)
2849 m = scmutil.match(repo[None], pats, opts)
2846 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2850 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2847 return rejected and 1 or 0
2851 return rejected and 1 or 0
2848
2852
2849 @command(
2853 @command(
2850 'graft',
2854 'graft',
2851 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2855 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2852 ('c', 'continue', False, _('resume interrupted graft')),
2856 ('c', 'continue', False, _('resume interrupted graft')),
2853 ('e', 'edit', False, _('invoke editor on commit messages')),
2857 ('e', 'edit', False, _('invoke editor on commit messages')),
2854 ('', 'log', None, _('append graft info to log message')),
2858 ('', 'log', None, _('append graft info to log message')),
2855 ('D', 'currentdate', False,
2859 ('D', 'currentdate', False,
2856 _('record the current date as commit date')),
2860 _('record the current date as commit date')),
2857 ('U', 'currentuser', False,
2861 ('U', 'currentuser', False,
2858 _('record the current user as committer'), _('DATE'))]
2862 _('record the current user as committer'), _('DATE'))]
2859 + commitopts2 + mergetoolopts + dryrunopts,
2863 + commitopts2 + mergetoolopts + dryrunopts,
2860 _('[OPTION]... [-r] REV...'))
2864 _('[OPTION]... [-r] REV...'))
2861 def graft(ui, repo, *revs, **opts):
2865 def graft(ui, repo, *revs, **opts):
2862 '''copy changes from other branches onto the current branch
2866 '''copy changes from other branches onto the current branch
2863
2867
2864 This command uses Mercurial's merge logic to copy individual
2868 This command uses Mercurial's merge logic to copy individual
2865 changes from other branches without merging branches in the
2869 changes from other branches without merging branches in the
2866 history graph. This is sometimes known as 'backporting' or
2870 history graph. This is sometimes known as 'backporting' or
2867 'cherry-picking'. By default, graft will copy user, date, and
2871 'cherry-picking'. By default, graft will copy user, date, and
2868 description from the source changesets.
2872 description from the source changesets.
2869
2873
2870 Changesets that are ancestors of the current revision, that have
2874 Changesets that are ancestors of the current revision, that have
2871 already been grafted, or that are merges will be skipped.
2875 already been grafted, or that are merges will be skipped.
2872
2876
2873 If --log is specified, log messages will have a comment appended
2877 If --log is specified, log messages will have a comment appended
2874 of the form::
2878 of the form::
2875
2879
2876 (grafted from CHANGESETHASH)
2880 (grafted from CHANGESETHASH)
2877
2881
2878 If a graft merge results in conflicts, the graft process is
2882 If a graft merge results in conflicts, the graft process is
2879 interrupted so that the current merge can be manually resolved.
2883 interrupted so that the current merge can be manually resolved.
2880 Once all conflicts are addressed, the graft process can be
2884 Once all conflicts are addressed, the graft process can be
2881 continued with the -c/--continue option.
2885 continued with the -c/--continue option.
2882
2886
2883 .. note::
2887 .. note::
2884 The -c/--continue option does not reapply earlier options.
2888 The -c/--continue option does not reapply earlier options.
2885
2889
2886 .. container:: verbose
2890 .. container:: verbose
2887
2891
2888 Examples:
2892 Examples:
2889
2893
2890 - copy a single change to the stable branch and edit its description::
2894 - copy a single change to the stable branch and edit its description::
2891
2895
2892 hg update stable
2896 hg update stable
2893 hg graft --edit 9393
2897 hg graft --edit 9393
2894
2898
2895 - graft a range of changesets with one exception, updating dates::
2899 - graft a range of changesets with one exception, updating dates::
2896
2900
2897 hg graft -D "2085::2093 and not 2091"
2901 hg graft -D "2085::2093 and not 2091"
2898
2902
2899 - continue a graft after resolving conflicts::
2903 - continue a graft after resolving conflicts::
2900
2904
2901 hg graft -c
2905 hg graft -c
2902
2906
2903 - show the source of a grafted changeset::
2907 - show the source of a grafted changeset::
2904
2908
2905 hg log --debug -r tip
2909 hg log --debug -r tip
2906
2910
2907 Returns 0 on successful completion.
2911 Returns 0 on successful completion.
2908 '''
2912 '''
2909
2913
2910 revs = list(revs)
2914 revs = list(revs)
2911 revs.extend(opts['rev'])
2915 revs.extend(opts['rev'])
2912
2916
2913 if not opts.get('user') and opts.get('currentuser'):
2917 if not opts.get('user') and opts.get('currentuser'):
2914 opts['user'] = ui.username()
2918 opts['user'] = ui.username()
2915 if not opts.get('date') and opts.get('currentdate'):
2919 if not opts.get('date') and opts.get('currentdate'):
2916 opts['date'] = "%d %d" % util.makedate()
2920 opts['date'] = "%d %d" % util.makedate()
2917
2921
2918 editor = None
2922 editor = None
2919 if opts.get('edit'):
2923 if opts.get('edit'):
2920 editor = cmdutil.commitforceeditor
2924 editor = cmdutil.commitforceeditor
2921
2925
2922 cont = False
2926 cont = False
2923 if opts['continue']:
2927 if opts['continue']:
2924 cont = True
2928 cont = True
2925 if revs:
2929 if revs:
2926 raise util.Abort(_("can't specify --continue and revisions"))
2930 raise util.Abort(_("can't specify --continue and revisions"))
2927 # read in unfinished revisions
2931 # read in unfinished revisions
2928 try:
2932 try:
2929 nodes = repo.opener.read('graftstate').splitlines()
2933 nodes = repo.opener.read('graftstate').splitlines()
2930 revs = [repo[node].rev() for node in nodes]
2934 revs = [repo[node].rev() for node in nodes]
2931 except IOError, inst:
2935 except IOError, inst:
2932 if inst.errno != errno.ENOENT:
2936 if inst.errno != errno.ENOENT:
2933 raise
2937 raise
2934 raise util.Abort(_("no graft state found, can't continue"))
2938 raise util.Abort(_("no graft state found, can't continue"))
2935 else:
2939 else:
2936 cmdutil.bailifchanged(repo)
2940 cmdutil.bailifchanged(repo)
2937 if not revs:
2941 if not revs:
2938 raise util.Abort(_('no revisions specified'))
2942 raise util.Abort(_('no revisions specified'))
2939 revs = scmutil.revrange(repo, revs)
2943 revs = scmutil.revrange(repo, revs)
2940
2944
2941 # check for merges
2945 # check for merges
2942 for rev in repo.revs('%ld and merge()', revs):
2946 for rev in repo.revs('%ld and merge()', revs):
2943 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2947 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2944 revs.remove(rev)
2948 revs.remove(rev)
2945 if not revs:
2949 if not revs:
2946 return -1
2950 return -1
2947
2951
2948 # check for ancestors of dest branch
2952 # check for ancestors of dest branch
2949 crev = repo['.'].rev()
2953 crev = repo['.'].rev()
2950 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2954 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2951 # don't mutate while iterating, create a copy
2955 # don't mutate while iterating, create a copy
2952 for rev in list(revs):
2956 for rev in list(revs):
2953 if rev in ancestors:
2957 if rev in ancestors:
2954 ui.warn(_('skipping ancestor revision %s\n') % rev)
2958 ui.warn(_('skipping ancestor revision %s\n') % rev)
2955 revs.remove(rev)
2959 revs.remove(rev)
2956 if not revs:
2960 if not revs:
2957 return -1
2961 return -1
2958
2962
2959 # analyze revs for earlier grafts
2963 # analyze revs for earlier grafts
2960 ids = {}
2964 ids = {}
2961 for ctx in repo.set("%ld", revs):
2965 for ctx in repo.set("%ld", revs):
2962 ids[ctx.hex()] = ctx.rev()
2966 ids[ctx.hex()] = ctx.rev()
2963 n = ctx.extra().get('source')
2967 n = ctx.extra().get('source')
2964 if n:
2968 if n:
2965 ids[n] = ctx.rev()
2969 ids[n] = ctx.rev()
2966
2970
2967 # check ancestors for earlier grafts
2971 # check ancestors for earlier grafts
2968 ui.debug('scanning for duplicate grafts\n')
2972 ui.debug('scanning for duplicate grafts\n')
2969
2973
2970 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2974 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2971 ctx = repo[rev]
2975 ctx = repo[rev]
2972 n = ctx.extra().get('source')
2976 n = ctx.extra().get('source')
2973 if n in ids:
2977 if n in ids:
2974 r = repo[n].rev()
2978 r = repo[n].rev()
2975 if r in revs:
2979 if r in revs:
2976 ui.warn(_('skipping already grafted revision %s\n') % r)
2980 ui.warn(_('skipping already grafted revision %s\n') % r)
2977 revs.remove(r)
2981 revs.remove(r)
2978 elif ids[n] in revs:
2982 elif ids[n] in revs:
2979 ui.warn(_('skipping already grafted revision %s '
2983 ui.warn(_('skipping already grafted revision %s '
2980 '(same origin %d)\n') % (ids[n], r))
2984 '(same origin %d)\n') % (ids[n], r))
2981 revs.remove(ids[n])
2985 revs.remove(ids[n])
2982 elif ctx.hex() in ids:
2986 elif ctx.hex() in ids:
2983 r = ids[ctx.hex()]
2987 r = ids[ctx.hex()]
2984 ui.warn(_('skipping already grafted revision %s '
2988 ui.warn(_('skipping already grafted revision %s '
2985 '(was grafted from %d)\n') % (r, rev))
2989 '(was grafted from %d)\n') % (r, rev))
2986 revs.remove(r)
2990 revs.remove(r)
2987 if not revs:
2991 if not revs:
2988 return -1
2992 return -1
2989
2993
2990 wlock = repo.wlock()
2994 wlock = repo.wlock()
2991 try:
2995 try:
2992 current = repo['.']
2996 current = repo['.']
2993 for pos, ctx in enumerate(repo.set("%ld", revs)):
2997 for pos, ctx in enumerate(repo.set("%ld", revs)):
2994
2998
2995 ui.status(_('grafting revision %s\n') % ctx.rev())
2999 ui.status(_('grafting revision %s\n') % ctx.rev())
2996 if opts.get('dry_run'):
3000 if opts.get('dry_run'):
2997 continue
3001 continue
2998
3002
2999 source = ctx.extra().get('source')
3003 source = ctx.extra().get('source')
3000 if not source:
3004 if not source:
3001 source = ctx.hex()
3005 source = ctx.hex()
3002 extra = {'source': source}
3006 extra = {'source': source}
3003 user = ctx.user()
3007 user = ctx.user()
3004 if opts.get('user'):
3008 if opts.get('user'):
3005 user = opts['user']
3009 user = opts['user']
3006 date = ctx.date()
3010 date = ctx.date()
3007 if opts.get('date'):
3011 if opts.get('date'):
3008 date = opts['date']
3012 date = opts['date']
3009 message = ctx.description()
3013 message = ctx.description()
3010 if opts.get('log'):
3014 if opts.get('log'):
3011 message += '\n(grafted from %s)' % ctx.hex()
3015 message += '\n(grafted from %s)' % ctx.hex()
3012
3016
3013 # we don't merge the first commit when continuing
3017 # we don't merge the first commit when continuing
3014 if not cont:
3018 if not cont:
3015 # perform the graft merge with p1(rev) as 'ancestor'
3019 # perform the graft merge with p1(rev) as 'ancestor'
3016 try:
3020 try:
3017 # ui.forcemerge is an internal variable, do not document
3021 # ui.forcemerge is an internal variable, do not document
3018 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3022 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3019 stats = mergemod.update(repo, ctx.node(), True, True, False,
3023 stats = mergemod.update(repo, ctx.node(), True, True, False,
3020 ctx.p1().node())
3024 ctx.p1().node())
3021 finally:
3025 finally:
3022 repo.ui.setconfig('ui', 'forcemerge', '')
3026 repo.ui.setconfig('ui', 'forcemerge', '')
3023 # report any conflicts
3027 # report any conflicts
3024 if stats and stats[3] > 0:
3028 if stats and stats[3] > 0:
3025 # write out state for --continue
3029 # write out state for --continue
3026 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3030 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3027 repo.opener.write('graftstate', ''.join(nodelines))
3031 repo.opener.write('graftstate', ''.join(nodelines))
3028 raise util.Abort(
3032 raise util.Abort(
3029 _("unresolved conflicts, can't continue"),
3033 _("unresolved conflicts, can't continue"),
3030 hint=_('use hg resolve and hg graft --continue'))
3034 hint=_('use hg resolve and hg graft --continue'))
3031 else:
3035 else:
3032 cont = False
3036 cont = False
3033
3037
3034 # drop the second merge parent
3038 # drop the second merge parent
3035 repo.setparents(current.node(), nullid)
3039 repo.setparents(current.node(), nullid)
3036 repo.dirstate.write()
3040 repo.dirstate.write()
3037 # fix up dirstate for copies and renames
3041 # fix up dirstate for copies and renames
3038 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3042 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3039
3043
3040 # commit
3044 # commit
3041 node = repo.commit(text=message, user=user,
3045 node = repo.commit(text=message, user=user,
3042 date=date, extra=extra, editor=editor)
3046 date=date, extra=extra, editor=editor)
3043 if node is None:
3047 if node is None:
3044 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3048 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3045 else:
3049 else:
3046 current = repo[node]
3050 current = repo[node]
3047 finally:
3051 finally:
3048 wlock.release()
3052 wlock.release()
3049
3053
3050 # remove state when we complete successfully
3054 # remove state when we complete successfully
3051 if not opts.get('dry_run'):
3055 if not opts.get('dry_run'):
3052 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3056 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3053
3057
3054 return 0
3058 return 0
3055
3059
3056 @command('grep',
3060 @command('grep',
3057 [('0', 'print0', None, _('end fields with NUL')),
3061 [('0', 'print0', None, _('end fields with NUL')),
3058 ('', 'all', None, _('print all revisions that match')),
3062 ('', 'all', None, _('print all revisions that match')),
3059 ('a', 'text', None, _('treat all files as text')),
3063 ('a', 'text', None, _('treat all files as text')),
3060 ('f', 'follow', None,
3064 ('f', 'follow', None,
3061 _('follow changeset history,'
3065 _('follow changeset history,'
3062 ' or file history across copies and renames')),
3066 ' or file history across copies and renames')),
3063 ('i', 'ignore-case', None, _('ignore case when matching')),
3067 ('i', 'ignore-case', None, _('ignore case when matching')),
3064 ('l', 'files-with-matches', None,
3068 ('l', 'files-with-matches', None,
3065 _('print only filenames and revisions that match')),
3069 _('print only filenames and revisions that match')),
3066 ('n', 'line-number', None, _('print matching line numbers')),
3070 ('n', 'line-number', None, _('print matching line numbers')),
3067 ('r', 'rev', [],
3071 ('r', 'rev', [],
3068 _('only search files changed within revision range'), _('REV')),
3072 _('only search files changed within revision range'), _('REV')),
3069 ('u', 'user', None, _('list the author (long with -v)')),
3073 ('u', 'user', None, _('list the author (long with -v)')),
3070 ('d', 'date', None, _('list the date (short with -q)')),
3074 ('d', 'date', None, _('list the date (short with -q)')),
3071 ] + walkopts,
3075 ] + walkopts,
3072 _('[OPTION]... PATTERN [FILE]...'))
3076 _('[OPTION]... PATTERN [FILE]...'))
3073 def grep(ui, repo, pattern, *pats, **opts):
3077 def grep(ui, repo, pattern, *pats, **opts):
3074 """search for a pattern in specified files and revisions
3078 """search for a pattern in specified files and revisions
3075
3079
3076 Search revisions of files for a regular expression.
3080 Search revisions of files for a regular expression.
3077
3081
3078 This command behaves differently than Unix grep. It only accepts
3082 This command behaves differently than Unix grep. It only accepts
3079 Python/Perl regexps. It searches repository history, not the
3083 Python/Perl regexps. It searches repository history, not the
3080 working directory. It always prints the revision number in which a
3084 working directory. It always prints the revision number in which a
3081 match appears.
3085 match appears.
3082
3086
3083 By default, grep only prints output for the first revision of a
3087 By default, grep only prints output for the first revision of a
3084 file in which it finds a match. To get it to print every revision
3088 file in which it finds a match. To get it to print every revision
3085 that contains a change in match status ("-" for a match that
3089 that contains a change in match status ("-" for a match that
3086 becomes a non-match, or "+" for a non-match that becomes a match),
3090 becomes a non-match, or "+" for a non-match that becomes a match),
3087 use the --all flag.
3091 use the --all flag.
3088
3092
3089 Returns 0 if a match is found, 1 otherwise.
3093 Returns 0 if a match is found, 1 otherwise.
3090 """
3094 """
3091 reflags = re.M
3095 reflags = re.M
3092 if opts.get('ignore_case'):
3096 if opts.get('ignore_case'):
3093 reflags |= re.I
3097 reflags |= re.I
3094 try:
3098 try:
3095 regexp = util.compilere(pattern, reflags)
3099 regexp = util.compilere(pattern, reflags)
3096 except re.error, inst:
3100 except re.error, inst:
3097 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3101 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3098 return 1
3102 return 1
3099 sep, eol = ':', '\n'
3103 sep, eol = ':', '\n'
3100 if opts.get('print0'):
3104 if opts.get('print0'):
3101 sep = eol = '\0'
3105 sep = eol = '\0'
3102
3106
3103 getfile = util.lrucachefunc(repo.file)
3107 getfile = util.lrucachefunc(repo.file)
3104
3108
3105 def matchlines(body):
3109 def matchlines(body):
3106 begin = 0
3110 begin = 0
3107 linenum = 0
3111 linenum = 0
3108 while begin < len(body):
3112 while begin < len(body):
3109 match = regexp.search(body, begin)
3113 match = regexp.search(body, begin)
3110 if not match:
3114 if not match:
3111 break
3115 break
3112 mstart, mend = match.span()
3116 mstart, mend = match.span()
3113 linenum += body.count('\n', begin, mstart) + 1
3117 linenum += body.count('\n', begin, mstart) + 1
3114 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3118 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3115 begin = body.find('\n', mend) + 1 or len(body) + 1
3119 begin = body.find('\n', mend) + 1 or len(body) + 1
3116 lend = begin - 1
3120 lend = begin - 1
3117 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3121 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3118
3122
3119 class linestate(object):
3123 class linestate(object):
3120 def __init__(self, line, linenum, colstart, colend):
3124 def __init__(self, line, linenum, colstart, colend):
3121 self.line = line
3125 self.line = line
3122 self.linenum = linenum
3126 self.linenum = linenum
3123 self.colstart = colstart
3127 self.colstart = colstart
3124 self.colend = colend
3128 self.colend = colend
3125
3129
3126 def __hash__(self):
3130 def __hash__(self):
3127 return hash((self.linenum, self.line))
3131 return hash((self.linenum, self.line))
3128
3132
3129 def __eq__(self, other):
3133 def __eq__(self, other):
3130 return self.line == other.line
3134 return self.line == other.line
3131
3135
3132 matches = {}
3136 matches = {}
3133 copies = {}
3137 copies = {}
3134 def grepbody(fn, rev, body):
3138 def grepbody(fn, rev, body):
3135 matches[rev].setdefault(fn, [])
3139 matches[rev].setdefault(fn, [])
3136 m = matches[rev][fn]
3140 m = matches[rev][fn]
3137 for lnum, cstart, cend, line in matchlines(body):
3141 for lnum, cstart, cend, line in matchlines(body):
3138 s = linestate(line, lnum, cstart, cend)
3142 s = linestate(line, lnum, cstart, cend)
3139 m.append(s)
3143 m.append(s)
3140
3144
3141 def difflinestates(a, b):
3145 def difflinestates(a, b):
3142 sm = difflib.SequenceMatcher(None, a, b)
3146 sm = difflib.SequenceMatcher(None, a, b)
3143 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3147 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3144 if tag == 'insert':
3148 if tag == 'insert':
3145 for i in xrange(blo, bhi):
3149 for i in xrange(blo, bhi):
3146 yield ('+', b[i])
3150 yield ('+', b[i])
3147 elif tag == 'delete':
3151 elif tag == 'delete':
3148 for i in xrange(alo, ahi):
3152 for i in xrange(alo, ahi):
3149 yield ('-', a[i])
3153 yield ('-', a[i])
3150 elif tag == 'replace':
3154 elif tag == 'replace':
3151 for i in xrange(alo, ahi):
3155 for i in xrange(alo, ahi):
3152 yield ('-', a[i])
3156 yield ('-', a[i])
3153 for i in xrange(blo, bhi):
3157 for i in xrange(blo, bhi):
3154 yield ('+', b[i])
3158 yield ('+', b[i])
3155
3159
3156 def display(fn, ctx, pstates, states):
3160 def display(fn, ctx, pstates, states):
3157 rev = ctx.rev()
3161 rev = ctx.rev()
3158 datefunc = ui.quiet and util.shortdate or util.datestr
3162 datefunc = ui.quiet and util.shortdate or util.datestr
3159 found = False
3163 found = False
3160 filerevmatches = {}
3164 filerevmatches = {}
3161 def binary():
3165 def binary():
3162 flog = getfile(fn)
3166 flog = getfile(fn)
3163 return util.binary(flog.read(ctx.filenode(fn)))
3167 return util.binary(flog.read(ctx.filenode(fn)))
3164
3168
3165 if opts.get('all'):
3169 if opts.get('all'):
3166 iter = difflinestates(pstates, states)
3170 iter = difflinestates(pstates, states)
3167 else:
3171 else:
3168 iter = [('', l) for l in states]
3172 iter = [('', l) for l in states]
3169 for change, l in iter:
3173 for change, l in iter:
3170 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3174 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3171 before, match, after = None, None, None
3175 before, match, after = None, None, None
3172
3176
3173 if opts.get('line_number'):
3177 if opts.get('line_number'):
3174 cols.append((str(l.linenum), 'grep.linenumber'))
3178 cols.append((str(l.linenum), 'grep.linenumber'))
3175 if opts.get('all'):
3179 if opts.get('all'):
3176 cols.append((change, 'grep.change'))
3180 cols.append((change, 'grep.change'))
3177 if opts.get('user'):
3181 if opts.get('user'):
3178 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3182 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3179 if opts.get('date'):
3183 if opts.get('date'):
3180 cols.append((datefunc(ctx.date()), 'grep.date'))
3184 cols.append((datefunc(ctx.date()), 'grep.date'))
3181 if opts.get('files_with_matches'):
3185 if opts.get('files_with_matches'):
3182 c = (fn, rev)
3186 c = (fn, rev)
3183 if c in filerevmatches:
3187 if c in filerevmatches:
3184 continue
3188 continue
3185 filerevmatches[c] = 1
3189 filerevmatches[c] = 1
3186 else:
3190 else:
3187 before = l.line[:l.colstart]
3191 before = l.line[:l.colstart]
3188 match = l.line[l.colstart:l.colend]
3192 match = l.line[l.colstart:l.colend]
3189 after = l.line[l.colend:]
3193 after = l.line[l.colend:]
3190 for col, label in cols[:-1]:
3194 for col, label in cols[:-1]:
3191 ui.write(col, label=label)
3195 ui.write(col, label=label)
3192 ui.write(sep, label='grep.sep')
3196 ui.write(sep, label='grep.sep')
3193 ui.write(cols[-1][0], label=cols[-1][1])
3197 ui.write(cols[-1][0], label=cols[-1][1])
3194 if before is not None:
3198 if before is not None:
3195 ui.write(sep, label='grep.sep')
3199 ui.write(sep, label='grep.sep')
3196 if not opts.get('text') and binary():
3200 if not opts.get('text') and binary():
3197 ui.write(" Binary file matches")
3201 ui.write(" Binary file matches")
3198 else:
3202 else:
3199 ui.write(before)
3203 ui.write(before)
3200 ui.write(match, label='grep.match')
3204 ui.write(match, label='grep.match')
3201 ui.write(after)
3205 ui.write(after)
3202 ui.write(eol)
3206 ui.write(eol)
3203 found = True
3207 found = True
3204 return found
3208 return found
3205
3209
3206 skip = {}
3210 skip = {}
3207 revfiles = {}
3211 revfiles = {}
3208 matchfn = scmutil.match(repo[None], pats, opts)
3212 matchfn = scmutil.match(repo[None], pats, opts)
3209 found = False
3213 found = False
3210 follow = opts.get('follow')
3214 follow = opts.get('follow')
3211
3215
3212 def prep(ctx, fns):
3216 def prep(ctx, fns):
3213 rev = ctx.rev()
3217 rev = ctx.rev()
3214 pctx = ctx.p1()
3218 pctx = ctx.p1()
3215 parent = pctx.rev()
3219 parent = pctx.rev()
3216 matches.setdefault(rev, {})
3220 matches.setdefault(rev, {})
3217 matches.setdefault(parent, {})
3221 matches.setdefault(parent, {})
3218 files = revfiles.setdefault(rev, [])
3222 files = revfiles.setdefault(rev, [])
3219 for fn in fns:
3223 for fn in fns:
3220 flog = getfile(fn)
3224 flog = getfile(fn)
3221 try:
3225 try:
3222 fnode = ctx.filenode(fn)
3226 fnode = ctx.filenode(fn)
3223 except error.LookupError:
3227 except error.LookupError:
3224 continue
3228 continue
3225
3229
3226 copied = flog.renamed(fnode)
3230 copied = flog.renamed(fnode)
3227 copy = follow and copied and copied[0]
3231 copy = follow and copied and copied[0]
3228 if copy:
3232 if copy:
3229 copies.setdefault(rev, {})[fn] = copy
3233 copies.setdefault(rev, {})[fn] = copy
3230 if fn in skip:
3234 if fn in skip:
3231 if copy:
3235 if copy:
3232 skip[copy] = True
3236 skip[copy] = True
3233 continue
3237 continue
3234 files.append(fn)
3238 files.append(fn)
3235
3239
3236 if fn not in matches[rev]:
3240 if fn not in matches[rev]:
3237 grepbody(fn, rev, flog.read(fnode))
3241 grepbody(fn, rev, flog.read(fnode))
3238
3242
3239 pfn = copy or fn
3243 pfn = copy or fn
3240 if pfn not in matches[parent]:
3244 if pfn not in matches[parent]:
3241 try:
3245 try:
3242 fnode = pctx.filenode(pfn)
3246 fnode = pctx.filenode(pfn)
3243 grepbody(pfn, parent, flog.read(fnode))
3247 grepbody(pfn, parent, flog.read(fnode))
3244 except error.LookupError:
3248 except error.LookupError:
3245 pass
3249 pass
3246
3250
3247 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3251 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3248 rev = ctx.rev()
3252 rev = ctx.rev()
3249 parent = ctx.p1().rev()
3253 parent = ctx.p1().rev()
3250 for fn in sorted(revfiles.get(rev, [])):
3254 for fn in sorted(revfiles.get(rev, [])):
3251 states = matches[rev][fn]
3255 states = matches[rev][fn]
3252 copy = copies.get(rev, {}).get(fn)
3256 copy = copies.get(rev, {}).get(fn)
3253 if fn in skip:
3257 if fn in skip:
3254 if copy:
3258 if copy:
3255 skip[copy] = True
3259 skip[copy] = True
3256 continue
3260 continue
3257 pstates = matches.get(parent, {}).get(copy or fn, [])
3261 pstates = matches.get(parent, {}).get(copy or fn, [])
3258 if pstates or states:
3262 if pstates or states:
3259 r = display(fn, ctx, pstates, states)
3263 r = display(fn, ctx, pstates, states)
3260 found = found or r
3264 found = found or r
3261 if r and not opts.get('all'):
3265 if r and not opts.get('all'):
3262 skip[fn] = True
3266 skip[fn] = True
3263 if copy:
3267 if copy:
3264 skip[copy] = True
3268 skip[copy] = True
3265 del matches[rev]
3269 del matches[rev]
3266 del revfiles[rev]
3270 del revfiles[rev]
3267
3271
3268 return not found
3272 return not found
3269
3273
3270 @command('heads',
3274 @command('heads',
3271 [('r', 'rev', '',
3275 [('r', 'rev', '',
3272 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3276 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3273 ('t', 'topo', False, _('show topological heads only')),
3277 ('t', 'topo', False, _('show topological heads only')),
3274 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3278 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3275 ('c', 'closed', False, _('show normal and closed branch heads')),
3279 ('c', 'closed', False, _('show normal and closed branch heads')),
3276 ] + templateopts,
3280 ] + templateopts,
3277 _('[-ct] [-r STARTREV] [REV]...'))
3281 _('[-ct] [-r STARTREV] [REV]...'))
3278 def heads(ui, repo, *branchrevs, **opts):
3282 def heads(ui, repo, *branchrevs, **opts):
3279 """show current repository heads or show branch heads
3283 """show current repository heads or show branch heads
3280
3284
3281 With no arguments, show all repository branch heads.
3285 With no arguments, show all repository branch heads.
3282
3286
3283 Repository "heads" are changesets with no child changesets. They are
3287 Repository "heads" are changesets with no child changesets. They are
3284 where development generally takes place and are the usual targets
3288 where development generally takes place and are the usual targets
3285 for update and merge operations. Branch heads are changesets that have
3289 for update and merge operations. Branch heads are changesets that have
3286 no child changeset on the same branch.
3290 no child changeset on the same branch.
3287
3291
3288 If one or more REVs are given, only branch heads on the branches
3292 If one or more REVs are given, only branch heads on the branches
3289 associated with the specified changesets are shown. This means
3293 associated with the specified changesets are shown. This means
3290 that you can use :hg:`heads foo` to see the heads on a branch
3294 that you can use :hg:`heads foo` to see the heads on a branch
3291 named ``foo``.
3295 named ``foo``.
3292
3296
3293 If -c/--closed is specified, also show branch heads marked closed
3297 If -c/--closed is specified, also show branch heads marked closed
3294 (see :hg:`commit --close-branch`).
3298 (see :hg:`commit --close-branch`).
3295
3299
3296 If STARTREV is specified, only those heads that are descendants of
3300 If STARTREV is specified, only those heads that are descendants of
3297 STARTREV will be displayed.
3301 STARTREV will be displayed.
3298
3302
3299 If -t/--topo is specified, named branch mechanics will be ignored and only
3303 If -t/--topo is specified, named branch mechanics will be ignored and only
3300 changesets without children will be shown.
3304 changesets without children will be shown.
3301
3305
3302 Returns 0 if matching heads are found, 1 if not.
3306 Returns 0 if matching heads are found, 1 if not.
3303 """
3307 """
3304
3308
3305 start = None
3309 start = None
3306 if 'rev' in opts:
3310 if 'rev' in opts:
3307 start = scmutil.revsingle(repo, opts['rev'], None).node()
3311 start = scmutil.revsingle(repo, opts['rev'], None).node()
3308
3312
3309 if opts.get('topo'):
3313 if opts.get('topo'):
3310 heads = [repo[h] for h in repo.heads(start)]
3314 heads = [repo[h] for h in repo.heads(start)]
3311 else:
3315 else:
3312 heads = []
3316 heads = []
3313 for branch in repo.branchmap():
3317 for branch in repo.branchmap():
3314 heads += repo.branchheads(branch, start, opts.get('closed'))
3318 heads += repo.branchheads(branch, start, opts.get('closed'))
3315 heads = [repo[h] for h in heads]
3319 heads = [repo[h] for h in heads]
3316
3320
3317 if branchrevs:
3321 if branchrevs:
3318 branches = set(repo[br].branch() for br in branchrevs)
3322 branches = set(repo[br].branch() for br in branchrevs)
3319 heads = [h for h in heads if h.branch() in branches]
3323 heads = [h for h in heads if h.branch() in branches]
3320
3324
3321 if opts.get('active') and branchrevs:
3325 if opts.get('active') and branchrevs:
3322 dagheads = repo.heads(start)
3326 dagheads = repo.heads(start)
3323 heads = [h for h in heads if h.node() in dagheads]
3327 heads = [h for h in heads if h.node() in dagheads]
3324
3328
3325 if branchrevs:
3329 if branchrevs:
3326 haveheads = set(h.branch() for h in heads)
3330 haveheads = set(h.branch() for h in heads)
3327 if branches - haveheads:
3331 if branches - haveheads:
3328 headless = ', '.join(b for b in branches - haveheads)
3332 headless = ', '.join(b for b in branches - haveheads)
3329 msg = _('no open branch heads found on branches %s')
3333 msg = _('no open branch heads found on branches %s')
3330 if opts.get('rev'):
3334 if opts.get('rev'):
3331 msg += _(' (started at %s)') % opts['rev']
3335 msg += _(' (started at %s)') % opts['rev']
3332 ui.warn((msg + '\n') % headless)
3336 ui.warn((msg + '\n') % headless)
3333
3337
3334 if not heads:
3338 if not heads:
3335 return 1
3339 return 1
3336
3340
3337 heads = sorted(heads, key=lambda x: -x.rev())
3341 heads = sorted(heads, key=lambda x: -x.rev())
3338 displayer = cmdutil.show_changeset(ui, repo, opts)
3342 displayer = cmdutil.show_changeset(ui, repo, opts)
3339 for ctx in heads:
3343 for ctx in heads:
3340 displayer.show(ctx)
3344 displayer.show(ctx)
3341 displayer.close()
3345 displayer.close()
3342
3346
3343 @command('help',
3347 @command('help',
3344 [('e', 'extension', None, _('show only help for extensions')),
3348 [('e', 'extension', None, _('show only help for extensions')),
3345 ('c', 'command', None, _('show only help for commands')),
3349 ('c', 'command', None, _('show only help for commands')),
3346 ('k', 'keyword', '', _('show topics matching keyword')),
3350 ('k', 'keyword', '', _('show topics matching keyword')),
3347 ],
3351 ],
3348 _('[-ec] [TOPIC]'))
3352 _('[-ec] [TOPIC]'))
3349 def help_(ui, name=None, **opts):
3353 def help_(ui, name=None, **opts):
3350 """show help for a given topic or a help overview
3354 """show help for a given topic or a help overview
3351
3355
3352 With no arguments, print a list of commands with short help messages.
3356 With no arguments, print a list of commands with short help messages.
3353
3357
3354 Given a topic, extension, or command name, print help for that
3358 Given a topic, extension, or command name, print help for that
3355 topic.
3359 topic.
3356
3360
3357 Returns 0 if successful.
3361 Returns 0 if successful.
3358 """
3362 """
3359
3363
3360 textwidth = min(ui.termwidth(), 80) - 2
3364 textwidth = min(ui.termwidth(), 80) - 2
3361
3365
3362 keep = ui.verbose and ['verbose'] or []
3366 keep = ui.verbose and ['verbose'] or []
3363 text = help.help_(ui, name, **opts)
3367 text = help.help_(ui, name, **opts)
3364
3368
3365 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3369 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3366 if 'verbose' in pruned:
3370 if 'verbose' in pruned:
3367 keep.append('omitted')
3371 keep.append('omitted')
3368 else:
3372 else:
3369 keep.append('notomitted')
3373 keep.append('notomitted')
3370 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3374 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3371 ui.write(formatted)
3375 ui.write(formatted)
3372
3376
3373
3377
3374 @command('identify|id',
3378 @command('identify|id',
3375 [('r', 'rev', '',
3379 [('r', 'rev', '',
3376 _('identify the specified revision'), _('REV')),
3380 _('identify the specified revision'), _('REV')),
3377 ('n', 'num', None, _('show local revision number')),
3381 ('n', 'num', None, _('show local revision number')),
3378 ('i', 'id', None, _('show global revision id')),
3382 ('i', 'id', None, _('show global revision id')),
3379 ('b', 'branch', None, _('show branch')),
3383 ('b', 'branch', None, _('show branch')),
3380 ('t', 'tags', None, _('show tags')),
3384 ('t', 'tags', None, _('show tags')),
3381 ('B', 'bookmarks', None, _('show bookmarks')),
3385 ('B', 'bookmarks', None, _('show bookmarks')),
3382 ] + remoteopts,
3386 ] + remoteopts,
3383 _('[-nibtB] [-r REV] [SOURCE]'))
3387 _('[-nibtB] [-r REV] [SOURCE]'))
3384 def identify(ui, repo, source=None, rev=None,
3388 def identify(ui, repo, source=None, rev=None,
3385 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3389 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3386 """identify the working copy or specified revision
3390 """identify the working copy or specified revision
3387
3391
3388 Print a summary identifying the repository state at REV using one or
3392 Print a summary identifying the repository state at REV using one or
3389 two parent hash identifiers, followed by a "+" if the working
3393 two parent hash identifiers, followed by a "+" if the working
3390 directory has uncommitted changes, the branch name (if not default),
3394 directory has uncommitted changes, the branch name (if not default),
3391 a list of tags, and a list of bookmarks.
3395 a list of tags, and a list of bookmarks.
3392
3396
3393 When REV is not given, print a summary of the current state of the
3397 When REV is not given, print a summary of the current state of the
3394 repository.
3398 repository.
3395
3399
3396 Specifying a path to a repository root or Mercurial bundle will
3400 Specifying a path to a repository root or Mercurial bundle will
3397 cause lookup to operate on that repository/bundle.
3401 cause lookup to operate on that repository/bundle.
3398
3402
3399 .. container:: verbose
3403 .. container:: verbose
3400
3404
3401 Examples:
3405 Examples:
3402
3406
3403 - generate a build identifier for the working directory::
3407 - generate a build identifier for the working directory::
3404
3408
3405 hg id --id > build-id.dat
3409 hg id --id > build-id.dat
3406
3410
3407 - find the revision corresponding to a tag::
3411 - find the revision corresponding to a tag::
3408
3412
3409 hg id -n -r 1.3
3413 hg id -n -r 1.3
3410
3414
3411 - check the most recent revision of a remote repository::
3415 - check the most recent revision of a remote repository::
3412
3416
3413 hg id -r tip http://selenic.com/hg/
3417 hg id -r tip http://selenic.com/hg/
3414
3418
3415 Returns 0 if successful.
3419 Returns 0 if successful.
3416 """
3420 """
3417
3421
3418 if not repo and not source:
3422 if not repo and not source:
3419 raise util.Abort(_("there is no Mercurial repository here "
3423 raise util.Abort(_("there is no Mercurial repository here "
3420 "(.hg not found)"))
3424 "(.hg not found)"))
3421
3425
3422 hexfunc = ui.debugflag and hex or short
3426 hexfunc = ui.debugflag and hex or short
3423 default = not (num or id or branch or tags or bookmarks)
3427 default = not (num or id or branch or tags or bookmarks)
3424 output = []
3428 output = []
3425 revs = []
3429 revs = []
3426
3430
3427 if source:
3431 if source:
3428 source, branches = hg.parseurl(ui.expandpath(source))
3432 source, branches = hg.parseurl(ui.expandpath(source))
3429 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3433 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3430 repo = peer.local()
3434 repo = peer.local()
3431 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3435 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3432
3436
3433 if not repo:
3437 if not repo:
3434 if num or branch or tags:
3438 if num or branch or tags:
3435 raise util.Abort(
3439 raise util.Abort(
3436 _("can't query remote revision number, branch, or tags"))
3440 _("can't query remote revision number, branch, or tags"))
3437 if not rev and revs:
3441 if not rev and revs:
3438 rev = revs[0]
3442 rev = revs[0]
3439 if not rev:
3443 if not rev:
3440 rev = "tip"
3444 rev = "tip"
3441
3445
3442 remoterev = peer.lookup(rev)
3446 remoterev = peer.lookup(rev)
3443 if default or id:
3447 if default or id:
3444 output = [hexfunc(remoterev)]
3448 output = [hexfunc(remoterev)]
3445
3449
3446 def getbms():
3450 def getbms():
3447 bms = []
3451 bms = []
3448
3452
3449 if 'bookmarks' in peer.listkeys('namespaces'):
3453 if 'bookmarks' in peer.listkeys('namespaces'):
3450 hexremoterev = hex(remoterev)
3454 hexremoterev = hex(remoterev)
3451 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3455 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3452 if bmr == hexremoterev]
3456 if bmr == hexremoterev]
3453
3457
3454 return sorted(bms)
3458 return sorted(bms)
3455
3459
3456 if bookmarks:
3460 if bookmarks:
3457 output.extend(getbms())
3461 output.extend(getbms())
3458 elif default and not ui.quiet:
3462 elif default and not ui.quiet:
3459 # multiple bookmarks for a single parent separated by '/'
3463 # multiple bookmarks for a single parent separated by '/'
3460 bm = '/'.join(getbms())
3464 bm = '/'.join(getbms())
3461 if bm:
3465 if bm:
3462 output.append(bm)
3466 output.append(bm)
3463 else:
3467 else:
3464 if not rev:
3468 if not rev:
3465 ctx = repo[None]
3469 ctx = repo[None]
3466 parents = ctx.parents()
3470 parents = ctx.parents()
3467 changed = ""
3471 changed = ""
3468 if default or id or num:
3472 if default or id or num:
3469 if (util.any(repo.status())
3473 if (util.any(repo.status())
3470 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3474 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3471 changed = '+'
3475 changed = '+'
3472 if default or id:
3476 if default or id:
3473 output = ["%s%s" %
3477 output = ["%s%s" %
3474 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3478 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3475 if num:
3479 if num:
3476 output.append("%s%s" %
3480 output.append("%s%s" %
3477 ('+'.join([str(p.rev()) for p in parents]), changed))
3481 ('+'.join([str(p.rev()) for p in parents]), changed))
3478 else:
3482 else:
3479 ctx = scmutil.revsingle(repo, rev)
3483 ctx = scmutil.revsingle(repo, rev)
3480 if default or id:
3484 if default or id:
3481 output = [hexfunc(ctx.node())]
3485 output = [hexfunc(ctx.node())]
3482 if num:
3486 if num:
3483 output.append(str(ctx.rev()))
3487 output.append(str(ctx.rev()))
3484
3488
3485 if default and not ui.quiet:
3489 if default and not ui.quiet:
3486 b = ctx.branch()
3490 b = ctx.branch()
3487 if b != 'default':
3491 if b != 'default':
3488 output.append("(%s)" % b)
3492 output.append("(%s)" % b)
3489
3493
3490 # multiple tags for a single parent separated by '/'
3494 # multiple tags for a single parent separated by '/'
3491 t = '/'.join(ctx.tags())
3495 t = '/'.join(ctx.tags())
3492 if t:
3496 if t:
3493 output.append(t)
3497 output.append(t)
3494
3498
3495 # multiple bookmarks for a single parent separated by '/'
3499 # multiple bookmarks for a single parent separated by '/'
3496 bm = '/'.join(ctx.bookmarks())
3500 bm = '/'.join(ctx.bookmarks())
3497 if bm:
3501 if bm:
3498 output.append(bm)
3502 output.append(bm)
3499 else:
3503 else:
3500 if branch:
3504 if branch:
3501 output.append(ctx.branch())
3505 output.append(ctx.branch())
3502
3506
3503 if tags:
3507 if tags:
3504 output.extend(ctx.tags())
3508 output.extend(ctx.tags())
3505
3509
3506 if bookmarks:
3510 if bookmarks:
3507 output.extend(ctx.bookmarks())
3511 output.extend(ctx.bookmarks())
3508
3512
3509 ui.write("%s\n" % ' '.join(output))
3513 ui.write("%s\n" % ' '.join(output))
3510
3514
3511 @command('import|patch',
3515 @command('import|patch',
3512 [('p', 'strip', 1,
3516 [('p', 'strip', 1,
3513 _('directory strip option for patch. This has the same '
3517 _('directory strip option for patch. This has the same '
3514 'meaning as the corresponding patch option'), _('NUM')),
3518 'meaning as the corresponding patch option'), _('NUM')),
3515 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3519 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3516 ('e', 'edit', False, _('invoke editor on commit messages')),
3520 ('e', 'edit', False, _('invoke editor on commit messages')),
3517 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3521 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3518 ('', 'no-commit', None,
3522 ('', 'no-commit', None,
3519 _("don't commit, just update the working directory")),
3523 _("don't commit, just update the working directory")),
3520 ('', 'bypass', None,
3524 ('', 'bypass', None,
3521 _("apply patch without touching the working directory")),
3525 _("apply patch without touching the working directory")),
3522 ('', 'exact', None,
3526 ('', 'exact', None,
3523 _('apply patch to the nodes from which it was generated')),
3527 _('apply patch to the nodes from which it was generated')),
3524 ('', 'import-branch', None,
3528 ('', 'import-branch', None,
3525 _('use any branch information in patch (implied by --exact)'))] +
3529 _('use any branch information in patch (implied by --exact)'))] +
3526 commitopts + commitopts2 + similarityopts,
3530 commitopts + commitopts2 + similarityopts,
3527 _('[OPTION]... PATCH...'))
3531 _('[OPTION]... PATCH...'))
3528 def import_(ui, repo, patch1=None, *patches, **opts):
3532 def import_(ui, repo, patch1=None, *patches, **opts):
3529 """import an ordered set of patches
3533 """import an ordered set of patches
3530
3534
3531 Import a list of patches and commit them individually (unless
3535 Import a list of patches and commit them individually (unless
3532 --no-commit is specified).
3536 --no-commit is specified).
3533
3537
3534 If there are outstanding changes in the working directory, import
3538 If there are outstanding changes in the working directory, import
3535 will abort unless given the -f/--force flag.
3539 will abort unless given the -f/--force flag.
3536
3540
3537 You can import a patch straight from a mail message. Even patches
3541 You can import a patch straight from a mail message. Even patches
3538 as attachments work (to use the body part, it must have type
3542 as attachments work (to use the body part, it must have type
3539 text/plain or text/x-patch). From and Subject headers of email
3543 text/plain or text/x-patch). From and Subject headers of email
3540 message are used as default committer and commit message. All
3544 message are used as default committer and commit message. All
3541 text/plain body parts before first diff are added to commit
3545 text/plain body parts before first diff are added to commit
3542 message.
3546 message.
3543
3547
3544 If the imported patch was generated by :hg:`export`, user and
3548 If the imported patch was generated by :hg:`export`, user and
3545 description from patch override values from message headers and
3549 description from patch override values from message headers and
3546 body. Values given on command line with -m/--message and -u/--user
3550 body. Values given on command line with -m/--message and -u/--user
3547 override these.
3551 override these.
3548
3552
3549 If --exact is specified, import will set the working directory to
3553 If --exact is specified, import will set the working directory to
3550 the parent of each patch before applying it, and will abort if the
3554 the parent of each patch before applying it, and will abort if the
3551 resulting changeset has a different ID than the one recorded in
3555 resulting changeset has a different ID than the one recorded in
3552 the patch. This may happen due to character set problems or other
3556 the patch. This may happen due to character set problems or other
3553 deficiencies in the text patch format.
3557 deficiencies in the text patch format.
3554
3558
3555 Use --bypass to apply and commit patches directly to the
3559 Use --bypass to apply and commit patches directly to the
3556 repository, not touching the working directory. Without --exact,
3560 repository, not touching the working directory. Without --exact,
3557 patches will be applied on top of the working directory parent
3561 patches will be applied on top of the working directory parent
3558 revision.
3562 revision.
3559
3563
3560 With -s/--similarity, hg will attempt to discover renames and
3564 With -s/--similarity, hg will attempt to discover renames and
3561 copies in the patch in the same way as :hg:`addremove`.
3565 copies in the patch in the same way as :hg:`addremove`.
3562
3566
3563 To read a patch from standard input, use "-" as the patch name. If
3567 To read a patch from standard input, use "-" as the patch name. If
3564 a URL is specified, the patch will be downloaded from it.
3568 a URL is specified, the patch will be downloaded from it.
3565 See :hg:`help dates` for a list of formats valid for -d/--date.
3569 See :hg:`help dates` for a list of formats valid for -d/--date.
3566
3570
3567 .. container:: verbose
3571 .. container:: verbose
3568
3572
3569 Examples:
3573 Examples:
3570
3574
3571 - import a traditional patch from a website and detect renames::
3575 - import a traditional patch from a website and detect renames::
3572
3576
3573 hg import -s 80 http://example.com/bugfix.patch
3577 hg import -s 80 http://example.com/bugfix.patch
3574
3578
3575 - import a changeset from an hgweb server::
3579 - import a changeset from an hgweb server::
3576
3580
3577 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3581 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3578
3582
3579 - import all the patches in an Unix-style mbox::
3583 - import all the patches in an Unix-style mbox::
3580
3584
3581 hg import incoming-patches.mbox
3585 hg import incoming-patches.mbox
3582
3586
3583 - attempt to exactly restore an exported changeset (not always
3587 - attempt to exactly restore an exported changeset (not always
3584 possible)::
3588 possible)::
3585
3589
3586 hg import --exact proposed-fix.patch
3590 hg import --exact proposed-fix.patch
3587
3591
3588 Returns 0 on success.
3592 Returns 0 on success.
3589 """
3593 """
3590
3594
3591 if not patch1:
3595 if not patch1:
3592 raise util.Abort(_('need at least one patch to import'))
3596 raise util.Abort(_('need at least one patch to import'))
3593
3597
3594 patches = (patch1,) + patches
3598 patches = (patch1,) + patches
3595
3599
3596 date = opts.get('date')
3600 date = opts.get('date')
3597 if date:
3601 if date:
3598 opts['date'] = util.parsedate(date)
3602 opts['date'] = util.parsedate(date)
3599
3603
3600 editor = cmdutil.commiteditor
3604 editor = cmdutil.commiteditor
3601 if opts.get('edit'):
3605 if opts.get('edit'):
3602 editor = cmdutil.commitforceeditor
3606 editor = cmdutil.commitforceeditor
3603
3607
3604 update = not opts.get('bypass')
3608 update = not opts.get('bypass')
3605 if not update and opts.get('no_commit'):
3609 if not update and opts.get('no_commit'):
3606 raise util.Abort(_('cannot use --no-commit with --bypass'))
3610 raise util.Abort(_('cannot use --no-commit with --bypass'))
3607 try:
3611 try:
3608 sim = float(opts.get('similarity') or 0)
3612 sim = float(opts.get('similarity') or 0)
3609 except ValueError:
3613 except ValueError:
3610 raise util.Abort(_('similarity must be a number'))
3614 raise util.Abort(_('similarity must be a number'))
3611 if sim < 0 or sim > 100:
3615 if sim < 0 or sim > 100:
3612 raise util.Abort(_('similarity must be between 0 and 100'))
3616 raise util.Abort(_('similarity must be between 0 and 100'))
3613 if sim and not update:
3617 if sim and not update:
3614 raise util.Abort(_('cannot use --similarity with --bypass'))
3618 raise util.Abort(_('cannot use --similarity with --bypass'))
3615
3619
3616 if (opts.get('exact') or not opts.get('force')) and update:
3620 if (opts.get('exact') or not opts.get('force')) and update:
3617 cmdutil.bailifchanged(repo)
3621 cmdutil.bailifchanged(repo)
3618
3622
3619 base = opts["base"]
3623 base = opts["base"]
3620 strip = opts["strip"]
3624 strip = opts["strip"]
3621 wlock = lock = tr = None
3625 wlock = lock = tr = None
3622 msgs = []
3626 msgs = []
3623
3627
3624 def tryone(ui, hunk, parents):
3628 def tryone(ui, hunk, parents):
3625 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3629 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3626 patch.extract(ui, hunk)
3630 patch.extract(ui, hunk)
3627
3631
3628 if not tmpname:
3632 if not tmpname:
3629 return (None, None)
3633 return (None, None)
3630 msg = _('applied to working directory')
3634 msg = _('applied to working directory')
3631
3635
3632 try:
3636 try:
3633 cmdline_message = cmdutil.logmessage(ui, opts)
3637 cmdline_message = cmdutil.logmessage(ui, opts)
3634 if cmdline_message:
3638 if cmdline_message:
3635 # pickup the cmdline msg
3639 # pickup the cmdline msg
3636 message = cmdline_message
3640 message = cmdline_message
3637 elif message:
3641 elif message:
3638 # pickup the patch msg
3642 # pickup the patch msg
3639 message = message.strip()
3643 message = message.strip()
3640 else:
3644 else:
3641 # launch the editor
3645 # launch the editor
3642 message = None
3646 message = None
3643 ui.debug('message:\n%s\n' % message)
3647 ui.debug('message:\n%s\n' % message)
3644
3648
3645 if len(parents) == 1:
3649 if len(parents) == 1:
3646 parents.append(repo[nullid])
3650 parents.append(repo[nullid])
3647 if opts.get('exact'):
3651 if opts.get('exact'):
3648 if not nodeid or not p1:
3652 if not nodeid or not p1:
3649 raise util.Abort(_('not a Mercurial patch'))
3653 raise util.Abort(_('not a Mercurial patch'))
3650 p1 = repo[p1]
3654 p1 = repo[p1]
3651 p2 = repo[p2 or nullid]
3655 p2 = repo[p2 or nullid]
3652 elif p2:
3656 elif p2:
3653 try:
3657 try:
3654 p1 = repo[p1]
3658 p1 = repo[p1]
3655 p2 = repo[p2]
3659 p2 = repo[p2]
3656 # Without any options, consider p2 only if the
3660 # Without any options, consider p2 only if the
3657 # patch is being applied on top of the recorded
3661 # patch is being applied on top of the recorded
3658 # first parent.
3662 # first parent.
3659 if p1 != parents[0]:
3663 if p1 != parents[0]:
3660 p1 = parents[0]
3664 p1 = parents[0]
3661 p2 = repo[nullid]
3665 p2 = repo[nullid]
3662 except error.RepoError:
3666 except error.RepoError:
3663 p1, p2 = parents
3667 p1, p2 = parents
3664 else:
3668 else:
3665 p1, p2 = parents
3669 p1, p2 = parents
3666
3670
3667 n = None
3671 n = None
3668 if update:
3672 if update:
3669 if p1 != parents[0]:
3673 if p1 != parents[0]:
3670 hg.clean(repo, p1.node())
3674 hg.clean(repo, p1.node())
3671 if p2 != parents[1]:
3675 if p2 != parents[1]:
3672 repo.setparents(p1.node(), p2.node())
3676 repo.setparents(p1.node(), p2.node())
3673
3677
3674 if opts.get('exact') or opts.get('import_branch'):
3678 if opts.get('exact') or opts.get('import_branch'):
3675 repo.dirstate.setbranch(branch or 'default')
3679 repo.dirstate.setbranch(branch or 'default')
3676
3680
3677 files = set()
3681 files = set()
3678 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3682 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3679 eolmode=None, similarity=sim / 100.0)
3683 eolmode=None, similarity=sim / 100.0)
3680 files = list(files)
3684 files = list(files)
3681 if opts.get('no_commit'):
3685 if opts.get('no_commit'):
3682 if message:
3686 if message:
3683 msgs.append(message)
3687 msgs.append(message)
3684 else:
3688 else:
3685 if opts.get('exact') or p2:
3689 if opts.get('exact') or p2:
3686 # If you got here, you either use --force and know what
3690 # If you got here, you either use --force and know what
3687 # you are doing or used --exact or a merge patch while
3691 # you are doing or used --exact or a merge patch while
3688 # being updated to its first parent.
3692 # being updated to its first parent.
3689 m = None
3693 m = None
3690 else:
3694 else:
3691 m = scmutil.matchfiles(repo, files or [])
3695 m = scmutil.matchfiles(repo, files or [])
3692 n = repo.commit(message, opts.get('user') or user,
3696 n = repo.commit(message, opts.get('user') or user,
3693 opts.get('date') or date, match=m,
3697 opts.get('date') or date, match=m,
3694 editor=editor)
3698 editor=editor)
3695 else:
3699 else:
3696 if opts.get('exact') or opts.get('import_branch'):
3700 if opts.get('exact') or opts.get('import_branch'):
3697 branch = branch or 'default'
3701 branch = branch or 'default'
3698 else:
3702 else:
3699 branch = p1.branch()
3703 branch = p1.branch()
3700 store = patch.filestore()
3704 store = patch.filestore()
3701 try:
3705 try:
3702 files = set()
3706 files = set()
3703 try:
3707 try:
3704 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3708 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3705 files, eolmode=None)
3709 files, eolmode=None)
3706 except patch.PatchError, e:
3710 except patch.PatchError, e:
3707 raise util.Abort(str(e))
3711 raise util.Abort(str(e))
3708 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3712 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3709 message,
3713 message,
3710 opts.get('user') or user,
3714 opts.get('user') or user,
3711 opts.get('date') or date,
3715 opts.get('date') or date,
3712 branch, files, store,
3716 branch, files, store,
3713 editor=cmdutil.commiteditor)
3717 editor=cmdutil.commiteditor)
3714 repo.savecommitmessage(memctx.description())
3718 repo.savecommitmessage(memctx.description())
3715 n = memctx.commit()
3719 n = memctx.commit()
3716 finally:
3720 finally:
3717 store.close()
3721 store.close()
3718 if opts.get('exact') and hex(n) != nodeid:
3722 if opts.get('exact') and hex(n) != nodeid:
3719 raise util.Abort(_('patch is damaged or loses information'))
3723 raise util.Abort(_('patch is damaged or loses information'))
3720 if n:
3724 if n:
3721 # i18n: refers to a short changeset id
3725 # i18n: refers to a short changeset id
3722 msg = _('created %s') % short(n)
3726 msg = _('created %s') % short(n)
3723 return (msg, n)
3727 return (msg, n)
3724 finally:
3728 finally:
3725 os.unlink(tmpname)
3729 os.unlink(tmpname)
3726
3730
3727 try:
3731 try:
3728 try:
3732 try:
3729 wlock = repo.wlock()
3733 wlock = repo.wlock()
3730 if not opts.get('no_commit'):
3734 if not opts.get('no_commit'):
3731 lock = repo.lock()
3735 lock = repo.lock()
3732 tr = repo.transaction('import')
3736 tr = repo.transaction('import')
3733 parents = repo.parents()
3737 parents = repo.parents()
3734 for patchurl in patches:
3738 for patchurl in patches:
3735 if patchurl == '-':
3739 if patchurl == '-':
3736 ui.status(_('applying patch from stdin\n'))
3740 ui.status(_('applying patch from stdin\n'))
3737 patchfile = ui.fin
3741 patchfile = ui.fin
3738 patchurl = 'stdin' # for error message
3742 patchurl = 'stdin' # for error message
3739 else:
3743 else:
3740 patchurl = os.path.join(base, patchurl)
3744 patchurl = os.path.join(base, patchurl)
3741 ui.status(_('applying %s\n') % patchurl)
3745 ui.status(_('applying %s\n') % patchurl)
3742 patchfile = hg.openpath(ui, patchurl)
3746 patchfile = hg.openpath(ui, patchurl)
3743
3747
3744 haspatch = False
3748 haspatch = False
3745 for hunk in patch.split(patchfile):
3749 for hunk in patch.split(patchfile):
3746 (msg, node) = tryone(ui, hunk, parents)
3750 (msg, node) = tryone(ui, hunk, parents)
3747 if msg:
3751 if msg:
3748 haspatch = True
3752 haspatch = True
3749 ui.note(msg + '\n')
3753 ui.note(msg + '\n')
3750 if update or opts.get('exact'):
3754 if update or opts.get('exact'):
3751 parents = repo.parents()
3755 parents = repo.parents()
3752 else:
3756 else:
3753 parents = [repo[node]]
3757 parents = [repo[node]]
3754
3758
3755 if not haspatch:
3759 if not haspatch:
3756 raise util.Abort(_('%s: no diffs found') % patchurl)
3760 raise util.Abort(_('%s: no diffs found') % patchurl)
3757
3761
3758 if tr:
3762 if tr:
3759 tr.close()
3763 tr.close()
3760 if msgs:
3764 if msgs:
3761 repo.savecommitmessage('\n* * *\n'.join(msgs))
3765 repo.savecommitmessage('\n* * *\n'.join(msgs))
3762 except: # re-raises
3766 except: # re-raises
3763 # wlock.release() indirectly calls dirstate.write(): since
3767 # wlock.release() indirectly calls dirstate.write(): since
3764 # we're crashing, we do not want to change the working dir
3768 # we're crashing, we do not want to change the working dir
3765 # parent after all, so make sure it writes nothing
3769 # parent after all, so make sure it writes nothing
3766 repo.dirstate.invalidate()
3770 repo.dirstate.invalidate()
3767 raise
3771 raise
3768 finally:
3772 finally:
3769 if tr:
3773 if tr:
3770 tr.release()
3774 tr.release()
3771 release(lock, wlock)
3775 release(lock, wlock)
3772
3776
3773 @command('incoming|in',
3777 @command('incoming|in',
3774 [('f', 'force', None,
3778 [('f', 'force', None,
3775 _('run even if remote repository is unrelated')),
3779 _('run even if remote repository is unrelated')),
3776 ('n', 'newest-first', None, _('show newest record first')),
3780 ('n', 'newest-first', None, _('show newest record first')),
3777 ('', 'bundle', '',
3781 ('', 'bundle', '',
3778 _('file to store the bundles into'), _('FILE')),
3782 _('file to store the bundles into'), _('FILE')),
3779 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3783 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3780 ('B', 'bookmarks', False, _("compare bookmarks")),
3784 ('B', 'bookmarks', False, _("compare bookmarks")),
3781 ('b', 'branch', [],
3785 ('b', 'branch', [],
3782 _('a specific branch you would like to pull'), _('BRANCH')),
3786 _('a specific branch you would like to pull'), _('BRANCH')),
3783 ] + logopts + remoteopts + subrepoopts,
3787 ] + logopts + remoteopts + subrepoopts,
3784 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3788 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3785 def incoming(ui, repo, source="default", **opts):
3789 def incoming(ui, repo, source="default", **opts):
3786 """show new changesets found in source
3790 """show new changesets found in source
3787
3791
3788 Show new changesets found in the specified path/URL or the default
3792 Show new changesets found in the specified path/URL or the default
3789 pull location. These are the changesets that would have been pulled
3793 pull location. These are the changesets that would have been pulled
3790 if a pull at the time you issued this command.
3794 if a pull at the time you issued this command.
3791
3795
3792 For remote repository, using --bundle avoids downloading the
3796 For remote repository, using --bundle avoids downloading the
3793 changesets twice if the incoming is followed by a pull.
3797 changesets twice if the incoming is followed by a pull.
3794
3798
3795 See pull for valid source format details.
3799 See pull for valid source format details.
3796
3800
3797 Returns 0 if there are incoming changes, 1 otherwise.
3801 Returns 0 if there are incoming changes, 1 otherwise.
3798 """
3802 """
3799 if opts.get('graph'):
3803 if opts.get('graph'):
3800 cmdutil.checkunsupportedgraphflags([], opts)
3804 cmdutil.checkunsupportedgraphflags([], opts)
3801 def display(other, chlist, displayer):
3805 def display(other, chlist, displayer):
3802 revdag = cmdutil.graphrevs(other, chlist, opts)
3806 revdag = cmdutil.graphrevs(other, chlist, opts)
3803 showparents = [ctx.node() for ctx in repo[None].parents()]
3807 showparents = [ctx.node() for ctx in repo[None].parents()]
3804 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3808 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3805 graphmod.asciiedges)
3809 graphmod.asciiedges)
3806
3810
3807 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3811 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3808 return 0
3812 return 0
3809
3813
3810 if opts.get('bundle') and opts.get('subrepos'):
3814 if opts.get('bundle') and opts.get('subrepos'):
3811 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3815 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3812
3816
3813 if opts.get('bookmarks'):
3817 if opts.get('bookmarks'):
3814 source, branches = hg.parseurl(ui.expandpath(source),
3818 source, branches = hg.parseurl(ui.expandpath(source),
3815 opts.get('branch'))
3819 opts.get('branch'))
3816 other = hg.peer(repo, opts, source)
3820 other = hg.peer(repo, opts, source)
3817 if 'bookmarks' not in other.listkeys('namespaces'):
3821 if 'bookmarks' not in other.listkeys('namespaces'):
3818 ui.warn(_("remote doesn't support bookmarks\n"))
3822 ui.warn(_("remote doesn't support bookmarks\n"))
3819 return 0
3823 return 0
3820 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3824 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3821 return bookmarks.diff(ui, repo, other)
3825 return bookmarks.diff(ui, repo, other)
3822
3826
3823 repo._subtoppath = ui.expandpath(source)
3827 repo._subtoppath = ui.expandpath(source)
3824 try:
3828 try:
3825 return hg.incoming(ui, repo, source, opts)
3829 return hg.incoming(ui, repo, source, opts)
3826 finally:
3830 finally:
3827 del repo._subtoppath
3831 del repo._subtoppath
3828
3832
3829
3833
3830 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3834 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3831 def init(ui, dest=".", **opts):
3835 def init(ui, dest=".", **opts):
3832 """create a new repository in the given directory
3836 """create a new repository in the given directory
3833
3837
3834 Initialize a new repository in the given directory. If the given
3838 Initialize a new repository in the given directory. If the given
3835 directory does not exist, it will be created.
3839 directory does not exist, it will be created.
3836
3840
3837 If no directory is given, the current directory is used.
3841 If no directory is given, the current directory is used.
3838
3842
3839 It is possible to specify an ``ssh://`` URL as the destination.
3843 It is possible to specify an ``ssh://`` URL as the destination.
3840 See :hg:`help urls` for more information.
3844 See :hg:`help urls` for more information.
3841
3845
3842 Returns 0 on success.
3846 Returns 0 on success.
3843 """
3847 """
3844 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3848 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3845
3849
3846 @command('locate',
3850 @command('locate',
3847 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3851 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3848 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3852 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3849 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3853 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3850 ] + walkopts,
3854 ] + walkopts,
3851 _('[OPTION]... [PATTERN]...'))
3855 _('[OPTION]... [PATTERN]...'))
3852 def locate(ui, repo, *pats, **opts):
3856 def locate(ui, repo, *pats, **opts):
3853 """locate files matching specific patterns
3857 """locate files matching specific patterns
3854
3858
3855 Print files under Mercurial control in the working directory whose
3859 Print files under Mercurial control in the working directory whose
3856 names match the given patterns.
3860 names match the given patterns.
3857
3861
3858 By default, this command searches all directories in the working
3862 By default, this command searches all directories in the working
3859 directory. To search just the current directory and its
3863 directory. To search just the current directory and its
3860 subdirectories, use "--include .".
3864 subdirectories, use "--include .".
3861
3865
3862 If no patterns are given to match, this command prints the names
3866 If no patterns are given to match, this command prints the names
3863 of all files under Mercurial control in the working directory.
3867 of all files under Mercurial control in the working directory.
3864
3868
3865 If you want to feed the output of this command into the "xargs"
3869 If you want to feed the output of this command into the "xargs"
3866 command, use the -0 option to both this command and "xargs". This
3870 command, use the -0 option to both this command and "xargs". This
3867 will avoid the problem of "xargs" treating single filenames that
3871 will avoid the problem of "xargs" treating single filenames that
3868 contain whitespace as multiple filenames.
3872 contain whitespace as multiple filenames.
3869
3873
3870 Returns 0 if a match is found, 1 otherwise.
3874 Returns 0 if a match is found, 1 otherwise.
3871 """
3875 """
3872 end = opts.get('print0') and '\0' or '\n'
3876 end = opts.get('print0') and '\0' or '\n'
3873 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3877 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3874
3878
3875 ret = 1
3879 ret = 1
3876 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3880 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3877 m.bad = lambda x, y: False
3881 m.bad = lambda x, y: False
3878 for abs in repo[rev].walk(m):
3882 for abs in repo[rev].walk(m):
3879 if not rev and abs not in repo.dirstate:
3883 if not rev and abs not in repo.dirstate:
3880 continue
3884 continue
3881 if opts.get('fullpath'):
3885 if opts.get('fullpath'):
3882 ui.write(repo.wjoin(abs), end)
3886 ui.write(repo.wjoin(abs), end)
3883 else:
3887 else:
3884 ui.write(((pats and m.rel(abs)) or abs), end)
3888 ui.write(((pats and m.rel(abs)) or abs), end)
3885 ret = 0
3889 ret = 0
3886
3890
3887 return ret
3891 return ret
3888
3892
3889 @command('^log|history',
3893 @command('^log|history',
3890 [('f', 'follow', None,
3894 [('f', 'follow', None,
3891 _('follow changeset history, or file history across copies and renames')),
3895 _('follow changeset history, or file history across copies and renames')),
3892 ('', 'follow-first', None,
3896 ('', 'follow-first', None,
3893 _('only follow the first parent of merge changesets (DEPRECATED)')),
3897 _('only follow the first parent of merge changesets (DEPRECATED)')),
3894 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3898 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3895 ('C', 'copies', None, _('show copied files')),
3899 ('C', 'copies', None, _('show copied files')),
3896 ('k', 'keyword', [],
3900 ('k', 'keyword', [],
3897 _('do case-insensitive search for a given text'), _('TEXT')),
3901 _('do case-insensitive search for a given text'), _('TEXT')),
3898 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3902 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3899 ('', 'removed', None, _('include revisions where files were removed')),
3903 ('', 'removed', None, _('include revisions where files were removed')),
3900 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3904 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3901 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3905 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3902 ('', 'only-branch', [],
3906 ('', 'only-branch', [],
3903 _('show only changesets within the given named branch (DEPRECATED)'),
3907 _('show only changesets within the given named branch (DEPRECATED)'),
3904 _('BRANCH')),
3908 _('BRANCH')),
3905 ('b', 'branch', [],
3909 ('b', 'branch', [],
3906 _('show changesets within the given named branch'), _('BRANCH')),
3910 _('show changesets within the given named branch'), _('BRANCH')),
3907 ('P', 'prune', [],
3911 ('P', 'prune', [],
3908 _('do not display revision or any of its ancestors'), _('REV')),
3912 _('do not display revision or any of its ancestors'), _('REV')),
3909 ] + logopts + walkopts,
3913 ] + logopts + walkopts,
3910 _('[OPTION]... [FILE]'))
3914 _('[OPTION]... [FILE]'))
3911 def log(ui, repo, *pats, **opts):
3915 def log(ui, repo, *pats, **opts):
3912 """show revision history of entire repository or files
3916 """show revision history of entire repository or files
3913
3917
3914 Print the revision history of the specified files or the entire
3918 Print the revision history of the specified files or the entire
3915 project.
3919 project.
3916
3920
3917 If no revision range is specified, the default is ``tip:0`` unless
3921 If no revision range is specified, the default is ``tip:0`` unless
3918 --follow is set, in which case the working directory parent is
3922 --follow is set, in which case the working directory parent is
3919 used as the starting revision.
3923 used as the starting revision.
3920
3924
3921 File history is shown without following rename or copy history of
3925 File history is shown without following rename or copy history of
3922 files. Use -f/--follow with a filename to follow history across
3926 files. Use -f/--follow with a filename to follow history across
3923 renames and copies. --follow without a filename will only show
3927 renames and copies. --follow without a filename will only show
3924 ancestors or descendants of the starting revision.
3928 ancestors or descendants of the starting revision.
3925
3929
3926 By default this command prints revision number and changeset id,
3930 By default this command prints revision number and changeset id,
3927 tags, non-trivial parents, user, date and time, and a summary for
3931 tags, non-trivial parents, user, date and time, and a summary for
3928 each commit. When the -v/--verbose switch is used, the list of
3932 each commit. When the -v/--verbose switch is used, the list of
3929 changed files and full commit message are shown.
3933 changed files and full commit message are shown.
3930
3934
3931 .. note::
3935 .. note::
3932 log -p/--patch may generate unexpected diff output for merge
3936 log -p/--patch may generate unexpected diff output for merge
3933 changesets, as it will only compare the merge changeset against
3937 changesets, as it will only compare the merge changeset against
3934 its first parent. Also, only files different from BOTH parents
3938 its first parent. Also, only files different from BOTH parents
3935 will appear in files:.
3939 will appear in files:.
3936
3940
3937 .. note::
3941 .. note::
3938 for performance reasons, log FILE may omit duplicate changes
3942 for performance reasons, log FILE may omit duplicate changes
3939 made on branches and will not show deletions. To see all
3943 made on branches and will not show deletions. To see all
3940 changes including duplicates and deletions, use the --removed
3944 changes including duplicates and deletions, use the --removed
3941 switch.
3945 switch.
3942
3946
3943 .. container:: verbose
3947 .. container:: verbose
3944
3948
3945 Some examples:
3949 Some examples:
3946
3950
3947 - changesets with full descriptions and file lists::
3951 - changesets with full descriptions and file lists::
3948
3952
3949 hg log -v
3953 hg log -v
3950
3954
3951 - changesets ancestral to the working directory::
3955 - changesets ancestral to the working directory::
3952
3956
3953 hg log -f
3957 hg log -f
3954
3958
3955 - last 10 commits on the current branch::
3959 - last 10 commits on the current branch::
3956
3960
3957 hg log -l 10 -b .
3961 hg log -l 10 -b .
3958
3962
3959 - changesets showing all modifications of a file, including removals::
3963 - changesets showing all modifications of a file, including removals::
3960
3964
3961 hg log --removed file.c
3965 hg log --removed file.c
3962
3966
3963 - all changesets that touch a directory, with diffs, excluding merges::
3967 - all changesets that touch a directory, with diffs, excluding merges::
3964
3968
3965 hg log -Mp lib/
3969 hg log -Mp lib/
3966
3970
3967 - all revision numbers that match a keyword::
3971 - all revision numbers that match a keyword::
3968
3972
3969 hg log -k bug --template "{rev}\\n"
3973 hg log -k bug --template "{rev}\\n"
3970
3974
3971 - check if a given changeset is included is a tagged release::
3975 - check if a given changeset is included is a tagged release::
3972
3976
3973 hg log -r "a21ccf and ancestor(1.9)"
3977 hg log -r "a21ccf and ancestor(1.9)"
3974
3978
3975 - find all changesets by some user in a date range::
3979 - find all changesets by some user in a date range::
3976
3980
3977 hg log -k alice -d "may 2008 to jul 2008"
3981 hg log -k alice -d "may 2008 to jul 2008"
3978
3982
3979 - summary of all changesets after the last tag::
3983 - summary of all changesets after the last tag::
3980
3984
3981 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3985 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3982
3986
3983 See :hg:`help dates` for a list of formats valid for -d/--date.
3987 See :hg:`help dates` for a list of formats valid for -d/--date.
3984
3988
3985 See :hg:`help revisions` and :hg:`help revsets` for more about
3989 See :hg:`help revisions` and :hg:`help revsets` for more about
3986 specifying revisions.
3990 specifying revisions.
3987
3991
3988 See :hg:`help templates` for more about pre-packaged styles and
3992 See :hg:`help templates` for more about pre-packaged styles and
3989 specifying custom templates.
3993 specifying custom templates.
3990
3994
3991 Returns 0 on success.
3995 Returns 0 on success.
3992 """
3996 """
3993 if opts.get('graph'):
3997 if opts.get('graph'):
3994 return cmdutil.graphlog(ui, repo, *pats, **opts)
3998 return cmdutil.graphlog(ui, repo, *pats, **opts)
3995
3999
3996 matchfn = scmutil.match(repo[None], pats, opts)
4000 matchfn = scmutil.match(repo[None], pats, opts)
3997 limit = cmdutil.loglimit(opts)
4001 limit = cmdutil.loglimit(opts)
3998 count = 0
4002 count = 0
3999
4003
4000 getrenamed, endrev = None, None
4004 getrenamed, endrev = None, None
4001 if opts.get('copies'):
4005 if opts.get('copies'):
4002 if opts.get('rev'):
4006 if opts.get('rev'):
4003 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4007 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4004 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4008 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4005
4009
4006 df = False
4010 df = False
4007 if opts.get("date"):
4011 if opts.get("date"):
4008 df = util.matchdate(opts["date"])
4012 df = util.matchdate(opts["date"])
4009
4013
4010 branches = opts.get('branch', []) + opts.get('only_branch', [])
4014 branches = opts.get('branch', []) + opts.get('only_branch', [])
4011 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4015 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4012
4016
4013 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4017 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4014 def prep(ctx, fns):
4018 def prep(ctx, fns):
4015 rev = ctx.rev()
4019 rev = ctx.rev()
4016 parents = [p for p in repo.changelog.parentrevs(rev)
4020 parents = [p for p in repo.changelog.parentrevs(rev)
4017 if p != nullrev]
4021 if p != nullrev]
4018 if opts.get('no_merges') and len(parents) == 2:
4022 if opts.get('no_merges') and len(parents) == 2:
4019 return
4023 return
4020 if opts.get('only_merges') and len(parents) != 2:
4024 if opts.get('only_merges') and len(parents) != 2:
4021 return
4025 return
4022 if opts.get('branch') and ctx.branch() not in opts['branch']:
4026 if opts.get('branch') and ctx.branch() not in opts['branch']:
4023 return
4027 return
4024 if df and not df(ctx.date()[0]):
4028 if df and not df(ctx.date()[0]):
4025 return
4029 return
4026
4030
4027 lower = encoding.lower
4031 lower = encoding.lower
4028 if opts.get('user'):
4032 if opts.get('user'):
4029 luser = lower(ctx.user())
4033 luser = lower(ctx.user())
4030 for k in [lower(x) for x in opts['user']]:
4034 for k in [lower(x) for x in opts['user']]:
4031 if (k in luser):
4035 if (k in luser):
4032 break
4036 break
4033 else:
4037 else:
4034 return
4038 return
4035 if opts.get('keyword'):
4039 if opts.get('keyword'):
4036 luser = lower(ctx.user())
4040 luser = lower(ctx.user())
4037 ldesc = lower(ctx.description())
4041 ldesc = lower(ctx.description())
4038 lfiles = lower(" ".join(ctx.files()))
4042 lfiles = lower(" ".join(ctx.files()))
4039 for k in [lower(x) for x in opts['keyword']]:
4043 for k in [lower(x) for x in opts['keyword']]:
4040 if (k in luser or k in ldesc or k in lfiles):
4044 if (k in luser or k in ldesc or k in lfiles):
4041 break
4045 break
4042 else:
4046 else:
4043 return
4047 return
4044
4048
4045 copies = None
4049 copies = None
4046 if getrenamed is not None and rev:
4050 if getrenamed is not None and rev:
4047 copies = []
4051 copies = []
4048 for fn in ctx.files():
4052 for fn in ctx.files():
4049 rename = getrenamed(fn, rev)
4053 rename = getrenamed(fn, rev)
4050 if rename:
4054 if rename:
4051 copies.append((fn, rename[0]))
4055 copies.append((fn, rename[0]))
4052
4056
4053 revmatchfn = None
4057 revmatchfn = None
4054 if opts.get('patch') or opts.get('stat'):
4058 if opts.get('patch') or opts.get('stat'):
4055 if opts.get('follow') or opts.get('follow_first'):
4059 if opts.get('follow') or opts.get('follow_first'):
4056 # note: this might be wrong when following through merges
4060 # note: this might be wrong when following through merges
4057 revmatchfn = scmutil.match(repo[None], fns, default='path')
4061 revmatchfn = scmutil.match(repo[None], fns, default='path')
4058 else:
4062 else:
4059 revmatchfn = matchfn
4063 revmatchfn = matchfn
4060
4064
4061 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4065 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4062
4066
4063 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4067 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4064 if displayer.flush(ctx.rev()):
4068 if displayer.flush(ctx.rev()):
4065 count += 1
4069 count += 1
4066 if count == limit:
4070 if count == limit:
4067 break
4071 break
4068 displayer.close()
4072 displayer.close()
4069
4073
4070 @command('manifest',
4074 @command('manifest',
4071 [('r', 'rev', '', _('revision to display'), _('REV')),
4075 [('r', 'rev', '', _('revision to display'), _('REV')),
4072 ('', 'all', False, _("list files from all revisions"))],
4076 ('', 'all', False, _("list files from all revisions"))],
4073 _('[-r REV]'))
4077 _('[-r REV]'))
4074 def manifest(ui, repo, node=None, rev=None, **opts):
4078 def manifest(ui, repo, node=None, rev=None, **opts):
4075 """output the current or given revision of the project manifest
4079 """output the current or given revision of the project manifest
4076
4080
4077 Print a list of version controlled files for the given revision.
4081 Print a list of version controlled files for the given revision.
4078 If no revision is given, the first parent of the working directory
4082 If no revision is given, the first parent of the working directory
4079 is used, or the null revision if no revision is checked out.
4083 is used, or the null revision if no revision is checked out.
4080
4084
4081 With -v, print file permissions, symlink and executable bits.
4085 With -v, print file permissions, symlink and executable bits.
4082 With --debug, print file revision hashes.
4086 With --debug, print file revision hashes.
4083
4087
4084 If option --all is specified, the list of all files from all revisions
4088 If option --all is specified, the list of all files from all revisions
4085 is printed. This includes deleted and renamed files.
4089 is printed. This includes deleted and renamed files.
4086
4090
4087 Returns 0 on success.
4091 Returns 0 on success.
4088 """
4092 """
4089
4093
4090 fm = ui.formatter('manifest', opts)
4094 fm = ui.formatter('manifest', opts)
4091
4095
4092 if opts.get('all'):
4096 if opts.get('all'):
4093 if rev or node:
4097 if rev or node:
4094 raise util.Abort(_("can't specify a revision with --all"))
4098 raise util.Abort(_("can't specify a revision with --all"))
4095
4099
4096 res = []
4100 res = []
4097 prefix = "data/"
4101 prefix = "data/"
4098 suffix = ".i"
4102 suffix = ".i"
4099 plen = len(prefix)
4103 plen = len(prefix)
4100 slen = len(suffix)
4104 slen = len(suffix)
4101 lock = repo.lock()
4105 lock = repo.lock()
4102 try:
4106 try:
4103 for fn, b, size in repo.store.datafiles():
4107 for fn, b, size in repo.store.datafiles():
4104 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4108 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4105 res.append(fn[plen:-slen])
4109 res.append(fn[plen:-slen])
4106 finally:
4110 finally:
4107 lock.release()
4111 lock.release()
4108 for f in res:
4112 for f in res:
4109 fm.startitem()
4113 fm.startitem()
4110 fm.write("path", '%s\n', f)
4114 fm.write("path", '%s\n', f)
4111 fm.end()
4115 fm.end()
4112 return
4116 return
4113
4117
4114 if rev and node:
4118 if rev and node:
4115 raise util.Abort(_("please specify just one revision"))
4119 raise util.Abort(_("please specify just one revision"))
4116
4120
4117 if not node:
4121 if not node:
4118 node = rev
4122 node = rev
4119
4123
4120 char = {'l': '@', 'x': '*', '': ''}
4124 char = {'l': '@', 'x': '*', '': ''}
4121 mode = {'l': '644', 'x': '755', '': '644'}
4125 mode = {'l': '644', 'x': '755', '': '644'}
4122 ctx = scmutil.revsingle(repo, node)
4126 ctx = scmutil.revsingle(repo, node)
4123 mf = ctx.manifest()
4127 mf = ctx.manifest()
4124 for f in ctx:
4128 for f in ctx:
4125 fm.startitem()
4129 fm.startitem()
4126 fl = ctx[f].flags()
4130 fl = ctx[f].flags()
4127 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4131 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4128 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4132 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4129 fm.write('path', '%s\n', f)
4133 fm.write('path', '%s\n', f)
4130 fm.end()
4134 fm.end()
4131
4135
4132 @command('^merge',
4136 @command('^merge',
4133 [('f', 'force', None, _('force a merge with outstanding changes')),
4137 [('f', 'force', None, _('force a merge with outstanding changes')),
4134 ('r', 'rev', '', _('revision to merge'), _('REV')),
4138 ('r', 'rev', '', _('revision to merge'), _('REV')),
4135 ('P', 'preview', None,
4139 ('P', 'preview', None,
4136 _('review revisions to merge (no merge is performed)'))
4140 _('review revisions to merge (no merge is performed)'))
4137 ] + mergetoolopts,
4141 ] + mergetoolopts,
4138 _('[-P] [-f] [[-r] REV]'))
4142 _('[-P] [-f] [[-r] REV]'))
4139 def merge(ui, repo, node=None, **opts):
4143 def merge(ui, repo, node=None, **opts):
4140 """merge working directory with another revision
4144 """merge working directory with another revision
4141
4145
4142 The current working directory is updated with all changes made in
4146 The current working directory is updated with all changes made in
4143 the requested revision since the last common predecessor revision.
4147 the requested revision since the last common predecessor revision.
4144
4148
4145 Files that changed between either parent are marked as changed for
4149 Files that changed between either parent are marked as changed for
4146 the next commit and a commit must be performed before any further
4150 the next commit and a commit must be performed before any further
4147 updates to the repository are allowed. The next commit will have
4151 updates to the repository are allowed. The next commit will have
4148 two parents.
4152 two parents.
4149
4153
4150 ``--tool`` can be used to specify the merge tool used for file
4154 ``--tool`` can be used to specify the merge tool used for file
4151 merges. It overrides the HGMERGE environment variable and your
4155 merges. It overrides the HGMERGE environment variable and your
4152 configuration files. See :hg:`help merge-tools` for options.
4156 configuration files. See :hg:`help merge-tools` for options.
4153
4157
4154 If no revision is specified, the working directory's parent is a
4158 If no revision is specified, the working directory's parent is a
4155 head revision, and the current branch contains exactly one other
4159 head revision, and the current branch contains exactly one other
4156 head, the other head is merged with by default. Otherwise, an
4160 head, the other head is merged with by default. Otherwise, an
4157 explicit revision with which to merge with must be provided.
4161 explicit revision with which to merge with must be provided.
4158
4162
4159 :hg:`resolve` must be used to resolve unresolved files.
4163 :hg:`resolve` must be used to resolve unresolved files.
4160
4164
4161 To undo an uncommitted merge, use :hg:`update --clean .` which
4165 To undo an uncommitted merge, use :hg:`update --clean .` which
4162 will check out a clean copy of the original merge parent, losing
4166 will check out a clean copy of the original merge parent, losing
4163 all changes.
4167 all changes.
4164
4168
4165 Returns 0 on success, 1 if there are unresolved files.
4169 Returns 0 on success, 1 if there are unresolved files.
4166 """
4170 """
4167
4171
4168 if opts.get('rev') and node:
4172 if opts.get('rev') and node:
4169 raise util.Abort(_("please specify just one revision"))
4173 raise util.Abort(_("please specify just one revision"))
4170 if not node:
4174 if not node:
4171 node = opts.get('rev')
4175 node = opts.get('rev')
4172
4176
4173 if node:
4177 if node:
4174 node = scmutil.revsingle(repo, node).node()
4178 node = scmutil.revsingle(repo, node).node()
4175
4179
4176 if not node and repo._bookmarkcurrent:
4180 if not node and repo._bookmarkcurrent:
4177 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4181 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4178 curhead = repo[repo._bookmarkcurrent].node()
4182 curhead = repo[repo._bookmarkcurrent].node()
4179 if len(bmheads) == 2:
4183 if len(bmheads) == 2:
4180 if curhead == bmheads[0]:
4184 if curhead == bmheads[0]:
4181 node = bmheads[1]
4185 node = bmheads[1]
4182 else:
4186 else:
4183 node = bmheads[0]
4187 node = bmheads[0]
4184 elif len(bmheads) > 2:
4188 elif len(bmheads) > 2:
4185 raise util.Abort(_("multiple matching bookmarks to merge - "
4189 raise util.Abort(_("multiple matching bookmarks to merge - "
4186 "please merge with an explicit rev or bookmark"),
4190 "please merge with an explicit rev or bookmark"),
4187 hint=_("run 'hg heads' to see all heads"))
4191 hint=_("run 'hg heads' to see all heads"))
4188 elif len(bmheads) <= 1:
4192 elif len(bmheads) <= 1:
4189 raise util.Abort(_("no matching bookmark to merge - "
4193 raise util.Abort(_("no matching bookmark to merge - "
4190 "please merge with an explicit rev or bookmark"),
4194 "please merge with an explicit rev or bookmark"),
4191 hint=_("run 'hg heads' to see all heads"))
4195 hint=_("run 'hg heads' to see all heads"))
4192
4196
4193 if not node and not repo._bookmarkcurrent:
4197 if not node and not repo._bookmarkcurrent:
4194 branch = repo[None].branch()
4198 branch = repo[None].branch()
4195 bheads = repo.branchheads(branch)
4199 bheads = repo.branchheads(branch)
4196 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4200 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4197
4201
4198 if len(nbhs) > 2:
4202 if len(nbhs) > 2:
4199 raise util.Abort(_("branch '%s' has %d heads - "
4203 raise util.Abort(_("branch '%s' has %d heads - "
4200 "please merge with an explicit rev")
4204 "please merge with an explicit rev")
4201 % (branch, len(bheads)),
4205 % (branch, len(bheads)),
4202 hint=_("run 'hg heads .' to see heads"))
4206 hint=_("run 'hg heads .' to see heads"))
4203
4207
4204 parent = repo.dirstate.p1()
4208 parent = repo.dirstate.p1()
4205 if len(nbhs) <= 1:
4209 if len(nbhs) <= 1:
4206 if len(bheads) > 1:
4210 if len(bheads) > 1:
4207 raise util.Abort(_("heads are bookmarked - "
4211 raise util.Abort(_("heads are bookmarked - "
4208 "please merge with an explicit rev"),
4212 "please merge with an explicit rev"),
4209 hint=_("run 'hg heads' to see all heads"))
4213 hint=_("run 'hg heads' to see all heads"))
4210 if len(repo.heads()) > 1:
4214 if len(repo.heads()) > 1:
4211 raise util.Abort(_("branch '%s' has one head - "
4215 raise util.Abort(_("branch '%s' has one head - "
4212 "please merge with an explicit rev")
4216 "please merge with an explicit rev")
4213 % branch,
4217 % branch,
4214 hint=_("run 'hg heads' to see all heads"))
4218 hint=_("run 'hg heads' to see all heads"))
4215 msg, hint = _('nothing to merge'), None
4219 msg, hint = _('nothing to merge'), None
4216 if parent != repo.lookup(branch):
4220 if parent != repo.lookup(branch):
4217 hint = _("use 'hg update' instead")
4221 hint = _("use 'hg update' instead")
4218 raise util.Abort(msg, hint=hint)
4222 raise util.Abort(msg, hint=hint)
4219
4223
4220 if parent not in bheads:
4224 if parent not in bheads:
4221 raise util.Abort(_('working directory not at a head revision'),
4225 raise util.Abort(_('working directory not at a head revision'),
4222 hint=_("use 'hg update' or merge with an "
4226 hint=_("use 'hg update' or merge with an "
4223 "explicit revision"))
4227 "explicit revision"))
4224 if parent == nbhs[0]:
4228 if parent == nbhs[0]:
4225 node = nbhs[-1]
4229 node = nbhs[-1]
4226 else:
4230 else:
4227 node = nbhs[0]
4231 node = nbhs[0]
4228
4232
4229 if opts.get('preview'):
4233 if opts.get('preview'):
4230 # find nodes that are ancestors of p2 but not of p1
4234 # find nodes that are ancestors of p2 but not of p1
4231 p1 = repo.lookup('.')
4235 p1 = repo.lookup('.')
4232 p2 = repo.lookup(node)
4236 p2 = repo.lookup(node)
4233 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4237 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4234
4238
4235 displayer = cmdutil.show_changeset(ui, repo, opts)
4239 displayer = cmdutil.show_changeset(ui, repo, opts)
4236 for node in nodes:
4240 for node in nodes:
4237 displayer.show(repo[node])
4241 displayer.show(repo[node])
4238 displayer.close()
4242 displayer.close()
4239 return 0
4243 return 0
4240
4244
4241 try:
4245 try:
4242 # ui.forcemerge is an internal variable, do not document
4246 # ui.forcemerge is an internal variable, do not document
4243 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4247 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4244 return hg.merge(repo, node, force=opts.get('force'))
4248 return hg.merge(repo, node, force=opts.get('force'))
4245 finally:
4249 finally:
4246 ui.setconfig('ui', 'forcemerge', '')
4250 ui.setconfig('ui', 'forcemerge', '')
4247
4251
4248 @command('outgoing|out',
4252 @command('outgoing|out',
4249 [('f', 'force', None, _('run even when the destination is unrelated')),
4253 [('f', 'force', None, _('run even when the destination is unrelated')),
4250 ('r', 'rev', [],
4254 ('r', 'rev', [],
4251 _('a changeset intended to be included in the destination'), _('REV')),
4255 _('a changeset intended to be included in the destination'), _('REV')),
4252 ('n', 'newest-first', None, _('show newest record first')),
4256 ('n', 'newest-first', None, _('show newest record first')),
4253 ('B', 'bookmarks', False, _('compare bookmarks')),
4257 ('B', 'bookmarks', False, _('compare bookmarks')),
4254 ('b', 'branch', [], _('a specific branch you would like to push'),
4258 ('b', 'branch', [], _('a specific branch you would like to push'),
4255 _('BRANCH')),
4259 _('BRANCH')),
4256 ] + logopts + remoteopts + subrepoopts,
4260 ] + logopts + remoteopts + subrepoopts,
4257 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4261 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4258 def outgoing(ui, repo, dest=None, **opts):
4262 def outgoing(ui, repo, dest=None, **opts):
4259 """show changesets not found in the destination
4263 """show changesets not found in the destination
4260
4264
4261 Show changesets not found in the specified destination repository
4265 Show changesets not found in the specified destination repository
4262 or the default push location. These are the changesets that would
4266 or the default push location. These are the changesets that would
4263 be pushed if a push was requested.
4267 be pushed if a push was requested.
4264
4268
4265 See pull for details of valid destination formats.
4269 See pull for details of valid destination formats.
4266
4270
4267 Returns 0 if there are outgoing changes, 1 otherwise.
4271 Returns 0 if there are outgoing changes, 1 otherwise.
4268 """
4272 """
4269 if opts.get('graph'):
4273 if opts.get('graph'):
4270 cmdutil.checkunsupportedgraphflags([], opts)
4274 cmdutil.checkunsupportedgraphflags([], opts)
4271 o = hg._outgoing(ui, repo, dest, opts)
4275 o = hg._outgoing(ui, repo, dest, opts)
4272 if o is None:
4276 if o is None:
4273 return
4277 return
4274
4278
4275 revdag = cmdutil.graphrevs(repo, o, opts)
4279 revdag = cmdutil.graphrevs(repo, o, opts)
4276 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4280 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4277 showparents = [ctx.node() for ctx in repo[None].parents()]
4281 showparents = [ctx.node() for ctx in repo[None].parents()]
4278 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4282 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4279 graphmod.asciiedges)
4283 graphmod.asciiedges)
4280 return 0
4284 return 0
4281
4285
4282 if opts.get('bookmarks'):
4286 if opts.get('bookmarks'):
4283 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4287 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4284 dest, branches = hg.parseurl(dest, opts.get('branch'))
4288 dest, branches = hg.parseurl(dest, opts.get('branch'))
4285 other = hg.peer(repo, opts, dest)
4289 other = hg.peer(repo, opts, dest)
4286 if 'bookmarks' not in other.listkeys('namespaces'):
4290 if 'bookmarks' not in other.listkeys('namespaces'):
4287 ui.warn(_("remote doesn't support bookmarks\n"))
4291 ui.warn(_("remote doesn't support bookmarks\n"))
4288 return 0
4292 return 0
4289 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4293 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4290 return bookmarks.diff(ui, other, repo)
4294 return bookmarks.diff(ui, other, repo)
4291
4295
4292 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4296 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4293 try:
4297 try:
4294 return hg.outgoing(ui, repo, dest, opts)
4298 return hg.outgoing(ui, repo, dest, opts)
4295 finally:
4299 finally:
4296 del repo._subtoppath
4300 del repo._subtoppath
4297
4301
4298 @command('parents',
4302 @command('parents',
4299 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4303 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4300 ] + templateopts,
4304 ] + templateopts,
4301 _('[-r REV] [FILE]'))
4305 _('[-r REV] [FILE]'))
4302 def parents(ui, repo, file_=None, **opts):
4306 def parents(ui, repo, file_=None, **opts):
4303 """show the parents of the working directory or revision
4307 """show the parents of the working directory or revision
4304
4308
4305 Print the working directory's parent revisions. If a revision is
4309 Print the working directory's parent revisions. If a revision is
4306 given via -r/--rev, the parent of that revision will be printed.
4310 given via -r/--rev, the parent of that revision will be printed.
4307 If a file argument is given, the revision in which the file was
4311 If a file argument is given, the revision in which the file was
4308 last changed (before the working directory revision or the
4312 last changed (before the working directory revision or the
4309 argument to --rev if given) is printed.
4313 argument to --rev if given) is printed.
4310
4314
4311 Returns 0 on success.
4315 Returns 0 on success.
4312 """
4316 """
4313
4317
4314 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4318 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4315
4319
4316 if file_:
4320 if file_:
4317 m = scmutil.match(ctx, (file_,), opts)
4321 m = scmutil.match(ctx, (file_,), opts)
4318 if m.anypats() or len(m.files()) != 1:
4322 if m.anypats() or len(m.files()) != 1:
4319 raise util.Abort(_('can only specify an explicit filename'))
4323 raise util.Abort(_('can only specify an explicit filename'))
4320 file_ = m.files()[0]
4324 file_ = m.files()[0]
4321 filenodes = []
4325 filenodes = []
4322 for cp in ctx.parents():
4326 for cp in ctx.parents():
4323 if not cp:
4327 if not cp:
4324 continue
4328 continue
4325 try:
4329 try:
4326 filenodes.append(cp.filenode(file_))
4330 filenodes.append(cp.filenode(file_))
4327 except error.LookupError:
4331 except error.LookupError:
4328 pass
4332 pass
4329 if not filenodes:
4333 if not filenodes:
4330 raise util.Abort(_("'%s' not found in manifest!") % file_)
4334 raise util.Abort(_("'%s' not found in manifest!") % file_)
4331 fl = repo.file(file_)
4335 fl = repo.file(file_)
4332 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4336 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4333 else:
4337 else:
4334 p = [cp.node() for cp in ctx.parents()]
4338 p = [cp.node() for cp in ctx.parents()]
4335
4339
4336 displayer = cmdutil.show_changeset(ui, repo, opts)
4340 displayer = cmdutil.show_changeset(ui, repo, opts)
4337 for n in p:
4341 for n in p:
4338 if n != nullid:
4342 if n != nullid:
4339 displayer.show(repo[n])
4343 displayer.show(repo[n])
4340 displayer.close()
4344 displayer.close()
4341
4345
4342 @command('paths', [], _('[NAME]'))
4346 @command('paths', [], _('[NAME]'))
4343 def paths(ui, repo, search=None):
4347 def paths(ui, repo, search=None):
4344 """show aliases for remote repositories
4348 """show aliases for remote repositories
4345
4349
4346 Show definition of symbolic path name NAME. If no name is given,
4350 Show definition of symbolic path name NAME. If no name is given,
4347 show definition of all available names.
4351 show definition of all available names.
4348
4352
4349 Option -q/--quiet suppresses all output when searching for NAME
4353 Option -q/--quiet suppresses all output when searching for NAME
4350 and shows only the path names when listing all definitions.
4354 and shows only the path names when listing all definitions.
4351
4355
4352 Path names are defined in the [paths] section of your
4356 Path names are defined in the [paths] section of your
4353 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4357 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4354 repository, ``.hg/hgrc`` is used, too.
4358 repository, ``.hg/hgrc`` is used, too.
4355
4359
4356 The path names ``default`` and ``default-push`` have a special
4360 The path names ``default`` and ``default-push`` have a special
4357 meaning. When performing a push or pull operation, they are used
4361 meaning. When performing a push or pull operation, they are used
4358 as fallbacks if no location is specified on the command-line.
4362 as fallbacks if no location is specified on the command-line.
4359 When ``default-push`` is set, it will be used for push and
4363 When ``default-push`` is set, it will be used for push and
4360 ``default`` will be used for pull; otherwise ``default`` is used
4364 ``default`` will be used for pull; otherwise ``default`` is used
4361 as the fallback for both. When cloning a repository, the clone
4365 as the fallback for both. When cloning a repository, the clone
4362 source is written as ``default`` in ``.hg/hgrc``. Note that
4366 source is written as ``default`` in ``.hg/hgrc``. Note that
4363 ``default`` and ``default-push`` apply to all inbound (e.g.
4367 ``default`` and ``default-push`` apply to all inbound (e.g.
4364 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4368 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4365 :hg:`bundle`) operations.
4369 :hg:`bundle`) operations.
4366
4370
4367 See :hg:`help urls` for more information.
4371 See :hg:`help urls` for more information.
4368
4372
4369 Returns 0 on success.
4373 Returns 0 on success.
4370 """
4374 """
4371 if search:
4375 if search:
4372 for name, path in ui.configitems("paths"):
4376 for name, path in ui.configitems("paths"):
4373 if name == search:
4377 if name == search:
4374 ui.status("%s\n" % util.hidepassword(path))
4378 ui.status("%s\n" % util.hidepassword(path))
4375 return
4379 return
4376 if not ui.quiet:
4380 if not ui.quiet:
4377 ui.warn(_("not found!\n"))
4381 ui.warn(_("not found!\n"))
4378 return 1
4382 return 1
4379 else:
4383 else:
4380 for name, path in ui.configitems("paths"):
4384 for name, path in ui.configitems("paths"):
4381 if ui.quiet:
4385 if ui.quiet:
4382 ui.write("%s\n" % name)
4386 ui.write("%s\n" % name)
4383 else:
4387 else:
4384 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4388 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4385
4389
4386 @command('phase',
4390 @command('phase',
4387 [('p', 'public', False, _('set changeset phase to public')),
4391 [('p', 'public', False, _('set changeset phase to public')),
4388 ('d', 'draft', False, _('set changeset phase to draft')),
4392 ('d', 'draft', False, _('set changeset phase to draft')),
4389 ('s', 'secret', False, _('set changeset phase to secret')),
4393 ('s', 'secret', False, _('set changeset phase to secret')),
4390 ('f', 'force', False, _('allow to move boundary backward')),
4394 ('f', 'force', False, _('allow to move boundary backward')),
4391 ('r', 'rev', [], _('target revision'), _('REV')),
4395 ('r', 'rev', [], _('target revision'), _('REV')),
4392 ],
4396 ],
4393 _('[-p|-d|-s] [-f] [-r] REV...'))
4397 _('[-p|-d|-s] [-f] [-r] REV...'))
4394 def phase(ui, repo, *revs, **opts):
4398 def phase(ui, repo, *revs, **opts):
4395 """set or show the current phase name
4399 """set or show the current phase name
4396
4400
4397 With no argument, show the phase name of specified revisions.
4401 With no argument, show the phase name of specified revisions.
4398
4402
4399 With one of -p/--public, -d/--draft or -s/--secret, change the
4403 With one of -p/--public, -d/--draft or -s/--secret, change the
4400 phase value of the specified revisions.
4404 phase value of the specified revisions.
4401
4405
4402 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4406 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4403 lower phase to an higher phase. Phases are ordered as follows::
4407 lower phase to an higher phase. Phases are ordered as follows::
4404
4408
4405 public < draft < secret
4409 public < draft < secret
4406
4410
4407 Return 0 on success, 1 if no phases were changed or some could not
4411 Return 0 on success, 1 if no phases were changed or some could not
4408 be changed.
4412 be changed.
4409 """
4413 """
4410 # search for a unique phase argument
4414 # search for a unique phase argument
4411 targetphase = None
4415 targetphase = None
4412 for idx, name in enumerate(phases.phasenames):
4416 for idx, name in enumerate(phases.phasenames):
4413 if opts[name]:
4417 if opts[name]:
4414 if targetphase is not None:
4418 if targetphase is not None:
4415 raise util.Abort(_('only one phase can be specified'))
4419 raise util.Abort(_('only one phase can be specified'))
4416 targetphase = idx
4420 targetphase = idx
4417
4421
4418 # look for specified revision
4422 # look for specified revision
4419 revs = list(revs)
4423 revs = list(revs)
4420 revs.extend(opts['rev'])
4424 revs.extend(opts['rev'])
4421 if not revs:
4425 if not revs:
4422 raise util.Abort(_('no revisions specified'))
4426 raise util.Abort(_('no revisions specified'))
4423
4427
4424 revs = scmutil.revrange(repo, revs)
4428 revs = scmutil.revrange(repo, revs)
4425
4429
4426 lock = None
4430 lock = None
4427 ret = 0
4431 ret = 0
4428 if targetphase is None:
4432 if targetphase is None:
4429 # display
4433 # display
4430 for r in revs:
4434 for r in revs:
4431 ctx = repo[r]
4435 ctx = repo[r]
4432 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4436 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4433 else:
4437 else:
4434 lock = repo.lock()
4438 lock = repo.lock()
4435 try:
4439 try:
4436 # set phase
4440 # set phase
4437 if not revs:
4441 if not revs:
4438 raise util.Abort(_('empty revision set'))
4442 raise util.Abort(_('empty revision set'))
4439 nodes = [repo[r].node() for r in revs]
4443 nodes = [repo[r].node() for r in revs]
4440 olddata = repo._phasecache.getphaserevs(repo)[:]
4444 olddata = repo._phasecache.getphaserevs(repo)[:]
4441 phases.advanceboundary(repo, targetphase, nodes)
4445 phases.advanceboundary(repo, targetphase, nodes)
4442 if opts['force']:
4446 if opts['force']:
4443 phases.retractboundary(repo, targetphase, nodes)
4447 phases.retractboundary(repo, targetphase, nodes)
4444 finally:
4448 finally:
4445 lock.release()
4449 lock.release()
4446 # moving revision from public to draft may hide them
4450 # moving revision from public to draft may hide them
4447 # We have to check result on an unfiltered repository
4451 # We have to check result on an unfiltered repository
4448 unfi = repo.unfiltered()
4452 unfi = repo.unfiltered()
4449 newdata = repo._phasecache.getphaserevs(unfi)
4453 newdata = repo._phasecache.getphaserevs(unfi)
4450 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4454 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4451 cl = unfi.changelog
4455 cl = unfi.changelog
4452 rejected = [n for n in nodes
4456 rejected = [n for n in nodes
4453 if newdata[cl.rev(n)] < targetphase]
4457 if newdata[cl.rev(n)] < targetphase]
4454 if rejected:
4458 if rejected:
4455 ui.warn(_('cannot move %i changesets to a more permissive '
4459 ui.warn(_('cannot move %i changesets to a more permissive '
4456 'phase, use --force\n') % len(rejected))
4460 'phase, use --force\n') % len(rejected))
4457 ret = 1
4461 ret = 1
4458 if changes:
4462 if changes:
4459 msg = _('phase changed for %i changesets\n') % changes
4463 msg = _('phase changed for %i changesets\n') % changes
4460 if ret:
4464 if ret:
4461 ui.status(msg)
4465 ui.status(msg)
4462 else:
4466 else:
4463 ui.note(msg)
4467 ui.note(msg)
4464 else:
4468 else:
4465 ui.warn(_('no phases changed\n'))
4469 ui.warn(_('no phases changed\n'))
4466 ret = 1
4470 ret = 1
4467 return ret
4471 return ret
4468
4472
4469 def postincoming(ui, repo, modheads, optupdate, checkout):
4473 def postincoming(ui, repo, modheads, optupdate, checkout):
4470 if modheads == 0:
4474 if modheads == 0:
4471 return
4475 return
4472 if optupdate:
4476 if optupdate:
4473 movemarkfrom = repo['.'].node()
4477 movemarkfrom = repo['.'].node()
4474 try:
4478 try:
4475 ret = hg.update(repo, checkout)
4479 ret = hg.update(repo, checkout)
4476 except util.Abort, inst:
4480 except util.Abort, inst:
4477 ui.warn(_("not updating: %s\n") % str(inst))
4481 ui.warn(_("not updating: %s\n") % str(inst))
4478 return 0
4482 return 0
4479 if not ret and not checkout:
4483 if not ret and not checkout:
4480 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4484 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4481 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4485 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4482 return ret
4486 return ret
4483 if modheads > 1:
4487 if modheads > 1:
4484 currentbranchheads = len(repo.branchheads())
4488 currentbranchheads = len(repo.branchheads())
4485 if currentbranchheads == modheads:
4489 if currentbranchheads == modheads:
4486 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4490 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4487 elif currentbranchheads > 1:
4491 elif currentbranchheads > 1:
4488 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4492 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4489 "merge)\n"))
4493 "merge)\n"))
4490 else:
4494 else:
4491 ui.status(_("(run 'hg heads' to see heads)\n"))
4495 ui.status(_("(run 'hg heads' to see heads)\n"))
4492 else:
4496 else:
4493 ui.status(_("(run 'hg update' to get a working copy)\n"))
4497 ui.status(_("(run 'hg update' to get a working copy)\n"))
4494
4498
4495 @command('^pull',
4499 @command('^pull',
4496 [('u', 'update', None,
4500 [('u', 'update', None,
4497 _('update to new branch head if changesets were pulled')),
4501 _('update to new branch head if changesets were pulled')),
4498 ('f', 'force', None, _('run even when remote repository is unrelated')),
4502 ('f', 'force', None, _('run even when remote repository is unrelated')),
4499 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4503 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4500 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4504 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4501 ('b', 'branch', [], _('a specific branch you would like to pull'),
4505 ('b', 'branch', [], _('a specific branch you would like to pull'),
4502 _('BRANCH')),
4506 _('BRANCH')),
4503 ] + remoteopts,
4507 ] + remoteopts,
4504 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4508 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4505 def pull(ui, repo, source="default", **opts):
4509 def pull(ui, repo, source="default", **opts):
4506 """pull changes from the specified source
4510 """pull changes from the specified source
4507
4511
4508 Pull changes from a remote repository to a local one.
4512 Pull changes from a remote repository to a local one.
4509
4513
4510 This finds all changes from the repository at the specified path
4514 This finds all changes from the repository at the specified path
4511 or URL and adds them to a local repository (the current one unless
4515 or URL and adds them to a local repository (the current one unless
4512 -R is specified). By default, this does not update the copy of the
4516 -R is specified). By default, this does not update the copy of the
4513 project in the working directory.
4517 project in the working directory.
4514
4518
4515 Use :hg:`incoming` if you want to see what would have been added
4519 Use :hg:`incoming` if you want to see what would have been added
4516 by a pull at the time you issued this command. If you then decide
4520 by a pull at the time you issued this command. If you then decide
4517 to add those changes to the repository, you should use :hg:`pull
4521 to add those changes to the repository, you should use :hg:`pull
4518 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4522 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4519
4523
4520 If SOURCE is omitted, the 'default' path will be used.
4524 If SOURCE is omitted, the 'default' path will be used.
4521 See :hg:`help urls` for more information.
4525 See :hg:`help urls` for more information.
4522
4526
4523 Returns 0 on success, 1 if an update had unresolved files.
4527 Returns 0 on success, 1 if an update had unresolved files.
4524 """
4528 """
4525 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4529 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4526 other = hg.peer(repo, opts, source)
4530 other = hg.peer(repo, opts, source)
4527 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4531 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4528 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4532 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4529
4533
4530 remotebookmarks = other.listkeys('bookmarks')
4534 remotebookmarks = other.listkeys('bookmarks')
4531
4535
4532 if opts.get('bookmark'):
4536 if opts.get('bookmark'):
4533 if not revs:
4537 if not revs:
4534 revs = []
4538 revs = []
4535 for b in opts['bookmark']:
4539 for b in opts['bookmark']:
4536 if b not in remotebookmarks:
4540 if b not in remotebookmarks:
4537 raise util.Abort(_('remote bookmark %s not found!') % b)
4541 raise util.Abort(_('remote bookmark %s not found!') % b)
4538 revs.append(remotebookmarks[b])
4542 revs.append(remotebookmarks[b])
4539
4543
4540 if revs:
4544 if revs:
4541 try:
4545 try:
4542 revs = [other.lookup(rev) for rev in revs]
4546 revs = [other.lookup(rev) for rev in revs]
4543 except error.CapabilityError:
4547 except error.CapabilityError:
4544 err = _("other repository doesn't support revision lookup, "
4548 err = _("other repository doesn't support revision lookup, "
4545 "so a rev cannot be specified.")
4549 "so a rev cannot be specified.")
4546 raise util.Abort(err)
4550 raise util.Abort(err)
4547
4551
4548 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4552 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4549 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4553 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4550 if checkout:
4554 if checkout:
4551 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4555 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4552 repo._subtoppath = source
4556 repo._subtoppath = source
4553 try:
4557 try:
4554 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4558 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4555
4559
4556 finally:
4560 finally:
4557 del repo._subtoppath
4561 del repo._subtoppath
4558
4562
4559 # update specified bookmarks
4563 # update specified bookmarks
4560 if opts.get('bookmark'):
4564 if opts.get('bookmark'):
4561 marks = repo._bookmarks
4565 marks = repo._bookmarks
4562 for b in opts['bookmark']:
4566 for b in opts['bookmark']:
4563 # explicit pull overrides local bookmark if any
4567 # explicit pull overrides local bookmark if any
4564 ui.status(_("importing bookmark %s\n") % b)
4568 ui.status(_("importing bookmark %s\n") % b)
4565 marks[b] = repo[remotebookmarks[b]].node()
4569 marks[b] = repo[remotebookmarks[b]].node()
4566 marks.write()
4570 marks.write()
4567
4571
4568 return ret
4572 return ret
4569
4573
4570 @command('^push',
4574 @command('^push',
4571 [('f', 'force', None, _('force push')),
4575 [('f', 'force', None, _('force push')),
4572 ('r', 'rev', [],
4576 ('r', 'rev', [],
4573 _('a changeset intended to be included in the destination'),
4577 _('a changeset intended to be included in the destination'),
4574 _('REV')),
4578 _('REV')),
4575 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4579 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4576 ('b', 'branch', [],
4580 ('b', 'branch', [],
4577 _('a specific branch you would like to push'), _('BRANCH')),
4581 _('a specific branch you would like to push'), _('BRANCH')),
4578 ('', 'new-branch', False, _('allow pushing a new branch')),
4582 ('', 'new-branch', False, _('allow pushing a new branch')),
4579 ] + remoteopts,
4583 ] + remoteopts,
4580 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4584 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4581 def push(ui, repo, dest=None, **opts):
4585 def push(ui, repo, dest=None, **opts):
4582 """push changes to the specified destination
4586 """push changes to the specified destination
4583
4587
4584 Push changesets from the local repository to the specified
4588 Push changesets from the local repository to the specified
4585 destination.
4589 destination.
4586
4590
4587 This operation is symmetrical to pull: it is identical to a pull
4591 This operation is symmetrical to pull: it is identical to a pull
4588 in the destination repository from the current one.
4592 in the destination repository from the current one.
4589
4593
4590 By default, push will not allow creation of new heads at the
4594 By default, push will not allow creation of new heads at the
4591 destination, since multiple heads would make it unclear which head
4595 destination, since multiple heads would make it unclear which head
4592 to use. In this situation, it is recommended to pull and merge
4596 to use. In this situation, it is recommended to pull and merge
4593 before pushing.
4597 before pushing.
4594
4598
4595 Use --new-branch if you want to allow push to create a new named
4599 Use --new-branch if you want to allow push to create a new named
4596 branch that is not present at the destination. This allows you to
4600 branch that is not present at the destination. This allows you to
4597 only create a new branch without forcing other changes.
4601 only create a new branch without forcing other changes.
4598
4602
4599 Use -f/--force to override the default behavior and push all
4603 Use -f/--force to override the default behavior and push all
4600 changesets on all branches.
4604 changesets on all branches.
4601
4605
4602 If -r/--rev is used, the specified revision and all its ancestors
4606 If -r/--rev is used, the specified revision and all its ancestors
4603 will be pushed to the remote repository.
4607 will be pushed to the remote repository.
4604
4608
4605 If -B/--bookmark is used, the specified bookmarked revision, its
4609 If -B/--bookmark is used, the specified bookmarked revision, its
4606 ancestors, and the bookmark will be pushed to the remote
4610 ancestors, and the bookmark will be pushed to the remote
4607 repository.
4611 repository.
4608
4612
4609 Please see :hg:`help urls` for important details about ``ssh://``
4613 Please see :hg:`help urls` for important details about ``ssh://``
4610 URLs. If DESTINATION is omitted, a default path will be used.
4614 URLs. If DESTINATION is omitted, a default path will be used.
4611
4615
4612 Returns 0 if push was successful, 1 if nothing to push.
4616 Returns 0 if push was successful, 1 if nothing to push.
4613 """
4617 """
4614
4618
4615 if opts.get('bookmark'):
4619 if opts.get('bookmark'):
4616 for b in opts['bookmark']:
4620 for b in opts['bookmark']:
4617 # translate -B options to -r so changesets get pushed
4621 # translate -B options to -r so changesets get pushed
4618 if b in repo._bookmarks:
4622 if b in repo._bookmarks:
4619 opts.setdefault('rev', []).append(b)
4623 opts.setdefault('rev', []).append(b)
4620 else:
4624 else:
4621 # if we try to push a deleted bookmark, translate it to null
4625 # if we try to push a deleted bookmark, translate it to null
4622 # this lets simultaneous -r, -b options continue working
4626 # this lets simultaneous -r, -b options continue working
4623 opts.setdefault('rev', []).append("null")
4627 opts.setdefault('rev', []).append("null")
4624
4628
4625 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4629 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4626 dest, branches = hg.parseurl(dest, opts.get('branch'))
4630 dest, branches = hg.parseurl(dest, opts.get('branch'))
4627 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4631 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4628 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4632 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4629 other = hg.peer(repo, opts, dest)
4633 other = hg.peer(repo, opts, dest)
4630 if revs:
4634 if revs:
4631 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4635 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4632
4636
4633 repo._subtoppath = dest
4637 repo._subtoppath = dest
4634 try:
4638 try:
4635 # push subrepos depth-first for coherent ordering
4639 # push subrepos depth-first for coherent ordering
4636 c = repo['']
4640 c = repo['']
4637 subs = c.substate # only repos that are committed
4641 subs = c.substate # only repos that are committed
4638 for s in sorted(subs):
4642 for s in sorted(subs):
4639 if c.sub(s).push(opts) == 0:
4643 if c.sub(s).push(opts) == 0:
4640 return False
4644 return False
4641 finally:
4645 finally:
4642 del repo._subtoppath
4646 del repo._subtoppath
4643 result = repo.push(other, opts.get('force'), revs=revs,
4647 result = repo.push(other, opts.get('force'), revs=revs,
4644 newbranch=opts.get('new_branch'))
4648 newbranch=opts.get('new_branch'))
4645
4649
4646 result = not result
4650 result = not result
4647
4651
4648 if opts.get('bookmark'):
4652 if opts.get('bookmark'):
4649 rb = other.listkeys('bookmarks')
4653 rb = other.listkeys('bookmarks')
4650 for b in opts['bookmark']:
4654 for b in opts['bookmark']:
4651 # explicit push overrides remote bookmark if any
4655 # explicit push overrides remote bookmark if any
4652 if b in repo._bookmarks:
4656 if b in repo._bookmarks:
4653 ui.status(_("exporting bookmark %s\n") % b)
4657 ui.status(_("exporting bookmark %s\n") % b)
4654 new = repo[b].hex()
4658 new = repo[b].hex()
4655 elif b in rb:
4659 elif b in rb:
4656 ui.status(_("deleting remote bookmark %s\n") % b)
4660 ui.status(_("deleting remote bookmark %s\n") % b)
4657 new = '' # delete
4661 new = '' # delete
4658 else:
4662 else:
4659 ui.warn(_('bookmark %s does not exist on the local '
4663 ui.warn(_('bookmark %s does not exist on the local '
4660 'or remote repository!\n') % b)
4664 'or remote repository!\n') % b)
4661 return 2
4665 return 2
4662 old = rb.get(b, '')
4666 old = rb.get(b, '')
4663 r = other.pushkey('bookmarks', b, old, new)
4667 r = other.pushkey('bookmarks', b, old, new)
4664 if not r:
4668 if not r:
4665 ui.warn(_('updating bookmark %s failed!\n') % b)
4669 ui.warn(_('updating bookmark %s failed!\n') % b)
4666 if not result:
4670 if not result:
4667 result = 2
4671 result = 2
4668
4672
4669 return result
4673 return result
4670
4674
4671 @command('recover', [])
4675 @command('recover', [])
4672 def recover(ui, repo):
4676 def recover(ui, repo):
4673 """roll back an interrupted transaction
4677 """roll back an interrupted transaction
4674
4678
4675 Recover from an interrupted commit or pull.
4679 Recover from an interrupted commit or pull.
4676
4680
4677 This command tries to fix the repository status after an
4681 This command tries to fix the repository status after an
4678 interrupted operation. It should only be necessary when Mercurial
4682 interrupted operation. It should only be necessary when Mercurial
4679 suggests it.
4683 suggests it.
4680
4684
4681 Returns 0 if successful, 1 if nothing to recover or verify fails.
4685 Returns 0 if successful, 1 if nothing to recover or verify fails.
4682 """
4686 """
4683 if repo.recover():
4687 if repo.recover():
4684 return hg.verify(repo)
4688 return hg.verify(repo)
4685 return 1
4689 return 1
4686
4690
4687 @command('^remove|rm',
4691 @command('^remove|rm',
4688 [('A', 'after', None, _('record delete for missing files')),
4692 [('A', 'after', None, _('record delete for missing files')),
4689 ('f', 'force', None,
4693 ('f', 'force', None,
4690 _('remove (and delete) file even if added or modified')),
4694 _('remove (and delete) file even if added or modified')),
4691 ] + walkopts,
4695 ] + walkopts,
4692 _('[OPTION]... FILE...'))
4696 _('[OPTION]... FILE...'))
4693 def remove(ui, repo, *pats, **opts):
4697 def remove(ui, repo, *pats, **opts):
4694 """remove the specified files on the next commit
4698 """remove the specified files on the next commit
4695
4699
4696 Schedule the indicated files for removal from the current branch.
4700 Schedule the indicated files for removal from the current branch.
4697
4701
4698 This command schedules the files to be removed at the next commit.
4702 This command schedules the files to be removed at the next commit.
4699 To undo a remove before that, see :hg:`revert`. To undo added
4703 To undo a remove before that, see :hg:`revert`. To undo added
4700 files, see :hg:`forget`.
4704 files, see :hg:`forget`.
4701
4705
4702 .. container:: verbose
4706 .. container:: verbose
4703
4707
4704 -A/--after can be used to remove only files that have already
4708 -A/--after can be used to remove only files that have already
4705 been deleted, -f/--force can be used to force deletion, and -Af
4709 been deleted, -f/--force can be used to force deletion, and -Af
4706 can be used to remove files from the next revision without
4710 can be used to remove files from the next revision without
4707 deleting them from the working directory.
4711 deleting them from the working directory.
4708
4712
4709 The following table details the behavior of remove for different
4713 The following table details the behavior of remove for different
4710 file states (columns) and option combinations (rows). The file
4714 file states (columns) and option combinations (rows). The file
4711 states are Added [A], Clean [C], Modified [M] and Missing [!]
4715 states are Added [A], Clean [C], Modified [M] and Missing [!]
4712 (as reported by :hg:`status`). The actions are Warn, Remove
4716 (as reported by :hg:`status`). The actions are Warn, Remove
4713 (from branch) and Delete (from disk):
4717 (from branch) and Delete (from disk):
4714
4718
4715 ======= == == == ==
4719 ======= == == == ==
4716 A C M !
4720 A C M !
4717 ======= == == == ==
4721 ======= == == == ==
4718 none W RD W R
4722 none W RD W R
4719 -f R RD RD R
4723 -f R RD RD R
4720 -A W W W R
4724 -A W W W R
4721 -Af R R R R
4725 -Af R R R R
4722 ======= == == == ==
4726 ======= == == == ==
4723
4727
4724 Note that remove never deletes files in Added [A] state from the
4728 Note that remove never deletes files in Added [A] state from the
4725 working directory, not even if option --force is specified.
4729 working directory, not even if option --force is specified.
4726
4730
4727 Returns 0 on success, 1 if any warnings encountered.
4731 Returns 0 on success, 1 if any warnings encountered.
4728 """
4732 """
4729
4733
4730 ret = 0
4734 ret = 0
4731 after, force = opts.get('after'), opts.get('force')
4735 after, force = opts.get('after'), opts.get('force')
4732 if not pats and not after:
4736 if not pats and not after:
4733 raise util.Abort(_('no files specified'))
4737 raise util.Abort(_('no files specified'))
4734
4738
4735 m = scmutil.match(repo[None], pats, opts)
4739 m = scmutil.match(repo[None], pats, opts)
4736 s = repo.status(match=m, clean=True)
4740 s = repo.status(match=m, clean=True)
4737 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4741 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4738
4742
4739 # warn about failure to delete explicit files/dirs
4743 # warn about failure to delete explicit files/dirs
4740 wctx = repo[None]
4744 wctx = repo[None]
4741 for f in m.files():
4745 for f in m.files():
4742 if f in repo.dirstate or f in wctx.dirs():
4746 if f in repo.dirstate or f in wctx.dirs():
4743 continue
4747 continue
4744 if os.path.exists(m.rel(f)):
4748 if os.path.exists(m.rel(f)):
4745 if os.path.isdir(m.rel(f)):
4749 if os.path.isdir(m.rel(f)):
4746 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4750 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4747 else:
4751 else:
4748 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4752 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4749 # missing files will generate a warning elsewhere
4753 # missing files will generate a warning elsewhere
4750 ret = 1
4754 ret = 1
4751
4755
4752 if force:
4756 if force:
4753 list = modified + deleted + clean + added
4757 list = modified + deleted + clean + added
4754 elif after:
4758 elif after:
4755 list = deleted
4759 list = deleted
4756 for f in modified + added + clean:
4760 for f in modified + added + clean:
4757 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4761 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4758 ret = 1
4762 ret = 1
4759 else:
4763 else:
4760 list = deleted + clean
4764 list = deleted + clean
4761 for f in modified:
4765 for f in modified:
4762 ui.warn(_('not removing %s: file is modified (use -f'
4766 ui.warn(_('not removing %s: file is modified (use -f'
4763 ' to force removal)\n') % m.rel(f))
4767 ' to force removal)\n') % m.rel(f))
4764 ret = 1
4768 ret = 1
4765 for f in added:
4769 for f in added:
4766 ui.warn(_('not removing %s: file has been marked for add'
4770 ui.warn(_('not removing %s: file has been marked for add'
4767 ' (use forget to undo)\n') % m.rel(f))
4771 ' (use forget to undo)\n') % m.rel(f))
4768 ret = 1
4772 ret = 1
4769
4773
4770 for f in sorted(list):
4774 for f in sorted(list):
4771 if ui.verbose or not m.exact(f):
4775 if ui.verbose or not m.exact(f):
4772 ui.status(_('removing %s\n') % m.rel(f))
4776 ui.status(_('removing %s\n') % m.rel(f))
4773
4777
4774 wlock = repo.wlock()
4778 wlock = repo.wlock()
4775 try:
4779 try:
4776 if not after:
4780 if not after:
4777 for f in list:
4781 for f in list:
4778 if f in added:
4782 if f in added:
4779 continue # we never unlink added files on remove
4783 continue # we never unlink added files on remove
4780 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4784 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4781 repo[None].forget(list)
4785 repo[None].forget(list)
4782 finally:
4786 finally:
4783 wlock.release()
4787 wlock.release()
4784
4788
4785 return ret
4789 return ret
4786
4790
4787 @command('rename|move|mv',
4791 @command('rename|move|mv',
4788 [('A', 'after', None, _('record a rename that has already occurred')),
4792 [('A', 'after', None, _('record a rename that has already occurred')),
4789 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4793 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4790 ] + walkopts + dryrunopts,
4794 ] + walkopts + dryrunopts,
4791 _('[OPTION]... SOURCE... DEST'))
4795 _('[OPTION]... SOURCE... DEST'))
4792 def rename(ui, repo, *pats, **opts):
4796 def rename(ui, repo, *pats, **opts):
4793 """rename files; equivalent of copy + remove
4797 """rename files; equivalent of copy + remove
4794
4798
4795 Mark dest as copies of sources; mark sources for deletion. If dest
4799 Mark dest as copies of sources; mark sources for deletion. If dest
4796 is a directory, copies are put in that directory. If dest is a
4800 is a directory, copies are put in that directory. If dest is a
4797 file, there can only be one source.
4801 file, there can only be one source.
4798
4802
4799 By default, this command copies the contents of files as they
4803 By default, this command copies the contents of files as they
4800 exist in the working directory. If invoked with -A/--after, the
4804 exist in the working directory. If invoked with -A/--after, the
4801 operation is recorded, but no copying is performed.
4805 operation is recorded, but no copying is performed.
4802
4806
4803 This command takes effect at the next commit. To undo a rename
4807 This command takes effect at the next commit. To undo a rename
4804 before that, see :hg:`revert`.
4808 before that, see :hg:`revert`.
4805
4809
4806 Returns 0 on success, 1 if errors are encountered.
4810 Returns 0 on success, 1 if errors are encountered.
4807 """
4811 """
4808 wlock = repo.wlock(False)
4812 wlock = repo.wlock(False)
4809 try:
4813 try:
4810 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4814 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4811 finally:
4815 finally:
4812 wlock.release()
4816 wlock.release()
4813
4817
4814 @command('resolve',
4818 @command('resolve',
4815 [('a', 'all', None, _('select all unresolved files')),
4819 [('a', 'all', None, _('select all unresolved files')),
4816 ('l', 'list', None, _('list state of files needing merge')),
4820 ('l', 'list', None, _('list state of files needing merge')),
4817 ('m', 'mark', None, _('mark files as resolved')),
4821 ('m', 'mark', None, _('mark files as resolved')),
4818 ('u', 'unmark', None, _('mark files as unresolved')),
4822 ('u', 'unmark', None, _('mark files as unresolved')),
4819 ('n', 'no-status', None, _('hide status prefix'))]
4823 ('n', 'no-status', None, _('hide status prefix'))]
4820 + mergetoolopts + walkopts,
4824 + mergetoolopts + walkopts,
4821 _('[OPTION]... [FILE]...'))
4825 _('[OPTION]... [FILE]...'))
4822 def resolve(ui, repo, *pats, **opts):
4826 def resolve(ui, repo, *pats, **opts):
4823 """redo merges or set/view the merge status of files
4827 """redo merges or set/view the merge status of files
4824
4828
4825 Merges with unresolved conflicts are often the result of
4829 Merges with unresolved conflicts are often the result of
4826 non-interactive merging using the ``internal:merge`` configuration
4830 non-interactive merging using the ``internal:merge`` configuration
4827 setting, or a command-line merge tool like ``diff3``. The resolve
4831 setting, or a command-line merge tool like ``diff3``. The resolve
4828 command is used to manage the files involved in a merge, after
4832 command is used to manage the files involved in a merge, after
4829 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4833 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4830 working directory must have two parents). See :hg:`help
4834 working directory must have two parents). See :hg:`help
4831 merge-tools` for information on configuring merge tools.
4835 merge-tools` for information on configuring merge tools.
4832
4836
4833 The resolve command can be used in the following ways:
4837 The resolve command can be used in the following ways:
4834
4838
4835 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4839 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4836 files, discarding any previous merge attempts. Re-merging is not
4840 files, discarding any previous merge attempts. Re-merging is not
4837 performed for files already marked as resolved. Use ``--all/-a``
4841 performed for files already marked as resolved. Use ``--all/-a``
4838 to select all unresolved files. ``--tool`` can be used to specify
4842 to select all unresolved files. ``--tool`` can be used to specify
4839 the merge tool used for the given files. It overrides the HGMERGE
4843 the merge tool used for the given files. It overrides the HGMERGE
4840 environment variable and your configuration files. Previous file
4844 environment variable and your configuration files. Previous file
4841 contents are saved with a ``.orig`` suffix.
4845 contents are saved with a ``.orig`` suffix.
4842
4846
4843 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4847 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4844 (e.g. after having manually fixed-up the files). The default is
4848 (e.g. after having manually fixed-up the files). The default is
4845 to mark all unresolved files.
4849 to mark all unresolved files.
4846
4850
4847 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4851 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4848 default is to mark all resolved files.
4852 default is to mark all resolved files.
4849
4853
4850 - :hg:`resolve -l`: list files which had or still have conflicts.
4854 - :hg:`resolve -l`: list files which had or still have conflicts.
4851 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4855 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4852
4856
4853 Note that Mercurial will not let you commit files with unresolved
4857 Note that Mercurial will not let you commit files with unresolved
4854 merge conflicts. You must use :hg:`resolve -m ...` before you can
4858 merge conflicts. You must use :hg:`resolve -m ...` before you can
4855 commit after a conflicting merge.
4859 commit after a conflicting merge.
4856
4860
4857 Returns 0 on success, 1 if any files fail a resolve attempt.
4861 Returns 0 on success, 1 if any files fail a resolve attempt.
4858 """
4862 """
4859
4863
4860 all, mark, unmark, show, nostatus = \
4864 all, mark, unmark, show, nostatus = \
4861 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4865 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4862
4866
4863 if (show and (mark or unmark)) or (mark and unmark):
4867 if (show and (mark or unmark)) or (mark and unmark):
4864 raise util.Abort(_("too many options specified"))
4868 raise util.Abort(_("too many options specified"))
4865 if pats and all:
4869 if pats and all:
4866 raise util.Abort(_("can't specify --all and patterns"))
4870 raise util.Abort(_("can't specify --all and patterns"))
4867 if not (all or pats or show or mark or unmark):
4871 if not (all or pats or show or mark or unmark):
4868 raise util.Abort(_('no files or directories specified; '
4872 raise util.Abort(_('no files or directories specified; '
4869 'use --all to remerge all files'))
4873 'use --all to remerge all files'))
4870
4874
4871 ms = mergemod.mergestate(repo)
4875 ms = mergemod.mergestate(repo)
4872 m = scmutil.match(repo[None], pats, opts)
4876 m = scmutil.match(repo[None], pats, opts)
4873 ret = 0
4877 ret = 0
4874
4878
4875 for f in ms:
4879 for f in ms:
4876 if m(f):
4880 if m(f):
4877 if show:
4881 if show:
4878 if nostatus:
4882 if nostatus:
4879 ui.write("%s\n" % f)
4883 ui.write("%s\n" % f)
4880 else:
4884 else:
4881 ui.write("%s %s\n" % (ms[f].upper(), f),
4885 ui.write("%s %s\n" % (ms[f].upper(), f),
4882 label='resolve.' +
4886 label='resolve.' +
4883 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4887 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4884 elif mark:
4888 elif mark:
4885 ms.mark(f, "r")
4889 ms.mark(f, "r")
4886 elif unmark:
4890 elif unmark:
4887 ms.mark(f, "u")
4891 ms.mark(f, "u")
4888 else:
4892 else:
4889 wctx = repo[None]
4893 wctx = repo[None]
4890 mctx = wctx.parents()[-1]
4894 mctx = wctx.parents()[-1]
4891
4895
4892 # backup pre-resolve (merge uses .orig for its own purposes)
4896 # backup pre-resolve (merge uses .orig for its own purposes)
4893 a = repo.wjoin(f)
4897 a = repo.wjoin(f)
4894 util.copyfile(a, a + ".resolve")
4898 util.copyfile(a, a + ".resolve")
4895
4899
4896 try:
4900 try:
4897 # resolve file
4901 # resolve file
4898 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4902 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4899 if ms.resolve(f, wctx, mctx):
4903 if ms.resolve(f, wctx, mctx):
4900 ret = 1
4904 ret = 1
4901 finally:
4905 finally:
4902 ui.setconfig('ui', 'forcemerge', '')
4906 ui.setconfig('ui', 'forcemerge', '')
4903 ms.commit()
4907 ms.commit()
4904
4908
4905 # replace filemerge's .orig file with our resolve file
4909 # replace filemerge's .orig file with our resolve file
4906 util.rename(a + ".resolve", a + ".orig")
4910 util.rename(a + ".resolve", a + ".orig")
4907
4911
4908 ms.commit()
4912 ms.commit()
4909 return ret
4913 return ret
4910
4914
4911 @command('revert',
4915 @command('revert',
4912 [('a', 'all', None, _('revert all changes when no arguments given')),
4916 [('a', 'all', None, _('revert all changes when no arguments given')),
4913 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4917 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4914 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4918 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4915 ('C', 'no-backup', None, _('do not save backup copies of files')),
4919 ('C', 'no-backup', None, _('do not save backup copies of files')),
4916 ] + walkopts + dryrunopts,
4920 ] + walkopts + dryrunopts,
4917 _('[OPTION]... [-r REV] [NAME]...'))
4921 _('[OPTION]... [-r REV] [NAME]...'))
4918 def revert(ui, repo, *pats, **opts):
4922 def revert(ui, repo, *pats, **opts):
4919 """restore files to their checkout state
4923 """restore files to their checkout state
4920
4924
4921 .. note::
4925 .. note::
4922 To check out earlier revisions, you should use :hg:`update REV`.
4926 To check out earlier revisions, you should use :hg:`update REV`.
4923 To cancel an uncommitted merge (and lose your changes),
4927 To cancel an uncommitted merge (and lose your changes),
4924 use :hg:`update --clean .`.
4928 use :hg:`update --clean .`.
4925
4929
4926 With no revision specified, revert the specified files or directories
4930 With no revision specified, revert the specified files or directories
4927 to the contents they had in the parent of the working directory.
4931 to the contents they had in the parent of the working directory.
4928 This restores the contents of files to an unmodified
4932 This restores the contents of files to an unmodified
4929 state and unschedules adds, removes, copies, and renames. If the
4933 state and unschedules adds, removes, copies, and renames. If the
4930 working directory has two parents, you must explicitly specify a
4934 working directory has two parents, you must explicitly specify a
4931 revision.
4935 revision.
4932
4936
4933 Using the -r/--rev or -d/--date options, revert the given files or
4937 Using the -r/--rev or -d/--date options, revert the given files or
4934 directories to their states as of a specific revision. Because
4938 directories to their states as of a specific revision. Because
4935 revert does not change the working directory parents, this will
4939 revert does not change the working directory parents, this will
4936 cause these files to appear modified. This can be helpful to "back
4940 cause these files to appear modified. This can be helpful to "back
4937 out" some or all of an earlier change. See :hg:`backout` for a
4941 out" some or all of an earlier change. See :hg:`backout` for a
4938 related method.
4942 related method.
4939
4943
4940 Modified files are saved with a .orig suffix before reverting.
4944 Modified files are saved with a .orig suffix before reverting.
4941 To disable these backups, use --no-backup.
4945 To disable these backups, use --no-backup.
4942
4946
4943 See :hg:`help dates` for a list of formats valid for -d/--date.
4947 See :hg:`help dates` for a list of formats valid for -d/--date.
4944
4948
4945 Returns 0 on success.
4949 Returns 0 on success.
4946 """
4950 """
4947
4951
4948 if opts.get("date"):
4952 if opts.get("date"):
4949 if opts.get("rev"):
4953 if opts.get("rev"):
4950 raise util.Abort(_("you can't specify a revision and a date"))
4954 raise util.Abort(_("you can't specify a revision and a date"))
4951 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4955 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4952
4956
4953 parent, p2 = repo.dirstate.parents()
4957 parent, p2 = repo.dirstate.parents()
4954 if not opts.get('rev') and p2 != nullid:
4958 if not opts.get('rev') and p2 != nullid:
4955 # revert after merge is a trap for new users (issue2915)
4959 # revert after merge is a trap for new users (issue2915)
4956 raise util.Abort(_('uncommitted merge with no revision specified'),
4960 raise util.Abort(_('uncommitted merge with no revision specified'),
4957 hint=_('use "hg update" or see "hg help revert"'))
4961 hint=_('use "hg update" or see "hg help revert"'))
4958
4962
4959 ctx = scmutil.revsingle(repo, opts.get('rev'))
4963 ctx = scmutil.revsingle(repo, opts.get('rev'))
4960
4964
4961 if not pats and not opts.get('all'):
4965 if not pats and not opts.get('all'):
4962 msg = _("no files or directories specified")
4966 msg = _("no files or directories specified")
4963 if p2 != nullid:
4967 if p2 != nullid:
4964 hint = _("uncommitted merge, use --all to discard all changes,"
4968 hint = _("uncommitted merge, use --all to discard all changes,"
4965 " or 'hg update -C .' to abort the merge")
4969 " or 'hg update -C .' to abort the merge")
4966 raise util.Abort(msg, hint=hint)
4970 raise util.Abort(msg, hint=hint)
4967 dirty = util.any(repo.status())
4971 dirty = util.any(repo.status())
4968 node = ctx.node()
4972 node = ctx.node()
4969 if node != parent:
4973 if node != parent:
4970 if dirty:
4974 if dirty:
4971 hint = _("uncommitted changes, use --all to discard all"
4975 hint = _("uncommitted changes, use --all to discard all"
4972 " changes, or 'hg update %s' to update") % ctx.rev()
4976 " changes, or 'hg update %s' to update") % ctx.rev()
4973 else:
4977 else:
4974 hint = _("use --all to revert all files,"
4978 hint = _("use --all to revert all files,"
4975 " or 'hg update %s' to update") % ctx.rev()
4979 " or 'hg update %s' to update") % ctx.rev()
4976 elif dirty:
4980 elif dirty:
4977 hint = _("uncommitted changes, use --all to discard all changes")
4981 hint = _("uncommitted changes, use --all to discard all changes")
4978 else:
4982 else:
4979 hint = _("use --all to revert all files")
4983 hint = _("use --all to revert all files")
4980 raise util.Abort(msg, hint=hint)
4984 raise util.Abort(msg, hint=hint)
4981
4985
4982 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4986 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4983
4987
4984 @command('rollback', dryrunopts +
4988 @command('rollback', dryrunopts +
4985 [('f', 'force', False, _('ignore safety measures'))])
4989 [('f', 'force', False, _('ignore safety measures'))])
4986 def rollback(ui, repo, **opts):
4990 def rollback(ui, repo, **opts):
4987 """roll back the last transaction (dangerous)
4991 """roll back the last transaction (dangerous)
4988
4992
4989 This command should be used with care. There is only one level of
4993 This command should be used with care. There is only one level of
4990 rollback, and there is no way to undo a rollback. It will also
4994 rollback, and there is no way to undo a rollback. It will also
4991 restore the dirstate at the time of the last transaction, losing
4995 restore the dirstate at the time of the last transaction, losing
4992 any dirstate changes since that time. This command does not alter
4996 any dirstate changes since that time. This command does not alter
4993 the working directory.
4997 the working directory.
4994
4998
4995 Transactions are used to encapsulate the effects of all commands
4999 Transactions are used to encapsulate the effects of all commands
4996 that create new changesets or propagate existing changesets into a
5000 that create new changesets or propagate existing changesets into a
4997 repository.
5001 repository.
4998
5002
4999 .. container:: verbose
5003 .. container:: verbose
5000
5004
5001 For example, the following commands are transactional, and their
5005 For example, the following commands are transactional, and their
5002 effects can be rolled back:
5006 effects can be rolled back:
5003
5007
5004 - commit
5008 - commit
5005 - import
5009 - import
5006 - pull
5010 - pull
5007 - push (with this repository as the destination)
5011 - push (with this repository as the destination)
5008 - unbundle
5012 - unbundle
5009
5013
5010 To avoid permanent data loss, rollback will refuse to rollback a
5014 To avoid permanent data loss, rollback will refuse to rollback a
5011 commit transaction if it isn't checked out. Use --force to
5015 commit transaction if it isn't checked out. Use --force to
5012 override this protection.
5016 override this protection.
5013
5017
5014 This command is not intended for use on public repositories. Once
5018 This command is not intended for use on public repositories. Once
5015 changes are visible for pull by other users, rolling a transaction
5019 changes are visible for pull by other users, rolling a transaction
5016 back locally is ineffective (someone else may already have pulled
5020 back locally is ineffective (someone else may already have pulled
5017 the changes). Furthermore, a race is possible with readers of the
5021 the changes). Furthermore, a race is possible with readers of the
5018 repository; for example an in-progress pull from the repository
5022 repository; for example an in-progress pull from the repository
5019 may fail if a rollback is performed.
5023 may fail if a rollback is performed.
5020
5024
5021 Returns 0 on success, 1 if no rollback data is available.
5025 Returns 0 on success, 1 if no rollback data is available.
5022 """
5026 """
5023 return repo.rollback(dryrun=opts.get('dry_run'),
5027 return repo.rollback(dryrun=opts.get('dry_run'),
5024 force=opts.get('force'))
5028 force=opts.get('force'))
5025
5029
5026 @command('root', [])
5030 @command('root', [])
5027 def root(ui, repo):
5031 def root(ui, repo):
5028 """print the root (top) of the current working directory
5032 """print the root (top) of the current working directory
5029
5033
5030 Print the root directory of the current repository.
5034 Print the root directory of the current repository.
5031
5035
5032 Returns 0 on success.
5036 Returns 0 on success.
5033 """
5037 """
5034 ui.write(repo.root + "\n")
5038 ui.write(repo.root + "\n")
5035
5039
5036 @command('^serve',
5040 @command('^serve',
5037 [('A', 'accesslog', '', _('name of access log file to write to'),
5041 [('A', 'accesslog', '', _('name of access log file to write to'),
5038 _('FILE')),
5042 _('FILE')),
5039 ('d', 'daemon', None, _('run server in background')),
5043 ('d', 'daemon', None, _('run server in background')),
5040 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5044 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5041 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5045 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5042 # use string type, then we can check if something was passed
5046 # use string type, then we can check if something was passed
5043 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5047 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5044 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5048 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5045 _('ADDR')),
5049 _('ADDR')),
5046 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5050 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5047 _('PREFIX')),
5051 _('PREFIX')),
5048 ('n', 'name', '',
5052 ('n', 'name', '',
5049 _('name to show in web pages (default: working directory)'), _('NAME')),
5053 _('name to show in web pages (default: working directory)'), _('NAME')),
5050 ('', 'web-conf', '',
5054 ('', 'web-conf', '',
5051 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5055 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5052 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5056 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5053 _('FILE')),
5057 _('FILE')),
5054 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5058 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5055 ('', 'stdio', None, _('for remote clients')),
5059 ('', 'stdio', None, _('for remote clients')),
5056 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5060 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5057 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5061 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5058 ('', 'style', '', _('template style to use'), _('STYLE')),
5062 ('', 'style', '', _('template style to use'), _('STYLE')),
5059 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5063 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5060 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5064 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5061 _('[OPTION]...'))
5065 _('[OPTION]...'))
5062 def serve(ui, repo, **opts):
5066 def serve(ui, repo, **opts):
5063 """start stand-alone webserver
5067 """start stand-alone webserver
5064
5068
5065 Start a local HTTP repository browser and pull server. You can use
5069 Start a local HTTP repository browser and pull server. You can use
5066 this for ad-hoc sharing and browsing of repositories. It is
5070 this for ad-hoc sharing and browsing of repositories. It is
5067 recommended to use a real web server to serve a repository for
5071 recommended to use a real web server to serve a repository for
5068 longer periods of time.
5072 longer periods of time.
5069
5073
5070 Please note that the server does not implement access control.
5074 Please note that the server does not implement access control.
5071 This means that, by default, anybody can read from the server and
5075 This means that, by default, anybody can read from the server and
5072 nobody can write to it by default. Set the ``web.allow_push``
5076 nobody can write to it by default. Set the ``web.allow_push``
5073 option to ``*`` to allow everybody to push to the server. You
5077 option to ``*`` to allow everybody to push to the server. You
5074 should use a real web server if you need to authenticate users.
5078 should use a real web server if you need to authenticate users.
5075
5079
5076 By default, the server logs accesses to stdout and errors to
5080 By default, the server logs accesses to stdout and errors to
5077 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5081 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5078 files.
5082 files.
5079
5083
5080 To have the server choose a free port number to listen on, specify
5084 To have the server choose a free port number to listen on, specify
5081 a port number of 0; in this case, the server will print the port
5085 a port number of 0; in this case, the server will print the port
5082 number it uses.
5086 number it uses.
5083
5087
5084 Returns 0 on success.
5088 Returns 0 on success.
5085 """
5089 """
5086
5090
5087 if opts["stdio"] and opts["cmdserver"]:
5091 if opts["stdio"] and opts["cmdserver"]:
5088 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5092 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5089
5093
5090 def checkrepo():
5094 def checkrepo():
5091 if repo is None:
5095 if repo is None:
5092 raise error.RepoError(_("there is no Mercurial repository here"
5096 raise error.RepoError(_("there is no Mercurial repository here"
5093 " (.hg not found)"))
5097 " (.hg not found)"))
5094
5098
5095 if opts["stdio"]:
5099 if opts["stdio"]:
5096 checkrepo()
5100 checkrepo()
5097 s = sshserver.sshserver(ui, repo)
5101 s = sshserver.sshserver(ui, repo)
5098 s.serve_forever()
5102 s.serve_forever()
5099
5103
5100 if opts["cmdserver"]:
5104 if opts["cmdserver"]:
5101 checkrepo()
5105 checkrepo()
5102 s = commandserver.server(ui, repo, opts["cmdserver"])
5106 s = commandserver.server(ui, repo, opts["cmdserver"])
5103 return s.serve()
5107 return s.serve()
5104
5108
5105 # this way we can check if something was given in the command-line
5109 # this way we can check if something was given in the command-line
5106 if opts.get('port'):
5110 if opts.get('port'):
5107 opts['port'] = util.getport(opts.get('port'))
5111 opts['port'] = util.getport(opts.get('port'))
5108
5112
5109 baseui = repo and repo.baseui or ui
5113 baseui = repo and repo.baseui or ui
5110 optlist = ("name templates style address port prefix ipv6"
5114 optlist = ("name templates style address port prefix ipv6"
5111 " accesslog errorlog certificate encoding")
5115 " accesslog errorlog certificate encoding")
5112 for o in optlist.split():
5116 for o in optlist.split():
5113 val = opts.get(o, '')
5117 val = opts.get(o, '')
5114 if val in (None, ''): # should check against default options instead
5118 if val in (None, ''): # should check against default options instead
5115 continue
5119 continue
5116 baseui.setconfig("web", o, val)
5120 baseui.setconfig("web", o, val)
5117 if repo and repo.ui != baseui:
5121 if repo and repo.ui != baseui:
5118 repo.ui.setconfig("web", o, val)
5122 repo.ui.setconfig("web", o, val)
5119
5123
5120 o = opts.get('web_conf') or opts.get('webdir_conf')
5124 o = opts.get('web_conf') or opts.get('webdir_conf')
5121 if not o:
5125 if not o:
5122 if not repo:
5126 if not repo:
5123 raise error.RepoError(_("there is no Mercurial repository"
5127 raise error.RepoError(_("there is no Mercurial repository"
5124 " here (.hg not found)"))
5128 " here (.hg not found)"))
5125 o = repo
5129 o = repo
5126
5130
5127 app = hgweb.hgweb(o, baseui=baseui)
5131 app = hgweb.hgweb(o, baseui=baseui)
5128
5132
5129 class service(object):
5133 class service(object):
5130 def init(self):
5134 def init(self):
5131 util.setsignalhandler()
5135 util.setsignalhandler()
5132 self.httpd = hgweb.server.create_server(ui, app)
5136 self.httpd = hgweb.server.create_server(ui, app)
5133
5137
5134 if opts['port'] and not ui.verbose:
5138 if opts['port'] and not ui.verbose:
5135 return
5139 return
5136
5140
5137 if self.httpd.prefix:
5141 if self.httpd.prefix:
5138 prefix = self.httpd.prefix.strip('/') + '/'
5142 prefix = self.httpd.prefix.strip('/') + '/'
5139 else:
5143 else:
5140 prefix = ''
5144 prefix = ''
5141
5145
5142 port = ':%d' % self.httpd.port
5146 port = ':%d' % self.httpd.port
5143 if port == ':80':
5147 if port == ':80':
5144 port = ''
5148 port = ''
5145
5149
5146 bindaddr = self.httpd.addr
5150 bindaddr = self.httpd.addr
5147 if bindaddr == '0.0.0.0':
5151 if bindaddr == '0.0.0.0':
5148 bindaddr = '*'
5152 bindaddr = '*'
5149 elif ':' in bindaddr: # IPv6
5153 elif ':' in bindaddr: # IPv6
5150 bindaddr = '[%s]' % bindaddr
5154 bindaddr = '[%s]' % bindaddr
5151
5155
5152 fqaddr = self.httpd.fqaddr
5156 fqaddr = self.httpd.fqaddr
5153 if ':' in fqaddr:
5157 if ':' in fqaddr:
5154 fqaddr = '[%s]' % fqaddr
5158 fqaddr = '[%s]' % fqaddr
5155 if opts['port']:
5159 if opts['port']:
5156 write = ui.status
5160 write = ui.status
5157 else:
5161 else:
5158 write = ui.write
5162 write = ui.write
5159 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5163 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5160 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5164 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5161
5165
5162 def run(self):
5166 def run(self):
5163 self.httpd.serve_forever()
5167 self.httpd.serve_forever()
5164
5168
5165 service = service()
5169 service = service()
5166
5170
5167 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5171 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5168
5172
5169 @command('showconfig|debugconfig',
5173 @command('showconfig|debugconfig',
5170 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5174 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5171 _('[-u] [NAME]...'))
5175 _('[-u] [NAME]...'))
5172 def showconfig(ui, repo, *values, **opts):
5176 def showconfig(ui, repo, *values, **opts):
5173 """show combined config settings from all hgrc files
5177 """show combined config settings from all hgrc files
5174
5178
5175 With no arguments, print names and values of all config items.
5179 With no arguments, print names and values of all config items.
5176
5180
5177 With one argument of the form section.name, print just the value
5181 With one argument of the form section.name, print just the value
5178 of that config item.
5182 of that config item.
5179
5183
5180 With multiple arguments, print names and values of all config
5184 With multiple arguments, print names and values of all config
5181 items with matching section names.
5185 items with matching section names.
5182
5186
5183 With --debug, the source (filename and line number) is printed
5187 With --debug, the source (filename and line number) is printed
5184 for each config item.
5188 for each config item.
5185
5189
5186 Returns 0 on success.
5190 Returns 0 on success.
5187 """
5191 """
5188
5192
5189 for f in scmutil.rcpath():
5193 for f in scmutil.rcpath():
5190 ui.debug('read config from: %s\n' % f)
5194 ui.debug('read config from: %s\n' % f)
5191 untrusted = bool(opts.get('untrusted'))
5195 untrusted = bool(opts.get('untrusted'))
5192 if values:
5196 if values:
5193 sections = [v for v in values if '.' not in v]
5197 sections = [v for v in values if '.' not in v]
5194 items = [v for v in values if '.' in v]
5198 items = [v for v in values if '.' in v]
5195 if len(items) > 1 or items and sections:
5199 if len(items) > 1 or items and sections:
5196 raise util.Abort(_('only one config item permitted'))
5200 raise util.Abort(_('only one config item permitted'))
5197 for section, name, value in ui.walkconfig(untrusted=untrusted):
5201 for section, name, value in ui.walkconfig(untrusted=untrusted):
5198 value = str(value).replace('\n', '\\n')
5202 value = str(value).replace('\n', '\\n')
5199 sectname = section + '.' + name
5203 sectname = section + '.' + name
5200 if values:
5204 if values:
5201 for v in values:
5205 for v in values:
5202 if v == section:
5206 if v == section:
5203 ui.debug('%s: ' %
5207 ui.debug('%s: ' %
5204 ui.configsource(section, name, untrusted))
5208 ui.configsource(section, name, untrusted))
5205 ui.write('%s=%s\n' % (sectname, value))
5209 ui.write('%s=%s\n' % (sectname, value))
5206 elif v == sectname:
5210 elif v == sectname:
5207 ui.debug('%s: ' %
5211 ui.debug('%s: ' %
5208 ui.configsource(section, name, untrusted))
5212 ui.configsource(section, name, untrusted))
5209 ui.write(value, '\n')
5213 ui.write(value, '\n')
5210 else:
5214 else:
5211 ui.debug('%s: ' %
5215 ui.debug('%s: ' %
5212 ui.configsource(section, name, untrusted))
5216 ui.configsource(section, name, untrusted))
5213 ui.write('%s=%s\n' % (sectname, value))
5217 ui.write('%s=%s\n' % (sectname, value))
5214
5218
5215 @command('^status|st',
5219 @command('^status|st',
5216 [('A', 'all', None, _('show status of all files')),
5220 [('A', 'all', None, _('show status of all files')),
5217 ('m', 'modified', None, _('show only modified files')),
5221 ('m', 'modified', None, _('show only modified files')),
5218 ('a', 'added', None, _('show only added files')),
5222 ('a', 'added', None, _('show only added files')),
5219 ('r', 'removed', None, _('show only removed files')),
5223 ('r', 'removed', None, _('show only removed files')),
5220 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5224 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5221 ('c', 'clean', None, _('show only files without changes')),
5225 ('c', 'clean', None, _('show only files without changes')),
5222 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5226 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5223 ('i', 'ignored', None, _('show only ignored files')),
5227 ('i', 'ignored', None, _('show only ignored files')),
5224 ('n', 'no-status', None, _('hide status prefix')),
5228 ('n', 'no-status', None, _('hide status prefix')),
5225 ('C', 'copies', None, _('show source of copied files')),
5229 ('C', 'copies', None, _('show source of copied files')),
5226 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5230 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5227 ('', 'rev', [], _('show difference from revision'), _('REV')),
5231 ('', 'rev', [], _('show difference from revision'), _('REV')),
5228 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5232 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5229 ] + walkopts + subrepoopts,
5233 ] + walkopts + subrepoopts,
5230 _('[OPTION]... [FILE]...'))
5234 _('[OPTION]... [FILE]...'))
5231 def status(ui, repo, *pats, **opts):
5235 def status(ui, repo, *pats, **opts):
5232 """show changed files in the working directory
5236 """show changed files in the working directory
5233
5237
5234 Show status of files in the repository. If names are given, only
5238 Show status of files in the repository. If names are given, only
5235 files that match are shown. Files that are clean or ignored or
5239 files that match are shown. Files that are clean or ignored or
5236 the source of a copy/move operation, are not listed unless
5240 the source of a copy/move operation, are not listed unless
5237 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5241 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5238 Unless options described with "show only ..." are given, the
5242 Unless options described with "show only ..." are given, the
5239 options -mardu are used.
5243 options -mardu are used.
5240
5244
5241 Option -q/--quiet hides untracked (unknown and ignored) files
5245 Option -q/--quiet hides untracked (unknown and ignored) files
5242 unless explicitly requested with -u/--unknown or -i/--ignored.
5246 unless explicitly requested with -u/--unknown or -i/--ignored.
5243
5247
5244 .. note::
5248 .. note::
5245 status may appear to disagree with diff if permissions have
5249 status may appear to disagree with diff if permissions have
5246 changed or a merge has occurred. The standard diff format does
5250 changed or a merge has occurred. The standard diff format does
5247 not report permission changes and diff only reports changes
5251 not report permission changes and diff only reports changes
5248 relative to one merge parent.
5252 relative to one merge parent.
5249
5253
5250 If one revision is given, it is used as the base revision.
5254 If one revision is given, it is used as the base revision.
5251 If two revisions are given, the differences between them are
5255 If two revisions are given, the differences between them are
5252 shown. The --change option can also be used as a shortcut to list
5256 shown. The --change option can also be used as a shortcut to list
5253 the changed files of a revision from its first parent.
5257 the changed files of a revision from its first parent.
5254
5258
5255 The codes used to show the status of files are::
5259 The codes used to show the status of files are::
5256
5260
5257 M = modified
5261 M = modified
5258 A = added
5262 A = added
5259 R = removed
5263 R = removed
5260 C = clean
5264 C = clean
5261 ! = missing (deleted by non-hg command, but still tracked)
5265 ! = missing (deleted by non-hg command, but still tracked)
5262 ? = not tracked
5266 ? = not tracked
5263 I = ignored
5267 I = ignored
5264 = origin of the previous file listed as A (added)
5268 = origin of the previous file listed as A (added)
5265
5269
5266 .. container:: verbose
5270 .. container:: verbose
5267
5271
5268 Examples:
5272 Examples:
5269
5273
5270 - show changes in the working directory relative to a
5274 - show changes in the working directory relative to a
5271 changeset::
5275 changeset::
5272
5276
5273 hg status --rev 9353
5277 hg status --rev 9353
5274
5278
5275 - show all changes including copies in an existing changeset::
5279 - show all changes including copies in an existing changeset::
5276
5280
5277 hg status --copies --change 9353
5281 hg status --copies --change 9353
5278
5282
5279 - get a NUL separated list of added files, suitable for xargs::
5283 - get a NUL separated list of added files, suitable for xargs::
5280
5284
5281 hg status -an0
5285 hg status -an0
5282
5286
5283 Returns 0 on success.
5287 Returns 0 on success.
5284 """
5288 """
5285
5289
5286 revs = opts.get('rev')
5290 revs = opts.get('rev')
5287 change = opts.get('change')
5291 change = opts.get('change')
5288
5292
5289 if revs and change:
5293 if revs and change:
5290 msg = _('cannot specify --rev and --change at the same time')
5294 msg = _('cannot specify --rev and --change at the same time')
5291 raise util.Abort(msg)
5295 raise util.Abort(msg)
5292 elif change:
5296 elif change:
5293 node2 = scmutil.revsingle(repo, change, None).node()
5297 node2 = scmutil.revsingle(repo, change, None).node()
5294 node1 = repo[node2].p1().node()
5298 node1 = repo[node2].p1().node()
5295 else:
5299 else:
5296 node1, node2 = scmutil.revpair(repo, revs)
5300 node1, node2 = scmutil.revpair(repo, revs)
5297
5301
5298 cwd = (pats and repo.getcwd()) or ''
5302 cwd = (pats and repo.getcwd()) or ''
5299 end = opts.get('print0') and '\0' or '\n'
5303 end = opts.get('print0') and '\0' or '\n'
5300 copy = {}
5304 copy = {}
5301 states = 'modified added removed deleted unknown ignored clean'.split()
5305 states = 'modified added removed deleted unknown ignored clean'.split()
5302 show = [k for k in states if opts.get(k)]
5306 show = [k for k in states if opts.get(k)]
5303 if opts.get('all'):
5307 if opts.get('all'):
5304 show += ui.quiet and (states[:4] + ['clean']) or states
5308 show += ui.quiet and (states[:4] + ['clean']) or states
5305 if not show:
5309 if not show:
5306 show = ui.quiet and states[:4] or states[:5]
5310 show = ui.quiet and states[:4] or states[:5]
5307
5311
5308 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5312 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5309 'ignored' in show, 'clean' in show, 'unknown' in show,
5313 'ignored' in show, 'clean' in show, 'unknown' in show,
5310 opts.get('subrepos'))
5314 opts.get('subrepos'))
5311 changestates = zip(states, 'MAR!?IC', stat)
5315 changestates = zip(states, 'MAR!?IC', stat)
5312
5316
5313 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5317 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5314 copy = copies.pathcopies(repo[node1], repo[node2])
5318 copy = copies.pathcopies(repo[node1], repo[node2])
5315
5319
5316 fm = ui.formatter('status', opts)
5320 fm = ui.formatter('status', opts)
5317 fmt = '%s' + end
5321 fmt = '%s' + end
5318 showchar = not opts.get('no_status')
5322 showchar = not opts.get('no_status')
5319
5323
5320 for state, char, files in changestates:
5324 for state, char, files in changestates:
5321 if state in show:
5325 if state in show:
5322 label = 'status.' + state
5326 label = 'status.' + state
5323 for f in files:
5327 for f in files:
5324 fm.startitem()
5328 fm.startitem()
5325 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5329 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5326 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5330 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5327 if f in copy:
5331 if f in copy:
5328 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5332 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5329 label='status.copied')
5333 label='status.copied')
5330 fm.end()
5334 fm.end()
5331
5335
5332 @command('^summary|sum',
5336 @command('^summary|sum',
5333 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5337 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5334 def summary(ui, repo, **opts):
5338 def summary(ui, repo, **opts):
5335 """summarize working directory state
5339 """summarize working directory state
5336
5340
5337 This generates a brief summary of the working directory state,
5341 This generates a brief summary of the working directory state,
5338 including parents, branch, commit status, and available updates.
5342 including parents, branch, commit status, and available updates.
5339
5343
5340 With the --remote option, this will check the default paths for
5344 With the --remote option, this will check the default paths for
5341 incoming and outgoing changes. This can be time-consuming.
5345 incoming and outgoing changes. This can be time-consuming.
5342
5346
5343 Returns 0 on success.
5347 Returns 0 on success.
5344 """
5348 """
5345
5349
5346 ctx = repo[None]
5350 ctx = repo[None]
5347 parents = ctx.parents()
5351 parents = ctx.parents()
5348 pnode = parents[0].node()
5352 pnode = parents[0].node()
5349 marks = []
5353 marks = []
5350
5354
5351 for p in parents:
5355 for p in parents:
5352 # label with log.changeset (instead of log.parent) since this
5356 # label with log.changeset (instead of log.parent) since this
5353 # shows a working directory parent *changeset*:
5357 # shows a working directory parent *changeset*:
5354 # i18n: column positioning for "hg summary"
5358 # i18n: column positioning for "hg summary"
5355 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5359 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5356 label='log.changeset changeset.%s' % p.phasestr())
5360 label='log.changeset changeset.%s' % p.phasestr())
5357 ui.write(' '.join(p.tags()), label='log.tag')
5361 ui.write(' '.join(p.tags()), label='log.tag')
5358 if p.bookmarks():
5362 if p.bookmarks():
5359 marks.extend(p.bookmarks())
5363 marks.extend(p.bookmarks())
5360 if p.rev() == -1:
5364 if p.rev() == -1:
5361 if not len(repo):
5365 if not len(repo):
5362 ui.write(_(' (empty repository)'))
5366 ui.write(_(' (empty repository)'))
5363 else:
5367 else:
5364 ui.write(_(' (no revision checked out)'))
5368 ui.write(_(' (no revision checked out)'))
5365 ui.write('\n')
5369 ui.write('\n')
5366 if p.description():
5370 if p.description():
5367 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5371 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5368 label='log.summary')
5372 label='log.summary')
5369
5373
5370 branch = ctx.branch()
5374 branch = ctx.branch()
5371 bheads = repo.branchheads(branch)
5375 bheads = repo.branchheads(branch)
5372 # i18n: column positioning for "hg summary"
5376 # i18n: column positioning for "hg summary"
5373 m = _('branch: %s\n') % branch
5377 m = _('branch: %s\n') % branch
5374 if branch != 'default':
5378 if branch != 'default':
5375 ui.write(m, label='log.branch')
5379 ui.write(m, label='log.branch')
5376 else:
5380 else:
5377 ui.status(m, label='log.branch')
5381 ui.status(m, label='log.branch')
5378
5382
5379 if marks:
5383 if marks:
5380 current = repo._bookmarkcurrent
5384 current = repo._bookmarkcurrent
5381 # i18n: column positioning for "hg summary"
5385 # i18n: column positioning for "hg summary"
5382 ui.write(_('bookmarks:'), label='log.bookmark')
5386 ui.write(_('bookmarks:'), label='log.bookmark')
5383 if current is not None:
5387 if current is not None:
5384 if current in marks:
5388 if current in marks:
5385 ui.write(' *' + current, label='bookmarks.current')
5389 ui.write(' *' + current, label='bookmarks.current')
5386 marks.remove(current)
5390 marks.remove(current)
5387 else:
5391 else:
5388 ui.write(' [%s]' % current, label='bookmarks.current')
5392 ui.write(' [%s]' % current, label='bookmarks.current')
5389 for m in marks:
5393 for m in marks:
5390 ui.write(' ' + m, label='log.bookmark')
5394 ui.write(' ' + m, label='log.bookmark')
5391 ui.write('\n', label='log.bookmark')
5395 ui.write('\n', label='log.bookmark')
5392
5396
5393 st = list(repo.status(unknown=True))[:6]
5397 st = list(repo.status(unknown=True))[:6]
5394
5398
5395 c = repo.dirstate.copies()
5399 c = repo.dirstate.copies()
5396 copied, renamed = [], []
5400 copied, renamed = [], []
5397 for d, s in c.iteritems():
5401 for d, s in c.iteritems():
5398 if s in st[2]:
5402 if s in st[2]:
5399 st[2].remove(s)
5403 st[2].remove(s)
5400 renamed.append(d)
5404 renamed.append(d)
5401 else:
5405 else:
5402 copied.append(d)
5406 copied.append(d)
5403 if d in st[1]:
5407 if d in st[1]:
5404 st[1].remove(d)
5408 st[1].remove(d)
5405 st.insert(3, renamed)
5409 st.insert(3, renamed)
5406 st.insert(4, copied)
5410 st.insert(4, copied)
5407
5411
5408 ms = mergemod.mergestate(repo)
5412 ms = mergemod.mergestate(repo)
5409 st.append([f for f in ms if ms[f] == 'u'])
5413 st.append([f for f in ms if ms[f] == 'u'])
5410
5414
5411 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5415 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5412 st.append(subs)
5416 st.append(subs)
5413
5417
5414 labels = [ui.label(_('%d modified'), 'status.modified'),
5418 labels = [ui.label(_('%d modified'), 'status.modified'),
5415 ui.label(_('%d added'), 'status.added'),
5419 ui.label(_('%d added'), 'status.added'),
5416 ui.label(_('%d removed'), 'status.removed'),
5420 ui.label(_('%d removed'), 'status.removed'),
5417 ui.label(_('%d renamed'), 'status.copied'),
5421 ui.label(_('%d renamed'), 'status.copied'),
5418 ui.label(_('%d copied'), 'status.copied'),
5422 ui.label(_('%d copied'), 'status.copied'),
5419 ui.label(_('%d deleted'), 'status.deleted'),
5423 ui.label(_('%d deleted'), 'status.deleted'),
5420 ui.label(_('%d unknown'), 'status.unknown'),
5424 ui.label(_('%d unknown'), 'status.unknown'),
5421 ui.label(_('%d ignored'), 'status.ignored'),
5425 ui.label(_('%d ignored'), 'status.ignored'),
5422 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5426 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5423 ui.label(_('%d subrepos'), 'status.modified')]
5427 ui.label(_('%d subrepos'), 'status.modified')]
5424 t = []
5428 t = []
5425 for s, l in zip(st, labels):
5429 for s, l in zip(st, labels):
5426 if s:
5430 if s:
5427 t.append(l % len(s))
5431 t.append(l % len(s))
5428
5432
5429 t = ', '.join(t)
5433 t = ', '.join(t)
5430 cleanworkdir = False
5434 cleanworkdir = False
5431
5435
5432 if len(parents) > 1:
5436 if len(parents) > 1:
5433 t += _(' (merge)')
5437 t += _(' (merge)')
5434 elif branch != parents[0].branch():
5438 elif branch != parents[0].branch():
5435 t += _(' (new branch)')
5439 t += _(' (new branch)')
5436 elif (parents[0].closesbranch() and
5440 elif (parents[0].closesbranch() and
5437 pnode in repo.branchheads(branch, closed=True)):
5441 pnode in repo.branchheads(branch, closed=True)):
5438 t += _(' (head closed)')
5442 t += _(' (head closed)')
5439 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5443 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5440 t += _(' (clean)')
5444 t += _(' (clean)')
5441 cleanworkdir = True
5445 cleanworkdir = True
5442 elif pnode not in bheads:
5446 elif pnode not in bheads:
5443 t += _(' (new branch head)')
5447 t += _(' (new branch head)')
5444
5448
5445 if cleanworkdir:
5449 if cleanworkdir:
5446 # i18n: column positioning for "hg summary"
5450 # i18n: column positioning for "hg summary"
5447 ui.status(_('commit: %s\n') % t.strip())
5451 ui.status(_('commit: %s\n') % t.strip())
5448 else:
5452 else:
5449 # i18n: column positioning for "hg summary"
5453 # i18n: column positioning for "hg summary"
5450 ui.write(_('commit: %s\n') % t.strip())
5454 ui.write(_('commit: %s\n') % t.strip())
5451
5455
5452 # all ancestors of branch heads - all ancestors of parent = new csets
5456 # all ancestors of branch heads - all ancestors of parent = new csets
5453 new = [0] * len(repo)
5457 new = [0] * len(repo)
5454 cl = repo.changelog
5458 cl = repo.changelog
5455 for a in [cl.rev(n) for n in bheads]:
5459 for a in [cl.rev(n) for n in bheads]:
5456 new[a] = 1
5460 new[a] = 1
5457 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5461 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5458 new[a] = 1
5462 new[a] = 1
5459 for a in [p.rev() for p in parents]:
5463 for a in [p.rev() for p in parents]:
5460 if a >= 0:
5464 if a >= 0:
5461 new[a] = 0
5465 new[a] = 0
5462 for a in cl.ancestors([p.rev() for p in parents]):
5466 for a in cl.ancestors([p.rev() for p in parents]):
5463 new[a] = 0
5467 new[a] = 0
5464 new = sum(new)
5468 new = sum(new)
5465
5469
5466 if new == 0:
5470 if new == 0:
5467 # i18n: column positioning for "hg summary"
5471 # i18n: column positioning for "hg summary"
5468 ui.status(_('update: (current)\n'))
5472 ui.status(_('update: (current)\n'))
5469 elif pnode not in bheads:
5473 elif pnode not in bheads:
5470 # i18n: column positioning for "hg summary"
5474 # i18n: column positioning for "hg summary"
5471 ui.write(_('update: %d new changesets (update)\n') % new)
5475 ui.write(_('update: %d new changesets (update)\n') % new)
5472 else:
5476 else:
5473 # i18n: column positioning for "hg summary"
5477 # i18n: column positioning for "hg summary"
5474 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5478 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5475 (new, len(bheads)))
5479 (new, len(bheads)))
5476
5480
5477 if opts.get('remote'):
5481 if opts.get('remote'):
5478 t = []
5482 t = []
5479 source, branches = hg.parseurl(ui.expandpath('default'))
5483 source, branches = hg.parseurl(ui.expandpath('default'))
5480 sbranch = branches[0]
5484 sbranch = branches[0]
5481 other = hg.peer(repo, {}, source)
5485 other = hg.peer(repo, {}, source)
5482 revs, checkout = hg.addbranchrevs(repo, other, branches,
5486 revs, checkout = hg.addbranchrevs(repo, other, branches,
5483 opts.get('rev'))
5487 opts.get('rev'))
5484 if revs:
5488 if revs:
5485 revs = [other.lookup(rev) for rev in revs]
5489 revs = [other.lookup(rev) for rev in revs]
5486 ui.debug('comparing with %s\n' % util.hidepassword(source))
5490 ui.debug('comparing with %s\n' % util.hidepassword(source))
5487 repo.ui.pushbuffer()
5491 repo.ui.pushbuffer()
5488 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5492 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5489 _common, incoming, _rheads = commoninc
5493 _common, incoming, _rheads = commoninc
5490 repo.ui.popbuffer()
5494 repo.ui.popbuffer()
5491 if incoming:
5495 if incoming:
5492 t.append(_('1 or more incoming'))
5496 t.append(_('1 or more incoming'))
5493
5497
5494 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5498 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5495 dbranch = branches[0]
5499 dbranch = branches[0]
5496 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5500 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5497 if source != dest:
5501 if source != dest:
5498 other = hg.peer(repo, {}, dest)
5502 other = hg.peer(repo, {}, dest)
5499 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5503 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5500 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5504 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5501 commoninc = None
5505 commoninc = None
5502 if revs:
5506 if revs:
5503 revs = [repo.lookup(rev) for rev in revs]
5507 revs = [repo.lookup(rev) for rev in revs]
5504 repo.ui.pushbuffer()
5508 repo.ui.pushbuffer()
5505 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5509 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5506 commoninc=commoninc)
5510 commoninc=commoninc)
5507 repo.ui.popbuffer()
5511 repo.ui.popbuffer()
5508 o = outgoing.missing
5512 o = outgoing.missing
5509 if o:
5513 if o:
5510 t.append(_('%d outgoing') % len(o))
5514 t.append(_('%d outgoing') % len(o))
5511 if 'bookmarks' in other.listkeys('namespaces'):
5515 if 'bookmarks' in other.listkeys('namespaces'):
5512 lmarks = repo.listkeys('bookmarks')
5516 lmarks = repo.listkeys('bookmarks')
5513 rmarks = other.listkeys('bookmarks')
5517 rmarks = other.listkeys('bookmarks')
5514 diff = set(rmarks) - set(lmarks)
5518 diff = set(rmarks) - set(lmarks)
5515 if len(diff) > 0:
5519 if len(diff) > 0:
5516 t.append(_('%d incoming bookmarks') % len(diff))
5520 t.append(_('%d incoming bookmarks') % len(diff))
5517 diff = set(lmarks) - set(rmarks)
5521 diff = set(lmarks) - set(rmarks)
5518 if len(diff) > 0:
5522 if len(diff) > 0:
5519 t.append(_('%d outgoing bookmarks') % len(diff))
5523 t.append(_('%d outgoing bookmarks') % len(diff))
5520
5524
5521 if t:
5525 if t:
5522 # i18n: column positioning for "hg summary"
5526 # i18n: column positioning for "hg summary"
5523 ui.write(_('remote: %s\n') % (', '.join(t)))
5527 ui.write(_('remote: %s\n') % (', '.join(t)))
5524 else:
5528 else:
5525 # i18n: column positioning for "hg summary"
5529 # i18n: column positioning for "hg summary"
5526 ui.status(_('remote: (synced)\n'))
5530 ui.status(_('remote: (synced)\n'))
5527
5531
5528 @command('tag',
5532 @command('tag',
5529 [('f', 'force', None, _('force tag')),
5533 [('f', 'force', None, _('force tag')),
5530 ('l', 'local', None, _('make the tag local')),
5534 ('l', 'local', None, _('make the tag local')),
5531 ('r', 'rev', '', _('revision to tag'), _('REV')),
5535 ('r', 'rev', '', _('revision to tag'), _('REV')),
5532 ('', 'remove', None, _('remove a tag')),
5536 ('', 'remove', None, _('remove a tag')),
5533 # -l/--local is already there, commitopts cannot be used
5537 # -l/--local is already there, commitopts cannot be used
5534 ('e', 'edit', None, _('edit commit message')),
5538 ('e', 'edit', None, _('edit commit message')),
5535 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5539 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5536 ] + commitopts2,
5540 ] + commitopts2,
5537 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5541 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5538 def tag(ui, repo, name1, *names, **opts):
5542 def tag(ui, repo, name1, *names, **opts):
5539 """add one or more tags for the current or given revision
5543 """add one or more tags for the current or given revision
5540
5544
5541 Name a particular revision using <name>.
5545 Name a particular revision using <name>.
5542
5546
5543 Tags are used to name particular revisions of the repository and are
5547 Tags are used to name particular revisions of the repository and are
5544 very useful to compare different revisions, to go back to significant
5548 very useful to compare different revisions, to go back to significant
5545 earlier versions or to mark branch points as releases, etc. Changing
5549 earlier versions or to mark branch points as releases, etc. Changing
5546 an existing tag is normally disallowed; use -f/--force to override.
5550 an existing tag is normally disallowed; use -f/--force to override.
5547
5551
5548 If no revision is given, the parent of the working directory is
5552 If no revision is given, the parent of the working directory is
5549 used, or tip if no revision is checked out.
5553 used, or tip if no revision is checked out.
5550
5554
5551 To facilitate version control, distribution, and merging of tags,
5555 To facilitate version control, distribution, and merging of tags,
5552 they are stored as a file named ".hgtags" which is managed similarly
5556 they are stored as a file named ".hgtags" which is managed similarly
5553 to other project files and can be hand-edited if necessary. This
5557 to other project files and can be hand-edited if necessary. This
5554 also means that tagging creates a new commit. The file
5558 also means that tagging creates a new commit. The file
5555 ".hg/localtags" is used for local tags (not shared among
5559 ".hg/localtags" is used for local tags (not shared among
5556 repositories).
5560 repositories).
5557
5561
5558 Tag commits are usually made at the head of a branch. If the parent
5562 Tag commits are usually made at the head of a branch. If the parent
5559 of the working directory is not a branch head, :hg:`tag` aborts; use
5563 of the working directory is not a branch head, :hg:`tag` aborts; use
5560 -f/--force to force the tag commit to be based on a non-head
5564 -f/--force to force the tag commit to be based on a non-head
5561 changeset.
5565 changeset.
5562
5566
5563 See :hg:`help dates` for a list of formats valid for -d/--date.
5567 See :hg:`help dates` for a list of formats valid for -d/--date.
5564
5568
5565 Since tag names have priority over branch names during revision
5569 Since tag names have priority over branch names during revision
5566 lookup, using an existing branch name as a tag name is discouraged.
5570 lookup, using an existing branch name as a tag name is discouraged.
5567
5571
5568 Returns 0 on success.
5572 Returns 0 on success.
5569 """
5573 """
5570 wlock = lock = None
5574 wlock = lock = None
5571 try:
5575 try:
5572 wlock = repo.wlock()
5576 wlock = repo.wlock()
5573 lock = repo.lock()
5577 lock = repo.lock()
5574 rev_ = "."
5578 rev_ = "."
5575 names = [t.strip() for t in (name1,) + names]
5579 names = [t.strip() for t in (name1,) + names]
5576 if len(names) != len(set(names)):
5580 if len(names) != len(set(names)):
5577 raise util.Abort(_('tag names must be unique'))
5581 raise util.Abort(_('tag names must be unique'))
5578 for n in names:
5582 for n in names:
5579 scmutil.checknewlabel(repo, n, 'tag')
5583 scmutil.checknewlabel(repo, n, 'tag')
5580 if not n:
5584 if not n:
5581 raise util.Abort(_('tag names cannot consist entirely of '
5585 raise util.Abort(_('tag names cannot consist entirely of '
5582 'whitespace'))
5586 'whitespace'))
5583 if opts.get('rev') and opts.get('remove'):
5587 if opts.get('rev') and opts.get('remove'):
5584 raise util.Abort(_("--rev and --remove are incompatible"))
5588 raise util.Abort(_("--rev and --remove are incompatible"))
5585 if opts.get('rev'):
5589 if opts.get('rev'):
5586 rev_ = opts['rev']
5590 rev_ = opts['rev']
5587 message = opts.get('message')
5591 message = opts.get('message')
5588 if opts.get('remove'):
5592 if opts.get('remove'):
5589 expectedtype = opts.get('local') and 'local' or 'global'
5593 expectedtype = opts.get('local') and 'local' or 'global'
5590 for n in names:
5594 for n in names:
5591 if not repo.tagtype(n):
5595 if not repo.tagtype(n):
5592 raise util.Abort(_("tag '%s' does not exist") % n)
5596 raise util.Abort(_("tag '%s' does not exist") % n)
5593 if repo.tagtype(n) != expectedtype:
5597 if repo.tagtype(n) != expectedtype:
5594 if expectedtype == 'global':
5598 if expectedtype == 'global':
5595 raise util.Abort(_("tag '%s' is not a global tag") % n)
5599 raise util.Abort(_("tag '%s' is not a global tag") % n)
5596 else:
5600 else:
5597 raise util.Abort(_("tag '%s' is not a local tag") % n)
5601 raise util.Abort(_("tag '%s' is not a local tag") % n)
5598 rev_ = nullid
5602 rev_ = nullid
5599 if not message:
5603 if not message:
5600 # we don't translate commit messages
5604 # we don't translate commit messages
5601 message = 'Removed tag %s' % ', '.join(names)
5605 message = 'Removed tag %s' % ', '.join(names)
5602 elif not opts.get('force'):
5606 elif not opts.get('force'):
5603 for n in names:
5607 for n in names:
5604 if n in repo.tags():
5608 if n in repo.tags():
5605 raise util.Abort(_("tag '%s' already exists "
5609 raise util.Abort(_("tag '%s' already exists "
5606 "(use -f to force)") % n)
5610 "(use -f to force)") % n)
5607 if not opts.get('local'):
5611 if not opts.get('local'):
5608 p1, p2 = repo.dirstate.parents()
5612 p1, p2 = repo.dirstate.parents()
5609 if p2 != nullid:
5613 if p2 != nullid:
5610 raise util.Abort(_('uncommitted merge'))
5614 raise util.Abort(_('uncommitted merge'))
5611 bheads = repo.branchheads()
5615 bheads = repo.branchheads()
5612 if not opts.get('force') and bheads and p1 not in bheads:
5616 if not opts.get('force') and bheads and p1 not in bheads:
5613 raise util.Abort(_('not at a branch head (use -f to force)'))
5617 raise util.Abort(_('not at a branch head (use -f to force)'))
5614 r = scmutil.revsingle(repo, rev_).node()
5618 r = scmutil.revsingle(repo, rev_).node()
5615
5619
5616 if not message:
5620 if not message:
5617 # we don't translate commit messages
5621 # we don't translate commit messages
5618 message = ('Added tag %s for changeset %s' %
5622 message = ('Added tag %s for changeset %s' %
5619 (', '.join(names), short(r)))
5623 (', '.join(names), short(r)))
5620
5624
5621 date = opts.get('date')
5625 date = opts.get('date')
5622 if date:
5626 if date:
5623 date = util.parsedate(date)
5627 date = util.parsedate(date)
5624
5628
5625 if opts.get('edit'):
5629 if opts.get('edit'):
5626 message = ui.edit(message, ui.username())
5630 message = ui.edit(message, ui.username())
5627
5631
5628 # don't allow tagging the null rev
5632 # don't allow tagging the null rev
5629 if (not opts.get('remove') and
5633 if (not opts.get('remove') and
5630 scmutil.revsingle(repo, rev_).rev() == nullrev):
5634 scmutil.revsingle(repo, rev_).rev() == nullrev):
5631 raise util.Abort(_("cannot tag null revision"))
5635 raise util.Abort(_("cannot tag null revision"))
5632
5636
5633 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5637 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5634 finally:
5638 finally:
5635 release(lock, wlock)
5639 release(lock, wlock)
5636
5640
5637 @command('tags', [], '')
5641 @command('tags', [], '')
5638 def tags(ui, repo, **opts):
5642 def tags(ui, repo, **opts):
5639 """list repository tags
5643 """list repository tags
5640
5644
5641 This lists both regular and local tags. When the -v/--verbose
5645 This lists both regular and local tags. When the -v/--verbose
5642 switch is used, a third column "local" is printed for local tags.
5646 switch is used, a third column "local" is printed for local tags.
5643
5647
5644 Returns 0 on success.
5648 Returns 0 on success.
5645 """
5649 """
5646
5650
5647 fm = ui.formatter('tags', opts)
5651 fm = ui.formatter('tags', opts)
5648 hexfunc = ui.debugflag and hex or short
5652 hexfunc = ui.debugflag and hex or short
5649 tagtype = ""
5653 tagtype = ""
5650
5654
5651 for t, n in reversed(repo.tagslist()):
5655 for t, n in reversed(repo.tagslist()):
5652 hn = hexfunc(n)
5656 hn = hexfunc(n)
5653 label = 'tags.normal'
5657 label = 'tags.normal'
5654 tagtype = ''
5658 tagtype = ''
5655 if repo.tagtype(t) == 'local':
5659 if repo.tagtype(t) == 'local':
5656 label = 'tags.local'
5660 label = 'tags.local'
5657 tagtype = 'local'
5661 tagtype = 'local'
5658
5662
5659 fm.startitem()
5663 fm.startitem()
5660 fm.write('tag', '%s', t, label=label)
5664 fm.write('tag', '%s', t, label=label)
5661 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5665 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5662 fm.condwrite(not ui.quiet, 'rev id', fmt,
5666 fm.condwrite(not ui.quiet, 'rev id', fmt,
5663 repo.changelog.rev(n), hn, label=label)
5667 repo.changelog.rev(n), hn, label=label)
5664 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5668 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5665 tagtype, label=label)
5669 tagtype, label=label)
5666 fm.plain('\n')
5670 fm.plain('\n')
5667 fm.end()
5671 fm.end()
5668
5672
5669 @command('tip',
5673 @command('tip',
5670 [('p', 'patch', None, _('show patch')),
5674 [('p', 'patch', None, _('show patch')),
5671 ('g', 'git', None, _('use git extended diff format')),
5675 ('g', 'git', None, _('use git extended diff format')),
5672 ] + templateopts,
5676 ] + templateopts,
5673 _('[-p] [-g]'))
5677 _('[-p] [-g]'))
5674 def tip(ui, repo, **opts):
5678 def tip(ui, repo, **opts):
5675 """show the tip revision
5679 """show the tip revision
5676
5680
5677 The tip revision (usually just called the tip) is the changeset
5681 The tip revision (usually just called the tip) is the changeset
5678 most recently added to the repository (and therefore the most
5682 most recently added to the repository (and therefore the most
5679 recently changed head).
5683 recently changed head).
5680
5684
5681 If you have just made a commit, that commit will be the tip. If
5685 If you have just made a commit, that commit will be the tip. If
5682 you have just pulled changes from another repository, the tip of
5686 you have just pulled changes from another repository, the tip of
5683 that repository becomes the current tip. The "tip" tag is special
5687 that repository becomes the current tip. The "tip" tag is special
5684 and cannot be renamed or assigned to a different changeset.
5688 and cannot be renamed or assigned to a different changeset.
5685
5689
5686 Returns 0 on success.
5690 Returns 0 on success.
5687 """
5691 """
5688 displayer = cmdutil.show_changeset(ui, repo, opts)
5692 displayer = cmdutil.show_changeset(ui, repo, opts)
5689 displayer.show(repo['tip'])
5693 displayer.show(repo['tip'])
5690 displayer.close()
5694 displayer.close()
5691
5695
5692 @command('unbundle',
5696 @command('unbundle',
5693 [('u', 'update', None,
5697 [('u', 'update', None,
5694 _('update to new branch head if changesets were unbundled'))],
5698 _('update to new branch head if changesets were unbundled'))],
5695 _('[-u] FILE...'))
5699 _('[-u] FILE...'))
5696 def unbundle(ui, repo, fname1, *fnames, **opts):
5700 def unbundle(ui, repo, fname1, *fnames, **opts):
5697 """apply one or more changegroup files
5701 """apply one or more changegroup files
5698
5702
5699 Apply one or more compressed changegroup files generated by the
5703 Apply one or more compressed changegroup files generated by the
5700 bundle command.
5704 bundle command.
5701
5705
5702 Returns 0 on success, 1 if an update has unresolved files.
5706 Returns 0 on success, 1 if an update has unresolved files.
5703 """
5707 """
5704 fnames = (fname1,) + fnames
5708 fnames = (fname1,) + fnames
5705
5709
5706 lock = repo.lock()
5710 lock = repo.lock()
5707 wc = repo['.']
5711 wc = repo['.']
5708 try:
5712 try:
5709 for fname in fnames:
5713 for fname in fnames:
5710 f = hg.openpath(ui, fname)
5714 f = hg.openpath(ui, fname)
5711 gen = changegroup.readbundle(f, fname)
5715 gen = changegroup.readbundle(f, fname)
5712 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5716 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5713 finally:
5717 finally:
5714 lock.release()
5718 lock.release()
5715 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5719 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5716 return postincoming(ui, repo, modheads, opts.get('update'), None)
5720 return postincoming(ui, repo, modheads, opts.get('update'), None)
5717
5721
5718 @command('^update|up|checkout|co',
5722 @command('^update|up|checkout|co',
5719 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5723 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5720 ('c', 'check', None,
5724 ('c', 'check', None,
5721 _('update across branches if no uncommitted changes')),
5725 _('update across branches if no uncommitted changes')),
5722 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5726 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5723 ('r', 'rev', '', _('revision'), _('REV'))],
5727 ('r', 'rev', '', _('revision'), _('REV'))],
5724 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5728 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5725 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5729 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5726 """update working directory (or switch revisions)
5730 """update working directory (or switch revisions)
5727
5731
5728 Update the repository's working directory to the specified
5732 Update the repository's working directory to the specified
5729 changeset. If no changeset is specified, update to the tip of the
5733 changeset. If no changeset is specified, update to the tip of the
5730 current named branch and move the current bookmark (see :hg:`help
5734 current named branch and move the current bookmark (see :hg:`help
5731 bookmarks`).
5735 bookmarks`).
5732
5736
5733 Update sets the working directory's parent revision to the specified
5737 Update sets the working directory's parent revision to the specified
5734 changeset (see :hg:`help parents`).
5738 changeset (see :hg:`help parents`).
5735
5739
5736 If the changeset is not a descendant or ancestor of the working
5740 If the changeset is not a descendant or ancestor of the working
5737 directory's parent, the update is aborted. With the -c/--check
5741 directory's parent, the update is aborted. With the -c/--check
5738 option, the working directory is checked for uncommitted changes; if
5742 option, the working directory is checked for uncommitted changes; if
5739 none are found, the working directory is updated to the specified
5743 none are found, the working directory is updated to the specified
5740 changeset.
5744 changeset.
5741
5745
5742 .. container:: verbose
5746 .. container:: verbose
5743
5747
5744 The following rules apply when the working directory contains
5748 The following rules apply when the working directory contains
5745 uncommitted changes:
5749 uncommitted changes:
5746
5750
5747 1. If neither -c/--check nor -C/--clean is specified, and if
5751 1. If neither -c/--check nor -C/--clean is specified, and if
5748 the requested changeset is an ancestor or descendant of
5752 the requested changeset is an ancestor or descendant of
5749 the working directory's parent, the uncommitted changes
5753 the working directory's parent, the uncommitted changes
5750 are merged into the requested changeset and the merged
5754 are merged into the requested changeset and the merged
5751 result is left uncommitted. If the requested changeset is
5755 result is left uncommitted. If the requested changeset is
5752 not an ancestor or descendant (that is, it is on another
5756 not an ancestor or descendant (that is, it is on another
5753 branch), the update is aborted and the uncommitted changes
5757 branch), the update is aborted and the uncommitted changes
5754 are preserved.
5758 are preserved.
5755
5759
5756 2. With the -c/--check option, the update is aborted and the
5760 2. With the -c/--check option, the update is aborted and the
5757 uncommitted changes are preserved.
5761 uncommitted changes are preserved.
5758
5762
5759 3. With the -C/--clean option, uncommitted changes are discarded and
5763 3. With the -C/--clean option, uncommitted changes are discarded and
5760 the working directory is updated to the requested changeset.
5764 the working directory is updated to the requested changeset.
5761
5765
5762 To cancel an uncommitted merge (and lose your changes), use
5766 To cancel an uncommitted merge (and lose your changes), use
5763 :hg:`update --clean .`.
5767 :hg:`update --clean .`.
5764
5768
5765 Use null as the changeset to remove the working directory (like
5769 Use null as the changeset to remove the working directory (like
5766 :hg:`clone -U`).
5770 :hg:`clone -U`).
5767
5771
5768 If you want to revert just one file to an older revision, use
5772 If you want to revert just one file to an older revision, use
5769 :hg:`revert [-r REV] NAME`.
5773 :hg:`revert [-r REV] NAME`.
5770
5774
5771 See :hg:`help dates` for a list of formats valid for -d/--date.
5775 See :hg:`help dates` for a list of formats valid for -d/--date.
5772
5776
5773 Returns 0 on success, 1 if there are unresolved files.
5777 Returns 0 on success, 1 if there are unresolved files.
5774 """
5778 """
5775 if rev and node:
5779 if rev and node:
5776 raise util.Abort(_("please specify just one revision"))
5780 raise util.Abort(_("please specify just one revision"))
5777
5781
5778 if rev is None or rev == '':
5782 if rev is None or rev == '':
5779 rev = node
5783 rev = node
5780
5784
5781 # with no argument, we also move the current bookmark, if any
5785 # with no argument, we also move the current bookmark, if any
5782 movemarkfrom = None
5786 movemarkfrom = None
5783 if rev is None:
5787 if rev is None:
5784 curmark = repo._bookmarkcurrent
5788 curmark = repo._bookmarkcurrent
5785 if bookmarks.iscurrent(repo):
5789 if bookmarks.iscurrent(repo):
5786 movemarkfrom = repo['.'].node()
5790 movemarkfrom = repo['.'].node()
5787 elif curmark:
5791 elif curmark:
5788 ui.status(_("updating to active bookmark %s\n") % curmark)
5792 ui.status(_("updating to active bookmark %s\n") % curmark)
5789 rev = curmark
5793 rev = curmark
5790
5794
5791 # if we defined a bookmark, we have to remember the original bookmark name
5795 # if we defined a bookmark, we have to remember the original bookmark name
5792 brev = rev
5796 brev = rev
5793 rev = scmutil.revsingle(repo, rev, rev).rev()
5797 rev = scmutil.revsingle(repo, rev, rev).rev()
5794
5798
5795 if check and clean:
5799 if check and clean:
5796 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5800 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5797
5801
5798 if date:
5802 if date:
5799 if rev is not None:
5803 if rev is not None:
5800 raise util.Abort(_("you can't specify a revision and a date"))
5804 raise util.Abort(_("you can't specify a revision and a date"))
5801 rev = cmdutil.finddate(ui, repo, date)
5805 rev = cmdutil.finddate(ui, repo, date)
5802
5806
5803 if check:
5807 if check:
5804 c = repo[None]
5808 c = repo[None]
5805 if c.dirty(merge=False, branch=False, missing=True):
5809 if c.dirty(merge=False, branch=False, missing=True):
5806 raise util.Abort(_("uncommitted local changes"))
5810 raise util.Abort(_("uncommitted local changes"))
5807 if rev is None:
5811 if rev is None:
5808 rev = repo[repo[None].branch()].rev()
5812 rev = repo[repo[None].branch()].rev()
5809 mergemod._checkunknown(repo, repo[None], repo[rev])
5813 mergemod._checkunknown(repo, repo[None], repo[rev])
5810
5814
5811 if clean:
5815 if clean:
5812 ret = hg.clean(repo, rev)
5816 ret = hg.clean(repo, rev)
5813 else:
5817 else:
5814 ret = hg.update(repo, rev)
5818 ret = hg.update(repo, rev)
5815
5819
5816 if not ret and movemarkfrom:
5820 if not ret and movemarkfrom:
5817 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5821 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5818 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5822 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5819 elif brev in repo._bookmarks:
5823 elif brev in repo._bookmarks:
5820 bookmarks.setcurrent(repo, brev)
5824 bookmarks.setcurrent(repo, brev)
5821 elif brev:
5825 elif brev:
5822 bookmarks.unsetcurrent(repo)
5826 bookmarks.unsetcurrent(repo)
5823
5827
5824 return ret
5828 return ret
5825
5829
5826 @command('verify', [])
5830 @command('verify', [])
5827 def verify(ui, repo):
5831 def verify(ui, repo):
5828 """verify the integrity of the repository
5832 """verify the integrity of the repository
5829
5833
5830 Verify the integrity of the current repository.
5834 Verify the integrity of the current repository.
5831
5835
5832 This will perform an extensive check of the repository's
5836 This will perform an extensive check of the repository's
5833 integrity, validating the hashes and checksums of each entry in
5837 integrity, validating the hashes and checksums of each entry in
5834 the changelog, manifest, and tracked files, as well as the
5838 the changelog, manifest, and tracked files, as well as the
5835 integrity of their crosslinks and indices.
5839 integrity of their crosslinks and indices.
5836
5840
5837 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5841 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5838 for more information about recovery from corruption of the
5842 for more information about recovery from corruption of the
5839 repository.
5843 repository.
5840
5844
5841 Returns 0 on success, 1 if errors are encountered.
5845 Returns 0 on success, 1 if errors are encountered.
5842 """
5846 """
5843 return hg.verify(repo)
5847 return hg.verify(repo)
5844
5848
5845 @command('version', [])
5849 @command('version', [])
5846 def version_(ui):
5850 def version_(ui):
5847 """output version and copyright information"""
5851 """output version and copyright information"""
5848 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5852 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5849 % util.version())
5853 % util.version())
5850 ui.status(_(
5854 ui.status(_(
5851 "(see http://mercurial.selenic.com for more information)\n"
5855 "(see http://mercurial.selenic.com for more information)\n"
5852 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5856 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5853 "This is free software; see the source for copying conditions. "
5857 "This is free software; see the source for copying conditions. "
5854 "There is NO\nwarranty; "
5858 "There is NO\nwarranty; "
5855 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5859 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5856 ))
5860 ))
5857
5861
5858 norepo = ("clone init version help debugcommands debugcomplete"
5862 norepo = ("clone init version help debugcommands debugcomplete"
5859 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5863 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5860 " debugknown debuggetbundle debugbundle")
5864 " debugknown debuggetbundle debugbundle")
5861 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5865 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5862 " debugdata debugindex debugindexdot debugrevlog")
5866 " debugdata debugindex debugindexdot debugrevlog")
5863 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5867 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5864 " remove resolve status debugwalk")
5868 " remove resolve status debugwalk")
@@ -1,538 +1,545 b''
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1
53 skipping ancestor revision 1
54 skipping ancestor revision 2
54 skipping ancestor revision 2
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1
60 skipping ancestor revision 1
61 skipping ancestor revision 2
61 skipping ancestor revision 2
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2
65 skipping ancestor revision 2
66 skipping ancestor revision 1
66 skipping ancestor revision 1
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: outstanding uncommitted changes
74 abort: outstanding uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79
79
80 $ hg graft 2 -u foo
80 $ hg graft 2 -u foo
81 grafting revision 2
81 grafting revision 2
82 merging a and b to b
82 merging a and b to b
83 $ hg export tip --git
83 $ hg export tip --git
84 # HG changeset patch
84 # HG changeset patch
85 # User foo
85 # User foo
86 # Date 0 0
86 # Date 0 0
87 # Thu Jan 01 00:00:00 1970 +0000
87 # Thu Jan 01 00:00:00 1970 +0000
88 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
88 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
89 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
89 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
90 2
90 2
91
91
92 diff --git a/a b/b
92 diff --git a/a b/b
93 rename from a
93 rename from a
94 rename to b
94 rename to b
95
95
96 Look for extra:source
96 Look for extra:source
97
97
98 $ hg log --debug -r tip
98 $ hg log --debug -r tip
99 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
99 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
100 tag: tip
100 tag: tip
101 phase: draft
101 phase: draft
102 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
102 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
103 parent: -1:0000000000000000000000000000000000000000
103 parent: -1:0000000000000000000000000000000000000000
104 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
104 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
105 user: foo
105 user: foo
106 date: Thu Jan 01 00:00:00 1970 +0000
106 date: Thu Jan 01 00:00:00 1970 +0000
107 files+: b
107 files+: b
108 files-: a
108 files-: a
109 extra: branch=default
109 extra: branch=default
110 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
110 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
111 description:
111 description:
112 2
112 2
113
113
114
114
115
115
116 Graft out of order, skipping a merge and a duplicate
116 Graft out of order, skipping a merge and a duplicate
117
117
118 $ hg graft 1 5 4 3 'merge()' 2 -n
118 $ hg graft 1 5 4 3 'merge()' 2 -n
119 skipping ungraftable merge revision 6
119 skipping ungraftable merge revision 6
120 skipping already grafted revision 2
120 skipping already grafted revision 2
121 grafting revision 1
121 grafting revision 1
122 grafting revision 5
122 grafting revision 5
123 grafting revision 4
123 grafting revision 4
124 grafting revision 3
124 grafting revision 3
125
125
126 $ hg graft 1 5 4 3 'merge()' 2 --debug
126 $ hg graft 1 5 4 3 'merge()' 2 --debug
127 skipping ungraftable merge revision 6
127 skipping ungraftable merge revision 6
128 scanning for duplicate grafts
128 scanning for duplicate grafts
129 skipping already grafted revision 2
129 skipping already grafted revision 2
130 grafting revision 1
130 grafting revision 1
131 searching for copies back to rev 1
131 searching for copies back to rev 1
132 unmatched files in local:
132 unmatched files in local:
133 b
133 b
134 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
134 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
135 src: 'a' -> dst: 'b' *
135 src: 'a' -> dst: 'b' *
136 checking for directory renames
136 checking for directory renames
137 resolving manifests
137 resolving manifests
138 branchmerge: True, force: True, partial: False
138 branchmerge: True, force: True, partial: False
139 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
139 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
140 b: local copied/moved to a -> m
140 b: local copied/moved to a -> m
141 preserving b for resolve of b
141 preserving b for resolve of b
142 updating: b 1/1 files (100.00%)
142 updating: b 1/1 files (100.00%)
143 picked tool 'internal:merge' for b (binary False symlink False)
143 picked tool 'internal:merge' for b (binary False symlink False)
144 merging b and a to b
144 merging b and a to b
145 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
145 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
146 premerge successful
146 premerge successful
147 b
147 b
148 grafting revision 5
148 grafting revision 5
149 searching for copies back to rev 1
149 searching for copies back to rev 1
150 resolving manifests
150 resolving manifests
151 branchmerge: True, force: True, partial: False
151 branchmerge: True, force: True, partial: False
152 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
152 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
153 e: remote is newer -> g
153 e: remote is newer -> g
154 getting e
154 getting e
155 updating: e 1/1 files (100.00%)
155 updating: e 1/1 files (100.00%)
156 e
156 e
157 grafting revision 4
157 grafting revision 4
158 searching for copies back to rev 1
158 searching for copies back to rev 1
159 resolving manifests
159 resolving manifests
160 branchmerge: True, force: True, partial: False
160 branchmerge: True, force: True, partial: False
161 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
161 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
162 d: remote is newer -> g
162 d: remote is newer -> g
163 e: versions differ -> m
163 e: versions differ -> m
164 preserving e for resolve of e
164 preserving e for resolve of e
165 getting d
165 getting d
166 updating: d 1/2 files (50.00%)
166 updating: d 1/2 files (50.00%)
167 updating: e 2/2 files (100.00%)
167 updating: e 2/2 files (100.00%)
168 picked tool 'internal:merge' for e (binary False symlink False)
168 picked tool 'internal:merge' for e (binary False symlink False)
169 merging e
169 merging e
170 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
170 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
171 warning: conflicts during merge.
171 warning: conflicts during merge.
172 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
172 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
173 abort: unresolved conflicts, can't continue
173 abort: unresolved conflicts, can't continue
174 (use hg resolve and hg graft --continue)
174 (use hg resolve and hg graft --continue)
175 [255]
175 [255]
176
176
177 Commit while interrupted should fail:
178
179 $ hg ci -m 'commit interrupted graft'
180 abort: cannot commit an interrupted graft operation
181 (use "hg graft -c" to continue graft)
182 [255]
183
177 Continue without resolve should fail:
184 Continue without resolve should fail:
178
185
179 $ hg graft -c
186 $ hg graft -c
180 grafting revision 4
187 grafting revision 4
181 abort: unresolved merge conflicts (see hg help resolve)
188 abort: unresolved merge conflicts (see hg help resolve)
182 [255]
189 [255]
183
190
184 Fix up:
191 Fix up:
185
192
186 $ echo b > e
193 $ echo b > e
187 $ hg resolve -m e
194 $ hg resolve -m e
188
195
189 Continue with a revision should fail:
196 Continue with a revision should fail:
190
197
191 $ hg graft -c 6
198 $ hg graft -c 6
192 abort: can't specify --continue and revisions
199 abort: can't specify --continue and revisions
193 [255]
200 [255]
194
201
195 $ hg graft -c -r 6
202 $ hg graft -c -r 6
196 abort: can't specify --continue and revisions
203 abort: can't specify --continue and revisions
197 [255]
204 [255]
198
205
199 Continue for real, clobber usernames
206 Continue for real, clobber usernames
200
207
201 $ hg graft -c -U
208 $ hg graft -c -U
202 grafting revision 4
209 grafting revision 4
203 grafting revision 3
210 grafting revision 3
204
211
205 Compare with original:
212 Compare with original:
206
213
207 $ hg diff -r 6
214 $ hg diff -r 6
208 $ hg status --rev 0:. -C
215 $ hg status --rev 0:. -C
209 M d
216 M d
210 M e
217 M e
211 A b
218 A b
212 a
219 a
213 A c
220 A c
214 a
221 a
215 R a
222 R a
216
223
217 View graph:
224 View graph:
218
225
219 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
226 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
220 @ test@11.draft: 3
227 @ test@11.draft: 3
221 |
228 |
222 o test@10.draft: 4
229 o test@10.draft: 4
223 |
230 |
224 o test@9.draft: 5
231 o test@9.draft: 5
225 |
232 |
226 o bar@8.draft: 1
233 o bar@8.draft: 1
227 |
234 |
228 o foo@7.draft: 2
235 o foo@7.draft: 2
229 |
236 |
230 | o test@6.secret: 6
237 | o test@6.secret: 6
231 | |\
238 | |\
232 | | o test@5.draft: 5
239 | | o test@5.draft: 5
233 | | |
240 | | |
234 | o | test@4.draft: 4
241 | o | test@4.draft: 4
235 | |/
242 | |/
236 | o baz@3.public: 3
243 | o baz@3.public: 3
237 | |
244 | |
238 | o test@2.public: 2
245 | o test@2.public: 2
239 | |
246 | |
240 | o bar@1.public: 1
247 | o bar@1.public: 1
241 |/
248 |/
242 o test@0.public: 0
249 o test@0.public: 0
243
250
244 Graft again onto another branch should preserve the original source
251 Graft again onto another branch should preserve the original source
245 $ hg up -q 0
252 $ hg up -q 0
246 $ echo 'g'>g
253 $ echo 'g'>g
247 $ hg add g
254 $ hg add g
248 $ hg ci -m 7
255 $ hg ci -m 7
249 created new head
256 created new head
250 $ hg graft 7
257 $ hg graft 7
251 grafting revision 7
258 grafting revision 7
252
259
253 $ hg log -r 7 --template '{rev}:{node}\n'
260 $ hg log -r 7 --template '{rev}:{node}\n'
254 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
261 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
255 $ hg log -r 2 --template '{rev}:{node}\n'
262 $ hg log -r 2 --template '{rev}:{node}\n'
256 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
263 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
257
264
258 $ hg log --debug -r tip
265 $ hg log --debug -r tip
259 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
266 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
260 tag: tip
267 tag: tip
261 phase: draft
268 phase: draft
262 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
269 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
263 parent: -1:0000000000000000000000000000000000000000
270 parent: -1:0000000000000000000000000000000000000000
264 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
271 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
265 user: foo
272 user: foo
266 date: Thu Jan 01 00:00:00 1970 +0000
273 date: Thu Jan 01 00:00:00 1970 +0000
267 files+: b
274 files+: b
268 files-: a
275 files-: a
269 extra: branch=default
276 extra: branch=default
270 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
277 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
271 description:
278 description:
272 2
279 2
273
280
274
281
275 Disallow grafting an already grafted cset onto its original branch
282 Disallow grafting an already grafted cset onto its original branch
276 $ hg up -q 6
283 $ hg up -q 6
277 $ hg graft 7
284 $ hg graft 7
278 skipping already grafted revision 7 (was grafted from 2)
285 skipping already grafted revision 7 (was grafted from 2)
279 [255]
286 [255]
280
287
281 Disallow grafting already grafted csets with the same origin onto each other
288 Disallow grafting already grafted csets with the same origin onto each other
282 $ hg up -q 13
289 $ hg up -q 13
283 $ hg graft 2
290 $ hg graft 2
284 skipping already grafted revision 2
291 skipping already grafted revision 2
285 [255]
292 [255]
286 $ hg graft 7
293 $ hg graft 7
287 skipping already grafted revision 7 (same origin 2)
294 skipping already grafted revision 7 (same origin 2)
288 [255]
295 [255]
289
296
290 $ hg up -q 7
297 $ hg up -q 7
291 $ hg graft 2
298 $ hg graft 2
292 skipping already grafted revision 2
299 skipping already grafted revision 2
293 [255]
300 [255]
294 $ hg graft tip
301 $ hg graft tip
295 skipping already grafted revision 13 (same origin 2)
302 skipping already grafted revision 13 (same origin 2)
296 [255]
303 [255]
297
304
298 Graft with --log
305 Graft with --log
299
306
300 $ hg up -Cq 1
307 $ hg up -Cq 1
301 $ hg graft 3 --log -u foo
308 $ hg graft 3 --log -u foo
302 grafting revision 3
309 grafting revision 3
303 warning: can't find ancestor for 'c' copied from 'b'!
310 warning: can't find ancestor for 'c' copied from 'b'!
304 $ hg log --template '{rev} {parents} {desc}\n' -r tip
311 $ hg log --template '{rev} {parents} {desc}\n' -r tip
305 14 1:5d205f8b35b6 3
312 14 1:5d205f8b35b6 3
306 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
313 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
307
314
308 Resolve conflicted graft
315 Resolve conflicted graft
309 $ hg up -q 0
316 $ hg up -q 0
310 $ echo b > a
317 $ echo b > a
311 $ hg ci -m 8
318 $ hg ci -m 8
312 created new head
319 created new head
313 $ echo a > a
320 $ echo a > a
314 $ hg ci -m 9
321 $ hg ci -m 9
315 $ hg graft 1 --tool internal:fail
322 $ hg graft 1 --tool internal:fail
316 grafting revision 1
323 grafting revision 1
317 abort: unresolved conflicts, can't continue
324 abort: unresolved conflicts, can't continue
318 (use hg resolve and hg graft --continue)
325 (use hg resolve and hg graft --continue)
319 [255]
326 [255]
320 $ hg resolve --all
327 $ hg resolve --all
321 merging a
328 merging a
322 $ hg graft -c
329 $ hg graft -c
323 grafting revision 1
330 grafting revision 1
324 $ hg export tip --git
331 $ hg export tip --git
325 # HG changeset patch
332 # HG changeset patch
326 # User bar
333 # User bar
327 # Date 0 0
334 # Date 0 0
328 # Thu Jan 01 00:00:00 1970 +0000
335 # Thu Jan 01 00:00:00 1970 +0000
329 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
336 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
330 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
337 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
331 1
338 1
332
339
333 diff --git a/a b/a
340 diff --git a/a b/a
334 --- a/a
341 --- a/a
335 +++ b/a
342 +++ b/a
336 @@ -1,1 +1,1 @@
343 @@ -1,1 +1,1 @@
337 -a
344 -a
338 +b
345 +b
339
346
340 Resolve conflicted graft with rename
347 Resolve conflicted graft with rename
341 $ echo c > a
348 $ echo c > a
342 $ hg ci -m 10
349 $ hg ci -m 10
343 $ hg graft 2 --tool internal:fail
350 $ hg graft 2 --tool internal:fail
344 grafting revision 2
351 grafting revision 2
345 abort: unresolved conflicts, can't continue
352 abort: unresolved conflicts, can't continue
346 (use hg resolve and hg graft --continue)
353 (use hg resolve and hg graft --continue)
347 [255]
354 [255]
348 $ hg resolve --all
355 $ hg resolve --all
349 merging a and b to b
356 merging a and b to b
350 $ hg graft -c
357 $ hg graft -c
351 grafting revision 2
358 grafting revision 2
352 $ hg export tip --git
359 $ hg export tip --git
353 # HG changeset patch
360 # HG changeset patch
354 # User test
361 # User test
355 # Date 0 0
362 # Date 0 0
356 # Thu Jan 01 00:00:00 1970 +0000
363 # Thu Jan 01 00:00:00 1970 +0000
357 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
364 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
358 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
365 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
359 2
366 2
360
367
361 diff --git a/a b/b
368 diff --git a/a b/b
362 rename from a
369 rename from a
363 rename to b
370 rename to b
364
371
365 Test simple origin(), with and without args
372 Test simple origin(), with and without args
366 $ hg log -r 'origin()'
373 $ hg log -r 'origin()'
367 changeset: 1:5d205f8b35b6
374 changeset: 1:5d205f8b35b6
368 user: bar
375 user: bar
369 date: Thu Jan 01 00:00:00 1970 +0000
376 date: Thu Jan 01 00:00:00 1970 +0000
370 summary: 1
377 summary: 1
371
378
372 changeset: 2:5c095ad7e90f
379 changeset: 2:5c095ad7e90f
373 user: test
380 user: test
374 date: Thu Jan 01 00:00:00 1970 +0000
381 date: Thu Jan 01 00:00:00 1970 +0000
375 summary: 2
382 summary: 2
376
383
377 changeset: 3:4c60f11aa304
384 changeset: 3:4c60f11aa304
378 user: baz
385 user: baz
379 date: Thu Jan 01 00:00:00 1970 +0000
386 date: Thu Jan 01 00:00:00 1970 +0000
380 summary: 3
387 summary: 3
381
388
382 changeset: 4:9c233e8e184d
389 changeset: 4:9c233e8e184d
383 user: test
390 user: test
384 date: Thu Jan 01 00:00:00 1970 +0000
391 date: Thu Jan 01 00:00:00 1970 +0000
385 summary: 4
392 summary: 4
386
393
387 changeset: 5:97f8bfe72746
394 changeset: 5:97f8bfe72746
388 branch: stable
395 branch: stable
389 parent: 3:4c60f11aa304
396 parent: 3:4c60f11aa304
390 user: test
397 user: test
391 date: Thu Jan 01 00:00:00 1970 +0000
398 date: Thu Jan 01 00:00:00 1970 +0000
392 summary: 5
399 summary: 5
393
400
394 $ hg log -r 'origin(7)'
401 $ hg log -r 'origin(7)'
395 changeset: 2:5c095ad7e90f
402 changeset: 2:5c095ad7e90f
396 user: test
403 user: test
397 date: Thu Jan 01 00:00:00 1970 +0000
404 date: Thu Jan 01 00:00:00 1970 +0000
398 summary: 2
405 summary: 2
399
406
400 Now transplant a graft to test following through copies
407 Now transplant a graft to test following through copies
401 $ hg up -q 0
408 $ hg up -q 0
402 $ hg branch -q dev
409 $ hg branch -q dev
403 $ hg ci -qm "dev branch"
410 $ hg ci -qm "dev branch"
404 $ hg --config extensions.transplant= transplant -q 7
411 $ hg --config extensions.transplant= transplant -q 7
405 $ hg log -r 'origin(.)'
412 $ hg log -r 'origin(.)'
406 changeset: 2:5c095ad7e90f
413 changeset: 2:5c095ad7e90f
407 user: test
414 user: test
408 date: Thu Jan 01 00:00:00 1970 +0000
415 date: Thu Jan 01 00:00:00 1970 +0000
409 summary: 2
416 summary: 2
410
417
411 Test simple destination
418 Test simple destination
412 $ hg log -r 'destination()'
419 $ hg log -r 'destination()'
413 changeset: 7:ef0ef43d49e7
420 changeset: 7:ef0ef43d49e7
414 parent: 0:68795b066622
421 parent: 0:68795b066622
415 user: foo
422 user: foo
416 date: Thu Jan 01 00:00:00 1970 +0000
423 date: Thu Jan 01 00:00:00 1970 +0000
417 summary: 2
424 summary: 2
418
425
419 changeset: 8:6b9e5368ca4e
426 changeset: 8:6b9e5368ca4e
420 user: bar
427 user: bar
421 date: Thu Jan 01 00:00:00 1970 +0000
428 date: Thu Jan 01 00:00:00 1970 +0000
422 summary: 1
429 summary: 1
423
430
424 changeset: 9:1905859650ec
431 changeset: 9:1905859650ec
425 user: test
432 user: test
426 date: Thu Jan 01 00:00:00 1970 +0000
433 date: Thu Jan 01 00:00:00 1970 +0000
427 summary: 5
434 summary: 5
428
435
429 changeset: 10:52dc0b4c6907
436 changeset: 10:52dc0b4c6907
430 user: test
437 user: test
431 date: Thu Jan 01 00:00:00 1970 +0000
438 date: Thu Jan 01 00:00:00 1970 +0000
432 summary: 4
439 summary: 4
433
440
434 changeset: 11:882b35362a6b
441 changeset: 11:882b35362a6b
435 user: test
442 user: test
436 date: Thu Jan 01 00:00:00 1970 +0000
443 date: Thu Jan 01 00:00:00 1970 +0000
437 summary: 3
444 summary: 3
438
445
439 changeset: 13:9db0f28fd374
446 changeset: 13:9db0f28fd374
440 user: foo
447 user: foo
441 date: Thu Jan 01 00:00:00 1970 +0000
448 date: Thu Jan 01 00:00:00 1970 +0000
442 summary: 2
449 summary: 2
443
450
444 changeset: 14:f64defefacee
451 changeset: 14:f64defefacee
445 parent: 1:5d205f8b35b6
452 parent: 1:5d205f8b35b6
446 user: foo
453 user: foo
447 date: Thu Jan 01 00:00:00 1970 +0000
454 date: Thu Jan 01 00:00:00 1970 +0000
448 summary: 3
455 summary: 3
449
456
450 changeset: 17:64ecd9071ce8
457 changeset: 17:64ecd9071ce8
451 user: bar
458 user: bar
452 date: Thu Jan 01 00:00:00 1970 +0000
459 date: Thu Jan 01 00:00:00 1970 +0000
453 summary: 1
460 summary: 1
454
461
455 changeset: 19:2e80e1351d6e
462 changeset: 19:2e80e1351d6e
456 user: test
463 user: test
457 date: Thu Jan 01 00:00:00 1970 +0000
464 date: Thu Jan 01 00:00:00 1970 +0000
458 summary: 2
465 summary: 2
459
466
460 changeset: 21:7e61b508e709
467 changeset: 21:7e61b508e709
461 branch: dev
468 branch: dev
462 tag: tip
469 tag: tip
463 user: foo
470 user: foo
464 date: Thu Jan 01 00:00:00 1970 +0000
471 date: Thu Jan 01 00:00:00 1970 +0000
465 summary: 2
472 summary: 2
466
473
467 $ hg log -r 'destination(2)'
474 $ hg log -r 'destination(2)'
468 changeset: 7:ef0ef43d49e7
475 changeset: 7:ef0ef43d49e7
469 parent: 0:68795b066622
476 parent: 0:68795b066622
470 user: foo
477 user: foo
471 date: Thu Jan 01 00:00:00 1970 +0000
478 date: Thu Jan 01 00:00:00 1970 +0000
472 summary: 2
479 summary: 2
473
480
474 changeset: 13:9db0f28fd374
481 changeset: 13:9db0f28fd374
475 user: foo
482 user: foo
476 date: Thu Jan 01 00:00:00 1970 +0000
483 date: Thu Jan 01 00:00:00 1970 +0000
477 summary: 2
484 summary: 2
478
485
479 changeset: 19:2e80e1351d6e
486 changeset: 19:2e80e1351d6e
480 user: test
487 user: test
481 date: Thu Jan 01 00:00:00 1970 +0000
488 date: Thu Jan 01 00:00:00 1970 +0000
482 summary: 2
489 summary: 2
483
490
484 changeset: 21:7e61b508e709
491 changeset: 21:7e61b508e709
485 branch: dev
492 branch: dev
486 tag: tip
493 tag: tip
487 user: foo
494 user: foo
488 date: Thu Jan 01 00:00:00 1970 +0000
495 date: Thu Jan 01 00:00:00 1970 +0000
489 summary: 2
496 summary: 2
490
497
491 Transplants of grafts can find a destination...
498 Transplants of grafts can find a destination...
492 $ hg log -r 'destination(7)'
499 $ hg log -r 'destination(7)'
493 changeset: 21:7e61b508e709
500 changeset: 21:7e61b508e709
494 branch: dev
501 branch: dev
495 tag: tip
502 tag: tip
496 user: foo
503 user: foo
497 date: Thu Jan 01 00:00:00 1970 +0000
504 date: Thu Jan 01 00:00:00 1970 +0000
498 summary: 2
505 summary: 2
499
506
500 ... grafts of grafts unfortunately can't
507 ... grafts of grafts unfortunately can't
501 $ hg graft -q 13
508 $ hg graft -q 13
502 $ hg log -r 'destination(13)'
509 $ hg log -r 'destination(13)'
503 All copies of a cset
510 All copies of a cset
504 $ hg log -r 'origin(13) or destination(origin(13))'
511 $ hg log -r 'origin(13) or destination(origin(13))'
505 changeset: 2:5c095ad7e90f
512 changeset: 2:5c095ad7e90f
506 user: test
513 user: test
507 date: Thu Jan 01 00:00:00 1970 +0000
514 date: Thu Jan 01 00:00:00 1970 +0000
508 summary: 2
515 summary: 2
509
516
510 changeset: 7:ef0ef43d49e7
517 changeset: 7:ef0ef43d49e7
511 parent: 0:68795b066622
518 parent: 0:68795b066622
512 user: foo
519 user: foo
513 date: Thu Jan 01 00:00:00 1970 +0000
520 date: Thu Jan 01 00:00:00 1970 +0000
514 summary: 2
521 summary: 2
515
522
516 changeset: 13:9db0f28fd374
523 changeset: 13:9db0f28fd374
517 user: foo
524 user: foo
518 date: Thu Jan 01 00:00:00 1970 +0000
525 date: Thu Jan 01 00:00:00 1970 +0000
519 summary: 2
526 summary: 2
520
527
521 changeset: 19:2e80e1351d6e
528 changeset: 19:2e80e1351d6e
522 user: test
529 user: test
523 date: Thu Jan 01 00:00:00 1970 +0000
530 date: Thu Jan 01 00:00:00 1970 +0000
524 summary: 2
531 summary: 2
525
532
526 changeset: 21:7e61b508e709
533 changeset: 21:7e61b508e709
527 branch: dev
534 branch: dev
528 user: foo
535 user: foo
529 date: Thu Jan 01 00:00:00 1970 +0000
536 date: Thu Jan 01 00:00:00 1970 +0000
530 summary: 2
537 summary: 2
531
538
532 changeset: 22:1313d0a825e2
539 changeset: 22:1313d0a825e2
533 branch: dev
540 branch: dev
534 tag: tip
541 tag: tip
535 user: foo
542 user: foo
536 date: Thu Jan 01 00:00:00 1970 +0000
543 date: Thu Jan 01 00:00:00 1970 +0000
537 summary: 2
544 summary: 2
538
545
General Comments 0
You need to be logged in to leave comments. Login now