##// END OF EJS Templates
bookmarks: allow bookmark command to take multiple arguments...
Kevin Bullock -
r19147:5b183548 default
parent child Browse files
Show More
@@ -1,5860 +1,5872 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 [OPTIONS]... [NAME]...'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, *names, **opts):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
772 '''track a line of development with movable markers
774
773
775 Bookmarks are pointers to certain commits that move when committing.
774 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
775 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
776 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
777 :hg:`update NAME` to update to a given bookmark.
779
778
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
779 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
780 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
781 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
782 the bookmark is assigned to that revision.
784
783
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
784 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
785 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
786 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
787 the bookmarks extension must be enabled.
789
788
790 If you set a bookmark called '@', new clones of the repository will
789 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
790 have that revision checked out (and the bookmark made active) by
792 default.
791 default.
793
792
794 With -i/--inactive, the new bookmark will not be made the active
793 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
794 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
795 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
796 current active bookmark will be marked inactive.
798 '''
797 '''
798 force = opts.get('force')
799 rev = opts.get('rev')
800 delete = opts.get('delete')
801 rename = opts.get('rename')
802 inactive = opts.get('inactive')
803
799 hexfn = ui.debugflag and hex or short
804 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
805 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
806 cur = repo.changectx('.').node()
802
807
803 def checkformat(mark):
808 def checkformat(mark):
804 mark = mark.strip()
809 mark = mark.strip()
805 if not mark:
810 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
811 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
812 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
813 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
814 return mark
810
815
811 def checkconflict(repo, mark, force=False, target=None):
816 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
817 if mark in marks and not force:
813 if target:
818 if target:
814 if marks[mark] == target and target == cur:
819 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
820 # re-activating a bookmark
816 return
821 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
822 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
823 bmctx = repo[marks[mark]]
819 divs = [repo[b].node() for b in marks
824 divs = [repo[b].node() for b in marks
820 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
825 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
821
826
822 # allow resolving a single divergent bookmark even if moving
827 # allow resolving a single divergent bookmark even if moving
823 # the bookmark across branches when a revision is specified
828 # the bookmark across branches when a revision is specified
824 # that contains a divergent bookmark
829 # that contains a divergent bookmark
825 if bmctx.rev() not in anc and target in divs:
830 if bmctx.rev() not in anc and target in divs:
826 bookmarks.deletedivergent(repo, [target], mark)
831 bookmarks.deletedivergent(repo, [target], mark)
827 return
832 return
828
833
829 deletefrom = [b for b in divs
834 deletefrom = [b for b in divs
830 if repo[b].rev() in anc or b == target]
835 if repo[b].rev() in anc or b == target]
831 bookmarks.deletedivergent(repo, deletefrom, mark)
836 bookmarks.deletedivergent(repo, deletefrom, mark)
832 if bmctx.rev() in anc:
837 if bmctx.rev() in anc:
833 ui.status(_("moving bookmark '%s' forward from %s\n") %
838 ui.status(_("moving bookmark '%s' forward from %s\n") %
834 (mark, short(bmctx.node())))
839 (mark, short(bmctx.node())))
835 return
840 return
836 raise util.Abort(_("bookmark '%s' already exists "
841 raise util.Abort(_("bookmark '%s' already exists "
837 "(use -f to force)") % mark)
842 "(use -f to force)") % mark)
838 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
843 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
839 and not force):
844 and not force):
840 raise util.Abort(
845 raise util.Abort(
841 _("a bookmark cannot have the name of an existing branch"))
846 _("a bookmark cannot have the name of an existing branch"))
842
847
843 if delete and rename:
848 if delete and rename:
844 raise util.Abort(_("--delete and --rename are incompatible"))
849 raise util.Abort(_("--delete and --rename are incompatible"))
845 if delete and rev:
850 if delete and rev:
846 raise util.Abort(_("--rev is incompatible with --delete"))
851 raise util.Abort(_("--rev is incompatible with --delete"))
847 if rename and rev:
852 if rename and rev:
848 raise util.Abort(_("--rev is incompatible with --rename"))
853 raise util.Abort(_("--rev is incompatible with --rename"))
849 if mark is None and (delete or rev):
854 if not names and (delete or rev):
850 raise util.Abort(_("bookmark name required"))
855 raise util.Abort(_("bookmark name required"))
851
856
852 if delete:
857 if delete:
853 if mark not in marks:
858 for mark in names:
854 raise util.Abort(_("bookmark '%s' does not exist") % mark)
859 if mark not in marks:
855 if mark == repo._bookmarkcurrent:
860 raise util.Abort(_("bookmark '%s' does not exist") % mark)
856 bookmarks.setcurrent(repo, None)
861 if mark == repo._bookmarkcurrent:
857 del marks[mark]
862 bookmarks.setcurrent(repo, None)
863 del marks[mark]
858 marks.write()
864 marks.write()
859
865
860 elif rename:
866 elif rename:
861 if mark is None:
867 if not names:
862 raise util.Abort(_("new bookmark name required"))
868 raise util.Abort(_("new bookmark name required"))
863 mark = checkformat(mark)
869 elif len(names) > 1:
870 raise util.Abort(_("only one new bookmark name allowed"))
871 mark = checkformat(names[0])
864 if rename not in marks:
872 if rename not in marks:
865 raise util.Abort(_("bookmark '%s' does not exist") % rename)
873 raise util.Abort(_("bookmark '%s' does not exist") % rename)
866 checkconflict(repo, mark, force)
874 checkconflict(repo, mark, force)
867 marks[mark] = marks[rename]
875 marks[mark] = marks[rename]
868 if repo._bookmarkcurrent == rename and not inactive:
876 if repo._bookmarkcurrent == rename and not inactive:
869 bookmarks.setcurrent(repo, mark)
877 bookmarks.setcurrent(repo, mark)
870 del marks[rename]
878 del marks[rename]
871 marks.write()
879 marks.write()
872
880
873 elif mark is not None:
881 elif names:
874 mark = checkformat(mark)
882 newact = None
875 if inactive and mark == repo._bookmarkcurrent:
883 for mark in names:
876 bookmarks.setcurrent(repo, None)
884 mark = checkformat(mark)
877 return
885 if newact is None:
878 tgt = cur
886 newact = mark
879 if rev:
887 if inactive and mark == repo._bookmarkcurrent:
880 tgt = scmutil.revsingle(repo, rev).node()
888 bookmarks.setcurrent(repo, None)
881 checkconflict(repo, mark, force, tgt)
889 return
882 marks[mark] = tgt
890 tgt = cur
883 if not inactive and cur == marks[mark] and not rev:
891 if rev:
884 bookmarks.setcurrent(repo, mark)
892 tgt = scmutil.revsingle(repo, rev).node()
885 elif cur != tgt and mark == repo._bookmarkcurrent:
893 checkconflict(repo, mark, force, tgt)
894 marks[mark] = tgt
895 if not inactive and cur == marks[newact] and not rev:
896 bookmarks.setcurrent(repo, newact)
897 elif cur != tgt and newact == repo._bookmarkcurrent:
886 bookmarks.setcurrent(repo, None)
898 bookmarks.setcurrent(repo, None)
887 marks.write()
899 marks.write()
888
900
889 # Same message whether trying to deactivate the current bookmark (-i
901 # Same message whether trying to deactivate the current bookmark (-i
890 # with no NAME) or listing bookmarks
902 # with no NAME) or listing bookmarks
891 elif len(marks) == 0:
903 elif len(marks) == 0:
892 ui.status(_("no bookmarks set\n"))
904 ui.status(_("no bookmarks set\n"))
893
905
894 elif inactive:
906 elif inactive:
895 if not repo._bookmarkcurrent:
907 if not repo._bookmarkcurrent:
896 ui.status(_("no active bookmark\n"))
908 ui.status(_("no active bookmark\n"))
897 else:
909 else:
898 bookmarks.setcurrent(repo, None)
910 bookmarks.setcurrent(repo, None)
899
911
900 else: # show bookmarks
912 else: # show bookmarks
901 for bmark, n in sorted(marks.iteritems()):
913 for bmark, n in sorted(marks.iteritems()):
902 current = repo._bookmarkcurrent
914 current = repo._bookmarkcurrent
903 if bmark == current:
915 if bmark == current:
904 prefix, label = '*', 'bookmarks.current'
916 prefix, label = '*', 'bookmarks.current'
905 else:
917 else:
906 prefix, label = ' ', ''
918 prefix, label = ' ', ''
907
919
908 if ui.quiet:
920 if ui.quiet:
909 ui.write("%s\n" % bmark, label=label)
921 ui.write("%s\n" % bmark, label=label)
910 else:
922 else:
911 ui.write(" %s %-25s %d:%s\n" % (
923 ui.write(" %s %-25s %d:%s\n" % (
912 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
924 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
913 label=label)
925 label=label)
914
926
915 @command('branch',
927 @command('branch',
916 [('f', 'force', None,
928 [('f', 'force', None,
917 _('set branch name even if it shadows an existing branch')),
929 _('set branch name even if it shadows an existing branch')),
918 ('C', 'clean', None, _('reset branch name to parent branch name'))],
930 ('C', 'clean', None, _('reset branch name to parent branch name'))],
919 _('[-fC] [NAME]'))
931 _('[-fC] [NAME]'))
920 def branch(ui, repo, label=None, **opts):
932 def branch(ui, repo, label=None, **opts):
921 """set or show the current branch name
933 """set or show the current branch name
922
934
923 .. note::
935 .. note::
924 Branch names are permanent and global. Use :hg:`bookmark` to create a
936 Branch names are permanent and global. Use :hg:`bookmark` to create a
925 light-weight bookmark instead. See :hg:`help glossary` for more
937 light-weight bookmark instead. See :hg:`help glossary` for more
926 information about named branches and bookmarks.
938 information about named branches and bookmarks.
927
939
928 With no argument, show the current branch name. With one argument,
940 With no argument, show the current branch name. With one argument,
929 set the working directory branch name (the branch will not exist
941 set the working directory branch name (the branch will not exist
930 in the repository until the next commit). Standard practice
942 in the repository until the next commit). Standard practice
931 recommends that primary development take place on the 'default'
943 recommends that primary development take place on the 'default'
932 branch.
944 branch.
933
945
934 Unless -f/--force is specified, branch will not let you set a
946 Unless -f/--force is specified, branch will not let you set a
935 branch name that already exists, even if it's inactive.
947 branch name that already exists, even if it's inactive.
936
948
937 Use -C/--clean to reset the working directory branch to that of
949 Use -C/--clean to reset the working directory branch to that of
938 the parent of the working directory, negating a previous branch
950 the parent of the working directory, negating a previous branch
939 change.
951 change.
940
952
941 Use the command :hg:`update` to switch to an existing branch. Use
953 Use the command :hg:`update` to switch to an existing branch. Use
942 :hg:`commit --close-branch` to mark this branch as closed.
954 :hg:`commit --close-branch` to mark this branch as closed.
943
955
944 Returns 0 on success.
956 Returns 0 on success.
945 """
957 """
946 if not opts.get('clean') and not label:
958 if not opts.get('clean') and not label:
947 ui.write("%s\n" % repo.dirstate.branch())
959 ui.write("%s\n" % repo.dirstate.branch())
948 return
960 return
949
961
950 wlock = repo.wlock()
962 wlock = repo.wlock()
951 try:
963 try:
952 if opts.get('clean'):
964 if opts.get('clean'):
953 label = repo[None].p1().branch()
965 label = repo[None].p1().branch()
954 repo.dirstate.setbranch(label)
966 repo.dirstate.setbranch(label)
955 ui.status(_('reset working directory to branch %s\n') % label)
967 ui.status(_('reset working directory to branch %s\n') % label)
956 elif label:
968 elif label:
957 if not opts.get('force') and label in repo.branchmap():
969 if not opts.get('force') and label in repo.branchmap():
958 if label not in [p.branch() for p in repo.parents()]:
970 if label not in [p.branch() for p in repo.parents()]:
959 raise util.Abort(_('a branch of the same name already'
971 raise util.Abort(_('a branch of the same name already'
960 ' exists'),
972 ' exists'),
961 # i18n: "it" refers to an existing branch
973 # i18n: "it" refers to an existing branch
962 hint=_("use 'hg update' to switch to it"))
974 hint=_("use 'hg update' to switch to it"))
963 scmutil.checknewlabel(repo, label, 'branch')
975 scmutil.checknewlabel(repo, label, 'branch')
964 repo.dirstate.setbranch(label)
976 repo.dirstate.setbranch(label)
965 ui.status(_('marked working directory as branch %s\n') % label)
977 ui.status(_('marked working directory as branch %s\n') % label)
966 ui.status(_('(branches are permanent and global, '
978 ui.status(_('(branches are permanent and global, '
967 'did you want a bookmark?)\n'))
979 'did you want a bookmark?)\n'))
968 finally:
980 finally:
969 wlock.release()
981 wlock.release()
970
982
971 @command('branches',
983 @command('branches',
972 [('a', 'active', False, _('show only branches that have unmerged heads')),
984 [('a', 'active', False, _('show only branches that have unmerged heads')),
973 ('c', 'closed', False, _('show normal and closed branches'))],
985 ('c', 'closed', False, _('show normal and closed branches'))],
974 _('[-ac]'))
986 _('[-ac]'))
975 def branches(ui, repo, active=False, closed=False):
987 def branches(ui, repo, active=False, closed=False):
976 """list repository named branches
988 """list repository named branches
977
989
978 List the repository's named branches, indicating which ones are
990 List the repository's named branches, indicating which ones are
979 inactive. If -c/--closed is specified, also list branches which have
991 inactive. If -c/--closed is specified, also list branches which have
980 been marked closed (see :hg:`commit --close-branch`).
992 been marked closed (see :hg:`commit --close-branch`).
981
993
982 If -a/--active is specified, only show active branches. A branch
994 If -a/--active is specified, only show active branches. A branch
983 is considered active if it contains repository heads.
995 is considered active if it contains repository heads.
984
996
985 Use the command :hg:`update` to switch to an existing branch.
997 Use the command :hg:`update` to switch to an existing branch.
986
998
987 Returns 0.
999 Returns 0.
988 """
1000 """
989
1001
990 hexfunc = ui.debugflag and hex or short
1002 hexfunc = ui.debugflag and hex or short
991
1003
992 activebranches = set([repo[n].branch() for n in repo.heads()])
1004 activebranches = set([repo[n].branch() for n in repo.heads()])
993 branches = []
1005 branches = []
994 for tag, heads in repo.branchmap().iteritems():
1006 for tag, heads in repo.branchmap().iteritems():
995 for h in reversed(heads):
1007 for h in reversed(heads):
996 ctx = repo[h]
1008 ctx = repo[h]
997 isopen = not ctx.closesbranch()
1009 isopen = not ctx.closesbranch()
998 if isopen:
1010 if isopen:
999 tip = ctx
1011 tip = ctx
1000 break
1012 break
1001 else:
1013 else:
1002 tip = repo[heads[-1]]
1014 tip = repo[heads[-1]]
1003 isactive = tag in activebranches and isopen
1015 isactive = tag in activebranches and isopen
1004 branches.append((tip, isactive, isopen))
1016 branches.append((tip, isactive, isopen))
1005 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1017 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1006 reverse=True)
1018 reverse=True)
1007
1019
1008 for ctx, isactive, isopen in branches:
1020 for ctx, isactive, isopen in branches:
1009 if (not active) or isactive:
1021 if (not active) or isactive:
1010 if isactive:
1022 if isactive:
1011 label = 'branches.active'
1023 label = 'branches.active'
1012 notice = ''
1024 notice = ''
1013 elif not isopen:
1025 elif not isopen:
1014 if not closed:
1026 if not closed:
1015 continue
1027 continue
1016 label = 'branches.closed'
1028 label = 'branches.closed'
1017 notice = _(' (closed)')
1029 notice = _(' (closed)')
1018 else:
1030 else:
1019 label = 'branches.inactive'
1031 label = 'branches.inactive'
1020 notice = _(' (inactive)')
1032 notice = _(' (inactive)')
1021 if ctx.branch() == repo.dirstate.branch():
1033 if ctx.branch() == repo.dirstate.branch():
1022 label = 'branches.current'
1034 label = 'branches.current'
1023 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1035 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1024 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1036 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1025 'log.changeset changeset.%s' % ctx.phasestr())
1037 'log.changeset changeset.%s' % ctx.phasestr())
1026 tag = ui.label(ctx.branch(), label)
1038 tag = ui.label(ctx.branch(), label)
1027 if ui.quiet:
1039 if ui.quiet:
1028 ui.write("%s\n" % tag)
1040 ui.write("%s\n" % tag)
1029 else:
1041 else:
1030 ui.write("%s %s%s\n" % (tag, rev, notice))
1042 ui.write("%s %s%s\n" % (tag, rev, notice))
1031
1043
1032 @command('bundle',
1044 @command('bundle',
1033 [('f', 'force', None, _('run even when the destination is unrelated')),
1045 [('f', 'force', None, _('run even when the destination is unrelated')),
1034 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1046 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1035 _('REV')),
1047 _('REV')),
1036 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1048 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1037 _('BRANCH')),
1049 _('BRANCH')),
1038 ('', 'base', [],
1050 ('', 'base', [],
1039 _('a base changeset assumed to be available at the destination'),
1051 _('a base changeset assumed to be available at the destination'),
1040 _('REV')),
1052 _('REV')),
1041 ('a', 'all', None, _('bundle all changesets in the repository')),
1053 ('a', 'all', None, _('bundle all changesets in the repository')),
1042 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1054 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1043 ] + remoteopts,
1055 ] + remoteopts,
1044 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1056 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1045 def bundle(ui, repo, fname, dest=None, **opts):
1057 def bundle(ui, repo, fname, dest=None, **opts):
1046 """create a changegroup file
1058 """create a changegroup file
1047
1059
1048 Generate a compressed changegroup file collecting changesets not
1060 Generate a compressed changegroup file collecting changesets not
1049 known to be in another repository.
1061 known to be in another repository.
1050
1062
1051 If you omit the destination repository, then hg assumes the
1063 If you omit the destination repository, then hg assumes the
1052 destination will have all the nodes you specify with --base
1064 destination will have all the nodes you specify with --base
1053 parameters. To create a bundle containing all changesets, use
1065 parameters. To create a bundle containing all changesets, use
1054 -a/--all (or --base null).
1066 -a/--all (or --base null).
1055
1067
1056 You can change compression method with the -t/--type option.
1068 You can change compression method with the -t/--type option.
1057 The available compression methods are: none, bzip2, and
1069 The available compression methods are: none, bzip2, and
1058 gzip (by default, bundles are compressed using bzip2).
1070 gzip (by default, bundles are compressed using bzip2).
1059
1071
1060 The bundle file can then be transferred using conventional means
1072 The bundle file can then be transferred using conventional means
1061 and applied to another repository with the unbundle or pull
1073 and applied to another repository with the unbundle or pull
1062 command. This is useful when direct push and pull are not
1074 command. This is useful when direct push and pull are not
1063 available or when exporting an entire repository is undesirable.
1075 available or when exporting an entire repository is undesirable.
1064
1076
1065 Applying bundles preserves all changeset contents including
1077 Applying bundles preserves all changeset contents including
1066 permissions, copy/rename information, and revision history.
1078 permissions, copy/rename information, and revision history.
1067
1079
1068 Returns 0 on success, 1 if no changes found.
1080 Returns 0 on success, 1 if no changes found.
1069 """
1081 """
1070 revs = None
1082 revs = None
1071 if 'rev' in opts:
1083 if 'rev' in opts:
1072 revs = scmutil.revrange(repo, opts['rev'])
1084 revs = scmutil.revrange(repo, opts['rev'])
1073
1085
1074 bundletype = opts.get('type', 'bzip2').lower()
1086 bundletype = opts.get('type', 'bzip2').lower()
1075 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1087 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1076 bundletype = btypes.get(bundletype)
1088 bundletype = btypes.get(bundletype)
1077 if bundletype not in changegroup.bundletypes:
1089 if bundletype not in changegroup.bundletypes:
1078 raise util.Abort(_('unknown bundle type specified with --type'))
1090 raise util.Abort(_('unknown bundle type specified with --type'))
1079
1091
1080 if opts.get('all'):
1092 if opts.get('all'):
1081 base = ['null']
1093 base = ['null']
1082 else:
1094 else:
1083 base = scmutil.revrange(repo, opts.get('base'))
1095 base = scmutil.revrange(repo, opts.get('base'))
1084 if base:
1096 if base:
1085 if dest:
1097 if dest:
1086 raise util.Abort(_("--base is incompatible with specifying "
1098 raise util.Abort(_("--base is incompatible with specifying "
1087 "a destination"))
1099 "a destination"))
1088 common = [repo.lookup(rev) for rev in base]
1100 common = [repo.lookup(rev) for rev in base]
1089 heads = revs and map(repo.lookup, revs) or revs
1101 heads = revs and map(repo.lookup, revs) or revs
1090 cg = repo.getbundle('bundle', heads=heads, common=common)
1102 cg = repo.getbundle('bundle', heads=heads, common=common)
1091 outgoing = None
1103 outgoing = None
1092 else:
1104 else:
1093 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1105 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1094 dest, branches = hg.parseurl(dest, opts.get('branch'))
1106 dest, branches = hg.parseurl(dest, opts.get('branch'))
1095 other = hg.peer(repo, opts, dest)
1107 other = hg.peer(repo, opts, dest)
1096 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1108 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1097 heads = revs and map(repo.lookup, revs) or revs
1109 heads = revs and map(repo.lookup, revs) or revs
1098 outgoing = discovery.findcommonoutgoing(repo, other,
1110 outgoing = discovery.findcommonoutgoing(repo, other,
1099 onlyheads=heads,
1111 onlyheads=heads,
1100 force=opts.get('force'),
1112 force=opts.get('force'),
1101 portable=True)
1113 portable=True)
1102 cg = repo.getlocalbundle('bundle', outgoing)
1114 cg = repo.getlocalbundle('bundle', outgoing)
1103 if not cg:
1115 if not cg:
1104 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1116 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1105 return 1
1117 return 1
1106
1118
1107 changegroup.writebundle(cg, fname, bundletype)
1119 changegroup.writebundle(cg, fname, bundletype)
1108
1120
1109 @command('cat',
1121 @command('cat',
1110 [('o', 'output', '',
1122 [('o', 'output', '',
1111 _('print output to file with formatted name'), _('FORMAT')),
1123 _('print output to file with formatted name'), _('FORMAT')),
1112 ('r', 'rev', '', _('print the given revision'), _('REV')),
1124 ('r', 'rev', '', _('print the given revision'), _('REV')),
1113 ('', 'decode', None, _('apply any matching decode filter')),
1125 ('', 'decode', None, _('apply any matching decode filter')),
1114 ] + walkopts,
1126 ] + walkopts,
1115 _('[OPTION]... FILE...'))
1127 _('[OPTION]... FILE...'))
1116 def cat(ui, repo, file1, *pats, **opts):
1128 def cat(ui, repo, file1, *pats, **opts):
1117 """output the current or given revision of files
1129 """output the current or given revision of files
1118
1130
1119 Print the specified files as they were at the given revision. If
1131 Print the specified files as they were at the given revision. If
1120 no revision is given, the parent of the working directory is used,
1132 no revision is given, the parent of the working directory is used,
1121 or tip if no revision is checked out.
1133 or tip if no revision is checked out.
1122
1134
1123 Output may be to a file, in which case the name of the file is
1135 Output may be to a file, in which case the name of the file is
1124 given using a format string. The formatting rules are the same as
1136 given using a format string. The formatting rules are the same as
1125 for the export command, with the following additions:
1137 for the export command, with the following additions:
1126
1138
1127 :``%s``: basename of file being printed
1139 :``%s``: basename of file being printed
1128 :``%d``: dirname of file being printed, or '.' if in repository root
1140 :``%d``: dirname of file being printed, or '.' if in repository root
1129 :``%p``: root-relative path name of file being printed
1141 :``%p``: root-relative path name of file being printed
1130
1142
1131 Returns 0 on success.
1143 Returns 0 on success.
1132 """
1144 """
1133 ctx = scmutil.revsingle(repo, opts.get('rev'))
1145 ctx = scmutil.revsingle(repo, opts.get('rev'))
1134 err = 1
1146 err = 1
1135 m = scmutil.match(ctx, (file1,) + pats, opts)
1147 m = scmutil.match(ctx, (file1,) + pats, opts)
1136 for abs in ctx.walk(m):
1148 for abs in ctx.walk(m):
1137 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1149 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1138 pathname=abs)
1150 pathname=abs)
1139 data = ctx[abs].data()
1151 data = ctx[abs].data()
1140 if opts.get('decode'):
1152 if opts.get('decode'):
1141 data = repo.wwritedata(abs, data)
1153 data = repo.wwritedata(abs, data)
1142 fp.write(data)
1154 fp.write(data)
1143 fp.close()
1155 fp.close()
1144 err = 0
1156 err = 0
1145 return err
1157 return err
1146
1158
1147 @command('^clone',
1159 @command('^clone',
1148 [('U', 'noupdate', None,
1160 [('U', 'noupdate', None,
1149 _('the clone will include an empty working copy (only a repository)')),
1161 _('the clone will include an empty working copy (only a repository)')),
1150 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1162 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1151 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1163 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1152 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1164 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1153 ('', 'pull', None, _('use pull protocol to copy metadata')),
1165 ('', 'pull', None, _('use pull protocol to copy metadata')),
1154 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1166 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1155 ] + remoteopts,
1167 ] + remoteopts,
1156 _('[OPTION]... SOURCE [DEST]'))
1168 _('[OPTION]... SOURCE [DEST]'))
1157 def clone(ui, source, dest=None, **opts):
1169 def clone(ui, source, dest=None, **opts):
1158 """make a copy of an existing repository
1170 """make a copy of an existing repository
1159
1171
1160 Create a copy of an existing repository in a new directory.
1172 Create a copy of an existing repository in a new directory.
1161
1173
1162 If no destination directory name is specified, it defaults to the
1174 If no destination directory name is specified, it defaults to the
1163 basename of the source.
1175 basename of the source.
1164
1176
1165 The location of the source is added to the new repository's
1177 The location of the source is added to the new repository's
1166 ``.hg/hgrc`` file, as the default to be used for future pulls.
1178 ``.hg/hgrc`` file, as the default to be used for future pulls.
1167
1179
1168 Only local paths and ``ssh://`` URLs are supported as
1180 Only local paths and ``ssh://`` URLs are supported as
1169 destinations. For ``ssh://`` destinations, no working directory or
1181 destinations. For ``ssh://`` destinations, no working directory or
1170 ``.hg/hgrc`` will be created on the remote side.
1182 ``.hg/hgrc`` will be created on the remote side.
1171
1183
1172 To pull only a subset of changesets, specify one or more revisions
1184 To pull only a subset of changesets, specify one or more revisions
1173 identifiers with -r/--rev or branches with -b/--branch. The
1185 identifiers with -r/--rev or branches with -b/--branch. The
1174 resulting clone will contain only the specified changesets and
1186 resulting clone will contain only the specified changesets and
1175 their ancestors. These options (or 'clone src#rev dest') imply
1187 their ancestors. These options (or 'clone src#rev dest') imply
1176 --pull, even for local source repositories. Note that specifying a
1188 --pull, even for local source repositories. Note that specifying a
1177 tag will include the tagged changeset but not the changeset
1189 tag will include the tagged changeset but not the changeset
1178 containing the tag.
1190 containing the tag.
1179
1191
1180 If the source repository has a bookmark called '@' set, that
1192 If the source repository has a bookmark called '@' set, that
1181 revision will be checked out in the new repository by default.
1193 revision will be checked out in the new repository by default.
1182
1194
1183 To check out a particular version, use -u/--update, or
1195 To check out a particular version, use -u/--update, or
1184 -U/--noupdate to create a clone with no working directory.
1196 -U/--noupdate to create a clone with no working directory.
1185
1197
1186 .. container:: verbose
1198 .. container:: verbose
1187
1199
1188 For efficiency, hardlinks are used for cloning whenever the
1200 For efficiency, hardlinks are used for cloning whenever the
1189 source and destination are on the same filesystem (note this
1201 source and destination are on the same filesystem (note this
1190 applies only to the repository data, not to the working
1202 applies only to the repository data, not to the working
1191 directory). Some filesystems, such as AFS, implement hardlinking
1203 directory). Some filesystems, such as AFS, implement hardlinking
1192 incorrectly, but do not report errors. In these cases, use the
1204 incorrectly, but do not report errors. In these cases, use the
1193 --pull option to avoid hardlinking.
1205 --pull option to avoid hardlinking.
1194
1206
1195 In some cases, you can clone repositories and the working
1207 In some cases, you can clone repositories and the working
1196 directory using full hardlinks with ::
1208 directory using full hardlinks with ::
1197
1209
1198 $ cp -al REPO REPOCLONE
1210 $ cp -al REPO REPOCLONE
1199
1211
1200 This is the fastest way to clone, but it is not always safe. The
1212 This is the fastest way to clone, but it is not always safe. The
1201 operation is not atomic (making sure REPO is not modified during
1213 operation is not atomic (making sure REPO is not modified during
1202 the operation is up to you) and you have to make sure your
1214 the operation is up to you) and you have to make sure your
1203 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1215 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1204 so). Also, this is not compatible with certain extensions that
1216 so). Also, this is not compatible with certain extensions that
1205 place their metadata under the .hg directory, such as mq.
1217 place their metadata under the .hg directory, such as mq.
1206
1218
1207 Mercurial will update the working directory to the first applicable
1219 Mercurial will update the working directory to the first applicable
1208 revision from this list:
1220 revision from this list:
1209
1221
1210 a) null if -U or the source repository has no changesets
1222 a) null if -U or the source repository has no changesets
1211 b) if -u . and the source repository is local, the first parent of
1223 b) if -u . and the source repository is local, the first parent of
1212 the source repository's working directory
1224 the source repository's working directory
1213 c) the changeset specified with -u (if a branch name, this means the
1225 c) the changeset specified with -u (if a branch name, this means the
1214 latest head of that branch)
1226 latest head of that branch)
1215 d) the changeset specified with -r
1227 d) the changeset specified with -r
1216 e) the tipmost head specified with -b
1228 e) the tipmost head specified with -b
1217 f) the tipmost head specified with the url#branch source syntax
1229 f) the tipmost head specified with the url#branch source syntax
1218 g) the revision marked with the '@' bookmark, if present
1230 g) the revision marked with the '@' bookmark, if present
1219 h) the tipmost head of the default branch
1231 h) the tipmost head of the default branch
1220 i) tip
1232 i) tip
1221
1233
1222 Examples:
1234 Examples:
1223
1235
1224 - clone a remote repository to a new directory named hg/::
1236 - clone a remote repository to a new directory named hg/::
1225
1237
1226 hg clone http://selenic.com/hg
1238 hg clone http://selenic.com/hg
1227
1239
1228 - create a lightweight local clone::
1240 - create a lightweight local clone::
1229
1241
1230 hg clone project/ project-feature/
1242 hg clone project/ project-feature/
1231
1243
1232 - clone from an absolute path on an ssh server (note double-slash)::
1244 - clone from an absolute path on an ssh server (note double-slash)::
1233
1245
1234 hg clone ssh://user@server//home/projects/alpha/
1246 hg clone ssh://user@server//home/projects/alpha/
1235
1247
1236 - do a high-speed clone over a LAN while checking out a
1248 - do a high-speed clone over a LAN while checking out a
1237 specified version::
1249 specified version::
1238
1250
1239 hg clone --uncompressed http://server/repo -u 1.5
1251 hg clone --uncompressed http://server/repo -u 1.5
1240
1252
1241 - create a repository without changesets after a particular revision::
1253 - create a repository without changesets after a particular revision::
1242
1254
1243 hg clone -r 04e544 experimental/ good/
1255 hg clone -r 04e544 experimental/ good/
1244
1256
1245 - clone (and track) a particular named branch::
1257 - clone (and track) a particular named branch::
1246
1258
1247 hg clone http://selenic.com/hg#stable
1259 hg clone http://selenic.com/hg#stable
1248
1260
1249 See :hg:`help urls` for details on specifying URLs.
1261 See :hg:`help urls` for details on specifying URLs.
1250
1262
1251 Returns 0 on success.
1263 Returns 0 on success.
1252 """
1264 """
1253 if opts.get('noupdate') and opts.get('updaterev'):
1265 if opts.get('noupdate') and opts.get('updaterev'):
1254 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1266 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1255
1267
1256 r = hg.clone(ui, opts, source, dest,
1268 r = hg.clone(ui, opts, source, dest,
1257 pull=opts.get('pull'),
1269 pull=opts.get('pull'),
1258 stream=opts.get('uncompressed'),
1270 stream=opts.get('uncompressed'),
1259 rev=opts.get('rev'),
1271 rev=opts.get('rev'),
1260 update=opts.get('updaterev') or not opts.get('noupdate'),
1272 update=opts.get('updaterev') or not opts.get('noupdate'),
1261 branch=opts.get('branch'))
1273 branch=opts.get('branch'))
1262
1274
1263 return r is None
1275 return r is None
1264
1276
1265 @command('^commit|ci',
1277 @command('^commit|ci',
1266 [('A', 'addremove', None,
1278 [('A', 'addremove', None,
1267 _('mark new/missing files as added/removed before committing')),
1279 _('mark new/missing files as added/removed before committing')),
1268 ('', 'close-branch', None,
1280 ('', 'close-branch', None,
1269 _('mark a branch as closed, hiding it from the branch list')),
1281 _('mark a branch as closed, hiding it from the branch list')),
1270 ('', 'amend', None, _('amend the parent of the working dir')),
1282 ('', 'amend', None, _('amend the parent of the working dir')),
1271 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1283 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1272 _('[OPTION]... [FILE]...'))
1284 _('[OPTION]... [FILE]...'))
1273 def commit(ui, repo, *pats, **opts):
1285 def commit(ui, repo, *pats, **opts):
1274 """commit the specified files or all outstanding changes
1286 """commit the specified files or all outstanding changes
1275
1287
1276 Commit changes to the given files into the repository. Unlike a
1288 Commit changes to the given files into the repository. Unlike a
1277 centralized SCM, this operation is a local operation. See
1289 centralized SCM, this operation is a local operation. See
1278 :hg:`push` for a way to actively distribute your changes.
1290 :hg:`push` for a way to actively distribute your changes.
1279
1291
1280 If a list of files is omitted, all changes reported by :hg:`status`
1292 If a list of files is omitted, all changes reported by :hg:`status`
1281 will be committed.
1293 will be committed.
1282
1294
1283 If you are committing the result of a merge, do not provide any
1295 If you are committing the result of a merge, do not provide any
1284 filenames or -I/-X filters.
1296 filenames or -I/-X filters.
1285
1297
1286 If no commit message is specified, Mercurial starts your
1298 If no commit message is specified, Mercurial starts your
1287 configured editor where you can enter a message. In case your
1299 configured editor where you can enter a message. In case your
1288 commit fails, you will find a backup of your message in
1300 commit fails, you will find a backup of your message in
1289 ``.hg/last-message.txt``.
1301 ``.hg/last-message.txt``.
1290
1302
1291 The --amend flag can be used to amend the parent of the
1303 The --amend flag can be used to amend the parent of the
1292 working directory with a new commit that contains the changes
1304 working directory with a new commit that contains the changes
1293 in the parent in addition to those currently reported by :hg:`status`,
1305 in the parent in addition to those currently reported by :hg:`status`,
1294 if there are any. The old commit is stored in a backup bundle in
1306 if there are any. The old commit is stored in a backup bundle in
1295 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1307 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1296 on how to restore it).
1308 on how to restore it).
1297
1309
1298 Message, user and date are taken from the amended commit unless
1310 Message, user and date are taken from the amended commit unless
1299 specified. When a message isn't specified on the command line,
1311 specified. When a message isn't specified on the command line,
1300 the editor will open with the message of the amended commit.
1312 the editor will open with the message of the amended commit.
1301
1313
1302 It is not possible to amend public changesets (see :hg:`help phases`)
1314 It is not possible to amend public changesets (see :hg:`help phases`)
1303 or changesets that have children.
1315 or changesets that have children.
1304
1316
1305 See :hg:`help dates` for a list of formats valid for -d/--date.
1317 See :hg:`help dates` for a list of formats valid for -d/--date.
1306
1318
1307 Returns 0 on success, 1 if nothing changed.
1319 Returns 0 on success, 1 if nothing changed.
1308 """
1320 """
1309 if opts.get('subrepos'):
1321 if opts.get('subrepos'):
1310 # Let --subrepos on the command line override config setting.
1322 # Let --subrepos on the command line override config setting.
1311 ui.setconfig('ui', 'commitsubrepos', True)
1323 ui.setconfig('ui', 'commitsubrepos', True)
1312
1324
1313 extra = {}
1325 extra = {}
1314 if opts.get('close_branch'):
1326 if opts.get('close_branch'):
1315 extra['close'] = 1
1327 extra['close'] = 1
1316
1328
1317 branch = repo[None].branch()
1329 branch = repo[None].branch()
1318 bheads = repo.branchheads(branch)
1330 bheads = repo.branchheads(branch)
1319
1331
1320 if opts.get('amend'):
1332 if opts.get('amend'):
1321 if ui.configbool('ui', 'commitsubrepos'):
1333 if ui.configbool('ui', 'commitsubrepos'):
1322 raise util.Abort(_('cannot amend recursively'))
1334 raise util.Abort(_('cannot amend recursively'))
1323
1335
1324 old = repo['.']
1336 old = repo['.']
1325 if old.phase() == phases.public:
1337 if old.phase() == phases.public:
1326 raise util.Abort(_('cannot amend public changesets'))
1338 raise util.Abort(_('cannot amend public changesets'))
1327 if len(repo[None].parents()) > 1:
1339 if len(repo[None].parents()) > 1:
1328 raise util.Abort(_('cannot amend while merging'))
1340 raise util.Abort(_('cannot amend while merging'))
1329 if (not obsolete._enabled) and old.children():
1341 if (not obsolete._enabled) and old.children():
1330 raise util.Abort(_('cannot amend changeset with children'))
1342 raise util.Abort(_('cannot amend changeset with children'))
1331
1343
1332 e = cmdutil.commiteditor
1344 e = cmdutil.commiteditor
1333 if opts.get('force_editor'):
1345 if opts.get('force_editor'):
1334 e = cmdutil.commitforceeditor
1346 e = cmdutil.commitforceeditor
1335
1347
1336 def commitfunc(ui, repo, message, match, opts):
1348 def commitfunc(ui, repo, message, match, opts):
1337 editor = e
1349 editor = e
1338 # message contains text from -m or -l, if it's empty,
1350 # message contains text from -m or -l, if it's empty,
1339 # open the editor with the old message
1351 # open the editor with the old message
1340 if not message:
1352 if not message:
1341 message = old.description()
1353 message = old.description()
1342 editor = cmdutil.commitforceeditor
1354 editor = cmdutil.commitforceeditor
1343 return repo.commit(message,
1355 return repo.commit(message,
1344 opts.get('user') or old.user(),
1356 opts.get('user') or old.user(),
1345 opts.get('date') or old.date(),
1357 opts.get('date') or old.date(),
1346 match,
1358 match,
1347 editor=editor,
1359 editor=editor,
1348 extra=extra)
1360 extra=extra)
1349
1361
1350 current = repo._bookmarkcurrent
1362 current = repo._bookmarkcurrent
1351 marks = old.bookmarks()
1363 marks = old.bookmarks()
1352 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1364 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1353 if node == old.node():
1365 if node == old.node():
1354 ui.status(_("nothing changed\n"))
1366 ui.status(_("nothing changed\n"))
1355 return 1
1367 return 1
1356 elif marks:
1368 elif marks:
1357 ui.debug('moving bookmarks %r from %s to %s\n' %
1369 ui.debug('moving bookmarks %r from %s to %s\n' %
1358 (marks, old.hex(), hex(node)))
1370 (marks, old.hex(), hex(node)))
1359 newmarks = repo._bookmarks
1371 newmarks = repo._bookmarks
1360 for bm in marks:
1372 for bm in marks:
1361 newmarks[bm] = node
1373 newmarks[bm] = node
1362 if bm == current:
1374 if bm == current:
1363 bookmarks.setcurrent(repo, bm)
1375 bookmarks.setcurrent(repo, bm)
1364 newmarks.write()
1376 newmarks.write()
1365 else:
1377 else:
1366 e = cmdutil.commiteditor
1378 e = cmdutil.commiteditor
1367 if opts.get('force_editor'):
1379 if opts.get('force_editor'):
1368 e = cmdutil.commitforceeditor
1380 e = cmdutil.commitforceeditor
1369
1381
1370 def commitfunc(ui, repo, message, match, opts):
1382 def commitfunc(ui, repo, message, match, opts):
1371 return repo.commit(message, opts.get('user'), opts.get('date'),
1383 return repo.commit(message, opts.get('user'), opts.get('date'),
1372 match, editor=e, extra=extra)
1384 match, editor=e, extra=extra)
1373
1385
1374 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1386 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1375
1387
1376 if not node:
1388 if not node:
1377 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1389 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1378 if stat[3]:
1390 if stat[3]:
1379 ui.status(_("nothing changed (%d missing files, see "
1391 ui.status(_("nothing changed (%d missing files, see "
1380 "'hg status')\n") % len(stat[3]))
1392 "'hg status')\n") % len(stat[3]))
1381 else:
1393 else:
1382 ui.status(_("nothing changed\n"))
1394 ui.status(_("nothing changed\n"))
1383 return 1
1395 return 1
1384
1396
1385 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1397 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1386
1398
1387 @command('copy|cp',
1399 @command('copy|cp',
1388 [('A', 'after', None, _('record a copy that has already occurred')),
1400 [('A', 'after', None, _('record a copy that has already occurred')),
1389 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1401 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1390 ] + walkopts + dryrunopts,
1402 ] + walkopts + dryrunopts,
1391 _('[OPTION]... [SOURCE]... DEST'))
1403 _('[OPTION]... [SOURCE]... DEST'))
1392 def copy(ui, repo, *pats, **opts):
1404 def copy(ui, repo, *pats, **opts):
1393 """mark files as copied for the next commit
1405 """mark files as copied for the next commit
1394
1406
1395 Mark dest as having copies of source files. If dest is a
1407 Mark dest as having copies of source files. If dest is a
1396 directory, copies are put in that directory. If dest is a file,
1408 directory, copies are put in that directory. If dest is a file,
1397 the source must be a single file.
1409 the source must be a single file.
1398
1410
1399 By default, this command copies the contents of files as they
1411 By default, this command copies the contents of files as they
1400 exist in the working directory. If invoked with -A/--after, the
1412 exist in the working directory. If invoked with -A/--after, the
1401 operation is recorded, but no copying is performed.
1413 operation is recorded, but no copying is performed.
1402
1414
1403 This command takes effect with the next commit. To undo a copy
1415 This command takes effect with the next commit. To undo a copy
1404 before that, see :hg:`revert`.
1416 before that, see :hg:`revert`.
1405
1417
1406 Returns 0 on success, 1 if errors are encountered.
1418 Returns 0 on success, 1 if errors are encountered.
1407 """
1419 """
1408 wlock = repo.wlock(False)
1420 wlock = repo.wlock(False)
1409 try:
1421 try:
1410 return cmdutil.copy(ui, repo, pats, opts)
1422 return cmdutil.copy(ui, repo, pats, opts)
1411 finally:
1423 finally:
1412 wlock.release()
1424 wlock.release()
1413
1425
1414 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1426 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1415 def debugancestor(ui, repo, *args):
1427 def debugancestor(ui, repo, *args):
1416 """find the ancestor revision of two revisions in a given index"""
1428 """find the ancestor revision of two revisions in a given index"""
1417 if len(args) == 3:
1429 if len(args) == 3:
1418 index, rev1, rev2 = args
1430 index, rev1, rev2 = args
1419 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1431 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1420 lookup = r.lookup
1432 lookup = r.lookup
1421 elif len(args) == 2:
1433 elif len(args) == 2:
1422 if not repo:
1434 if not repo:
1423 raise util.Abort(_("there is no Mercurial repository here "
1435 raise util.Abort(_("there is no Mercurial repository here "
1424 "(.hg not found)"))
1436 "(.hg not found)"))
1425 rev1, rev2 = args
1437 rev1, rev2 = args
1426 r = repo.changelog
1438 r = repo.changelog
1427 lookup = repo.lookup
1439 lookup = repo.lookup
1428 else:
1440 else:
1429 raise util.Abort(_('either two or three arguments required'))
1441 raise util.Abort(_('either two or three arguments required'))
1430 a = r.ancestor(lookup(rev1), lookup(rev2))
1442 a = r.ancestor(lookup(rev1), lookup(rev2))
1431 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1443 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1432
1444
1433 @command('debugbuilddag',
1445 @command('debugbuilddag',
1434 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1446 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1435 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1447 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1436 ('n', 'new-file', None, _('add new file at each rev'))],
1448 ('n', 'new-file', None, _('add new file at each rev'))],
1437 _('[OPTION]... [TEXT]'))
1449 _('[OPTION]... [TEXT]'))
1438 def debugbuilddag(ui, repo, text=None,
1450 def debugbuilddag(ui, repo, text=None,
1439 mergeable_file=False,
1451 mergeable_file=False,
1440 overwritten_file=False,
1452 overwritten_file=False,
1441 new_file=False):
1453 new_file=False):
1442 """builds a repo with a given DAG from scratch in the current empty repo
1454 """builds a repo with a given DAG from scratch in the current empty repo
1443
1455
1444 The description of the DAG is read from stdin if not given on the
1456 The description of the DAG is read from stdin if not given on the
1445 command line.
1457 command line.
1446
1458
1447 Elements:
1459 Elements:
1448
1460
1449 - "+n" is a linear run of n nodes based on the current default parent
1461 - "+n" is a linear run of n nodes based on the current default parent
1450 - "." is a single node based on the current default parent
1462 - "." is a single node based on the current default parent
1451 - "$" resets the default parent to null (implied at the start);
1463 - "$" resets the default parent to null (implied at the start);
1452 otherwise the default parent is always the last node created
1464 otherwise the default parent is always the last node created
1453 - "<p" sets the default parent to the backref p
1465 - "<p" sets the default parent to the backref p
1454 - "*p" is a fork at parent p, which is a backref
1466 - "*p" is a fork at parent p, which is a backref
1455 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1467 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1456 - "/p2" is a merge of the preceding node and p2
1468 - "/p2" is a merge of the preceding node and p2
1457 - ":tag" defines a local tag for the preceding node
1469 - ":tag" defines a local tag for the preceding node
1458 - "@branch" sets the named branch for subsequent nodes
1470 - "@branch" sets the named branch for subsequent nodes
1459 - "#...\\n" is a comment up to the end of the line
1471 - "#...\\n" is a comment up to the end of the line
1460
1472
1461 Whitespace between the above elements is ignored.
1473 Whitespace between the above elements is ignored.
1462
1474
1463 A backref is either
1475 A backref is either
1464
1476
1465 - a number n, which references the node curr-n, where curr is the current
1477 - a number n, which references the node curr-n, where curr is the current
1466 node, or
1478 node, or
1467 - the name of a local tag you placed earlier using ":tag", or
1479 - the name of a local tag you placed earlier using ":tag", or
1468 - empty to denote the default parent.
1480 - empty to denote the default parent.
1469
1481
1470 All string valued-elements are either strictly alphanumeric, or must
1482 All string valued-elements are either strictly alphanumeric, or must
1471 be enclosed in double quotes ("..."), with "\\" as escape character.
1483 be enclosed in double quotes ("..."), with "\\" as escape character.
1472 """
1484 """
1473
1485
1474 if text is None:
1486 if text is None:
1475 ui.status(_("reading DAG from stdin\n"))
1487 ui.status(_("reading DAG from stdin\n"))
1476 text = ui.fin.read()
1488 text = ui.fin.read()
1477
1489
1478 cl = repo.changelog
1490 cl = repo.changelog
1479 if len(cl) > 0:
1491 if len(cl) > 0:
1480 raise util.Abort(_('repository is not empty'))
1492 raise util.Abort(_('repository is not empty'))
1481
1493
1482 # determine number of revs in DAG
1494 # determine number of revs in DAG
1483 total = 0
1495 total = 0
1484 for type, data in dagparser.parsedag(text):
1496 for type, data in dagparser.parsedag(text):
1485 if type == 'n':
1497 if type == 'n':
1486 total += 1
1498 total += 1
1487
1499
1488 if mergeable_file:
1500 if mergeable_file:
1489 linesperrev = 2
1501 linesperrev = 2
1490 # make a file with k lines per rev
1502 # make a file with k lines per rev
1491 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1503 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1492 initialmergedlines.append("")
1504 initialmergedlines.append("")
1493
1505
1494 tags = []
1506 tags = []
1495
1507
1496 lock = tr = None
1508 lock = tr = None
1497 try:
1509 try:
1498 lock = repo.lock()
1510 lock = repo.lock()
1499 tr = repo.transaction("builddag")
1511 tr = repo.transaction("builddag")
1500
1512
1501 at = -1
1513 at = -1
1502 atbranch = 'default'
1514 atbranch = 'default'
1503 nodeids = []
1515 nodeids = []
1504 id = 0
1516 id = 0
1505 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1517 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1506 for type, data in dagparser.parsedag(text):
1518 for type, data in dagparser.parsedag(text):
1507 if type == 'n':
1519 if type == 'n':
1508 ui.note(('node %s\n' % str(data)))
1520 ui.note(('node %s\n' % str(data)))
1509 id, ps = data
1521 id, ps = data
1510
1522
1511 files = []
1523 files = []
1512 fctxs = {}
1524 fctxs = {}
1513
1525
1514 p2 = None
1526 p2 = None
1515 if mergeable_file:
1527 if mergeable_file:
1516 fn = "mf"
1528 fn = "mf"
1517 p1 = repo[ps[0]]
1529 p1 = repo[ps[0]]
1518 if len(ps) > 1:
1530 if len(ps) > 1:
1519 p2 = repo[ps[1]]
1531 p2 = repo[ps[1]]
1520 pa = p1.ancestor(p2)
1532 pa = p1.ancestor(p2)
1521 base, local, other = [x[fn].data() for x in (pa, p1,
1533 base, local, other = [x[fn].data() for x in (pa, p1,
1522 p2)]
1534 p2)]
1523 m3 = simplemerge.Merge3Text(base, local, other)
1535 m3 = simplemerge.Merge3Text(base, local, other)
1524 ml = [l.strip() for l in m3.merge_lines()]
1536 ml = [l.strip() for l in m3.merge_lines()]
1525 ml.append("")
1537 ml.append("")
1526 elif at > 0:
1538 elif at > 0:
1527 ml = p1[fn].data().split("\n")
1539 ml = p1[fn].data().split("\n")
1528 else:
1540 else:
1529 ml = initialmergedlines
1541 ml = initialmergedlines
1530 ml[id * linesperrev] += " r%i" % id
1542 ml[id * linesperrev] += " r%i" % id
1531 mergedtext = "\n".join(ml)
1543 mergedtext = "\n".join(ml)
1532 files.append(fn)
1544 files.append(fn)
1533 fctxs[fn] = context.memfilectx(fn, mergedtext)
1545 fctxs[fn] = context.memfilectx(fn, mergedtext)
1534
1546
1535 if overwritten_file:
1547 if overwritten_file:
1536 fn = "of"
1548 fn = "of"
1537 files.append(fn)
1549 files.append(fn)
1538 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1550 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1539
1551
1540 if new_file:
1552 if new_file:
1541 fn = "nf%i" % id
1553 fn = "nf%i" % id
1542 files.append(fn)
1554 files.append(fn)
1543 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1555 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1544 if len(ps) > 1:
1556 if len(ps) > 1:
1545 if not p2:
1557 if not p2:
1546 p2 = repo[ps[1]]
1558 p2 = repo[ps[1]]
1547 for fn in p2:
1559 for fn in p2:
1548 if fn.startswith("nf"):
1560 if fn.startswith("nf"):
1549 files.append(fn)
1561 files.append(fn)
1550 fctxs[fn] = p2[fn]
1562 fctxs[fn] = p2[fn]
1551
1563
1552 def fctxfn(repo, cx, path):
1564 def fctxfn(repo, cx, path):
1553 return fctxs.get(path)
1565 return fctxs.get(path)
1554
1566
1555 if len(ps) == 0 or ps[0] < 0:
1567 if len(ps) == 0 or ps[0] < 0:
1556 pars = [None, None]
1568 pars = [None, None]
1557 elif len(ps) == 1:
1569 elif len(ps) == 1:
1558 pars = [nodeids[ps[0]], None]
1570 pars = [nodeids[ps[0]], None]
1559 else:
1571 else:
1560 pars = [nodeids[p] for p in ps]
1572 pars = [nodeids[p] for p in ps]
1561 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1573 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1562 date=(id, 0),
1574 date=(id, 0),
1563 user="debugbuilddag",
1575 user="debugbuilddag",
1564 extra={'branch': atbranch})
1576 extra={'branch': atbranch})
1565 nodeid = repo.commitctx(cx)
1577 nodeid = repo.commitctx(cx)
1566 nodeids.append(nodeid)
1578 nodeids.append(nodeid)
1567 at = id
1579 at = id
1568 elif type == 'l':
1580 elif type == 'l':
1569 id, name = data
1581 id, name = data
1570 ui.note(('tag %s\n' % name))
1582 ui.note(('tag %s\n' % name))
1571 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1583 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1572 elif type == 'a':
1584 elif type == 'a':
1573 ui.note(('branch %s\n' % data))
1585 ui.note(('branch %s\n' % data))
1574 atbranch = data
1586 atbranch = data
1575 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1587 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1576 tr.close()
1588 tr.close()
1577
1589
1578 if tags:
1590 if tags:
1579 repo.opener.write("localtags", "".join(tags))
1591 repo.opener.write("localtags", "".join(tags))
1580 finally:
1592 finally:
1581 ui.progress(_('building'), None)
1593 ui.progress(_('building'), None)
1582 release(tr, lock)
1594 release(tr, lock)
1583
1595
1584 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1596 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1585 def debugbundle(ui, bundlepath, all=None, **opts):
1597 def debugbundle(ui, bundlepath, all=None, **opts):
1586 """lists the contents of a bundle"""
1598 """lists the contents of a bundle"""
1587 f = hg.openpath(ui, bundlepath)
1599 f = hg.openpath(ui, bundlepath)
1588 try:
1600 try:
1589 gen = changegroup.readbundle(f, bundlepath)
1601 gen = changegroup.readbundle(f, bundlepath)
1590 if all:
1602 if all:
1591 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1603 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1592
1604
1593 def showchunks(named):
1605 def showchunks(named):
1594 ui.write("\n%s\n" % named)
1606 ui.write("\n%s\n" % named)
1595 chain = None
1607 chain = None
1596 while True:
1608 while True:
1597 chunkdata = gen.deltachunk(chain)
1609 chunkdata = gen.deltachunk(chain)
1598 if not chunkdata:
1610 if not chunkdata:
1599 break
1611 break
1600 node = chunkdata['node']
1612 node = chunkdata['node']
1601 p1 = chunkdata['p1']
1613 p1 = chunkdata['p1']
1602 p2 = chunkdata['p2']
1614 p2 = chunkdata['p2']
1603 cs = chunkdata['cs']
1615 cs = chunkdata['cs']
1604 deltabase = chunkdata['deltabase']
1616 deltabase = chunkdata['deltabase']
1605 delta = chunkdata['delta']
1617 delta = chunkdata['delta']
1606 ui.write("%s %s %s %s %s %s\n" %
1618 ui.write("%s %s %s %s %s %s\n" %
1607 (hex(node), hex(p1), hex(p2),
1619 (hex(node), hex(p1), hex(p2),
1608 hex(cs), hex(deltabase), len(delta)))
1620 hex(cs), hex(deltabase), len(delta)))
1609 chain = node
1621 chain = node
1610
1622
1611 chunkdata = gen.changelogheader()
1623 chunkdata = gen.changelogheader()
1612 showchunks("changelog")
1624 showchunks("changelog")
1613 chunkdata = gen.manifestheader()
1625 chunkdata = gen.manifestheader()
1614 showchunks("manifest")
1626 showchunks("manifest")
1615 while True:
1627 while True:
1616 chunkdata = gen.filelogheader()
1628 chunkdata = gen.filelogheader()
1617 if not chunkdata:
1629 if not chunkdata:
1618 break
1630 break
1619 fname = chunkdata['filename']
1631 fname = chunkdata['filename']
1620 showchunks(fname)
1632 showchunks(fname)
1621 else:
1633 else:
1622 chunkdata = gen.changelogheader()
1634 chunkdata = gen.changelogheader()
1623 chain = None
1635 chain = None
1624 while True:
1636 while True:
1625 chunkdata = gen.deltachunk(chain)
1637 chunkdata = gen.deltachunk(chain)
1626 if not chunkdata:
1638 if not chunkdata:
1627 break
1639 break
1628 node = chunkdata['node']
1640 node = chunkdata['node']
1629 ui.write("%s\n" % hex(node))
1641 ui.write("%s\n" % hex(node))
1630 chain = node
1642 chain = node
1631 finally:
1643 finally:
1632 f.close()
1644 f.close()
1633
1645
1634 @command('debugcheckstate', [], '')
1646 @command('debugcheckstate', [], '')
1635 def debugcheckstate(ui, repo):
1647 def debugcheckstate(ui, repo):
1636 """validate the correctness of the current dirstate"""
1648 """validate the correctness of the current dirstate"""
1637 parent1, parent2 = repo.dirstate.parents()
1649 parent1, parent2 = repo.dirstate.parents()
1638 m1 = repo[parent1].manifest()
1650 m1 = repo[parent1].manifest()
1639 m2 = repo[parent2].manifest()
1651 m2 = repo[parent2].manifest()
1640 errors = 0
1652 errors = 0
1641 for f in repo.dirstate:
1653 for f in repo.dirstate:
1642 state = repo.dirstate[f]
1654 state = repo.dirstate[f]
1643 if state in "nr" and f not in m1:
1655 if state in "nr" and f not in m1:
1644 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1656 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1645 errors += 1
1657 errors += 1
1646 if state in "a" and f in m1:
1658 if state in "a" and f in m1:
1647 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1659 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1648 errors += 1
1660 errors += 1
1649 if state in "m" and f not in m1 and f not in m2:
1661 if state in "m" and f not in m1 and f not in m2:
1650 ui.warn(_("%s in state %s, but not in either manifest\n") %
1662 ui.warn(_("%s in state %s, but not in either manifest\n") %
1651 (f, state))
1663 (f, state))
1652 errors += 1
1664 errors += 1
1653 for f in m1:
1665 for f in m1:
1654 state = repo.dirstate[f]
1666 state = repo.dirstate[f]
1655 if state not in "nrm":
1667 if state not in "nrm":
1656 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1668 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1657 errors += 1
1669 errors += 1
1658 if errors:
1670 if errors:
1659 error = _(".hg/dirstate inconsistent with current parent's manifest")
1671 error = _(".hg/dirstate inconsistent with current parent's manifest")
1660 raise util.Abort(error)
1672 raise util.Abort(error)
1661
1673
1662 @command('debugcommands', [], _('[COMMAND]'))
1674 @command('debugcommands', [], _('[COMMAND]'))
1663 def debugcommands(ui, cmd='', *args):
1675 def debugcommands(ui, cmd='', *args):
1664 """list all available commands and options"""
1676 """list all available commands and options"""
1665 for cmd, vals in sorted(table.iteritems()):
1677 for cmd, vals in sorted(table.iteritems()):
1666 cmd = cmd.split('|')[0].strip('^')
1678 cmd = cmd.split('|')[0].strip('^')
1667 opts = ', '.join([i[1] for i in vals[1]])
1679 opts = ', '.join([i[1] for i in vals[1]])
1668 ui.write('%s: %s\n' % (cmd, opts))
1680 ui.write('%s: %s\n' % (cmd, opts))
1669
1681
1670 @command('debugcomplete',
1682 @command('debugcomplete',
1671 [('o', 'options', None, _('show the command options'))],
1683 [('o', 'options', None, _('show the command options'))],
1672 _('[-o] CMD'))
1684 _('[-o] CMD'))
1673 def debugcomplete(ui, cmd='', **opts):
1685 def debugcomplete(ui, cmd='', **opts):
1674 """returns the completion list associated with the given command"""
1686 """returns the completion list associated with the given command"""
1675
1687
1676 if opts.get('options'):
1688 if opts.get('options'):
1677 options = []
1689 options = []
1678 otables = [globalopts]
1690 otables = [globalopts]
1679 if cmd:
1691 if cmd:
1680 aliases, entry = cmdutil.findcmd(cmd, table, False)
1692 aliases, entry = cmdutil.findcmd(cmd, table, False)
1681 otables.append(entry[1])
1693 otables.append(entry[1])
1682 for t in otables:
1694 for t in otables:
1683 for o in t:
1695 for o in t:
1684 if "(DEPRECATED)" in o[3]:
1696 if "(DEPRECATED)" in o[3]:
1685 continue
1697 continue
1686 if o[0]:
1698 if o[0]:
1687 options.append('-%s' % o[0])
1699 options.append('-%s' % o[0])
1688 options.append('--%s' % o[1])
1700 options.append('--%s' % o[1])
1689 ui.write("%s\n" % "\n".join(options))
1701 ui.write("%s\n" % "\n".join(options))
1690 return
1702 return
1691
1703
1692 cmdlist = cmdutil.findpossible(cmd, table)
1704 cmdlist = cmdutil.findpossible(cmd, table)
1693 if ui.verbose:
1705 if ui.verbose:
1694 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1706 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1695 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1707 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1696
1708
1697 @command('debugdag',
1709 @command('debugdag',
1698 [('t', 'tags', None, _('use tags as labels')),
1710 [('t', 'tags', None, _('use tags as labels')),
1699 ('b', 'branches', None, _('annotate with branch names')),
1711 ('b', 'branches', None, _('annotate with branch names')),
1700 ('', 'dots', None, _('use dots for runs')),
1712 ('', 'dots', None, _('use dots for runs')),
1701 ('s', 'spaces', None, _('separate elements by spaces'))],
1713 ('s', 'spaces', None, _('separate elements by spaces'))],
1702 _('[OPTION]... [FILE [REV]...]'))
1714 _('[OPTION]... [FILE [REV]...]'))
1703 def debugdag(ui, repo, file_=None, *revs, **opts):
1715 def debugdag(ui, repo, file_=None, *revs, **opts):
1704 """format the changelog or an index DAG as a concise textual description
1716 """format the changelog or an index DAG as a concise textual description
1705
1717
1706 If you pass a revlog index, the revlog's DAG is emitted. If you list
1718 If you pass a revlog index, the revlog's DAG is emitted. If you list
1707 revision numbers, they get labeled in the output as rN.
1719 revision numbers, they get labeled in the output as rN.
1708
1720
1709 Otherwise, the changelog DAG of the current repo is emitted.
1721 Otherwise, the changelog DAG of the current repo is emitted.
1710 """
1722 """
1711 spaces = opts.get('spaces')
1723 spaces = opts.get('spaces')
1712 dots = opts.get('dots')
1724 dots = opts.get('dots')
1713 if file_:
1725 if file_:
1714 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1726 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1715 revs = set((int(r) for r in revs))
1727 revs = set((int(r) for r in revs))
1716 def events():
1728 def events():
1717 for r in rlog:
1729 for r in rlog:
1718 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1730 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1719 if p != -1)))
1731 if p != -1)))
1720 if r in revs:
1732 if r in revs:
1721 yield 'l', (r, "r%i" % r)
1733 yield 'l', (r, "r%i" % r)
1722 elif repo:
1734 elif repo:
1723 cl = repo.changelog
1735 cl = repo.changelog
1724 tags = opts.get('tags')
1736 tags = opts.get('tags')
1725 branches = opts.get('branches')
1737 branches = opts.get('branches')
1726 if tags:
1738 if tags:
1727 labels = {}
1739 labels = {}
1728 for l, n in repo.tags().items():
1740 for l, n in repo.tags().items():
1729 labels.setdefault(cl.rev(n), []).append(l)
1741 labels.setdefault(cl.rev(n), []).append(l)
1730 def events():
1742 def events():
1731 b = "default"
1743 b = "default"
1732 for r in cl:
1744 for r in cl:
1733 if branches:
1745 if branches:
1734 newb = cl.read(cl.node(r))[5]['branch']
1746 newb = cl.read(cl.node(r))[5]['branch']
1735 if newb != b:
1747 if newb != b:
1736 yield 'a', newb
1748 yield 'a', newb
1737 b = newb
1749 b = newb
1738 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1750 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1739 if p != -1)))
1751 if p != -1)))
1740 if tags:
1752 if tags:
1741 ls = labels.get(r)
1753 ls = labels.get(r)
1742 if ls:
1754 if ls:
1743 for l in ls:
1755 for l in ls:
1744 yield 'l', (r, l)
1756 yield 'l', (r, l)
1745 else:
1757 else:
1746 raise util.Abort(_('need repo for changelog dag'))
1758 raise util.Abort(_('need repo for changelog dag'))
1747
1759
1748 for line in dagparser.dagtextlines(events(),
1760 for line in dagparser.dagtextlines(events(),
1749 addspaces=spaces,
1761 addspaces=spaces,
1750 wraplabels=True,
1762 wraplabels=True,
1751 wrapannotations=True,
1763 wrapannotations=True,
1752 wrapnonlinear=dots,
1764 wrapnonlinear=dots,
1753 usedots=dots,
1765 usedots=dots,
1754 maxlinewidth=70):
1766 maxlinewidth=70):
1755 ui.write(line)
1767 ui.write(line)
1756 ui.write("\n")
1768 ui.write("\n")
1757
1769
1758 @command('debugdata',
1770 @command('debugdata',
1759 [('c', 'changelog', False, _('open changelog')),
1771 [('c', 'changelog', False, _('open changelog')),
1760 ('m', 'manifest', False, _('open manifest'))],
1772 ('m', 'manifest', False, _('open manifest'))],
1761 _('-c|-m|FILE REV'))
1773 _('-c|-m|FILE REV'))
1762 def debugdata(ui, repo, file_, rev = None, **opts):
1774 def debugdata(ui, repo, file_, rev = None, **opts):
1763 """dump the contents of a data file revision"""
1775 """dump the contents of a data file revision"""
1764 if opts.get('changelog') or opts.get('manifest'):
1776 if opts.get('changelog') or opts.get('manifest'):
1765 file_, rev = None, file_
1777 file_, rev = None, file_
1766 elif rev is None:
1778 elif rev is None:
1767 raise error.CommandError('debugdata', _('invalid arguments'))
1779 raise error.CommandError('debugdata', _('invalid arguments'))
1768 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1780 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1769 try:
1781 try:
1770 ui.write(r.revision(r.lookup(rev)))
1782 ui.write(r.revision(r.lookup(rev)))
1771 except KeyError:
1783 except KeyError:
1772 raise util.Abort(_('invalid revision identifier %s') % rev)
1784 raise util.Abort(_('invalid revision identifier %s') % rev)
1773
1785
1774 @command('debugdate',
1786 @command('debugdate',
1775 [('e', 'extended', None, _('try extended date formats'))],
1787 [('e', 'extended', None, _('try extended date formats'))],
1776 _('[-e] DATE [RANGE]'))
1788 _('[-e] DATE [RANGE]'))
1777 def debugdate(ui, date, range=None, **opts):
1789 def debugdate(ui, date, range=None, **opts):
1778 """parse and display a date"""
1790 """parse and display a date"""
1779 if opts["extended"]:
1791 if opts["extended"]:
1780 d = util.parsedate(date, util.extendeddateformats)
1792 d = util.parsedate(date, util.extendeddateformats)
1781 else:
1793 else:
1782 d = util.parsedate(date)
1794 d = util.parsedate(date)
1783 ui.write(("internal: %s %s\n") % d)
1795 ui.write(("internal: %s %s\n") % d)
1784 ui.write(("standard: %s\n") % util.datestr(d))
1796 ui.write(("standard: %s\n") % util.datestr(d))
1785 if range:
1797 if range:
1786 m = util.matchdate(range)
1798 m = util.matchdate(range)
1787 ui.write(("match: %s\n") % m(d[0]))
1799 ui.write(("match: %s\n") % m(d[0]))
1788
1800
1789 @command('debugdiscovery',
1801 @command('debugdiscovery',
1790 [('', 'old', None, _('use old-style discovery')),
1802 [('', 'old', None, _('use old-style discovery')),
1791 ('', 'nonheads', None,
1803 ('', 'nonheads', None,
1792 _('use old-style discovery with non-heads included')),
1804 _('use old-style discovery with non-heads included')),
1793 ] + remoteopts,
1805 ] + remoteopts,
1794 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1806 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1795 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1807 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1796 """runs the changeset discovery protocol in isolation"""
1808 """runs the changeset discovery protocol in isolation"""
1797 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1809 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1798 opts.get('branch'))
1810 opts.get('branch'))
1799 remote = hg.peer(repo, opts, remoteurl)
1811 remote = hg.peer(repo, opts, remoteurl)
1800 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1812 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1801
1813
1802 # make sure tests are repeatable
1814 # make sure tests are repeatable
1803 random.seed(12323)
1815 random.seed(12323)
1804
1816
1805 def doit(localheads, remoteheads, remote=remote):
1817 def doit(localheads, remoteheads, remote=remote):
1806 if opts.get('old'):
1818 if opts.get('old'):
1807 if localheads:
1819 if localheads:
1808 raise util.Abort('cannot use localheads with old style '
1820 raise util.Abort('cannot use localheads with old style '
1809 'discovery')
1821 'discovery')
1810 if not util.safehasattr(remote, 'branches'):
1822 if not util.safehasattr(remote, 'branches'):
1811 # enable in-client legacy support
1823 # enable in-client legacy support
1812 remote = localrepo.locallegacypeer(remote.local())
1824 remote = localrepo.locallegacypeer(remote.local())
1813 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1825 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1814 force=True)
1826 force=True)
1815 common = set(common)
1827 common = set(common)
1816 if not opts.get('nonheads'):
1828 if not opts.get('nonheads'):
1817 ui.write(("unpruned common: %s\n") %
1829 ui.write(("unpruned common: %s\n") %
1818 " ".join(sorted(short(n) for n in common)))
1830 " ".join(sorted(short(n) for n in common)))
1819 dag = dagutil.revlogdag(repo.changelog)
1831 dag = dagutil.revlogdag(repo.changelog)
1820 all = dag.ancestorset(dag.internalizeall(common))
1832 all = dag.ancestorset(dag.internalizeall(common))
1821 common = dag.externalizeall(dag.headsetofconnecteds(all))
1833 common = dag.externalizeall(dag.headsetofconnecteds(all))
1822 else:
1834 else:
1823 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1835 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1824 common = set(common)
1836 common = set(common)
1825 rheads = set(hds)
1837 rheads = set(hds)
1826 lheads = set(repo.heads())
1838 lheads = set(repo.heads())
1827 ui.write(("common heads: %s\n") %
1839 ui.write(("common heads: %s\n") %
1828 " ".join(sorted(short(n) for n in common)))
1840 " ".join(sorted(short(n) for n in common)))
1829 if lheads <= common:
1841 if lheads <= common:
1830 ui.write(("local is subset\n"))
1842 ui.write(("local is subset\n"))
1831 elif rheads <= common:
1843 elif rheads <= common:
1832 ui.write(("remote is subset\n"))
1844 ui.write(("remote is subset\n"))
1833
1845
1834 serverlogs = opts.get('serverlog')
1846 serverlogs = opts.get('serverlog')
1835 if serverlogs:
1847 if serverlogs:
1836 for filename in serverlogs:
1848 for filename in serverlogs:
1837 logfile = open(filename, 'r')
1849 logfile = open(filename, 'r')
1838 try:
1850 try:
1839 line = logfile.readline()
1851 line = logfile.readline()
1840 while line:
1852 while line:
1841 parts = line.strip().split(';')
1853 parts = line.strip().split(';')
1842 op = parts[1]
1854 op = parts[1]
1843 if op == 'cg':
1855 if op == 'cg':
1844 pass
1856 pass
1845 elif op == 'cgss':
1857 elif op == 'cgss':
1846 doit(parts[2].split(' '), parts[3].split(' '))
1858 doit(parts[2].split(' '), parts[3].split(' '))
1847 elif op == 'unb':
1859 elif op == 'unb':
1848 doit(parts[3].split(' '), parts[2].split(' '))
1860 doit(parts[3].split(' '), parts[2].split(' '))
1849 line = logfile.readline()
1861 line = logfile.readline()
1850 finally:
1862 finally:
1851 logfile.close()
1863 logfile.close()
1852
1864
1853 else:
1865 else:
1854 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1866 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1855 opts.get('remote_head'))
1867 opts.get('remote_head'))
1856 localrevs = opts.get('local_head')
1868 localrevs = opts.get('local_head')
1857 doit(localrevs, remoterevs)
1869 doit(localrevs, remoterevs)
1858
1870
1859 @command('debugfileset',
1871 @command('debugfileset',
1860 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1872 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1861 _('[-r REV] FILESPEC'))
1873 _('[-r REV] FILESPEC'))
1862 def debugfileset(ui, repo, expr, **opts):
1874 def debugfileset(ui, repo, expr, **opts):
1863 '''parse and apply a fileset specification'''
1875 '''parse and apply a fileset specification'''
1864 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1876 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1865 if ui.verbose:
1877 if ui.verbose:
1866 tree = fileset.parse(expr)[0]
1878 tree = fileset.parse(expr)[0]
1867 ui.note(tree, "\n")
1879 ui.note(tree, "\n")
1868
1880
1869 for f in fileset.getfileset(ctx, expr):
1881 for f in fileset.getfileset(ctx, expr):
1870 ui.write("%s\n" % f)
1882 ui.write("%s\n" % f)
1871
1883
1872 @command('debugfsinfo', [], _('[PATH]'))
1884 @command('debugfsinfo', [], _('[PATH]'))
1873 def debugfsinfo(ui, path = "."):
1885 def debugfsinfo(ui, path = "."):
1874 """show information detected about current filesystem"""
1886 """show information detected about current filesystem"""
1875 util.writefile('.debugfsinfo', '')
1887 util.writefile('.debugfsinfo', '')
1876 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1888 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1877 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1889 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1878 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1890 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1879 and 'yes' or 'no'))
1891 and 'yes' or 'no'))
1880 os.unlink('.debugfsinfo')
1892 os.unlink('.debugfsinfo')
1881
1893
1882 @command('debuggetbundle',
1894 @command('debuggetbundle',
1883 [('H', 'head', [], _('id of head node'), _('ID')),
1895 [('H', 'head', [], _('id of head node'), _('ID')),
1884 ('C', 'common', [], _('id of common node'), _('ID')),
1896 ('C', 'common', [], _('id of common node'), _('ID')),
1885 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1897 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1886 _('REPO FILE [-H|-C ID]...'))
1898 _('REPO FILE [-H|-C ID]...'))
1887 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1899 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1888 """retrieves a bundle from a repo
1900 """retrieves a bundle from a repo
1889
1901
1890 Every ID must be a full-length hex node id string. Saves the bundle to the
1902 Every ID must be a full-length hex node id string. Saves the bundle to the
1891 given file.
1903 given file.
1892 """
1904 """
1893 repo = hg.peer(ui, opts, repopath)
1905 repo = hg.peer(ui, opts, repopath)
1894 if not repo.capable('getbundle'):
1906 if not repo.capable('getbundle'):
1895 raise util.Abort("getbundle() not supported by target repository")
1907 raise util.Abort("getbundle() not supported by target repository")
1896 args = {}
1908 args = {}
1897 if common:
1909 if common:
1898 args['common'] = [bin(s) for s in common]
1910 args['common'] = [bin(s) for s in common]
1899 if head:
1911 if head:
1900 args['heads'] = [bin(s) for s in head]
1912 args['heads'] = [bin(s) for s in head]
1901 bundle = repo.getbundle('debug', **args)
1913 bundle = repo.getbundle('debug', **args)
1902
1914
1903 bundletype = opts.get('type', 'bzip2').lower()
1915 bundletype = opts.get('type', 'bzip2').lower()
1904 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1916 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1905 bundletype = btypes.get(bundletype)
1917 bundletype = btypes.get(bundletype)
1906 if bundletype not in changegroup.bundletypes:
1918 if bundletype not in changegroup.bundletypes:
1907 raise util.Abort(_('unknown bundle type specified with --type'))
1919 raise util.Abort(_('unknown bundle type specified with --type'))
1908 changegroup.writebundle(bundle, bundlepath, bundletype)
1920 changegroup.writebundle(bundle, bundlepath, bundletype)
1909
1921
1910 @command('debugignore', [], '')
1922 @command('debugignore', [], '')
1911 def debugignore(ui, repo, *values, **opts):
1923 def debugignore(ui, repo, *values, **opts):
1912 """display the combined ignore pattern"""
1924 """display the combined ignore pattern"""
1913 ignore = repo.dirstate._ignore
1925 ignore = repo.dirstate._ignore
1914 includepat = getattr(ignore, 'includepat', None)
1926 includepat = getattr(ignore, 'includepat', None)
1915 if includepat is not None:
1927 if includepat is not None:
1916 ui.write("%s\n" % includepat)
1928 ui.write("%s\n" % includepat)
1917 else:
1929 else:
1918 raise util.Abort(_("no ignore patterns found"))
1930 raise util.Abort(_("no ignore patterns found"))
1919
1931
1920 @command('debugindex',
1932 @command('debugindex',
1921 [('c', 'changelog', False, _('open changelog')),
1933 [('c', 'changelog', False, _('open changelog')),
1922 ('m', 'manifest', False, _('open manifest')),
1934 ('m', 'manifest', False, _('open manifest')),
1923 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1935 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1924 _('[-f FORMAT] -c|-m|FILE'))
1936 _('[-f FORMAT] -c|-m|FILE'))
1925 def debugindex(ui, repo, file_ = None, **opts):
1937 def debugindex(ui, repo, file_ = None, **opts):
1926 """dump the contents of an index file"""
1938 """dump the contents of an index file"""
1927 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1939 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1928 format = opts.get('format', 0)
1940 format = opts.get('format', 0)
1929 if format not in (0, 1):
1941 if format not in (0, 1):
1930 raise util.Abort(_("unknown format %d") % format)
1942 raise util.Abort(_("unknown format %d") % format)
1931
1943
1932 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1944 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1933 if generaldelta:
1945 if generaldelta:
1934 basehdr = ' delta'
1946 basehdr = ' delta'
1935 else:
1947 else:
1936 basehdr = ' base'
1948 basehdr = ' base'
1937
1949
1938 if format == 0:
1950 if format == 0:
1939 ui.write(" rev offset length " + basehdr + " linkrev"
1951 ui.write(" rev offset length " + basehdr + " linkrev"
1940 " nodeid p1 p2\n")
1952 " nodeid p1 p2\n")
1941 elif format == 1:
1953 elif format == 1:
1942 ui.write(" rev flag offset length"
1954 ui.write(" rev flag offset length"
1943 " size " + basehdr + " link p1 p2"
1955 " size " + basehdr + " link p1 p2"
1944 " nodeid\n")
1956 " nodeid\n")
1945
1957
1946 for i in r:
1958 for i in r:
1947 node = r.node(i)
1959 node = r.node(i)
1948 if generaldelta:
1960 if generaldelta:
1949 base = r.deltaparent(i)
1961 base = r.deltaparent(i)
1950 else:
1962 else:
1951 base = r.chainbase(i)
1963 base = r.chainbase(i)
1952 if format == 0:
1964 if format == 0:
1953 try:
1965 try:
1954 pp = r.parents(node)
1966 pp = r.parents(node)
1955 except Exception:
1967 except Exception:
1956 pp = [nullid, nullid]
1968 pp = [nullid, nullid]
1957 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1969 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1958 i, r.start(i), r.length(i), base, r.linkrev(i),
1970 i, r.start(i), r.length(i), base, r.linkrev(i),
1959 short(node), short(pp[0]), short(pp[1])))
1971 short(node), short(pp[0]), short(pp[1])))
1960 elif format == 1:
1972 elif format == 1:
1961 pr = r.parentrevs(i)
1973 pr = r.parentrevs(i)
1962 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1974 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1963 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1975 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1964 base, r.linkrev(i), pr[0], pr[1], short(node)))
1976 base, r.linkrev(i), pr[0], pr[1], short(node)))
1965
1977
1966 @command('debugindexdot', [], _('FILE'))
1978 @command('debugindexdot', [], _('FILE'))
1967 def debugindexdot(ui, repo, file_):
1979 def debugindexdot(ui, repo, file_):
1968 """dump an index DAG as a graphviz dot file"""
1980 """dump an index DAG as a graphviz dot file"""
1969 r = None
1981 r = None
1970 if repo:
1982 if repo:
1971 filelog = repo.file(file_)
1983 filelog = repo.file(file_)
1972 if len(filelog):
1984 if len(filelog):
1973 r = filelog
1985 r = filelog
1974 if not r:
1986 if not r:
1975 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1987 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1976 ui.write(("digraph G {\n"))
1988 ui.write(("digraph G {\n"))
1977 for i in r:
1989 for i in r:
1978 node = r.node(i)
1990 node = r.node(i)
1979 pp = r.parents(node)
1991 pp = r.parents(node)
1980 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1992 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1981 if pp[1] != nullid:
1993 if pp[1] != nullid:
1982 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1994 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1983 ui.write("}\n")
1995 ui.write("}\n")
1984
1996
1985 @command('debuginstall', [], '')
1997 @command('debuginstall', [], '')
1986 def debuginstall(ui):
1998 def debuginstall(ui):
1987 '''test Mercurial installation
1999 '''test Mercurial installation
1988
2000
1989 Returns 0 on success.
2001 Returns 0 on success.
1990 '''
2002 '''
1991
2003
1992 def writetemp(contents):
2004 def writetemp(contents):
1993 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2005 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1994 f = os.fdopen(fd, "wb")
2006 f = os.fdopen(fd, "wb")
1995 f.write(contents)
2007 f.write(contents)
1996 f.close()
2008 f.close()
1997 return name
2009 return name
1998
2010
1999 problems = 0
2011 problems = 0
2000
2012
2001 # encoding
2013 # encoding
2002 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2014 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2003 try:
2015 try:
2004 encoding.fromlocal("test")
2016 encoding.fromlocal("test")
2005 except util.Abort, inst:
2017 except util.Abort, inst:
2006 ui.write(" %s\n" % inst)
2018 ui.write(" %s\n" % inst)
2007 ui.write(_(" (check that your locale is properly set)\n"))
2019 ui.write(_(" (check that your locale is properly set)\n"))
2008 problems += 1
2020 problems += 1
2009
2021
2010 # Python lib
2022 # Python lib
2011 ui.status(_("checking Python lib (%s)...\n")
2023 ui.status(_("checking Python lib (%s)...\n")
2012 % os.path.dirname(os.__file__))
2024 % os.path.dirname(os.__file__))
2013
2025
2014 # compiled modules
2026 # compiled modules
2015 ui.status(_("checking installed modules (%s)...\n")
2027 ui.status(_("checking installed modules (%s)...\n")
2016 % os.path.dirname(__file__))
2028 % os.path.dirname(__file__))
2017 try:
2029 try:
2018 import bdiff, mpatch, base85, osutil
2030 import bdiff, mpatch, base85, osutil
2019 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2031 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2020 except Exception, inst:
2032 except Exception, inst:
2021 ui.write(" %s\n" % inst)
2033 ui.write(" %s\n" % inst)
2022 ui.write(_(" One or more extensions could not be found"))
2034 ui.write(_(" One or more extensions could not be found"))
2023 ui.write(_(" (check that you compiled the extensions)\n"))
2035 ui.write(_(" (check that you compiled the extensions)\n"))
2024 problems += 1
2036 problems += 1
2025
2037
2026 # templates
2038 # templates
2027 import templater
2039 import templater
2028 p = templater.templatepath()
2040 p = templater.templatepath()
2029 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2041 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2030 try:
2042 try:
2031 templater.templater(templater.templatepath("map-cmdline.default"))
2043 templater.templater(templater.templatepath("map-cmdline.default"))
2032 except Exception, inst:
2044 except Exception, inst:
2033 ui.write(" %s\n" % inst)
2045 ui.write(" %s\n" % inst)
2034 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2046 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2035 problems += 1
2047 problems += 1
2036
2048
2037 # editor
2049 # editor
2038 ui.status(_("checking commit editor...\n"))
2050 ui.status(_("checking commit editor...\n"))
2039 editor = ui.geteditor()
2051 editor = ui.geteditor()
2040 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2052 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2041 if not cmdpath:
2053 if not cmdpath:
2042 if editor == 'vi':
2054 if editor == 'vi':
2043 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2055 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2044 ui.write(_(" (specify a commit editor in your configuration"
2056 ui.write(_(" (specify a commit editor in your configuration"
2045 " file)\n"))
2057 " file)\n"))
2046 else:
2058 else:
2047 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2059 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2048 ui.write(_(" (specify a commit editor in your configuration"
2060 ui.write(_(" (specify a commit editor in your configuration"
2049 " file)\n"))
2061 " file)\n"))
2050 problems += 1
2062 problems += 1
2051
2063
2052 # check username
2064 # check username
2053 ui.status(_("checking username...\n"))
2065 ui.status(_("checking username...\n"))
2054 try:
2066 try:
2055 ui.username()
2067 ui.username()
2056 except util.Abort, e:
2068 except util.Abort, e:
2057 ui.write(" %s\n" % e)
2069 ui.write(" %s\n" % e)
2058 ui.write(_(" (specify a username in your configuration file)\n"))
2070 ui.write(_(" (specify a username in your configuration file)\n"))
2059 problems += 1
2071 problems += 1
2060
2072
2061 if not problems:
2073 if not problems:
2062 ui.status(_("no problems detected\n"))
2074 ui.status(_("no problems detected\n"))
2063 else:
2075 else:
2064 ui.write(_("%s problems detected,"
2076 ui.write(_("%s problems detected,"
2065 " please check your install!\n") % problems)
2077 " please check your install!\n") % problems)
2066
2078
2067 return problems
2079 return problems
2068
2080
2069 @command('debugknown', [], _('REPO ID...'))
2081 @command('debugknown', [], _('REPO ID...'))
2070 def debugknown(ui, repopath, *ids, **opts):
2082 def debugknown(ui, repopath, *ids, **opts):
2071 """test whether node ids are known to a repo
2083 """test whether node ids are known to a repo
2072
2084
2073 Every ID must be a full-length hex node id string. Returns a list of 0s
2085 Every ID must be a full-length hex node id string. Returns a list of 0s
2074 and 1s indicating unknown/known.
2086 and 1s indicating unknown/known.
2075 """
2087 """
2076 repo = hg.peer(ui, opts, repopath)
2088 repo = hg.peer(ui, opts, repopath)
2077 if not repo.capable('known'):
2089 if not repo.capable('known'):
2078 raise util.Abort("known() not supported by target repository")
2090 raise util.Abort("known() not supported by target repository")
2079 flags = repo.known([bin(s) for s in ids])
2091 flags = repo.known([bin(s) for s in ids])
2080 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2092 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2081
2093
2082 @command('debuglabelcomplete', [], _('LABEL...'))
2094 @command('debuglabelcomplete', [], _('LABEL...'))
2083 def debuglabelcomplete(ui, repo, *args):
2095 def debuglabelcomplete(ui, repo, *args):
2084 '''complete "labels" - tags, open branch names, bookmark names'''
2096 '''complete "labels" - tags, open branch names, bookmark names'''
2085
2097
2086 labels = set()
2098 labels = set()
2087 labels.update(t[0] for t in repo.tagslist())
2099 labels.update(t[0] for t in repo.tagslist())
2088 labels.update(repo._bookmarks.keys())
2100 labels.update(repo._bookmarks.keys())
2089 for heads in repo.branchmap().itervalues():
2101 for heads in repo.branchmap().itervalues():
2090 for h in heads:
2102 for h in heads:
2091 ctx = repo[h]
2103 ctx = repo[h]
2092 if not ctx.closesbranch():
2104 if not ctx.closesbranch():
2093 labels.add(ctx.branch())
2105 labels.add(ctx.branch())
2094 completions = set()
2106 completions = set()
2095 if not args:
2107 if not args:
2096 args = ['']
2108 args = ['']
2097 for a in args:
2109 for a in args:
2098 completions.update(l for l in labels if l.startswith(a))
2110 completions.update(l for l in labels if l.startswith(a))
2099 ui.write('\n'.join(sorted(completions)))
2111 ui.write('\n'.join(sorted(completions)))
2100 ui.write('\n')
2112 ui.write('\n')
2101
2113
2102 @command('debugobsolete',
2114 @command('debugobsolete',
2103 [('', 'flags', 0, _('markers flag')),
2115 [('', 'flags', 0, _('markers flag')),
2104 ] + commitopts2,
2116 ] + commitopts2,
2105 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2117 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2106 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2118 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2107 """create arbitrary obsolete marker
2119 """create arbitrary obsolete marker
2108
2120
2109 With no arguments, displays the list of obsolescence markers."""
2121 With no arguments, displays the list of obsolescence markers."""
2110 def parsenodeid(s):
2122 def parsenodeid(s):
2111 try:
2123 try:
2112 # We do not use revsingle/revrange functions here to accept
2124 # We do not use revsingle/revrange functions here to accept
2113 # arbitrary node identifiers, possibly not present in the
2125 # arbitrary node identifiers, possibly not present in the
2114 # local repository.
2126 # local repository.
2115 n = bin(s)
2127 n = bin(s)
2116 if len(n) != len(nullid):
2128 if len(n) != len(nullid):
2117 raise TypeError()
2129 raise TypeError()
2118 return n
2130 return n
2119 except TypeError:
2131 except TypeError:
2120 raise util.Abort('changeset references must be full hexadecimal '
2132 raise util.Abort('changeset references must be full hexadecimal '
2121 'node identifiers')
2133 'node identifiers')
2122
2134
2123 if precursor is not None:
2135 if precursor is not None:
2124 metadata = {}
2136 metadata = {}
2125 if 'date' in opts:
2137 if 'date' in opts:
2126 metadata['date'] = opts['date']
2138 metadata['date'] = opts['date']
2127 metadata['user'] = opts['user'] or ui.username()
2139 metadata['user'] = opts['user'] or ui.username()
2128 succs = tuple(parsenodeid(succ) for succ in successors)
2140 succs = tuple(parsenodeid(succ) for succ in successors)
2129 l = repo.lock()
2141 l = repo.lock()
2130 try:
2142 try:
2131 tr = repo.transaction('debugobsolete')
2143 tr = repo.transaction('debugobsolete')
2132 try:
2144 try:
2133 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2145 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2134 opts['flags'], metadata)
2146 opts['flags'], metadata)
2135 tr.close()
2147 tr.close()
2136 finally:
2148 finally:
2137 tr.release()
2149 tr.release()
2138 finally:
2150 finally:
2139 l.release()
2151 l.release()
2140 else:
2152 else:
2141 for m in obsolete.allmarkers(repo):
2153 for m in obsolete.allmarkers(repo):
2142 ui.write(hex(m.precnode()))
2154 ui.write(hex(m.precnode()))
2143 for repl in m.succnodes():
2155 for repl in m.succnodes():
2144 ui.write(' ')
2156 ui.write(' ')
2145 ui.write(hex(repl))
2157 ui.write(hex(repl))
2146 ui.write(' %X ' % m._data[2])
2158 ui.write(' %X ' % m._data[2])
2147 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2159 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2148 sorted(m.metadata().items()))))
2160 sorted(m.metadata().items()))))
2149 ui.write('\n')
2161 ui.write('\n')
2150
2162
2151 @command('debugpathcomplete',
2163 @command('debugpathcomplete',
2152 [('f', 'full', None, _('complete an entire path')),
2164 [('f', 'full', None, _('complete an entire path')),
2153 ('n', 'normal', None, _('show only normal files')),
2165 ('n', 'normal', None, _('show only normal files')),
2154 ('a', 'added', None, _('show only added files')),
2166 ('a', 'added', None, _('show only added files')),
2155 ('r', 'removed', None, _('show only removed files'))],
2167 ('r', 'removed', None, _('show only removed files'))],
2156 _('FILESPEC...'))
2168 _('FILESPEC...'))
2157 def debugpathcomplete(ui, repo, *specs, **opts):
2169 def debugpathcomplete(ui, repo, *specs, **opts):
2158 '''complete part or all of a tracked path
2170 '''complete part or all of a tracked path
2159
2171
2160 This command supports shells that offer path name completion. It
2172 This command supports shells that offer path name completion. It
2161 currently completes only files already known to the dirstate.
2173 currently completes only files already known to the dirstate.
2162
2174
2163 Completion extends only to the next path segment unless
2175 Completion extends only to the next path segment unless
2164 --full is specified, in which case entire paths are used.'''
2176 --full is specified, in which case entire paths are used.'''
2165
2177
2166 def complete(path, acceptable):
2178 def complete(path, acceptable):
2167 dirstate = repo.dirstate
2179 dirstate = repo.dirstate
2168 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2180 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2169 rootdir = repo.root + os.sep
2181 rootdir = repo.root + os.sep
2170 if spec != repo.root and not spec.startswith(rootdir):
2182 if spec != repo.root and not spec.startswith(rootdir):
2171 return [], []
2183 return [], []
2172 if os.path.isdir(spec):
2184 if os.path.isdir(spec):
2173 spec += '/'
2185 spec += '/'
2174 spec = spec[len(rootdir):]
2186 spec = spec[len(rootdir):]
2175 fixpaths = os.sep != '/'
2187 fixpaths = os.sep != '/'
2176 if fixpaths:
2188 if fixpaths:
2177 spec = spec.replace(os.sep, '/')
2189 spec = spec.replace(os.sep, '/')
2178 speclen = len(spec)
2190 speclen = len(spec)
2179 fullpaths = opts['full']
2191 fullpaths = opts['full']
2180 files, dirs = set(), set()
2192 files, dirs = set(), set()
2181 adddir, addfile = dirs.add, files.add
2193 adddir, addfile = dirs.add, files.add
2182 for f, st in dirstate.iteritems():
2194 for f, st in dirstate.iteritems():
2183 if f.startswith(spec) and st[0] in acceptable:
2195 if f.startswith(spec) and st[0] in acceptable:
2184 if fixpaths:
2196 if fixpaths:
2185 f = f.replace('/', os.sep)
2197 f = f.replace('/', os.sep)
2186 if fullpaths:
2198 if fullpaths:
2187 addfile(f)
2199 addfile(f)
2188 continue
2200 continue
2189 s = f.find(os.sep, speclen)
2201 s = f.find(os.sep, speclen)
2190 if s >= 0:
2202 if s >= 0:
2191 adddir(f[:s + 1])
2203 adddir(f[:s + 1])
2192 else:
2204 else:
2193 addfile(f)
2205 addfile(f)
2194 return files, dirs
2206 return files, dirs
2195
2207
2196 acceptable = ''
2208 acceptable = ''
2197 if opts['normal']:
2209 if opts['normal']:
2198 acceptable += 'nm'
2210 acceptable += 'nm'
2199 if opts['added']:
2211 if opts['added']:
2200 acceptable += 'a'
2212 acceptable += 'a'
2201 if opts['removed']:
2213 if opts['removed']:
2202 acceptable += 'r'
2214 acceptable += 'r'
2203 cwd = repo.getcwd()
2215 cwd = repo.getcwd()
2204 if not specs:
2216 if not specs:
2205 specs = ['.']
2217 specs = ['.']
2206
2218
2207 files, dirs = set(), set()
2219 files, dirs = set(), set()
2208 for spec in specs:
2220 for spec in specs:
2209 f, d = complete(spec, acceptable or 'nmar')
2221 f, d = complete(spec, acceptable or 'nmar')
2210 files.update(f)
2222 files.update(f)
2211 dirs.update(d)
2223 dirs.update(d)
2212 if not files and len(dirs) == 1:
2224 if not files and len(dirs) == 1:
2213 # force the shell to consider a completion that matches one
2225 # force the shell to consider a completion that matches one
2214 # directory and zero files to be ambiguous
2226 # directory and zero files to be ambiguous
2215 dirs.add(iter(dirs).next() + '.')
2227 dirs.add(iter(dirs).next() + '.')
2216 files.update(dirs)
2228 files.update(dirs)
2217 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2229 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2218 ui.write('\n')
2230 ui.write('\n')
2219
2231
2220 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2232 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2221 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2233 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2222 '''access the pushkey key/value protocol
2234 '''access the pushkey key/value protocol
2223
2235
2224 With two args, list the keys in the given namespace.
2236 With two args, list the keys in the given namespace.
2225
2237
2226 With five args, set a key to new if it currently is set to old.
2238 With five args, set a key to new if it currently is set to old.
2227 Reports success or failure.
2239 Reports success or failure.
2228 '''
2240 '''
2229
2241
2230 target = hg.peer(ui, {}, repopath)
2242 target = hg.peer(ui, {}, repopath)
2231 if keyinfo:
2243 if keyinfo:
2232 key, old, new = keyinfo
2244 key, old, new = keyinfo
2233 r = target.pushkey(namespace, key, old, new)
2245 r = target.pushkey(namespace, key, old, new)
2234 ui.status(str(r) + '\n')
2246 ui.status(str(r) + '\n')
2235 return not r
2247 return not r
2236 else:
2248 else:
2237 for k, v in sorted(target.listkeys(namespace).iteritems()):
2249 for k, v in sorted(target.listkeys(namespace).iteritems()):
2238 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2250 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2239 v.encode('string-escape')))
2251 v.encode('string-escape')))
2240
2252
2241 @command('debugpvec', [], _('A B'))
2253 @command('debugpvec', [], _('A B'))
2242 def debugpvec(ui, repo, a, b=None):
2254 def debugpvec(ui, repo, a, b=None):
2243 ca = scmutil.revsingle(repo, a)
2255 ca = scmutil.revsingle(repo, a)
2244 cb = scmutil.revsingle(repo, b)
2256 cb = scmutil.revsingle(repo, b)
2245 pa = pvec.ctxpvec(ca)
2257 pa = pvec.ctxpvec(ca)
2246 pb = pvec.ctxpvec(cb)
2258 pb = pvec.ctxpvec(cb)
2247 if pa == pb:
2259 if pa == pb:
2248 rel = "="
2260 rel = "="
2249 elif pa > pb:
2261 elif pa > pb:
2250 rel = ">"
2262 rel = ">"
2251 elif pa < pb:
2263 elif pa < pb:
2252 rel = "<"
2264 rel = "<"
2253 elif pa | pb:
2265 elif pa | pb:
2254 rel = "|"
2266 rel = "|"
2255 ui.write(_("a: %s\n") % pa)
2267 ui.write(_("a: %s\n") % pa)
2256 ui.write(_("b: %s\n") % pb)
2268 ui.write(_("b: %s\n") % pb)
2257 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2269 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2258 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2270 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2259 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2271 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2260 pa.distance(pb), rel))
2272 pa.distance(pb), rel))
2261
2273
2262 @command('debugrebuilddirstate|debugrebuildstate',
2274 @command('debugrebuilddirstate|debugrebuildstate',
2263 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2275 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2264 _('[-r REV]'))
2276 _('[-r REV]'))
2265 def debugrebuilddirstate(ui, repo, rev):
2277 def debugrebuilddirstate(ui, repo, rev):
2266 """rebuild the dirstate as it would look like for the given revision
2278 """rebuild the dirstate as it would look like for the given revision
2267
2279
2268 If no revision is specified the first current parent will be used.
2280 If no revision is specified the first current parent will be used.
2269
2281
2270 The dirstate will be set to the files of the given revision.
2282 The dirstate will be set to the files of the given revision.
2271 The actual working directory content or existing dirstate
2283 The actual working directory content or existing dirstate
2272 information such as adds or removes is not considered.
2284 information such as adds or removes is not considered.
2273
2285
2274 One use of this command is to make the next :hg:`status` invocation
2286 One use of this command is to make the next :hg:`status` invocation
2275 check the actual file content.
2287 check the actual file content.
2276 """
2288 """
2277 ctx = scmutil.revsingle(repo, rev)
2289 ctx = scmutil.revsingle(repo, rev)
2278 wlock = repo.wlock()
2290 wlock = repo.wlock()
2279 try:
2291 try:
2280 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2292 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2281 finally:
2293 finally:
2282 wlock.release()
2294 wlock.release()
2283
2295
2284 @command('debugrename',
2296 @command('debugrename',
2285 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2297 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2286 _('[-r REV] FILE'))
2298 _('[-r REV] FILE'))
2287 def debugrename(ui, repo, file1, *pats, **opts):
2299 def debugrename(ui, repo, file1, *pats, **opts):
2288 """dump rename information"""
2300 """dump rename information"""
2289
2301
2290 ctx = scmutil.revsingle(repo, opts.get('rev'))
2302 ctx = scmutil.revsingle(repo, opts.get('rev'))
2291 m = scmutil.match(ctx, (file1,) + pats, opts)
2303 m = scmutil.match(ctx, (file1,) + pats, opts)
2292 for abs in ctx.walk(m):
2304 for abs in ctx.walk(m):
2293 fctx = ctx[abs]
2305 fctx = ctx[abs]
2294 o = fctx.filelog().renamed(fctx.filenode())
2306 o = fctx.filelog().renamed(fctx.filenode())
2295 rel = m.rel(abs)
2307 rel = m.rel(abs)
2296 if o:
2308 if o:
2297 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2309 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2298 else:
2310 else:
2299 ui.write(_("%s not renamed\n") % rel)
2311 ui.write(_("%s not renamed\n") % rel)
2300
2312
2301 @command('debugrevlog',
2313 @command('debugrevlog',
2302 [('c', 'changelog', False, _('open changelog')),
2314 [('c', 'changelog', False, _('open changelog')),
2303 ('m', 'manifest', False, _('open manifest')),
2315 ('m', 'manifest', False, _('open manifest')),
2304 ('d', 'dump', False, _('dump index data'))],
2316 ('d', 'dump', False, _('dump index data'))],
2305 _('-c|-m|FILE'))
2317 _('-c|-m|FILE'))
2306 def debugrevlog(ui, repo, file_ = None, **opts):
2318 def debugrevlog(ui, repo, file_ = None, **opts):
2307 """show data and statistics about a revlog"""
2319 """show data and statistics about a revlog"""
2308 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2320 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2309
2321
2310 if opts.get("dump"):
2322 if opts.get("dump"):
2311 numrevs = len(r)
2323 numrevs = len(r)
2312 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2324 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2313 " rawsize totalsize compression heads\n")
2325 " rawsize totalsize compression heads\n")
2314 ts = 0
2326 ts = 0
2315 heads = set()
2327 heads = set()
2316 for rev in xrange(numrevs):
2328 for rev in xrange(numrevs):
2317 dbase = r.deltaparent(rev)
2329 dbase = r.deltaparent(rev)
2318 if dbase == -1:
2330 if dbase == -1:
2319 dbase = rev
2331 dbase = rev
2320 cbase = r.chainbase(rev)
2332 cbase = r.chainbase(rev)
2321 p1, p2 = r.parentrevs(rev)
2333 p1, p2 = r.parentrevs(rev)
2322 rs = r.rawsize(rev)
2334 rs = r.rawsize(rev)
2323 ts = ts + rs
2335 ts = ts + rs
2324 heads -= set(r.parentrevs(rev))
2336 heads -= set(r.parentrevs(rev))
2325 heads.add(rev)
2337 heads.add(rev)
2326 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2338 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2327 (rev, p1, p2, r.start(rev), r.end(rev),
2339 (rev, p1, p2, r.start(rev), r.end(rev),
2328 r.start(dbase), r.start(cbase),
2340 r.start(dbase), r.start(cbase),
2329 r.start(p1), r.start(p2),
2341 r.start(p1), r.start(p2),
2330 rs, ts, ts / r.end(rev), len(heads)))
2342 rs, ts, ts / r.end(rev), len(heads)))
2331 return 0
2343 return 0
2332
2344
2333 v = r.version
2345 v = r.version
2334 format = v & 0xFFFF
2346 format = v & 0xFFFF
2335 flags = []
2347 flags = []
2336 gdelta = False
2348 gdelta = False
2337 if v & revlog.REVLOGNGINLINEDATA:
2349 if v & revlog.REVLOGNGINLINEDATA:
2338 flags.append('inline')
2350 flags.append('inline')
2339 if v & revlog.REVLOGGENERALDELTA:
2351 if v & revlog.REVLOGGENERALDELTA:
2340 gdelta = True
2352 gdelta = True
2341 flags.append('generaldelta')
2353 flags.append('generaldelta')
2342 if not flags:
2354 if not flags:
2343 flags = ['(none)']
2355 flags = ['(none)']
2344
2356
2345 nummerges = 0
2357 nummerges = 0
2346 numfull = 0
2358 numfull = 0
2347 numprev = 0
2359 numprev = 0
2348 nump1 = 0
2360 nump1 = 0
2349 nump2 = 0
2361 nump2 = 0
2350 numother = 0
2362 numother = 0
2351 nump1prev = 0
2363 nump1prev = 0
2352 nump2prev = 0
2364 nump2prev = 0
2353 chainlengths = []
2365 chainlengths = []
2354
2366
2355 datasize = [None, 0, 0L]
2367 datasize = [None, 0, 0L]
2356 fullsize = [None, 0, 0L]
2368 fullsize = [None, 0, 0L]
2357 deltasize = [None, 0, 0L]
2369 deltasize = [None, 0, 0L]
2358
2370
2359 def addsize(size, l):
2371 def addsize(size, l):
2360 if l[0] is None or size < l[0]:
2372 if l[0] is None or size < l[0]:
2361 l[0] = size
2373 l[0] = size
2362 if size > l[1]:
2374 if size > l[1]:
2363 l[1] = size
2375 l[1] = size
2364 l[2] += size
2376 l[2] += size
2365
2377
2366 numrevs = len(r)
2378 numrevs = len(r)
2367 for rev in xrange(numrevs):
2379 for rev in xrange(numrevs):
2368 p1, p2 = r.parentrevs(rev)
2380 p1, p2 = r.parentrevs(rev)
2369 delta = r.deltaparent(rev)
2381 delta = r.deltaparent(rev)
2370 if format > 0:
2382 if format > 0:
2371 addsize(r.rawsize(rev), datasize)
2383 addsize(r.rawsize(rev), datasize)
2372 if p2 != nullrev:
2384 if p2 != nullrev:
2373 nummerges += 1
2385 nummerges += 1
2374 size = r.length(rev)
2386 size = r.length(rev)
2375 if delta == nullrev:
2387 if delta == nullrev:
2376 chainlengths.append(0)
2388 chainlengths.append(0)
2377 numfull += 1
2389 numfull += 1
2378 addsize(size, fullsize)
2390 addsize(size, fullsize)
2379 else:
2391 else:
2380 chainlengths.append(chainlengths[delta] + 1)
2392 chainlengths.append(chainlengths[delta] + 1)
2381 addsize(size, deltasize)
2393 addsize(size, deltasize)
2382 if delta == rev - 1:
2394 if delta == rev - 1:
2383 numprev += 1
2395 numprev += 1
2384 if delta == p1:
2396 if delta == p1:
2385 nump1prev += 1
2397 nump1prev += 1
2386 elif delta == p2:
2398 elif delta == p2:
2387 nump2prev += 1
2399 nump2prev += 1
2388 elif delta == p1:
2400 elif delta == p1:
2389 nump1 += 1
2401 nump1 += 1
2390 elif delta == p2:
2402 elif delta == p2:
2391 nump2 += 1
2403 nump2 += 1
2392 elif delta != nullrev:
2404 elif delta != nullrev:
2393 numother += 1
2405 numother += 1
2394
2406
2395 # Adjust size min value for empty cases
2407 # Adjust size min value for empty cases
2396 for size in (datasize, fullsize, deltasize):
2408 for size in (datasize, fullsize, deltasize):
2397 if size[0] is None:
2409 if size[0] is None:
2398 size[0] = 0
2410 size[0] = 0
2399
2411
2400 numdeltas = numrevs - numfull
2412 numdeltas = numrevs - numfull
2401 numoprev = numprev - nump1prev - nump2prev
2413 numoprev = numprev - nump1prev - nump2prev
2402 totalrawsize = datasize[2]
2414 totalrawsize = datasize[2]
2403 datasize[2] /= numrevs
2415 datasize[2] /= numrevs
2404 fulltotal = fullsize[2]
2416 fulltotal = fullsize[2]
2405 fullsize[2] /= numfull
2417 fullsize[2] /= numfull
2406 deltatotal = deltasize[2]
2418 deltatotal = deltasize[2]
2407 if numrevs - numfull > 0:
2419 if numrevs - numfull > 0:
2408 deltasize[2] /= numrevs - numfull
2420 deltasize[2] /= numrevs - numfull
2409 totalsize = fulltotal + deltatotal
2421 totalsize = fulltotal + deltatotal
2410 avgchainlen = sum(chainlengths) / numrevs
2422 avgchainlen = sum(chainlengths) / numrevs
2411 compratio = totalrawsize / totalsize
2423 compratio = totalrawsize / totalsize
2412
2424
2413 basedfmtstr = '%%%dd\n'
2425 basedfmtstr = '%%%dd\n'
2414 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2426 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2415
2427
2416 def dfmtstr(max):
2428 def dfmtstr(max):
2417 return basedfmtstr % len(str(max))
2429 return basedfmtstr % len(str(max))
2418 def pcfmtstr(max, padding=0):
2430 def pcfmtstr(max, padding=0):
2419 return basepcfmtstr % (len(str(max)), ' ' * padding)
2431 return basepcfmtstr % (len(str(max)), ' ' * padding)
2420
2432
2421 def pcfmt(value, total):
2433 def pcfmt(value, total):
2422 return (value, 100 * float(value) / total)
2434 return (value, 100 * float(value) / total)
2423
2435
2424 ui.write(('format : %d\n') % format)
2436 ui.write(('format : %d\n') % format)
2425 ui.write(('flags : %s\n') % ', '.join(flags))
2437 ui.write(('flags : %s\n') % ', '.join(flags))
2426
2438
2427 ui.write('\n')
2439 ui.write('\n')
2428 fmt = pcfmtstr(totalsize)
2440 fmt = pcfmtstr(totalsize)
2429 fmt2 = dfmtstr(totalsize)
2441 fmt2 = dfmtstr(totalsize)
2430 ui.write(('revisions : ') + fmt2 % numrevs)
2442 ui.write(('revisions : ') + fmt2 % numrevs)
2431 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2443 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2432 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2444 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2433 ui.write(('revisions : ') + fmt2 % numrevs)
2445 ui.write(('revisions : ') + fmt2 % numrevs)
2434 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2446 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2435 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2447 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2436 ui.write(('revision size : ') + fmt2 % totalsize)
2448 ui.write(('revision size : ') + fmt2 % totalsize)
2437 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2449 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2438 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2450 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2439
2451
2440 ui.write('\n')
2452 ui.write('\n')
2441 fmt = dfmtstr(max(avgchainlen, compratio))
2453 fmt = dfmtstr(max(avgchainlen, compratio))
2442 ui.write(('avg chain length : ') + fmt % avgchainlen)
2454 ui.write(('avg chain length : ') + fmt % avgchainlen)
2443 ui.write(('compression ratio : ') + fmt % compratio)
2455 ui.write(('compression ratio : ') + fmt % compratio)
2444
2456
2445 if format > 0:
2457 if format > 0:
2446 ui.write('\n')
2458 ui.write('\n')
2447 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2459 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2448 % tuple(datasize))
2460 % tuple(datasize))
2449 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2461 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2450 % tuple(fullsize))
2462 % tuple(fullsize))
2451 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2463 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2452 % tuple(deltasize))
2464 % tuple(deltasize))
2453
2465
2454 if numdeltas > 0:
2466 if numdeltas > 0:
2455 ui.write('\n')
2467 ui.write('\n')
2456 fmt = pcfmtstr(numdeltas)
2468 fmt = pcfmtstr(numdeltas)
2457 fmt2 = pcfmtstr(numdeltas, 4)
2469 fmt2 = pcfmtstr(numdeltas, 4)
2458 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2470 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2459 if numprev > 0:
2471 if numprev > 0:
2460 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2472 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2461 numprev))
2473 numprev))
2462 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2474 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2463 numprev))
2475 numprev))
2464 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2476 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2465 numprev))
2477 numprev))
2466 if gdelta:
2478 if gdelta:
2467 ui.write(('deltas against p1 : ')
2479 ui.write(('deltas against p1 : ')
2468 + fmt % pcfmt(nump1, numdeltas))
2480 + fmt % pcfmt(nump1, numdeltas))
2469 ui.write(('deltas against p2 : ')
2481 ui.write(('deltas against p2 : ')
2470 + fmt % pcfmt(nump2, numdeltas))
2482 + fmt % pcfmt(nump2, numdeltas))
2471 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2483 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2472 numdeltas))
2484 numdeltas))
2473
2485
2474 @command('debugrevspec', [], ('REVSPEC'))
2486 @command('debugrevspec', [], ('REVSPEC'))
2475 def debugrevspec(ui, repo, expr):
2487 def debugrevspec(ui, repo, expr):
2476 """parse and apply a revision specification
2488 """parse and apply a revision specification
2477
2489
2478 Use --verbose to print the parsed tree before and after aliases
2490 Use --verbose to print the parsed tree before and after aliases
2479 expansion.
2491 expansion.
2480 """
2492 """
2481 if ui.verbose:
2493 if ui.verbose:
2482 tree = revset.parse(expr)[0]
2494 tree = revset.parse(expr)[0]
2483 ui.note(revset.prettyformat(tree), "\n")
2495 ui.note(revset.prettyformat(tree), "\n")
2484 newtree = revset.findaliases(ui, tree)
2496 newtree = revset.findaliases(ui, tree)
2485 if newtree != tree:
2497 if newtree != tree:
2486 ui.note(revset.prettyformat(newtree), "\n")
2498 ui.note(revset.prettyformat(newtree), "\n")
2487 func = revset.match(ui, expr)
2499 func = revset.match(ui, expr)
2488 for c in func(repo, range(len(repo))):
2500 for c in func(repo, range(len(repo))):
2489 ui.write("%s\n" % c)
2501 ui.write("%s\n" % c)
2490
2502
2491 @command('debugsetparents', [], _('REV1 [REV2]'))
2503 @command('debugsetparents', [], _('REV1 [REV2]'))
2492 def debugsetparents(ui, repo, rev1, rev2=None):
2504 def debugsetparents(ui, repo, rev1, rev2=None):
2493 """manually set the parents of the current working directory
2505 """manually set the parents of the current working directory
2494
2506
2495 This is useful for writing repository conversion tools, but should
2507 This is useful for writing repository conversion tools, but should
2496 be used with care.
2508 be used with care.
2497
2509
2498 Returns 0 on success.
2510 Returns 0 on success.
2499 """
2511 """
2500
2512
2501 r1 = scmutil.revsingle(repo, rev1).node()
2513 r1 = scmutil.revsingle(repo, rev1).node()
2502 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2514 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2503
2515
2504 wlock = repo.wlock()
2516 wlock = repo.wlock()
2505 try:
2517 try:
2506 repo.setparents(r1, r2)
2518 repo.setparents(r1, r2)
2507 finally:
2519 finally:
2508 wlock.release()
2520 wlock.release()
2509
2521
2510 @command('debugdirstate|debugstate',
2522 @command('debugdirstate|debugstate',
2511 [('', 'nodates', None, _('do not display the saved mtime')),
2523 [('', 'nodates', None, _('do not display the saved mtime')),
2512 ('', 'datesort', None, _('sort by saved mtime'))],
2524 ('', 'datesort', None, _('sort by saved mtime'))],
2513 _('[OPTION]...'))
2525 _('[OPTION]...'))
2514 def debugstate(ui, repo, nodates=None, datesort=None):
2526 def debugstate(ui, repo, nodates=None, datesort=None):
2515 """show the contents of the current dirstate"""
2527 """show the contents of the current dirstate"""
2516 timestr = ""
2528 timestr = ""
2517 showdate = not nodates
2529 showdate = not nodates
2518 if datesort:
2530 if datesort:
2519 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2531 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2520 else:
2532 else:
2521 keyfunc = None # sort by filename
2533 keyfunc = None # sort by filename
2522 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2534 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2523 if showdate:
2535 if showdate:
2524 if ent[3] == -1:
2536 if ent[3] == -1:
2525 # Pad or slice to locale representation
2537 # Pad or slice to locale representation
2526 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2538 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2527 time.localtime(0)))
2539 time.localtime(0)))
2528 timestr = 'unset'
2540 timestr = 'unset'
2529 timestr = (timestr[:locale_len] +
2541 timestr = (timestr[:locale_len] +
2530 ' ' * (locale_len - len(timestr)))
2542 ' ' * (locale_len - len(timestr)))
2531 else:
2543 else:
2532 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2544 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2533 time.localtime(ent[3]))
2545 time.localtime(ent[3]))
2534 if ent[1] & 020000:
2546 if ent[1] & 020000:
2535 mode = 'lnk'
2547 mode = 'lnk'
2536 else:
2548 else:
2537 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2549 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2538 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2550 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2539 for f in repo.dirstate.copies():
2551 for f in repo.dirstate.copies():
2540 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2552 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2541
2553
2542 @command('debugsub',
2554 @command('debugsub',
2543 [('r', 'rev', '',
2555 [('r', 'rev', '',
2544 _('revision to check'), _('REV'))],
2556 _('revision to check'), _('REV'))],
2545 _('[-r REV] [REV]'))
2557 _('[-r REV] [REV]'))
2546 def debugsub(ui, repo, rev=None):
2558 def debugsub(ui, repo, rev=None):
2547 ctx = scmutil.revsingle(repo, rev, None)
2559 ctx = scmutil.revsingle(repo, rev, None)
2548 for k, v in sorted(ctx.substate.items()):
2560 for k, v in sorted(ctx.substate.items()):
2549 ui.write(('path %s\n') % k)
2561 ui.write(('path %s\n') % k)
2550 ui.write((' source %s\n') % v[0])
2562 ui.write((' source %s\n') % v[0])
2551 ui.write((' revision %s\n') % v[1])
2563 ui.write((' revision %s\n') % v[1])
2552
2564
2553 @command('debugsuccessorssets',
2565 @command('debugsuccessorssets',
2554 [],
2566 [],
2555 _('[REV]'))
2567 _('[REV]'))
2556 def debugsuccessorssets(ui, repo, *revs):
2568 def debugsuccessorssets(ui, repo, *revs):
2557 """show set of successors for revision
2569 """show set of successors for revision
2558
2570
2559 A successors set of changeset A is a consistent group of revisions that
2571 A successors set of changeset A is a consistent group of revisions that
2560 succeed A. It contains non-obsolete changesets only.
2572 succeed A. It contains non-obsolete changesets only.
2561
2573
2562 In most cases a changeset A has a single successors set containing a single
2574 In most cases a changeset A has a single successors set containing a single
2563 successor (changeset A replaced by A').
2575 successor (changeset A replaced by A').
2564
2576
2565 A changeset that is made obsolete with no successors are called "pruned".
2577 A changeset that is made obsolete with no successors are called "pruned".
2566 Such changesets have no successors sets at all.
2578 Such changesets have no successors sets at all.
2567
2579
2568 A changeset that has been "split" will have a successors set containing
2580 A changeset that has been "split" will have a successors set containing
2569 more than one successor.
2581 more than one successor.
2570
2582
2571 A changeset that has been rewritten in multiple different ways is called
2583 A changeset that has been rewritten in multiple different ways is called
2572 "divergent". Such changesets have multiple successor sets (each of which
2584 "divergent". Such changesets have multiple successor sets (each of which
2573 may also be split, i.e. have multiple successors).
2585 may also be split, i.e. have multiple successors).
2574
2586
2575 Results are displayed as follows::
2587 Results are displayed as follows::
2576
2588
2577 <rev1>
2589 <rev1>
2578 <successors-1A>
2590 <successors-1A>
2579 <rev2>
2591 <rev2>
2580 <successors-2A>
2592 <successors-2A>
2581 <successors-2B1> <successors-2B2> <successors-2B3>
2593 <successors-2B1> <successors-2B2> <successors-2B3>
2582
2594
2583 Here rev2 has two possible (i.e. divergent) successors sets. The first
2595 Here rev2 has two possible (i.e. divergent) successors sets. The first
2584 holds one element, whereas the second holds three (i.e. the changeset has
2596 holds one element, whereas the second holds three (i.e. the changeset has
2585 been split).
2597 been split).
2586 """
2598 """
2587 # passed to successorssets caching computation from one call to another
2599 # passed to successorssets caching computation from one call to another
2588 cache = {}
2600 cache = {}
2589 ctx2str = str
2601 ctx2str = str
2590 node2str = short
2602 node2str = short
2591 if ui.debug():
2603 if ui.debug():
2592 def ctx2str(ctx):
2604 def ctx2str(ctx):
2593 return ctx.hex()
2605 return ctx.hex()
2594 node2str = hex
2606 node2str = hex
2595 for rev in scmutil.revrange(repo, revs):
2607 for rev in scmutil.revrange(repo, revs):
2596 ctx = repo[rev]
2608 ctx = repo[rev]
2597 ui.write('%s\n'% ctx2str(ctx))
2609 ui.write('%s\n'% ctx2str(ctx))
2598 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2610 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2599 if succsset:
2611 if succsset:
2600 ui.write(' ')
2612 ui.write(' ')
2601 ui.write(node2str(succsset[0]))
2613 ui.write(node2str(succsset[0]))
2602 for node in succsset[1:]:
2614 for node in succsset[1:]:
2603 ui.write(' ')
2615 ui.write(' ')
2604 ui.write(node2str(node))
2616 ui.write(node2str(node))
2605 ui.write('\n')
2617 ui.write('\n')
2606
2618
2607 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2619 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2608 def debugwalk(ui, repo, *pats, **opts):
2620 def debugwalk(ui, repo, *pats, **opts):
2609 """show how files match on given patterns"""
2621 """show how files match on given patterns"""
2610 m = scmutil.match(repo[None], pats, opts)
2622 m = scmutil.match(repo[None], pats, opts)
2611 items = list(repo.walk(m))
2623 items = list(repo.walk(m))
2612 if not items:
2624 if not items:
2613 return
2625 return
2614 f = lambda fn: fn
2626 f = lambda fn: fn
2615 if ui.configbool('ui', 'slash') and os.sep != '/':
2627 if ui.configbool('ui', 'slash') and os.sep != '/':
2616 f = lambda fn: util.normpath(fn)
2628 f = lambda fn: util.normpath(fn)
2617 fmt = 'f %%-%ds %%-%ds %%s' % (
2629 fmt = 'f %%-%ds %%-%ds %%s' % (
2618 max([len(abs) for abs in items]),
2630 max([len(abs) for abs in items]),
2619 max([len(m.rel(abs)) for abs in items]))
2631 max([len(m.rel(abs)) for abs in items]))
2620 for abs in items:
2632 for abs in items:
2621 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2633 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2622 ui.write("%s\n" % line.rstrip())
2634 ui.write("%s\n" % line.rstrip())
2623
2635
2624 @command('debugwireargs',
2636 @command('debugwireargs',
2625 [('', 'three', '', 'three'),
2637 [('', 'three', '', 'three'),
2626 ('', 'four', '', 'four'),
2638 ('', 'four', '', 'four'),
2627 ('', 'five', '', 'five'),
2639 ('', 'five', '', 'five'),
2628 ] + remoteopts,
2640 ] + remoteopts,
2629 _('REPO [OPTIONS]... [ONE [TWO]]'))
2641 _('REPO [OPTIONS]... [ONE [TWO]]'))
2630 def debugwireargs(ui, repopath, *vals, **opts):
2642 def debugwireargs(ui, repopath, *vals, **opts):
2631 repo = hg.peer(ui, opts, repopath)
2643 repo = hg.peer(ui, opts, repopath)
2632 for opt in remoteopts:
2644 for opt in remoteopts:
2633 del opts[opt[1]]
2645 del opts[opt[1]]
2634 args = {}
2646 args = {}
2635 for k, v in opts.iteritems():
2647 for k, v in opts.iteritems():
2636 if v:
2648 if v:
2637 args[k] = v
2649 args[k] = v
2638 # run twice to check that we don't mess up the stream for the next command
2650 # run twice to check that we don't mess up the stream for the next command
2639 res1 = repo.debugwireargs(*vals, **args)
2651 res1 = repo.debugwireargs(*vals, **args)
2640 res2 = repo.debugwireargs(*vals, **args)
2652 res2 = repo.debugwireargs(*vals, **args)
2641 ui.write("%s\n" % res1)
2653 ui.write("%s\n" % res1)
2642 if res1 != res2:
2654 if res1 != res2:
2643 ui.warn("%s\n" % res2)
2655 ui.warn("%s\n" % res2)
2644
2656
2645 @command('^diff',
2657 @command('^diff',
2646 [('r', 'rev', [], _('revision'), _('REV')),
2658 [('r', 'rev', [], _('revision'), _('REV')),
2647 ('c', 'change', '', _('change made by revision'), _('REV'))
2659 ('c', 'change', '', _('change made by revision'), _('REV'))
2648 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2660 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2649 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2661 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2650 def diff(ui, repo, *pats, **opts):
2662 def diff(ui, repo, *pats, **opts):
2651 """diff repository (or selected files)
2663 """diff repository (or selected files)
2652
2664
2653 Show differences between revisions for the specified files.
2665 Show differences between revisions for the specified files.
2654
2666
2655 Differences between files are shown using the unified diff format.
2667 Differences between files are shown using the unified diff format.
2656
2668
2657 .. note::
2669 .. note::
2658 diff may generate unexpected results for merges, as it will
2670 diff may generate unexpected results for merges, as it will
2659 default to comparing against the working directory's first
2671 default to comparing against the working directory's first
2660 parent changeset if no revisions are specified.
2672 parent changeset if no revisions are specified.
2661
2673
2662 When two revision arguments are given, then changes are shown
2674 When two revision arguments are given, then changes are shown
2663 between those revisions. If only one revision is specified then
2675 between those revisions. If only one revision is specified then
2664 that revision is compared to the working directory, and, when no
2676 that revision is compared to the working directory, and, when no
2665 revisions are specified, the working directory files are compared
2677 revisions are specified, the working directory files are compared
2666 to its parent.
2678 to its parent.
2667
2679
2668 Alternatively you can specify -c/--change with a revision to see
2680 Alternatively you can specify -c/--change with a revision to see
2669 the changes in that changeset relative to its first parent.
2681 the changes in that changeset relative to its first parent.
2670
2682
2671 Without the -a/--text option, diff will avoid generating diffs of
2683 Without the -a/--text option, diff will avoid generating diffs of
2672 files it detects as binary. With -a, diff will generate a diff
2684 files it detects as binary. With -a, diff will generate a diff
2673 anyway, probably with undesirable results.
2685 anyway, probably with undesirable results.
2674
2686
2675 Use the -g/--git option to generate diffs in the git extended diff
2687 Use the -g/--git option to generate diffs in the git extended diff
2676 format. For more information, read :hg:`help diffs`.
2688 format. For more information, read :hg:`help diffs`.
2677
2689
2678 .. container:: verbose
2690 .. container:: verbose
2679
2691
2680 Examples:
2692 Examples:
2681
2693
2682 - compare a file in the current working directory to its parent::
2694 - compare a file in the current working directory to its parent::
2683
2695
2684 hg diff foo.c
2696 hg diff foo.c
2685
2697
2686 - compare two historical versions of a directory, with rename info::
2698 - compare two historical versions of a directory, with rename info::
2687
2699
2688 hg diff --git -r 1.0:1.2 lib/
2700 hg diff --git -r 1.0:1.2 lib/
2689
2701
2690 - get change stats relative to the last change on some date::
2702 - get change stats relative to the last change on some date::
2691
2703
2692 hg diff --stat -r "date('may 2')"
2704 hg diff --stat -r "date('may 2')"
2693
2705
2694 - diff all newly-added files that contain a keyword::
2706 - diff all newly-added files that contain a keyword::
2695
2707
2696 hg diff "set:added() and grep(GNU)"
2708 hg diff "set:added() and grep(GNU)"
2697
2709
2698 - compare a revision and its parents::
2710 - compare a revision and its parents::
2699
2711
2700 hg diff -c 9353 # compare against first parent
2712 hg diff -c 9353 # compare against first parent
2701 hg diff -r 9353^:9353 # same using revset syntax
2713 hg diff -r 9353^:9353 # same using revset syntax
2702 hg diff -r 9353^2:9353 # compare against the second parent
2714 hg diff -r 9353^2:9353 # compare against the second parent
2703
2715
2704 Returns 0 on success.
2716 Returns 0 on success.
2705 """
2717 """
2706
2718
2707 revs = opts.get('rev')
2719 revs = opts.get('rev')
2708 change = opts.get('change')
2720 change = opts.get('change')
2709 stat = opts.get('stat')
2721 stat = opts.get('stat')
2710 reverse = opts.get('reverse')
2722 reverse = opts.get('reverse')
2711
2723
2712 if revs and change:
2724 if revs and change:
2713 msg = _('cannot specify --rev and --change at the same time')
2725 msg = _('cannot specify --rev and --change at the same time')
2714 raise util.Abort(msg)
2726 raise util.Abort(msg)
2715 elif change:
2727 elif change:
2716 node2 = scmutil.revsingle(repo, change, None).node()
2728 node2 = scmutil.revsingle(repo, change, None).node()
2717 node1 = repo[node2].p1().node()
2729 node1 = repo[node2].p1().node()
2718 else:
2730 else:
2719 node1, node2 = scmutil.revpair(repo, revs)
2731 node1, node2 = scmutil.revpair(repo, revs)
2720
2732
2721 if reverse:
2733 if reverse:
2722 node1, node2 = node2, node1
2734 node1, node2 = node2, node1
2723
2735
2724 diffopts = patch.diffopts(ui, opts)
2736 diffopts = patch.diffopts(ui, opts)
2725 m = scmutil.match(repo[node2], pats, opts)
2737 m = scmutil.match(repo[node2], pats, opts)
2726 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2738 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2727 listsubrepos=opts.get('subrepos'))
2739 listsubrepos=opts.get('subrepos'))
2728
2740
2729 @command('^export',
2741 @command('^export',
2730 [('o', 'output', '',
2742 [('o', 'output', '',
2731 _('print output to file with formatted name'), _('FORMAT')),
2743 _('print output to file with formatted name'), _('FORMAT')),
2732 ('', 'switch-parent', None, _('diff against the second parent')),
2744 ('', 'switch-parent', None, _('diff against the second parent')),
2733 ('r', 'rev', [], _('revisions to export'), _('REV')),
2745 ('r', 'rev', [], _('revisions to export'), _('REV')),
2734 ] + diffopts,
2746 ] + diffopts,
2735 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2747 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2736 def export(ui, repo, *changesets, **opts):
2748 def export(ui, repo, *changesets, **opts):
2737 """dump the header and diffs for one or more changesets
2749 """dump the header and diffs for one or more changesets
2738
2750
2739 Print the changeset header and diffs for one or more revisions.
2751 Print the changeset header and diffs for one or more revisions.
2740 If no revision is given, the parent of the working directory is used.
2752 If no revision is given, the parent of the working directory is used.
2741
2753
2742 The information shown in the changeset header is: author, date,
2754 The information shown in the changeset header is: author, date,
2743 branch name (if non-default), changeset hash, parent(s) and commit
2755 branch name (if non-default), changeset hash, parent(s) and commit
2744 comment.
2756 comment.
2745
2757
2746 .. note::
2758 .. note::
2747 export may generate unexpected diff output for merge
2759 export may generate unexpected diff output for merge
2748 changesets, as it will compare the merge changeset against its
2760 changesets, as it will compare the merge changeset against its
2749 first parent only.
2761 first parent only.
2750
2762
2751 Output may be to a file, in which case the name of the file is
2763 Output may be to a file, in which case the name of the file is
2752 given using a format string. The formatting rules are as follows:
2764 given using a format string. The formatting rules are as follows:
2753
2765
2754 :``%%``: literal "%" character
2766 :``%%``: literal "%" character
2755 :``%H``: changeset hash (40 hexadecimal digits)
2767 :``%H``: changeset hash (40 hexadecimal digits)
2756 :``%N``: number of patches being generated
2768 :``%N``: number of patches being generated
2757 :``%R``: changeset revision number
2769 :``%R``: changeset revision number
2758 :``%b``: basename of the exporting repository
2770 :``%b``: basename of the exporting repository
2759 :``%h``: short-form changeset hash (12 hexadecimal digits)
2771 :``%h``: short-form changeset hash (12 hexadecimal digits)
2760 :``%m``: first line of the commit message (only alphanumeric characters)
2772 :``%m``: first line of the commit message (only alphanumeric characters)
2761 :``%n``: zero-padded sequence number, starting at 1
2773 :``%n``: zero-padded sequence number, starting at 1
2762 :``%r``: zero-padded changeset revision number
2774 :``%r``: zero-padded changeset revision number
2763
2775
2764 Without the -a/--text option, export will avoid generating diffs
2776 Without the -a/--text option, export will avoid generating diffs
2765 of files it detects as binary. With -a, export will generate a
2777 of files it detects as binary. With -a, export will generate a
2766 diff anyway, probably with undesirable results.
2778 diff anyway, probably with undesirable results.
2767
2779
2768 Use the -g/--git option to generate diffs in the git extended diff
2780 Use the -g/--git option to generate diffs in the git extended diff
2769 format. See :hg:`help diffs` for more information.
2781 format. See :hg:`help diffs` for more information.
2770
2782
2771 With the --switch-parent option, the diff will be against the
2783 With the --switch-parent option, the diff will be against the
2772 second parent. It can be useful to review a merge.
2784 second parent. It can be useful to review a merge.
2773
2785
2774 .. container:: verbose
2786 .. container:: verbose
2775
2787
2776 Examples:
2788 Examples:
2777
2789
2778 - use export and import to transplant a bugfix to the current
2790 - use export and import to transplant a bugfix to the current
2779 branch::
2791 branch::
2780
2792
2781 hg export -r 9353 | hg import -
2793 hg export -r 9353 | hg import -
2782
2794
2783 - export all the changesets between two revisions to a file with
2795 - export all the changesets between two revisions to a file with
2784 rename information::
2796 rename information::
2785
2797
2786 hg export --git -r 123:150 > changes.txt
2798 hg export --git -r 123:150 > changes.txt
2787
2799
2788 - split outgoing changes into a series of patches with
2800 - split outgoing changes into a series of patches with
2789 descriptive names::
2801 descriptive names::
2790
2802
2791 hg export -r "outgoing()" -o "%n-%m.patch"
2803 hg export -r "outgoing()" -o "%n-%m.patch"
2792
2804
2793 Returns 0 on success.
2805 Returns 0 on success.
2794 """
2806 """
2795 changesets += tuple(opts.get('rev', []))
2807 changesets += tuple(opts.get('rev', []))
2796 if not changesets:
2808 if not changesets:
2797 changesets = ['.']
2809 changesets = ['.']
2798 revs = scmutil.revrange(repo, changesets)
2810 revs = scmutil.revrange(repo, changesets)
2799 if not revs:
2811 if not revs:
2800 raise util.Abort(_("export requires at least one changeset"))
2812 raise util.Abort(_("export requires at least one changeset"))
2801 if len(revs) > 1:
2813 if len(revs) > 1:
2802 ui.note(_('exporting patches:\n'))
2814 ui.note(_('exporting patches:\n'))
2803 else:
2815 else:
2804 ui.note(_('exporting patch:\n'))
2816 ui.note(_('exporting patch:\n'))
2805 cmdutil.export(repo, revs, template=opts.get('output'),
2817 cmdutil.export(repo, revs, template=opts.get('output'),
2806 switch_parent=opts.get('switch_parent'),
2818 switch_parent=opts.get('switch_parent'),
2807 opts=patch.diffopts(ui, opts))
2819 opts=patch.diffopts(ui, opts))
2808
2820
2809 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2821 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2810 def forget(ui, repo, *pats, **opts):
2822 def forget(ui, repo, *pats, **opts):
2811 """forget the specified files on the next commit
2823 """forget the specified files on the next commit
2812
2824
2813 Mark the specified files so they will no longer be tracked
2825 Mark the specified files so they will no longer be tracked
2814 after the next commit.
2826 after the next commit.
2815
2827
2816 This only removes files from the current branch, not from the
2828 This only removes files from the current branch, not from the
2817 entire project history, and it does not delete them from the
2829 entire project history, and it does not delete them from the
2818 working directory.
2830 working directory.
2819
2831
2820 To undo a forget before the next commit, see :hg:`add`.
2832 To undo a forget before the next commit, see :hg:`add`.
2821
2833
2822 .. container:: verbose
2834 .. container:: verbose
2823
2835
2824 Examples:
2836 Examples:
2825
2837
2826 - forget newly-added binary files::
2838 - forget newly-added binary files::
2827
2839
2828 hg forget "set:added() and binary()"
2840 hg forget "set:added() and binary()"
2829
2841
2830 - forget files that would be excluded by .hgignore::
2842 - forget files that would be excluded by .hgignore::
2831
2843
2832 hg forget "set:hgignore()"
2844 hg forget "set:hgignore()"
2833
2845
2834 Returns 0 on success.
2846 Returns 0 on success.
2835 """
2847 """
2836
2848
2837 if not pats:
2849 if not pats:
2838 raise util.Abort(_('no files specified'))
2850 raise util.Abort(_('no files specified'))
2839
2851
2840 m = scmutil.match(repo[None], pats, opts)
2852 m = scmutil.match(repo[None], pats, opts)
2841 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2853 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2842 return rejected and 1 or 0
2854 return rejected and 1 or 0
2843
2855
2844 @command(
2856 @command(
2845 'graft',
2857 'graft',
2846 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2858 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2847 ('c', 'continue', False, _('resume interrupted graft')),
2859 ('c', 'continue', False, _('resume interrupted graft')),
2848 ('e', 'edit', False, _('invoke editor on commit messages')),
2860 ('e', 'edit', False, _('invoke editor on commit messages')),
2849 ('', 'log', None, _('append graft info to log message')),
2861 ('', 'log', None, _('append graft info to log message')),
2850 ('D', 'currentdate', False,
2862 ('D', 'currentdate', False,
2851 _('record the current date as commit date')),
2863 _('record the current date as commit date')),
2852 ('U', 'currentuser', False,
2864 ('U', 'currentuser', False,
2853 _('record the current user as committer'), _('DATE'))]
2865 _('record the current user as committer'), _('DATE'))]
2854 + commitopts2 + mergetoolopts + dryrunopts,
2866 + commitopts2 + mergetoolopts + dryrunopts,
2855 _('[OPTION]... [-r] REV...'))
2867 _('[OPTION]... [-r] REV...'))
2856 def graft(ui, repo, *revs, **opts):
2868 def graft(ui, repo, *revs, **opts):
2857 '''copy changes from other branches onto the current branch
2869 '''copy changes from other branches onto the current branch
2858
2870
2859 This command uses Mercurial's merge logic to copy individual
2871 This command uses Mercurial's merge logic to copy individual
2860 changes from other branches without merging branches in the
2872 changes from other branches without merging branches in the
2861 history graph. This is sometimes known as 'backporting' or
2873 history graph. This is sometimes known as 'backporting' or
2862 'cherry-picking'. By default, graft will copy user, date, and
2874 'cherry-picking'. By default, graft will copy user, date, and
2863 description from the source changesets.
2875 description from the source changesets.
2864
2876
2865 Changesets that are ancestors of the current revision, that have
2877 Changesets that are ancestors of the current revision, that have
2866 already been grafted, or that are merges will be skipped.
2878 already been grafted, or that are merges will be skipped.
2867
2879
2868 If --log is specified, log messages will have a comment appended
2880 If --log is specified, log messages will have a comment appended
2869 of the form::
2881 of the form::
2870
2882
2871 (grafted from CHANGESETHASH)
2883 (grafted from CHANGESETHASH)
2872
2884
2873 If a graft merge results in conflicts, the graft process is
2885 If a graft merge results in conflicts, the graft process is
2874 interrupted so that the current merge can be manually resolved.
2886 interrupted so that the current merge can be manually resolved.
2875 Once all conflicts are addressed, the graft process can be
2887 Once all conflicts are addressed, the graft process can be
2876 continued with the -c/--continue option.
2888 continued with the -c/--continue option.
2877
2889
2878 .. note::
2890 .. note::
2879 The -c/--continue option does not reapply earlier options.
2891 The -c/--continue option does not reapply earlier options.
2880
2892
2881 .. container:: verbose
2893 .. container:: verbose
2882
2894
2883 Examples:
2895 Examples:
2884
2896
2885 - copy a single change to the stable branch and edit its description::
2897 - copy a single change to the stable branch and edit its description::
2886
2898
2887 hg update stable
2899 hg update stable
2888 hg graft --edit 9393
2900 hg graft --edit 9393
2889
2901
2890 - graft a range of changesets with one exception, updating dates::
2902 - graft a range of changesets with one exception, updating dates::
2891
2903
2892 hg graft -D "2085::2093 and not 2091"
2904 hg graft -D "2085::2093 and not 2091"
2893
2905
2894 - continue a graft after resolving conflicts::
2906 - continue a graft after resolving conflicts::
2895
2907
2896 hg graft -c
2908 hg graft -c
2897
2909
2898 - show the source of a grafted changeset::
2910 - show the source of a grafted changeset::
2899
2911
2900 hg log --debug -r tip
2912 hg log --debug -r tip
2901
2913
2902 Returns 0 on successful completion.
2914 Returns 0 on successful completion.
2903 '''
2915 '''
2904
2916
2905 revs = list(revs)
2917 revs = list(revs)
2906 revs.extend(opts['rev'])
2918 revs.extend(opts['rev'])
2907
2919
2908 if not opts.get('user') and opts.get('currentuser'):
2920 if not opts.get('user') and opts.get('currentuser'):
2909 opts['user'] = ui.username()
2921 opts['user'] = ui.username()
2910 if not opts.get('date') and opts.get('currentdate'):
2922 if not opts.get('date') and opts.get('currentdate'):
2911 opts['date'] = "%d %d" % util.makedate()
2923 opts['date'] = "%d %d" % util.makedate()
2912
2924
2913 editor = None
2925 editor = None
2914 if opts.get('edit'):
2926 if opts.get('edit'):
2915 editor = cmdutil.commitforceeditor
2927 editor = cmdutil.commitforceeditor
2916
2928
2917 cont = False
2929 cont = False
2918 if opts['continue']:
2930 if opts['continue']:
2919 cont = True
2931 cont = True
2920 if revs:
2932 if revs:
2921 raise util.Abort(_("can't specify --continue and revisions"))
2933 raise util.Abort(_("can't specify --continue and revisions"))
2922 # read in unfinished revisions
2934 # read in unfinished revisions
2923 try:
2935 try:
2924 nodes = repo.opener.read('graftstate').splitlines()
2936 nodes = repo.opener.read('graftstate').splitlines()
2925 revs = [repo[node].rev() for node in nodes]
2937 revs = [repo[node].rev() for node in nodes]
2926 except IOError, inst:
2938 except IOError, inst:
2927 if inst.errno != errno.ENOENT:
2939 if inst.errno != errno.ENOENT:
2928 raise
2940 raise
2929 raise util.Abort(_("no graft state found, can't continue"))
2941 raise util.Abort(_("no graft state found, can't continue"))
2930 else:
2942 else:
2931 cmdutil.bailifchanged(repo)
2943 cmdutil.bailifchanged(repo)
2932 if not revs:
2944 if not revs:
2933 raise util.Abort(_('no revisions specified'))
2945 raise util.Abort(_('no revisions specified'))
2934 revs = scmutil.revrange(repo, revs)
2946 revs = scmutil.revrange(repo, revs)
2935
2947
2936 # check for merges
2948 # check for merges
2937 for rev in repo.revs('%ld and merge()', revs):
2949 for rev in repo.revs('%ld and merge()', revs):
2938 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2950 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2939 revs.remove(rev)
2951 revs.remove(rev)
2940 if not revs:
2952 if not revs:
2941 return -1
2953 return -1
2942
2954
2943 # check for ancestors of dest branch
2955 # check for ancestors of dest branch
2944 crev = repo['.'].rev()
2956 crev = repo['.'].rev()
2945 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2957 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2946 # don't mutate while iterating, create a copy
2958 # don't mutate while iterating, create a copy
2947 for rev in list(revs):
2959 for rev in list(revs):
2948 if rev in ancestors:
2960 if rev in ancestors:
2949 ui.warn(_('skipping ancestor revision %s\n') % rev)
2961 ui.warn(_('skipping ancestor revision %s\n') % rev)
2950 revs.remove(rev)
2962 revs.remove(rev)
2951 if not revs:
2963 if not revs:
2952 return -1
2964 return -1
2953
2965
2954 # analyze revs for earlier grafts
2966 # analyze revs for earlier grafts
2955 ids = {}
2967 ids = {}
2956 for ctx in repo.set("%ld", revs):
2968 for ctx in repo.set("%ld", revs):
2957 ids[ctx.hex()] = ctx.rev()
2969 ids[ctx.hex()] = ctx.rev()
2958 n = ctx.extra().get('source')
2970 n = ctx.extra().get('source')
2959 if n:
2971 if n:
2960 ids[n] = ctx.rev()
2972 ids[n] = ctx.rev()
2961
2973
2962 # check ancestors for earlier grafts
2974 # check ancestors for earlier grafts
2963 ui.debug('scanning for duplicate grafts\n')
2975 ui.debug('scanning for duplicate grafts\n')
2964
2976
2965 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2977 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2966 ctx = repo[rev]
2978 ctx = repo[rev]
2967 n = ctx.extra().get('source')
2979 n = ctx.extra().get('source')
2968 if n in ids:
2980 if n in ids:
2969 r = repo[n].rev()
2981 r = repo[n].rev()
2970 if r in revs:
2982 if r in revs:
2971 ui.warn(_('skipping already grafted revision %s\n') % r)
2983 ui.warn(_('skipping already grafted revision %s\n') % r)
2972 revs.remove(r)
2984 revs.remove(r)
2973 elif ids[n] in revs:
2985 elif ids[n] in revs:
2974 ui.warn(_('skipping already grafted revision %s '
2986 ui.warn(_('skipping already grafted revision %s '
2975 '(same origin %d)\n') % (ids[n], r))
2987 '(same origin %d)\n') % (ids[n], r))
2976 revs.remove(ids[n])
2988 revs.remove(ids[n])
2977 elif ctx.hex() in ids:
2989 elif ctx.hex() in ids:
2978 r = ids[ctx.hex()]
2990 r = ids[ctx.hex()]
2979 ui.warn(_('skipping already grafted revision %s '
2991 ui.warn(_('skipping already grafted revision %s '
2980 '(was grafted from %d)\n') % (r, rev))
2992 '(was grafted from %d)\n') % (r, rev))
2981 revs.remove(r)
2993 revs.remove(r)
2982 if not revs:
2994 if not revs:
2983 return -1
2995 return -1
2984
2996
2985 wlock = repo.wlock()
2997 wlock = repo.wlock()
2986 try:
2998 try:
2987 current = repo['.']
2999 current = repo['.']
2988 for pos, ctx in enumerate(repo.set("%ld", revs)):
3000 for pos, ctx in enumerate(repo.set("%ld", revs)):
2989
3001
2990 ui.status(_('grafting revision %s\n') % ctx.rev())
3002 ui.status(_('grafting revision %s\n') % ctx.rev())
2991 if opts.get('dry_run'):
3003 if opts.get('dry_run'):
2992 continue
3004 continue
2993
3005
2994 source = ctx.extra().get('source')
3006 source = ctx.extra().get('source')
2995 if not source:
3007 if not source:
2996 source = ctx.hex()
3008 source = ctx.hex()
2997 extra = {'source': source}
3009 extra = {'source': source}
2998 user = ctx.user()
3010 user = ctx.user()
2999 if opts.get('user'):
3011 if opts.get('user'):
3000 user = opts['user']
3012 user = opts['user']
3001 date = ctx.date()
3013 date = ctx.date()
3002 if opts.get('date'):
3014 if opts.get('date'):
3003 date = opts['date']
3015 date = opts['date']
3004 message = ctx.description()
3016 message = ctx.description()
3005 if opts.get('log'):
3017 if opts.get('log'):
3006 message += '\n(grafted from %s)' % ctx.hex()
3018 message += '\n(grafted from %s)' % ctx.hex()
3007
3019
3008 # we don't merge the first commit when continuing
3020 # we don't merge the first commit when continuing
3009 if not cont:
3021 if not cont:
3010 # perform the graft merge with p1(rev) as 'ancestor'
3022 # perform the graft merge with p1(rev) as 'ancestor'
3011 try:
3023 try:
3012 # ui.forcemerge is an internal variable, do not document
3024 # ui.forcemerge is an internal variable, do not document
3013 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3025 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3014 stats = mergemod.update(repo, ctx.node(), True, True, False,
3026 stats = mergemod.update(repo, ctx.node(), True, True, False,
3015 ctx.p1().node())
3027 ctx.p1().node())
3016 finally:
3028 finally:
3017 repo.ui.setconfig('ui', 'forcemerge', '')
3029 repo.ui.setconfig('ui', 'forcemerge', '')
3018 # report any conflicts
3030 # report any conflicts
3019 if stats and stats[3] > 0:
3031 if stats and stats[3] > 0:
3020 # write out state for --continue
3032 # write out state for --continue
3021 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3033 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3022 repo.opener.write('graftstate', ''.join(nodelines))
3034 repo.opener.write('graftstate', ''.join(nodelines))
3023 raise util.Abort(
3035 raise util.Abort(
3024 _("unresolved conflicts, can't continue"),
3036 _("unresolved conflicts, can't continue"),
3025 hint=_('use hg resolve and hg graft --continue'))
3037 hint=_('use hg resolve and hg graft --continue'))
3026 else:
3038 else:
3027 cont = False
3039 cont = False
3028
3040
3029 # drop the second merge parent
3041 # drop the second merge parent
3030 repo.setparents(current.node(), nullid)
3042 repo.setparents(current.node(), nullid)
3031 repo.dirstate.write()
3043 repo.dirstate.write()
3032 # fix up dirstate for copies and renames
3044 # fix up dirstate for copies and renames
3033 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3045 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3034
3046
3035 # commit
3047 # commit
3036 node = repo.commit(text=message, user=user,
3048 node = repo.commit(text=message, user=user,
3037 date=date, extra=extra, editor=editor)
3049 date=date, extra=extra, editor=editor)
3038 if node is None:
3050 if node is None:
3039 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3051 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3040 else:
3052 else:
3041 current = repo[node]
3053 current = repo[node]
3042 finally:
3054 finally:
3043 wlock.release()
3055 wlock.release()
3044
3056
3045 # remove state when we complete successfully
3057 # remove state when we complete successfully
3046 if not opts.get('dry_run'):
3058 if not opts.get('dry_run'):
3047 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3059 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3048
3060
3049 return 0
3061 return 0
3050
3062
3051 @command('grep',
3063 @command('grep',
3052 [('0', 'print0', None, _('end fields with NUL')),
3064 [('0', 'print0', None, _('end fields with NUL')),
3053 ('', 'all', None, _('print all revisions that match')),
3065 ('', 'all', None, _('print all revisions that match')),
3054 ('a', 'text', None, _('treat all files as text')),
3066 ('a', 'text', None, _('treat all files as text')),
3055 ('f', 'follow', None,
3067 ('f', 'follow', None,
3056 _('follow changeset history,'
3068 _('follow changeset history,'
3057 ' or file history across copies and renames')),
3069 ' or file history across copies and renames')),
3058 ('i', 'ignore-case', None, _('ignore case when matching')),
3070 ('i', 'ignore-case', None, _('ignore case when matching')),
3059 ('l', 'files-with-matches', None,
3071 ('l', 'files-with-matches', None,
3060 _('print only filenames and revisions that match')),
3072 _('print only filenames and revisions that match')),
3061 ('n', 'line-number', None, _('print matching line numbers')),
3073 ('n', 'line-number', None, _('print matching line numbers')),
3062 ('r', 'rev', [],
3074 ('r', 'rev', [],
3063 _('only search files changed within revision range'), _('REV')),
3075 _('only search files changed within revision range'), _('REV')),
3064 ('u', 'user', None, _('list the author (long with -v)')),
3076 ('u', 'user', None, _('list the author (long with -v)')),
3065 ('d', 'date', None, _('list the date (short with -q)')),
3077 ('d', 'date', None, _('list the date (short with -q)')),
3066 ] + walkopts,
3078 ] + walkopts,
3067 _('[OPTION]... PATTERN [FILE]...'))
3079 _('[OPTION]... PATTERN [FILE]...'))
3068 def grep(ui, repo, pattern, *pats, **opts):
3080 def grep(ui, repo, pattern, *pats, **opts):
3069 """search for a pattern in specified files and revisions
3081 """search for a pattern in specified files and revisions
3070
3082
3071 Search revisions of files for a regular expression.
3083 Search revisions of files for a regular expression.
3072
3084
3073 This command behaves differently than Unix grep. It only accepts
3085 This command behaves differently than Unix grep. It only accepts
3074 Python/Perl regexps. It searches repository history, not the
3086 Python/Perl regexps. It searches repository history, not the
3075 working directory. It always prints the revision number in which a
3087 working directory. It always prints the revision number in which a
3076 match appears.
3088 match appears.
3077
3089
3078 By default, grep only prints output for the first revision of a
3090 By default, grep only prints output for the first revision of a
3079 file in which it finds a match. To get it to print every revision
3091 file in which it finds a match. To get it to print every revision
3080 that contains a change in match status ("-" for a match that
3092 that contains a change in match status ("-" for a match that
3081 becomes a non-match, or "+" for a non-match that becomes a match),
3093 becomes a non-match, or "+" for a non-match that becomes a match),
3082 use the --all flag.
3094 use the --all flag.
3083
3095
3084 Returns 0 if a match is found, 1 otherwise.
3096 Returns 0 if a match is found, 1 otherwise.
3085 """
3097 """
3086 reflags = re.M
3098 reflags = re.M
3087 if opts.get('ignore_case'):
3099 if opts.get('ignore_case'):
3088 reflags |= re.I
3100 reflags |= re.I
3089 try:
3101 try:
3090 regexp = util.compilere(pattern, reflags)
3102 regexp = util.compilere(pattern, reflags)
3091 except re.error, inst:
3103 except re.error, inst:
3092 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3104 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3093 return 1
3105 return 1
3094 sep, eol = ':', '\n'
3106 sep, eol = ':', '\n'
3095 if opts.get('print0'):
3107 if opts.get('print0'):
3096 sep = eol = '\0'
3108 sep = eol = '\0'
3097
3109
3098 getfile = util.lrucachefunc(repo.file)
3110 getfile = util.lrucachefunc(repo.file)
3099
3111
3100 def matchlines(body):
3112 def matchlines(body):
3101 begin = 0
3113 begin = 0
3102 linenum = 0
3114 linenum = 0
3103 while begin < len(body):
3115 while begin < len(body):
3104 match = regexp.search(body, begin)
3116 match = regexp.search(body, begin)
3105 if not match:
3117 if not match:
3106 break
3118 break
3107 mstart, mend = match.span()
3119 mstart, mend = match.span()
3108 linenum += body.count('\n', begin, mstart) + 1
3120 linenum += body.count('\n', begin, mstart) + 1
3109 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3121 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3110 begin = body.find('\n', mend) + 1 or len(body) + 1
3122 begin = body.find('\n', mend) + 1 or len(body) + 1
3111 lend = begin - 1
3123 lend = begin - 1
3112 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3124 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3113
3125
3114 class linestate(object):
3126 class linestate(object):
3115 def __init__(self, line, linenum, colstart, colend):
3127 def __init__(self, line, linenum, colstart, colend):
3116 self.line = line
3128 self.line = line
3117 self.linenum = linenum
3129 self.linenum = linenum
3118 self.colstart = colstart
3130 self.colstart = colstart
3119 self.colend = colend
3131 self.colend = colend
3120
3132
3121 def __hash__(self):
3133 def __hash__(self):
3122 return hash((self.linenum, self.line))
3134 return hash((self.linenum, self.line))
3123
3135
3124 def __eq__(self, other):
3136 def __eq__(self, other):
3125 return self.line == other.line
3137 return self.line == other.line
3126
3138
3127 matches = {}
3139 matches = {}
3128 copies = {}
3140 copies = {}
3129 def grepbody(fn, rev, body):
3141 def grepbody(fn, rev, body):
3130 matches[rev].setdefault(fn, [])
3142 matches[rev].setdefault(fn, [])
3131 m = matches[rev][fn]
3143 m = matches[rev][fn]
3132 for lnum, cstart, cend, line in matchlines(body):
3144 for lnum, cstart, cend, line in matchlines(body):
3133 s = linestate(line, lnum, cstart, cend)
3145 s = linestate(line, lnum, cstart, cend)
3134 m.append(s)
3146 m.append(s)
3135
3147
3136 def difflinestates(a, b):
3148 def difflinestates(a, b):
3137 sm = difflib.SequenceMatcher(None, a, b)
3149 sm = difflib.SequenceMatcher(None, a, b)
3138 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3150 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3139 if tag == 'insert':
3151 if tag == 'insert':
3140 for i in xrange(blo, bhi):
3152 for i in xrange(blo, bhi):
3141 yield ('+', b[i])
3153 yield ('+', b[i])
3142 elif tag == 'delete':
3154 elif tag == 'delete':
3143 for i in xrange(alo, ahi):
3155 for i in xrange(alo, ahi):
3144 yield ('-', a[i])
3156 yield ('-', a[i])
3145 elif tag == 'replace':
3157 elif tag == 'replace':
3146 for i in xrange(alo, ahi):
3158 for i in xrange(alo, ahi):
3147 yield ('-', a[i])
3159 yield ('-', a[i])
3148 for i in xrange(blo, bhi):
3160 for i in xrange(blo, bhi):
3149 yield ('+', b[i])
3161 yield ('+', b[i])
3150
3162
3151 def display(fn, ctx, pstates, states):
3163 def display(fn, ctx, pstates, states):
3152 rev = ctx.rev()
3164 rev = ctx.rev()
3153 datefunc = ui.quiet and util.shortdate or util.datestr
3165 datefunc = ui.quiet and util.shortdate or util.datestr
3154 found = False
3166 found = False
3155 filerevmatches = {}
3167 filerevmatches = {}
3156 def binary():
3168 def binary():
3157 flog = getfile(fn)
3169 flog = getfile(fn)
3158 return util.binary(flog.read(ctx.filenode(fn)))
3170 return util.binary(flog.read(ctx.filenode(fn)))
3159
3171
3160 if opts.get('all'):
3172 if opts.get('all'):
3161 iter = difflinestates(pstates, states)
3173 iter = difflinestates(pstates, states)
3162 else:
3174 else:
3163 iter = [('', l) for l in states]
3175 iter = [('', l) for l in states]
3164 for change, l in iter:
3176 for change, l in iter:
3165 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3177 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3166 before, match, after = None, None, None
3178 before, match, after = None, None, None
3167
3179
3168 if opts.get('line_number'):
3180 if opts.get('line_number'):
3169 cols.append((str(l.linenum), 'grep.linenumber'))
3181 cols.append((str(l.linenum), 'grep.linenumber'))
3170 if opts.get('all'):
3182 if opts.get('all'):
3171 cols.append((change, 'grep.change'))
3183 cols.append((change, 'grep.change'))
3172 if opts.get('user'):
3184 if opts.get('user'):
3173 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3185 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3174 if opts.get('date'):
3186 if opts.get('date'):
3175 cols.append((datefunc(ctx.date()), 'grep.date'))
3187 cols.append((datefunc(ctx.date()), 'grep.date'))
3176 if opts.get('files_with_matches'):
3188 if opts.get('files_with_matches'):
3177 c = (fn, rev)
3189 c = (fn, rev)
3178 if c in filerevmatches:
3190 if c in filerevmatches:
3179 continue
3191 continue
3180 filerevmatches[c] = 1
3192 filerevmatches[c] = 1
3181 else:
3193 else:
3182 before = l.line[:l.colstart]
3194 before = l.line[:l.colstart]
3183 match = l.line[l.colstart:l.colend]
3195 match = l.line[l.colstart:l.colend]
3184 after = l.line[l.colend:]
3196 after = l.line[l.colend:]
3185 for col, label in cols[:-1]:
3197 for col, label in cols[:-1]:
3186 ui.write(col, label=label)
3198 ui.write(col, label=label)
3187 ui.write(sep, label='grep.sep')
3199 ui.write(sep, label='grep.sep')
3188 ui.write(cols[-1][0], label=cols[-1][1])
3200 ui.write(cols[-1][0], label=cols[-1][1])
3189 if before is not None:
3201 if before is not None:
3190 ui.write(sep, label='grep.sep')
3202 ui.write(sep, label='grep.sep')
3191 if not opts.get('text') and binary():
3203 if not opts.get('text') and binary():
3192 ui.write(" Binary file matches")
3204 ui.write(" Binary file matches")
3193 else:
3205 else:
3194 ui.write(before)
3206 ui.write(before)
3195 ui.write(match, label='grep.match')
3207 ui.write(match, label='grep.match')
3196 ui.write(after)
3208 ui.write(after)
3197 ui.write(eol)
3209 ui.write(eol)
3198 found = True
3210 found = True
3199 return found
3211 return found
3200
3212
3201 skip = {}
3213 skip = {}
3202 revfiles = {}
3214 revfiles = {}
3203 matchfn = scmutil.match(repo[None], pats, opts)
3215 matchfn = scmutil.match(repo[None], pats, opts)
3204 found = False
3216 found = False
3205 follow = opts.get('follow')
3217 follow = opts.get('follow')
3206
3218
3207 def prep(ctx, fns):
3219 def prep(ctx, fns):
3208 rev = ctx.rev()
3220 rev = ctx.rev()
3209 pctx = ctx.p1()
3221 pctx = ctx.p1()
3210 parent = pctx.rev()
3222 parent = pctx.rev()
3211 matches.setdefault(rev, {})
3223 matches.setdefault(rev, {})
3212 matches.setdefault(parent, {})
3224 matches.setdefault(parent, {})
3213 files = revfiles.setdefault(rev, [])
3225 files = revfiles.setdefault(rev, [])
3214 for fn in fns:
3226 for fn in fns:
3215 flog = getfile(fn)
3227 flog = getfile(fn)
3216 try:
3228 try:
3217 fnode = ctx.filenode(fn)
3229 fnode = ctx.filenode(fn)
3218 except error.LookupError:
3230 except error.LookupError:
3219 continue
3231 continue
3220
3232
3221 copied = flog.renamed(fnode)
3233 copied = flog.renamed(fnode)
3222 copy = follow and copied and copied[0]
3234 copy = follow and copied and copied[0]
3223 if copy:
3235 if copy:
3224 copies.setdefault(rev, {})[fn] = copy
3236 copies.setdefault(rev, {})[fn] = copy
3225 if fn in skip:
3237 if fn in skip:
3226 if copy:
3238 if copy:
3227 skip[copy] = True
3239 skip[copy] = True
3228 continue
3240 continue
3229 files.append(fn)
3241 files.append(fn)
3230
3242
3231 if fn not in matches[rev]:
3243 if fn not in matches[rev]:
3232 grepbody(fn, rev, flog.read(fnode))
3244 grepbody(fn, rev, flog.read(fnode))
3233
3245
3234 pfn = copy or fn
3246 pfn = copy or fn
3235 if pfn not in matches[parent]:
3247 if pfn not in matches[parent]:
3236 try:
3248 try:
3237 fnode = pctx.filenode(pfn)
3249 fnode = pctx.filenode(pfn)
3238 grepbody(pfn, parent, flog.read(fnode))
3250 grepbody(pfn, parent, flog.read(fnode))
3239 except error.LookupError:
3251 except error.LookupError:
3240 pass
3252 pass
3241
3253
3242 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3254 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3243 rev = ctx.rev()
3255 rev = ctx.rev()
3244 parent = ctx.p1().rev()
3256 parent = ctx.p1().rev()
3245 for fn in sorted(revfiles.get(rev, [])):
3257 for fn in sorted(revfiles.get(rev, [])):
3246 states = matches[rev][fn]
3258 states = matches[rev][fn]
3247 copy = copies.get(rev, {}).get(fn)
3259 copy = copies.get(rev, {}).get(fn)
3248 if fn in skip:
3260 if fn in skip:
3249 if copy:
3261 if copy:
3250 skip[copy] = True
3262 skip[copy] = True
3251 continue
3263 continue
3252 pstates = matches.get(parent, {}).get(copy or fn, [])
3264 pstates = matches.get(parent, {}).get(copy or fn, [])
3253 if pstates or states:
3265 if pstates or states:
3254 r = display(fn, ctx, pstates, states)
3266 r = display(fn, ctx, pstates, states)
3255 found = found or r
3267 found = found or r
3256 if r and not opts.get('all'):
3268 if r and not opts.get('all'):
3257 skip[fn] = True
3269 skip[fn] = True
3258 if copy:
3270 if copy:
3259 skip[copy] = True
3271 skip[copy] = True
3260 del matches[rev]
3272 del matches[rev]
3261 del revfiles[rev]
3273 del revfiles[rev]
3262
3274
3263 return not found
3275 return not found
3264
3276
3265 @command('heads',
3277 @command('heads',
3266 [('r', 'rev', '',
3278 [('r', 'rev', '',
3267 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3279 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3268 ('t', 'topo', False, _('show topological heads only')),
3280 ('t', 'topo', False, _('show topological heads only')),
3269 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3281 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3270 ('c', 'closed', False, _('show normal and closed branch heads')),
3282 ('c', 'closed', False, _('show normal and closed branch heads')),
3271 ] + templateopts,
3283 ] + templateopts,
3272 _('[-ct] [-r STARTREV] [REV]...'))
3284 _('[-ct] [-r STARTREV] [REV]...'))
3273 def heads(ui, repo, *branchrevs, **opts):
3285 def heads(ui, repo, *branchrevs, **opts):
3274 """show current repository heads or show branch heads
3286 """show current repository heads or show branch heads
3275
3287
3276 With no arguments, show all repository branch heads.
3288 With no arguments, show all repository branch heads.
3277
3289
3278 Repository "heads" are changesets with no child changesets. They are
3290 Repository "heads" are changesets with no child changesets. They are
3279 where development generally takes place and are the usual targets
3291 where development generally takes place and are the usual targets
3280 for update and merge operations. Branch heads are changesets that have
3292 for update and merge operations. Branch heads are changesets that have
3281 no child changeset on the same branch.
3293 no child changeset on the same branch.
3282
3294
3283 If one or more REVs are given, only branch heads on the branches
3295 If one or more REVs are given, only branch heads on the branches
3284 associated with the specified changesets are shown. This means
3296 associated with the specified changesets are shown. This means
3285 that you can use :hg:`heads foo` to see the heads on a branch
3297 that you can use :hg:`heads foo` to see the heads on a branch
3286 named ``foo``.
3298 named ``foo``.
3287
3299
3288 If -c/--closed is specified, also show branch heads marked closed
3300 If -c/--closed is specified, also show branch heads marked closed
3289 (see :hg:`commit --close-branch`).
3301 (see :hg:`commit --close-branch`).
3290
3302
3291 If STARTREV is specified, only those heads that are descendants of
3303 If STARTREV is specified, only those heads that are descendants of
3292 STARTREV will be displayed.
3304 STARTREV will be displayed.
3293
3305
3294 If -t/--topo is specified, named branch mechanics will be ignored and only
3306 If -t/--topo is specified, named branch mechanics will be ignored and only
3295 changesets without children will be shown.
3307 changesets without children will be shown.
3296
3308
3297 Returns 0 if matching heads are found, 1 if not.
3309 Returns 0 if matching heads are found, 1 if not.
3298 """
3310 """
3299
3311
3300 start = None
3312 start = None
3301 if 'rev' in opts:
3313 if 'rev' in opts:
3302 start = scmutil.revsingle(repo, opts['rev'], None).node()
3314 start = scmutil.revsingle(repo, opts['rev'], None).node()
3303
3315
3304 if opts.get('topo'):
3316 if opts.get('topo'):
3305 heads = [repo[h] for h in repo.heads(start)]
3317 heads = [repo[h] for h in repo.heads(start)]
3306 else:
3318 else:
3307 heads = []
3319 heads = []
3308 for branch in repo.branchmap():
3320 for branch in repo.branchmap():
3309 heads += repo.branchheads(branch, start, opts.get('closed'))
3321 heads += repo.branchheads(branch, start, opts.get('closed'))
3310 heads = [repo[h] for h in heads]
3322 heads = [repo[h] for h in heads]
3311
3323
3312 if branchrevs:
3324 if branchrevs:
3313 branches = set(repo[br].branch() for br in branchrevs)
3325 branches = set(repo[br].branch() for br in branchrevs)
3314 heads = [h for h in heads if h.branch() in branches]
3326 heads = [h for h in heads if h.branch() in branches]
3315
3327
3316 if opts.get('active') and branchrevs:
3328 if opts.get('active') and branchrevs:
3317 dagheads = repo.heads(start)
3329 dagheads = repo.heads(start)
3318 heads = [h for h in heads if h.node() in dagheads]
3330 heads = [h for h in heads if h.node() in dagheads]
3319
3331
3320 if branchrevs:
3332 if branchrevs:
3321 haveheads = set(h.branch() for h in heads)
3333 haveheads = set(h.branch() for h in heads)
3322 if branches - haveheads:
3334 if branches - haveheads:
3323 headless = ', '.join(b for b in branches - haveheads)
3335 headless = ', '.join(b for b in branches - haveheads)
3324 msg = _('no open branch heads found on branches %s')
3336 msg = _('no open branch heads found on branches %s')
3325 if opts.get('rev'):
3337 if opts.get('rev'):
3326 msg += _(' (started at %s)') % opts['rev']
3338 msg += _(' (started at %s)') % opts['rev']
3327 ui.warn((msg + '\n') % headless)
3339 ui.warn((msg + '\n') % headless)
3328
3340
3329 if not heads:
3341 if not heads:
3330 return 1
3342 return 1
3331
3343
3332 heads = sorted(heads, key=lambda x: -x.rev())
3344 heads = sorted(heads, key=lambda x: -x.rev())
3333 displayer = cmdutil.show_changeset(ui, repo, opts)
3345 displayer = cmdutil.show_changeset(ui, repo, opts)
3334 for ctx in heads:
3346 for ctx in heads:
3335 displayer.show(ctx)
3347 displayer.show(ctx)
3336 displayer.close()
3348 displayer.close()
3337
3349
3338 @command('help',
3350 @command('help',
3339 [('e', 'extension', None, _('show only help for extensions')),
3351 [('e', 'extension', None, _('show only help for extensions')),
3340 ('c', 'command', None, _('show only help for commands')),
3352 ('c', 'command', None, _('show only help for commands')),
3341 ('k', 'keyword', '', _('show topics matching keyword')),
3353 ('k', 'keyword', '', _('show topics matching keyword')),
3342 ],
3354 ],
3343 _('[-ec] [TOPIC]'))
3355 _('[-ec] [TOPIC]'))
3344 def help_(ui, name=None, **opts):
3356 def help_(ui, name=None, **opts):
3345 """show help for a given topic or a help overview
3357 """show help for a given topic or a help overview
3346
3358
3347 With no arguments, print a list of commands with short help messages.
3359 With no arguments, print a list of commands with short help messages.
3348
3360
3349 Given a topic, extension, or command name, print help for that
3361 Given a topic, extension, or command name, print help for that
3350 topic.
3362 topic.
3351
3363
3352 Returns 0 if successful.
3364 Returns 0 if successful.
3353 """
3365 """
3354
3366
3355 textwidth = min(ui.termwidth(), 80) - 2
3367 textwidth = min(ui.termwidth(), 80) - 2
3356
3368
3357 keep = ui.verbose and ['verbose'] or []
3369 keep = ui.verbose and ['verbose'] or []
3358 text = help.help_(ui, name, **opts)
3370 text = help.help_(ui, name, **opts)
3359
3371
3360 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3372 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3361 if 'verbose' in pruned:
3373 if 'verbose' in pruned:
3362 keep.append('omitted')
3374 keep.append('omitted')
3363 else:
3375 else:
3364 keep.append('notomitted')
3376 keep.append('notomitted')
3365 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3377 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3366 ui.write(formatted)
3378 ui.write(formatted)
3367
3379
3368
3380
3369 @command('identify|id',
3381 @command('identify|id',
3370 [('r', 'rev', '',
3382 [('r', 'rev', '',
3371 _('identify the specified revision'), _('REV')),
3383 _('identify the specified revision'), _('REV')),
3372 ('n', 'num', None, _('show local revision number')),
3384 ('n', 'num', None, _('show local revision number')),
3373 ('i', 'id', None, _('show global revision id')),
3385 ('i', 'id', None, _('show global revision id')),
3374 ('b', 'branch', None, _('show branch')),
3386 ('b', 'branch', None, _('show branch')),
3375 ('t', 'tags', None, _('show tags')),
3387 ('t', 'tags', None, _('show tags')),
3376 ('B', 'bookmarks', None, _('show bookmarks')),
3388 ('B', 'bookmarks', None, _('show bookmarks')),
3377 ] + remoteopts,
3389 ] + remoteopts,
3378 _('[-nibtB] [-r REV] [SOURCE]'))
3390 _('[-nibtB] [-r REV] [SOURCE]'))
3379 def identify(ui, repo, source=None, rev=None,
3391 def identify(ui, repo, source=None, rev=None,
3380 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3392 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3381 """identify the working copy or specified revision
3393 """identify the working copy or specified revision
3382
3394
3383 Print a summary identifying the repository state at REV using one or
3395 Print a summary identifying the repository state at REV using one or
3384 two parent hash identifiers, followed by a "+" if the working
3396 two parent hash identifiers, followed by a "+" if the working
3385 directory has uncommitted changes, the branch name (if not default),
3397 directory has uncommitted changes, the branch name (if not default),
3386 a list of tags, and a list of bookmarks.
3398 a list of tags, and a list of bookmarks.
3387
3399
3388 When REV is not given, print a summary of the current state of the
3400 When REV is not given, print a summary of the current state of the
3389 repository.
3401 repository.
3390
3402
3391 Specifying a path to a repository root or Mercurial bundle will
3403 Specifying a path to a repository root or Mercurial bundle will
3392 cause lookup to operate on that repository/bundle.
3404 cause lookup to operate on that repository/bundle.
3393
3405
3394 .. container:: verbose
3406 .. container:: verbose
3395
3407
3396 Examples:
3408 Examples:
3397
3409
3398 - generate a build identifier for the working directory::
3410 - generate a build identifier for the working directory::
3399
3411
3400 hg id --id > build-id.dat
3412 hg id --id > build-id.dat
3401
3413
3402 - find the revision corresponding to a tag::
3414 - find the revision corresponding to a tag::
3403
3415
3404 hg id -n -r 1.3
3416 hg id -n -r 1.3
3405
3417
3406 - check the most recent revision of a remote repository::
3418 - check the most recent revision of a remote repository::
3407
3419
3408 hg id -r tip http://selenic.com/hg/
3420 hg id -r tip http://selenic.com/hg/
3409
3421
3410 Returns 0 if successful.
3422 Returns 0 if successful.
3411 """
3423 """
3412
3424
3413 if not repo and not source:
3425 if not repo and not source:
3414 raise util.Abort(_("there is no Mercurial repository here "
3426 raise util.Abort(_("there is no Mercurial repository here "
3415 "(.hg not found)"))
3427 "(.hg not found)"))
3416
3428
3417 hexfunc = ui.debugflag and hex or short
3429 hexfunc = ui.debugflag and hex or short
3418 default = not (num or id or branch or tags or bookmarks)
3430 default = not (num or id or branch or tags or bookmarks)
3419 output = []
3431 output = []
3420 revs = []
3432 revs = []
3421
3433
3422 if source:
3434 if source:
3423 source, branches = hg.parseurl(ui.expandpath(source))
3435 source, branches = hg.parseurl(ui.expandpath(source))
3424 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3436 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3425 repo = peer.local()
3437 repo = peer.local()
3426 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3438 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3427
3439
3428 if not repo:
3440 if not repo:
3429 if num or branch or tags:
3441 if num or branch or tags:
3430 raise util.Abort(
3442 raise util.Abort(
3431 _("can't query remote revision number, branch, or tags"))
3443 _("can't query remote revision number, branch, or tags"))
3432 if not rev and revs:
3444 if not rev and revs:
3433 rev = revs[0]
3445 rev = revs[0]
3434 if not rev:
3446 if not rev:
3435 rev = "tip"
3447 rev = "tip"
3436
3448
3437 remoterev = peer.lookup(rev)
3449 remoterev = peer.lookup(rev)
3438 if default or id:
3450 if default or id:
3439 output = [hexfunc(remoterev)]
3451 output = [hexfunc(remoterev)]
3440
3452
3441 def getbms():
3453 def getbms():
3442 bms = []
3454 bms = []
3443
3455
3444 if 'bookmarks' in peer.listkeys('namespaces'):
3456 if 'bookmarks' in peer.listkeys('namespaces'):
3445 hexremoterev = hex(remoterev)
3457 hexremoterev = hex(remoterev)
3446 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3458 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3447 if bmr == hexremoterev]
3459 if bmr == hexremoterev]
3448
3460
3449 return sorted(bms)
3461 return sorted(bms)
3450
3462
3451 if bookmarks:
3463 if bookmarks:
3452 output.extend(getbms())
3464 output.extend(getbms())
3453 elif default and not ui.quiet:
3465 elif default and not ui.quiet:
3454 # multiple bookmarks for a single parent separated by '/'
3466 # multiple bookmarks for a single parent separated by '/'
3455 bm = '/'.join(getbms())
3467 bm = '/'.join(getbms())
3456 if bm:
3468 if bm:
3457 output.append(bm)
3469 output.append(bm)
3458 else:
3470 else:
3459 if not rev:
3471 if not rev:
3460 ctx = repo[None]
3472 ctx = repo[None]
3461 parents = ctx.parents()
3473 parents = ctx.parents()
3462 changed = ""
3474 changed = ""
3463 if default or id or num:
3475 if default or id or num:
3464 if (util.any(repo.status())
3476 if (util.any(repo.status())
3465 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3477 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3466 changed = '+'
3478 changed = '+'
3467 if default or id:
3479 if default or id:
3468 output = ["%s%s" %
3480 output = ["%s%s" %
3469 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3481 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3470 if num:
3482 if num:
3471 output.append("%s%s" %
3483 output.append("%s%s" %
3472 ('+'.join([str(p.rev()) for p in parents]), changed))
3484 ('+'.join([str(p.rev()) for p in parents]), changed))
3473 else:
3485 else:
3474 ctx = scmutil.revsingle(repo, rev)
3486 ctx = scmutil.revsingle(repo, rev)
3475 if default or id:
3487 if default or id:
3476 output = [hexfunc(ctx.node())]
3488 output = [hexfunc(ctx.node())]
3477 if num:
3489 if num:
3478 output.append(str(ctx.rev()))
3490 output.append(str(ctx.rev()))
3479
3491
3480 if default and not ui.quiet:
3492 if default and not ui.quiet:
3481 b = ctx.branch()
3493 b = ctx.branch()
3482 if b != 'default':
3494 if b != 'default':
3483 output.append("(%s)" % b)
3495 output.append("(%s)" % b)
3484
3496
3485 # multiple tags for a single parent separated by '/'
3497 # multiple tags for a single parent separated by '/'
3486 t = '/'.join(ctx.tags())
3498 t = '/'.join(ctx.tags())
3487 if t:
3499 if t:
3488 output.append(t)
3500 output.append(t)
3489
3501
3490 # multiple bookmarks for a single parent separated by '/'
3502 # multiple bookmarks for a single parent separated by '/'
3491 bm = '/'.join(ctx.bookmarks())
3503 bm = '/'.join(ctx.bookmarks())
3492 if bm:
3504 if bm:
3493 output.append(bm)
3505 output.append(bm)
3494 else:
3506 else:
3495 if branch:
3507 if branch:
3496 output.append(ctx.branch())
3508 output.append(ctx.branch())
3497
3509
3498 if tags:
3510 if tags:
3499 output.extend(ctx.tags())
3511 output.extend(ctx.tags())
3500
3512
3501 if bookmarks:
3513 if bookmarks:
3502 output.extend(ctx.bookmarks())
3514 output.extend(ctx.bookmarks())
3503
3515
3504 ui.write("%s\n" % ' '.join(output))
3516 ui.write("%s\n" % ' '.join(output))
3505
3517
3506 @command('import|patch',
3518 @command('import|patch',
3507 [('p', 'strip', 1,
3519 [('p', 'strip', 1,
3508 _('directory strip option for patch. This has the same '
3520 _('directory strip option for patch. This has the same '
3509 'meaning as the corresponding patch option'), _('NUM')),
3521 'meaning as the corresponding patch option'), _('NUM')),
3510 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3522 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3511 ('e', 'edit', False, _('invoke editor on commit messages')),
3523 ('e', 'edit', False, _('invoke editor on commit messages')),
3512 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3524 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3513 ('', 'no-commit', None,
3525 ('', 'no-commit', None,
3514 _("don't commit, just update the working directory")),
3526 _("don't commit, just update the working directory")),
3515 ('', 'bypass', None,
3527 ('', 'bypass', None,
3516 _("apply patch without touching the working directory")),
3528 _("apply patch without touching the working directory")),
3517 ('', 'exact', None,
3529 ('', 'exact', None,
3518 _('apply patch to the nodes from which it was generated')),
3530 _('apply patch to the nodes from which it was generated')),
3519 ('', 'import-branch', None,
3531 ('', 'import-branch', None,
3520 _('use any branch information in patch (implied by --exact)'))] +
3532 _('use any branch information in patch (implied by --exact)'))] +
3521 commitopts + commitopts2 + similarityopts,
3533 commitopts + commitopts2 + similarityopts,
3522 _('[OPTION]... PATCH...'))
3534 _('[OPTION]... PATCH...'))
3523 def import_(ui, repo, patch1=None, *patches, **opts):
3535 def import_(ui, repo, patch1=None, *patches, **opts):
3524 """import an ordered set of patches
3536 """import an ordered set of patches
3525
3537
3526 Import a list of patches and commit them individually (unless
3538 Import a list of patches and commit them individually (unless
3527 --no-commit is specified).
3539 --no-commit is specified).
3528
3540
3529 If there are outstanding changes in the working directory, import
3541 If there are outstanding changes in the working directory, import
3530 will abort unless given the -f/--force flag.
3542 will abort unless given the -f/--force flag.
3531
3543
3532 You can import a patch straight from a mail message. Even patches
3544 You can import a patch straight from a mail message. Even patches
3533 as attachments work (to use the body part, it must have type
3545 as attachments work (to use the body part, it must have type
3534 text/plain or text/x-patch). From and Subject headers of email
3546 text/plain or text/x-patch). From and Subject headers of email
3535 message are used as default committer and commit message. All
3547 message are used as default committer and commit message. All
3536 text/plain body parts before first diff are added to commit
3548 text/plain body parts before first diff are added to commit
3537 message.
3549 message.
3538
3550
3539 If the imported patch was generated by :hg:`export`, user and
3551 If the imported patch was generated by :hg:`export`, user and
3540 description from patch override values from message headers and
3552 description from patch override values from message headers and
3541 body. Values given on command line with -m/--message and -u/--user
3553 body. Values given on command line with -m/--message and -u/--user
3542 override these.
3554 override these.
3543
3555
3544 If --exact is specified, import will set the working directory to
3556 If --exact is specified, import will set the working directory to
3545 the parent of each patch before applying it, and will abort if the
3557 the parent of each patch before applying it, and will abort if the
3546 resulting changeset has a different ID than the one recorded in
3558 resulting changeset has a different ID than the one recorded in
3547 the patch. This may happen due to character set problems or other
3559 the patch. This may happen due to character set problems or other
3548 deficiencies in the text patch format.
3560 deficiencies in the text patch format.
3549
3561
3550 Use --bypass to apply and commit patches directly to the
3562 Use --bypass to apply and commit patches directly to the
3551 repository, not touching the working directory. Without --exact,
3563 repository, not touching the working directory. Without --exact,
3552 patches will be applied on top of the working directory parent
3564 patches will be applied on top of the working directory parent
3553 revision.
3565 revision.
3554
3566
3555 With -s/--similarity, hg will attempt to discover renames and
3567 With -s/--similarity, hg will attempt to discover renames and
3556 copies in the patch in the same way as :hg:`addremove`.
3568 copies in the patch in the same way as :hg:`addremove`.
3557
3569
3558 To read a patch from standard input, use "-" as the patch name. If
3570 To read a patch from standard input, use "-" as the patch name. If
3559 a URL is specified, the patch will be downloaded from it.
3571 a URL is specified, the patch will be downloaded from it.
3560 See :hg:`help dates` for a list of formats valid for -d/--date.
3572 See :hg:`help dates` for a list of formats valid for -d/--date.
3561
3573
3562 .. container:: verbose
3574 .. container:: verbose
3563
3575
3564 Examples:
3576 Examples:
3565
3577
3566 - import a traditional patch from a website and detect renames::
3578 - import a traditional patch from a website and detect renames::
3567
3579
3568 hg import -s 80 http://example.com/bugfix.patch
3580 hg import -s 80 http://example.com/bugfix.patch
3569
3581
3570 - import a changeset from an hgweb server::
3582 - import a changeset from an hgweb server::
3571
3583
3572 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3584 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3573
3585
3574 - import all the patches in an Unix-style mbox::
3586 - import all the patches in an Unix-style mbox::
3575
3587
3576 hg import incoming-patches.mbox
3588 hg import incoming-patches.mbox
3577
3589
3578 - attempt to exactly restore an exported changeset (not always
3590 - attempt to exactly restore an exported changeset (not always
3579 possible)::
3591 possible)::
3580
3592
3581 hg import --exact proposed-fix.patch
3593 hg import --exact proposed-fix.patch
3582
3594
3583 Returns 0 on success.
3595 Returns 0 on success.
3584 """
3596 """
3585
3597
3586 if not patch1:
3598 if not patch1:
3587 raise util.Abort(_('need at least one patch to import'))
3599 raise util.Abort(_('need at least one patch to import'))
3588
3600
3589 patches = (patch1,) + patches
3601 patches = (patch1,) + patches
3590
3602
3591 date = opts.get('date')
3603 date = opts.get('date')
3592 if date:
3604 if date:
3593 opts['date'] = util.parsedate(date)
3605 opts['date'] = util.parsedate(date)
3594
3606
3595 editor = cmdutil.commiteditor
3607 editor = cmdutil.commiteditor
3596 if opts.get('edit'):
3608 if opts.get('edit'):
3597 editor = cmdutil.commitforceeditor
3609 editor = cmdutil.commitforceeditor
3598
3610
3599 update = not opts.get('bypass')
3611 update = not opts.get('bypass')
3600 if not update and opts.get('no_commit'):
3612 if not update and opts.get('no_commit'):
3601 raise util.Abort(_('cannot use --no-commit with --bypass'))
3613 raise util.Abort(_('cannot use --no-commit with --bypass'))
3602 try:
3614 try:
3603 sim = float(opts.get('similarity') or 0)
3615 sim = float(opts.get('similarity') or 0)
3604 except ValueError:
3616 except ValueError:
3605 raise util.Abort(_('similarity must be a number'))
3617 raise util.Abort(_('similarity must be a number'))
3606 if sim < 0 or sim > 100:
3618 if sim < 0 or sim > 100:
3607 raise util.Abort(_('similarity must be between 0 and 100'))
3619 raise util.Abort(_('similarity must be between 0 and 100'))
3608 if sim and not update:
3620 if sim and not update:
3609 raise util.Abort(_('cannot use --similarity with --bypass'))
3621 raise util.Abort(_('cannot use --similarity with --bypass'))
3610
3622
3611 if (opts.get('exact') or not opts.get('force')) and update:
3623 if (opts.get('exact') or not opts.get('force')) and update:
3612 cmdutil.bailifchanged(repo)
3624 cmdutil.bailifchanged(repo)
3613
3625
3614 base = opts["base"]
3626 base = opts["base"]
3615 strip = opts["strip"]
3627 strip = opts["strip"]
3616 wlock = lock = tr = None
3628 wlock = lock = tr = None
3617 msgs = []
3629 msgs = []
3618
3630
3619 def tryone(ui, hunk, parents):
3631 def tryone(ui, hunk, parents):
3620 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3632 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3621 patch.extract(ui, hunk)
3633 patch.extract(ui, hunk)
3622
3634
3623 if not tmpname:
3635 if not tmpname:
3624 return (None, None)
3636 return (None, None)
3625 msg = _('applied to working directory')
3637 msg = _('applied to working directory')
3626
3638
3627 try:
3639 try:
3628 cmdline_message = cmdutil.logmessage(ui, opts)
3640 cmdline_message = cmdutil.logmessage(ui, opts)
3629 if cmdline_message:
3641 if cmdline_message:
3630 # pickup the cmdline msg
3642 # pickup the cmdline msg
3631 message = cmdline_message
3643 message = cmdline_message
3632 elif message:
3644 elif message:
3633 # pickup the patch msg
3645 # pickup the patch msg
3634 message = message.strip()
3646 message = message.strip()
3635 else:
3647 else:
3636 # launch the editor
3648 # launch the editor
3637 message = None
3649 message = None
3638 ui.debug('message:\n%s\n' % message)
3650 ui.debug('message:\n%s\n' % message)
3639
3651
3640 if len(parents) == 1:
3652 if len(parents) == 1:
3641 parents.append(repo[nullid])
3653 parents.append(repo[nullid])
3642 if opts.get('exact'):
3654 if opts.get('exact'):
3643 if not nodeid or not p1:
3655 if not nodeid or not p1:
3644 raise util.Abort(_('not a Mercurial patch'))
3656 raise util.Abort(_('not a Mercurial patch'))
3645 p1 = repo[p1]
3657 p1 = repo[p1]
3646 p2 = repo[p2 or nullid]
3658 p2 = repo[p2 or nullid]
3647 elif p2:
3659 elif p2:
3648 try:
3660 try:
3649 p1 = repo[p1]
3661 p1 = repo[p1]
3650 p2 = repo[p2]
3662 p2 = repo[p2]
3651 # Without any options, consider p2 only if the
3663 # Without any options, consider p2 only if the
3652 # patch is being applied on top of the recorded
3664 # patch is being applied on top of the recorded
3653 # first parent.
3665 # first parent.
3654 if p1 != parents[0]:
3666 if p1 != parents[0]:
3655 p1 = parents[0]
3667 p1 = parents[0]
3656 p2 = repo[nullid]
3668 p2 = repo[nullid]
3657 except error.RepoError:
3669 except error.RepoError:
3658 p1, p2 = parents
3670 p1, p2 = parents
3659 else:
3671 else:
3660 p1, p2 = parents
3672 p1, p2 = parents
3661
3673
3662 n = None
3674 n = None
3663 if update:
3675 if update:
3664 if p1 != parents[0]:
3676 if p1 != parents[0]:
3665 hg.clean(repo, p1.node())
3677 hg.clean(repo, p1.node())
3666 if p2 != parents[1]:
3678 if p2 != parents[1]:
3667 repo.setparents(p1.node(), p2.node())
3679 repo.setparents(p1.node(), p2.node())
3668
3680
3669 if opts.get('exact') or opts.get('import_branch'):
3681 if opts.get('exact') or opts.get('import_branch'):
3670 repo.dirstate.setbranch(branch or 'default')
3682 repo.dirstate.setbranch(branch or 'default')
3671
3683
3672 files = set()
3684 files = set()
3673 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3685 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3674 eolmode=None, similarity=sim / 100.0)
3686 eolmode=None, similarity=sim / 100.0)
3675 files = list(files)
3687 files = list(files)
3676 if opts.get('no_commit'):
3688 if opts.get('no_commit'):
3677 if message:
3689 if message:
3678 msgs.append(message)
3690 msgs.append(message)
3679 else:
3691 else:
3680 if opts.get('exact') or p2:
3692 if opts.get('exact') or p2:
3681 # If you got here, you either use --force and know what
3693 # If you got here, you either use --force and know what
3682 # you are doing or used --exact or a merge patch while
3694 # you are doing or used --exact or a merge patch while
3683 # being updated to its first parent.
3695 # being updated to its first parent.
3684 m = None
3696 m = None
3685 else:
3697 else:
3686 m = scmutil.matchfiles(repo, files or [])
3698 m = scmutil.matchfiles(repo, files or [])
3687 n = repo.commit(message, opts.get('user') or user,
3699 n = repo.commit(message, opts.get('user') or user,
3688 opts.get('date') or date, match=m,
3700 opts.get('date') or date, match=m,
3689 editor=editor)
3701 editor=editor)
3690 else:
3702 else:
3691 if opts.get('exact') or opts.get('import_branch'):
3703 if opts.get('exact') or opts.get('import_branch'):
3692 branch = branch or 'default'
3704 branch = branch or 'default'
3693 else:
3705 else:
3694 branch = p1.branch()
3706 branch = p1.branch()
3695 store = patch.filestore()
3707 store = patch.filestore()
3696 try:
3708 try:
3697 files = set()
3709 files = set()
3698 try:
3710 try:
3699 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3711 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3700 files, eolmode=None)
3712 files, eolmode=None)
3701 except patch.PatchError, e:
3713 except patch.PatchError, e:
3702 raise util.Abort(str(e))
3714 raise util.Abort(str(e))
3703 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3715 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3704 message,
3716 message,
3705 opts.get('user') or user,
3717 opts.get('user') or user,
3706 opts.get('date') or date,
3718 opts.get('date') or date,
3707 branch, files, store,
3719 branch, files, store,
3708 editor=cmdutil.commiteditor)
3720 editor=cmdutil.commiteditor)
3709 repo.savecommitmessage(memctx.description())
3721 repo.savecommitmessage(memctx.description())
3710 n = memctx.commit()
3722 n = memctx.commit()
3711 finally:
3723 finally:
3712 store.close()
3724 store.close()
3713 if opts.get('exact') and hex(n) != nodeid:
3725 if opts.get('exact') and hex(n) != nodeid:
3714 raise util.Abort(_('patch is damaged or loses information'))
3726 raise util.Abort(_('patch is damaged or loses information'))
3715 if n:
3727 if n:
3716 # i18n: refers to a short changeset id
3728 # i18n: refers to a short changeset id
3717 msg = _('created %s') % short(n)
3729 msg = _('created %s') % short(n)
3718 return (msg, n)
3730 return (msg, n)
3719 finally:
3731 finally:
3720 os.unlink(tmpname)
3732 os.unlink(tmpname)
3721
3733
3722 try:
3734 try:
3723 try:
3735 try:
3724 wlock = repo.wlock()
3736 wlock = repo.wlock()
3725 if not opts.get('no_commit'):
3737 if not opts.get('no_commit'):
3726 lock = repo.lock()
3738 lock = repo.lock()
3727 tr = repo.transaction('import')
3739 tr = repo.transaction('import')
3728 parents = repo.parents()
3740 parents = repo.parents()
3729 for patchurl in patches:
3741 for patchurl in patches:
3730 if patchurl == '-':
3742 if patchurl == '-':
3731 ui.status(_('applying patch from stdin\n'))
3743 ui.status(_('applying patch from stdin\n'))
3732 patchfile = ui.fin
3744 patchfile = ui.fin
3733 patchurl = 'stdin' # for error message
3745 patchurl = 'stdin' # for error message
3734 else:
3746 else:
3735 patchurl = os.path.join(base, patchurl)
3747 patchurl = os.path.join(base, patchurl)
3736 ui.status(_('applying %s\n') % patchurl)
3748 ui.status(_('applying %s\n') % patchurl)
3737 patchfile = hg.openpath(ui, patchurl)
3749 patchfile = hg.openpath(ui, patchurl)
3738
3750
3739 haspatch = False
3751 haspatch = False
3740 for hunk in patch.split(patchfile):
3752 for hunk in patch.split(patchfile):
3741 (msg, node) = tryone(ui, hunk, parents)
3753 (msg, node) = tryone(ui, hunk, parents)
3742 if msg:
3754 if msg:
3743 haspatch = True
3755 haspatch = True
3744 ui.note(msg + '\n')
3756 ui.note(msg + '\n')
3745 if update or opts.get('exact'):
3757 if update or opts.get('exact'):
3746 parents = repo.parents()
3758 parents = repo.parents()
3747 else:
3759 else:
3748 parents = [repo[node]]
3760 parents = [repo[node]]
3749
3761
3750 if not haspatch:
3762 if not haspatch:
3751 raise util.Abort(_('%s: no diffs found') % patchurl)
3763 raise util.Abort(_('%s: no diffs found') % patchurl)
3752
3764
3753 if tr:
3765 if tr:
3754 tr.close()
3766 tr.close()
3755 if msgs:
3767 if msgs:
3756 repo.savecommitmessage('\n* * *\n'.join(msgs))
3768 repo.savecommitmessage('\n* * *\n'.join(msgs))
3757 except: # re-raises
3769 except: # re-raises
3758 # wlock.release() indirectly calls dirstate.write(): since
3770 # wlock.release() indirectly calls dirstate.write(): since
3759 # we're crashing, we do not want to change the working dir
3771 # we're crashing, we do not want to change the working dir
3760 # parent after all, so make sure it writes nothing
3772 # parent after all, so make sure it writes nothing
3761 repo.dirstate.invalidate()
3773 repo.dirstate.invalidate()
3762 raise
3774 raise
3763 finally:
3775 finally:
3764 if tr:
3776 if tr:
3765 tr.release()
3777 tr.release()
3766 release(lock, wlock)
3778 release(lock, wlock)
3767
3779
3768 @command('incoming|in',
3780 @command('incoming|in',
3769 [('f', 'force', None,
3781 [('f', 'force', None,
3770 _('run even if remote repository is unrelated')),
3782 _('run even if remote repository is unrelated')),
3771 ('n', 'newest-first', None, _('show newest record first')),
3783 ('n', 'newest-first', None, _('show newest record first')),
3772 ('', 'bundle', '',
3784 ('', 'bundle', '',
3773 _('file to store the bundles into'), _('FILE')),
3785 _('file to store the bundles into'), _('FILE')),
3774 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3786 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3775 ('B', 'bookmarks', False, _("compare bookmarks")),
3787 ('B', 'bookmarks', False, _("compare bookmarks")),
3776 ('b', 'branch', [],
3788 ('b', 'branch', [],
3777 _('a specific branch you would like to pull'), _('BRANCH')),
3789 _('a specific branch you would like to pull'), _('BRANCH')),
3778 ] + logopts + remoteopts + subrepoopts,
3790 ] + logopts + remoteopts + subrepoopts,
3779 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3791 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3780 def incoming(ui, repo, source="default", **opts):
3792 def incoming(ui, repo, source="default", **opts):
3781 """show new changesets found in source
3793 """show new changesets found in source
3782
3794
3783 Show new changesets found in the specified path/URL or the default
3795 Show new changesets found in the specified path/URL or the default
3784 pull location. These are the changesets that would have been pulled
3796 pull location. These are the changesets that would have been pulled
3785 if a pull at the time you issued this command.
3797 if a pull at the time you issued this command.
3786
3798
3787 For remote repository, using --bundle avoids downloading the
3799 For remote repository, using --bundle avoids downloading the
3788 changesets twice if the incoming is followed by a pull.
3800 changesets twice if the incoming is followed by a pull.
3789
3801
3790 See pull for valid source format details.
3802 See pull for valid source format details.
3791
3803
3792 Returns 0 if there are incoming changes, 1 otherwise.
3804 Returns 0 if there are incoming changes, 1 otherwise.
3793 """
3805 """
3794 if opts.get('graph'):
3806 if opts.get('graph'):
3795 cmdutil.checkunsupportedgraphflags([], opts)
3807 cmdutil.checkunsupportedgraphflags([], opts)
3796 def display(other, chlist, displayer):
3808 def display(other, chlist, displayer):
3797 revdag = cmdutil.graphrevs(other, chlist, opts)
3809 revdag = cmdutil.graphrevs(other, chlist, opts)
3798 showparents = [ctx.node() for ctx in repo[None].parents()]
3810 showparents = [ctx.node() for ctx in repo[None].parents()]
3799 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3811 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3800 graphmod.asciiedges)
3812 graphmod.asciiedges)
3801
3813
3802 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3814 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3803 return 0
3815 return 0
3804
3816
3805 if opts.get('bundle') and opts.get('subrepos'):
3817 if opts.get('bundle') and opts.get('subrepos'):
3806 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3818 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3807
3819
3808 if opts.get('bookmarks'):
3820 if opts.get('bookmarks'):
3809 source, branches = hg.parseurl(ui.expandpath(source),
3821 source, branches = hg.parseurl(ui.expandpath(source),
3810 opts.get('branch'))
3822 opts.get('branch'))
3811 other = hg.peer(repo, opts, source)
3823 other = hg.peer(repo, opts, source)
3812 if 'bookmarks' not in other.listkeys('namespaces'):
3824 if 'bookmarks' not in other.listkeys('namespaces'):
3813 ui.warn(_("remote doesn't support bookmarks\n"))
3825 ui.warn(_("remote doesn't support bookmarks\n"))
3814 return 0
3826 return 0
3815 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3827 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3816 return bookmarks.diff(ui, repo, other)
3828 return bookmarks.diff(ui, repo, other)
3817
3829
3818 repo._subtoppath = ui.expandpath(source)
3830 repo._subtoppath = ui.expandpath(source)
3819 try:
3831 try:
3820 return hg.incoming(ui, repo, source, opts)
3832 return hg.incoming(ui, repo, source, opts)
3821 finally:
3833 finally:
3822 del repo._subtoppath
3834 del repo._subtoppath
3823
3835
3824
3836
3825 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3837 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3826 def init(ui, dest=".", **opts):
3838 def init(ui, dest=".", **opts):
3827 """create a new repository in the given directory
3839 """create a new repository in the given directory
3828
3840
3829 Initialize a new repository in the given directory. If the given
3841 Initialize a new repository in the given directory. If the given
3830 directory does not exist, it will be created.
3842 directory does not exist, it will be created.
3831
3843
3832 If no directory is given, the current directory is used.
3844 If no directory is given, the current directory is used.
3833
3845
3834 It is possible to specify an ``ssh://`` URL as the destination.
3846 It is possible to specify an ``ssh://`` URL as the destination.
3835 See :hg:`help urls` for more information.
3847 See :hg:`help urls` for more information.
3836
3848
3837 Returns 0 on success.
3849 Returns 0 on success.
3838 """
3850 """
3839 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3851 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3840
3852
3841 @command('locate',
3853 @command('locate',
3842 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3854 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3843 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3855 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3844 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3856 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3845 ] + walkopts,
3857 ] + walkopts,
3846 _('[OPTION]... [PATTERN]...'))
3858 _('[OPTION]... [PATTERN]...'))
3847 def locate(ui, repo, *pats, **opts):
3859 def locate(ui, repo, *pats, **opts):
3848 """locate files matching specific patterns
3860 """locate files matching specific patterns
3849
3861
3850 Print files under Mercurial control in the working directory whose
3862 Print files under Mercurial control in the working directory whose
3851 names match the given patterns.
3863 names match the given patterns.
3852
3864
3853 By default, this command searches all directories in the working
3865 By default, this command searches all directories in the working
3854 directory. To search just the current directory and its
3866 directory. To search just the current directory and its
3855 subdirectories, use "--include .".
3867 subdirectories, use "--include .".
3856
3868
3857 If no patterns are given to match, this command prints the names
3869 If no patterns are given to match, this command prints the names
3858 of all files under Mercurial control in the working directory.
3870 of all files under Mercurial control in the working directory.
3859
3871
3860 If you want to feed the output of this command into the "xargs"
3872 If you want to feed the output of this command into the "xargs"
3861 command, use the -0 option to both this command and "xargs". This
3873 command, use the -0 option to both this command and "xargs". This
3862 will avoid the problem of "xargs" treating single filenames that
3874 will avoid the problem of "xargs" treating single filenames that
3863 contain whitespace as multiple filenames.
3875 contain whitespace as multiple filenames.
3864
3876
3865 Returns 0 if a match is found, 1 otherwise.
3877 Returns 0 if a match is found, 1 otherwise.
3866 """
3878 """
3867 end = opts.get('print0') and '\0' or '\n'
3879 end = opts.get('print0') and '\0' or '\n'
3868 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3880 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3869
3881
3870 ret = 1
3882 ret = 1
3871 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3883 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3872 m.bad = lambda x, y: False
3884 m.bad = lambda x, y: False
3873 for abs in repo[rev].walk(m):
3885 for abs in repo[rev].walk(m):
3874 if not rev and abs not in repo.dirstate:
3886 if not rev and abs not in repo.dirstate:
3875 continue
3887 continue
3876 if opts.get('fullpath'):
3888 if opts.get('fullpath'):
3877 ui.write(repo.wjoin(abs), end)
3889 ui.write(repo.wjoin(abs), end)
3878 else:
3890 else:
3879 ui.write(((pats and m.rel(abs)) or abs), end)
3891 ui.write(((pats and m.rel(abs)) or abs), end)
3880 ret = 0
3892 ret = 0
3881
3893
3882 return ret
3894 return ret
3883
3895
3884 @command('^log|history',
3896 @command('^log|history',
3885 [('f', 'follow', None,
3897 [('f', 'follow', None,
3886 _('follow changeset history, or file history across copies and renames')),
3898 _('follow changeset history, or file history across copies and renames')),
3887 ('', 'follow-first', None,
3899 ('', 'follow-first', None,
3888 _('only follow the first parent of merge changesets (DEPRECATED)')),
3900 _('only follow the first parent of merge changesets (DEPRECATED)')),
3889 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3901 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3890 ('C', 'copies', None, _('show copied files')),
3902 ('C', 'copies', None, _('show copied files')),
3891 ('k', 'keyword', [],
3903 ('k', 'keyword', [],
3892 _('do case-insensitive search for a given text'), _('TEXT')),
3904 _('do case-insensitive search for a given text'), _('TEXT')),
3893 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3905 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3894 ('', 'removed', None, _('include revisions where files were removed')),
3906 ('', 'removed', None, _('include revisions where files were removed')),
3895 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3907 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3896 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3908 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3897 ('', 'only-branch', [],
3909 ('', 'only-branch', [],
3898 _('show only changesets within the given named branch (DEPRECATED)'),
3910 _('show only changesets within the given named branch (DEPRECATED)'),
3899 _('BRANCH')),
3911 _('BRANCH')),
3900 ('b', 'branch', [],
3912 ('b', 'branch', [],
3901 _('show changesets within the given named branch'), _('BRANCH')),
3913 _('show changesets within the given named branch'), _('BRANCH')),
3902 ('P', 'prune', [],
3914 ('P', 'prune', [],
3903 _('do not display revision or any of its ancestors'), _('REV')),
3915 _('do not display revision or any of its ancestors'), _('REV')),
3904 ] + logopts + walkopts,
3916 ] + logopts + walkopts,
3905 _('[OPTION]... [FILE]'))
3917 _('[OPTION]... [FILE]'))
3906 def log(ui, repo, *pats, **opts):
3918 def log(ui, repo, *pats, **opts):
3907 """show revision history of entire repository or files
3919 """show revision history of entire repository or files
3908
3920
3909 Print the revision history of the specified files or the entire
3921 Print the revision history of the specified files or the entire
3910 project.
3922 project.
3911
3923
3912 If no revision range is specified, the default is ``tip:0`` unless
3924 If no revision range is specified, the default is ``tip:0`` unless
3913 --follow is set, in which case the working directory parent is
3925 --follow is set, in which case the working directory parent is
3914 used as the starting revision.
3926 used as the starting revision.
3915
3927
3916 File history is shown without following rename or copy history of
3928 File history is shown without following rename or copy history of
3917 files. Use -f/--follow with a filename to follow history across
3929 files. Use -f/--follow with a filename to follow history across
3918 renames and copies. --follow without a filename will only show
3930 renames and copies. --follow without a filename will only show
3919 ancestors or descendants of the starting revision.
3931 ancestors or descendants of the starting revision.
3920
3932
3921 By default this command prints revision number and changeset id,
3933 By default this command prints revision number and changeset id,
3922 tags, non-trivial parents, user, date and time, and a summary for
3934 tags, non-trivial parents, user, date and time, and a summary for
3923 each commit. When the -v/--verbose switch is used, the list of
3935 each commit. When the -v/--verbose switch is used, the list of
3924 changed files and full commit message are shown.
3936 changed files and full commit message are shown.
3925
3937
3926 .. note::
3938 .. note::
3927 log -p/--patch may generate unexpected diff output for merge
3939 log -p/--patch may generate unexpected diff output for merge
3928 changesets, as it will only compare the merge changeset against
3940 changesets, as it will only compare the merge changeset against
3929 its first parent. Also, only files different from BOTH parents
3941 its first parent. Also, only files different from BOTH parents
3930 will appear in files:.
3942 will appear in files:.
3931
3943
3932 .. note::
3944 .. note::
3933 for performance reasons, log FILE may omit duplicate changes
3945 for performance reasons, log FILE may omit duplicate changes
3934 made on branches and will not show deletions. To see all
3946 made on branches and will not show deletions. To see all
3935 changes including duplicates and deletions, use the --removed
3947 changes including duplicates and deletions, use the --removed
3936 switch.
3948 switch.
3937
3949
3938 .. container:: verbose
3950 .. container:: verbose
3939
3951
3940 Some examples:
3952 Some examples:
3941
3953
3942 - changesets with full descriptions and file lists::
3954 - changesets with full descriptions and file lists::
3943
3955
3944 hg log -v
3956 hg log -v
3945
3957
3946 - changesets ancestral to the working directory::
3958 - changesets ancestral to the working directory::
3947
3959
3948 hg log -f
3960 hg log -f
3949
3961
3950 - last 10 commits on the current branch::
3962 - last 10 commits on the current branch::
3951
3963
3952 hg log -l 10 -b .
3964 hg log -l 10 -b .
3953
3965
3954 - changesets showing all modifications of a file, including removals::
3966 - changesets showing all modifications of a file, including removals::
3955
3967
3956 hg log --removed file.c
3968 hg log --removed file.c
3957
3969
3958 - all changesets that touch a directory, with diffs, excluding merges::
3970 - all changesets that touch a directory, with diffs, excluding merges::
3959
3971
3960 hg log -Mp lib/
3972 hg log -Mp lib/
3961
3973
3962 - all revision numbers that match a keyword::
3974 - all revision numbers that match a keyword::
3963
3975
3964 hg log -k bug --template "{rev}\\n"
3976 hg log -k bug --template "{rev}\\n"
3965
3977
3966 - check if a given changeset is included is a tagged release::
3978 - check if a given changeset is included is a tagged release::
3967
3979
3968 hg log -r "a21ccf and ancestor(1.9)"
3980 hg log -r "a21ccf and ancestor(1.9)"
3969
3981
3970 - find all changesets by some user in a date range::
3982 - find all changesets by some user in a date range::
3971
3983
3972 hg log -k alice -d "may 2008 to jul 2008"
3984 hg log -k alice -d "may 2008 to jul 2008"
3973
3985
3974 - summary of all changesets after the last tag::
3986 - summary of all changesets after the last tag::
3975
3987
3976 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3988 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3977
3989
3978 See :hg:`help dates` for a list of formats valid for -d/--date.
3990 See :hg:`help dates` for a list of formats valid for -d/--date.
3979
3991
3980 See :hg:`help revisions` and :hg:`help revsets` for more about
3992 See :hg:`help revisions` and :hg:`help revsets` for more about
3981 specifying revisions.
3993 specifying revisions.
3982
3994
3983 See :hg:`help templates` for more about pre-packaged styles and
3995 See :hg:`help templates` for more about pre-packaged styles and
3984 specifying custom templates.
3996 specifying custom templates.
3985
3997
3986 Returns 0 on success.
3998 Returns 0 on success.
3987 """
3999 """
3988 if opts.get('graph'):
4000 if opts.get('graph'):
3989 return cmdutil.graphlog(ui, repo, *pats, **opts)
4001 return cmdutil.graphlog(ui, repo, *pats, **opts)
3990
4002
3991 matchfn = scmutil.match(repo[None], pats, opts)
4003 matchfn = scmutil.match(repo[None], pats, opts)
3992 limit = cmdutil.loglimit(opts)
4004 limit = cmdutil.loglimit(opts)
3993 count = 0
4005 count = 0
3994
4006
3995 getrenamed, endrev = None, None
4007 getrenamed, endrev = None, None
3996 if opts.get('copies'):
4008 if opts.get('copies'):
3997 if opts.get('rev'):
4009 if opts.get('rev'):
3998 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4010 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3999 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4011 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4000
4012
4001 df = False
4013 df = False
4002 if opts.get("date"):
4014 if opts.get("date"):
4003 df = util.matchdate(opts["date"])
4015 df = util.matchdate(opts["date"])
4004
4016
4005 branches = opts.get('branch', []) + opts.get('only_branch', [])
4017 branches = opts.get('branch', []) + opts.get('only_branch', [])
4006 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4018 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4007
4019
4008 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4020 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4009 def prep(ctx, fns):
4021 def prep(ctx, fns):
4010 rev = ctx.rev()
4022 rev = ctx.rev()
4011 parents = [p for p in repo.changelog.parentrevs(rev)
4023 parents = [p for p in repo.changelog.parentrevs(rev)
4012 if p != nullrev]
4024 if p != nullrev]
4013 if opts.get('no_merges') and len(parents) == 2:
4025 if opts.get('no_merges') and len(parents) == 2:
4014 return
4026 return
4015 if opts.get('only_merges') and len(parents) != 2:
4027 if opts.get('only_merges') and len(parents) != 2:
4016 return
4028 return
4017 if opts.get('branch') and ctx.branch() not in opts['branch']:
4029 if opts.get('branch') and ctx.branch() not in opts['branch']:
4018 return
4030 return
4019 if df and not df(ctx.date()[0]):
4031 if df and not df(ctx.date()[0]):
4020 return
4032 return
4021
4033
4022 lower = encoding.lower
4034 lower = encoding.lower
4023 if opts.get('user'):
4035 if opts.get('user'):
4024 luser = lower(ctx.user())
4036 luser = lower(ctx.user())
4025 for k in [lower(x) for x in opts['user']]:
4037 for k in [lower(x) for x in opts['user']]:
4026 if (k in luser):
4038 if (k in luser):
4027 break
4039 break
4028 else:
4040 else:
4029 return
4041 return
4030 if opts.get('keyword'):
4042 if opts.get('keyword'):
4031 luser = lower(ctx.user())
4043 luser = lower(ctx.user())
4032 ldesc = lower(ctx.description())
4044 ldesc = lower(ctx.description())
4033 lfiles = lower(" ".join(ctx.files()))
4045 lfiles = lower(" ".join(ctx.files()))
4034 for k in [lower(x) for x in opts['keyword']]:
4046 for k in [lower(x) for x in opts['keyword']]:
4035 if (k in luser or k in ldesc or k in lfiles):
4047 if (k in luser or k in ldesc or k in lfiles):
4036 break
4048 break
4037 else:
4049 else:
4038 return
4050 return
4039
4051
4040 copies = None
4052 copies = None
4041 if getrenamed is not None and rev:
4053 if getrenamed is not None and rev:
4042 copies = []
4054 copies = []
4043 for fn in ctx.files():
4055 for fn in ctx.files():
4044 rename = getrenamed(fn, rev)
4056 rename = getrenamed(fn, rev)
4045 if rename:
4057 if rename:
4046 copies.append((fn, rename[0]))
4058 copies.append((fn, rename[0]))
4047
4059
4048 revmatchfn = None
4060 revmatchfn = None
4049 if opts.get('patch') or opts.get('stat'):
4061 if opts.get('patch') or opts.get('stat'):
4050 if opts.get('follow') or opts.get('follow_first'):
4062 if opts.get('follow') or opts.get('follow_first'):
4051 # note: this might be wrong when following through merges
4063 # note: this might be wrong when following through merges
4052 revmatchfn = scmutil.match(repo[None], fns, default='path')
4064 revmatchfn = scmutil.match(repo[None], fns, default='path')
4053 else:
4065 else:
4054 revmatchfn = matchfn
4066 revmatchfn = matchfn
4055
4067
4056 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4068 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4057
4069
4058 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4070 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4059 if displayer.flush(ctx.rev()):
4071 if displayer.flush(ctx.rev()):
4060 count += 1
4072 count += 1
4061 if count == limit:
4073 if count == limit:
4062 break
4074 break
4063 displayer.close()
4075 displayer.close()
4064
4076
4065 @command('manifest',
4077 @command('manifest',
4066 [('r', 'rev', '', _('revision to display'), _('REV')),
4078 [('r', 'rev', '', _('revision to display'), _('REV')),
4067 ('', 'all', False, _("list files from all revisions"))],
4079 ('', 'all', False, _("list files from all revisions"))],
4068 _('[-r REV]'))
4080 _('[-r REV]'))
4069 def manifest(ui, repo, node=None, rev=None, **opts):
4081 def manifest(ui, repo, node=None, rev=None, **opts):
4070 """output the current or given revision of the project manifest
4082 """output the current or given revision of the project manifest
4071
4083
4072 Print a list of version controlled files for the given revision.
4084 Print a list of version controlled files for the given revision.
4073 If no revision is given, the first parent of the working directory
4085 If no revision is given, the first parent of the working directory
4074 is used, or the null revision if no revision is checked out.
4086 is used, or the null revision if no revision is checked out.
4075
4087
4076 With -v, print file permissions, symlink and executable bits.
4088 With -v, print file permissions, symlink and executable bits.
4077 With --debug, print file revision hashes.
4089 With --debug, print file revision hashes.
4078
4090
4079 If option --all is specified, the list of all files from all revisions
4091 If option --all is specified, the list of all files from all revisions
4080 is printed. This includes deleted and renamed files.
4092 is printed. This includes deleted and renamed files.
4081
4093
4082 Returns 0 on success.
4094 Returns 0 on success.
4083 """
4095 """
4084
4096
4085 fm = ui.formatter('manifest', opts)
4097 fm = ui.formatter('manifest', opts)
4086
4098
4087 if opts.get('all'):
4099 if opts.get('all'):
4088 if rev or node:
4100 if rev or node:
4089 raise util.Abort(_("can't specify a revision with --all"))
4101 raise util.Abort(_("can't specify a revision with --all"))
4090
4102
4091 res = []
4103 res = []
4092 prefix = "data/"
4104 prefix = "data/"
4093 suffix = ".i"
4105 suffix = ".i"
4094 plen = len(prefix)
4106 plen = len(prefix)
4095 slen = len(suffix)
4107 slen = len(suffix)
4096 lock = repo.lock()
4108 lock = repo.lock()
4097 try:
4109 try:
4098 for fn, b, size in repo.store.datafiles():
4110 for fn, b, size in repo.store.datafiles():
4099 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4111 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4100 res.append(fn[plen:-slen])
4112 res.append(fn[plen:-slen])
4101 finally:
4113 finally:
4102 lock.release()
4114 lock.release()
4103 for f in res:
4115 for f in res:
4104 fm.startitem()
4116 fm.startitem()
4105 fm.write("path", '%s\n', f)
4117 fm.write("path", '%s\n', f)
4106 fm.end()
4118 fm.end()
4107 return
4119 return
4108
4120
4109 if rev and node:
4121 if rev and node:
4110 raise util.Abort(_("please specify just one revision"))
4122 raise util.Abort(_("please specify just one revision"))
4111
4123
4112 if not node:
4124 if not node:
4113 node = rev
4125 node = rev
4114
4126
4115 char = {'l': '@', 'x': '*', '': ''}
4127 char = {'l': '@', 'x': '*', '': ''}
4116 mode = {'l': '644', 'x': '755', '': '644'}
4128 mode = {'l': '644', 'x': '755', '': '644'}
4117 ctx = scmutil.revsingle(repo, node)
4129 ctx = scmutil.revsingle(repo, node)
4118 mf = ctx.manifest()
4130 mf = ctx.manifest()
4119 for f in ctx:
4131 for f in ctx:
4120 fm.startitem()
4132 fm.startitem()
4121 fl = ctx[f].flags()
4133 fl = ctx[f].flags()
4122 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4134 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4123 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4135 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4124 fm.write('path', '%s\n', f)
4136 fm.write('path', '%s\n', f)
4125 fm.end()
4137 fm.end()
4126
4138
4127 @command('^merge',
4139 @command('^merge',
4128 [('f', 'force', None, _('force a merge with outstanding changes')),
4140 [('f', 'force', None, _('force a merge with outstanding changes')),
4129 ('r', 'rev', '', _('revision to merge'), _('REV')),
4141 ('r', 'rev', '', _('revision to merge'), _('REV')),
4130 ('P', 'preview', None,
4142 ('P', 'preview', None,
4131 _('review revisions to merge (no merge is performed)'))
4143 _('review revisions to merge (no merge is performed)'))
4132 ] + mergetoolopts,
4144 ] + mergetoolopts,
4133 _('[-P] [-f] [[-r] REV]'))
4145 _('[-P] [-f] [[-r] REV]'))
4134 def merge(ui, repo, node=None, **opts):
4146 def merge(ui, repo, node=None, **opts):
4135 """merge working directory with another revision
4147 """merge working directory with another revision
4136
4148
4137 The current working directory is updated with all changes made in
4149 The current working directory is updated with all changes made in
4138 the requested revision since the last common predecessor revision.
4150 the requested revision since the last common predecessor revision.
4139
4151
4140 Files that changed between either parent are marked as changed for
4152 Files that changed between either parent are marked as changed for
4141 the next commit and a commit must be performed before any further
4153 the next commit and a commit must be performed before any further
4142 updates to the repository are allowed. The next commit will have
4154 updates to the repository are allowed. The next commit will have
4143 two parents.
4155 two parents.
4144
4156
4145 ``--tool`` can be used to specify the merge tool used for file
4157 ``--tool`` can be used to specify the merge tool used for file
4146 merges. It overrides the HGMERGE environment variable and your
4158 merges. It overrides the HGMERGE environment variable and your
4147 configuration files. See :hg:`help merge-tools` for options.
4159 configuration files. See :hg:`help merge-tools` for options.
4148
4160
4149 If no revision is specified, the working directory's parent is a
4161 If no revision is specified, the working directory's parent is a
4150 head revision, and the current branch contains exactly one other
4162 head revision, and the current branch contains exactly one other
4151 head, the other head is merged with by default. Otherwise, an
4163 head, the other head is merged with by default. Otherwise, an
4152 explicit revision with which to merge with must be provided.
4164 explicit revision with which to merge with must be provided.
4153
4165
4154 :hg:`resolve` must be used to resolve unresolved files.
4166 :hg:`resolve` must be used to resolve unresolved files.
4155
4167
4156 To undo an uncommitted merge, use :hg:`update --clean .` which
4168 To undo an uncommitted merge, use :hg:`update --clean .` which
4157 will check out a clean copy of the original merge parent, losing
4169 will check out a clean copy of the original merge parent, losing
4158 all changes.
4170 all changes.
4159
4171
4160 Returns 0 on success, 1 if there are unresolved files.
4172 Returns 0 on success, 1 if there are unresolved files.
4161 """
4173 """
4162
4174
4163 if opts.get('rev') and node:
4175 if opts.get('rev') and node:
4164 raise util.Abort(_("please specify just one revision"))
4176 raise util.Abort(_("please specify just one revision"))
4165 if not node:
4177 if not node:
4166 node = opts.get('rev')
4178 node = opts.get('rev')
4167
4179
4168 if node:
4180 if node:
4169 node = scmutil.revsingle(repo, node).node()
4181 node = scmutil.revsingle(repo, node).node()
4170
4182
4171 if not node and repo._bookmarkcurrent:
4183 if not node and repo._bookmarkcurrent:
4172 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4184 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4173 curhead = repo[repo._bookmarkcurrent].node()
4185 curhead = repo[repo._bookmarkcurrent].node()
4174 if len(bmheads) == 2:
4186 if len(bmheads) == 2:
4175 if curhead == bmheads[0]:
4187 if curhead == bmheads[0]:
4176 node = bmheads[1]
4188 node = bmheads[1]
4177 else:
4189 else:
4178 node = bmheads[0]
4190 node = bmheads[0]
4179 elif len(bmheads) > 2:
4191 elif len(bmheads) > 2:
4180 raise util.Abort(_("multiple matching bookmarks to merge - "
4192 raise util.Abort(_("multiple matching bookmarks to merge - "
4181 "please merge with an explicit rev or bookmark"),
4193 "please merge with an explicit rev or bookmark"),
4182 hint=_("run 'hg heads' to see all heads"))
4194 hint=_("run 'hg heads' to see all heads"))
4183 elif len(bmheads) <= 1:
4195 elif len(bmheads) <= 1:
4184 raise util.Abort(_("no matching bookmark to merge - "
4196 raise util.Abort(_("no matching bookmark to merge - "
4185 "please merge with an explicit rev or bookmark"),
4197 "please merge with an explicit rev or bookmark"),
4186 hint=_("run 'hg heads' to see all heads"))
4198 hint=_("run 'hg heads' to see all heads"))
4187
4199
4188 if not node and not repo._bookmarkcurrent:
4200 if not node and not repo._bookmarkcurrent:
4189 branch = repo[None].branch()
4201 branch = repo[None].branch()
4190 bheads = repo.branchheads(branch)
4202 bheads = repo.branchheads(branch)
4191 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4203 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4192
4204
4193 if len(nbhs) > 2:
4205 if len(nbhs) > 2:
4194 raise util.Abort(_("branch '%s' has %d heads - "
4206 raise util.Abort(_("branch '%s' has %d heads - "
4195 "please merge with an explicit rev")
4207 "please merge with an explicit rev")
4196 % (branch, len(bheads)),
4208 % (branch, len(bheads)),
4197 hint=_("run 'hg heads .' to see heads"))
4209 hint=_("run 'hg heads .' to see heads"))
4198
4210
4199 parent = repo.dirstate.p1()
4211 parent = repo.dirstate.p1()
4200 if len(nbhs) <= 1:
4212 if len(nbhs) <= 1:
4201 if len(bheads) > 1:
4213 if len(bheads) > 1:
4202 raise util.Abort(_("heads are bookmarked - "
4214 raise util.Abort(_("heads are bookmarked - "
4203 "please merge with an explicit rev"),
4215 "please merge with an explicit rev"),
4204 hint=_("run 'hg heads' to see all heads"))
4216 hint=_("run 'hg heads' to see all heads"))
4205 if len(repo.heads()) > 1:
4217 if len(repo.heads()) > 1:
4206 raise util.Abort(_("branch '%s' has one head - "
4218 raise util.Abort(_("branch '%s' has one head - "
4207 "please merge with an explicit rev")
4219 "please merge with an explicit rev")
4208 % branch,
4220 % branch,
4209 hint=_("run 'hg heads' to see all heads"))
4221 hint=_("run 'hg heads' to see all heads"))
4210 msg, hint = _('nothing to merge'), None
4222 msg, hint = _('nothing to merge'), None
4211 if parent != repo.lookup(branch):
4223 if parent != repo.lookup(branch):
4212 hint = _("use 'hg update' instead")
4224 hint = _("use 'hg update' instead")
4213 raise util.Abort(msg, hint=hint)
4225 raise util.Abort(msg, hint=hint)
4214
4226
4215 if parent not in bheads:
4227 if parent not in bheads:
4216 raise util.Abort(_('working directory not at a head revision'),
4228 raise util.Abort(_('working directory not at a head revision'),
4217 hint=_("use 'hg update' or merge with an "
4229 hint=_("use 'hg update' or merge with an "
4218 "explicit revision"))
4230 "explicit revision"))
4219 if parent == nbhs[0]:
4231 if parent == nbhs[0]:
4220 node = nbhs[-1]
4232 node = nbhs[-1]
4221 else:
4233 else:
4222 node = nbhs[0]
4234 node = nbhs[0]
4223
4235
4224 if opts.get('preview'):
4236 if opts.get('preview'):
4225 # find nodes that are ancestors of p2 but not of p1
4237 # find nodes that are ancestors of p2 but not of p1
4226 p1 = repo.lookup('.')
4238 p1 = repo.lookup('.')
4227 p2 = repo.lookup(node)
4239 p2 = repo.lookup(node)
4228 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4240 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4229
4241
4230 displayer = cmdutil.show_changeset(ui, repo, opts)
4242 displayer = cmdutil.show_changeset(ui, repo, opts)
4231 for node in nodes:
4243 for node in nodes:
4232 displayer.show(repo[node])
4244 displayer.show(repo[node])
4233 displayer.close()
4245 displayer.close()
4234 return 0
4246 return 0
4235
4247
4236 try:
4248 try:
4237 # ui.forcemerge is an internal variable, do not document
4249 # ui.forcemerge is an internal variable, do not document
4238 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4250 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4239 return hg.merge(repo, node, force=opts.get('force'))
4251 return hg.merge(repo, node, force=opts.get('force'))
4240 finally:
4252 finally:
4241 ui.setconfig('ui', 'forcemerge', '')
4253 ui.setconfig('ui', 'forcemerge', '')
4242
4254
4243 @command('outgoing|out',
4255 @command('outgoing|out',
4244 [('f', 'force', None, _('run even when the destination is unrelated')),
4256 [('f', 'force', None, _('run even when the destination is unrelated')),
4245 ('r', 'rev', [],
4257 ('r', 'rev', [],
4246 _('a changeset intended to be included in the destination'), _('REV')),
4258 _('a changeset intended to be included in the destination'), _('REV')),
4247 ('n', 'newest-first', None, _('show newest record first')),
4259 ('n', 'newest-first', None, _('show newest record first')),
4248 ('B', 'bookmarks', False, _('compare bookmarks')),
4260 ('B', 'bookmarks', False, _('compare bookmarks')),
4249 ('b', 'branch', [], _('a specific branch you would like to push'),
4261 ('b', 'branch', [], _('a specific branch you would like to push'),
4250 _('BRANCH')),
4262 _('BRANCH')),
4251 ] + logopts + remoteopts + subrepoopts,
4263 ] + logopts + remoteopts + subrepoopts,
4252 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4264 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4253 def outgoing(ui, repo, dest=None, **opts):
4265 def outgoing(ui, repo, dest=None, **opts):
4254 """show changesets not found in the destination
4266 """show changesets not found in the destination
4255
4267
4256 Show changesets not found in the specified destination repository
4268 Show changesets not found in the specified destination repository
4257 or the default push location. These are the changesets that would
4269 or the default push location. These are the changesets that would
4258 be pushed if a push was requested.
4270 be pushed if a push was requested.
4259
4271
4260 See pull for details of valid destination formats.
4272 See pull for details of valid destination formats.
4261
4273
4262 Returns 0 if there are outgoing changes, 1 otherwise.
4274 Returns 0 if there are outgoing changes, 1 otherwise.
4263 """
4275 """
4264 if opts.get('graph'):
4276 if opts.get('graph'):
4265 cmdutil.checkunsupportedgraphflags([], opts)
4277 cmdutil.checkunsupportedgraphflags([], opts)
4266 o = hg._outgoing(ui, repo, dest, opts)
4278 o = hg._outgoing(ui, repo, dest, opts)
4267 if o is None:
4279 if o is None:
4268 return
4280 return
4269
4281
4270 revdag = cmdutil.graphrevs(repo, o, opts)
4282 revdag = cmdutil.graphrevs(repo, o, opts)
4271 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4283 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4272 showparents = [ctx.node() for ctx in repo[None].parents()]
4284 showparents = [ctx.node() for ctx in repo[None].parents()]
4273 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4285 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4274 graphmod.asciiedges)
4286 graphmod.asciiedges)
4275 return 0
4287 return 0
4276
4288
4277 if opts.get('bookmarks'):
4289 if opts.get('bookmarks'):
4278 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4290 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4279 dest, branches = hg.parseurl(dest, opts.get('branch'))
4291 dest, branches = hg.parseurl(dest, opts.get('branch'))
4280 other = hg.peer(repo, opts, dest)
4292 other = hg.peer(repo, opts, dest)
4281 if 'bookmarks' not in other.listkeys('namespaces'):
4293 if 'bookmarks' not in other.listkeys('namespaces'):
4282 ui.warn(_("remote doesn't support bookmarks\n"))
4294 ui.warn(_("remote doesn't support bookmarks\n"))
4283 return 0
4295 return 0
4284 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4296 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4285 return bookmarks.diff(ui, other, repo)
4297 return bookmarks.diff(ui, other, repo)
4286
4298
4287 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4299 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4288 try:
4300 try:
4289 return hg.outgoing(ui, repo, dest, opts)
4301 return hg.outgoing(ui, repo, dest, opts)
4290 finally:
4302 finally:
4291 del repo._subtoppath
4303 del repo._subtoppath
4292
4304
4293 @command('parents',
4305 @command('parents',
4294 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4306 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4295 ] + templateopts,
4307 ] + templateopts,
4296 _('[-r REV] [FILE]'))
4308 _('[-r REV] [FILE]'))
4297 def parents(ui, repo, file_=None, **opts):
4309 def parents(ui, repo, file_=None, **opts):
4298 """show the parents of the working directory or revision
4310 """show the parents of the working directory or revision
4299
4311
4300 Print the working directory's parent revisions. If a revision is
4312 Print the working directory's parent revisions. If a revision is
4301 given via -r/--rev, the parent of that revision will be printed.
4313 given via -r/--rev, the parent of that revision will be printed.
4302 If a file argument is given, the revision in which the file was
4314 If a file argument is given, the revision in which the file was
4303 last changed (before the working directory revision or the
4315 last changed (before the working directory revision or the
4304 argument to --rev if given) is printed.
4316 argument to --rev if given) is printed.
4305
4317
4306 Returns 0 on success.
4318 Returns 0 on success.
4307 """
4319 """
4308
4320
4309 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4321 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4310
4322
4311 if file_:
4323 if file_:
4312 m = scmutil.match(ctx, (file_,), opts)
4324 m = scmutil.match(ctx, (file_,), opts)
4313 if m.anypats() or len(m.files()) != 1:
4325 if m.anypats() or len(m.files()) != 1:
4314 raise util.Abort(_('can only specify an explicit filename'))
4326 raise util.Abort(_('can only specify an explicit filename'))
4315 file_ = m.files()[0]
4327 file_ = m.files()[0]
4316 filenodes = []
4328 filenodes = []
4317 for cp in ctx.parents():
4329 for cp in ctx.parents():
4318 if not cp:
4330 if not cp:
4319 continue
4331 continue
4320 try:
4332 try:
4321 filenodes.append(cp.filenode(file_))
4333 filenodes.append(cp.filenode(file_))
4322 except error.LookupError:
4334 except error.LookupError:
4323 pass
4335 pass
4324 if not filenodes:
4336 if not filenodes:
4325 raise util.Abort(_("'%s' not found in manifest!") % file_)
4337 raise util.Abort(_("'%s' not found in manifest!") % file_)
4326 fl = repo.file(file_)
4338 fl = repo.file(file_)
4327 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4339 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4328 else:
4340 else:
4329 p = [cp.node() for cp in ctx.parents()]
4341 p = [cp.node() for cp in ctx.parents()]
4330
4342
4331 displayer = cmdutil.show_changeset(ui, repo, opts)
4343 displayer = cmdutil.show_changeset(ui, repo, opts)
4332 for n in p:
4344 for n in p:
4333 if n != nullid:
4345 if n != nullid:
4334 displayer.show(repo[n])
4346 displayer.show(repo[n])
4335 displayer.close()
4347 displayer.close()
4336
4348
4337 @command('paths', [], _('[NAME]'))
4349 @command('paths', [], _('[NAME]'))
4338 def paths(ui, repo, search=None):
4350 def paths(ui, repo, search=None):
4339 """show aliases for remote repositories
4351 """show aliases for remote repositories
4340
4352
4341 Show definition of symbolic path name NAME. If no name is given,
4353 Show definition of symbolic path name NAME. If no name is given,
4342 show definition of all available names.
4354 show definition of all available names.
4343
4355
4344 Option -q/--quiet suppresses all output when searching for NAME
4356 Option -q/--quiet suppresses all output when searching for NAME
4345 and shows only the path names when listing all definitions.
4357 and shows only the path names when listing all definitions.
4346
4358
4347 Path names are defined in the [paths] section of your
4359 Path names are defined in the [paths] section of your
4348 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4360 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4349 repository, ``.hg/hgrc`` is used, too.
4361 repository, ``.hg/hgrc`` is used, too.
4350
4362
4351 The path names ``default`` and ``default-push`` have a special
4363 The path names ``default`` and ``default-push`` have a special
4352 meaning. When performing a push or pull operation, they are used
4364 meaning. When performing a push or pull operation, they are used
4353 as fallbacks if no location is specified on the command-line.
4365 as fallbacks if no location is specified on the command-line.
4354 When ``default-push`` is set, it will be used for push and
4366 When ``default-push`` is set, it will be used for push and
4355 ``default`` will be used for pull; otherwise ``default`` is used
4367 ``default`` will be used for pull; otherwise ``default`` is used
4356 as the fallback for both. When cloning a repository, the clone
4368 as the fallback for both. When cloning a repository, the clone
4357 source is written as ``default`` in ``.hg/hgrc``. Note that
4369 source is written as ``default`` in ``.hg/hgrc``. Note that
4358 ``default`` and ``default-push`` apply to all inbound (e.g.
4370 ``default`` and ``default-push`` apply to all inbound (e.g.
4359 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4371 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4360 :hg:`bundle`) operations.
4372 :hg:`bundle`) operations.
4361
4373
4362 See :hg:`help urls` for more information.
4374 See :hg:`help urls` for more information.
4363
4375
4364 Returns 0 on success.
4376 Returns 0 on success.
4365 """
4377 """
4366 if search:
4378 if search:
4367 for name, path in ui.configitems("paths"):
4379 for name, path in ui.configitems("paths"):
4368 if name == search:
4380 if name == search:
4369 ui.status("%s\n" % util.hidepassword(path))
4381 ui.status("%s\n" % util.hidepassword(path))
4370 return
4382 return
4371 if not ui.quiet:
4383 if not ui.quiet:
4372 ui.warn(_("not found!\n"))
4384 ui.warn(_("not found!\n"))
4373 return 1
4385 return 1
4374 else:
4386 else:
4375 for name, path in ui.configitems("paths"):
4387 for name, path in ui.configitems("paths"):
4376 if ui.quiet:
4388 if ui.quiet:
4377 ui.write("%s\n" % name)
4389 ui.write("%s\n" % name)
4378 else:
4390 else:
4379 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4391 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4380
4392
4381 @command('phase',
4393 @command('phase',
4382 [('p', 'public', False, _('set changeset phase to public')),
4394 [('p', 'public', False, _('set changeset phase to public')),
4383 ('d', 'draft', False, _('set changeset phase to draft')),
4395 ('d', 'draft', False, _('set changeset phase to draft')),
4384 ('s', 'secret', False, _('set changeset phase to secret')),
4396 ('s', 'secret', False, _('set changeset phase to secret')),
4385 ('f', 'force', False, _('allow to move boundary backward')),
4397 ('f', 'force', False, _('allow to move boundary backward')),
4386 ('r', 'rev', [], _('target revision'), _('REV')),
4398 ('r', 'rev', [], _('target revision'), _('REV')),
4387 ],
4399 ],
4388 _('[-p|-d|-s] [-f] [-r] REV...'))
4400 _('[-p|-d|-s] [-f] [-r] REV...'))
4389 def phase(ui, repo, *revs, **opts):
4401 def phase(ui, repo, *revs, **opts):
4390 """set or show the current phase name
4402 """set or show the current phase name
4391
4403
4392 With no argument, show the phase name of specified revisions.
4404 With no argument, show the phase name of specified revisions.
4393
4405
4394 With one of -p/--public, -d/--draft or -s/--secret, change the
4406 With one of -p/--public, -d/--draft or -s/--secret, change the
4395 phase value of the specified revisions.
4407 phase value of the specified revisions.
4396
4408
4397 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4409 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4398 lower phase to an higher phase. Phases are ordered as follows::
4410 lower phase to an higher phase. Phases are ordered as follows::
4399
4411
4400 public < draft < secret
4412 public < draft < secret
4401
4413
4402 Return 0 on success, 1 if no phases were changed or some could not
4414 Return 0 on success, 1 if no phases were changed or some could not
4403 be changed.
4415 be changed.
4404 """
4416 """
4405 # search for a unique phase argument
4417 # search for a unique phase argument
4406 targetphase = None
4418 targetphase = None
4407 for idx, name in enumerate(phases.phasenames):
4419 for idx, name in enumerate(phases.phasenames):
4408 if opts[name]:
4420 if opts[name]:
4409 if targetphase is not None:
4421 if targetphase is not None:
4410 raise util.Abort(_('only one phase can be specified'))
4422 raise util.Abort(_('only one phase can be specified'))
4411 targetphase = idx
4423 targetphase = idx
4412
4424
4413 # look for specified revision
4425 # look for specified revision
4414 revs = list(revs)
4426 revs = list(revs)
4415 revs.extend(opts['rev'])
4427 revs.extend(opts['rev'])
4416 if not revs:
4428 if not revs:
4417 raise util.Abort(_('no revisions specified'))
4429 raise util.Abort(_('no revisions specified'))
4418
4430
4419 revs = scmutil.revrange(repo, revs)
4431 revs = scmutil.revrange(repo, revs)
4420
4432
4421 lock = None
4433 lock = None
4422 ret = 0
4434 ret = 0
4423 if targetphase is None:
4435 if targetphase is None:
4424 # display
4436 # display
4425 for r in revs:
4437 for r in revs:
4426 ctx = repo[r]
4438 ctx = repo[r]
4427 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4439 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4428 else:
4440 else:
4429 lock = repo.lock()
4441 lock = repo.lock()
4430 try:
4442 try:
4431 # set phase
4443 # set phase
4432 if not revs:
4444 if not revs:
4433 raise util.Abort(_('empty revision set'))
4445 raise util.Abort(_('empty revision set'))
4434 nodes = [repo[r].node() for r in revs]
4446 nodes = [repo[r].node() for r in revs]
4435 olddata = repo._phasecache.getphaserevs(repo)[:]
4447 olddata = repo._phasecache.getphaserevs(repo)[:]
4436 phases.advanceboundary(repo, targetphase, nodes)
4448 phases.advanceboundary(repo, targetphase, nodes)
4437 if opts['force']:
4449 if opts['force']:
4438 phases.retractboundary(repo, targetphase, nodes)
4450 phases.retractboundary(repo, targetphase, nodes)
4439 finally:
4451 finally:
4440 lock.release()
4452 lock.release()
4441 # moving revision from public to draft may hide them
4453 # moving revision from public to draft may hide them
4442 # We have to check result on an unfiltered repository
4454 # We have to check result on an unfiltered repository
4443 unfi = repo.unfiltered()
4455 unfi = repo.unfiltered()
4444 newdata = repo._phasecache.getphaserevs(unfi)
4456 newdata = repo._phasecache.getphaserevs(unfi)
4445 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4457 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4446 cl = unfi.changelog
4458 cl = unfi.changelog
4447 rejected = [n for n in nodes
4459 rejected = [n for n in nodes
4448 if newdata[cl.rev(n)] < targetphase]
4460 if newdata[cl.rev(n)] < targetphase]
4449 if rejected:
4461 if rejected:
4450 ui.warn(_('cannot move %i changesets to a more permissive '
4462 ui.warn(_('cannot move %i changesets to a more permissive '
4451 'phase, use --force\n') % len(rejected))
4463 'phase, use --force\n') % len(rejected))
4452 ret = 1
4464 ret = 1
4453 if changes:
4465 if changes:
4454 msg = _('phase changed for %i changesets\n') % changes
4466 msg = _('phase changed for %i changesets\n') % changes
4455 if ret:
4467 if ret:
4456 ui.status(msg)
4468 ui.status(msg)
4457 else:
4469 else:
4458 ui.note(msg)
4470 ui.note(msg)
4459 else:
4471 else:
4460 ui.warn(_('no phases changed\n'))
4472 ui.warn(_('no phases changed\n'))
4461 ret = 1
4473 ret = 1
4462 return ret
4474 return ret
4463
4475
4464 def postincoming(ui, repo, modheads, optupdate, checkout):
4476 def postincoming(ui, repo, modheads, optupdate, checkout):
4465 if modheads == 0:
4477 if modheads == 0:
4466 return
4478 return
4467 if optupdate:
4479 if optupdate:
4468 movemarkfrom = repo['.'].node()
4480 movemarkfrom = repo['.'].node()
4469 try:
4481 try:
4470 ret = hg.update(repo, checkout)
4482 ret = hg.update(repo, checkout)
4471 except util.Abort, inst:
4483 except util.Abort, inst:
4472 ui.warn(_("not updating: %s\n") % str(inst))
4484 ui.warn(_("not updating: %s\n") % str(inst))
4473 return 0
4485 return 0
4474 if not ret and not checkout:
4486 if not ret and not checkout:
4475 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4487 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4476 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4488 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4477 return ret
4489 return ret
4478 if modheads > 1:
4490 if modheads > 1:
4479 currentbranchheads = len(repo.branchheads())
4491 currentbranchheads = len(repo.branchheads())
4480 if currentbranchheads == modheads:
4492 if currentbranchheads == modheads:
4481 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4493 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4482 elif currentbranchheads > 1:
4494 elif currentbranchheads > 1:
4483 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4495 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4484 "merge)\n"))
4496 "merge)\n"))
4485 else:
4497 else:
4486 ui.status(_("(run 'hg heads' to see heads)\n"))
4498 ui.status(_("(run 'hg heads' to see heads)\n"))
4487 else:
4499 else:
4488 ui.status(_("(run 'hg update' to get a working copy)\n"))
4500 ui.status(_("(run 'hg update' to get a working copy)\n"))
4489
4501
4490 @command('^pull',
4502 @command('^pull',
4491 [('u', 'update', None,
4503 [('u', 'update', None,
4492 _('update to new branch head if changesets were pulled')),
4504 _('update to new branch head if changesets were pulled')),
4493 ('f', 'force', None, _('run even when remote repository is unrelated')),
4505 ('f', 'force', None, _('run even when remote repository is unrelated')),
4494 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4506 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4495 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4507 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4496 ('b', 'branch', [], _('a specific branch you would like to pull'),
4508 ('b', 'branch', [], _('a specific branch you would like to pull'),
4497 _('BRANCH')),
4509 _('BRANCH')),
4498 ] + remoteopts,
4510 ] + remoteopts,
4499 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4511 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4500 def pull(ui, repo, source="default", **opts):
4512 def pull(ui, repo, source="default", **opts):
4501 """pull changes from the specified source
4513 """pull changes from the specified source
4502
4514
4503 Pull changes from a remote repository to a local one.
4515 Pull changes from a remote repository to a local one.
4504
4516
4505 This finds all changes from the repository at the specified path
4517 This finds all changes from the repository at the specified path
4506 or URL and adds them to a local repository (the current one unless
4518 or URL and adds them to a local repository (the current one unless
4507 -R is specified). By default, this does not update the copy of the
4519 -R is specified). By default, this does not update the copy of the
4508 project in the working directory.
4520 project in the working directory.
4509
4521
4510 Use :hg:`incoming` if you want to see what would have been added
4522 Use :hg:`incoming` if you want to see what would have been added
4511 by a pull at the time you issued this command. If you then decide
4523 by a pull at the time you issued this command. If you then decide
4512 to add those changes to the repository, you should use :hg:`pull
4524 to add those changes to the repository, you should use :hg:`pull
4513 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4525 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4514
4526
4515 If SOURCE is omitted, the 'default' path will be used.
4527 If SOURCE is omitted, the 'default' path will be used.
4516 See :hg:`help urls` for more information.
4528 See :hg:`help urls` for more information.
4517
4529
4518 Returns 0 on success, 1 if an update had unresolved files.
4530 Returns 0 on success, 1 if an update had unresolved files.
4519 """
4531 """
4520 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4532 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4521 other = hg.peer(repo, opts, source)
4533 other = hg.peer(repo, opts, source)
4522 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4534 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4523 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4535 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4524
4536
4525 remotebookmarks = other.listkeys('bookmarks')
4537 remotebookmarks = other.listkeys('bookmarks')
4526
4538
4527 if opts.get('bookmark'):
4539 if opts.get('bookmark'):
4528 if not revs:
4540 if not revs:
4529 revs = []
4541 revs = []
4530 for b in opts['bookmark']:
4542 for b in opts['bookmark']:
4531 if b not in remotebookmarks:
4543 if b not in remotebookmarks:
4532 raise util.Abort(_('remote bookmark %s not found!') % b)
4544 raise util.Abort(_('remote bookmark %s not found!') % b)
4533 revs.append(remotebookmarks[b])
4545 revs.append(remotebookmarks[b])
4534
4546
4535 if revs:
4547 if revs:
4536 try:
4548 try:
4537 revs = [other.lookup(rev) for rev in revs]
4549 revs = [other.lookup(rev) for rev in revs]
4538 except error.CapabilityError:
4550 except error.CapabilityError:
4539 err = _("other repository doesn't support revision lookup, "
4551 err = _("other repository doesn't support revision lookup, "
4540 "so a rev cannot be specified.")
4552 "so a rev cannot be specified.")
4541 raise util.Abort(err)
4553 raise util.Abort(err)
4542
4554
4543 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4555 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4544 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4556 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4545 if checkout:
4557 if checkout:
4546 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4558 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4547 repo._subtoppath = source
4559 repo._subtoppath = source
4548 try:
4560 try:
4549 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4561 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4550
4562
4551 finally:
4563 finally:
4552 del repo._subtoppath
4564 del repo._subtoppath
4553
4565
4554 # update specified bookmarks
4566 # update specified bookmarks
4555 if opts.get('bookmark'):
4567 if opts.get('bookmark'):
4556 marks = repo._bookmarks
4568 marks = repo._bookmarks
4557 for b in opts['bookmark']:
4569 for b in opts['bookmark']:
4558 # explicit pull overrides local bookmark if any
4570 # explicit pull overrides local bookmark if any
4559 ui.status(_("importing bookmark %s\n") % b)
4571 ui.status(_("importing bookmark %s\n") % b)
4560 marks[b] = repo[remotebookmarks[b]].node()
4572 marks[b] = repo[remotebookmarks[b]].node()
4561 marks.write()
4573 marks.write()
4562
4574
4563 return ret
4575 return ret
4564
4576
4565 @command('^push',
4577 @command('^push',
4566 [('f', 'force', None, _('force push')),
4578 [('f', 'force', None, _('force push')),
4567 ('r', 'rev', [],
4579 ('r', 'rev', [],
4568 _('a changeset intended to be included in the destination'),
4580 _('a changeset intended to be included in the destination'),
4569 _('REV')),
4581 _('REV')),
4570 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4582 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4571 ('b', 'branch', [],
4583 ('b', 'branch', [],
4572 _('a specific branch you would like to push'), _('BRANCH')),
4584 _('a specific branch you would like to push'), _('BRANCH')),
4573 ('', 'new-branch', False, _('allow pushing a new branch')),
4585 ('', 'new-branch', False, _('allow pushing a new branch')),
4574 ] + remoteopts,
4586 ] + remoteopts,
4575 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4587 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4576 def push(ui, repo, dest=None, **opts):
4588 def push(ui, repo, dest=None, **opts):
4577 """push changes to the specified destination
4589 """push changes to the specified destination
4578
4590
4579 Push changesets from the local repository to the specified
4591 Push changesets from the local repository to the specified
4580 destination.
4592 destination.
4581
4593
4582 This operation is symmetrical to pull: it is identical to a pull
4594 This operation is symmetrical to pull: it is identical to a pull
4583 in the destination repository from the current one.
4595 in the destination repository from the current one.
4584
4596
4585 By default, push will not allow creation of new heads at the
4597 By default, push will not allow creation of new heads at the
4586 destination, since multiple heads would make it unclear which head
4598 destination, since multiple heads would make it unclear which head
4587 to use. In this situation, it is recommended to pull and merge
4599 to use. In this situation, it is recommended to pull and merge
4588 before pushing.
4600 before pushing.
4589
4601
4590 Use --new-branch if you want to allow push to create a new named
4602 Use --new-branch if you want to allow push to create a new named
4591 branch that is not present at the destination. This allows you to
4603 branch that is not present at the destination. This allows you to
4592 only create a new branch without forcing other changes.
4604 only create a new branch without forcing other changes.
4593
4605
4594 Use -f/--force to override the default behavior and push all
4606 Use -f/--force to override the default behavior and push all
4595 changesets on all branches.
4607 changesets on all branches.
4596
4608
4597 If -r/--rev is used, the specified revision and all its ancestors
4609 If -r/--rev is used, the specified revision and all its ancestors
4598 will be pushed to the remote repository.
4610 will be pushed to the remote repository.
4599
4611
4600 If -B/--bookmark is used, the specified bookmarked revision, its
4612 If -B/--bookmark is used, the specified bookmarked revision, its
4601 ancestors, and the bookmark will be pushed to the remote
4613 ancestors, and the bookmark will be pushed to the remote
4602 repository.
4614 repository.
4603
4615
4604 Please see :hg:`help urls` for important details about ``ssh://``
4616 Please see :hg:`help urls` for important details about ``ssh://``
4605 URLs. If DESTINATION is omitted, a default path will be used.
4617 URLs. If DESTINATION is omitted, a default path will be used.
4606
4618
4607 Returns 0 if push was successful, 1 if nothing to push.
4619 Returns 0 if push was successful, 1 if nothing to push.
4608 """
4620 """
4609
4621
4610 if opts.get('bookmark'):
4622 if opts.get('bookmark'):
4611 for b in opts['bookmark']:
4623 for b in opts['bookmark']:
4612 # translate -B options to -r so changesets get pushed
4624 # translate -B options to -r so changesets get pushed
4613 if b in repo._bookmarks:
4625 if b in repo._bookmarks:
4614 opts.setdefault('rev', []).append(b)
4626 opts.setdefault('rev', []).append(b)
4615 else:
4627 else:
4616 # if we try to push a deleted bookmark, translate it to null
4628 # if we try to push a deleted bookmark, translate it to null
4617 # this lets simultaneous -r, -b options continue working
4629 # this lets simultaneous -r, -b options continue working
4618 opts.setdefault('rev', []).append("null")
4630 opts.setdefault('rev', []).append("null")
4619
4631
4620 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4632 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4621 dest, branches = hg.parseurl(dest, opts.get('branch'))
4633 dest, branches = hg.parseurl(dest, opts.get('branch'))
4622 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4634 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4623 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4635 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4624 other = hg.peer(repo, opts, dest)
4636 other = hg.peer(repo, opts, dest)
4625 if revs:
4637 if revs:
4626 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4638 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4627
4639
4628 repo._subtoppath = dest
4640 repo._subtoppath = dest
4629 try:
4641 try:
4630 # push subrepos depth-first for coherent ordering
4642 # push subrepos depth-first for coherent ordering
4631 c = repo['']
4643 c = repo['']
4632 subs = c.substate # only repos that are committed
4644 subs = c.substate # only repos that are committed
4633 for s in sorted(subs):
4645 for s in sorted(subs):
4634 if c.sub(s).push(opts) == 0:
4646 if c.sub(s).push(opts) == 0:
4635 return False
4647 return False
4636 finally:
4648 finally:
4637 del repo._subtoppath
4649 del repo._subtoppath
4638 result = repo.push(other, opts.get('force'), revs=revs,
4650 result = repo.push(other, opts.get('force'), revs=revs,
4639 newbranch=opts.get('new_branch'))
4651 newbranch=opts.get('new_branch'))
4640
4652
4641 result = not result
4653 result = not result
4642
4654
4643 if opts.get('bookmark'):
4655 if opts.get('bookmark'):
4644 rb = other.listkeys('bookmarks')
4656 rb = other.listkeys('bookmarks')
4645 for b in opts['bookmark']:
4657 for b in opts['bookmark']:
4646 # explicit push overrides remote bookmark if any
4658 # explicit push overrides remote bookmark if any
4647 if b in repo._bookmarks:
4659 if b in repo._bookmarks:
4648 ui.status(_("exporting bookmark %s\n") % b)
4660 ui.status(_("exporting bookmark %s\n") % b)
4649 new = repo[b].hex()
4661 new = repo[b].hex()
4650 elif b in rb:
4662 elif b in rb:
4651 ui.status(_("deleting remote bookmark %s\n") % b)
4663 ui.status(_("deleting remote bookmark %s\n") % b)
4652 new = '' # delete
4664 new = '' # delete
4653 else:
4665 else:
4654 ui.warn(_('bookmark %s does not exist on the local '
4666 ui.warn(_('bookmark %s does not exist on the local '
4655 'or remote repository!\n') % b)
4667 'or remote repository!\n') % b)
4656 return 2
4668 return 2
4657 old = rb.get(b, '')
4669 old = rb.get(b, '')
4658 r = other.pushkey('bookmarks', b, old, new)
4670 r = other.pushkey('bookmarks', b, old, new)
4659 if not r:
4671 if not r:
4660 ui.warn(_('updating bookmark %s failed!\n') % b)
4672 ui.warn(_('updating bookmark %s failed!\n') % b)
4661 if not result:
4673 if not result:
4662 result = 2
4674 result = 2
4663
4675
4664 return result
4676 return result
4665
4677
4666 @command('recover', [])
4678 @command('recover', [])
4667 def recover(ui, repo):
4679 def recover(ui, repo):
4668 """roll back an interrupted transaction
4680 """roll back an interrupted transaction
4669
4681
4670 Recover from an interrupted commit or pull.
4682 Recover from an interrupted commit or pull.
4671
4683
4672 This command tries to fix the repository status after an
4684 This command tries to fix the repository status after an
4673 interrupted operation. It should only be necessary when Mercurial
4685 interrupted operation. It should only be necessary when Mercurial
4674 suggests it.
4686 suggests it.
4675
4687
4676 Returns 0 if successful, 1 if nothing to recover or verify fails.
4688 Returns 0 if successful, 1 if nothing to recover or verify fails.
4677 """
4689 """
4678 if repo.recover():
4690 if repo.recover():
4679 return hg.verify(repo)
4691 return hg.verify(repo)
4680 return 1
4692 return 1
4681
4693
4682 @command('^remove|rm',
4694 @command('^remove|rm',
4683 [('A', 'after', None, _('record delete for missing files')),
4695 [('A', 'after', None, _('record delete for missing files')),
4684 ('f', 'force', None,
4696 ('f', 'force', None,
4685 _('remove (and delete) file even if added or modified')),
4697 _('remove (and delete) file even if added or modified')),
4686 ] + walkopts,
4698 ] + walkopts,
4687 _('[OPTION]... FILE...'))
4699 _('[OPTION]... FILE...'))
4688 def remove(ui, repo, *pats, **opts):
4700 def remove(ui, repo, *pats, **opts):
4689 """remove the specified files on the next commit
4701 """remove the specified files on the next commit
4690
4702
4691 Schedule the indicated files for removal from the current branch.
4703 Schedule the indicated files for removal from the current branch.
4692
4704
4693 This command schedules the files to be removed at the next commit.
4705 This command schedules the files to be removed at the next commit.
4694 To undo a remove before that, see :hg:`revert`. To undo added
4706 To undo a remove before that, see :hg:`revert`. To undo added
4695 files, see :hg:`forget`.
4707 files, see :hg:`forget`.
4696
4708
4697 .. container:: verbose
4709 .. container:: verbose
4698
4710
4699 -A/--after can be used to remove only files that have already
4711 -A/--after can be used to remove only files that have already
4700 been deleted, -f/--force can be used to force deletion, and -Af
4712 been deleted, -f/--force can be used to force deletion, and -Af
4701 can be used to remove files from the next revision without
4713 can be used to remove files from the next revision without
4702 deleting them from the working directory.
4714 deleting them from the working directory.
4703
4715
4704 The following table details the behavior of remove for different
4716 The following table details the behavior of remove for different
4705 file states (columns) and option combinations (rows). The file
4717 file states (columns) and option combinations (rows). The file
4706 states are Added [A], Clean [C], Modified [M] and Missing [!]
4718 states are Added [A], Clean [C], Modified [M] and Missing [!]
4707 (as reported by :hg:`status`). The actions are Warn, Remove
4719 (as reported by :hg:`status`). The actions are Warn, Remove
4708 (from branch) and Delete (from disk):
4720 (from branch) and Delete (from disk):
4709
4721
4710 ======= == == == ==
4722 ======= == == == ==
4711 A C M !
4723 A C M !
4712 ======= == == == ==
4724 ======= == == == ==
4713 none W RD W R
4725 none W RD W R
4714 -f R RD RD R
4726 -f R RD RD R
4715 -A W W W R
4727 -A W W W R
4716 -Af R R R R
4728 -Af R R R R
4717 ======= == == == ==
4729 ======= == == == ==
4718
4730
4719 Note that remove never deletes files in Added [A] state from the
4731 Note that remove never deletes files in Added [A] state from the
4720 working directory, not even if option --force is specified.
4732 working directory, not even if option --force is specified.
4721
4733
4722 Returns 0 on success, 1 if any warnings encountered.
4734 Returns 0 on success, 1 if any warnings encountered.
4723 """
4735 """
4724
4736
4725 ret = 0
4737 ret = 0
4726 after, force = opts.get('after'), opts.get('force')
4738 after, force = opts.get('after'), opts.get('force')
4727 if not pats and not after:
4739 if not pats and not after:
4728 raise util.Abort(_('no files specified'))
4740 raise util.Abort(_('no files specified'))
4729
4741
4730 m = scmutil.match(repo[None], pats, opts)
4742 m = scmutil.match(repo[None], pats, opts)
4731 s = repo.status(match=m, clean=True)
4743 s = repo.status(match=m, clean=True)
4732 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4744 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4733
4745
4734 # warn about failure to delete explicit files/dirs
4746 # warn about failure to delete explicit files/dirs
4735 wctx = repo[None]
4747 wctx = repo[None]
4736 for f in m.files():
4748 for f in m.files():
4737 if f in repo.dirstate or f in wctx.dirs():
4749 if f in repo.dirstate or f in wctx.dirs():
4738 continue
4750 continue
4739 if os.path.exists(m.rel(f)):
4751 if os.path.exists(m.rel(f)):
4740 if os.path.isdir(m.rel(f)):
4752 if os.path.isdir(m.rel(f)):
4741 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4753 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4742 else:
4754 else:
4743 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4755 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4744 # missing files will generate a warning elsewhere
4756 # missing files will generate a warning elsewhere
4745 ret = 1
4757 ret = 1
4746
4758
4747 if force:
4759 if force:
4748 list = modified + deleted + clean + added
4760 list = modified + deleted + clean + added
4749 elif after:
4761 elif after:
4750 list = deleted
4762 list = deleted
4751 for f in modified + added + clean:
4763 for f in modified + added + clean:
4752 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4764 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4753 ret = 1
4765 ret = 1
4754 else:
4766 else:
4755 list = deleted + clean
4767 list = deleted + clean
4756 for f in modified:
4768 for f in modified:
4757 ui.warn(_('not removing %s: file is modified (use -f'
4769 ui.warn(_('not removing %s: file is modified (use -f'
4758 ' to force removal)\n') % m.rel(f))
4770 ' to force removal)\n') % m.rel(f))
4759 ret = 1
4771 ret = 1
4760 for f in added:
4772 for f in added:
4761 ui.warn(_('not removing %s: file has been marked for add'
4773 ui.warn(_('not removing %s: file has been marked for add'
4762 ' (use forget to undo)\n') % m.rel(f))
4774 ' (use forget to undo)\n') % m.rel(f))
4763 ret = 1
4775 ret = 1
4764
4776
4765 for f in sorted(list):
4777 for f in sorted(list):
4766 if ui.verbose or not m.exact(f):
4778 if ui.verbose or not m.exact(f):
4767 ui.status(_('removing %s\n') % m.rel(f))
4779 ui.status(_('removing %s\n') % m.rel(f))
4768
4780
4769 wlock = repo.wlock()
4781 wlock = repo.wlock()
4770 try:
4782 try:
4771 if not after:
4783 if not after:
4772 for f in list:
4784 for f in list:
4773 if f in added:
4785 if f in added:
4774 continue # we never unlink added files on remove
4786 continue # we never unlink added files on remove
4775 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4787 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4776 repo[None].forget(list)
4788 repo[None].forget(list)
4777 finally:
4789 finally:
4778 wlock.release()
4790 wlock.release()
4779
4791
4780 return ret
4792 return ret
4781
4793
4782 @command('rename|move|mv',
4794 @command('rename|move|mv',
4783 [('A', 'after', None, _('record a rename that has already occurred')),
4795 [('A', 'after', None, _('record a rename that has already occurred')),
4784 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4796 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4785 ] + walkopts + dryrunopts,
4797 ] + walkopts + dryrunopts,
4786 _('[OPTION]... SOURCE... DEST'))
4798 _('[OPTION]... SOURCE... DEST'))
4787 def rename(ui, repo, *pats, **opts):
4799 def rename(ui, repo, *pats, **opts):
4788 """rename files; equivalent of copy + remove
4800 """rename files; equivalent of copy + remove
4789
4801
4790 Mark dest as copies of sources; mark sources for deletion. If dest
4802 Mark dest as copies of sources; mark sources for deletion. If dest
4791 is a directory, copies are put in that directory. If dest is a
4803 is a directory, copies are put in that directory. If dest is a
4792 file, there can only be one source.
4804 file, there can only be one source.
4793
4805
4794 By default, this command copies the contents of files as they
4806 By default, this command copies the contents of files as they
4795 exist in the working directory. If invoked with -A/--after, the
4807 exist in the working directory. If invoked with -A/--after, the
4796 operation is recorded, but no copying is performed.
4808 operation is recorded, but no copying is performed.
4797
4809
4798 This command takes effect at the next commit. To undo a rename
4810 This command takes effect at the next commit. To undo a rename
4799 before that, see :hg:`revert`.
4811 before that, see :hg:`revert`.
4800
4812
4801 Returns 0 on success, 1 if errors are encountered.
4813 Returns 0 on success, 1 if errors are encountered.
4802 """
4814 """
4803 wlock = repo.wlock(False)
4815 wlock = repo.wlock(False)
4804 try:
4816 try:
4805 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4817 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4806 finally:
4818 finally:
4807 wlock.release()
4819 wlock.release()
4808
4820
4809 @command('resolve',
4821 @command('resolve',
4810 [('a', 'all', None, _('select all unresolved files')),
4822 [('a', 'all', None, _('select all unresolved files')),
4811 ('l', 'list', None, _('list state of files needing merge')),
4823 ('l', 'list', None, _('list state of files needing merge')),
4812 ('m', 'mark', None, _('mark files as resolved')),
4824 ('m', 'mark', None, _('mark files as resolved')),
4813 ('u', 'unmark', None, _('mark files as unresolved')),
4825 ('u', 'unmark', None, _('mark files as unresolved')),
4814 ('n', 'no-status', None, _('hide status prefix'))]
4826 ('n', 'no-status', None, _('hide status prefix'))]
4815 + mergetoolopts + walkopts,
4827 + mergetoolopts + walkopts,
4816 _('[OPTION]... [FILE]...'))
4828 _('[OPTION]... [FILE]...'))
4817 def resolve(ui, repo, *pats, **opts):
4829 def resolve(ui, repo, *pats, **opts):
4818 """redo merges or set/view the merge status of files
4830 """redo merges or set/view the merge status of files
4819
4831
4820 Merges with unresolved conflicts are often the result of
4832 Merges with unresolved conflicts are often the result of
4821 non-interactive merging using the ``internal:merge`` configuration
4833 non-interactive merging using the ``internal:merge`` configuration
4822 setting, or a command-line merge tool like ``diff3``. The resolve
4834 setting, or a command-line merge tool like ``diff3``. The resolve
4823 command is used to manage the files involved in a merge, after
4835 command is used to manage the files involved in a merge, after
4824 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4836 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4825 working directory must have two parents). See :hg:`help
4837 working directory must have two parents). See :hg:`help
4826 merge-tools` for information on configuring merge tools.
4838 merge-tools` for information on configuring merge tools.
4827
4839
4828 The resolve command can be used in the following ways:
4840 The resolve command can be used in the following ways:
4829
4841
4830 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4842 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4831 files, discarding any previous merge attempts. Re-merging is not
4843 files, discarding any previous merge attempts. Re-merging is not
4832 performed for files already marked as resolved. Use ``--all/-a``
4844 performed for files already marked as resolved. Use ``--all/-a``
4833 to select all unresolved files. ``--tool`` can be used to specify
4845 to select all unresolved files. ``--tool`` can be used to specify
4834 the merge tool used for the given files. It overrides the HGMERGE
4846 the merge tool used for the given files. It overrides the HGMERGE
4835 environment variable and your configuration files. Previous file
4847 environment variable and your configuration files. Previous file
4836 contents are saved with a ``.orig`` suffix.
4848 contents are saved with a ``.orig`` suffix.
4837
4849
4838 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4850 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4839 (e.g. after having manually fixed-up the files). The default is
4851 (e.g. after having manually fixed-up the files). The default is
4840 to mark all unresolved files.
4852 to mark all unresolved files.
4841
4853
4842 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4854 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4843 default is to mark all resolved files.
4855 default is to mark all resolved files.
4844
4856
4845 - :hg:`resolve -l`: list files which had or still have conflicts.
4857 - :hg:`resolve -l`: list files which had or still have conflicts.
4846 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4858 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4847
4859
4848 Note that Mercurial will not let you commit files with unresolved
4860 Note that Mercurial will not let you commit files with unresolved
4849 merge conflicts. You must use :hg:`resolve -m ...` before you can
4861 merge conflicts. You must use :hg:`resolve -m ...` before you can
4850 commit after a conflicting merge.
4862 commit after a conflicting merge.
4851
4863
4852 Returns 0 on success, 1 if any files fail a resolve attempt.
4864 Returns 0 on success, 1 if any files fail a resolve attempt.
4853 """
4865 """
4854
4866
4855 all, mark, unmark, show, nostatus = \
4867 all, mark, unmark, show, nostatus = \
4856 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4868 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4857
4869
4858 if (show and (mark or unmark)) or (mark and unmark):
4870 if (show and (mark or unmark)) or (mark and unmark):
4859 raise util.Abort(_("too many options specified"))
4871 raise util.Abort(_("too many options specified"))
4860 if pats and all:
4872 if pats and all:
4861 raise util.Abort(_("can't specify --all and patterns"))
4873 raise util.Abort(_("can't specify --all and patterns"))
4862 if not (all or pats or show or mark or unmark):
4874 if not (all or pats or show or mark or unmark):
4863 raise util.Abort(_('no files or directories specified; '
4875 raise util.Abort(_('no files or directories specified; '
4864 'use --all to remerge all files'))
4876 'use --all to remerge all files'))
4865
4877
4866 ms = mergemod.mergestate(repo)
4878 ms = mergemod.mergestate(repo)
4867 m = scmutil.match(repo[None], pats, opts)
4879 m = scmutil.match(repo[None], pats, opts)
4868 ret = 0
4880 ret = 0
4869
4881
4870 for f in ms:
4882 for f in ms:
4871 if m(f):
4883 if m(f):
4872 if show:
4884 if show:
4873 if nostatus:
4885 if nostatus:
4874 ui.write("%s\n" % f)
4886 ui.write("%s\n" % f)
4875 else:
4887 else:
4876 ui.write("%s %s\n" % (ms[f].upper(), f),
4888 ui.write("%s %s\n" % (ms[f].upper(), f),
4877 label='resolve.' +
4889 label='resolve.' +
4878 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4890 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4879 elif mark:
4891 elif mark:
4880 ms.mark(f, "r")
4892 ms.mark(f, "r")
4881 elif unmark:
4893 elif unmark:
4882 ms.mark(f, "u")
4894 ms.mark(f, "u")
4883 else:
4895 else:
4884 wctx = repo[None]
4896 wctx = repo[None]
4885 mctx = wctx.parents()[-1]
4897 mctx = wctx.parents()[-1]
4886
4898
4887 # backup pre-resolve (merge uses .orig for its own purposes)
4899 # backup pre-resolve (merge uses .orig for its own purposes)
4888 a = repo.wjoin(f)
4900 a = repo.wjoin(f)
4889 util.copyfile(a, a + ".resolve")
4901 util.copyfile(a, a + ".resolve")
4890
4902
4891 try:
4903 try:
4892 # resolve file
4904 # resolve file
4893 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4905 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4894 if ms.resolve(f, wctx, mctx):
4906 if ms.resolve(f, wctx, mctx):
4895 ret = 1
4907 ret = 1
4896 finally:
4908 finally:
4897 ui.setconfig('ui', 'forcemerge', '')
4909 ui.setconfig('ui', 'forcemerge', '')
4898 ms.commit()
4910 ms.commit()
4899
4911
4900 # replace filemerge's .orig file with our resolve file
4912 # replace filemerge's .orig file with our resolve file
4901 util.rename(a + ".resolve", a + ".orig")
4913 util.rename(a + ".resolve", a + ".orig")
4902
4914
4903 ms.commit()
4915 ms.commit()
4904 return ret
4916 return ret
4905
4917
4906 @command('revert',
4918 @command('revert',
4907 [('a', 'all', None, _('revert all changes when no arguments given')),
4919 [('a', 'all', None, _('revert all changes when no arguments given')),
4908 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4920 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4909 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4921 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4910 ('C', 'no-backup', None, _('do not save backup copies of files')),
4922 ('C', 'no-backup', None, _('do not save backup copies of files')),
4911 ] + walkopts + dryrunopts,
4923 ] + walkopts + dryrunopts,
4912 _('[OPTION]... [-r REV] [NAME]...'))
4924 _('[OPTION]... [-r REV] [NAME]...'))
4913 def revert(ui, repo, *pats, **opts):
4925 def revert(ui, repo, *pats, **opts):
4914 """restore files to their checkout state
4926 """restore files to their checkout state
4915
4927
4916 .. note::
4928 .. note::
4917
4929
4918 To check out earlier revisions, you should use :hg:`update REV`.
4930 To check out earlier revisions, you should use :hg:`update REV`.
4919 To cancel an uncommitted merge (and lose your changes), use
4931 To cancel an uncommitted merge (and lose your changes), use
4920 :hg:`update --clean .`.
4932 :hg:`update --clean .`.
4921
4933
4922 With no revision specified, revert the specified files or directories
4934 With no revision specified, revert the specified files or directories
4923 to the contents they had in the parent of the working directory.
4935 to the contents they had in the parent of the working directory.
4924 This restores the contents of files to an unmodified
4936 This restores the contents of files to an unmodified
4925 state and unschedules adds, removes, copies, and renames. If the
4937 state and unschedules adds, removes, copies, and renames. If the
4926 working directory has two parents, you must explicitly specify a
4938 working directory has two parents, you must explicitly specify a
4927 revision.
4939 revision.
4928
4940
4929 Using the -r/--rev or -d/--date options, revert the given files or
4941 Using the -r/--rev or -d/--date options, revert the given files or
4930 directories to their states as of a specific revision. Because
4942 directories to their states as of a specific revision. Because
4931 revert does not change the working directory parents, this will
4943 revert does not change the working directory parents, this will
4932 cause these files to appear modified. This can be helpful to "back
4944 cause these files to appear modified. This can be helpful to "back
4933 out" some or all of an earlier change. See :hg:`backout` for a
4945 out" some or all of an earlier change. See :hg:`backout` for a
4934 related method.
4946 related method.
4935
4947
4936 Modified files are saved with a .orig suffix before reverting.
4948 Modified files are saved with a .orig suffix before reverting.
4937 To disable these backups, use --no-backup.
4949 To disable these backups, use --no-backup.
4938
4950
4939 See :hg:`help dates` for a list of formats valid for -d/--date.
4951 See :hg:`help dates` for a list of formats valid for -d/--date.
4940
4952
4941 Returns 0 on success.
4953 Returns 0 on success.
4942 """
4954 """
4943
4955
4944 if opts.get("date"):
4956 if opts.get("date"):
4945 if opts.get("rev"):
4957 if opts.get("rev"):
4946 raise util.Abort(_("you can't specify a revision and a date"))
4958 raise util.Abort(_("you can't specify a revision and a date"))
4947 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4959 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4948
4960
4949 parent, p2 = repo.dirstate.parents()
4961 parent, p2 = repo.dirstate.parents()
4950 if not opts.get('rev') and p2 != nullid:
4962 if not opts.get('rev') and p2 != nullid:
4951 # revert after merge is a trap for new users (issue2915)
4963 # revert after merge is a trap for new users (issue2915)
4952 raise util.Abort(_('uncommitted merge with no revision specified'),
4964 raise util.Abort(_('uncommitted merge with no revision specified'),
4953 hint=_('use "hg update" or see "hg help revert"'))
4965 hint=_('use "hg update" or see "hg help revert"'))
4954
4966
4955 ctx = scmutil.revsingle(repo, opts.get('rev'))
4967 ctx = scmutil.revsingle(repo, opts.get('rev'))
4956
4968
4957 if not pats and not opts.get('all'):
4969 if not pats and not opts.get('all'):
4958 msg = _("no files or directories specified")
4970 msg = _("no files or directories specified")
4959 if p2 != nullid:
4971 if p2 != nullid:
4960 hint = _("uncommitted merge, use --all to discard all changes,"
4972 hint = _("uncommitted merge, use --all to discard all changes,"
4961 " or 'hg update -C .' to abort the merge")
4973 " or 'hg update -C .' to abort the merge")
4962 raise util.Abort(msg, hint=hint)
4974 raise util.Abort(msg, hint=hint)
4963 dirty = util.any(repo.status())
4975 dirty = util.any(repo.status())
4964 node = ctx.node()
4976 node = ctx.node()
4965 if node != parent:
4977 if node != parent:
4966 if dirty:
4978 if dirty:
4967 hint = _("uncommitted changes, use --all to discard all"
4979 hint = _("uncommitted changes, use --all to discard all"
4968 " changes, or 'hg update %s' to update") % ctx.rev()
4980 " changes, or 'hg update %s' to update") % ctx.rev()
4969 else:
4981 else:
4970 hint = _("use --all to revert all files,"
4982 hint = _("use --all to revert all files,"
4971 " or 'hg update %s' to update") % ctx.rev()
4983 " or 'hg update %s' to update") % ctx.rev()
4972 elif dirty:
4984 elif dirty:
4973 hint = _("uncommitted changes, use --all to discard all changes")
4985 hint = _("uncommitted changes, use --all to discard all changes")
4974 else:
4986 else:
4975 hint = _("use --all to revert all files")
4987 hint = _("use --all to revert all files")
4976 raise util.Abort(msg, hint=hint)
4988 raise util.Abort(msg, hint=hint)
4977
4989
4978 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4990 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4979
4991
4980 @command('rollback', dryrunopts +
4992 @command('rollback', dryrunopts +
4981 [('f', 'force', False, _('ignore safety measures'))])
4993 [('f', 'force', False, _('ignore safety measures'))])
4982 def rollback(ui, repo, **opts):
4994 def rollback(ui, repo, **opts):
4983 """roll back the last transaction (dangerous)
4995 """roll back the last transaction (dangerous)
4984
4996
4985 This command should be used with care. There is only one level of
4997 This command should be used with care. There is only one level of
4986 rollback, and there is no way to undo a rollback. It will also
4998 rollback, and there is no way to undo a rollback. It will also
4987 restore the dirstate at the time of the last transaction, losing
4999 restore the dirstate at the time of the last transaction, losing
4988 any dirstate changes since that time. This command does not alter
5000 any dirstate changes since that time. This command does not alter
4989 the working directory.
5001 the working directory.
4990
5002
4991 Transactions are used to encapsulate the effects of all commands
5003 Transactions are used to encapsulate the effects of all commands
4992 that create new changesets or propagate existing changesets into a
5004 that create new changesets or propagate existing changesets into a
4993 repository.
5005 repository.
4994
5006
4995 .. container:: verbose
5007 .. container:: verbose
4996
5008
4997 For example, the following commands are transactional, and their
5009 For example, the following commands are transactional, and their
4998 effects can be rolled back:
5010 effects can be rolled back:
4999
5011
5000 - commit
5012 - commit
5001 - import
5013 - import
5002 - pull
5014 - pull
5003 - push (with this repository as the destination)
5015 - push (with this repository as the destination)
5004 - unbundle
5016 - unbundle
5005
5017
5006 To avoid permanent data loss, rollback will refuse to rollback a
5018 To avoid permanent data loss, rollback will refuse to rollback a
5007 commit transaction if it isn't checked out. Use --force to
5019 commit transaction if it isn't checked out. Use --force to
5008 override this protection.
5020 override this protection.
5009
5021
5010 This command is not intended for use on public repositories. Once
5022 This command is not intended for use on public repositories. Once
5011 changes are visible for pull by other users, rolling a transaction
5023 changes are visible for pull by other users, rolling a transaction
5012 back locally is ineffective (someone else may already have pulled
5024 back locally is ineffective (someone else may already have pulled
5013 the changes). Furthermore, a race is possible with readers of the
5025 the changes). Furthermore, a race is possible with readers of the
5014 repository; for example an in-progress pull from the repository
5026 repository; for example an in-progress pull from the repository
5015 may fail if a rollback is performed.
5027 may fail if a rollback is performed.
5016
5028
5017 Returns 0 on success, 1 if no rollback data is available.
5029 Returns 0 on success, 1 if no rollback data is available.
5018 """
5030 """
5019 return repo.rollback(dryrun=opts.get('dry_run'),
5031 return repo.rollback(dryrun=opts.get('dry_run'),
5020 force=opts.get('force'))
5032 force=opts.get('force'))
5021
5033
5022 @command('root', [])
5034 @command('root', [])
5023 def root(ui, repo):
5035 def root(ui, repo):
5024 """print the root (top) of the current working directory
5036 """print the root (top) of the current working directory
5025
5037
5026 Print the root directory of the current repository.
5038 Print the root directory of the current repository.
5027
5039
5028 Returns 0 on success.
5040 Returns 0 on success.
5029 """
5041 """
5030 ui.write(repo.root + "\n")
5042 ui.write(repo.root + "\n")
5031
5043
5032 @command('^serve',
5044 @command('^serve',
5033 [('A', 'accesslog', '', _('name of access log file to write to'),
5045 [('A', 'accesslog', '', _('name of access log file to write to'),
5034 _('FILE')),
5046 _('FILE')),
5035 ('d', 'daemon', None, _('run server in background')),
5047 ('d', 'daemon', None, _('run server in background')),
5036 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5048 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5037 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5049 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5038 # use string type, then we can check if something was passed
5050 # use string type, then we can check if something was passed
5039 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5051 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5040 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5052 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5041 _('ADDR')),
5053 _('ADDR')),
5042 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5054 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5043 _('PREFIX')),
5055 _('PREFIX')),
5044 ('n', 'name', '',
5056 ('n', 'name', '',
5045 _('name to show in web pages (default: working directory)'), _('NAME')),
5057 _('name to show in web pages (default: working directory)'), _('NAME')),
5046 ('', 'web-conf', '',
5058 ('', 'web-conf', '',
5047 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5059 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5048 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5060 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5049 _('FILE')),
5061 _('FILE')),
5050 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5062 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5051 ('', 'stdio', None, _('for remote clients')),
5063 ('', 'stdio', None, _('for remote clients')),
5052 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5064 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5053 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5065 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5054 ('', 'style', '', _('template style to use'), _('STYLE')),
5066 ('', 'style', '', _('template style to use'), _('STYLE')),
5055 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5067 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5056 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5068 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5057 _('[OPTION]...'))
5069 _('[OPTION]...'))
5058 def serve(ui, repo, **opts):
5070 def serve(ui, repo, **opts):
5059 """start stand-alone webserver
5071 """start stand-alone webserver
5060
5072
5061 Start a local HTTP repository browser and pull server. You can use
5073 Start a local HTTP repository browser and pull server. You can use
5062 this for ad-hoc sharing and browsing of repositories. It is
5074 this for ad-hoc sharing and browsing of repositories. It is
5063 recommended to use a real web server to serve a repository for
5075 recommended to use a real web server to serve a repository for
5064 longer periods of time.
5076 longer periods of time.
5065
5077
5066 Please note that the server does not implement access control.
5078 Please note that the server does not implement access control.
5067 This means that, by default, anybody can read from the server and
5079 This means that, by default, anybody can read from the server and
5068 nobody can write to it by default. Set the ``web.allow_push``
5080 nobody can write to it by default. Set the ``web.allow_push``
5069 option to ``*`` to allow everybody to push to the server. You
5081 option to ``*`` to allow everybody to push to the server. You
5070 should use a real web server if you need to authenticate users.
5082 should use a real web server if you need to authenticate users.
5071
5083
5072 By default, the server logs accesses to stdout and errors to
5084 By default, the server logs accesses to stdout and errors to
5073 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5085 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5074 files.
5086 files.
5075
5087
5076 To have the server choose a free port number to listen on, specify
5088 To have the server choose a free port number to listen on, specify
5077 a port number of 0; in this case, the server will print the port
5089 a port number of 0; in this case, the server will print the port
5078 number it uses.
5090 number it uses.
5079
5091
5080 Returns 0 on success.
5092 Returns 0 on success.
5081 """
5093 """
5082
5094
5083 if opts["stdio"] and opts["cmdserver"]:
5095 if opts["stdio"] and opts["cmdserver"]:
5084 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5096 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5085
5097
5086 def checkrepo():
5098 def checkrepo():
5087 if repo is None:
5099 if repo is None:
5088 raise error.RepoError(_("there is no Mercurial repository here"
5100 raise error.RepoError(_("there is no Mercurial repository here"
5089 " (.hg not found)"))
5101 " (.hg not found)"))
5090
5102
5091 if opts["stdio"]:
5103 if opts["stdio"]:
5092 checkrepo()
5104 checkrepo()
5093 s = sshserver.sshserver(ui, repo)
5105 s = sshserver.sshserver(ui, repo)
5094 s.serve_forever()
5106 s.serve_forever()
5095
5107
5096 if opts["cmdserver"]:
5108 if opts["cmdserver"]:
5097 checkrepo()
5109 checkrepo()
5098 s = commandserver.server(ui, repo, opts["cmdserver"])
5110 s = commandserver.server(ui, repo, opts["cmdserver"])
5099 return s.serve()
5111 return s.serve()
5100
5112
5101 # this way we can check if something was given in the command-line
5113 # this way we can check if something was given in the command-line
5102 if opts.get('port'):
5114 if opts.get('port'):
5103 opts['port'] = util.getport(opts.get('port'))
5115 opts['port'] = util.getport(opts.get('port'))
5104
5116
5105 baseui = repo and repo.baseui or ui
5117 baseui = repo and repo.baseui or ui
5106 optlist = ("name templates style address port prefix ipv6"
5118 optlist = ("name templates style address port prefix ipv6"
5107 " accesslog errorlog certificate encoding")
5119 " accesslog errorlog certificate encoding")
5108 for o in optlist.split():
5120 for o in optlist.split():
5109 val = opts.get(o, '')
5121 val = opts.get(o, '')
5110 if val in (None, ''): # should check against default options instead
5122 if val in (None, ''): # should check against default options instead
5111 continue
5123 continue
5112 baseui.setconfig("web", o, val)
5124 baseui.setconfig("web", o, val)
5113 if repo and repo.ui != baseui:
5125 if repo and repo.ui != baseui:
5114 repo.ui.setconfig("web", o, val)
5126 repo.ui.setconfig("web", o, val)
5115
5127
5116 o = opts.get('web_conf') or opts.get('webdir_conf')
5128 o = opts.get('web_conf') or opts.get('webdir_conf')
5117 if not o:
5129 if not o:
5118 if not repo:
5130 if not repo:
5119 raise error.RepoError(_("there is no Mercurial repository"
5131 raise error.RepoError(_("there is no Mercurial repository"
5120 " here (.hg not found)"))
5132 " here (.hg not found)"))
5121 o = repo
5133 o = repo
5122
5134
5123 app = hgweb.hgweb(o, baseui=baseui)
5135 app = hgweb.hgweb(o, baseui=baseui)
5124
5136
5125 class service(object):
5137 class service(object):
5126 def init(self):
5138 def init(self):
5127 util.setsignalhandler()
5139 util.setsignalhandler()
5128 self.httpd = hgweb.server.create_server(ui, app)
5140 self.httpd = hgweb.server.create_server(ui, app)
5129
5141
5130 if opts['port'] and not ui.verbose:
5142 if opts['port'] and not ui.verbose:
5131 return
5143 return
5132
5144
5133 if self.httpd.prefix:
5145 if self.httpd.prefix:
5134 prefix = self.httpd.prefix.strip('/') + '/'
5146 prefix = self.httpd.prefix.strip('/') + '/'
5135 else:
5147 else:
5136 prefix = ''
5148 prefix = ''
5137
5149
5138 port = ':%d' % self.httpd.port
5150 port = ':%d' % self.httpd.port
5139 if port == ':80':
5151 if port == ':80':
5140 port = ''
5152 port = ''
5141
5153
5142 bindaddr = self.httpd.addr
5154 bindaddr = self.httpd.addr
5143 if bindaddr == '0.0.0.0':
5155 if bindaddr == '0.0.0.0':
5144 bindaddr = '*'
5156 bindaddr = '*'
5145 elif ':' in bindaddr: # IPv6
5157 elif ':' in bindaddr: # IPv6
5146 bindaddr = '[%s]' % bindaddr
5158 bindaddr = '[%s]' % bindaddr
5147
5159
5148 fqaddr = self.httpd.fqaddr
5160 fqaddr = self.httpd.fqaddr
5149 if ':' in fqaddr:
5161 if ':' in fqaddr:
5150 fqaddr = '[%s]' % fqaddr
5162 fqaddr = '[%s]' % fqaddr
5151 if opts['port']:
5163 if opts['port']:
5152 write = ui.status
5164 write = ui.status
5153 else:
5165 else:
5154 write = ui.write
5166 write = ui.write
5155 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5167 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5156 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5168 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5157
5169
5158 def run(self):
5170 def run(self):
5159 self.httpd.serve_forever()
5171 self.httpd.serve_forever()
5160
5172
5161 service = service()
5173 service = service()
5162
5174
5163 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5175 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5164
5176
5165 @command('showconfig|debugconfig',
5177 @command('showconfig|debugconfig',
5166 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5178 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5167 _('[-u] [NAME]...'))
5179 _('[-u] [NAME]...'))
5168 def showconfig(ui, repo, *values, **opts):
5180 def showconfig(ui, repo, *values, **opts):
5169 """show combined config settings from all hgrc files
5181 """show combined config settings from all hgrc files
5170
5182
5171 With no arguments, print names and values of all config items.
5183 With no arguments, print names and values of all config items.
5172
5184
5173 With one argument of the form section.name, print just the value
5185 With one argument of the form section.name, print just the value
5174 of that config item.
5186 of that config item.
5175
5187
5176 With multiple arguments, print names and values of all config
5188 With multiple arguments, print names and values of all config
5177 items with matching section names.
5189 items with matching section names.
5178
5190
5179 With --debug, the source (filename and line number) is printed
5191 With --debug, the source (filename and line number) is printed
5180 for each config item.
5192 for each config item.
5181
5193
5182 Returns 0 on success.
5194 Returns 0 on success.
5183 """
5195 """
5184
5196
5185 for f in scmutil.rcpath():
5197 for f in scmutil.rcpath():
5186 ui.debug('read config from: %s\n' % f)
5198 ui.debug('read config from: %s\n' % f)
5187 untrusted = bool(opts.get('untrusted'))
5199 untrusted = bool(opts.get('untrusted'))
5188 if values:
5200 if values:
5189 sections = [v for v in values if '.' not in v]
5201 sections = [v for v in values if '.' not in v]
5190 items = [v for v in values if '.' in v]
5202 items = [v for v in values if '.' in v]
5191 if len(items) > 1 or items and sections:
5203 if len(items) > 1 or items and sections:
5192 raise util.Abort(_('only one config item permitted'))
5204 raise util.Abort(_('only one config item permitted'))
5193 for section, name, value in ui.walkconfig(untrusted=untrusted):
5205 for section, name, value in ui.walkconfig(untrusted=untrusted):
5194 value = str(value).replace('\n', '\\n')
5206 value = str(value).replace('\n', '\\n')
5195 sectname = section + '.' + name
5207 sectname = section + '.' + name
5196 if values:
5208 if values:
5197 for v in values:
5209 for v in values:
5198 if v == section:
5210 if v == section:
5199 ui.debug('%s: ' %
5211 ui.debug('%s: ' %
5200 ui.configsource(section, name, untrusted))
5212 ui.configsource(section, name, untrusted))
5201 ui.write('%s=%s\n' % (sectname, value))
5213 ui.write('%s=%s\n' % (sectname, value))
5202 elif v == sectname:
5214 elif v == sectname:
5203 ui.debug('%s: ' %
5215 ui.debug('%s: ' %
5204 ui.configsource(section, name, untrusted))
5216 ui.configsource(section, name, untrusted))
5205 ui.write(value, '\n')
5217 ui.write(value, '\n')
5206 else:
5218 else:
5207 ui.debug('%s: ' %
5219 ui.debug('%s: ' %
5208 ui.configsource(section, name, untrusted))
5220 ui.configsource(section, name, untrusted))
5209 ui.write('%s=%s\n' % (sectname, value))
5221 ui.write('%s=%s\n' % (sectname, value))
5210
5222
5211 @command('^status|st',
5223 @command('^status|st',
5212 [('A', 'all', None, _('show status of all files')),
5224 [('A', 'all', None, _('show status of all files')),
5213 ('m', 'modified', None, _('show only modified files')),
5225 ('m', 'modified', None, _('show only modified files')),
5214 ('a', 'added', None, _('show only added files')),
5226 ('a', 'added', None, _('show only added files')),
5215 ('r', 'removed', None, _('show only removed files')),
5227 ('r', 'removed', None, _('show only removed files')),
5216 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5228 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5217 ('c', 'clean', None, _('show only files without changes')),
5229 ('c', 'clean', None, _('show only files without changes')),
5218 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5230 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5219 ('i', 'ignored', None, _('show only ignored files')),
5231 ('i', 'ignored', None, _('show only ignored files')),
5220 ('n', 'no-status', None, _('hide status prefix')),
5232 ('n', 'no-status', None, _('hide status prefix')),
5221 ('C', 'copies', None, _('show source of copied files')),
5233 ('C', 'copies', None, _('show source of copied files')),
5222 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5234 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5223 ('', 'rev', [], _('show difference from revision'), _('REV')),
5235 ('', 'rev', [], _('show difference from revision'), _('REV')),
5224 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5236 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5225 ] + walkopts + subrepoopts,
5237 ] + walkopts + subrepoopts,
5226 _('[OPTION]... [FILE]...'))
5238 _('[OPTION]... [FILE]...'))
5227 def status(ui, repo, *pats, **opts):
5239 def status(ui, repo, *pats, **opts):
5228 """show changed files in the working directory
5240 """show changed files in the working directory
5229
5241
5230 Show status of files in the repository. If names are given, only
5242 Show status of files in the repository. If names are given, only
5231 files that match are shown. Files that are clean or ignored or
5243 files that match are shown. Files that are clean or ignored or
5232 the source of a copy/move operation, are not listed unless
5244 the source of a copy/move operation, are not listed unless
5233 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5245 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5234 Unless options described with "show only ..." are given, the
5246 Unless options described with "show only ..." are given, the
5235 options -mardu are used.
5247 options -mardu are used.
5236
5248
5237 Option -q/--quiet hides untracked (unknown and ignored) files
5249 Option -q/--quiet hides untracked (unknown and ignored) files
5238 unless explicitly requested with -u/--unknown or -i/--ignored.
5250 unless explicitly requested with -u/--unknown or -i/--ignored.
5239
5251
5240 .. note::
5252 .. note::
5241 status may appear to disagree with diff if permissions have
5253 status may appear to disagree with diff if permissions have
5242 changed or a merge has occurred. The standard diff format does
5254 changed or a merge has occurred. The standard diff format does
5243 not report permission changes and diff only reports changes
5255 not report permission changes and diff only reports changes
5244 relative to one merge parent.
5256 relative to one merge parent.
5245
5257
5246 If one revision is given, it is used as the base revision.
5258 If one revision is given, it is used as the base revision.
5247 If two revisions are given, the differences between them are
5259 If two revisions are given, the differences between them are
5248 shown. The --change option can also be used as a shortcut to list
5260 shown. The --change option can also be used as a shortcut to list
5249 the changed files of a revision from its first parent.
5261 the changed files of a revision from its first parent.
5250
5262
5251 The codes used to show the status of files are::
5263 The codes used to show the status of files are::
5252
5264
5253 M = modified
5265 M = modified
5254 A = added
5266 A = added
5255 R = removed
5267 R = removed
5256 C = clean
5268 C = clean
5257 ! = missing (deleted by non-hg command, but still tracked)
5269 ! = missing (deleted by non-hg command, but still tracked)
5258 ? = not tracked
5270 ? = not tracked
5259 I = ignored
5271 I = ignored
5260 = origin of the previous file listed as A (added)
5272 = origin of the previous file listed as A (added)
5261
5273
5262 .. container:: verbose
5274 .. container:: verbose
5263
5275
5264 Examples:
5276 Examples:
5265
5277
5266 - show changes in the working directory relative to a
5278 - show changes in the working directory relative to a
5267 changeset::
5279 changeset::
5268
5280
5269 hg status --rev 9353
5281 hg status --rev 9353
5270
5282
5271 - show all changes including copies in an existing changeset::
5283 - show all changes including copies in an existing changeset::
5272
5284
5273 hg status --copies --change 9353
5285 hg status --copies --change 9353
5274
5286
5275 - get a NUL separated list of added files, suitable for xargs::
5287 - get a NUL separated list of added files, suitable for xargs::
5276
5288
5277 hg status -an0
5289 hg status -an0
5278
5290
5279 Returns 0 on success.
5291 Returns 0 on success.
5280 """
5292 """
5281
5293
5282 revs = opts.get('rev')
5294 revs = opts.get('rev')
5283 change = opts.get('change')
5295 change = opts.get('change')
5284
5296
5285 if revs and change:
5297 if revs and change:
5286 msg = _('cannot specify --rev and --change at the same time')
5298 msg = _('cannot specify --rev and --change at the same time')
5287 raise util.Abort(msg)
5299 raise util.Abort(msg)
5288 elif change:
5300 elif change:
5289 node2 = scmutil.revsingle(repo, change, None).node()
5301 node2 = scmutil.revsingle(repo, change, None).node()
5290 node1 = repo[node2].p1().node()
5302 node1 = repo[node2].p1().node()
5291 else:
5303 else:
5292 node1, node2 = scmutil.revpair(repo, revs)
5304 node1, node2 = scmutil.revpair(repo, revs)
5293
5305
5294 cwd = (pats and repo.getcwd()) or ''
5306 cwd = (pats and repo.getcwd()) or ''
5295 end = opts.get('print0') and '\0' or '\n'
5307 end = opts.get('print0') and '\0' or '\n'
5296 copy = {}
5308 copy = {}
5297 states = 'modified added removed deleted unknown ignored clean'.split()
5309 states = 'modified added removed deleted unknown ignored clean'.split()
5298 show = [k for k in states if opts.get(k)]
5310 show = [k for k in states if opts.get(k)]
5299 if opts.get('all'):
5311 if opts.get('all'):
5300 show += ui.quiet and (states[:4] + ['clean']) or states
5312 show += ui.quiet and (states[:4] + ['clean']) or states
5301 if not show:
5313 if not show:
5302 show = ui.quiet and states[:4] or states[:5]
5314 show = ui.quiet and states[:4] or states[:5]
5303
5315
5304 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5316 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5305 'ignored' in show, 'clean' in show, 'unknown' in show,
5317 'ignored' in show, 'clean' in show, 'unknown' in show,
5306 opts.get('subrepos'))
5318 opts.get('subrepos'))
5307 changestates = zip(states, 'MAR!?IC', stat)
5319 changestates = zip(states, 'MAR!?IC', stat)
5308
5320
5309 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5321 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5310 copy = copies.pathcopies(repo[node1], repo[node2])
5322 copy = copies.pathcopies(repo[node1], repo[node2])
5311
5323
5312 fm = ui.formatter('status', opts)
5324 fm = ui.formatter('status', opts)
5313 fmt = '%s' + end
5325 fmt = '%s' + end
5314 showchar = not opts.get('no_status')
5326 showchar = not opts.get('no_status')
5315
5327
5316 for state, char, files in changestates:
5328 for state, char, files in changestates:
5317 if state in show:
5329 if state in show:
5318 label = 'status.' + state
5330 label = 'status.' + state
5319 for f in files:
5331 for f in files:
5320 fm.startitem()
5332 fm.startitem()
5321 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5333 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5322 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5334 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5323 if f in copy:
5335 if f in copy:
5324 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5336 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5325 label='status.copied')
5337 label='status.copied')
5326 fm.end()
5338 fm.end()
5327
5339
5328 @command('^summary|sum',
5340 @command('^summary|sum',
5329 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5341 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5330 def summary(ui, repo, **opts):
5342 def summary(ui, repo, **opts):
5331 """summarize working directory state
5343 """summarize working directory state
5332
5344
5333 This generates a brief summary of the working directory state,
5345 This generates a brief summary of the working directory state,
5334 including parents, branch, commit status, and available updates.
5346 including parents, branch, commit status, and available updates.
5335
5347
5336 With the --remote option, this will check the default paths for
5348 With the --remote option, this will check the default paths for
5337 incoming and outgoing changes. This can be time-consuming.
5349 incoming and outgoing changes. This can be time-consuming.
5338
5350
5339 Returns 0 on success.
5351 Returns 0 on success.
5340 """
5352 """
5341
5353
5342 ctx = repo[None]
5354 ctx = repo[None]
5343 parents = ctx.parents()
5355 parents = ctx.parents()
5344 pnode = parents[0].node()
5356 pnode = parents[0].node()
5345 marks = []
5357 marks = []
5346
5358
5347 for p in parents:
5359 for p in parents:
5348 # label with log.changeset (instead of log.parent) since this
5360 # label with log.changeset (instead of log.parent) since this
5349 # shows a working directory parent *changeset*:
5361 # shows a working directory parent *changeset*:
5350 # i18n: column positioning for "hg summary"
5362 # i18n: column positioning for "hg summary"
5351 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5363 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5352 label='log.changeset changeset.%s' % p.phasestr())
5364 label='log.changeset changeset.%s' % p.phasestr())
5353 ui.write(' '.join(p.tags()), label='log.tag')
5365 ui.write(' '.join(p.tags()), label='log.tag')
5354 if p.bookmarks():
5366 if p.bookmarks():
5355 marks.extend(p.bookmarks())
5367 marks.extend(p.bookmarks())
5356 if p.rev() == -1:
5368 if p.rev() == -1:
5357 if not len(repo):
5369 if not len(repo):
5358 ui.write(_(' (empty repository)'))
5370 ui.write(_(' (empty repository)'))
5359 else:
5371 else:
5360 ui.write(_(' (no revision checked out)'))
5372 ui.write(_(' (no revision checked out)'))
5361 ui.write('\n')
5373 ui.write('\n')
5362 if p.description():
5374 if p.description():
5363 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5375 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5364 label='log.summary')
5376 label='log.summary')
5365
5377
5366 branch = ctx.branch()
5378 branch = ctx.branch()
5367 bheads = repo.branchheads(branch)
5379 bheads = repo.branchheads(branch)
5368 # i18n: column positioning for "hg summary"
5380 # i18n: column positioning for "hg summary"
5369 m = _('branch: %s\n') % branch
5381 m = _('branch: %s\n') % branch
5370 if branch != 'default':
5382 if branch != 'default':
5371 ui.write(m, label='log.branch')
5383 ui.write(m, label='log.branch')
5372 else:
5384 else:
5373 ui.status(m, label='log.branch')
5385 ui.status(m, label='log.branch')
5374
5386
5375 if marks:
5387 if marks:
5376 current = repo._bookmarkcurrent
5388 current = repo._bookmarkcurrent
5377 # i18n: column positioning for "hg summary"
5389 # i18n: column positioning for "hg summary"
5378 ui.write(_('bookmarks:'), label='log.bookmark')
5390 ui.write(_('bookmarks:'), label='log.bookmark')
5379 if current is not None:
5391 if current is not None:
5380 if current in marks:
5392 if current in marks:
5381 ui.write(' *' + current, label='bookmarks.current')
5393 ui.write(' *' + current, label='bookmarks.current')
5382 marks.remove(current)
5394 marks.remove(current)
5383 else:
5395 else:
5384 ui.write(' [%s]' % current, label='bookmarks.current')
5396 ui.write(' [%s]' % current, label='bookmarks.current')
5385 for m in marks:
5397 for m in marks:
5386 ui.write(' ' + m, label='log.bookmark')
5398 ui.write(' ' + m, label='log.bookmark')
5387 ui.write('\n', label='log.bookmark')
5399 ui.write('\n', label='log.bookmark')
5388
5400
5389 st = list(repo.status(unknown=True))[:6]
5401 st = list(repo.status(unknown=True))[:6]
5390
5402
5391 c = repo.dirstate.copies()
5403 c = repo.dirstate.copies()
5392 copied, renamed = [], []
5404 copied, renamed = [], []
5393 for d, s in c.iteritems():
5405 for d, s in c.iteritems():
5394 if s in st[2]:
5406 if s in st[2]:
5395 st[2].remove(s)
5407 st[2].remove(s)
5396 renamed.append(d)
5408 renamed.append(d)
5397 else:
5409 else:
5398 copied.append(d)
5410 copied.append(d)
5399 if d in st[1]:
5411 if d in st[1]:
5400 st[1].remove(d)
5412 st[1].remove(d)
5401 st.insert(3, renamed)
5413 st.insert(3, renamed)
5402 st.insert(4, copied)
5414 st.insert(4, copied)
5403
5415
5404 ms = mergemod.mergestate(repo)
5416 ms = mergemod.mergestate(repo)
5405 st.append([f for f in ms if ms[f] == 'u'])
5417 st.append([f for f in ms if ms[f] == 'u'])
5406
5418
5407 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5419 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5408 st.append(subs)
5420 st.append(subs)
5409
5421
5410 labels = [ui.label(_('%d modified'), 'status.modified'),
5422 labels = [ui.label(_('%d modified'), 'status.modified'),
5411 ui.label(_('%d added'), 'status.added'),
5423 ui.label(_('%d added'), 'status.added'),
5412 ui.label(_('%d removed'), 'status.removed'),
5424 ui.label(_('%d removed'), 'status.removed'),
5413 ui.label(_('%d renamed'), 'status.copied'),
5425 ui.label(_('%d renamed'), 'status.copied'),
5414 ui.label(_('%d copied'), 'status.copied'),
5426 ui.label(_('%d copied'), 'status.copied'),
5415 ui.label(_('%d deleted'), 'status.deleted'),
5427 ui.label(_('%d deleted'), 'status.deleted'),
5416 ui.label(_('%d unknown'), 'status.unknown'),
5428 ui.label(_('%d unknown'), 'status.unknown'),
5417 ui.label(_('%d ignored'), 'status.ignored'),
5429 ui.label(_('%d ignored'), 'status.ignored'),
5418 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5430 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5419 ui.label(_('%d subrepos'), 'status.modified')]
5431 ui.label(_('%d subrepos'), 'status.modified')]
5420 t = []
5432 t = []
5421 for s, l in zip(st, labels):
5433 for s, l in zip(st, labels):
5422 if s:
5434 if s:
5423 t.append(l % len(s))
5435 t.append(l % len(s))
5424
5436
5425 t = ', '.join(t)
5437 t = ', '.join(t)
5426 cleanworkdir = False
5438 cleanworkdir = False
5427
5439
5428 if len(parents) > 1:
5440 if len(parents) > 1:
5429 t += _(' (merge)')
5441 t += _(' (merge)')
5430 elif branch != parents[0].branch():
5442 elif branch != parents[0].branch():
5431 t += _(' (new branch)')
5443 t += _(' (new branch)')
5432 elif (parents[0].closesbranch() and
5444 elif (parents[0].closesbranch() and
5433 pnode in repo.branchheads(branch, closed=True)):
5445 pnode in repo.branchheads(branch, closed=True)):
5434 t += _(' (head closed)')
5446 t += _(' (head closed)')
5435 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5447 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5436 t += _(' (clean)')
5448 t += _(' (clean)')
5437 cleanworkdir = True
5449 cleanworkdir = True
5438 elif pnode not in bheads:
5450 elif pnode not in bheads:
5439 t += _(' (new branch head)')
5451 t += _(' (new branch head)')
5440
5452
5441 if cleanworkdir:
5453 if cleanworkdir:
5442 # i18n: column positioning for "hg summary"
5454 # i18n: column positioning for "hg summary"
5443 ui.status(_('commit: %s\n') % t.strip())
5455 ui.status(_('commit: %s\n') % t.strip())
5444 else:
5456 else:
5445 # i18n: column positioning for "hg summary"
5457 # i18n: column positioning for "hg summary"
5446 ui.write(_('commit: %s\n') % t.strip())
5458 ui.write(_('commit: %s\n') % t.strip())
5447
5459
5448 # all ancestors of branch heads - all ancestors of parent = new csets
5460 # all ancestors of branch heads - all ancestors of parent = new csets
5449 new = [0] * len(repo)
5461 new = [0] * len(repo)
5450 cl = repo.changelog
5462 cl = repo.changelog
5451 for a in [cl.rev(n) for n in bheads]:
5463 for a in [cl.rev(n) for n in bheads]:
5452 new[a] = 1
5464 new[a] = 1
5453 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5465 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5454 new[a] = 1
5466 new[a] = 1
5455 for a in [p.rev() for p in parents]:
5467 for a in [p.rev() for p in parents]:
5456 if a >= 0:
5468 if a >= 0:
5457 new[a] = 0
5469 new[a] = 0
5458 for a in cl.ancestors([p.rev() for p in parents]):
5470 for a in cl.ancestors([p.rev() for p in parents]):
5459 new[a] = 0
5471 new[a] = 0
5460 new = sum(new)
5472 new = sum(new)
5461
5473
5462 if new == 0:
5474 if new == 0:
5463 # i18n: column positioning for "hg summary"
5475 # i18n: column positioning for "hg summary"
5464 ui.status(_('update: (current)\n'))
5476 ui.status(_('update: (current)\n'))
5465 elif pnode not in bheads:
5477 elif pnode not in bheads:
5466 # i18n: column positioning for "hg summary"
5478 # i18n: column positioning for "hg summary"
5467 ui.write(_('update: %d new changesets (update)\n') % new)
5479 ui.write(_('update: %d new changesets (update)\n') % new)
5468 else:
5480 else:
5469 # i18n: column positioning for "hg summary"
5481 # i18n: column positioning for "hg summary"
5470 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5482 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5471 (new, len(bheads)))
5483 (new, len(bheads)))
5472
5484
5473 if opts.get('remote'):
5485 if opts.get('remote'):
5474 t = []
5486 t = []
5475 source, branches = hg.parseurl(ui.expandpath('default'))
5487 source, branches = hg.parseurl(ui.expandpath('default'))
5476 sbranch = branches[0]
5488 sbranch = branches[0]
5477 other = hg.peer(repo, {}, source)
5489 other = hg.peer(repo, {}, source)
5478 revs, checkout = hg.addbranchrevs(repo, other, branches,
5490 revs, checkout = hg.addbranchrevs(repo, other, branches,
5479 opts.get('rev'))
5491 opts.get('rev'))
5480 if revs:
5492 if revs:
5481 revs = [other.lookup(rev) for rev in revs]
5493 revs = [other.lookup(rev) for rev in revs]
5482 ui.debug('comparing with %s\n' % util.hidepassword(source))
5494 ui.debug('comparing with %s\n' % util.hidepassword(source))
5483 repo.ui.pushbuffer()
5495 repo.ui.pushbuffer()
5484 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5496 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5485 _common, incoming, _rheads = commoninc
5497 _common, incoming, _rheads = commoninc
5486 repo.ui.popbuffer()
5498 repo.ui.popbuffer()
5487 if incoming:
5499 if incoming:
5488 t.append(_('1 or more incoming'))
5500 t.append(_('1 or more incoming'))
5489
5501
5490 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5502 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5491 dbranch = branches[0]
5503 dbranch = branches[0]
5492 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5504 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5493 if source != dest:
5505 if source != dest:
5494 other = hg.peer(repo, {}, dest)
5506 other = hg.peer(repo, {}, dest)
5495 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5507 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5496 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5508 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5497 commoninc = None
5509 commoninc = None
5498 if revs:
5510 if revs:
5499 revs = [repo.lookup(rev) for rev in revs]
5511 revs = [repo.lookup(rev) for rev in revs]
5500 repo.ui.pushbuffer()
5512 repo.ui.pushbuffer()
5501 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5513 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5502 commoninc=commoninc)
5514 commoninc=commoninc)
5503 repo.ui.popbuffer()
5515 repo.ui.popbuffer()
5504 o = outgoing.missing
5516 o = outgoing.missing
5505 if o:
5517 if o:
5506 t.append(_('%d outgoing') % len(o))
5518 t.append(_('%d outgoing') % len(o))
5507 if 'bookmarks' in other.listkeys('namespaces'):
5519 if 'bookmarks' in other.listkeys('namespaces'):
5508 lmarks = repo.listkeys('bookmarks')
5520 lmarks = repo.listkeys('bookmarks')
5509 rmarks = other.listkeys('bookmarks')
5521 rmarks = other.listkeys('bookmarks')
5510 diff = set(rmarks) - set(lmarks)
5522 diff = set(rmarks) - set(lmarks)
5511 if len(diff) > 0:
5523 if len(diff) > 0:
5512 t.append(_('%d incoming bookmarks') % len(diff))
5524 t.append(_('%d incoming bookmarks') % len(diff))
5513 diff = set(lmarks) - set(rmarks)
5525 diff = set(lmarks) - set(rmarks)
5514 if len(diff) > 0:
5526 if len(diff) > 0:
5515 t.append(_('%d outgoing bookmarks') % len(diff))
5527 t.append(_('%d outgoing bookmarks') % len(diff))
5516
5528
5517 if t:
5529 if t:
5518 # i18n: column positioning for "hg summary"
5530 # i18n: column positioning for "hg summary"
5519 ui.write(_('remote: %s\n') % (', '.join(t)))
5531 ui.write(_('remote: %s\n') % (', '.join(t)))
5520 else:
5532 else:
5521 # i18n: column positioning for "hg summary"
5533 # i18n: column positioning for "hg summary"
5522 ui.status(_('remote: (synced)\n'))
5534 ui.status(_('remote: (synced)\n'))
5523
5535
5524 @command('tag',
5536 @command('tag',
5525 [('f', 'force', None, _('force tag')),
5537 [('f', 'force', None, _('force tag')),
5526 ('l', 'local', None, _('make the tag local')),
5538 ('l', 'local', None, _('make the tag local')),
5527 ('r', 'rev', '', _('revision to tag'), _('REV')),
5539 ('r', 'rev', '', _('revision to tag'), _('REV')),
5528 ('', 'remove', None, _('remove a tag')),
5540 ('', 'remove', None, _('remove a tag')),
5529 # -l/--local is already there, commitopts cannot be used
5541 # -l/--local is already there, commitopts cannot be used
5530 ('e', 'edit', None, _('edit commit message')),
5542 ('e', 'edit', None, _('edit commit message')),
5531 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5543 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5532 ] + commitopts2,
5544 ] + commitopts2,
5533 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5545 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5534 def tag(ui, repo, name1, *names, **opts):
5546 def tag(ui, repo, name1, *names, **opts):
5535 """add one or more tags for the current or given revision
5547 """add one or more tags for the current or given revision
5536
5548
5537 Name a particular revision using <name>.
5549 Name a particular revision using <name>.
5538
5550
5539 Tags are used to name particular revisions of the repository and are
5551 Tags are used to name particular revisions of the repository and are
5540 very useful to compare different revisions, to go back to significant
5552 very useful to compare different revisions, to go back to significant
5541 earlier versions or to mark branch points as releases, etc. Changing
5553 earlier versions or to mark branch points as releases, etc. Changing
5542 an existing tag is normally disallowed; use -f/--force to override.
5554 an existing tag is normally disallowed; use -f/--force to override.
5543
5555
5544 If no revision is given, the parent of the working directory is
5556 If no revision is given, the parent of the working directory is
5545 used, or tip if no revision is checked out.
5557 used, or tip if no revision is checked out.
5546
5558
5547 To facilitate version control, distribution, and merging of tags,
5559 To facilitate version control, distribution, and merging of tags,
5548 they are stored as a file named ".hgtags" which is managed similarly
5560 they are stored as a file named ".hgtags" which is managed similarly
5549 to other project files and can be hand-edited if necessary. This
5561 to other project files and can be hand-edited if necessary. This
5550 also means that tagging creates a new commit. The file
5562 also means that tagging creates a new commit. The file
5551 ".hg/localtags" is used for local tags (not shared among
5563 ".hg/localtags" is used for local tags (not shared among
5552 repositories).
5564 repositories).
5553
5565
5554 Tag commits are usually made at the head of a branch. If the parent
5566 Tag commits are usually made at the head of a branch. If the parent
5555 of the working directory is not a branch head, :hg:`tag` aborts; use
5567 of the working directory is not a branch head, :hg:`tag` aborts; use
5556 -f/--force to force the tag commit to be based on a non-head
5568 -f/--force to force the tag commit to be based on a non-head
5557 changeset.
5569 changeset.
5558
5570
5559 See :hg:`help dates` for a list of formats valid for -d/--date.
5571 See :hg:`help dates` for a list of formats valid for -d/--date.
5560
5572
5561 Since tag names have priority over branch names during revision
5573 Since tag names have priority over branch names during revision
5562 lookup, using an existing branch name as a tag name is discouraged.
5574 lookup, using an existing branch name as a tag name is discouraged.
5563
5575
5564 Returns 0 on success.
5576 Returns 0 on success.
5565 """
5577 """
5566 wlock = lock = None
5578 wlock = lock = None
5567 try:
5579 try:
5568 wlock = repo.wlock()
5580 wlock = repo.wlock()
5569 lock = repo.lock()
5581 lock = repo.lock()
5570 rev_ = "."
5582 rev_ = "."
5571 names = [t.strip() for t in (name1,) + names]
5583 names = [t.strip() for t in (name1,) + names]
5572 if len(names) != len(set(names)):
5584 if len(names) != len(set(names)):
5573 raise util.Abort(_('tag names must be unique'))
5585 raise util.Abort(_('tag names must be unique'))
5574 for n in names:
5586 for n in names:
5575 scmutil.checknewlabel(repo, n, 'tag')
5587 scmutil.checknewlabel(repo, n, 'tag')
5576 if not n:
5588 if not n:
5577 raise util.Abort(_('tag names cannot consist entirely of '
5589 raise util.Abort(_('tag names cannot consist entirely of '
5578 'whitespace'))
5590 'whitespace'))
5579 if opts.get('rev') and opts.get('remove'):
5591 if opts.get('rev') and opts.get('remove'):
5580 raise util.Abort(_("--rev and --remove are incompatible"))
5592 raise util.Abort(_("--rev and --remove are incompatible"))
5581 if opts.get('rev'):
5593 if opts.get('rev'):
5582 rev_ = opts['rev']
5594 rev_ = opts['rev']
5583 message = opts.get('message')
5595 message = opts.get('message')
5584 if opts.get('remove'):
5596 if opts.get('remove'):
5585 expectedtype = opts.get('local') and 'local' or 'global'
5597 expectedtype = opts.get('local') and 'local' or 'global'
5586 for n in names:
5598 for n in names:
5587 if not repo.tagtype(n):
5599 if not repo.tagtype(n):
5588 raise util.Abort(_("tag '%s' does not exist") % n)
5600 raise util.Abort(_("tag '%s' does not exist") % n)
5589 if repo.tagtype(n) != expectedtype:
5601 if repo.tagtype(n) != expectedtype:
5590 if expectedtype == 'global':
5602 if expectedtype == 'global':
5591 raise util.Abort(_("tag '%s' is not a global tag") % n)
5603 raise util.Abort(_("tag '%s' is not a global tag") % n)
5592 else:
5604 else:
5593 raise util.Abort(_("tag '%s' is not a local tag") % n)
5605 raise util.Abort(_("tag '%s' is not a local tag") % n)
5594 rev_ = nullid
5606 rev_ = nullid
5595 if not message:
5607 if not message:
5596 # we don't translate commit messages
5608 # we don't translate commit messages
5597 message = 'Removed tag %s' % ', '.join(names)
5609 message = 'Removed tag %s' % ', '.join(names)
5598 elif not opts.get('force'):
5610 elif not opts.get('force'):
5599 for n in names:
5611 for n in names:
5600 if n in repo.tags():
5612 if n in repo.tags():
5601 raise util.Abort(_("tag '%s' already exists "
5613 raise util.Abort(_("tag '%s' already exists "
5602 "(use -f to force)") % n)
5614 "(use -f to force)") % n)
5603 if not opts.get('local'):
5615 if not opts.get('local'):
5604 p1, p2 = repo.dirstate.parents()
5616 p1, p2 = repo.dirstate.parents()
5605 if p2 != nullid:
5617 if p2 != nullid:
5606 raise util.Abort(_('uncommitted merge'))
5618 raise util.Abort(_('uncommitted merge'))
5607 bheads = repo.branchheads()
5619 bheads = repo.branchheads()
5608 if not opts.get('force') and bheads and p1 not in bheads:
5620 if not opts.get('force') and bheads and p1 not in bheads:
5609 raise util.Abort(_('not at a branch head (use -f to force)'))
5621 raise util.Abort(_('not at a branch head (use -f to force)'))
5610 r = scmutil.revsingle(repo, rev_).node()
5622 r = scmutil.revsingle(repo, rev_).node()
5611
5623
5612 if not message:
5624 if not message:
5613 # we don't translate commit messages
5625 # we don't translate commit messages
5614 message = ('Added tag %s for changeset %s' %
5626 message = ('Added tag %s for changeset %s' %
5615 (', '.join(names), short(r)))
5627 (', '.join(names), short(r)))
5616
5628
5617 date = opts.get('date')
5629 date = opts.get('date')
5618 if date:
5630 if date:
5619 date = util.parsedate(date)
5631 date = util.parsedate(date)
5620
5632
5621 if opts.get('edit'):
5633 if opts.get('edit'):
5622 message = ui.edit(message, ui.username())
5634 message = ui.edit(message, ui.username())
5623
5635
5624 # don't allow tagging the null rev
5636 # don't allow tagging the null rev
5625 if (not opts.get('remove') and
5637 if (not opts.get('remove') and
5626 scmutil.revsingle(repo, rev_).rev() == nullrev):
5638 scmutil.revsingle(repo, rev_).rev() == nullrev):
5627 raise util.Abort(_("cannot tag null revision"))
5639 raise util.Abort(_("cannot tag null revision"))
5628
5640
5629 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5641 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5630 finally:
5642 finally:
5631 release(lock, wlock)
5643 release(lock, wlock)
5632
5644
5633 @command('tags', [], '')
5645 @command('tags', [], '')
5634 def tags(ui, repo, **opts):
5646 def tags(ui, repo, **opts):
5635 """list repository tags
5647 """list repository tags
5636
5648
5637 This lists both regular and local tags. When the -v/--verbose
5649 This lists both regular and local tags. When the -v/--verbose
5638 switch is used, a third column "local" is printed for local tags.
5650 switch is used, a third column "local" is printed for local tags.
5639
5651
5640 Returns 0 on success.
5652 Returns 0 on success.
5641 """
5653 """
5642
5654
5643 fm = ui.formatter('tags', opts)
5655 fm = ui.formatter('tags', opts)
5644 hexfunc = ui.debugflag and hex or short
5656 hexfunc = ui.debugflag and hex or short
5645 tagtype = ""
5657 tagtype = ""
5646
5658
5647 for t, n in reversed(repo.tagslist()):
5659 for t, n in reversed(repo.tagslist()):
5648 hn = hexfunc(n)
5660 hn = hexfunc(n)
5649 label = 'tags.normal'
5661 label = 'tags.normal'
5650 tagtype = ''
5662 tagtype = ''
5651 if repo.tagtype(t) == 'local':
5663 if repo.tagtype(t) == 'local':
5652 label = 'tags.local'
5664 label = 'tags.local'
5653 tagtype = 'local'
5665 tagtype = 'local'
5654
5666
5655 fm.startitem()
5667 fm.startitem()
5656 fm.write('tag', '%s', t, label=label)
5668 fm.write('tag', '%s', t, label=label)
5657 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5669 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5658 fm.condwrite(not ui.quiet, 'rev id', fmt,
5670 fm.condwrite(not ui.quiet, 'rev id', fmt,
5659 repo.changelog.rev(n), hn, label=label)
5671 repo.changelog.rev(n), hn, label=label)
5660 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5672 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5661 tagtype, label=label)
5673 tagtype, label=label)
5662 fm.plain('\n')
5674 fm.plain('\n')
5663 fm.end()
5675 fm.end()
5664
5676
5665 @command('tip',
5677 @command('tip',
5666 [('p', 'patch', None, _('show patch')),
5678 [('p', 'patch', None, _('show patch')),
5667 ('g', 'git', None, _('use git extended diff format')),
5679 ('g', 'git', None, _('use git extended diff format')),
5668 ] + templateopts,
5680 ] + templateopts,
5669 _('[-p] [-g]'))
5681 _('[-p] [-g]'))
5670 def tip(ui, repo, **opts):
5682 def tip(ui, repo, **opts):
5671 """show the tip revision
5683 """show the tip revision
5672
5684
5673 The tip revision (usually just called the tip) is the changeset
5685 The tip revision (usually just called the tip) is the changeset
5674 most recently added to the repository (and therefore the most
5686 most recently added to the repository (and therefore the most
5675 recently changed head).
5687 recently changed head).
5676
5688
5677 If you have just made a commit, that commit will be the tip. If
5689 If you have just made a commit, that commit will be the tip. If
5678 you have just pulled changes from another repository, the tip of
5690 you have just pulled changes from another repository, the tip of
5679 that repository becomes the current tip. The "tip" tag is special
5691 that repository becomes the current tip. The "tip" tag is special
5680 and cannot be renamed or assigned to a different changeset.
5692 and cannot be renamed or assigned to a different changeset.
5681
5693
5682 Returns 0 on success.
5694 Returns 0 on success.
5683 """
5695 """
5684 displayer = cmdutil.show_changeset(ui, repo, opts)
5696 displayer = cmdutil.show_changeset(ui, repo, opts)
5685 displayer.show(repo['tip'])
5697 displayer.show(repo['tip'])
5686 displayer.close()
5698 displayer.close()
5687
5699
5688 @command('unbundle',
5700 @command('unbundle',
5689 [('u', 'update', None,
5701 [('u', 'update', None,
5690 _('update to new branch head if changesets were unbundled'))],
5702 _('update to new branch head if changesets were unbundled'))],
5691 _('[-u] FILE...'))
5703 _('[-u] FILE...'))
5692 def unbundle(ui, repo, fname1, *fnames, **opts):
5704 def unbundle(ui, repo, fname1, *fnames, **opts):
5693 """apply one or more changegroup files
5705 """apply one or more changegroup files
5694
5706
5695 Apply one or more compressed changegroup files generated by the
5707 Apply one or more compressed changegroup files generated by the
5696 bundle command.
5708 bundle command.
5697
5709
5698 Returns 0 on success, 1 if an update has unresolved files.
5710 Returns 0 on success, 1 if an update has unresolved files.
5699 """
5711 """
5700 fnames = (fname1,) + fnames
5712 fnames = (fname1,) + fnames
5701
5713
5702 lock = repo.lock()
5714 lock = repo.lock()
5703 wc = repo['.']
5715 wc = repo['.']
5704 try:
5716 try:
5705 for fname in fnames:
5717 for fname in fnames:
5706 f = hg.openpath(ui, fname)
5718 f = hg.openpath(ui, fname)
5707 gen = changegroup.readbundle(f, fname)
5719 gen = changegroup.readbundle(f, fname)
5708 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5720 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5709 finally:
5721 finally:
5710 lock.release()
5722 lock.release()
5711 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5723 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5712 return postincoming(ui, repo, modheads, opts.get('update'), None)
5724 return postincoming(ui, repo, modheads, opts.get('update'), None)
5713
5725
5714 @command('^update|up|checkout|co',
5726 @command('^update|up|checkout|co',
5715 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5727 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5716 ('c', 'check', None,
5728 ('c', 'check', None,
5717 _('update across branches if no uncommitted changes')),
5729 _('update across branches if no uncommitted changes')),
5718 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5730 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5719 ('r', 'rev', '', _('revision'), _('REV'))],
5731 ('r', 'rev', '', _('revision'), _('REV'))],
5720 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5732 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5721 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5733 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5722 """update working directory (or switch revisions)
5734 """update working directory (or switch revisions)
5723
5735
5724 Update the repository's working directory to the specified
5736 Update the repository's working directory to the specified
5725 changeset. If no changeset is specified, update to the tip of the
5737 changeset. If no changeset is specified, update to the tip of the
5726 current named branch and move the current bookmark (see :hg:`help
5738 current named branch and move the current bookmark (see :hg:`help
5727 bookmarks`).
5739 bookmarks`).
5728
5740
5729 Update sets the working directory's parent revision to the specified
5741 Update sets the working directory's parent revision to the specified
5730 changeset (see :hg:`help parents`).
5742 changeset (see :hg:`help parents`).
5731
5743
5732 If the changeset is not a descendant or ancestor of the working
5744 If the changeset is not a descendant or ancestor of the working
5733 directory's parent, the update is aborted. With the -c/--check
5745 directory's parent, the update is aborted. With the -c/--check
5734 option, the working directory is checked for uncommitted changes; if
5746 option, the working directory is checked for uncommitted changes; if
5735 none are found, the working directory is updated to the specified
5747 none are found, the working directory is updated to the specified
5736 changeset.
5748 changeset.
5737
5749
5738 .. container:: verbose
5750 .. container:: verbose
5739
5751
5740 The following rules apply when the working directory contains
5752 The following rules apply when the working directory contains
5741 uncommitted changes:
5753 uncommitted changes:
5742
5754
5743 1. If neither -c/--check nor -C/--clean is specified, and if
5755 1. If neither -c/--check nor -C/--clean is specified, and if
5744 the requested changeset is an ancestor or descendant of
5756 the requested changeset is an ancestor or descendant of
5745 the working directory's parent, the uncommitted changes
5757 the working directory's parent, the uncommitted changes
5746 are merged into the requested changeset and the merged
5758 are merged into the requested changeset and the merged
5747 result is left uncommitted. If the requested changeset is
5759 result is left uncommitted. If the requested changeset is
5748 not an ancestor or descendant (that is, it is on another
5760 not an ancestor or descendant (that is, it is on another
5749 branch), the update is aborted and the uncommitted changes
5761 branch), the update is aborted and the uncommitted changes
5750 are preserved.
5762 are preserved.
5751
5763
5752 2. With the -c/--check option, the update is aborted and the
5764 2. With the -c/--check option, the update is aborted and the
5753 uncommitted changes are preserved.
5765 uncommitted changes are preserved.
5754
5766
5755 3. With the -C/--clean option, uncommitted changes are discarded and
5767 3. With the -C/--clean option, uncommitted changes are discarded and
5756 the working directory is updated to the requested changeset.
5768 the working directory is updated to the requested changeset.
5757
5769
5758 To cancel an uncommitted merge (and lose your changes), use
5770 To cancel an uncommitted merge (and lose your changes), use
5759 :hg:`update --clean .`.
5771 :hg:`update --clean .`.
5760
5772
5761 Use null as the changeset to remove the working directory (like
5773 Use null as the changeset to remove the working directory (like
5762 :hg:`clone -U`).
5774 :hg:`clone -U`).
5763
5775
5764 If you want to revert just one file to an older revision, use
5776 If you want to revert just one file to an older revision, use
5765 :hg:`revert [-r REV] NAME`.
5777 :hg:`revert [-r REV] NAME`.
5766
5778
5767 See :hg:`help dates` for a list of formats valid for -d/--date.
5779 See :hg:`help dates` for a list of formats valid for -d/--date.
5768
5780
5769 Returns 0 on success, 1 if there are unresolved files.
5781 Returns 0 on success, 1 if there are unresolved files.
5770 """
5782 """
5771 if rev and node:
5783 if rev and node:
5772 raise util.Abort(_("please specify just one revision"))
5784 raise util.Abort(_("please specify just one revision"))
5773
5785
5774 if rev is None or rev == '':
5786 if rev is None or rev == '':
5775 rev = node
5787 rev = node
5776
5788
5777 # with no argument, we also move the current bookmark, if any
5789 # with no argument, we also move the current bookmark, if any
5778 movemarkfrom = None
5790 movemarkfrom = None
5779 if rev is None:
5791 if rev is None:
5780 curmark = repo._bookmarkcurrent
5792 curmark = repo._bookmarkcurrent
5781 if bookmarks.iscurrent(repo):
5793 if bookmarks.iscurrent(repo):
5782 movemarkfrom = repo['.'].node()
5794 movemarkfrom = repo['.'].node()
5783 elif curmark:
5795 elif curmark:
5784 ui.status(_("updating to active bookmark %s\n") % curmark)
5796 ui.status(_("updating to active bookmark %s\n") % curmark)
5785 rev = curmark
5797 rev = curmark
5786
5798
5787 # if we defined a bookmark, we have to remember the original bookmark name
5799 # if we defined a bookmark, we have to remember the original bookmark name
5788 brev = rev
5800 brev = rev
5789 rev = scmutil.revsingle(repo, rev, rev).rev()
5801 rev = scmutil.revsingle(repo, rev, rev).rev()
5790
5802
5791 if check and clean:
5803 if check and clean:
5792 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5804 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5793
5805
5794 if date:
5806 if date:
5795 if rev is not None:
5807 if rev is not None:
5796 raise util.Abort(_("you can't specify a revision and a date"))
5808 raise util.Abort(_("you can't specify a revision and a date"))
5797 rev = cmdutil.finddate(ui, repo, date)
5809 rev = cmdutil.finddate(ui, repo, date)
5798
5810
5799 if check:
5811 if check:
5800 c = repo[None]
5812 c = repo[None]
5801 if c.dirty(merge=False, branch=False, missing=True):
5813 if c.dirty(merge=False, branch=False, missing=True):
5802 raise util.Abort(_("uncommitted local changes"))
5814 raise util.Abort(_("uncommitted local changes"))
5803 if rev is None:
5815 if rev is None:
5804 rev = repo[repo[None].branch()].rev()
5816 rev = repo[repo[None].branch()].rev()
5805 mergemod._checkunknown(repo, repo[None], repo[rev])
5817 mergemod._checkunknown(repo, repo[None], repo[rev])
5806
5818
5807 if clean:
5819 if clean:
5808 ret = hg.clean(repo, rev)
5820 ret = hg.clean(repo, rev)
5809 else:
5821 else:
5810 ret = hg.update(repo, rev)
5822 ret = hg.update(repo, rev)
5811
5823
5812 if not ret and movemarkfrom:
5824 if not ret and movemarkfrom:
5813 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5825 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5814 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5826 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5815 elif brev in repo._bookmarks:
5827 elif brev in repo._bookmarks:
5816 bookmarks.setcurrent(repo, brev)
5828 bookmarks.setcurrent(repo, brev)
5817 elif brev:
5829 elif brev:
5818 bookmarks.unsetcurrent(repo)
5830 bookmarks.unsetcurrent(repo)
5819
5831
5820 return ret
5832 return ret
5821
5833
5822 @command('verify', [])
5834 @command('verify', [])
5823 def verify(ui, repo):
5835 def verify(ui, repo):
5824 """verify the integrity of the repository
5836 """verify the integrity of the repository
5825
5837
5826 Verify the integrity of the current repository.
5838 Verify the integrity of the current repository.
5827
5839
5828 This will perform an extensive check of the repository's
5840 This will perform an extensive check of the repository's
5829 integrity, validating the hashes and checksums of each entry in
5841 integrity, validating the hashes and checksums of each entry in
5830 the changelog, manifest, and tracked files, as well as the
5842 the changelog, manifest, and tracked files, as well as the
5831 integrity of their crosslinks and indices.
5843 integrity of their crosslinks and indices.
5832
5844
5833 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5845 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5834 for more information about recovery from corruption of the
5846 for more information about recovery from corruption of the
5835 repository.
5847 repository.
5836
5848
5837 Returns 0 on success, 1 if errors are encountered.
5849 Returns 0 on success, 1 if errors are encountered.
5838 """
5850 """
5839 return hg.verify(repo)
5851 return hg.verify(repo)
5840
5852
5841 @command('version', [])
5853 @command('version', [])
5842 def version_(ui):
5854 def version_(ui):
5843 """output version and copyright information"""
5855 """output version and copyright information"""
5844 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5856 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5845 % util.version())
5857 % util.version())
5846 ui.status(_(
5858 ui.status(_(
5847 "(see http://mercurial.selenic.com for more information)\n"
5859 "(see http://mercurial.selenic.com for more information)\n"
5848 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5860 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5849 "This is free software; see the source for copying conditions. "
5861 "This is free software; see the source for copying conditions. "
5850 "There is NO\nwarranty; "
5862 "There is NO\nwarranty; "
5851 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5863 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5852 ))
5864 ))
5853
5865
5854 norepo = ("clone init version help debugcommands debugcomplete"
5866 norepo = ("clone init version help debugcommands debugcomplete"
5855 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5867 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5856 " debugknown debuggetbundle debugbundle")
5868 " debugknown debuggetbundle debugbundle")
5857 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5869 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5858 " debugdata debugindex debugindexdot debugrevlog")
5870 " debugdata debugindex debugindexdot debugrevlog")
5859 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5871 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5860 " remove resolve status debugwalk")
5872 " remove resolve status debugwalk")
@@ -1,188 +1,191 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 set bookmark X
8 set bookmark X
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmark
14 $ hg bookmark
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmark --color=always
20 > bookmark --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 update to bookmark X
23 update to bookmark X
24
24
25 $ hg update X
25 $ hg update X
26 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
27
27
28 list bookmarks
28 list bookmarks
29
29
30 $ hg bookmarks
30 $ hg bookmarks
31 * X -1:000000000000
31 * X -1:000000000000
32
32
33 rename
33 rename
34
34
35 $ hg bookmark -m X Z
35 $ hg bookmark -m X Z
36
36
37 list bookmarks
37 list bookmarks
38
38
39 $ cat .hg/bookmarks.current
39 $ cat .hg/bookmarks.current
40 Z (no-eol)
40 Z (no-eol)
41 $ cat .hg/bookmarks
41 $ cat .hg/bookmarks
42 0000000000000000000000000000000000000000 Z
42 0000000000000000000000000000000000000000 Z
43 $ hg bookmarks
43 $ hg bookmarks
44 * Z -1:000000000000
44 * Z -1:000000000000
45
45
46 new bookmark Y
46 new bookmarks X and Y, first one made active
47
47
48 $ hg bookmark Y
48 $ hg bookmark Y X
49
49
50 list bookmarks
50 list bookmarks
51
51
52 $ hg bookmark
52 $ hg bookmark
53 X -1:000000000000
53 * Y -1:000000000000
54 * Y -1:000000000000
54 Z -1:000000000000
55 Z -1:000000000000
55
56
57 $ hg bookmark -d X
58
56 commit
59 commit
57
60
58 $ echo 'b' > b
61 $ echo 'b' > b
59 $ hg add b
62 $ hg add b
60 $ hg commit -m'test'
63 $ hg commit -m'test'
61
64
62 list bookmarks
65 list bookmarks
63
66
64 $ hg bookmark
67 $ hg bookmark
65 * Y 0:719295282060
68 * Y 0:719295282060
66 Z -1:000000000000
69 Z -1:000000000000
67
70
68 Verify that switching to Z updates the current bookmark:
71 Verify that switching to Z updates the current bookmark:
69 $ hg update Z
72 $ hg update Z
70 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
73 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
71 $ hg bookmark
74 $ hg bookmark
72 Y 0:719295282060
75 Y 0:719295282060
73 * Z -1:000000000000
76 * Z -1:000000000000
74
77
75 Switch back to Y for the remaining tests in this file:
78 Switch back to Y for the remaining tests in this file:
76 $ hg update Y
79 $ hg update Y
77 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
78
81
79 delete bookmarks
82 delete bookmarks
80
83
81 $ hg bookmark -d Y
84 $ hg bookmark -d Y
82 $ hg bookmark -d Z
85 $ hg bookmark -d Z
83
86
84 list bookmarks
87 list bookmarks
85
88
86 $ hg bookmark
89 $ hg bookmark
87 no bookmarks set
90 no bookmarks set
88
91
89 update to tip
92 update to tip
90
93
91 $ hg update tip
94 $ hg update tip
92 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
93
96
94 set bookmark Y using -r . but make sure that the active
97 set bookmark Y using -r . but make sure that the active
95 bookmark is not activated
98 bookmark is not activated
96
99
97 $ hg bookmark -r . Y
100 $ hg bookmark -r . Y
98
101
99 list bookmarks, Y should not be active
102 list bookmarks, Y should not be active
100
103
101 $ hg bookmark
104 $ hg bookmark
102 Y 0:719295282060
105 Y 0:719295282060
103
106
104 now, activate Y
107 now, activate Y
105
108
106 $ hg up -q Y
109 $ hg up -q Y
107
110
108 set bookmark Z using -i
111 set bookmark Z using -i
109
112
110 $ hg bookmark -r . -i Z
113 $ hg bookmark -r . -i Z
111 $ hg bookmarks
114 $ hg bookmarks
112 * Y 0:719295282060
115 * Y 0:719295282060
113 Z 0:719295282060
116 Z 0:719295282060
114
117
115 deactivate current bookmark using -i
118 deactivate current bookmark using -i
116
119
117 $ hg bookmark -i Y
120 $ hg bookmark -i Y
118 $ hg bookmarks
121 $ hg bookmarks
119 Y 0:719295282060
122 Y 0:719295282060
120 Z 0:719295282060
123 Z 0:719295282060
121
124
122 $ hg up -q Y
125 $ hg up -q Y
123 $ hg bookmark -i
126 $ hg bookmark -i
124 $ hg bookmarks
127 $ hg bookmarks
125 Y 0:719295282060
128 Y 0:719295282060
126 Z 0:719295282060
129 Z 0:719295282060
127 $ hg bookmark -i
130 $ hg bookmark -i
128 no active bookmark
131 no active bookmark
129 $ hg up -q Y
132 $ hg up -q Y
130 $ hg bookmarks
133 $ hg bookmarks
131 * Y 0:719295282060
134 * Y 0:719295282060
132 Z 0:719295282060
135 Z 0:719295282060
133
136
134 deactivate current bookmark while renaming
137 deactivate current bookmark while renaming
135
138
136 $ hg bookmark -i -m Y X
139 $ hg bookmark -i -m Y X
137 $ hg bookmarks
140 $ hg bookmarks
138 X 0:719295282060
141 X 0:719295282060
139 Z 0:719295282060
142 Z 0:719295282060
140
143
141 bare update moves the active bookmark forward and clear the divergent bookmarks
144 bare update moves the active bookmark forward and clear the divergent bookmarks
142
145
143 $ echo a > a
146 $ echo a > a
144 $ hg ci -Am1
147 $ hg ci -Am1
145 adding a
148 adding a
146 $ echo b >> a
149 $ echo b >> a
147 $ hg ci -Am2
150 $ hg ci -Am2
148 $ hg bookmark X@1 -r 1
151 $ hg bookmark X@1 -r 1
149 $ hg bookmark X@2 -r 2
152 $ hg bookmark X@2 -r 2
150 $ hg update X
153 $ hg update X
151 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
154 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
152 $ hg bookmarks
155 $ hg bookmarks
153 * X 0:719295282060
156 * X 0:719295282060
154 X@1 1:cc586d725fbe
157 X@1 1:cc586d725fbe
155 X@2 2:49e1c4e84c58
158 X@2 2:49e1c4e84c58
156 Z 0:719295282060
159 Z 0:719295282060
157 $ hg update
160 $ hg update
158 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 updating bookmark X
162 updating bookmark X
160 $ hg bookmarks
163 $ hg bookmarks
161 * X 2:49e1c4e84c58
164 * X 2:49e1c4e84c58
162 Z 0:719295282060
165 Z 0:719295282060
163
166
164 test deleting .hg/bookmarks.current when explicitly updating
167 test deleting .hg/bookmarks.current when explicitly updating
165 to a revision
168 to a revision
166
169
167 $ echo a >> b
170 $ echo a >> b
168 $ hg ci -m.
171 $ hg ci -m.
169 $ hg up -q X
172 $ hg up -q X
170 $ test -f .hg/bookmarks.current
173 $ test -f .hg/bookmarks.current
171
174
172 try to update to it again to make sure we don't
175 try to update to it again to make sure we don't
173 set and then unset it
176 set and then unset it
174
177
175 $ hg up -q X
178 $ hg up -q X
176 $ test -f .hg/bookmarks.current
179 $ test -f .hg/bookmarks.current
177
180
178 $ hg up -q 1
181 $ hg up -q 1
179 $ test -f .hg/bookmarks.current
182 $ test -f .hg/bookmarks.current
180 [1]
183 [1]
181
184
182 when a bookmark is active, hg up -r . is
185 when a bookmark is active, hg up -r . is
183 analogus to hg book -i <active bookmark>
186 analogus to hg book -i <active bookmark>
184
187
185 $ hg up -q X
188 $ hg up -q X
186 $ hg up -q .
189 $ hg up -q .
187 $ test -f .hg/bookmarks.current
190 $ test -f .hg/bookmarks.current
188 [1]
191 [1]
@@ -1,630 +1,634 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0, command should work even with ui.strict on
43 second bookmark for rev 0, command should work even with ui.strict on
44
44
45 $ hg --config ui.strict=1 bookmark X2
45 $ hg --config ui.strict=1 bookmark X2
46
46
47 bookmark rev -1 again
47 bookmark rev -1 again
48
48
49 $ hg bookmark -r null Y
49 $ hg bookmark -r null Y
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmarks
53 $ hg bookmarks
54 X 0:f7b1eb17ad24
54 X 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
56 Y -1:000000000000
56 Y -1:000000000000
57
57
58 $ echo b > b
58 $ echo b > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m 1
60 $ hg commit -m 1
61
61
62 bookmarks revset
62 bookmarks revset
63
63
64 $ hg log -r 'bookmark()'
64 $ hg log -r 'bookmark()'
65 changeset: 0:f7b1eb17ad24
65 changeset: 0:f7b1eb17ad24
66 bookmark: X
66 bookmark: X
67 user: test
67 user: test
68 date: Thu Jan 01 00:00:00 1970 +0000
68 date: Thu Jan 01 00:00:00 1970 +0000
69 summary: 0
69 summary: 0
70
70
71 changeset: 1:925d80f479bb
71 changeset: 1:925d80f479bb
72 bookmark: X2
72 bookmark: X2
73 tag: tip
73 tag: tip
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: 1
76 summary: 1
77
77
78 $ hg log -r 'bookmark(Y)'
78 $ hg log -r 'bookmark(Y)'
79 $ hg log -r 'bookmark(X2)'
79 $ hg log -r 'bookmark(X2)'
80 changeset: 1:925d80f479bb
80 changeset: 1:925d80f479bb
81 bookmark: X2
81 bookmark: X2
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: 1
85 summary: 1
86
86
87 $ hg log -r 'bookmark("re:X")'
87 $ hg log -r 'bookmark("re:X")'
88 changeset: 0:f7b1eb17ad24
88 changeset: 0:f7b1eb17ad24
89 bookmark: X
89 bookmark: X
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:00 1970 +0000
91 date: Thu Jan 01 00:00:00 1970 +0000
92 summary: 0
92 summary: 0
93
93
94 changeset: 1:925d80f479bb
94 changeset: 1:925d80f479bb
95 bookmark: X2
95 bookmark: X2
96 tag: tip
96 tag: tip
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:00 1970 +0000
98 date: Thu Jan 01 00:00:00 1970 +0000
99 summary: 1
99 summary: 1
100
100
101 $ hg log -r 'bookmark(unknown)'
101 $ hg log -r 'bookmark(unknown)'
102 abort: bookmark 'unknown' does not exist
102 abort: bookmark 'unknown' does not exist
103 [255]
103 [255]
104
104
105 $ hg help revsets | grep 'bookmark('
105 $ hg help revsets | grep 'bookmark('
106 "bookmark([name])"
106 "bookmark([name])"
107
107
108 bookmarks X and X2 moved to rev 1, Y at rev -1
108 bookmarks X and X2 moved to rev 1, Y at rev -1
109
109
110 $ hg bookmarks
110 $ hg bookmarks
111 X 0:f7b1eb17ad24
111 X 0:f7b1eb17ad24
112 * X2 1:925d80f479bb
112 * X2 1:925d80f479bb
113 Y -1:000000000000
113 Y -1:000000000000
114
114
115 bookmark rev 0 again
115 bookmark rev 0 again
116
116
117 $ hg bookmark -r 0 Z
117 $ hg bookmark -r 0 Z
118
118
119 $ hg update X
119 $ hg update X
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 $ echo c > c
121 $ echo c > c
122 $ hg add c
122 $ hg add c
123 $ hg commit -m 2
123 $ hg commit -m 2
124 created new head
124 created new head
125
125
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
127
127
128 $ hg bookmarks
128 $ hg bookmarks
129 * X 2:db815d6d32e6
129 * X 2:db815d6d32e6
130 X2 1:925d80f479bb
130 X2 1:925d80f479bb
131 Y -1:000000000000
131 Y -1:000000000000
132 Z 0:f7b1eb17ad24
132 Z 0:f7b1eb17ad24
133
133
134 rename nonexistent bookmark
134 rename nonexistent bookmark
135
135
136 $ hg bookmark -m A B
136 $ hg bookmark -m A B
137 abort: bookmark 'A' does not exist
137 abort: bookmark 'A' does not exist
138 [255]
138 [255]
139
139
140 rename to existent bookmark
140 rename to existent bookmark
141
141
142 $ hg bookmark -m X Y
142 $ hg bookmark -m X Y
143 abort: bookmark 'Y' already exists (use -f to force)
143 abort: bookmark 'Y' already exists (use -f to force)
144 [255]
144 [255]
145
145
146 force rename to existent bookmark
146 force rename to existent bookmark
147
147
148 $ hg bookmark -f -m X Y
148 $ hg bookmark -f -m X Y
149
149
150 list bookmarks
150 list bookmarks
151
151
152 $ hg bookmark
152 $ hg bookmark
153 X2 1:925d80f479bb
153 X2 1:925d80f479bb
154 * Y 2:db815d6d32e6
154 * Y 2:db815d6d32e6
155 Z 0:f7b1eb17ad24
155 Z 0:f7b1eb17ad24
156
156
157 bookmarks from a revset
157 bookmarks from a revset
158 $ hg bookmark -r '.^1' REVSET
158 $ hg bookmark -r '.^1' REVSET
159 $ hg bookmark -r ':tip' TIP
159 $ hg bookmark -r ':tip' TIP
160 $ hg up -q TIP
160 $ hg up -q TIP
161 $ hg bookmarks
161 $ hg bookmarks
162 REVSET 0:f7b1eb17ad24
162 REVSET 0:f7b1eb17ad24
163 * TIP 2:db815d6d32e6
163 * TIP 2:db815d6d32e6
164 X2 1:925d80f479bb
164 X2 1:925d80f479bb
165 Y 2:db815d6d32e6
165 Y 2:db815d6d32e6
166 Z 0:f7b1eb17ad24
166 Z 0:f7b1eb17ad24
167
167
168 $ hg bookmark -d REVSET
168 $ hg bookmark -d REVSET
169 $ hg bookmark -d TIP
169 $ hg bookmark -d TIP
170
170
171 rename without new name
171 rename without new name or multiple names
172
172
173 $ hg bookmark -m Y
173 $ hg bookmark -m Y
174 abort: new bookmark name required
174 abort: new bookmark name required
175 [255]
175 [255]
176 $ hg bookmark -m Y Y2 Y3
177 abort: only one new bookmark name allowed
178 [255]
176
179
177 delete without name
180 delete without name
178
181
179 $ hg bookmark -d
182 $ hg bookmark -d
180 abort: bookmark name required
183 abort: bookmark name required
181 [255]
184 [255]
182
185
183 delete nonexistent bookmark
186 delete nonexistent bookmark
184
187
185 $ hg bookmark -d A
188 $ hg bookmark -d A
186 abort: bookmark 'A' does not exist
189 abort: bookmark 'A' does not exist
187 [255]
190 [255]
188
191
189 bookmark name with spaces should be stripped
192 bookmark name with spaces should be stripped
190
193
191 $ hg bookmark ' x y '
194 $ hg bookmark ' x y '
192
195
193 list bookmarks
196 list bookmarks
194
197
195 $ hg bookmarks
198 $ hg bookmarks
196 X2 1:925d80f479bb
199 X2 1:925d80f479bb
197 Y 2:db815d6d32e6
200 Y 2:db815d6d32e6
198 Z 0:f7b1eb17ad24
201 Z 0:f7b1eb17ad24
199 * x y 2:db815d6d32e6
202 * x y 2:db815d6d32e6
200
203
201 look up stripped bookmark name
204 look up stripped bookmark name
202
205
203 $ hg log -r '"x y"'
206 $ hg log -r '"x y"'
204 changeset: 2:db815d6d32e6
207 changeset: 2:db815d6d32e6
205 bookmark: Y
208 bookmark: Y
206 bookmark: x y
209 bookmark: x y
207 tag: tip
210 tag: tip
208 parent: 0:f7b1eb17ad24
211 parent: 0:f7b1eb17ad24
209 user: test
212 user: test
210 date: Thu Jan 01 00:00:00 1970 +0000
213 date: Thu Jan 01 00:00:00 1970 +0000
211 summary: 2
214 summary: 2
212
215
213
216
214 reject bookmark name with newline
217 reject bookmark name with newline
215
218
216 $ hg bookmark '
219 $ hg bookmark '
217 > '
220 > '
218 abort: bookmark names cannot consist entirely of whitespace
221 abort: bookmark names cannot consist entirely of whitespace
219 [255]
222 [255]
220
223
221 $ hg bookmark -m Z '
224 $ hg bookmark -m Z '
222 > '
225 > '
223 abort: bookmark names cannot consist entirely of whitespace
226 abort: bookmark names cannot consist entirely of whitespace
224 [255]
227 [255]
225
228
226 bookmark with reserved name
229 bookmark with reserved name
227
230
228 $ hg bookmark tip
231 $ hg bookmark tip
229 abort: the name 'tip' is reserved
232 abort: the name 'tip' is reserved
230 [255]
233 [255]
231
234
232 $ hg bookmark .
235 $ hg bookmark .
233 abort: the name '.' is reserved
236 abort: the name '.' is reserved
234 [255]
237 [255]
235
238
236 $ hg bookmark null
239 $ hg bookmark null
237 abort: the name 'null' is reserved
240 abort: the name 'null' is reserved
238 [255]
241 [255]
239
242
240
243
241 bookmark with existing name
244 bookmark with existing name
242
245
243 $ hg bookmark X2
246 $ hg bookmark X2
244 abort: bookmark 'X2' already exists (use -f to force)
247 abort: bookmark 'X2' already exists (use -f to force)
245 [255]
248 [255]
246
249
247 $ hg bookmark -m Y Z
250 $ hg bookmark -m Y Z
248 abort: bookmark 'Z' already exists (use -f to force)
251 abort: bookmark 'Z' already exists (use -f to force)
249 [255]
252 [255]
250
253
251 bookmark with name of branch
254 bookmark with name of branch
252
255
253 $ hg bookmark default
256 $ hg bookmark default
254 abort: a bookmark cannot have the name of an existing branch
257 abort: a bookmark cannot have the name of an existing branch
255 [255]
258 [255]
256
259
257 $ hg bookmark -m Y default
260 $ hg bookmark -m Y default
258 abort: a bookmark cannot have the name of an existing branch
261 abort: a bookmark cannot have the name of an existing branch
259 [255]
262 [255]
260
263
261 bookmark with integer name
264 bookmark with integer name
262
265
263 $ hg bookmark 10
266 $ hg bookmark 10
264 abort: cannot use an integer as a name
267 abort: cannot use an integer as a name
265 [255]
268 [255]
266
269
267 incompatible options
270 incompatible options
268
271
269 $ hg bookmark -m Y -d Z
272 $ hg bookmark -m Y -d Z
270 abort: --delete and --rename are incompatible
273 abort: --delete and --rename are incompatible
271 [255]
274 [255]
272
275
273 $ hg bookmark -r 1 -d Z
276 $ hg bookmark -r 1 -d Z
274 abort: --rev is incompatible with --delete
277 abort: --rev is incompatible with --delete
275 [255]
278 [255]
276
279
277 $ hg bookmark -r 1 -m Z Y
280 $ hg bookmark -r 1 -m Z Y
278 abort: --rev is incompatible with --rename
281 abort: --rev is incompatible with --rename
279 [255]
282 [255]
280
283
281 force bookmark with existing name
284 force bookmark with existing name
282
285
283 $ hg bookmark -f X2
286 $ hg bookmark -f X2
284
287
285 force bookmark back to where it was, should deactivate it
288 force bookmark back to where it was, should deactivate it
286
289
287 $ hg bookmark -fr1 X2
290 $ hg bookmark -fr1 X2
288 $ hg bookmarks
291 $ hg bookmarks
289 X2 1:925d80f479bb
292 X2 1:925d80f479bb
290 Y 2:db815d6d32e6
293 Y 2:db815d6d32e6
291 Z 0:f7b1eb17ad24
294 Z 0:f7b1eb17ad24
292 x y 2:db815d6d32e6
295 x y 2:db815d6d32e6
293
296
294 forward bookmark to descendant without --force
297 forward bookmark to descendant without --force
295
298
296 $ hg bookmark Z
299 $ hg bookmark Z
297 moving bookmark 'Z' forward from f7b1eb17ad24
300 moving bookmark 'Z' forward from f7b1eb17ad24
298
301
299 list bookmarks
302 list bookmarks
300
303
301 $ hg bookmark
304 $ hg bookmark
302 X2 1:925d80f479bb
305 X2 1:925d80f479bb
303 Y 2:db815d6d32e6
306 Y 2:db815d6d32e6
304 * Z 2:db815d6d32e6
307 * Z 2:db815d6d32e6
305 x y 2:db815d6d32e6
308 x y 2:db815d6d32e6
306
309
307 revision but no bookmark name
310 revision but no bookmark name
308
311
309 $ hg bookmark -r .
312 $ hg bookmark -r .
310 abort: bookmark name required
313 abort: bookmark name required
311 [255]
314 [255]
312
315
313 bookmark name with whitespace only
316 bookmark name with whitespace only
314
317
315 $ hg bookmark ' '
318 $ hg bookmark ' '
316 abort: bookmark names cannot consist entirely of whitespace
319 abort: bookmark names cannot consist entirely of whitespace
317 [255]
320 [255]
318
321
319 $ hg bookmark -m Y ' '
322 $ hg bookmark -m Y ' '
320 abort: bookmark names cannot consist entirely of whitespace
323 abort: bookmark names cannot consist entirely of whitespace
321 [255]
324 [255]
322
325
323 invalid bookmark
326 invalid bookmark
324
327
325 $ hg bookmark 'foo:bar'
328 $ hg bookmark 'foo:bar'
326 abort: ':' cannot be used in a name
329 abort: ':' cannot be used in a name
327 [255]
330 [255]
328
331
329 $ hg bookmark 'foo
332 $ hg bookmark 'foo
330 > bar'
333 > bar'
331 abort: '\n' cannot be used in a name
334 abort: '\n' cannot be used in a name
332 [255]
335 [255]
333
336
334 the bookmark extension should be ignored now that it is part of core
337 the bookmark extension should be ignored now that it is part of core
335
338
336 $ echo "[extensions]" >> $HGRCPATH
339 $ echo "[extensions]" >> $HGRCPATH
337 $ echo "bookmarks=" >> $HGRCPATH
340 $ echo "bookmarks=" >> $HGRCPATH
338 $ hg bookmarks
341 $ hg bookmarks
339 X2 1:925d80f479bb
342 X2 1:925d80f479bb
340 Y 2:db815d6d32e6
343 Y 2:db815d6d32e6
341 * Z 2:db815d6d32e6
344 * Z 2:db815d6d32e6
342 x y 2:db815d6d32e6
345 x y 2:db815d6d32e6
343
346
344 test summary
347 test summary
345
348
346 $ hg summary
349 $ hg summary
347 parent: 2:db815d6d32e6 tip
350 parent: 2:db815d6d32e6 tip
348 2
351 2
349 branch: default
352 branch: default
350 bookmarks: *Z Y x y
353 bookmarks: *Z Y x y
351 commit: (clean)
354 commit: (clean)
352 update: 1 new changesets, 2 branch heads (merge)
355 update: 1 new changesets, 2 branch heads (merge)
353
356
354 test id
357 test id
355
358
356 $ hg id
359 $ hg id
357 db815d6d32e6 tip Y/Z/x y
360 db815d6d32e6 tip Y/Z/x y
358
361
359 test rollback
362 test rollback
360
363
361 $ echo foo > f1
364 $ echo foo > f1
362 $ hg ci -Amr
365 $ hg ci -Amr
363 adding f1
366 adding f1
364 $ hg bookmark -f Y -r 1
367 $ hg bookmark -f Y -r 1
365 $ hg bookmark -f Z -r 1
368 $ hg bookmark -f Z -r 1
366 $ hg rollback
369 $ hg rollback
367 repository tip rolled back to revision 2 (undo commit)
370 repository tip rolled back to revision 2 (undo commit)
368 working directory now based on revision 2
371 working directory now based on revision 2
369 $ hg bookmarks
372 $ hg bookmarks
370 X2 1:925d80f479bb
373 X2 1:925d80f479bb
371 Y 2:db815d6d32e6
374 Y 2:db815d6d32e6
372 Z 2:db815d6d32e6
375 Z 2:db815d6d32e6
373 x y 2:db815d6d32e6
376 x y 2:db815d6d32e6
374
377
375 activate bookmark on working dir parent without --force
378 activate bookmark on working dir parent without --force
376
379
377 $ hg bookmark --inactive Z
380 $ hg bookmark --inactive Z
378 $ hg bookmark Z
381 $ hg bookmark Z
379
382
380 test clone
383 test clone
381
384
382 $ hg bookmark -r 2 -i @
385 $ hg bookmark -r 2 -i @
383 $ hg bookmark -r 2 -i a@
386 $ hg bookmark -r 2 -i a@
384 $ hg bookmarks
387 $ hg bookmarks
385 @ 2:db815d6d32e6
388 @ 2:db815d6d32e6
386 X2 1:925d80f479bb
389 X2 1:925d80f479bb
387 Y 2:db815d6d32e6
390 Y 2:db815d6d32e6
388 * Z 2:db815d6d32e6
391 * Z 2:db815d6d32e6
389 a@ 2:db815d6d32e6
392 a@ 2:db815d6d32e6
390 x y 2:db815d6d32e6
393 x y 2:db815d6d32e6
391 $ hg clone . cloned-bookmarks
394 $ hg clone . cloned-bookmarks
392 updating to bookmark @
395 updating to bookmark @
393 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
396 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
394 $ hg -R cloned-bookmarks bookmarks
397 $ hg -R cloned-bookmarks bookmarks
395 * @ 2:db815d6d32e6
398 * @ 2:db815d6d32e6
396 X2 1:925d80f479bb
399 X2 1:925d80f479bb
397 Y 2:db815d6d32e6
400 Y 2:db815d6d32e6
398 Z 2:db815d6d32e6
401 Z 2:db815d6d32e6
399 a@ 2:db815d6d32e6
402 a@ 2:db815d6d32e6
400 x y 2:db815d6d32e6
403 x y 2:db815d6d32e6
401
404
402 test clone with pull protocol
405 test clone with pull protocol
403
406
404 $ hg clone --pull . cloned-bookmarks-pull
407 $ hg clone --pull . cloned-bookmarks-pull
405 requesting all changes
408 requesting all changes
406 adding changesets
409 adding changesets
407 adding manifests
410 adding manifests
408 adding file changes
411 adding file changes
409 added 3 changesets with 3 changes to 3 files (+1 heads)
412 added 3 changesets with 3 changes to 3 files (+1 heads)
410 updating to bookmark @
413 updating to bookmark @
411 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
412 $ hg -R cloned-bookmarks-pull bookmarks
415 $ hg -R cloned-bookmarks-pull bookmarks
413 * @ 2:db815d6d32e6
416 * @ 2:db815d6d32e6
414 X2 1:925d80f479bb
417 X2 1:925d80f479bb
415 Y 2:db815d6d32e6
418 Y 2:db815d6d32e6
416 Z 2:db815d6d32e6
419 Z 2:db815d6d32e6
417 a@ 2:db815d6d32e6
420 a@ 2:db815d6d32e6
418 x y 2:db815d6d32e6
421 x y 2:db815d6d32e6
419
422
420 $ hg bookmark -d @
423 delete multiple bookmarks at once
421 $ hg bookmark -d a@
424
425 $ hg bookmark -d @ a@
422
426
423 test clone with a bookmark named "default" (issue3677)
427 test clone with a bookmark named "default" (issue3677)
424
428
425 $ hg bookmark -r 1 -f -i default
429 $ hg bookmark -r 1 -f -i default
426 $ hg clone . cloned-bookmark-default
430 $ hg clone . cloned-bookmark-default
427 updating to branch default
431 updating to branch default
428 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 $ hg -R cloned-bookmark-default bookmarks
433 $ hg -R cloned-bookmark-default bookmarks
430 X2 1:925d80f479bb
434 X2 1:925d80f479bb
431 Y 2:db815d6d32e6
435 Y 2:db815d6d32e6
432 Z 2:db815d6d32e6
436 Z 2:db815d6d32e6
433 default 1:925d80f479bb
437 default 1:925d80f479bb
434 x y 2:db815d6d32e6
438 x y 2:db815d6d32e6
435 $ hg -R cloned-bookmark-default parents -q
439 $ hg -R cloned-bookmark-default parents -q
436 2:db815d6d32e6
440 2:db815d6d32e6
437 $ hg bookmark -d default
441 $ hg bookmark -d default
438
442
439 test clone with a specific revision
443 test clone with a specific revision
440
444
441 $ hg clone -r 925d80 . cloned-bookmarks-rev
445 $ hg clone -r 925d80 . cloned-bookmarks-rev
442 adding changesets
446 adding changesets
443 adding manifests
447 adding manifests
444 adding file changes
448 adding file changes
445 added 2 changesets with 2 changes to 2 files
449 added 2 changesets with 2 changes to 2 files
446 updating to branch default
450 updating to branch default
447 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
451 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 $ hg -R cloned-bookmarks-rev bookmarks
452 $ hg -R cloned-bookmarks-rev bookmarks
449 X2 1:925d80f479bb
453 X2 1:925d80f479bb
450
454
451 test clone with update to a bookmark
455 test clone with update to a bookmark
452
456
453 $ hg clone -u Z . cloned-bookmarks-update
457 $ hg clone -u Z . cloned-bookmarks-update
454 updating to branch default
458 updating to branch default
455 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
459 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
456 $ hg -R cloned-bookmarks-update bookmarks
460 $ hg -R cloned-bookmarks-update bookmarks
457 X2 1:925d80f479bb
461 X2 1:925d80f479bb
458 Y 2:db815d6d32e6
462 Y 2:db815d6d32e6
459 * Z 2:db815d6d32e6
463 * Z 2:db815d6d32e6
460 x y 2:db815d6d32e6
464 x y 2:db815d6d32e6
461
465
462 create bundle with two heads
466 create bundle with two heads
463
467
464 $ hg clone . tobundle
468 $ hg clone . tobundle
465 updating to branch default
469 updating to branch default
466 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 $ echo x > tobundle/x
471 $ echo x > tobundle/x
468 $ hg -R tobundle add tobundle/x
472 $ hg -R tobundle add tobundle/x
469 $ hg -R tobundle commit -m'x'
473 $ hg -R tobundle commit -m'x'
470 $ hg -R tobundle update -r -2
474 $ hg -R tobundle update -r -2
471 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
475 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
472 $ echo y > tobundle/y
476 $ echo y > tobundle/y
473 $ hg -R tobundle branch test
477 $ hg -R tobundle branch test
474 marked working directory as branch test
478 marked working directory as branch test
475 (branches are permanent and global, did you want a bookmark?)
479 (branches are permanent and global, did you want a bookmark?)
476 $ hg -R tobundle add tobundle/y
480 $ hg -R tobundle add tobundle/y
477 $ hg -R tobundle commit -m'y'
481 $ hg -R tobundle commit -m'y'
478 $ hg -R tobundle bundle tobundle.hg
482 $ hg -R tobundle bundle tobundle.hg
479 searching for changes
483 searching for changes
480 2 changesets found
484 2 changesets found
481 $ hg unbundle tobundle.hg
485 $ hg unbundle tobundle.hg
482 adding changesets
486 adding changesets
483 adding manifests
487 adding manifests
484 adding file changes
488 adding file changes
485 added 2 changesets with 2 changes to 2 files (+1 heads)
489 added 2 changesets with 2 changes to 2 files (+1 heads)
486 (run 'hg heads' to see heads, 'hg merge' to merge)
490 (run 'hg heads' to see heads, 'hg merge' to merge)
487
491
488 update to current bookmark if it's not the parent
492 update to current bookmark if it's not the parent
489
493
490 $ hg summary
494 $ hg summary
491 parent: 2:db815d6d32e6
495 parent: 2:db815d6d32e6
492 2
496 2
493 branch: default
497 branch: default
494 bookmarks: [Z] Y x y
498 bookmarks: [Z] Y x y
495 commit: 1 added, 1 unknown (new branch head)
499 commit: 1 added, 1 unknown (new branch head)
496 update: 2 new changesets (update)
500 update: 2 new changesets (update)
497 $ hg update
501 $ hg update
498 updating to active bookmark Z
502 updating to active bookmark Z
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
503 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 $ hg bookmarks
504 $ hg bookmarks
501 X2 1:925d80f479bb
505 X2 1:925d80f479bb
502 Y 2:db815d6d32e6
506 Y 2:db815d6d32e6
503 * Z 3:125c9a1d6df6
507 * Z 3:125c9a1d6df6
504 x y 2:db815d6d32e6
508 x y 2:db815d6d32e6
505
509
506 test wrongly formated bookmark
510 test wrongly formated bookmark
507
511
508 $ echo '' >> .hg/bookmarks
512 $ echo '' >> .hg/bookmarks
509 $ hg bookmarks
513 $ hg bookmarks
510 X2 1:925d80f479bb
514 X2 1:925d80f479bb
511 Y 2:db815d6d32e6
515 Y 2:db815d6d32e6
512 * Z 3:125c9a1d6df6
516 * Z 3:125c9a1d6df6
513 x y 2:db815d6d32e6
517 x y 2:db815d6d32e6
514 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
518 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
515 $ hg bookmarks
519 $ hg bookmarks
516 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
520 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
517 X2 1:925d80f479bb
521 X2 1:925d80f479bb
518 Y 2:db815d6d32e6
522 Y 2:db815d6d32e6
519 * Z 3:125c9a1d6df6
523 * Z 3:125c9a1d6df6
520 x y 2:db815d6d32e6
524 x y 2:db815d6d32e6
521
525
522 test missing revisions
526 test missing revisions
523
527
524 $ echo "925d80f479bc z" > .hg/bookmarks
528 $ echo "925d80f479bc z" > .hg/bookmarks
525 $ hg book
529 $ hg book
526 no bookmarks set
530 no bookmarks set
527
531
528 test stripping a non-checked-out but bookmarked revision
532 test stripping a non-checked-out but bookmarked revision
529
533
530 $ hg --config extensions.graphlog= log --graph
534 $ hg --config extensions.graphlog= log --graph
531 o changeset: 4:9ba5f110a0b3
535 o changeset: 4:9ba5f110a0b3
532 | branch: test
536 | branch: test
533 | tag: tip
537 | tag: tip
534 | parent: 2:db815d6d32e6
538 | parent: 2:db815d6d32e6
535 | user: test
539 | user: test
536 | date: Thu Jan 01 00:00:00 1970 +0000
540 | date: Thu Jan 01 00:00:00 1970 +0000
537 | summary: y
541 | summary: y
538 |
542 |
539 | @ changeset: 3:125c9a1d6df6
543 | @ changeset: 3:125c9a1d6df6
540 |/ user: test
544 |/ user: test
541 | date: Thu Jan 01 00:00:00 1970 +0000
545 | date: Thu Jan 01 00:00:00 1970 +0000
542 | summary: x
546 | summary: x
543 |
547 |
544 o changeset: 2:db815d6d32e6
548 o changeset: 2:db815d6d32e6
545 | parent: 0:f7b1eb17ad24
549 | parent: 0:f7b1eb17ad24
546 | user: test
550 | user: test
547 | date: Thu Jan 01 00:00:00 1970 +0000
551 | date: Thu Jan 01 00:00:00 1970 +0000
548 | summary: 2
552 | summary: 2
549 |
553 |
550 | o changeset: 1:925d80f479bb
554 | o changeset: 1:925d80f479bb
551 |/ user: test
555 |/ user: test
552 | date: Thu Jan 01 00:00:00 1970 +0000
556 | date: Thu Jan 01 00:00:00 1970 +0000
553 | summary: 1
557 | summary: 1
554 |
558 |
555 o changeset: 0:f7b1eb17ad24
559 o changeset: 0:f7b1eb17ad24
556 user: test
560 user: test
557 date: Thu Jan 01 00:00:00 1970 +0000
561 date: Thu Jan 01 00:00:00 1970 +0000
558 summary: 0
562 summary: 0
559
563
560 $ hg book should-end-on-two
564 $ hg book should-end-on-two
561 $ hg co --clean 4
565 $ hg co --clean 4
562 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
566 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
563 $ hg book four
567 $ hg book four
564 $ hg --config extensions.mq= strip 3
568 $ hg --config extensions.mq= strip 3
565 saved backup bundle to * (glob)
569 saved backup bundle to * (glob)
566 should-end-on-two should end up pointing to revision 2, as that's the
570 should-end-on-two should end up pointing to revision 2, as that's the
567 tipmost surviving ancestor of the stripped revision.
571 tipmost surviving ancestor of the stripped revision.
568 $ hg --config extensions.graphlog= log --graph
572 $ hg --config extensions.graphlog= log --graph
569 @ changeset: 3:9ba5f110a0b3
573 @ changeset: 3:9ba5f110a0b3
570 | branch: test
574 | branch: test
571 | bookmark: four
575 | bookmark: four
572 | tag: tip
576 | tag: tip
573 | user: test
577 | user: test
574 | date: Thu Jan 01 00:00:00 1970 +0000
578 | date: Thu Jan 01 00:00:00 1970 +0000
575 | summary: y
579 | summary: y
576 |
580 |
577 o changeset: 2:db815d6d32e6
581 o changeset: 2:db815d6d32e6
578 | bookmark: should-end-on-two
582 | bookmark: should-end-on-two
579 | parent: 0:f7b1eb17ad24
583 | parent: 0:f7b1eb17ad24
580 | user: test
584 | user: test
581 | date: Thu Jan 01 00:00:00 1970 +0000
585 | date: Thu Jan 01 00:00:00 1970 +0000
582 | summary: 2
586 | summary: 2
583 |
587 |
584 | o changeset: 1:925d80f479bb
588 | o changeset: 1:925d80f479bb
585 |/ user: test
589 |/ user: test
586 | date: Thu Jan 01 00:00:00 1970 +0000
590 | date: Thu Jan 01 00:00:00 1970 +0000
587 | summary: 1
591 | summary: 1
588 |
592 |
589 o changeset: 0:f7b1eb17ad24
593 o changeset: 0:f7b1eb17ad24
590 user: test
594 user: test
591 date: Thu Jan 01 00:00:00 1970 +0000
595 date: Thu Jan 01 00:00:00 1970 +0000
592 summary: 0
596 summary: 0
593
597
594
598
595 test clearing divergent bookmarks of linear ancestors
599 test clearing divergent bookmarks of linear ancestors
596
600
597 $ hg bookmark Z -r 0
601 $ hg bookmark Z -r 0
598 $ hg bookmark Z@1 -r 1
602 $ hg bookmark Z@1 -r 1
599 $ hg bookmark Z@2 -r 2
603 $ hg bookmark Z@2 -r 2
600 $ hg bookmark Z@3 -r 3
604 $ hg bookmark Z@3 -r 3
601 $ hg book
605 $ hg book
602 Z 0:f7b1eb17ad24
606 Z 0:f7b1eb17ad24
603 Z@1 1:925d80f479bb
607 Z@1 1:925d80f479bb
604 Z@2 2:db815d6d32e6
608 Z@2 2:db815d6d32e6
605 Z@3 3:9ba5f110a0b3
609 Z@3 3:9ba5f110a0b3
606 * four 3:9ba5f110a0b3
610 * four 3:9ba5f110a0b3
607 should-end-on-two 2:db815d6d32e6
611 should-end-on-two 2:db815d6d32e6
608 $ hg bookmark Z
612 $ hg bookmark Z
609 moving bookmark 'Z' forward from f7b1eb17ad24
613 moving bookmark 'Z' forward from f7b1eb17ad24
610 $ hg book
614 $ hg book
611 * Z 3:9ba5f110a0b3
615 * Z 3:9ba5f110a0b3
612 Z@1 1:925d80f479bb
616 Z@1 1:925d80f479bb
613 four 3:9ba5f110a0b3
617 four 3:9ba5f110a0b3
614 should-end-on-two 2:db815d6d32e6
618 should-end-on-two 2:db815d6d32e6
615
619
616 test clearing only a single divergent bookmark across branches
620 test clearing only a single divergent bookmark across branches
617
621
618 $ hg book foo -r 1
622 $ hg book foo -r 1
619 $ hg book foo@1 -r 0
623 $ hg book foo@1 -r 0
620 $ hg book foo@2 -r 2
624 $ hg book foo@2 -r 2
621 $ hg book foo@3 -r 3
625 $ hg book foo@3 -r 3
622 $ hg book foo -r foo@3
626 $ hg book foo -r foo@3
623 $ hg book
627 $ hg book
624 * Z 3:9ba5f110a0b3
628 * Z 3:9ba5f110a0b3
625 Z@1 1:925d80f479bb
629 Z@1 1:925d80f479bb
626 foo 3:9ba5f110a0b3
630 foo 3:9ba5f110a0b3
627 foo@1 0:f7b1eb17ad24
631 foo@1 0:f7b1eb17ad24
628 foo@2 2:db815d6d32e6
632 foo@2 2:db815d6d32e6
629 four 3:9ba5f110a0b3
633 four 3:9ba5f110a0b3
630 should-end-on-two 2:db815d6d32e6
634 should-end-on-two 2:db815d6d32e6
General Comments 0
You need to be logged in to leave comments. Login now