##// END OF EJS Templates
bookmarks: resolve divergent bookmarks when fowarding bookmark to descendant...
Sean Farley -
r19109:26c51e87 stable
parent child Browse files
Show More
@@ -1,5847 +1,5852 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 divs = [repo[b].node() for b in marks
820 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
821 deletefrom = [b for b in divs
822 if repo[b].rev() in anc or b == target]
823 bookmarks.deletedivergent(repo, deletefrom, mark)
819 if bmctx.rev() in anc:
824 if bmctx.rev() in anc:
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
825 ui.status(_("moving bookmark '%s' forward from %s\n") %
821 (mark, short(bmctx.node())))
826 (mark, short(bmctx.node())))
822 return
827 return
823 raise util.Abort(_("bookmark '%s' already exists "
828 raise util.Abort(_("bookmark '%s' already exists "
824 "(use -f to force)") % mark)
829 "(use -f to force)") % mark)
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
830 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
826 and not force):
831 and not force):
827 raise util.Abort(
832 raise util.Abort(
828 _("a bookmark cannot have the name of an existing branch"))
833 _("a bookmark cannot have the name of an existing branch"))
829
834
830 if delete and rename:
835 if delete and rename:
831 raise util.Abort(_("--delete and --rename are incompatible"))
836 raise util.Abort(_("--delete and --rename are incompatible"))
832 if delete and rev:
837 if delete and rev:
833 raise util.Abort(_("--rev is incompatible with --delete"))
838 raise util.Abort(_("--rev is incompatible with --delete"))
834 if rename and rev:
839 if rename and rev:
835 raise util.Abort(_("--rev is incompatible with --rename"))
840 raise util.Abort(_("--rev is incompatible with --rename"))
836 if mark is None and (delete or rev):
841 if mark is None and (delete or rev):
837 raise util.Abort(_("bookmark name required"))
842 raise util.Abort(_("bookmark name required"))
838
843
839 if delete:
844 if delete:
840 if mark not in marks:
845 if mark not in marks:
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
846 raise util.Abort(_("bookmark '%s' does not exist") % mark)
842 if mark == repo._bookmarkcurrent:
847 if mark == repo._bookmarkcurrent:
843 bookmarks.setcurrent(repo, None)
848 bookmarks.setcurrent(repo, None)
844 del marks[mark]
849 del marks[mark]
845 marks.write()
850 marks.write()
846
851
847 elif rename:
852 elif rename:
848 if mark is None:
853 if mark is None:
849 raise util.Abort(_("new bookmark name required"))
854 raise util.Abort(_("new bookmark name required"))
850 mark = checkformat(mark)
855 mark = checkformat(mark)
851 if rename not in marks:
856 if rename not in marks:
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
857 raise util.Abort(_("bookmark '%s' does not exist") % rename)
853 checkconflict(repo, mark, force)
858 checkconflict(repo, mark, force)
854 marks[mark] = marks[rename]
859 marks[mark] = marks[rename]
855 if repo._bookmarkcurrent == rename and not inactive:
860 if repo._bookmarkcurrent == rename and not inactive:
856 bookmarks.setcurrent(repo, mark)
861 bookmarks.setcurrent(repo, mark)
857 del marks[rename]
862 del marks[rename]
858 marks.write()
863 marks.write()
859
864
860 elif mark is not None:
865 elif mark is not None:
861 mark = checkformat(mark)
866 mark = checkformat(mark)
862 if inactive and mark == repo._bookmarkcurrent:
867 if inactive and mark == repo._bookmarkcurrent:
863 bookmarks.setcurrent(repo, None)
868 bookmarks.setcurrent(repo, None)
864 return
869 return
865 tgt = cur
870 tgt = cur
866 if rev:
871 if rev:
867 tgt = scmutil.revsingle(repo, rev).node()
872 tgt = scmutil.revsingle(repo, rev).node()
868 checkconflict(repo, mark, force, tgt)
873 checkconflict(repo, mark, force, tgt)
869 marks[mark] = tgt
874 marks[mark] = tgt
870 if not inactive and cur == marks[mark]:
875 if not inactive and cur == marks[mark]:
871 bookmarks.setcurrent(repo, mark)
876 bookmarks.setcurrent(repo, mark)
872 elif cur != tgt and mark == repo._bookmarkcurrent:
877 elif cur != tgt and mark == repo._bookmarkcurrent:
873 bookmarks.setcurrent(repo, None)
878 bookmarks.setcurrent(repo, None)
874 marks.write()
879 marks.write()
875
880
876 # Same message whether trying to deactivate the current bookmark (-i
881 # Same message whether trying to deactivate the current bookmark (-i
877 # with no NAME) or listing bookmarks
882 # with no NAME) or listing bookmarks
878 elif len(marks) == 0:
883 elif len(marks) == 0:
879 ui.status(_("no bookmarks set\n"))
884 ui.status(_("no bookmarks set\n"))
880
885
881 elif inactive:
886 elif inactive:
882 if not repo._bookmarkcurrent:
887 if not repo._bookmarkcurrent:
883 ui.status(_("no active bookmark\n"))
888 ui.status(_("no active bookmark\n"))
884 else:
889 else:
885 bookmarks.setcurrent(repo, None)
890 bookmarks.setcurrent(repo, None)
886
891
887 else: # show bookmarks
892 else: # show bookmarks
888 for bmark, n in sorted(marks.iteritems()):
893 for bmark, n in sorted(marks.iteritems()):
889 current = repo._bookmarkcurrent
894 current = repo._bookmarkcurrent
890 if bmark == current:
895 if bmark == current:
891 prefix, label = '*', 'bookmarks.current'
896 prefix, label = '*', 'bookmarks.current'
892 else:
897 else:
893 prefix, label = ' ', ''
898 prefix, label = ' ', ''
894
899
895 if ui.quiet:
900 if ui.quiet:
896 ui.write("%s\n" % bmark, label=label)
901 ui.write("%s\n" % bmark, label=label)
897 else:
902 else:
898 ui.write(" %s %-25s %d:%s\n" % (
903 ui.write(" %s %-25s %d:%s\n" % (
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
904 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
900 label=label)
905 label=label)
901
906
902 @command('branch',
907 @command('branch',
903 [('f', 'force', None,
908 [('f', 'force', None,
904 _('set branch name even if it shadows an existing branch')),
909 _('set branch name even if it shadows an existing branch')),
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
910 ('C', 'clean', None, _('reset branch name to parent branch name'))],
906 _('[-fC] [NAME]'))
911 _('[-fC] [NAME]'))
907 def branch(ui, repo, label=None, **opts):
912 def branch(ui, repo, label=None, **opts):
908 """set or show the current branch name
913 """set or show the current branch name
909
914
910 .. note::
915 .. note::
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
916 Branch names are permanent and global. Use :hg:`bookmark` to create a
912 light-weight bookmark instead. See :hg:`help glossary` for more
917 light-weight bookmark instead. See :hg:`help glossary` for more
913 information about named branches and bookmarks.
918 information about named branches and bookmarks.
914
919
915 With no argument, show the current branch name. With one argument,
920 With no argument, show the current branch name. With one argument,
916 set the working directory branch name (the branch will not exist
921 set the working directory branch name (the branch will not exist
917 in the repository until the next commit). Standard practice
922 in the repository until the next commit). Standard practice
918 recommends that primary development take place on the 'default'
923 recommends that primary development take place on the 'default'
919 branch.
924 branch.
920
925
921 Unless -f/--force is specified, branch will not let you set a
926 Unless -f/--force is specified, branch will not let you set a
922 branch name that already exists, even if it's inactive.
927 branch name that already exists, even if it's inactive.
923
928
924 Use -C/--clean to reset the working directory branch to that of
929 Use -C/--clean to reset the working directory branch to that of
925 the parent of the working directory, negating a previous branch
930 the parent of the working directory, negating a previous branch
926 change.
931 change.
927
932
928 Use the command :hg:`update` to switch to an existing branch. Use
933 Use the command :hg:`update` to switch to an existing branch. Use
929 :hg:`commit --close-branch` to mark this branch as closed.
934 :hg:`commit --close-branch` to mark this branch as closed.
930
935
931 Returns 0 on success.
936 Returns 0 on success.
932 """
937 """
933 if not opts.get('clean') and not label:
938 if not opts.get('clean') and not label:
934 ui.write("%s\n" % repo.dirstate.branch())
939 ui.write("%s\n" % repo.dirstate.branch())
935 return
940 return
936
941
937 wlock = repo.wlock()
942 wlock = repo.wlock()
938 try:
943 try:
939 if opts.get('clean'):
944 if opts.get('clean'):
940 label = repo[None].p1().branch()
945 label = repo[None].p1().branch()
941 repo.dirstate.setbranch(label)
946 repo.dirstate.setbranch(label)
942 ui.status(_('reset working directory to branch %s\n') % label)
947 ui.status(_('reset working directory to branch %s\n') % label)
943 elif label:
948 elif label:
944 if not opts.get('force') and label in repo.branchmap():
949 if not opts.get('force') and label in repo.branchmap():
945 if label not in [p.branch() for p in repo.parents()]:
950 if label not in [p.branch() for p in repo.parents()]:
946 raise util.Abort(_('a branch of the same name already'
951 raise util.Abort(_('a branch of the same name already'
947 ' exists'),
952 ' exists'),
948 # i18n: "it" refers to an existing branch
953 # i18n: "it" refers to an existing branch
949 hint=_("use 'hg update' to switch to it"))
954 hint=_("use 'hg update' to switch to it"))
950 scmutil.checknewlabel(repo, label, 'branch')
955 scmutil.checknewlabel(repo, label, 'branch')
951 repo.dirstate.setbranch(label)
956 repo.dirstate.setbranch(label)
952 ui.status(_('marked working directory as branch %s\n') % label)
957 ui.status(_('marked working directory as branch %s\n') % label)
953 ui.status(_('(branches are permanent and global, '
958 ui.status(_('(branches are permanent and global, '
954 'did you want a bookmark?)\n'))
959 'did you want a bookmark?)\n'))
955 finally:
960 finally:
956 wlock.release()
961 wlock.release()
957
962
958 @command('branches',
963 @command('branches',
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
964 [('a', 'active', False, _('show only branches that have unmerged heads')),
960 ('c', 'closed', False, _('show normal and closed branches'))],
965 ('c', 'closed', False, _('show normal and closed branches'))],
961 _('[-ac]'))
966 _('[-ac]'))
962 def branches(ui, repo, active=False, closed=False):
967 def branches(ui, repo, active=False, closed=False):
963 """list repository named branches
968 """list repository named branches
964
969
965 List the repository's named branches, indicating which ones are
970 List the repository's named branches, indicating which ones are
966 inactive. If -c/--closed is specified, also list branches which have
971 inactive. If -c/--closed is specified, also list branches which have
967 been marked closed (see :hg:`commit --close-branch`).
972 been marked closed (see :hg:`commit --close-branch`).
968
973
969 If -a/--active is specified, only show active branches. A branch
974 If -a/--active is specified, only show active branches. A branch
970 is considered active if it contains repository heads.
975 is considered active if it contains repository heads.
971
976
972 Use the command :hg:`update` to switch to an existing branch.
977 Use the command :hg:`update` to switch to an existing branch.
973
978
974 Returns 0.
979 Returns 0.
975 """
980 """
976
981
977 hexfunc = ui.debugflag and hex or short
982 hexfunc = ui.debugflag and hex or short
978
983
979 activebranches = set([repo[n].branch() for n in repo.heads()])
984 activebranches = set([repo[n].branch() for n in repo.heads()])
980 branches = []
985 branches = []
981 for tag, heads in repo.branchmap().iteritems():
986 for tag, heads in repo.branchmap().iteritems():
982 for h in reversed(heads):
987 for h in reversed(heads):
983 ctx = repo[h]
988 ctx = repo[h]
984 isopen = not ctx.closesbranch()
989 isopen = not ctx.closesbranch()
985 if isopen:
990 if isopen:
986 tip = ctx
991 tip = ctx
987 break
992 break
988 else:
993 else:
989 tip = repo[heads[-1]]
994 tip = repo[heads[-1]]
990 isactive = tag in activebranches and isopen
995 isactive = tag in activebranches and isopen
991 branches.append((tip, isactive, isopen))
996 branches.append((tip, isactive, isopen))
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
997 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
993 reverse=True)
998 reverse=True)
994
999
995 for ctx, isactive, isopen in branches:
1000 for ctx, isactive, isopen in branches:
996 if (not active) or isactive:
1001 if (not active) or isactive:
997 if isactive:
1002 if isactive:
998 label = 'branches.active'
1003 label = 'branches.active'
999 notice = ''
1004 notice = ''
1000 elif not isopen:
1005 elif not isopen:
1001 if not closed:
1006 if not closed:
1002 continue
1007 continue
1003 label = 'branches.closed'
1008 label = 'branches.closed'
1004 notice = _(' (closed)')
1009 notice = _(' (closed)')
1005 else:
1010 else:
1006 label = 'branches.inactive'
1011 label = 'branches.inactive'
1007 notice = _(' (inactive)')
1012 notice = _(' (inactive)')
1008 if ctx.branch() == repo.dirstate.branch():
1013 if ctx.branch() == repo.dirstate.branch():
1009 label = 'branches.current'
1014 label = 'branches.current'
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1015 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1016 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1012 'log.changeset changeset.%s' % ctx.phasestr())
1017 'log.changeset changeset.%s' % ctx.phasestr())
1013 tag = ui.label(ctx.branch(), label)
1018 tag = ui.label(ctx.branch(), label)
1014 if ui.quiet:
1019 if ui.quiet:
1015 ui.write("%s\n" % tag)
1020 ui.write("%s\n" % tag)
1016 else:
1021 else:
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1022 ui.write("%s %s%s\n" % (tag, rev, notice))
1018
1023
1019 @command('bundle',
1024 @command('bundle',
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1025 [('f', 'force', None, _('run even when the destination is unrelated')),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1026 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1022 _('REV')),
1027 _('REV')),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1028 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1024 _('BRANCH')),
1029 _('BRANCH')),
1025 ('', 'base', [],
1030 ('', 'base', [],
1026 _('a base changeset assumed to be available at the destination'),
1031 _('a base changeset assumed to be available at the destination'),
1027 _('REV')),
1032 _('REV')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1033 ('a', 'all', None, _('bundle all changesets in the repository')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1034 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1030 ] + remoteopts,
1035 ] + remoteopts,
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1036 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1032 def bundle(ui, repo, fname, dest=None, **opts):
1037 def bundle(ui, repo, fname, dest=None, **opts):
1033 """create a changegroup file
1038 """create a changegroup file
1034
1039
1035 Generate a compressed changegroup file collecting changesets not
1040 Generate a compressed changegroup file collecting changesets not
1036 known to be in another repository.
1041 known to be in another repository.
1037
1042
1038 If you omit the destination repository, then hg assumes the
1043 If you omit the destination repository, then hg assumes the
1039 destination will have all the nodes you specify with --base
1044 destination will have all the nodes you specify with --base
1040 parameters. To create a bundle containing all changesets, use
1045 parameters. To create a bundle containing all changesets, use
1041 -a/--all (or --base null).
1046 -a/--all (or --base null).
1042
1047
1043 You can change compression method with the -t/--type option.
1048 You can change compression method with the -t/--type option.
1044 The available compression methods are: none, bzip2, and
1049 The available compression methods are: none, bzip2, and
1045 gzip (by default, bundles are compressed using bzip2).
1050 gzip (by default, bundles are compressed using bzip2).
1046
1051
1047 The bundle file can then be transferred using conventional means
1052 The bundle file can then be transferred using conventional means
1048 and applied to another repository with the unbundle or pull
1053 and applied to another repository with the unbundle or pull
1049 command. This is useful when direct push and pull are not
1054 command. This is useful when direct push and pull are not
1050 available or when exporting an entire repository is undesirable.
1055 available or when exporting an entire repository is undesirable.
1051
1056
1052 Applying bundles preserves all changeset contents including
1057 Applying bundles preserves all changeset contents including
1053 permissions, copy/rename information, and revision history.
1058 permissions, copy/rename information, and revision history.
1054
1059
1055 Returns 0 on success, 1 if no changes found.
1060 Returns 0 on success, 1 if no changes found.
1056 """
1061 """
1057 revs = None
1062 revs = None
1058 if 'rev' in opts:
1063 if 'rev' in opts:
1059 revs = scmutil.revrange(repo, opts['rev'])
1064 revs = scmutil.revrange(repo, opts['rev'])
1060
1065
1061 bundletype = opts.get('type', 'bzip2').lower()
1066 bundletype = opts.get('type', 'bzip2').lower()
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1067 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1063 bundletype = btypes.get(bundletype)
1068 bundletype = btypes.get(bundletype)
1064 if bundletype not in changegroup.bundletypes:
1069 if bundletype not in changegroup.bundletypes:
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1070 raise util.Abort(_('unknown bundle type specified with --type'))
1066
1071
1067 if opts.get('all'):
1072 if opts.get('all'):
1068 base = ['null']
1073 base = ['null']
1069 else:
1074 else:
1070 base = scmutil.revrange(repo, opts.get('base'))
1075 base = scmutil.revrange(repo, opts.get('base'))
1071 if base:
1076 if base:
1072 if dest:
1077 if dest:
1073 raise util.Abort(_("--base is incompatible with specifying "
1078 raise util.Abort(_("--base is incompatible with specifying "
1074 "a destination"))
1079 "a destination"))
1075 common = [repo.lookup(rev) for rev in base]
1080 common = [repo.lookup(rev) for rev in base]
1076 heads = revs and map(repo.lookup, revs) or revs
1081 heads = revs and map(repo.lookup, revs) or revs
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1082 cg = repo.getbundle('bundle', heads=heads, common=common)
1078 outgoing = None
1083 outgoing = None
1079 else:
1084 else:
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1085 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1086 dest, branches = hg.parseurl(dest, opts.get('branch'))
1082 other = hg.peer(repo, opts, dest)
1087 other = hg.peer(repo, opts, dest)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1088 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1084 heads = revs and map(repo.lookup, revs) or revs
1089 heads = revs and map(repo.lookup, revs) or revs
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1090 outgoing = discovery.findcommonoutgoing(repo, other,
1086 onlyheads=heads,
1091 onlyheads=heads,
1087 force=opts.get('force'),
1092 force=opts.get('force'),
1088 portable=True)
1093 portable=True)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1094 cg = repo.getlocalbundle('bundle', outgoing)
1090 if not cg:
1095 if not cg:
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1096 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1092 return 1
1097 return 1
1093
1098
1094 changegroup.writebundle(cg, fname, bundletype)
1099 changegroup.writebundle(cg, fname, bundletype)
1095
1100
1096 @command('cat',
1101 @command('cat',
1097 [('o', 'output', '',
1102 [('o', 'output', '',
1098 _('print output to file with formatted name'), _('FORMAT')),
1103 _('print output to file with formatted name'), _('FORMAT')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1104 ('r', 'rev', '', _('print the given revision'), _('REV')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1105 ('', 'decode', None, _('apply any matching decode filter')),
1101 ] + walkopts,
1106 ] + walkopts,
1102 _('[OPTION]... FILE...'))
1107 _('[OPTION]... FILE...'))
1103 def cat(ui, repo, file1, *pats, **opts):
1108 def cat(ui, repo, file1, *pats, **opts):
1104 """output the current or given revision of files
1109 """output the current or given revision of files
1105
1110
1106 Print the specified files as they were at the given revision. If
1111 Print the specified files as they were at the given revision. If
1107 no revision is given, the parent of the working directory is used,
1112 no revision is given, the parent of the working directory is used,
1108 or tip if no revision is checked out.
1113 or tip if no revision is checked out.
1109
1114
1110 Output may be to a file, in which case the name of the file is
1115 Output may be to a file, in which case the name of the file is
1111 given using a format string. The formatting rules are the same as
1116 given using a format string. The formatting rules are the same as
1112 for the export command, with the following additions:
1117 for the export command, with the following additions:
1113
1118
1114 :``%s``: basename of file being printed
1119 :``%s``: basename of file being printed
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1120 :``%d``: dirname of file being printed, or '.' if in repository root
1116 :``%p``: root-relative path name of file being printed
1121 :``%p``: root-relative path name of file being printed
1117
1122
1118 Returns 0 on success.
1123 Returns 0 on success.
1119 """
1124 """
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1125 ctx = scmutil.revsingle(repo, opts.get('rev'))
1121 err = 1
1126 err = 1
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1127 m = scmutil.match(ctx, (file1,) + pats, opts)
1123 for abs in ctx.walk(m):
1128 for abs in ctx.walk(m):
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1129 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1125 pathname=abs)
1130 pathname=abs)
1126 data = ctx[abs].data()
1131 data = ctx[abs].data()
1127 if opts.get('decode'):
1132 if opts.get('decode'):
1128 data = repo.wwritedata(abs, data)
1133 data = repo.wwritedata(abs, data)
1129 fp.write(data)
1134 fp.write(data)
1130 fp.close()
1135 fp.close()
1131 err = 0
1136 err = 0
1132 return err
1137 return err
1133
1138
1134 @command('^clone',
1139 @command('^clone',
1135 [('U', 'noupdate', None,
1140 [('U', 'noupdate', None,
1136 _('the clone will include an empty working copy (only a repository)')),
1141 _('the clone will include an empty working copy (only a repository)')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1142 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1143 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1144 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1145 ('', 'pull', None, _('use pull protocol to copy metadata')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1146 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1142 ] + remoteopts,
1147 ] + remoteopts,
1143 _('[OPTION]... SOURCE [DEST]'))
1148 _('[OPTION]... SOURCE [DEST]'))
1144 def clone(ui, source, dest=None, **opts):
1149 def clone(ui, source, dest=None, **opts):
1145 """make a copy of an existing repository
1150 """make a copy of an existing repository
1146
1151
1147 Create a copy of an existing repository in a new directory.
1152 Create a copy of an existing repository in a new directory.
1148
1153
1149 If no destination directory name is specified, it defaults to the
1154 If no destination directory name is specified, it defaults to the
1150 basename of the source.
1155 basename of the source.
1151
1156
1152 The location of the source is added to the new repository's
1157 The location of the source is added to the new repository's
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1158 ``.hg/hgrc`` file, as the default to be used for future pulls.
1154
1159
1155 Only local paths and ``ssh://`` URLs are supported as
1160 Only local paths and ``ssh://`` URLs are supported as
1156 destinations. For ``ssh://`` destinations, no working directory or
1161 destinations. For ``ssh://`` destinations, no working directory or
1157 ``.hg/hgrc`` will be created on the remote side.
1162 ``.hg/hgrc`` will be created on the remote side.
1158
1163
1159 To pull only a subset of changesets, specify one or more revisions
1164 To pull only a subset of changesets, specify one or more revisions
1160 identifiers with -r/--rev or branches with -b/--branch. The
1165 identifiers with -r/--rev or branches with -b/--branch. The
1161 resulting clone will contain only the specified changesets and
1166 resulting clone will contain only the specified changesets and
1162 their ancestors. These options (or 'clone src#rev dest') imply
1167 their ancestors. These options (or 'clone src#rev dest') imply
1163 --pull, even for local source repositories. Note that specifying a
1168 --pull, even for local source repositories. Note that specifying a
1164 tag will include the tagged changeset but not the changeset
1169 tag will include the tagged changeset but not the changeset
1165 containing the tag.
1170 containing the tag.
1166
1171
1167 If the source repository has a bookmark called '@' set, that
1172 If the source repository has a bookmark called '@' set, that
1168 revision will be checked out in the new repository by default.
1173 revision will be checked out in the new repository by default.
1169
1174
1170 To check out a particular version, use -u/--update, or
1175 To check out a particular version, use -u/--update, or
1171 -U/--noupdate to create a clone with no working directory.
1176 -U/--noupdate to create a clone with no working directory.
1172
1177
1173 .. container:: verbose
1178 .. container:: verbose
1174
1179
1175 For efficiency, hardlinks are used for cloning whenever the
1180 For efficiency, hardlinks are used for cloning whenever the
1176 source and destination are on the same filesystem (note this
1181 source and destination are on the same filesystem (note this
1177 applies only to the repository data, not to the working
1182 applies only to the repository data, not to the working
1178 directory). Some filesystems, such as AFS, implement hardlinking
1183 directory). Some filesystems, such as AFS, implement hardlinking
1179 incorrectly, but do not report errors. In these cases, use the
1184 incorrectly, but do not report errors. In these cases, use the
1180 --pull option to avoid hardlinking.
1185 --pull option to avoid hardlinking.
1181
1186
1182 In some cases, you can clone repositories and the working
1187 In some cases, you can clone repositories and the working
1183 directory using full hardlinks with ::
1188 directory using full hardlinks with ::
1184
1189
1185 $ cp -al REPO REPOCLONE
1190 $ cp -al REPO REPOCLONE
1186
1191
1187 This is the fastest way to clone, but it is not always safe. The
1192 This is the fastest way to clone, but it is not always safe. The
1188 operation is not atomic (making sure REPO is not modified during
1193 operation is not atomic (making sure REPO is not modified during
1189 the operation is up to you) and you have to make sure your
1194 the operation is up to you) and you have to make sure your
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1195 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1191 so). Also, this is not compatible with certain extensions that
1196 so). Also, this is not compatible with certain extensions that
1192 place their metadata under the .hg directory, such as mq.
1197 place their metadata under the .hg directory, such as mq.
1193
1198
1194 Mercurial will update the working directory to the first applicable
1199 Mercurial will update the working directory to the first applicable
1195 revision from this list:
1200 revision from this list:
1196
1201
1197 a) null if -U or the source repository has no changesets
1202 a) null if -U or the source repository has no changesets
1198 b) if -u . and the source repository is local, the first parent of
1203 b) if -u . and the source repository is local, the first parent of
1199 the source repository's working directory
1204 the source repository's working directory
1200 c) the changeset specified with -u (if a branch name, this means the
1205 c) the changeset specified with -u (if a branch name, this means the
1201 latest head of that branch)
1206 latest head of that branch)
1202 d) the changeset specified with -r
1207 d) the changeset specified with -r
1203 e) the tipmost head specified with -b
1208 e) the tipmost head specified with -b
1204 f) the tipmost head specified with the url#branch source syntax
1209 f) the tipmost head specified with the url#branch source syntax
1205 g) the revision marked with the '@' bookmark, if present
1210 g) the revision marked with the '@' bookmark, if present
1206 h) the tipmost head of the default branch
1211 h) the tipmost head of the default branch
1207 i) tip
1212 i) tip
1208
1213
1209 Examples:
1214 Examples:
1210
1215
1211 - clone a remote repository to a new directory named hg/::
1216 - clone a remote repository to a new directory named hg/::
1212
1217
1213 hg clone http://selenic.com/hg
1218 hg clone http://selenic.com/hg
1214
1219
1215 - create a lightweight local clone::
1220 - create a lightweight local clone::
1216
1221
1217 hg clone project/ project-feature/
1222 hg clone project/ project-feature/
1218
1223
1219 - clone from an absolute path on an ssh server (note double-slash)::
1224 - clone from an absolute path on an ssh server (note double-slash)::
1220
1225
1221 hg clone ssh://user@server//home/projects/alpha/
1226 hg clone ssh://user@server//home/projects/alpha/
1222
1227
1223 - do a high-speed clone over a LAN while checking out a
1228 - do a high-speed clone over a LAN while checking out a
1224 specified version::
1229 specified version::
1225
1230
1226 hg clone --uncompressed http://server/repo -u 1.5
1231 hg clone --uncompressed http://server/repo -u 1.5
1227
1232
1228 - create a repository without changesets after a particular revision::
1233 - create a repository without changesets after a particular revision::
1229
1234
1230 hg clone -r 04e544 experimental/ good/
1235 hg clone -r 04e544 experimental/ good/
1231
1236
1232 - clone (and track) a particular named branch::
1237 - clone (and track) a particular named branch::
1233
1238
1234 hg clone http://selenic.com/hg#stable
1239 hg clone http://selenic.com/hg#stable
1235
1240
1236 See :hg:`help urls` for details on specifying URLs.
1241 See :hg:`help urls` for details on specifying URLs.
1237
1242
1238 Returns 0 on success.
1243 Returns 0 on success.
1239 """
1244 """
1240 if opts.get('noupdate') and opts.get('updaterev'):
1245 if opts.get('noupdate') and opts.get('updaterev'):
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1246 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1242
1247
1243 r = hg.clone(ui, opts, source, dest,
1248 r = hg.clone(ui, opts, source, dest,
1244 pull=opts.get('pull'),
1249 pull=opts.get('pull'),
1245 stream=opts.get('uncompressed'),
1250 stream=opts.get('uncompressed'),
1246 rev=opts.get('rev'),
1251 rev=opts.get('rev'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1252 update=opts.get('updaterev') or not opts.get('noupdate'),
1248 branch=opts.get('branch'))
1253 branch=opts.get('branch'))
1249
1254
1250 return r is None
1255 return r is None
1251
1256
1252 @command('^commit|ci',
1257 @command('^commit|ci',
1253 [('A', 'addremove', None,
1258 [('A', 'addremove', None,
1254 _('mark new/missing files as added/removed before committing')),
1259 _('mark new/missing files as added/removed before committing')),
1255 ('', 'close-branch', None,
1260 ('', 'close-branch', None,
1256 _('mark a branch as closed, hiding it from the branch list')),
1261 _('mark a branch as closed, hiding it from the branch list')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1262 ('', 'amend', None, _('amend the parent of the working dir')),
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1263 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1259 _('[OPTION]... [FILE]...'))
1264 _('[OPTION]... [FILE]...'))
1260 def commit(ui, repo, *pats, **opts):
1265 def commit(ui, repo, *pats, **opts):
1261 """commit the specified files or all outstanding changes
1266 """commit the specified files or all outstanding changes
1262
1267
1263 Commit changes to the given files into the repository. Unlike a
1268 Commit changes to the given files into the repository. Unlike a
1264 centralized SCM, this operation is a local operation. See
1269 centralized SCM, this operation is a local operation. See
1265 :hg:`push` for a way to actively distribute your changes.
1270 :hg:`push` for a way to actively distribute your changes.
1266
1271
1267 If a list of files is omitted, all changes reported by :hg:`status`
1272 If a list of files is omitted, all changes reported by :hg:`status`
1268 will be committed.
1273 will be committed.
1269
1274
1270 If you are committing the result of a merge, do not provide any
1275 If you are committing the result of a merge, do not provide any
1271 filenames or -I/-X filters.
1276 filenames or -I/-X filters.
1272
1277
1273 If no commit message is specified, Mercurial starts your
1278 If no commit message is specified, Mercurial starts your
1274 configured editor where you can enter a message. In case your
1279 configured editor where you can enter a message. In case your
1275 commit fails, you will find a backup of your message in
1280 commit fails, you will find a backup of your message in
1276 ``.hg/last-message.txt``.
1281 ``.hg/last-message.txt``.
1277
1282
1278 The --amend flag can be used to amend the parent of the
1283 The --amend flag can be used to amend the parent of the
1279 working directory with a new commit that contains the changes
1284 working directory with a new commit that contains the changes
1280 in the parent in addition to those currently reported by :hg:`status`,
1285 in the parent in addition to those currently reported by :hg:`status`,
1281 if there are any. The old commit is stored in a backup bundle in
1286 if there are any. The old commit is stored in a backup bundle in
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1287 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1283 on how to restore it).
1288 on how to restore it).
1284
1289
1285 Message, user and date are taken from the amended commit unless
1290 Message, user and date are taken from the amended commit unless
1286 specified. When a message isn't specified on the command line,
1291 specified. When a message isn't specified on the command line,
1287 the editor will open with the message of the amended commit.
1292 the editor will open with the message of the amended commit.
1288
1293
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1294 It is not possible to amend public changesets (see :hg:`help phases`)
1290 or changesets that have children.
1295 or changesets that have children.
1291
1296
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1297 See :hg:`help dates` for a list of formats valid for -d/--date.
1293
1298
1294 Returns 0 on success, 1 if nothing changed.
1299 Returns 0 on success, 1 if nothing changed.
1295 """
1300 """
1296 if opts.get('subrepos'):
1301 if opts.get('subrepos'):
1297 # Let --subrepos on the command line override config setting.
1302 # Let --subrepos on the command line override config setting.
1298 ui.setconfig('ui', 'commitsubrepos', True)
1303 ui.setconfig('ui', 'commitsubrepos', True)
1299
1304
1300 extra = {}
1305 extra = {}
1301 if opts.get('close_branch'):
1306 if opts.get('close_branch'):
1302 extra['close'] = 1
1307 extra['close'] = 1
1303
1308
1304 branch = repo[None].branch()
1309 branch = repo[None].branch()
1305 bheads = repo.branchheads(branch)
1310 bheads = repo.branchheads(branch)
1306
1311
1307 if opts.get('amend'):
1312 if opts.get('amend'):
1308 if ui.configbool('ui', 'commitsubrepos'):
1313 if ui.configbool('ui', 'commitsubrepos'):
1309 raise util.Abort(_('cannot amend recursively'))
1314 raise util.Abort(_('cannot amend recursively'))
1310
1315
1311 old = repo['.']
1316 old = repo['.']
1312 if old.phase() == phases.public:
1317 if old.phase() == phases.public:
1313 raise util.Abort(_('cannot amend public changesets'))
1318 raise util.Abort(_('cannot amend public changesets'))
1314 if len(repo[None].parents()) > 1:
1319 if len(repo[None].parents()) > 1:
1315 raise util.Abort(_('cannot amend while merging'))
1320 raise util.Abort(_('cannot amend while merging'))
1316 if (not obsolete._enabled) and old.children():
1321 if (not obsolete._enabled) and old.children():
1317 raise util.Abort(_('cannot amend changeset with children'))
1322 raise util.Abort(_('cannot amend changeset with children'))
1318
1323
1319 e = cmdutil.commiteditor
1324 e = cmdutil.commiteditor
1320 if opts.get('force_editor'):
1325 if opts.get('force_editor'):
1321 e = cmdutil.commitforceeditor
1326 e = cmdutil.commitforceeditor
1322
1327
1323 def commitfunc(ui, repo, message, match, opts):
1328 def commitfunc(ui, repo, message, match, opts):
1324 editor = e
1329 editor = e
1325 # message contains text from -m or -l, if it's empty,
1330 # message contains text from -m or -l, if it's empty,
1326 # open the editor with the old message
1331 # open the editor with the old message
1327 if not message:
1332 if not message:
1328 message = old.description()
1333 message = old.description()
1329 editor = cmdutil.commitforceeditor
1334 editor = cmdutil.commitforceeditor
1330 return repo.commit(message,
1335 return repo.commit(message,
1331 opts.get('user') or old.user(),
1336 opts.get('user') or old.user(),
1332 opts.get('date') or old.date(),
1337 opts.get('date') or old.date(),
1333 match,
1338 match,
1334 editor=editor,
1339 editor=editor,
1335 extra=extra)
1340 extra=extra)
1336
1341
1337 current = repo._bookmarkcurrent
1342 current = repo._bookmarkcurrent
1338 marks = old.bookmarks()
1343 marks = old.bookmarks()
1339 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1344 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1340 if node == old.node():
1345 if node == old.node():
1341 ui.status(_("nothing changed\n"))
1346 ui.status(_("nothing changed\n"))
1342 return 1
1347 return 1
1343 elif marks:
1348 elif marks:
1344 ui.debug('moving bookmarks %r from %s to %s\n' %
1349 ui.debug('moving bookmarks %r from %s to %s\n' %
1345 (marks, old.hex(), hex(node)))
1350 (marks, old.hex(), hex(node)))
1346 newmarks = repo._bookmarks
1351 newmarks = repo._bookmarks
1347 for bm in marks:
1352 for bm in marks:
1348 newmarks[bm] = node
1353 newmarks[bm] = node
1349 if bm == current:
1354 if bm == current:
1350 bookmarks.setcurrent(repo, bm)
1355 bookmarks.setcurrent(repo, bm)
1351 newmarks.write()
1356 newmarks.write()
1352 else:
1357 else:
1353 e = cmdutil.commiteditor
1358 e = cmdutil.commiteditor
1354 if opts.get('force_editor'):
1359 if opts.get('force_editor'):
1355 e = cmdutil.commitforceeditor
1360 e = cmdutil.commitforceeditor
1356
1361
1357 def commitfunc(ui, repo, message, match, opts):
1362 def commitfunc(ui, repo, message, match, opts):
1358 return repo.commit(message, opts.get('user'), opts.get('date'),
1363 return repo.commit(message, opts.get('user'), opts.get('date'),
1359 match, editor=e, extra=extra)
1364 match, editor=e, extra=extra)
1360
1365
1361 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1366 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1362
1367
1363 if not node:
1368 if not node:
1364 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1369 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1365 if stat[3]:
1370 if stat[3]:
1366 ui.status(_("nothing changed (%d missing files, see "
1371 ui.status(_("nothing changed (%d missing files, see "
1367 "'hg status')\n") % len(stat[3]))
1372 "'hg status')\n") % len(stat[3]))
1368 else:
1373 else:
1369 ui.status(_("nothing changed\n"))
1374 ui.status(_("nothing changed\n"))
1370 return 1
1375 return 1
1371
1376
1372 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1377 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1373
1378
1374 @command('copy|cp',
1379 @command('copy|cp',
1375 [('A', 'after', None, _('record a copy that has already occurred')),
1380 [('A', 'after', None, _('record a copy that has already occurred')),
1376 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1381 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1377 ] + walkopts + dryrunopts,
1382 ] + walkopts + dryrunopts,
1378 _('[OPTION]... [SOURCE]... DEST'))
1383 _('[OPTION]... [SOURCE]... DEST'))
1379 def copy(ui, repo, *pats, **opts):
1384 def copy(ui, repo, *pats, **opts):
1380 """mark files as copied for the next commit
1385 """mark files as copied for the next commit
1381
1386
1382 Mark dest as having copies of source files. If dest is a
1387 Mark dest as having copies of source files. If dest is a
1383 directory, copies are put in that directory. If dest is a file,
1388 directory, copies are put in that directory. If dest is a file,
1384 the source must be a single file.
1389 the source must be a single file.
1385
1390
1386 By default, this command copies the contents of files as they
1391 By default, this command copies the contents of files as they
1387 exist in the working directory. If invoked with -A/--after, the
1392 exist in the working directory. If invoked with -A/--after, the
1388 operation is recorded, but no copying is performed.
1393 operation is recorded, but no copying is performed.
1389
1394
1390 This command takes effect with the next commit. To undo a copy
1395 This command takes effect with the next commit. To undo a copy
1391 before that, see :hg:`revert`.
1396 before that, see :hg:`revert`.
1392
1397
1393 Returns 0 on success, 1 if errors are encountered.
1398 Returns 0 on success, 1 if errors are encountered.
1394 """
1399 """
1395 wlock = repo.wlock(False)
1400 wlock = repo.wlock(False)
1396 try:
1401 try:
1397 return cmdutil.copy(ui, repo, pats, opts)
1402 return cmdutil.copy(ui, repo, pats, opts)
1398 finally:
1403 finally:
1399 wlock.release()
1404 wlock.release()
1400
1405
1401 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1406 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1402 def debugancestor(ui, repo, *args):
1407 def debugancestor(ui, repo, *args):
1403 """find the ancestor revision of two revisions in a given index"""
1408 """find the ancestor revision of two revisions in a given index"""
1404 if len(args) == 3:
1409 if len(args) == 3:
1405 index, rev1, rev2 = args
1410 index, rev1, rev2 = args
1406 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1411 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1407 lookup = r.lookup
1412 lookup = r.lookup
1408 elif len(args) == 2:
1413 elif len(args) == 2:
1409 if not repo:
1414 if not repo:
1410 raise util.Abort(_("there is no Mercurial repository here "
1415 raise util.Abort(_("there is no Mercurial repository here "
1411 "(.hg not found)"))
1416 "(.hg not found)"))
1412 rev1, rev2 = args
1417 rev1, rev2 = args
1413 r = repo.changelog
1418 r = repo.changelog
1414 lookup = repo.lookup
1419 lookup = repo.lookup
1415 else:
1420 else:
1416 raise util.Abort(_('either two or three arguments required'))
1421 raise util.Abort(_('either two or three arguments required'))
1417 a = r.ancestor(lookup(rev1), lookup(rev2))
1422 a = r.ancestor(lookup(rev1), lookup(rev2))
1418 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1423 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1419
1424
1420 @command('debugbuilddag',
1425 @command('debugbuilddag',
1421 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1426 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1422 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1427 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1423 ('n', 'new-file', None, _('add new file at each rev'))],
1428 ('n', 'new-file', None, _('add new file at each rev'))],
1424 _('[OPTION]... [TEXT]'))
1429 _('[OPTION]... [TEXT]'))
1425 def debugbuilddag(ui, repo, text=None,
1430 def debugbuilddag(ui, repo, text=None,
1426 mergeable_file=False,
1431 mergeable_file=False,
1427 overwritten_file=False,
1432 overwritten_file=False,
1428 new_file=False):
1433 new_file=False):
1429 """builds a repo with a given DAG from scratch in the current empty repo
1434 """builds a repo with a given DAG from scratch in the current empty repo
1430
1435
1431 The description of the DAG is read from stdin if not given on the
1436 The description of the DAG is read from stdin if not given on the
1432 command line.
1437 command line.
1433
1438
1434 Elements:
1439 Elements:
1435
1440
1436 - "+n" is a linear run of n nodes based on the current default parent
1441 - "+n" is a linear run of n nodes based on the current default parent
1437 - "." is a single node based on the current default parent
1442 - "." is a single node based on the current default parent
1438 - "$" resets the default parent to null (implied at the start);
1443 - "$" resets the default parent to null (implied at the start);
1439 otherwise the default parent is always the last node created
1444 otherwise the default parent is always the last node created
1440 - "<p" sets the default parent to the backref p
1445 - "<p" sets the default parent to the backref p
1441 - "*p" is a fork at parent p, which is a backref
1446 - "*p" is a fork at parent p, which is a backref
1442 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1447 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1443 - "/p2" is a merge of the preceding node and p2
1448 - "/p2" is a merge of the preceding node and p2
1444 - ":tag" defines a local tag for the preceding node
1449 - ":tag" defines a local tag for the preceding node
1445 - "@branch" sets the named branch for subsequent nodes
1450 - "@branch" sets the named branch for subsequent nodes
1446 - "#...\\n" is a comment up to the end of the line
1451 - "#...\\n" is a comment up to the end of the line
1447
1452
1448 Whitespace between the above elements is ignored.
1453 Whitespace between the above elements is ignored.
1449
1454
1450 A backref is either
1455 A backref is either
1451
1456
1452 - a number n, which references the node curr-n, where curr is the current
1457 - a number n, which references the node curr-n, where curr is the current
1453 node, or
1458 node, or
1454 - the name of a local tag you placed earlier using ":tag", or
1459 - the name of a local tag you placed earlier using ":tag", or
1455 - empty to denote the default parent.
1460 - empty to denote the default parent.
1456
1461
1457 All string valued-elements are either strictly alphanumeric, or must
1462 All string valued-elements are either strictly alphanumeric, or must
1458 be enclosed in double quotes ("..."), with "\\" as escape character.
1463 be enclosed in double quotes ("..."), with "\\" as escape character.
1459 """
1464 """
1460
1465
1461 if text is None:
1466 if text is None:
1462 ui.status(_("reading DAG from stdin\n"))
1467 ui.status(_("reading DAG from stdin\n"))
1463 text = ui.fin.read()
1468 text = ui.fin.read()
1464
1469
1465 cl = repo.changelog
1470 cl = repo.changelog
1466 if len(cl) > 0:
1471 if len(cl) > 0:
1467 raise util.Abort(_('repository is not empty'))
1472 raise util.Abort(_('repository is not empty'))
1468
1473
1469 # determine number of revs in DAG
1474 # determine number of revs in DAG
1470 total = 0
1475 total = 0
1471 for type, data in dagparser.parsedag(text):
1476 for type, data in dagparser.parsedag(text):
1472 if type == 'n':
1477 if type == 'n':
1473 total += 1
1478 total += 1
1474
1479
1475 if mergeable_file:
1480 if mergeable_file:
1476 linesperrev = 2
1481 linesperrev = 2
1477 # make a file with k lines per rev
1482 # make a file with k lines per rev
1478 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1483 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1479 initialmergedlines.append("")
1484 initialmergedlines.append("")
1480
1485
1481 tags = []
1486 tags = []
1482
1487
1483 lock = tr = None
1488 lock = tr = None
1484 try:
1489 try:
1485 lock = repo.lock()
1490 lock = repo.lock()
1486 tr = repo.transaction("builddag")
1491 tr = repo.transaction("builddag")
1487
1492
1488 at = -1
1493 at = -1
1489 atbranch = 'default'
1494 atbranch = 'default'
1490 nodeids = []
1495 nodeids = []
1491 id = 0
1496 id = 0
1492 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1497 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1493 for type, data in dagparser.parsedag(text):
1498 for type, data in dagparser.parsedag(text):
1494 if type == 'n':
1499 if type == 'n':
1495 ui.note(('node %s\n' % str(data)))
1500 ui.note(('node %s\n' % str(data)))
1496 id, ps = data
1501 id, ps = data
1497
1502
1498 files = []
1503 files = []
1499 fctxs = {}
1504 fctxs = {}
1500
1505
1501 p2 = None
1506 p2 = None
1502 if mergeable_file:
1507 if mergeable_file:
1503 fn = "mf"
1508 fn = "mf"
1504 p1 = repo[ps[0]]
1509 p1 = repo[ps[0]]
1505 if len(ps) > 1:
1510 if len(ps) > 1:
1506 p2 = repo[ps[1]]
1511 p2 = repo[ps[1]]
1507 pa = p1.ancestor(p2)
1512 pa = p1.ancestor(p2)
1508 base, local, other = [x[fn].data() for x in (pa, p1,
1513 base, local, other = [x[fn].data() for x in (pa, p1,
1509 p2)]
1514 p2)]
1510 m3 = simplemerge.Merge3Text(base, local, other)
1515 m3 = simplemerge.Merge3Text(base, local, other)
1511 ml = [l.strip() for l in m3.merge_lines()]
1516 ml = [l.strip() for l in m3.merge_lines()]
1512 ml.append("")
1517 ml.append("")
1513 elif at > 0:
1518 elif at > 0:
1514 ml = p1[fn].data().split("\n")
1519 ml = p1[fn].data().split("\n")
1515 else:
1520 else:
1516 ml = initialmergedlines
1521 ml = initialmergedlines
1517 ml[id * linesperrev] += " r%i" % id
1522 ml[id * linesperrev] += " r%i" % id
1518 mergedtext = "\n".join(ml)
1523 mergedtext = "\n".join(ml)
1519 files.append(fn)
1524 files.append(fn)
1520 fctxs[fn] = context.memfilectx(fn, mergedtext)
1525 fctxs[fn] = context.memfilectx(fn, mergedtext)
1521
1526
1522 if overwritten_file:
1527 if overwritten_file:
1523 fn = "of"
1528 fn = "of"
1524 files.append(fn)
1529 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1526
1531
1527 if new_file:
1532 if new_file:
1528 fn = "nf%i" % id
1533 fn = "nf%i" % id
1529 files.append(fn)
1534 files.append(fn)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1535 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531 if len(ps) > 1:
1536 if len(ps) > 1:
1532 if not p2:
1537 if not p2:
1533 p2 = repo[ps[1]]
1538 p2 = repo[ps[1]]
1534 for fn in p2:
1539 for fn in p2:
1535 if fn.startswith("nf"):
1540 if fn.startswith("nf"):
1536 files.append(fn)
1541 files.append(fn)
1537 fctxs[fn] = p2[fn]
1542 fctxs[fn] = p2[fn]
1538
1543
1539 def fctxfn(repo, cx, path):
1544 def fctxfn(repo, cx, path):
1540 return fctxs.get(path)
1545 return fctxs.get(path)
1541
1546
1542 if len(ps) == 0 or ps[0] < 0:
1547 if len(ps) == 0 or ps[0] < 0:
1543 pars = [None, None]
1548 pars = [None, None]
1544 elif len(ps) == 1:
1549 elif len(ps) == 1:
1545 pars = [nodeids[ps[0]], None]
1550 pars = [nodeids[ps[0]], None]
1546 else:
1551 else:
1547 pars = [nodeids[p] for p in ps]
1552 pars = [nodeids[p] for p in ps]
1548 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1553 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1549 date=(id, 0),
1554 date=(id, 0),
1550 user="debugbuilddag",
1555 user="debugbuilddag",
1551 extra={'branch': atbranch})
1556 extra={'branch': atbranch})
1552 nodeid = repo.commitctx(cx)
1557 nodeid = repo.commitctx(cx)
1553 nodeids.append(nodeid)
1558 nodeids.append(nodeid)
1554 at = id
1559 at = id
1555 elif type == 'l':
1560 elif type == 'l':
1556 id, name = data
1561 id, name = data
1557 ui.note(('tag %s\n' % name))
1562 ui.note(('tag %s\n' % name))
1558 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1563 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1559 elif type == 'a':
1564 elif type == 'a':
1560 ui.note(('branch %s\n' % data))
1565 ui.note(('branch %s\n' % data))
1561 atbranch = data
1566 atbranch = data
1562 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1567 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1563 tr.close()
1568 tr.close()
1564
1569
1565 if tags:
1570 if tags:
1566 repo.opener.write("localtags", "".join(tags))
1571 repo.opener.write("localtags", "".join(tags))
1567 finally:
1572 finally:
1568 ui.progress(_('building'), None)
1573 ui.progress(_('building'), None)
1569 release(tr, lock)
1574 release(tr, lock)
1570
1575
1571 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1576 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1572 def debugbundle(ui, bundlepath, all=None, **opts):
1577 def debugbundle(ui, bundlepath, all=None, **opts):
1573 """lists the contents of a bundle"""
1578 """lists the contents of a bundle"""
1574 f = hg.openpath(ui, bundlepath)
1579 f = hg.openpath(ui, bundlepath)
1575 try:
1580 try:
1576 gen = changegroup.readbundle(f, bundlepath)
1581 gen = changegroup.readbundle(f, bundlepath)
1577 if all:
1582 if all:
1578 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1583 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1579
1584
1580 def showchunks(named):
1585 def showchunks(named):
1581 ui.write("\n%s\n" % named)
1586 ui.write("\n%s\n" % named)
1582 chain = None
1587 chain = None
1583 while True:
1588 while True:
1584 chunkdata = gen.deltachunk(chain)
1589 chunkdata = gen.deltachunk(chain)
1585 if not chunkdata:
1590 if not chunkdata:
1586 break
1591 break
1587 node = chunkdata['node']
1592 node = chunkdata['node']
1588 p1 = chunkdata['p1']
1593 p1 = chunkdata['p1']
1589 p2 = chunkdata['p2']
1594 p2 = chunkdata['p2']
1590 cs = chunkdata['cs']
1595 cs = chunkdata['cs']
1591 deltabase = chunkdata['deltabase']
1596 deltabase = chunkdata['deltabase']
1592 delta = chunkdata['delta']
1597 delta = chunkdata['delta']
1593 ui.write("%s %s %s %s %s %s\n" %
1598 ui.write("%s %s %s %s %s %s\n" %
1594 (hex(node), hex(p1), hex(p2),
1599 (hex(node), hex(p1), hex(p2),
1595 hex(cs), hex(deltabase), len(delta)))
1600 hex(cs), hex(deltabase), len(delta)))
1596 chain = node
1601 chain = node
1597
1602
1598 chunkdata = gen.changelogheader()
1603 chunkdata = gen.changelogheader()
1599 showchunks("changelog")
1604 showchunks("changelog")
1600 chunkdata = gen.manifestheader()
1605 chunkdata = gen.manifestheader()
1601 showchunks("manifest")
1606 showchunks("manifest")
1602 while True:
1607 while True:
1603 chunkdata = gen.filelogheader()
1608 chunkdata = gen.filelogheader()
1604 if not chunkdata:
1609 if not chunkdata:
1605 break
1610 break
1606 fname = chunkdata['filename']
1611 fname = chunkdata['filename']
1607 showchunks(fname)
1612 showchunks(fname)
1608 else:
1613 else:
1609 chunkdata = gen.changelogheader()
1614 chunkdata = gen.changelogheader()
1610 chain = None
1615 chain = None
1611 while True:
1616 while True:
1612 chunkdata = gen.deltachunk(chain)
1617 chunkdata = gen.deltachunk(chain)
1613 if not chunkdata:
1618 if not chunkdata:
1614 break
1619 break
1615 node = chunkdata['node']
1620 node = chunkdata['node']
1616 ui.write("%s\n" % hex(node))
1621 ui.write("%s\n" % hex(node))
1617 chain = node
1622 chain = node
1618 finally:
1623 finally:
1619 f.close()
1624 f.close()
1620
1625
1621 @command('debugcheckstate', [], '')
1626 @command('debugcheckstate', [], '')
1622 def debugcheckstate(ui, repo):
1627 def debugcheckstate(ui, repo):
1623 """validate the correctness of the current dirstate"""
1628 """validate the correctness of the current dirstate"""
1624 parent1, parent2 = repo.dirstate.parents()
1629 parent1, parent2 = repo.dirstate.parents()
1625 m1 = repo[parent1].manifest()
1630 m1 = repo[parent1].manifest()
1626 m2 = repo[parent2].manifest()
1631 m2 = repo[parent2].manifest()
1627 errors = 0
1632 errors = 0
1628 for f in repo.dirstate:
1633 for f in repo.dirstate:
1629 state = repo.dirstate[f]
1634 state = repo.dirstate[f]
1630 if state in "nr" and f not in m1:
1635 if state in "nr" and f not in m1:
1631 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1636 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1632 errors += 1
1637 errors += 1
1633 if state in "a" and f in m1:
1638 if state in "a" and f in m1:
1634 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1639 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1635 errors += 1
1640 errors += 1
1636 if state in "m" and f not in m1 and f not in m2:
1641 if state in "m" and f not in m1 and f not in m2:
1637 ui.warn(_("%s in state %s, but not in either manifest\n") %
1642 ui.warn(_("%s in state %s, but not in either manifest\n") %
1638 (f, state))
1643 (f, state))
1639 errors += 1
1644 errors += 1
1640 for f in m1:
1645 for f in m1:
1641 state = repo.dirstate[f]
1646 state = repo.dirstate[f]
1642 if state not in "nrm":
1647 if state not in "nrm":
1643 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1648 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1644 errors += 1
1649 errors += 1
1645 if errors:
1650 if errors:
1646 error = _(".hg/dirstate inconsistent with current parent's manifest")
1651 error = _(".hg/dirstate inconsistent with current parent's manifest")
1647 raise util.Abort(error)
1652 raise util.Abort(error)
1648
1653
1649 @command('debugcommands', [], _('[COMMAND]'))
1654 @command('debugcommands', [], _('[COMMAND]'))
1650 def debugcommands(ui, cmd='', *args):
1655 def debugcommands(ui, cmd='', *args):
1651 """list all available commands and options"""
1656 """list all available commands and options"""
1652 for cmd, vals in sorted(table.iteritems()):
1657 for cmd, vals in sorted(table.iteritems()):
1653 cmd = cmd.split('|')[0].strip('^')
1658 cmd = cmd.split('|')[0].strip('^')
1654 opts = ', '.join([i[1] for i in vals[1]])
1659 opts = ', '.join([i[1] for i in vals[1]])
1655 ui.write('%s: %s\n' % (cmd, opts))
1660 ui.write('%s: %s\n' % (cmd, opts))
1656
1661
1657 @command('debugcomplete',
1662 @command('debugcomplete',
1658 [('o', 'options', None, _('show the command options'))],
1663 [('o', 'options', None, _('show the command options'))],
1659 _('[-o] CMD'))
1664 _('[-o] CMD'))
1660 def debugcomplete(ui, cmd='', **opts):
1665 def debugcomplete(ui, cmd='', **opts):
1661 """returns the completion list associated with the given command"""
1666 """returns the completion list associated with the given command"""
1662
1667
1663 if opts.get('options'):
1668 if opts.get('options'):
1664 options = []
1669 options = []
1665 otables = [globalopts]
1670 otables = [globalopts]
1666 if cmd:
1671 if cmd:
1667 aliases, entry = cmdutil.findcmd(cmd, table, False)
1672 aliases, entry = cmdutil.findcmd(cmd, table, False)
1668 otables.append(entry[1])
1673 otables.append(entry[1])
1669 for t in otables:
1674 for t in otables:
1670 for o in t:
1675 for o in t:
1671 if "(DEPRECATED)" in o[3]:
1676 if "(DEPRECATED)" in o[3]:
1672 continue
1677 continue
1673 if o[0]:
1678 if o[0]:
1674 options.append('-%s' % o[0])
1679 options.append('-%s' % o[0])
1675 options.append('--%s' % o[1])
1680 options.append('--%s' % o[1])
1676 ui.write("%s\n" % "\n".join(options))
1681 ui.write("%s\n" % "\n".join(options))
1677 return
1682 return
1678
1683
1679 cmdlist = cmdutil.findpossible(cmd, table)
1684 cmdlist = cmdutil.findpossible(cmd, table)
1680 if ui.verbose:
1685 if ui.verbose:
1681 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1686 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1682 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1687 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1683
1688
1684 @command('debugdag',
1689 @command('debugdag',
1685 [('t', 'tags', None, _('use tags as labels')),
1690 [('t', 'tags', None, _('use tags as labels')),
1686 ('b', 'branches', None, _('annotate with branch names')),
1691 ('b', 'branches', None, _('annotate with branch names')),
1687 ('', 'dots', None, _('use dots for runs')),
1692 ('', 'dots', None, _('use dots for runs')),
1688 ('s', 'spaces', None, _('separate elements by spaces'))],
1693 ('s', 'spaces', None, _('separate elements by spaces'))],
1689 _('[OPTION]... [FILE [REV]...]'))
1694 _('[OPTION]... [FILE [REV]...]'))
1690 def debugdag(ui, repo, file_=None, *revs, **opts):
1695 def debugdag(ui, repo, file_=None, *revs, **opts):
1691 """format the changelog or an index DAG as a concise textual description
1696 """format the changelog or an index DAG as a concise textual description
1692
1697
1693 If you pass a revlog index, the revlog's DAG is emitted. If you list
1698 If you pass a revlog index, the revlog's DAG is emitted. If you list
1694 revision numbers, they get labeled in the output as rN.
1699 revision numbers, they get labeled in the output as rN.
1695
1700
1696 Otherwise, the changelog DAG of the current repo is emitted.
1701 Otherwise, the changelog DAG of the current repo is emitted.
1697 """
1702 """
1698 spaces = opts.get('spaces')
1703 spaces = opts.get('spaces')
1699 dots = opts.get('dots')
1704 dots = opts.get('dots')
1700 if file_:
1705 if file_:
1701 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1706 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1702 revs = set((int(r) for r in revs))
1707 revs = set((int(r) for r in revs))
1703 def events():
1708 def events():
1704 for r in rlog:
1709 for r in rlog:
1705 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1710 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1706 if p != -1)))
1711 if p != -1)))
1707 if r in revs:
1712 if r in revs:
1708 yield 'l', (r, "r%i" % r)
1713 yield 'l', (r, "r%i" % r)
1709 elif repo:
1714 elif repo:
1710 cl = repo.changelog
1715 cl = repo.changelog
1711 tags = opts.get('tags')
1716 tags = opts.get('tags')
1712 branches = opts.get('branches')
1717 branches = opts.get('branches')
1713 if tags:
1718 if tags:
1714 labels = {}
1719 labels = {}
1715 for l, n in repo.tags().items():
1720 for l, n in repo.tags().items():
1716 labels.setdefault(cl.rev(n), []).append(l)
1721 labels.setdefault(cl.rev(n), []).append(l)
1717 def events():
1722 def events():
1718 b = "default"
1723 b = "default"
1719 for r in cl:
1724 for r in cl:
1720 if branches:
1725 if branches:
1721 newb = cl.read(cl.node(r))[5]['branch']
1726 newb = cl.read(cl.node(r))[5]['branch']
1722 if newb != b:
1727 if newb != b:
1723 yield 'a', newb
1728 yield 'a', newb
1724 b = newb
1729 b = newb
1725 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1730 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1726 if p != -1)))
1731 if p != -1)))
1727 if tags:
1732 if tags:
1728 ls = labels.get(r)
1733 ls = labels.get(r)
1729 if ls:
1734 if ls:
1730 for l in ls:
1735 for l in ls:
1731 yield 'l', (r, l)
1736 yield 'l', (r, l)
1732 else:
1737 else:
1733 raise util.Abort(_('need repo for changelog dag'))
1738 raise util.Abort(_('need repo for changelog dag'))
1734
1739
1735 for line in dagparser.dagtextlines(events(),
1740 for line in dagparser.dagtextlines(events(),
1736 addspaces=spaces,
1741 addspaces=spaces,
1737 wraplabels=True,
1742 wraplabels=True,
1738 wrapannotations=True,
1743 wrapannotations=True,
1739 wrapnonlinear=dots,
1744 wrapnonlinear=dots,
1740 usedots=dots,
1745 usedots=dots,
1741 maxlinewidth=70):
1746 maxlinewidth=70):
1742 ui.write(line)
1747 ui.write(line)
1743 ui.write("\n")
1748 ui.write("\n")
1744
1749
1745 @command('debugdata',
1750 @command('debugdata',
1746 [('c', 'changelog', False, _('open changelog')),
1751 [('c', 'changelog', False, _('open changelog')),
1747 ('m', 'manifest', False, _('open manifest'))],
1752 ('m', 'manifest', False, _('open manifest'))],
1748 _('-c|-m|FILE REV'))
1753 _('-c|-m|FILE REV'))
1749 def debugdata(ui, repo, file_, rev = None, **opts):
1754 def debugdata(ui, repo, file_, rev = None, **opts):
1750 """dump the contents of a data file revision"""
1755 """dump the contents of a data file revision"""
1751 if opts.get('changelog') or opts.get('manifest'):
1756 if opts.get('changelog') or opts.get('manifest'):
1752 file_, rev = None, file_
1757 file_, rev = None, file_
1753 elif rev is None:
1758 elif rev is None:
1754 raise error.CommandError('debugdata', _('invalid arguments'))
1759 raise error.CommandError('debugdata', _('invalid arguments'))
1755 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1760 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1756 try:
1761 try:
1757 ui.write(r.revision(r.lookup(rev)))
1762 ui.write(r.revision(r.lookup(rev)))
1758 except KeyError:
1763 except KeyError:
1759 raise util.Abort(_('invalid revision identifier %s') % rev)
1764 raise util.Abort(_('invalid revision identifier %s') % rev)
1760
1765
1761 @command('debugdate',
1766 @command('debugdate',
1762 [('e', 'extended', None, _('try extended date formats'))],
1767 [('e', 'extended', None, _('try extended date formats'))],
1763 _('[-e] DATE [RANGE]'))
1768 _('[-e] DATE [RANGE]'))
1764 def debugdate(ui, date, range=None, **opts):
1769 def debugdate(ui, date, range=None, **opts):
1765 """parse and display a date"""
1770 """parse and display a date"""
1766 if opts["extended"]:
1771 if opts["extended"]:
1767 d = util.parsedate(date, util.extendeddateformats)
1772 d = util.parsedate(date, util.extendeddateformats)
1768 else:
1773 else:
1769 d = util.parsedate(date)
1774 d = util.parsedate(date)
1770 ui.write(("internal: %s %s\n") % d)
1775 ui.write(("internal: %s %s\n") % d)
1771 ui.write(("standard: %s\n") % util.datestr(d))
1776 ui.write(("standard: %s\n") % util.datestr(d))
1772 if range:
1777 if range:
1773 m = util.matchdate(range)
1778 m = util.matchdate(range)
1774 ui.write(("match: %s\n") % m(d[0]))
1779 ui.write(("match: %s\n") % m(d[0]))
1775
1780
1776 @command('debugdiscovery',
1781 @command('debugdiscovery',
1777 [('', 'old', None, _('use old-style discovery')),
1782 [('', 'old', None, _('use old-style discovery')),
1778 ('', 'nonheads', None,
1783 ('', 'nonheads', None,
1779 _('use old-style discovery with non-heads included')),
1784 _('use old-style discovery with non-heads included')),
1780 ] + remoteopts,
1785 ] + remoteopts,
1781 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1786 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1782 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1787 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1783 """runs the changeset discovery protocol in isolation"""
1788 """runs the changeset discovery protocol in isolation"""
1784 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1789 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1785 opts.get('branch'))
1790 opts.get('branch'))
1786 remote = hg.peer(repo, opts, remoteurl)
1791 remote = hg.peer(repo, opts, remoteurl)
1787 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1792 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1788
1793
1789 # make sure tests are repeatable
1794 # make sure tests are repeatable
1790 random.seed(12323)
1795 random.seed(12323)
1791
1796
1792 def doit(localheads, remoteheads, remote=remote):
1797 def doit(localheads, remoteheads, remote=remote):
1793 if opts.get('old'):
1798 if opts.get('old'):
1794 if localheads:
1799 if localheads:
1795 raise util.Abort('cannot use localheads with old style '
1800 raise util.Abort('cannot use localheads with old style '
1796 'discovery')
1801 'discovery')
1797 if not util.safehasattr(remote, 'branches'):
1802 if not util.safehasattr(remote, 'branches'):
1798 # enable in-client legacy support
1803 # enable in-client legacy support
1799 remote = localrepo.locallegacypeer(remote.local())
1804 remote = localrepo.locallegacypeer(remote.local())
1800 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1805 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1801 force=True)
1806 force=True)
1802 common = set(common)
1807 common = set(common)
1803 if not opts.get('nonheads'):
1808 if not opts.get('nonheads'):
1804 ui.write(("unpruned common: %s\n") %
1809 ui.write(("unpruned common: %s\n") %
1805 " ".join(sorted(short(n) for n in common)))
1810 " ".join(sorted(short(n) for n in common)))
1806 dag = dagutil.revlogdag(repo.changelog)
1811 dag = dagutil.revlogdag(repo.changelog)
1807 all = dag.ancestorset(dag.internalizeall(common))
1812 all = dag.ancestorset(dag.internalizeall(common))
1808 common = dag.externalizeall(dag.headsetofconnecteds(all))
1813 common = dag.externalizeall(dag.headsetofconnecteds(all))
1809 else:
1814 else:
1810 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1815 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1811 common = set(common)
1816 common = set(common)
1812 rheads = set(hds)
1817 rheads = set(hds)
1813 lheads = set(repo.heads())
1818 lheads = set(repo.heads())
1814 ui.write(("common heads: %s\n") %
1819 ui.write(("common heads: %s\n") %
1815 " ".join(sorted(short(n) for n in common)))
1820 " ".join(sorted(short(n) for n in common)))
1816 if lheads <= common:
1821 if lheads <= common:
1817 ui.write(("local is subset\n"))
1822 ui.write(("local is subset\n"))
1818 elif rheads <= common:
1823 elif rheads <= common:
1819 ui.write(("remote is subset\n"))
1824 ui.write(("remote is subset\n"))
1820
1825
1821 serverlogs = opts.get('serverlog')
1826 serverlogs = opts.get('serverlog')
1822 if serverlogs:
1827 if serverlogs:
1823 for filename in serverlogs:
1828 for filename in serverlogs:
1824 logfile = open(filename, 'r')
1829 logfile = open(filename, 'r')
1825 try:
1830 try:
1826 line = logfile.readline()
1831 line = logfile.readline()
1827 while line:
1832 while line:
1828 parts = line.strip().split(';')
1833 parts = line.strip().split(';')
1829 op = parts[1]
1834 op = parts[1]
1830 if op == 'cg':
1835 if op == 'cg':
1831 pass
1836 pass
1832 elif op == 'cgss':
1837 elif op == 'cgss':
1833 doit(parts[2].split(' '), parts[3].split(' '))
1838 doit(parts[2].split(' '), parts[3].split(' '))
1834 elif op == 'unb':
1839 elif op == 'unb':
1835 doit(parts[3].split(' '), parts[2].split(' '))
1840 doit(parts[3].split(' '), parts[2].split(' '))
1836 line = logfile.readline()
1841 line = logfile.readline()
1837 finally:
1842 finally:
1838 logfile.close()
1843 logfile.close()
1839
1844
1840 else:
1845 else:
1841 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1846 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1842 opts.get('remote_head'))
1847 opts.get('remote_head'))
1843 localrevs = opts.get('local_head')
1848 localrevs = opts.get('local_head')
1844 doit(localrevs, remoterevs)
1849 doit(localrevs, remoterevs)
1845
1850
1846 @command('debugfileset',
1851 @command('debugfileset',
1847 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1852 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1848 _('[-r REV] FILESPEC'))
1853 _('[-r REV] FILESPEC'))
1849 def debugfileset(ui, repo, expr, **opts):
1854 def debugfileset(ui, repo, expr, **opts):
1850 '''parse and apply a fileset specification'''
1855 '''parse and apply a fileset specification'''
1851 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1856 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1852 if ui.verbose:
1857 if ui.verbose:
1853 tree = fileset.parse(expr)[0]
1858 tree = fileset.parse(expr)[0]
1854 ui.note(tree, "\n")
1859 ui.note(tree, "\n")
1855
1860
1856 for f in fileset.getfileset(ctx, expr):
1861 for f in fileset.getfileset(ctx, expr):
1857 ui.write("%s\n" % f)
1862 ui.write("%s\n" % f)
1858
1863
1859 @command('debugfsinfo', [], _('[PATH]'))
1864 @command('debugfsinfo', [], _('[PATH]'))
1860 def debugfsinfo(ui, path = "."):
1865 def debugfsinfo(ui, path = "."):
1861 """show information detected about current filesystem"""
1866 """show information detected about current filesystem"""
1862 util.writefile('.debugfsinfo', '')
1867 util.writefile('.debugfsinfo', '')
1863 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1868 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1864 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1869 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1865 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1870 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1866 and 'yes' or 'no'))
1871 and 'yes' or 'no'))
1867 os.unlink('.debugfsinfo')
1872 os.unlink('.debugfsinfo')
1868
1873
1869 @command('debuggetbundle',
1874 @command('debuggetbundle',
1870 [('H', 'head', [], _('id of head node'), _('ID')),
1875 [('H', 'head', [], _('id of head node'), _('ID')),
1871 ('C', 'common', [], _('id of common node'), _('ID')),
1876 ('C', 'common', [], _('id of common node'), _('ID')),
1872 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1877 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1873 _('REPO FILE [-H|-C ID]...'))
1878 _('REPO FILE [-H|-C ID]...'))
1874 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1879 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1875 """retrieves a bundle from a repo
1880 """retrieves a bundle from a repo
1876
1881
1877 Every ID must be a full-length hex node id string. Saves the bundle to the
1882 Every ID must be a full-length hex node id string. Saves the bundle to the
1878 given file.
1883 given file.
1879 """
1884 """
1880 repo = hg.peer(ui, opts, repopath)
1885 repo = hg.peer(ui, opts, repopath)
1881 if not repo.capable('getbundle'):
1886 if not repo.capable('getbundle'):
1882 raise util.Abort("getbundle() not supported by target repository")
1887 raise util.Abort("getbundle() not supported by target repository")
1883 args = {}
1888 args = {}
1884 if common:
1889 if common:
1885 args['common'] = [bin(s) for s in common]
1890 args['common'] = [bin(s) for s in common]
1886 if head:
1891 if head:
1887 args['heads'] = [bin(s) for s in head]
1892 args['heads'] = [bin(s) for s in head]
1888 bundle = repo.getbundle('debug', **args)
1893 bundle = repo.getbundle('debug', **args)
1889
1894
1890 bundletype = opts.get('type', 'bzip2').lower()
1895 bundletype = opts.get('type', 'bzip2').lower()
1891 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1896 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1892 bundletype = btypes.get(bundletype)
1897 bundletype = btypes.get(bundletype)
1893 if bundletype not in changegroup.bundletypes:
1898 if bundletype not in changegroup.bundletypes:
1894 raise util.Abort(_('unknown bundle type specified with --type'))
1899 raise util.Abort(_('unknown bundle type specified with --type'))
1895 changegroup.writebundle(bundle, bundlepath, bundletype)
1900 changegroup.writebundle(bundle, bundlepath, bundletype)
1896
1901
1897 @command('debugignore', [], '')
1902 @command('debugignore', [], '')
1898 def debugignore(ui, repo, *values, **opts):
1903 def debugignore(ui, repo, *values, **opts):
1899 """display the combined ignore pattern"""
1904 """display the combined ignore pattern"""
1900 ignore = repo.dirstate._ignore
1905 ignore = repo.dirstate._ignore
1901 includepat = getattr(ignore, 'includepat', None)
1906 includepat = getattr(ignore, 'includepat', None)
1902 if includepat is not None:
1907 if includepat is not None:
1903 ui.write("%s\n" % includepat)
1908 ui.write("%s\n" % includepat)
1904 else:
1909 else:
1905 raise util.Abort(_("no ignore patterns found"))
1910 raise util.Abort(_("no ignore patterns found"))
1906
1911
1907 @command('debugindex',
1912 @command('debugindex',
1908 [('c', 'changelog', False, _('open changelog')),
1913 [('c', 'changelog', False, _('open changelog')),
1909 ('m', 'manifest', False, _('open manifest')),
1914 ('m', 'manifest', False, _('open manifest')),
1910 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1915 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1911 _('[-f FORMAT] -c|-m|FILE'))
1916 _('[-f FORMAT] -c|-m|FILE'))
1912 def debugindex(ui, repo, file_ = None, **opts):
1917 def debugindex(ui, repo, file_ = None, **opts):
1913 """dump the contents of an index file"""
1918 """dump the contents of an index file"""
1914 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1919 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1915 format = opts.get('format', 0)
1920 format = opts.get('format', 0)
1916 if format not in (0, 1):
1921 if format not in (0, 1):
1917 raise util.Abort(_("unknown format %d") % format)
1922 raise util.Abort(_("unknown format %d") % format)
1918
1923
1919 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1924 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1920 if generaldelta:
1925 if generaldelta:
1921 basehdr = ' delta'
1926 basehdr = ' delta'
1922 else:
1927 else:
1923 basehdr = ' base'
1928 basehdr = ' base'
1924
1929
1925 if format == 0:
1930 if format == 0:
1926 ui.write(" rev offset length " + basehdr + " linkrev"
1931 ui.write(" rev offset length " + basehdr + " linkrev"
1927 " nodeid p1 p2\n")
1932 " nodeid p1 p2\n")
1928 elif format == 1:
1933 elif format == 1:
1929 ui.write(" rev flag offset length"
1934 ui.write(" rev flag offset length"
1930 " size " + basehdr + " link p1 p2"
1935 " size " + basehdr + " link p1 p2"
1931 " nodeid\n")
1936 " nodeid\n")
1932
1937
1933 for i in r:
1938 for i in r:
1934 node = r.node(i)
1939 node = r.node(i)
1935 if generaldelta:
1940 if generaldelta:
1936 base = r.deltaparent(i)
1941 base = r.deltaparent(i)
1937 else:
1942 else:
1938 base = r.chainbase(i)
1943 base = r.chainbase(i)
1939 if format == 0:
1944 if format == 0:
1940 try:
1945 try:
1941 pp = r.parents(node)
1946 pp = r.parents(node)
1942 except Exception:
1947 except Exception:
1943 pp = [nullid, nullid]
1948 pp = [nullid, nullid]
1944 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1949 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1945 i, r.start(i), r.length(i), base, r.linkrev(i),
1950 i, r.start(i), r.length(i), base, r.linkrev(i),
1946 short(node), short(pp[0]), short(pp[1])))
1951 short(node), short(pp[0]), short(pp[1])))
1947 elif format == 1:
1952 elif format == 1:
1948 pr = r.parentrevs(i)
1953 pr = r.parentrevs(i)
1949 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1954 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1950 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1955 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1951 base, r.linkrev(i), pr[0], pr[1], short(node)))
1956 base, r.linkrev(i), pr[0], pr[1], short(node)))
1952
1957
1953 @command('debugindexdot', [], _('FILE'))
1958 @command('debugindexdot', [], _('FILE'))
1954 def debugindexdot(ui, repo, file_):
1959 def debugindexdot(ui, repo, file_):
1955 """dump an index DAG as a graphviz dot file"""
1960 """dump an index DAG as a graphviz dot file"""
1956 r = None
1961 r = None
1957 if repo:
1962 if repo:
1958 filelog = repo.file(file_)
1963 filelog = repo.file(file_)
1959 if len(filelog):
1964 if len(filelog):
1960 r = filelog
1965 r = filelog
1961 if not r:
1966 if not r:
1962 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1967 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1963 ui.write(("digraph G {\n"))
1968 ui.write(("digraph G {\n"))
1964 for i in r:
1969 for i in r:
1965 node = r.node(i)
1970 node = r.node(i)
1966 pp = r.parents(node)
1971 pp = r.parents(node)
1967 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1972 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1968 if pp[1] != nullid:
1973 if pp[1] != nullid:
1969 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1974 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1970 ui.write("}\n")
1975 ui.write("}\n")
1971
1976
1972 @command('debuginstall', [], '')
1977 @command('debuginstall', [], '')
1973 def debuginstall(ui):
1978 def debuginstall(ui):
1974 '''test Mercurial installation
1979 '''test Mercurial installation
1975
1980
1976 Returns 0 on success.
1981 Returns 0 on success.
1977 '''
1982 '''
1978
1983
1979 def writetemp(contents):
1984 def writetemp(contents):
1980 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1985 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1981 f = os.fdopen(fd, "wb")
1986 f = os.fdopen(fd, "wb")
1982 f.write(contents)
1987 f.write(contents)
1983 f.close()
1988 f.close()
1984 return name
1989 return name
1985
1990
1986 problems = 0
1991 problems = 0
1987
1992
1988 # encoding
1993 # encoding
1989 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1994 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1990 try:
1995 try:
1991 encoding.fromlocal("test")
1996 encoding.fromlocal("test")
1992 except util.Abort, inst:
1997 except util.Abort, inst:
1993 ui.write(" %s\n" % inst)
1998 ui.write(" %s\n" % inst)
1994 ui.write(_(" (check that your locale is properly set)\n"))
1999 ui.write(_(" (check that your locale is properly set)\n"))
1995 problems += 1
2000 problems += 1
1996
2001
1997 # Python lib
2002 # Python lib
1998 ui.status(_("checking Python lib (%s)...\n")
2003 ui.status(_("checking Python lib (%s)...\n")
1999 % os.path.dirname(os.__file__))
2004 % os.path.dirname(os.__file__))
2000
2005
2001 # compiled modules
2006 # compiled modules
2002 ui.status(_("checking installed modules (%s)...\n")
2007 ui.status(_("checking installed modules (%s)...\n")
2003 % os.path.dirname(__file__))
2008 % os.path.dirname(__file__))
2004 try:
2009 try:
2005 import bdiff, mpatch, base85, osutil
2010 import bdiff, mpatch, base85, osutil
2006 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2011 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2007 except Exception, inst:
2012 except Exception, inst:
2008 ui.write(" %s\n" % inst)
2013 ui.write(" %s\n" % inst)
2009 ui.write(_(" One or more extensions could not be found"))
2014 ui.write(_(" One or more extensions could not be found"))
2010 ui.write(_(" (check that you compiled the extensions)\n"))
2015 ui.write(_(" (check that you compiled the extensions)\n"))
2011 problems += 1
2016 problems += 1
2012
2017
2013 # templates
2018 # templates
2014 import templater
2019 import templater
2015 p = templater.templatepath()
2020 p = templater.templatepath()
2016 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2021 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2017 try:
2022 try:
2018 templater.templater(templater.templatepath("map-cmdline.default"))
2023 templater.templater(templater.templatepath("map-cmdline.default"))
2019 except Exception, inst:
2024 except Exception, inst:
2020 ui.write(" %s\n" % inst)
2025 ui.write(" %s\n" % inst)
2021 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2026 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2022 problems += 1
2027 problems += 1
2023
2028
2024 # editor
2029 # editor
2025 ui.status(_("checking commit editor...\n"))
2030 ui.status(_("checking commit editor...\n"))
2026 editor = ui.geteditor()
2031 editor = ui.geteditor()
2027 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2032 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2028 if not cmdpath:
2033 if not cmdpath:
2029 if editor == 'vi':
2034 if editor == 'vi':
2030 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2035 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2031 ui.write(_(" (specify a commit editor in your configuration"
2036 ui.write(_(" (specify a commit editor in your configuration"
2032 " file)\n"))
2037 " file)\n"))
2033 else:
2038 else:
2034 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2039 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2035 ui.write(_(" (specify a commit editor in your configuration"
2040 ui.write(_(" (specify a commit editor in your configuration"
2036 " file)\n"))
2041 " file)\n"))
2037 problems += 1
2042 problems += 1
2038
2043
2039 # check username
2044 # check username
2040 ui.status(_("checking username...\n"))
2045 ui.status(_("checking username...\n"))
2041 try:
2046 try:
2042 ui.username()
2047 ui.username()
2043 except util.Abort, e:
2048 except util.Abort, e:
2044 ui.write(" %s\n" % e)
2049 ui.write(" %s\n" % e)
2045 ui.write(_(" (specify a username in your configuration file)\n"))
2050 ui.write(_(" (specify a username in your configuration file)\n"))
2046 problems += 1
2051 problems += 1
2047
2052
2048 if not problems:
2053 if not problems:
2049 ui.status(_("no problems detected\n"))
2054 ui.status(_("no problems detected\n"))
2050 else:
2055 else:
2051 ui.write(_("%s problems detected,"
2056 ui.write(_("%s problems detected,"
2052 " please check your install!\n") % problems)
2057 " please check your install!\n") % problems)
2053
2058
2054 return problems
2059 return problems
2055
2060
2056 @command('debugknown', [], _('REPO ID...'))
2061 @command('debugknown', [], _('REPO ID...'))
2057 def debugknown(ui, repopath, *ids, **opts):
2062 def debugknown(ui, repopath, *ids, **opts):
2058 """test whether node ids are known to a repo
2063 """test whether node ids are known to a repo
2059
2064
2060 Every ID must be a full-length hex node id string. Returns a list of 0s
2065 Every ID must be a full-length hex node id string. Returns a list of 0s
2061 and 1s indicating unknown/known.
2066 and 1s indicating unknown/known.
2062 """
2067 """
2063 repo = hg.peer(ui, opts, repopath)
2068 repo = hg.peer(ui, opts, repopath)
2064 if not repo.capable('known'):
2069 if not repo.capable('known'):
2065 raise util.Abort("known() not supported by target repository")
2070 raise util.Abort("known() not supported by target repository")
2066 flags = repo.known([bin(s) for s in ids])
2071 flags = repo.known([bin(s) for s in ids])
2067 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2072 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2068
2073
2069 @command('debuglabelcomplete', [], _('LABEL...'))
2074 @command('debuglabelcomplete', [], _('LABEL...'))
2070 def debuglabelcomplete(ui, repo, *args):
2075 def debuglabelcomplete(ui, repo, *args):
2071 '''complete "labels" - tags, open branch names, bookmark names'''
2076 '''complete "labels" - tags, open branch names, bookmark names'''
2072
2077
2073 labels = set()
2078 labels = set()
2074 labels.update(t[0] for t in repo.tagslist())
2079 labels.update(t[0] for t in repo.tagslist())
2075 labels.update(repo._bookmarks.keys())
2080 labels.update(repo._bookmarks.keys())
2076 for heads in repo.branchmap().itervalues():
2081 for heads in repo.branchmap().itervalues():
2077 for h in heads:
2082 for h in heads:
2078 ctx = repo[h]
2083 ctx = repo[h]
2079 if not ctx.closesbranch():
2084 if not ctx.closesbranch():
2080 labels.add(ctx.branch())
2085 labels.add(ctx.branch())
2081 completions = set()
2086 completions = set()
2082 if not args:
2087 if not args:
2083 args = ['']
2088 args = ['']
2084 for a in args:
2089 for a in args:
2085 completions.update(l for l in labels if l.startswith(a))
2090 completions.update(l for l in labels if l.startswith(a))
2086 ui.write('\n'.join(sorted(completions)))
2091 ui.write('\n'.join(sorted(completions)))
2087 ui.write('\n')
2092 ui.write('\n')
2088
2093
2089 @command('debugobsolete',
2094 @command('debugobsolete',
2090 [('', 'flags', 0, _('markers flag')),
2095 [('', 'flags', 0, _('markers flag')),
2091 ] + commitopts2,
2096 ] + commitopts2,
2092 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2097 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2093 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2098 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2094 """create arbitrary obsolete marker
2099 """create arbitrary obsolete marker
2095
2100
2096 With no arguments, displays the list of obsolescence markers."""
2101 With no arguments, displays the list of obsolescence markers."""
2097 def parsenodeid(s):
2102 def parsenodeid(s):
2098 try:
2103 try:
2099 # We do not use revsingle/revrange functions here to accept
2104 # We do not use revsingle/revrange functions here to accept
2100 # arbitrary node identifiers, possibly not present in the
2105 # arbitrary node identifiers, possibly not present in the
2101 # local repository.
2106 # local repository.
2102 n = bin(s)
2107 n = bin(s)
2103 if len(n) != len(nullid):
2108 if len(n) != len(nullid):
2104 raise TypeError()
2109 raise TypeError()
2105 return n
2110 return n
2106 except TypeError:
2111 except TypeError:
2107 raise util.Abort('changeset references must be full hexadecimal '
2112 raise util.Abort('changeset references must be full hexadecimal '
2108 'node identifiers')
2113 'node identifiers')
2109
2114
2110 if precursor is not None:
2115 if precursor is not None:
2111 metadata = {}
2116 metadata = {}
2112 if 'date' in opts:
2117 if 'date' in opts:
2113 metadata['date'] = opts['date']
2118 metadata['date'] = opts['date']
2114 metadata['user'] = opts['user'] or ui.username()
2119 metadata['user'] = opts['user'] or ui.username()
2115 succs = tuple(parsenodeid(succ) for succ in successors)
2120 succs = tuple(parsenodeid(succ) for succ in successors)
2116 l = repo.lock()
2121 l = repo.lock()
2117 try:
2122 try:
2118 tr = repo.transaction('debugobsolete')
2123 tr = repo.transaction('debugobsolete')
2119 try:
2124 try:
2120 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2125 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2121 opts['flags'], metadata)
2126 opts['flags'], metadata)
2122 tr.close()
2127 tr.close()
2123 finally:
2128 finally:
2124 tr.release()
2129 tr.release()
2125 finally:
2130 finally:
2126 l.release()
2131 l.release()
2127 else:
2132 else:
2128 for m in obsolete.allmarkers(repo):
2133 for m in obsolete.allmarkers(repo):
2129 ui.write(hex(m.precnode()))
2134 ui.write(hex(m.precnode()))
2130 for repl in m.succnodes():
2135 for repl in m.succnodes():
2131 ui.write(' ')
2136 ui.write(' ')
2132 ui.write(hex(repl))
2137 ui.write(hex(repl))
2133 ui.write(' %X ' % m._data[2])
2138 ui.write(' %X ' % m._data[2])
2134 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2139 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2135 sorted(m.metadata().items()))))
2140 sorted(m.metadata().items()))))
2136 ui.write('\n')
2141 ui.write('\n')
2137
2142
2138 @command('debugpathcomplete',
2143 @command('debugpathcomplete',
2139 [('f', 'full', None, _('complete an entire path')),
2144 [('f', 'full', None, _('complete an entire path')),
2140 ('n', 'normal', None, _('show only normal files')),
2145 ('n', 'normal', None, _('show only normal files')),
2141 ('a', 'added', None, _('show only added files')),
2146 ('a', 'added', None, _('show only added files')),
2142 ('r', 'removed', None, _('show only removed files'))],
2147 ('r', 'removed', None, _('show only removed files'))],
2143 _('FILESPEC...'))
2148 _('FILESPEC...'))
2144 def debugpathcomplete(ui, repo, *specs, **opts):
2149 def debugpathcomplete(ui, repo, *specs, **opts):
2145 '''complete part or all of a tracked path
2150 '''complete part or all of a tracked path
2146
2151
2147 This command supports shells that offer path name completion. It
2152 This command supports shells that offer path name completion. It
2148 currently completes only files already known to the dirstate.
2153 currently completes only files already known to the dirstate.
2149
2154
2150 Completion extends only to the next path segment unless
2155 Completion extends only to the next path segment unless
2151 --full is specified, in which case entire paths are used.'''
2156 --full is specified, in which case entire paths are used.'''
2152
2157
2153 def complete(path, acceptable):
2158 def complete(path, acceptable):
2154 dirstate = repo.dirstate
2159 dirstate = repo.dirstate
2155 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2160 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2156 rootdir = repo.root + os.sep
2161 rootdir = repo.root + os.sep
2157 if spec != repo.root and not spec.startswith(rootdir):
2162 if spec != repo.root and not spec.startswith(rootdir):
2158 return [], []
2163 return [], []
2159 if os.path.isdir(spec):
2164 if os.path.isdir(spec):
2160 spec += '/'
2165 spec += '/'
2161 spec = spec[len(rootdir):]
2166 spec = spec[len(rootdir):]
2162 fixpaths = os.sep != '/'
2167 fixpaths = os.sep != '/'
2163 if fixpaths:
2168 if fixpaths:
2164 spec = spec.replace(os.sep, '/')
2169 spec = spec.replace(os.sep, '/')
2165 speclen = len(spec)
2170 speclen = len(spec)
2166 fullpaths = opts['full']
2171 fullpaths = opts['full']
2167 files, dirs = set(), set()
2172 files, dirs = set(), set()
2168 adddir, addfile = dirs.add, files.add
2173 adddir, addfile = dirs.add, files.add
2169 for f, st in dirstate.iteritems():
2174 for f, st in dirstate.iteritems():
2170 if f.startswith(spec) and st[0] in acceptable:
2175 if f.startswith(spec) and st[0] in acceptable:
2171 if fixpaths:
2176 if fixpaths:
2172 f = f.replace('/', os.sep)
2177 f = f.replace('/', os.sep)
2173 if fullpaths:
2178 if fullpaths:
2174 addfile(f)
2179 addfile(f)
2175 continue
2180 continue
2176 s = f.find(os.sep, speclen)
2181 s = f.find(os.sep, speclen)
2177 if s >= 0:
2182 if s >= 0:
2178 adddir(f[:s + 1])
2183 adddir(f[:s + 1])
2179 else:
2184 else:
2180 addfile(f)
2185 addfile(f)
2181 return files, dirs
2186 return files, dirs
2182
2187
2183 acceptable = ''
2188 acceptable = ''
2184 if opts['normal']:
2189 if opts['normal']:
2185 acceptable += 'nm'
2190 acceptable += 'nm'
2186 if opts['added']:
2191 if opts['added']:
2187 acceptable += 'a'
2192 acceptable += 'a'
2188 if opts['removed']:
2193 if opts['removed']:
2189 acceptable += 'r'
2194 acceptable += 'r'
2190 cwd = repo.getcwd()
2195 cwd = repo.getcwd()
2191 if not specs:
2196 if not specs:
2192 specs = ['.']
2197 specs = ['.']
2193
2198
2194 files, dirs = set(), set()
2199 files, dirs = set(), set()
2195 for spec in specs:
2200 for spec in specs:
2196 f, d = complete(spec, acceptable or 'nmar')
2201 f, d = complete(spec, acceptable or 'nmar')
2197 files.update(f)
2202 files.update(f)
2198 dirs.update(d)
2203 dirs.update(d)
2199 if not files and len(dirs) == 1:
2204 if not files and len(dirs) == 1:
2200 # force the shell to consider a completion that matches one
2205 # force the shell to consider a completion that matches one
2201 # directory and zero files to be ambiguous
2206 # directory and zero files to be ambiguous
2202 dirs.add(iter(dirs).next() + '.')
2207 dirs.add(iter(dirs).next() + '.')
2203 files.update(dirs)
2208 files.update(dirs)
2204 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2209 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2205 ui.write('\n')
2210 ui.write('\n')
2206
2211
2207 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2212 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2208 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2213 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2209 '''access the pushkey key/value protocol
2214 '''access the pushkey key/value protocol
2210
2215
2211 With two args, list the keys in the given namespace.
2216 With two args, list the keys in the given namespace.
2212
2217
2213 With five args, set a key to new if it currently is set to old.
2218 With five args, set a key to new if it currently is set to old.
2214 Reports success or failure.
2219 Reports success or failure.
2215 '''
2220 '''
2216
2221
2217 target = hg.peer(ui, {}, repopath)
2222 target = hg.peer(ui, {}, repopath)
2218 if keyinfo:
2223 if keyinfo:
2219 key, old, new = keyinfo
2224 key, old, new = keyinfo
2220 r = target.pushkey(namespace, key, old, new)
2225 r = target.pushkey(namespace, key, old, new)
2221 ui.status(str(r) + '\n')
2226 ui.status(str(r) + '\n')
2222 return not r
2227 return not r
2223 else:
2228 else:
2224 for k, v in sorted(target.listkeys(namespace).iteritems()):
2229 for k, v in sorted(target.listkeys(namespace).iteritems()):
2225 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2230 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2226 v.encode('string-escape')))
2231 v.encode('string-escape')))
2227
2232
2228 @command('debugpvec', [], _('A B'))
2233 @command('debugpvec', [], _('A B'))
2229 def debugpvec(ui, repo, a, b=None):
2234 def debugpvec(ui, repo, a, b=None):
2230 ca = scmutil.revsingle(repo, a)
2235 ca = scmutil.revsingle(repo, a)
2231 cb = scmutil.revsingle(repo, b)
2236 cb = scmutil.revsingle(repo, b)
2232 pa = pvec.ctxpvec(ca)
2237 pa = pvec.ctxpvec(ca)
2233 pb = pvec.ctxpvec(cb)
2238 pb = pvec.ctxpvec(cb)
2234 if pa == pb:
2239 if pa == pb:
2235 rel = "="
2240 rel = "="
2236 elif pa > pb:
2241 elif pa > pb:
2237 rel = ">"
2242 rel = ">"
2238 elif pa < pb:
2243 elif pa < pb:
2239 rel = "<"
2244 rel = "<"
2240 elif pa | pb:
2245 elif pa | pb:
2241 rel = "|"
2246 rel = "|"
2242 ui.write(_("a: %s\n") % pa)
2247 ui.write(_("a: %s\n") % pa)
2243 ui.write(_("b: %s\n") % pb)
2248 ui.write(_("b: %s\n") % pb)
2244 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2249 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2245 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2250 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2246 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2251 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2247 pa.distance(pb), rel))
2252 pa.distance(pb), rel))
2248
2253
2249 @command('debugrebuilddirstate|debugrebuildstate',
2254 @command('debugrebuilddirstate|debugrebuildstate',
2250 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2255 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2251 _('[-r REV]'))
2256 _('[-r REV]'))
2252 def debugrebuilddirstate(ui, repo, rev):
2257 def debugrebuilddirstate(ui, repo, rev):
2253 """rebuild the dirstate as it would look like for the given revision
2258 """rebuild the dirstate as it would look like for the given revision
2254
2259
2255 If no revision is specified the first current parent will be used.
2260 If no revision is specified the first current parent will be used.
2256
2261
2257 The dirstate will be set to the files of the given revision.
2262 The dirstate will be set to the files of the given revision.
2258 The actual working directory content or existing dirstate
2263 The actual working directory content or existing dirstate
2259 information such as adds or removes is not considered.
2264 information such as adds or removes is not considered.
2260
2265
2261 One use of this command is to make the next :hg:`status` invocation
2266 One use of this command is to make the next :hg:`status` invocation
2262 check the actual file content.
2267 check the actual file content.
2263 """
2268 """
2264 ctx = scmutil.revsingle(repo, rev)
2269 ctx = scmutil.revsingle(repo, rev)
2265 wlock = repo.wlock()
2270 wlock = repo.wlock()
2266 try:
2271 try:
2267 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2272 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2268 finally:
2273 finally:
2269 wlock.release()
2274 wlock.release()
2270
2275
2271 @command('debugrename',
2276 @command('debugrename',
2272 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2277 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2273 _('[-r REV] FILE'))
2278 _('[-r REV] FILE'))
2274 def debugrename(ui, repo, file1, *pats, **opts):
2279 def debugrename(ui, repo, file1, *pats, **opts):
2275 """dump rename information"""
2280 """dump rename information"""
2276
2281
2277 ctx = scmutil.revsingle(repo, opts.get('rev'))
2282 ctx = scmutil.revsingle(repo, opts.get('rev'))
2278 m = scmutil.match(ctx, (file1,) + pats, opts)
2283 m = scmutil.match(ctx, (file1,) + pats, opts)
2279 for abs in ctx.walk(m):
2284 for abs in ctx.walk(m):
2280 fctx = ctx[abs]
2285 fctx = ctx[abs]
2281 o = fctx.filelog().renamed(fctx.filenode())
2286 o = fctx.filelog().renamed(fctx.filenode())
2282 rel = m.rel(abs)
2287 rel = m.rel(abs)
2283 if o:
2288 if o:
2284 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2289 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2285 else:
2290 else:
2286 ui.write(_("%s not renamed\n") % rel)
2291 ui.write(_("%s not renamed\n") % rel)
2287
2292
2288 @command('debugrevlog',
2293 @command('debugrevlog',
2289 [('c', 'changelog', False, _('open changelog')),
2294 [('c', 'changelog', False, _('open changelog')),
2290 ('m', 'manifest', False, _('open manifest')),
2295 ('m', 'manifest', False, _('open manifest')),
2291 ('d', 'dump', False, _('dump index data'))],
2296 ('d', 'dump', False, _('dump index data'))],
2292 _('-c|-m|FILE'))
2297 _('-c|-m|FILE'))
2293 def debugrevlog(ui, repo, file_ = None, **opts):
2298 def debugrevlog(ui, repo, file_ = None, **opts):
2294 """show data and statistics about a revlog"""
2299 """show data and statistics about a revlog"""
2295 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2300 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2296
2301
2297 if opts.get("dump"):
2302 if opts.get("dump"):
2298 numrevs = len(r)
2303 numrevs = len(r)
2299 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2304 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2300 " rawsize totalsize compression heads\n")
2305 " rawsize totalsize compression heads\n")
2301 ts = 0
2306 ts = 0
2302 heads = set()
2307 heads = set()
2303 for rev in xrange(numrevs):
2308 for rev in xrange(numrevs):
2304 dbase = r.deltaparent(rev)
2309 dbase = r.deltaparent(rev)
2305 if dbase == -1:
2310 if dbase == -1:
2306 dbase = rev
2311 dbase = rev
2307 cbase = r.chainbase(rev)
2312 cbase = r.chainbase(rev)
2308 p1, p2 = r.parentrevs(rev)
2313 p1, p2 = r.parentrevs(rev)
2309 rs = r.rawsize(rev)
2314 rs = r.rawsize(rev)
2310 ts = ts + rs
2315 ts = ts + rs
2311 heads -= set(r.parentrevs(rev))
2316 heads -= set(r.parentrevs(rev))
2312 heads.add(rev)
2317 heads.add(rev)
2313 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2318 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2314 (rev, p1, p2, r.start(rev), r.end(rev),
2319 (rev, p1, p2, r.start(rev), r.end(rev),
2315 r.start(dbase), r.start(cbase),
2320 r.start(dbase), r.start(cbase),
2316 r.start(p1), r.start(p2),
2321 r.start(p1), r.start(p2),
2317 rs, ts, ts / r.end(rev), len(heads)))
2322 rs, ts, ts / r.end(rev), len(heads)))
2318 return 0
2323 return 0
2319
2324
2320 v = r.version
2325 v = r.version
2321 format = v & 0xFFFF
2326 format = v & 0xFFFF
2322 flags = []
2327 flags = []
2323 gdelta = False
2328 gdelta = False
2324 if v & revlog.REVLOGNGINLINEDATA:
2329 if v & revlog.REVLOGNGINLINEDATA:
2325 flags.append('inline')
2330 flags.append('inline')
2326 if v & revlog.REVLOGGENERALDELTA:
2331 if v & revlog.REVLOGGENERALDELTA:
2327 gdelta = True
2332 gdelta = True
2328 flags.append('generaldelta')
2333 flags.append('generaldelta')
2329 if not flags:
2334 if not flags:
2330 flags = ['(none)']
2335 flags = ['(none)']
2331
2336
2332 nummerges = 0
2337 nummerges = 0
2333 numfull = 0
2338 numfull = 0
2334 numprev = 0
2339 numprev = 0
2335 nump1 = 0
2340 nump1 = 0
2336 nump2 = 0
2341 nump2 = 0
2337 numother = 0
2342 numother = 0
2338 nump1prev = 0
2343 nump1prev = 0
2339 nump2prev = 0
2344 nump2prev = 0
2340 chainlengths = []
2345 chainlengths = []
2341
2346
2342 datasize = [None, 0, 0L]
2347 datasize = [None, 0, 0L]
2343 fullsize = [None, 0, 0L]
2348 fullsize = [None, 0, 0L]
2344 deltasize = [None, 0, 0L]
2349 deltasize = [None, 0, 0L]
2345
2350
2346 def addsize(size, l):
2351 def addsize(size, l):
2347 if l[0] is None or size < l[0]:
2352 if l[0] is None or size < l[0]:
2348 l[0] = size
2353 l[0] = size
2349 if size > l[1]:
2354 if size > l[1]:
2350 l[1] = size
2355 l[1] = size
2351 l[2] += size
2356 l[2] += size
2352
2357
2353 numrevs = len(r)
2358 numrevs = len(r)
2354 for rev in xrange(numrevs):
2359 for rev in xrange(numrevs):
2355 p1, p2 = r.parentrevs(rev)
2360 p1, p2 = r.parentrevs(rev)
2356 delta = r.deltaparent(rev)
2361 delta = r.deltaparent(rev)
2357 if format > 0:
2362 if format > 0:
2358 addsize(r.rawsize(rev), datasize)
2363 addsize(r.rawsize(rev), datasize)
2359 if p2 != nullrev:
2364 if p2 != nullrev:
2360 nummerges += 1
2365 nummerges += 1
2361 size = r.length(rev)
2366 size = r.length(rev)
2362 if delta == nullrev:
2367 if delta == nullrev:
2363 chainlengths.append(0)
2368 chainlengths.append(0)
2364 numfull += 1
2369 numfull += 1
2365 addsize(size, fullsize)
2370 addsize(size, fullsize)
2366 else:
2371 else:
2367 chainlengths.append(chainlengths[delta] + 1)
2372 chainlengths.append(chainlengths[delta] + 1)
2368 addsize(size, deltasize)
2373 addsize(size, deltasize)
2369 if delta == rev - 1:
2374 if delta == rev - 1:
2370 numprev += 1
2375 numprev += 1
2371 if delta == p1:
2376 if delta == p1:
2372 nump1prev += 1
2377 nump1prev += 1
2373 elif delta == p2:
2378 elif delta == p2:
2374 nump2prev += 1
2379 nump2prev += 1
2375 elif delta == p1:
2380 elif delta == p1:
2376 nump1 += 1
2381 nump1 += 1
2377 elif delta == p2:
2382 elif delta == p2:
2378 nump2 += 1
2383 nump2 += 1
2379 elif delta != nullrev:
2384 elif delta != nullrev:
2380 numother += 1
2385 numother += 1
2381
2386
2382 # Adjust size min value for empty cases
2387 # Adjust size min value for empty cases
2383 for size in (datasize, fullsize, deltasize):
2388 for size in (datasize, fullsize, deltasize):
2384 if size[0] is None:
2389 if size[0] is None:
2385 size[0] = 0
2390 size[0] = 0
2386
2391
2387 numdeltas = numrevs - numfull
2392 numdeltas = numrevs - numfull
2388 numoprev = numprev - nump1prev - nump2prev
2393 numoprev = numprev - nump1prev - nump2prev
2389 totalrawsize = datasize[2]
2394 totalrawsize = datasize[2]
2390 datasize[2] /= numrevs
2395 datasize[2] /= numrevs
2391 fulltotal = fullsize[2]
2396 fulltotal = fullsize[2]
2392 fullsize[2] /= numfull
2397 fullsize[2] /= numfull
2393 deltatotal = deltasize[2]
2398 deltatotal = deltasize[2]
2394 if numrevs - numfull > 0:
2399 if numrevs - numfull > 0:
2395 deltasize[2] /= numrevs - numfull
2400 deltasize[2] /= numrevs - numfull
2396 totalsize = fulltotal + deltatotal
2401 totalsize = fulltotal + deltatotal
2397 avgchainlen = sum(chainlengths) / numrevs
2402 avgchainlen = sum(chainlengths) / numrevs
2398 compratio = totalrawsize / totalsize
2403 compratio = totalrawsize / totalsize
2399
2404
2400 basedfmtstr = '%%%dd\n'
2405 basedfmtstr = '%%%dd\n'
2401 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2406 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2402
2407
2403 def dfmtstr(max):
2408 def dfmtstr(max):
2404 return basedfmtstr % len(str(max))
2409 return basedfmtstr % len(str(max))
2405 def pcfmtstr(max, padding=0):
2410 def pcfmtstr(max, padding=0):
2406 return basepcfmtstr % (len(str(max)), ' ' * padding)
2411 return basepcfmtstr % (len(str(max)), ' ' * padding)
2407
2412
2408 def pcfmt(value, total):
2413 def pcfmt(value, total):
2409 return (value, 100 * float(value) / total)
2414 return (value, 100 * float(value) / total)
2410
2415
2411 ui.write(('format : %d\n') % format)
2416 ui.write(('format : %d\n') % format)
2412 ui.write(('flags : %s\n') % ', '.join(flags))
2417 ui.write(('flags : %s\n') % ', '.join(flags))
2413
2418
2414 ui.write('\n')
2419 ui.write('\n')
2415 fmt = pcfmtstr(totalsize)
2420 fmt = pcfmtstr(totalsize)
2416 fmt2 = dfmtstr(totalsize)
2421 fmt2 = dfmtstr(totalsize)
2417 ui.write(('revisions : ') + fmt2 % numrevs)
2422 ui.write(('revisions : ') + fmt2 % numrevs)
2418 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2423 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2419 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2424 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2420 ui.write(('revisions : ') + fmt2 % numrevs)
2425 ui.write(('revisions : ') + fmt2 % numrevs)
2421 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2426 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2422 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2427 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2423 ui.write(('revision size : ') + fmt2 % totalsize)
2428 ui.write(('revision size : ') + fmt2 % totalsize)
2424 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2429 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2425 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2430 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2426
2431
2427 ui.write('\n')
2432 ui.write('\n')
2428 fmt = dfmtstr(max(avgchainlen, compratio))
2433 fmt = dfmtstr(max(avgchainlen, compratio))
2429 ui.write(('avg chain length : ') + fmt % avgchainlen)
2434 ui.write(('avg chain length : ') + fmt % avgchainlen)
2430 ui.write(('compression ratio : ') + fmt % compratio)
2435 ui.write(('compression ratio : ') + fmt % compratio)
2431
2436
2432 if format > 0:
2437 if format > 0:
2433 ui.write('\n')
2438 ui.write('\n')
2434 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2439 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2435 % tuple(datasize))
2440 % tuple(datasize))
2436 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2441 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2437 % tuple(fullsize))
2442 % tuple(fullsize))
2438 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2443 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2439 % tuple(deltasize))
2444 % tuple(deltasize))
2440
2445
2441 if numdeltas > 0:
2446 if numdeltas > 0:
2442 ui.write('\n')
2447 ui.write('\n')
2443 fmt = pcfmtstr(numdeltas)
2448 fmt = pcfmtstr(numdeltas)
2444 fmt2 = pcfmtstr(numdeltas, 4)
2449 fmt2 = pcfmtstr(numdeltas, 4)
2445 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2450 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2446 if numprev > 0:
2451 if numprev > 0:
2447 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2452 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2448 numprev))
2453 numprev))
2449 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2454 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2450 numprev))
2455 numprev))
2451 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2456 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2452 numprev))
2457 numprev))
2453 if gdelta:
2458 if gdelta:
2454 ui.write(('deltas against p1 : ')
2459 ui.write(('deltas against p1 : ')
2455 + fmt % pcfmt(nump1, numdeltas))
2460 + fmt % pcfmt(nump1, numdeltas))
2456 ui.write(('deltas against p2 : ')
2461 ui.write(('deltas against p2 : ')
2457 + fmt % pcfmt(nump2, numdeltas))
2462 + fmt % pcfmt(nump2, numdeltas))
2458 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2463 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2459 numdeltas))
2464 numdeltas))
2460
2465
2461 @command('debugrevspec', [], ('REVSPEC'))
2466 @command('debugrevspec', [], ('REVSPEC'))
2462 def debugrevspec(ui, repo, expr):
2467 def debugrevspec(ui, repo, expr):
2463 """parse and apply a revision specification
2468 """parse and apply a revision specification
2464
2469
2465 Use --verbose to print the parsed tree before and after aliases
2470 Use --verbose to print the parsed tree before and after aliases
2466 expansion.
2471 expansion.
2467 """
2472 """
2468 if ui.verbose:
2473 if ui.verbose:
2469 tree = revset.parse(expr)[0]
2474 tree = revset.parse(expr)[0]
2470 ui.note(revset.prettyformat(tree), "\n")
2475 ui.note(revset.prettyformat(tree), "\n")
2471 newtree = revset.findaliases(ui, tree)
2476 newtree = revset.findaliases(ui, tree)
2472 if newtree != tree:
2477 if newtree != tree:
2473 ui.note(revset.prettyformat(newtree), "\n")
2478 ui.note(revset.prettyformat(newtree), "\n")
2474 func = revset.match(ui, expr)
2479 func = revset.match(ui, expr)
2475 for c in func(repo, range(len(repo))):
2480 for c in func(repo, range(len(repo))):
2476 ui.write("%s\n" % c)
2481 ui.write("%s\n" % c)
2477
2482
2478 @command('debugsetparents', [], _('REV1 [REV2]'))
2483 @command('debugsetparents', [], _('REV1 [REV2]'))
2479 def debugsetparents(ui, repo, rev1, rev2=None):
2484 def debugsetparents(ui, repo, rev1, rev2=None):
2480 """manually set the parents of the current working directory
2485 """manually set the parents of the current working directory
2481
2486
2482 This is useful for writing repository conversion tools, but should
2487 This is useful for writing repository conversion tools, but should
2483 be used with care.
2488 be used with care.
2484
2489
2485 Returns 0 on success.
2490 Returns 0 on success.
2486 """
2491 """
2487
2492
2488 r1 = scmutil.revsingle(repo, rev1).node()
2493 r1 = scmutil.revsingle(repo, rev1).node()
2489 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2494 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2490
2495
2491 wlock = repo.wlock()
2496 wlock = repo.wlock()
2492 try:
2497 try:
2493 repo.setparents(r1, r2)
2498 repo.setparents(r1, r2)
2494 finally:
2499 finally:
2495 wlock.release()
2500 wlock.release()
2496
2501
2497 @command('debugdirstate|debugstate',
2502 @command('debugdirstate|debugstate',
2498 [('', 'nodates', None, _('do not display the saved mtime')),
2503 [('', 'nodates', None, _('do not display the saved mtime')),
2499 ('', 'datesort', None, _('sort by saved mtime'))],
2504 ('', 'datesort', None, _('sort by saved mtime'))],
2500 _('[OPTION]...'))
2505 _('[OPTION]...'))
2501 def debugstate(ui, repo, nodates=None, datesort=None):
2506 def debugstate(ui, repo, nodates=None, datesort=None):
2502 """show the contents of the current dirstate"""
2507 """show the contents of the current dirstate"""
2503 timestr = ""
2508 timestr = ""
2504 showdate = not nodates
2509 showdate = not nodates
2505 if datesort:
2510 if datesort:
2506 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2511 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2507 else:
2512 else:
2508 keyfunc = None # sort by filename
2513 keyfunc = None # sort by filename
2509 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2514 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2510 if showdate:
2515 if showdate:
2511 if ent[3] == -1:
2516 if ent[3] == -1:
2512 # Pad or slice to locale representation
2517 # Pad or slice to locale representation
2513 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2518 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2514 time.localtime(0)))
2519 time.localtime(0)))
2515 timestr = 'unset'
2520 timestr = 'unset'
2516 timestr = (timestr[:locale_len] +
2521 timestr = (timestr[:locale_len] +
2517 ' ' * (locale_len - len(timestr)))
2522 ' ' * (locale_len - len(timestr)))
2518 else:
2523 else:
2519 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2524 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2520 time.localtime(ent[3]))
2525 time.localtime(ent[3]))
2521 if ent[1] & 020000:
2526 if ent[1] & 020000:
2522 mode = 'lnk'
2527 mode = 'lnk'
2523 else:
2528 else:
2524 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2529 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2525 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2530 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2526 for f in repo.dirstate.copies():
2531 for f in repo.dirstate.copies():
2527 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2532 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2528
2533
2529 @command('debugsub',
2534 @command('debugsub',
2530 [('r', 'rev', '',
2535 [('r', 'rev', '',
2531 _('revision to check'), _('REV'))],
2536 _('revision to check'), _('REV'))],
2532 _('[-r REV] [REV]'))
2537 _('[-r REV] [REV]'))
2533 def debugsub(ui, repo, rev=None):
2538 def debugsub(ui, repo, rev=None):
2534 ctx = scmutil.revsingle(repo, rev, None)
2539 ctx = scmutil.revsingle(repo, rev, None)
2535 for k, v in sorted(ctx.substate.items()):
2540 for k, v in sorted(ctx.substate.items()):
2536 ui.write(('path %s\n') % k)
2541 ui.write(('path %s\n') % k)
2537 ui.write((' source %s\n') % v[0])
2542 ui.write((' source %s\n') % v[0])
2538 ui.write((' revision %s\n') % v[1])
2543 ui.write((' revision %s\n') % v[1])
2539
2544
2540 @command('debugsuccessorssets',
2545 @command('debugsuccessorssets',
2541 [],
2546 [],
2542 _('[REV]'))
2547 _('[REV]'))
2543 def debugsuccessorssets(ui, repo, *revs):
2548 def debugsuccessorssets(ui, repo, *revs):
2544 """show set of successors for revision
2549 """show set of successors for revision
2545
2550
2546 A successors set of changeset A is a consistent group of revisions that
2551 A successors set of changeset A is a consistent group of revisions that
2547 succeed A. It contains non-obsolete changesets only.
2552 succeed A. It contains non-obsolete changesets only.
2548
2553
2549 In most cases a changeset A has a single successors set containing a single
2554 In most cases a changeset A has a single successors set containing a single
2550 successor (changeset A replaced by A').
2555 successor (changeset A replaced by A').
2551
2556
2552 A changeset that is made obsolete with no successors are called "pruned".
2557 A changeset that is made obsolete with no successors are called "pruned".
2553 Such changesets have no successors sets at all.
2558 Such changesets have no successors sets at all.
2554
2559
2555 A changeset that has been "split" will have a successors set containing
2560 A changeset that has been "split" will have a successors set containing
2556 more than one successor.
2561 more than one successor.
2557
2562
2558 A changeset that has been rewritten in multiple different ways is called
2563 A changeset that has been rewritten in multiple different ways is called
2559 "divergent". Such changesets have multiple successor sets (each of which
2564 "divergent". Such changesets have multiple successor sets (each of which
2560 may also be split, i.e. have multiple successors).
2565 may also be split, i.e. have multiple successors).
2561
2566
2562 Results are displayed as follows::
2567 Results are displayed as follows::
2563
2568
2564 <rev1>
2569 <rev1>
2565 <successors-1A>
2570 <successors-1A>
2566 <rev2>
2571 <rev2>
2567 <successors-2A>
2572 <successors-2A>
2568 <successors-2B1> <successors-2B2> <successors-2B3>
2573 <successors-2B1> <successors-2B2> <successors-2B3>
2569
2574
2570 Here rev2 has two possible (i.e. divergent) successors sets. The first
2575 Here rev2 has two possible (i.e. divergent) successors sets. The first
2571 holds one element, whereas the second holds three (i.e. the changeset has
2576 holds one element, whereas the second holds three (i.e. the changeset has
2572 been split).
2577 been split).
2573 """
2578 """
2574 # passed to successorssets caching computation from one call to another
2579 # passed to successorssets caching computation from one call to another
2575 cache = {}
2580 cache = {}
2576 ctx2str = str
2581 ctx2str = str
2577 node2str = short
2582 node2str = short
2578 if ui.debug():
2583 if ui.debug():
2579 def ctx2str(ctx):
2584 def ctx2str(ctx):
2580 return ctx.hex()
2585 return ctx.hex()
2581 node2str = hex
2586 node2str = hex
2582 for rev in scmutil.revrange(repo, revs):
2587 for rev in scmutil.revrange(repo, revs):
2583 ctx = repo[rev]
2588 ctx = repo[rev]
2584 ui.write('%s\n'% ctx2str(ctx))
2589 ui.write('%s\n'% ctx2str(ctx))
2585 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2590 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2586 if succsset:
2591 if succsset:
2587 ui.write(' ')
2592 ui.write(' ')
2588 ui.write(node2str(succsset[0]))
2593 ui.write(node2str(succsset[0]))
2589 for node in succsset[1:]:
2594 for node in succsset[1:]:
2590 ui.write(' ')
2595 ui.write(' ')
2591 ui.write(node2str(node))
2596 ui.write(node2str(node))
2592 ui.write('\n')
2597 ui.write('\n')
2593
2598
2594 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2599 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2595 def debugwalk(ui, repo, *pats, **opts):
2600 def debugwalk(ui, repo, *pats, **opts):
2596 """show how files match on given patterns"""
2601 """show how files match on given patterns"""
2597 m = scmutil.match(repo[None], pats, opts)
2602 m = scmutil.match(repo[None], pats, opts)
2598 items = list(repo.walk(m))
2603 items = list(repo.walk(m))
2599 if not items:
2604 if not items:
2600 return
2605 return
2601 f = lambda fn: fn
2606 f = lambda fn: fn
2602 if ui.configbool('ui', 'slash') and os.sep != '/':
2607 if ui.configbool('ui', 'slash') and os.sep != '/':
2603 f = lambda fn: util.normpath(fn)
2608 f = lambda fn: util.normpath(fn)
2604 fmt = 'f %%-%ds %%-%ds %%s' % (
2609 fmt = 'f %%-%ds %%-%ds %%s' % (
2605 max([len(abs) for abs in items]),
2610 max([len(abs) for abs in items]),
2606 max([len(m.rel(abs)) for abs in items]))
2611 max([len(m.rel(abs)) for abs in items]))
2607 for abs in items:
2612 for abs in items:
2608 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2613 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2609 ui.write("%s\n" % line.rstrip())
2614 ui.write("%s\n" % line.rstrip())
2610
2615
2611 @command('debugwireargs',
2616 @command('debugwireargs',
2612 [('', 'three', '', 'three'),
2617 [('', 'three', '', 'three'),
2613 ('', 'four', '', 'four'),
2618 ('', 'four', '', 'four'),
2614 ('', 'five', '', 'five'),
2619 ('', 'five', '', 'five'),
2615 ] + remoteopts,
2620 ] + remoteopts,
2616 _('REPO [OPTIONS]... [ONE [TWO]]'))
2621 _('REPO [OPTIONS]... [ONE [TWO]]'))
2617 def debugwireargs(ui, repopath, *vals, **opts):
2622 def debugwireargs(ui, repopath, *vals, **opts):
2618 repo = hg.peer(ui, opts, repopath)
2623 repo = hg.peer(ui, opts, repopath)
2619 for opt in remoteopts:
2624 for opt in remoteopts:
2620 del opts[opt[1]]
2625 del opts[opt[1]]
2621 args = {}
2626 args = {}
2622 for k, v in opts.iteritems():
2627 for k, v in opts.iteritems():
2623 if v:
2628 if v:
2624 args[k] = v
2629 args[k] = v
2625 # run twice to check that we don't mess up the stream for the next command
2630 # run twice to check that we don't mess up the stream for the next command
2626 res1 = repo.debugwireargs(*vals, **args)
2631 res1 = repo.debugwireargs(*vals, **args)
2627 res2 = repo.debugwireargs(*vals, **args)
2632 res2 = repo.debugwireargs(*vals, **args)
2628 ui.write("%s\n" % res1)
2633 ui.write("%s\n" % res1)
2629 if res1 != res2:
2634 if res1 != res2:
2630 ui.warn("%s\n" % res2)
2635 ui.warn("%s\n" % res2)
2631
2636
2632 @command('^diff',
2637 @command('^diff',
2633 [('r', 'rev', [], _('revision'), _('REV')),
2638 [('r', 'rev', [], _('revision'), _('REV')),
2634 ('c', 'change', '', _('change made by revision'), _('REV'))
2639 ('c', 'change', '', _('change made by revision'), _('REV'))
2635 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2640 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2636 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2641 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2637 def diff(ui, repo, *pats, **opts):
2642 def diff(ui, repo, *pats, **opts):
2638 """diff repository (or selected files)
2643 """diff repository (or selected files)
2639
2644
2640 Show differences between revisions for the specified files.
2645 Show differences between revisions for the specified files.
2641
2646
2642 Differences between files are shown using the unified diff format.
2647 Differences between files are shown using the unified diff format.
2643
2648
2644 .. note::
2649 .. note::
2645 diff may generate unexpected results for merges, as it will
2650 diff may generate unexpected results for merges, as it will
2646 default to comparing against the working directory's first
2651 default to comparing against the working directory's first
2647 parent changeset if no revisions are specified.
2652 parent changeset if no revisions are specified.
2648
2653
2649 When two revision arguments are given, then changes are shown
2654 When two revision arguments are given, then changes are shown
2650 between those revisions. If only one revision is specified then
2655 between those revisions. If only one revision is specified then
2651 that revision is compared to the working directory, and, when no
2656 that revision is compared to the working directory, and, when no
2652 revisions are specified, the working directory files are compared
2657 revisions are specified, the working directory files are compared
2653 to its parent.
2658 to its parent.
2654
2659
2655 Alternatively you can specify -c/--change with a revision to see
2660 Alternatively you can specify -c/--change with a revision to see
2656 the changes in that changeset relative to its first parent.
2661 the changes in that changeset relative to its first parent.
2657
2662
2658 Without the -a/--text option, diff will avoid generating diffs of
2663 Without the -a/--text option, diff will avoid generating diffs of
2659 files it detects as binary. With -a, diff will generate a diff
2664 files it detects as binary. With -a, diff will generate a diff
2660 anyway, probably with undesirable results.
2665 anyway, probably with undesirable results.
2661
2666
2662 Use the -g/--git option to generate diffs in the git extended diff
2667 Use the -g/--git option to generate diffs in the git extended diff
2663 format. For more information, read :hg:`help diffs`.
2668 format. For more information, read :hg:`help diffs`.
2664
2669
2665 .. container:: verbose
2670 .. container:: verbose
2666
2671
2667 Examples:
2672 Examples:
2668
2673
2669 - compare a file in the current working directory to its parent::
2674 - compare a file in the current working directory to its parent::
2670
2675
2671 hg diff foo.c
2676 hg diff foo.c
2672
2677
2673 - compare two historical versions of a directory, with rename info::
2678 - compare two historical versions of a directory, with rename info::
2674
2679
2675 hg diff --git -r 1.0:1.2 lib/
2680 hg diff --git -r 1.0:1.2 lib/
2676
2681
2677 - get change stats relative to the last change on some date::
2682 - get change stats relative to the last change on some date::
2678
2683
2679 hg diff --stat -r "date('may 2')"
2684 hg diff --stat -r "date('may 2')"
2680
2685
2681 - diff all newly-added files that contain a keyword::
2686 - diff all newly-added files that contain a keyword::
2682
2687
2683 hg diff "set:added() and grep(GNU)"
2688 hg diff "set:added() and grep(GNU)"
2684
2689
2685 - compare a revision and its parents::
2690 - compare a revision and its parents::
2686
2691
2687 hg diff -c 9353 # compare against first parent
2692 hg diff -c 9353 # compare against first parent
2688 hg diff -r 9353^:9353 # same using revset syntax
2693 hg diff -r 9353^:9353 # same using revset syntax
2689 hg diff -r 9353^2:9353 # compare against the second parent
2694 hg diff -r 9353^2:9353 # compare against the second parent
2690
2695
2691 Returns 0 on success.
2696 Returns 0 on success.
2692 """
2697 """
2693
2698
2694 revs = opts.get('rev')
2699 revs = opts.get('rev')
2695 change = opts.get('change')
2700 change = opts.get('change')
2696 stat = opts.get('stat')
2701 stat = opts.get('stat')
2697 reverse = opts.get('reverse')
2702 reverse = opts.get('reverse')
2698
2703
2699 if revs and change:
2704 if revs and change:
2700 msg = _('cannot specify --rev and --change at the same time')
2705 msg = _('cannot specify --rev and --change at the same time')
2701 raise util.Abort(msg)
2706 raise util.Abort(msg)
2702 elif change:
2707 elif change:
2703 node2 = scmutil.revsingle(repo, change, None).node()
2708 node2 = scmutil.revsingle(repo, change, None).node()
2704 node1 = repo[node2].p1().node()
2709 node1 = repo[node2].p1().node()
2705 else:
2710 else:
2706 node1, node2 = scmutil.revpair(repo, revs)
2711 node1, node2 = scmutil.revpair(repo, revs)
2707
2712
2708 if reverse:
2713 if reverse:
2709 node1, node2 = node2, node1
2714 node1, node2 = node2, node1
2710
2715
2711 diffopts = patch.diffopts(ui, opts)
2716 diffopts = patch.diffopts(ui, opts)
2712 m = scmutil.match(repo[node2], pats, opts)
2717 m = scmutil.match(repo[node2], pats, opts)
2713 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2718 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2714 listsubrepos=opts.get('subrepos'))
2719 listsubrepos=opts.get('subrepos'))
2715
2720
2716 @command('^export',
2721 @command('^export',
2717 [('o', 'output', '',
2722 [('o', 'output', '',
2718 _('print output to file with formatted name'), _('FORMAT')),
2723 _('print output to file with formatted name'), _('FORMAT')),
2719 ('', 'switch-parent', None, _('diff against the second parent')),
2724 ('', 'switch-parent', None, _('diff against the second parent')),
2720 ('r', 'rev', [], _('revisions to export'), _('REV')),
2725 ('r', 'rev', [], _('revisions to export'), _('REV')),
2721 ] + diffopts,
2726 ] + diffopts,
2722 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2727 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2723 def export(ui, repo, *changesets, **opts):
2728 def export(ui, repo, *changesets, **opts):
2724 """dump the header and diffs for one or more changesets
2729 """dump the header and diffs for one or more changesets
2725
2730
2726 Print the changeset header and diffs for one or more revisions.
2731 Print the changeset header and diffs for one or more revisions.
2727 If no revision is given, the parent of the working directory is used.
2732 If no revision is given, the parent of the working directory is used.
2728
2733
2729 The information shown in the changeset header is: author, date,
2734 The information shown in the changeset header is: author, date,
2730 branch name (if non-default), changeset hash, parent(s) and commit
2735 branch name (if non-default), changeset hash, parent(s) and commit
2731 comment.
2736 comment.
2732
2737
2733 .. note::
2738 .. note::
2734 export may generate unexpected diff output for merge
2739 export may generate unexpected diff output for merge
2735 changesets, as it will compare the merge changeset against its
2740 changesets, as it will compare the merge changeset against its
2736 first parent only.
2741 first parent only.
2737
2742
2738 Output may be to a file, in which case the name of the file is
2743 Output may be to a file, in which case the name of the file is
2739 given using a format string. The formatting rules are as follows:
2744 given using a format string. The formatting rules are as follows:
2740
2745
2741 :``%%``: literal "%" character
2746 :``%%``: literal "%" character
2742 :``%H``: changeset hash (40 hexadecimal digits)
2747 :``%H``: changeset hash (40 hexadecimal digits)
2743 :``%N``: number of patches being generated
2748 :``%N``: number of patches being generated
2744 :``%R``: changeset revision number
2749 :``%R``: changeset revision number
2745 :``%b``: basename of the exporting repository
2750 :``%b``: basename of the exporting repository
2746 :``%h``: short-form changeset hash (12 hexadecimal digits)
2751 :``%h``: short-form changeset hash (12 hexadecimal digits)
2747 :``%m``: first line of the commit message (only alphanumeric characters)
2752 :``%m``: first line of the commit message (only alphanumeric characters)
2748 :``%n``: zero-padded sequence number, starting at 1
2753 :``%n``: zero-padded sequence number, starting at 1
2749 :``%r``: zero-padded changeset revision number
2754 :``%r``: zero-padded changeset revision number
2750
2755
2751 Without the -a/--text option, export will avoid generating diffs
2756 Without the -a/--text option, export will avoid generating diffs
2752 of files it detects as binary. With -a, export will generate a
2757 of files it detects as binary. With -a, export will generate a
2753 diff anyway, probably with undesirable results.
2758 diff anyway, probably with undesirable results.
2754
2759
2755 Use the -g/--git option to generate diffs in the git extended diff
2760 Use the -g/--git option to generate diffs in the git extended diff
2756 format. See :hg:`help diffs` for more information.
2761 format. See :hg:`help diffs` for more information.
2757
2762
2758 With the --switch-parent option, the diff will be against the
2763 With the --switch-parent option, the diff will be against the
2759 second parent. It can be useful to review a merge.
2764 second parent. It can be useful to review a merge.
2760
2765
2761 .. container:: verbose
2766 .. container:: verbose
2762
2767
2763 Examples:
2768 Examples:
2764
2769
2765 - use export and import to transplant a bugfix to the current
2770 - use export and import to transplant a bugfix to the current
2766 branch::
2771 branch::
2767
2772
2768 hg export -r 9353 | hg import -
2773 hg export -r 9353 | hg import -
2769
2774
2770 - export all the changesets between two revisions to a file with
2775 - export all the changesets between two revisions to a file with
2771 rename information::
2776 rename information::
2772
2777
2773 hg export --git -r 123:150 > changes.txt
2778 hg export --git -r 123:150 > changes.txt
2774
2779
2775 - split outgoing changes into a series of patches with
2780 - split outgoing changes into a series of patches with
2776 descriptive names::
2781 descriptive names::
2777
2782
2778 hg export -r "outgoing()" -o "%n-%m.patch"
2783 hg export -r "outgoing()" -o "%n-%m.patch"
2779
2784
2780 Returns 0 on success.
2785 Returns 0 on success.
2781 """
2786 """
2782 changesets += tuple(opts.get('rev', []))
2787 changesets += tuple(opts.get('rev', []))
2783 if not changesets:
2788 if not changesets:
2784 changesets = ['.']
2789 changesets = ['.']
2785 revs = scmutil.revrange(repo, changesets)
2790 revs = scmutil.revrange(repo, changesets)
2786 if not revs:
2791 if not revs:
2787 raise util.Abort(_("export requires at least one changeset"))
2792 raise util.Abort(_("export requires at least one changeset"))
2788 if len(revs) > 1:
2793 if len(revs) > 1:
2789 ui.note(_('exporting patches:\n'))
2794 ui.note(_('exporting patches:\n'))
2790 else:
2795 else:
2791 ui.note(_('exporting patch:\n'))
2796 ui.note(_('exporting patch:\n'))
2792 cmdutil.export(repo, revs, template=opts.get('output'),
2797 cmdutil.export(repo, revs, template=opts.get('output'),
2793 switch_parent=opts.get('switch_parent'),
2798 switch_parent=opts.get('switch_parent'),
2794 opts=patch.diffopts(ui, opts))
2799 opts=patch.diffopts(ui, opts))
2795
2800
2796 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2801 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2797 def forget(ui, repo, *pats, **opts):
2802 def forget(ui, repo, *pats, **opts):
2798 """forget the specified files on the next commit
2803 """forget the specified files on the next commit
2799
2804
2800 Mark the specified files so they will no longer be tracked
2805 Mark the specified files so they will no longer be tracked
2801 after the next commit.
2806 after the next commit.
2802
2807
2803 This only removes files from the current branch, not from the
2808 This only removes files from the current branch, not from the
2804 entire project history, and it does not delete them from the
2809 entire project history, and it does not delete them from the
2805 working directory.
2810 working directory.
2806
2811
2807 To undo a forget before the next commit, see :hg:`add`.
2812 To undo a forget before the next commit, see :hg:`add`.
2808
2813
2809 .. container:: verbose
2814 .. container:: verbose
2810
2815
2811 Examples:
2816 Examples:
2812
2817
2813 - forget newly-added binary files::
2818 - forget newly-added binary files::
2814
2819
2815 hg forget "set:added() and binary()"
2820 hg forget "set:added() and binary()"
2816
2821
2817 - forget files that would be excluded by .hgignore::
2822 - forget files that would be excluded by .hgignore::
2818
2823
2819 hg forget "set:hgignore()"
2824 hg forget "set:hgignore()"
2820
2825
2821 Returns 0 on success.
2826 Returns 0 on success.
2822 """
2827 """
2823
2828
2824 if not pats:
2829 if not pats:
2825 raise util.Abort(_('no files specified'))
2830 raise util.Abort(_('no files specified'))
2826
2831
2827 m = scmutil.match(repo[None], pats, opts)
2832 m = scmutil.match(repo[None], pats, opts)
2828 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2833 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2829 return rejected and 1 or 0
2834 return rejected and 1 or 0
2830
2835
2831 @command(
2836 @command(
2832 'graft',
2837 'graft',
2833 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2838 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2834 ('c', 'continue', False, _('resume interrupted graft')),
2839 ('c', 'continue', False, _('resume interrupted graft')),
2835 ('e', 'edit', False, _('invoke editor on commit messages')),
2840 ('e', 'edit', False, _('invoke editor on commit messages')),
2836 ('', 'log', None, _('append graft info to log message')),
2841 ('', 'log', None, _('append graft info to log message')),
2837 ('D', 'currentdate', False,
2842 ('D', 'currentdate', False,
2838 _('record the current date as commit date')),
2843 _('record the current date as commit date')),
2839 ('U', 'currentuser', False,
2844 ('U', 'currentuser', False,
2840 _('record the current user as committer'), _('DATE'))]
2845 _('record the current user as committer'), _('DATE'))]
2841 + commitopts2 + mergetoolopts + dryrunopts,
2846 + commitopts2 + mergetoolopts + dryrunopts,
2842 _('[OPTION]... [-r] REV...'))
2847 _('[OPTION]... [-r] REV...'))
2843 def graft(ui, repo, *revs, **opts):
2848 def graft(ui, repo, *revs, **opts):
2844 '''copy changes from other branches onto the current branch
2849 '''copy changes from other branches onto the current branch
2845
2850
2846 This command uses Mercurial's merge logic to copy individual
2851 This command uses Mercurial's merge logic to copy individual
2847 changes from other branches without merging branches in the
2852 changes from other branches without merging branches in the
2848 history graph. This is sometimes known as 'backporting' or
2853 history graph. This is sometimes known as 'backporting' or
2849 'cherry-picking'. By default, graft will copy user, date, and
2854 'cherry-picking'. By default, graft will copy user, date, and
2850 description from the source changesets.
2855 description from the source changesets.
2851
2856
2852 Changesets that are ancestors of the current revision, that have
2857 Changesets that are ancestors of the current revision, that have
2853 already been grafted, or that are merges will be skipped.
2858 already been grafted, or that are merges will be skipped.
2854
2859
2855 If --log is specified, log messages will have a comment appended
2860 If --log is specified, log messages will have a comment appended
2856 of the form::
2861 of the form::
2857
2862
2858 (grafted from CHANGESETHASH)
2863 (grafted from CHANGESETHASH)
2859
2864
2860 If a graft merge results in conflicts, the graft process is
2865 If a graft merge results in conflicts, the graft process is
2861 interrupted so that the current merge can be manually resolved.
2866 interrupted so that the current merge can be manually resolved.
2862 Once all conflicts are addressed, the graft process can be
2867 Once all conflicts are addressed, the graft process can be
2863 continued with the -c/--continue option.
2868 continued with the -c/--continue option.
2864
2869
2865 .. note::
2870 .. note::
2866 The -c/--continue option does not reapply earlier options.
2871 The -c/--continue option does not reapply earlier options.
2867
2872
2868 .. container:: verbose
2873 .. container:: verbose
2869
2874
2870 Examples:
2875 Examples:
2871
2876
2872 - copy a single change to the stable branch and edit its description::
2877 - copy a single change to the stable branch and edit its description::
2873
2878
2874 hg update stable
2879 hg update stable
2875 hg graft --edit 9393
2880 hg graft --edit 9393
2876
2881
2877 - graft a range of changesets with one exception, updating dates::
2882 - graft a range of changesets with one exception, updating dates::
2878
2883
2879 hg graft -D "2085::2093 and not 2091"
2884 hg graft -D "2085::2093 and not 2091"
2880
2885
2881 - continue a graft after resolving conflicts::
2886 - continue a graft after resolving conflicts::
2882
2887
2883 hg graft -c
2888 hg graft -c
2884
2889
2885 - show the source of a grafted changeset::
2890 - show the source of a grafted changeset::
2886
2891
2887 hg log --debug -r tip
2892 hg log --debug -r tip
2888
2893
2889 Returns 0 on successful completion.
2894 Returns 0 on successful completion.
2890 '''
2895 '''
2891
2896
2892 revs = list(revs)
2897 revs = list(revs)
2893 revs.extend(opts['rev'])
2898 revs.extend(opts['rev'])
2894
2899
2895 if not opts.get('user') and opts.get('currentuser'):
2900 if not opts.get('user') and opts.get('currentuser'):
2896 opts['user'] = ui.username()
2901 opts['user'] = ui.username()
2897 if not opts.get('date') and opts.get('currentdate'):
2902 if not opts.get('date') and opts.get('currentdate'):
2898 opts['date'] = "%d %d" % util.makedate()
2903 opts['date'] = "%d %d" % util.makedate()
2899
2904
2900 editor = None
2905 editor = None
2901 if opts.get('edit'):
2906 if opts.get('edit'):
2902 editor = cmdutil.commitforceeditor
2907 editor = cmdutil.commitforceeditor
2903
2908
2904 cont = False
2909 cont = False
2905 if opts['continue']:
2910 if opts['continue']:
2906 cont = True
2911 cont = True
2907 if revs:
2912 if revs:
2908 raise util.Abort(_("can't specify --continue and revisions"))
2913 raise util.Abort(_("can't specify --continue and revisions"))
2909 # read in unfinished revisions
2914 # read in unfinished revisions
2910 try:
2915 try:
2911 nodes = repo.opener.read('graftstate').splitlines()
2916 nodes = repo.opener.read('graftstate').splitlines()
2912 revs = [repo[node].rev() for node in nodes]
2917 revs = [repo[node].rev() for node in nodes]
2913 except IOError, inst:
2918 except IOError, inst:
2914 if inst.errno != errno.ENOENT:
2919 if inst.errno != errno.ENOENT:
2915 raise
2920 raise
2916 raise util.Abort(_("no graft state found, can't continue"))
2921 raise util.Abort(_("no graft state found, can't continue"))
2917 else:
2922 else:
2918 cmdutil.bailifchanged(repo)
2923 cmdutil.bailifchanged(repo)
2919 if not revs:
2924 if not revs:
2920 raise util.Abort(_('no revisions specified'))
2925 raise util.Abort(_('no revisions specified'))
2921 revs = scmutil.revrange(repo, revs)
2926 revs = scmutil.revrange(repo, revs)
2922
2927
2923 # check for merges
2928 # check for merges
2924 for rev in repo.revs('%ld and merge()', revs):
2929 for rev in repo.revs('%ld and merge()', revs):
2925 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2930 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2926 revs.remove(rev)
2931 revs.remove(rev)
2927 if not revs:
2932 if not revs:
2928 return -1
2933 return -1
2929
2934
2930 # check for ancestors of dest branch
2935 # check for ancestors of dest branch
2931 crev = repo['.'].rev()
2936 crev = repo['.'].rev()
2932 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2937 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2933 # don't mutate while iterating, create a copy
2938 # don't mutate while iterating, create a copy
2934 for rev in list(revs):
2939 for rev in list(revs):
2935 if rev in ancestors:
2940 if rev in ancestors:
2936 ui.warn(_('skipping ancestor revision %s\n') % rev)
2941 ui.warn(_('skipping ancestor revision %s\n') % rev)
2937 revs.remove(rev)
2942 revs.remove(rev)
2938 if not revs:
2943 if not revs:
2939 return -1
2944 return -1
2940
2945
2941 # analyze revs for earlier grafts
2946 # analyze revs for earlier grafts
2942 ids = {}
2947 ids = {}
2943 for ctx in repo.set("%ld", revs):
2948 for ctx in repo.set("%ld", revs):
2944 ids[ctx.hex()] = ctx.rev()
2949 ids[ctx.hex()] = ctx.rev()
2945 n = ctx.extra().get('source')
2950 n = ctx.extra().get('source')
2946 if n:
2951 if n:
2947 ids[n] = ctx.rev()
2952 ids[n] = ctx.rev()
2948
2953
2949 # check ancestors for earlier grafts
2954 # check ancestors for earlier grafts
2950 ui.debug('scanning for duplicate grafts\n')
2955 ui.debug('scanning for duplicate grafts\n')
2951
2956
2952 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2957 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2953 ctx = repo[rev]
2958 ctx = repo[rev]
2954 n = ctx.extra().get('source')
2959 n = ctx.extra().get('source')
2955 if n in ids:
2960 if n in ids:
2956 r = repo[n].rev()
2961 r = repo[n].rev()
2957 if r in revs:
2962 if r in revs:
2958 ui.warn(_('skipping already grafted revision %s\n') % r)
2963 ui.warn(_('skipping already grafted revision %s\n') % r)
2959 revs.remove(r)
2964 revs.remove(r)
2960 elif ids[n] in revs:
2965 elif ids[n] in revs:
2961 ui.warn(_('skipping already grafted revision %s '
2966 ui.warn(_('skipping already grafted revision %s '
2962 '(same origin %d)\n') % (ids[n], r))
2967 '(same origin %d)\n') % (ids[n], r))
2963 revs.remove(ids[n])
2968 revs.remove(ids[n])
2964 elif ctx.hex() in ids:
2969 elif ctx.hex() in ids:
2965 r = ids[ctx.hex()]
2970 r = ids[ctx.hex()]
2966 ui.warn(_('skipping already grafted revision %s '
2971 ui.warn(_('skipping already grafted revision %s '
2967 '(was grafted from %d)\n') % (r, rev))
2972 '(was grafted from %d)\n') % (r, rev))
2968 revs.remove(r)
2973 revs.remove(r)
2969 if not revs:
2974 if not revs:
2970 return -1
2975 return -1
2971
2976
2972 wlock = repo.wlock()
2977 wlock = repo.wlock()
2973 try:
2978 try:
2974 current = repo['.']
2979 current = repo['.']
2975 for pos, ctx in enumerate(repo.set("%ld", revs)):
2980 for pos, ctx in enumerate(repo.set("%ld", revs)):
2976
2981
2977 ui.status(_('grafting revision %s\n') % ctx.rev())
2982 ui.status(_('grafting revision %s\n') % ctx.rev())
2978 if opts.get('dry_run'):
2983 if opts.get('dry_run'):
2979 continue
2984 continue
2980
2985
2981 source = ctx.extra().get('source')
2986 source = ctx.extra().get('source')
2982 if not source:
2987 if not source:
2983 source = ctx.hex()
2988 source = ctx.hex()
2984 extra = {'source': source}
2989 extra = {'source': source}
2985 user = ctx.user()
2990 user = ctx.user()
2986 if opts.get('user'):
2991 if opts.get('user'):
2987 user = opts['user']
2992 user = opts['user']
2988 date = ctx.date()
2993 date = ctx.date()
2989 if opts.get('date'):
2994 if opts.get('date'):
2990 date = opts['date']
2995 date = opts['date']
2991 message = ctx.description()
2996 message = ctx.description()
2992 if opts.get('log'):
2997 if opts.get('log'):
2993 message += '\n(grafted from %s)' % ctx.hex()
2998 message += '\n(grafted from %s)' % ctx.hex()
2994
2999
2995 # we don't merge the first commit when continuing
3000 # we don't merge the first commit when continuing
2996 if not cont:
3001 if not cont:
2997 # perform the graft merge with p1(rev) as 'ancestor'
3002 # perform the graft merge with p1(rev) as 'ancestor'
2998 try:
3003 try:
2999 # ui.forcemerge is an internal variable, do not document
3004 # ui.forcemerge is an internal variable, do not document
3000 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3005 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3001 stats = mergemod.update(repo, ctx.node(), True, True, False,
3006 stats = mergemod.update(repo, ctx.node(), True, True, False,
3002 ctx.p1().node())
3007 ctx.p1().node())
3003 finally:
3008 finally:
3004 repo.ui.setconfig('ui', 'forcemerge', '')
3009 repo.ui.setconfig('ui', 'forcemerge', '')
3005 # report any conflicts
3010 # report any conflicts
3006 if stats and stats[3] > 0:
3011 if stats and stats[3] > 0:
3007 # write out state for --continue
3012 # write out state for --continue
3008 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3013 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3009 repo.opener.write('graftstate', ''.join(nodelines))
3014 repo.opener.write('graftstate', ''.join(nodelines))
3010 raise util.Abort(
3015 raise util.Abort(
3011 _("unresolved conflicts, can't continue"),
3016 _("unresolved conflicts, can't continue"),
3012 hint=_('use hg resolve and hg graft --continue'))
3017 hint=_('use hg resolve and hg graft --continue'))
3013 else:
3018 else:
3014 cont = False
3019 cont = False
3015
3020
3016 # drop the second merge parent
3021 # drop the second merge parent
3017 repo.setparents(current.node(), nullid)
3022 repo.setparents(current.node(), nullid)
3018 repo.dirstate.write()
3023 repo.dirstate.write()
3019 # fix up dirstate for copies and renames
3024 # fix up dirstate for copies and renames
3020 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3025 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3021
3026
3022 # commit
3027 # commit
3023 node = repo.commit(text=message, user=user,
3028 node = repo.commit(text=message, user=user,
3024 date=date, extra=extra, editor=editor)
3029 date=date, extra=extra, editor=editor)
3025 if node is None:
3030 if node is None:
3026 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3031 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3027 else:
3032 else:
3028 current = repo[node]
3033 current = repo[node]
3029 finally:
3034 finally:
3030 wlock.release()
3035 wlock.release()
3031
3036
3032 # remove state when we complete successfully
3037 # remove state when we complete successfully
3033 if not opts.get('dry_run'):
3038 if not opts.get('dry_run'):
3034 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3039 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3035
3040
3036 return 0
3041 return 0
3037
3042
3038 @command('grep',
3043 @command('grep',
3039 [('0', 'print0', None, _('end fields with NUL')),
3044 [('0', 'print0', None, _('end fields with NUL')),
3040 ('', 'all', None, _('print all revisions that match')),
3045 ('', 'all', None, _('print all revisions that match')),
3041 ('a', 'text', None, _('treat all files as text')),
3046 ('a', 'text', None, _('treat all files as text')),
3042 ('f', 'follow', None,
3047 ('f', 'follow', None,
3043 _('follow changeset history,'
3048 _('follow changeset history,'
3044 ' or file history across copies and renames')),
3049 ' or file history across copies and renames')),
3045 ('i', 'ignore-case', None, _('ignore case when matching')),
3050 ('i', 'ignore-case', None, _('ignore case when matching')),
3046 ('l', 'files-with-matches', None,
3051 ('l', 'files-with-matches', None,
3047 _('print only filenames and revisions that match')),
3052 _('print only filenames and revisions that match')),
3048 ('n', 'line-number', None, _('print matching line numbers')),
3053 ('n', 'line-number', None, _('print matching line numbers')),
3049 ('r', 'rev', [],
3054 ('r', 'rev', [],
3050 _('only search files changed within revision range'), _('REV')),
3055 _('only search files changed within revision range'), _('REV')),
3051 ('u', 'user', None, _('list the author (long with -v)')),
3056 ('u', 'user', None, _('list the author (long with -v)')),
3052 ('d', 'date', None, _('list the date (short with -q)')),
3057 ('d', 'date', None, _('list the date (short with -q)')),
3053 ] + walkopts,
3058 ] + walkopts,
3054 _('[OPTION]... PATTERN [FILE]...'))
3059 _('[OPTION]... PATTERN [FILE]...'))
3055 def grep(ui, repo, pattern, *pats, **opts):
3060 def grep(ui, repo, pattern, *pats, **opts):
3056 """search for a pattern in specified files and revisions
3061 """search for a pattern in specified files and revisions
3057
3062
3058 Search revisions of files for a regular expression.
3063 Search revisions of files for a regular expression.
3059
3064
3060 This command behaves differently than Unix grep. It only accepts
3065 This command behaves differently than Unix grep. It only accepts
3061 Python/Perl regexps. It searches repository history, not the
3066 Python/Perl regexps. It searches repository history, not the
3062 working directory. It always prints the revision number in which a
3067 working directory. It always prints the revision number in which a
3063 match appears.
3068 match appears.
3064
3069
3065 By default, grep only prints output for the first revision of a
3070 By default, grep only prints output for the first revision of a
3066 file in which it finds a match. To get it to print every revision
3071 file in which it finds a match. To get it to print every revision
3067 that contains a change in match status ("-" for a match that
3072 that contains a change in match status ("-" for a match that
3068 becomes a non-match, or "+" for a non-match that becomes a match),
3073 becomes a non-match, or "+" for a non-match that becomes a match),
3069 use the --all flag.
3074 use the --all flag.
3070
3075
3071 Returns 0 if a match is found, 1 otherwise.
3076 Returns 0 if a match is found, 1 otherwise.
3072 """
3077 """
3073 reflags = re.M
3078 reflags = re.M
3074 if opts.get('ignore_case'):
3079 if opts.get('ignore_case'):
3075 reflags |= re.I
3080 reflags |= re.I
3076 try:
3081 try:
3077 regexp = util.compilere(pattern, reflags)
3082 regexp = util.compilere(pattern, reflags)
3078 except re.error, inst:
3083 except re.error, inst:
3079 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3084 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3080 return 1
3085 return 1
3081 sep, eol = ':', '\n'
3086 sep, eol = ':', '\n'
3082 if opts.get('print0'):
3087 if opts.get('print0'):
3083 sep = eol = '\0'
3088 sep = eol = '\0'
3084
3089
3085 getfile = util.lrucachefunc(repo.file)
3090 getfile = util.lrucachefunc(repo.file)
3086
3091
3087 def matchlines(body):
3092 def matchlines(body):
3088 begin = 0
3093 begin = 0
3089 linenum = 0
3094 linenum = 0
3090 while begin < len(body):
3095 while begin < len(body):
3091 match = regexp.search(body, begin)
3096 match = regexp.search(body, begin)
3092 if not match:
3097 if not match:
3093 break
3098 break
3094 mstart, mend = match.span()
3099 mstart, mend = match.span()
3095 linenum += body.count('\n', begin, mstart) + 1
3100 linenum += body.count('\n', begin, mstart) + 1
3096 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3101 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3097 begin = body.find('\n', mend) + 1 or len(body) + 1
3102 begin = body.find('\n', mend) + 1 or len(body) + 1
3098 lend = begin - 1
3103 lend = begin - 1
3099 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3104 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3100
3105
3101 class linestate(object):
3106 class linestate(object):
3102 def __init__(self, line, linenum, colstart, colend):
3107 def __init__(self, line, linenum, colstart, colend):
3103 self.line = line
3108 self.line = line
3104 self.linenum = linenum
3109 self.linenum = linenum
3105 self.colstart = colstart
3110 self.colstart = colstart
3106 self.colend = colend
3111 self.colend = colend
3107
3112
3108 def __hash__(self):
3113 def __hash__(self):
3109 return hash((self.linenum, self.line))
3114 return hash((self.linenum, self.line))
3110
3115
3111 def __eq__(self, other):
3116 def __eq__(self, other):
3112 return self.line == other.line
3117 return self.line == other.line
3113
3118
3114 matches = {}
3119 matches = {}
3115 copies = {}
3120 copies = {}
3116 def grepbody(fn, rev, body):
3121 def grepbody(fn, rev, body):
3117 matches[rev].setdefault(fn, [])
3122 matches[rev].setdefault(fn, [])
3118 m = matches[rev][fn]
3123 m = matches[rev][fn]
3119 for lnum, cstart, cend, line in matchlines(body):
3124 for lnum, cstart, cend, line in matchlines(body):
3120 s = linestate(line, lnum, cstart, cend)
3125 s = linestate(line, lnum, cstart, cend)
3121 m.append(s)
3126 m.append(s)
3122
3127
3123 def difflinestates(a, b):
3128 def difflinestates(a, b):
3124 sm = difflib.SequenceMatcher(None, a, b)
3129 sm = difflib.SequenceMatcher(None, a, b)
3125 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3130 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3126 if tag == 'insert':
3131 if tag == 'insert':
3127 for i in xrange(blo, bhi):
3132 for i in xrange(blo, bhi):
3128 yield ('+', b[i])
3133 yield ('+', b[i])
3129 elif tag == 'delete':
3134 elif tag == 'delete':
3130 for i in xrange(alo, ahi):
3135 for i in xrange(alo, ahi):
3131 yield ('-', a[i])
3136 yield ('-', a[i])
3132 elif tag == 'replace':
3137 elif tag == 'replace':
3133 for i in xrange(alo, ahi):
3138 for i in xrange(alo, ahi):
3134 yield ('-', a[i])
3139 yield ('-', a[i])
3135 for i in xrange(blo, bhi):
3140 for i in xrange(blo, bhi):
3136 yield ('+', b[i])
3141 yield ('+', b[i])
3137
3142
3138 def display(fn, ctx, pstates, states):
3143 def display(fn, ctx, pstates, states):
3139 rev = ctx.rev()
3144 rev = ctx.rev()
3140 datefunc = ui.quiet and util.shortdate or util.datestr
3145 datefunc = ui.quiet and util.shortdate or util.datestr
3141 found = False
3146 found = False
3142 filerevmatches = {}
3147 filerevmatches = {}
3143 def binary():
3148 def binary():
3144 flog = getfile(fn)
3149 flog = getfile(fn)
3145 return util.binary(flog.read(ctx.filenode(fn)))
3150 return util.binary(flog.read(ctx.filenode(fn)))
3146
3151
3147 if opts.get('all'):
3152 if opts.get('all'):
3148 iter = difflinestates(pstates, states)
3153 iter = difflinestates(pstates, states)
3149 else:
3154 else:
3150 iter = [('', l) for l in states]
3155 iter = [('', l) for l in states]
3151 for change, l in iter:
3156 for change, l in iter:
3152 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3157 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3153 before, match, after = None, None, None
3158 before, match, after = None, None, None
3154
3159
3155 if opts.get('line_number'):
3160 if opts.get('line_number'):
3156 cols.append((str(l.linenum), 'grep.linenumber'))
3161 cols.append((str(l.linenum), 'grep.linenumber'))
3157 if opts.get('all'):
3162 if opts.get('all'):
3158 cols.append((change, 'grep.change'))
3163 cols.append((change, 'grep.change'))
3159 if opts.get('user'):
3164 if opts.get('user'):
3160 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3165 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3161 if opts.get('date'):
3166 if opts.get('date'):
3162 cols.append((datefunc(ctx.date()), 'grep.date'))
3167 cols.append((datefunc(ctx.date()), 'grep.date'))
3163 if opts.get('files_with_matches'):
3168 if opts.get('files_with_matches'):
3164 c = (fn, rev)
3169 c = (fn, rev)
3165 if c in filerevmatches:
3170 if c in filerevmatches:
3166 continue
3171 continue
3167 filerevmatches[c] = 1
3172 filerevmatches[c] = 1
3168 else:
3173 else:
3169 before = l.line[:l.colstart]
3174 before = l.line[:l.colstart]
3170 match = l.line[l.colstart:l.colend]
3175 match = l.line[l.colstart:l.colend]
3171 after = l.line[l.colend:]
3176 after = l.line[l.colend:]
3172 for col, label in cols[:-1]:
3177 for col, label in cols[:-1]:
3173 ui.write(col, label=label)
3178 ui.write(col, label=label)
3174 ui.write(sep, label='grep.sep')
3179 ui.write(sep, label='grep.sep')
3175 ui.write(cols[-1][0], label=cols[-1][1])
3180 ui.write(cols[-1][0], label=cols[-1][1])
3176 if before is not None:
3181 if before is not None:
3177 ui.write(sep, label='grep.sep')
3182 ui.write(sep, label='grep.sep')
3178 if not opts.get('text') and binary():
3183 if not opts.get('text') and binary():
3179 ui.write(" Binary file matches")
3184 ui.write(" Binary file matches")
3180 else:
3185 else:
3181 ui.write(before)
3186 ui.write(before)
3182 ui.write(match, label='grep.match')
3187 ui.write(match, label='grep.match')
3183 ui.write(after)
3188 ui.write(after)
3184 ui.write(eol)
3189 ui.write(eol)
3185 found = True
3190 found = True
3186 return found
3191 return found
3187
3192
3188 skip = {}
3193 skip = {}
3189 revfiles = {}
3194 revfiles = {}
3190 matchfn = scmutil.match(repo[None], pats, opts)
3195 matchfn = scmutil.match(repo[None], pats, opts)
3191 found = False
3196 found = False
3192 follow = opts.get('follow')
3197 follow = opts.get('follow')
3193
3198
3194 def prep(ctx, fns):
3199 def prep(ctx, fns):
3195 rev = ctx.rev()
3200 rev = ctx.rev()
3196 pctx = ctx.p1()
3201 pctx = ctx.p1()
3197 parent = pctx.rev()
3202 parent = pctx.rev()
3198 matches.setdefault(rev, {})
3203 matches.setdefault(rev, {})
3199 matches.setdefault(parent, {})
3204 matches.setdefault(parent, {})
3200 files = revfiles.setdefault(rev, [])
3205 files = revfiles.setdefault(rev, [])
3201 for fn in fns:
3206 for fn in fns:
3202 flog = getfile(fn)
3207 flog = getfile(fn)
3203 try:
3208 try:
3204 fnode = ctx.filenode(fn)
3209 fnode = ctx.filenode(fn)
3205 except error.LookupError:
3210 except error.LookupError:
3206 continue
3211 continue
3207
3212
3208 copied = flog.renamed(fnode)
3213 copied = flog.renamed(fnode)
3209 copy = follow and copied and copied[0]
3214 copy = follow and copied and copied[0]
3210 if copy:
3215 if copy:
3211 copies.setdefault(rev, {})[fn] = copy
3216 copies.setdefault(rev, {})[fn] = copy
3212 if fn in skip:
3217 if fn in skip:
3213 if copy:
3218 if copy:
3214 skip[copy] = True
3219 skip[copy] = True
3215 continue
3220 continue
3216 files.append(fn)
3221 files.append(fn)
3217
3222
3218 if fn not in matches[rev]:
3223 if fn not in matches[rev]:
3219 grepbody(fn, rev, flog.read(fnode))
3224 grepbody(fn, rev, flog.read(fnode))
3220
3225
3221 pfn = copy or fn
3226 pfn = copy or fn
3222 if pfn not in matches[parent]:
3227 if pfn not in matches[parent]:
3223 try:
3228 try:
3224 fnode = pctx.filenode(pfn)
3229 fnode = pctx.filenode(pfn)
3225 grepbody(pfn, parent, flog.read(fnode))
3230 grepbody(pfn, parent, flog.read(fnode))
3226 except error.LookupError:
3231 except error.LookupError:
3227 pass
3232 pass
3228
3233
3229 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3234 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3230 rev = ctx.rev()
3235 rev = ctx.rev()
3231 parent = ctx.p1().rev()
3236 parent = ctx.p1().rev()
3232 for fn in sorted(revfiles.get(rev, [])):
3237 for fn in sorted(revfiles.get(rev, [])):
3233 states = matches[rev][fn]
3238 states = matches[rev][fn]
3234 copy = copies.get(rev, {}).get(fn)
3239 copy = copies.get(rev, {}).get(fn)
3235 if fn in skip:
3240 if fn in skip:
3236 if copy:
3241 if copy:
3237 skip[copy] = True
3242 skip[copy] = True
3238 continue
3243 continue
3239 pstates = matches.get(parent, {}).get(copy or fn, [])
3244 pstates = matches.get(parent, {}).get(copy or fn, [])
3240 if pstates or states:
3245 if pstates or states:
3241 r = display(fn, ctx, pstates, states)
3246 r = display(fn, ctx, pstates, states)
3242 found = found or r
3247 found = found or r
3243 if r and not opts.get('all'):
3248 if r and not opts.get('all'):
3244 skip[fn] = True
3249 skip[fn] = True
3245 if copy:
3250 if copy:
3246 skip[copy] = True
3251 skip[copy] = True
3247 del matches[rev]
3252 del matches[rev]
3248 del revfiles[rev]
3253 del revfiles[rev]
3249
3254
3250 return not found
3255 return not found
3251
3256
3252 @command('heads',
3257 @command('heads',
3253 [('r', 'rev', '',
3258 [('r', 'rev', '',
3254 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3259 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3255 ('t', 'topo', False, _('show topological heads only')),
3260 ('t', 'topo', False, _('show topological heads only')),
3256 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3261 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3257 ('c', 'closed', False, _('show normal and closed branch heads')),
3262 ('c', 'closed', False, _('show normal and closed branch heads')),
3258 ] + templateopts,
3263 ] + templateopts,
3259 _('[-ct] [-r STARTREV] [REV]...'))
3264 _('[-ct] [-r STARTREV] [REV]...'))
3260 def heads(ui, repo, *branchrevs, **opts):
3265 def heads(ui, repo, *branchrevs, **opts):
3261 """show current repository heads or show branch heads
3266 """show current repository heads or show branch heads
3262
3267
3263 With no arguments, show all repository branch heads.
3268 With no arguments, show all repository branch heads.
3264
3269
3265 Repository "heads" are changesets with no child changesets. They are
3270 Repository "heads" are changesets with no child changesets. They are
3266 where development generally takes place and are the usual targets
3271 where development generally takes place and are the usual targets
3267 for update and merge operations. Branch heads are changesets that have
3272 for update and merge operations. Branch heads are changesets that have
3268 no child changeset on the same branch.
3273 no child changeset on the same branch.
3269
3274
3270 If one or more REVs are given, only branch heads on the branches
3275 If one or more REVs are given, only branch heads on the branches
3271 associated with the specified changesets are shown. This means
3276 associated with the specified changesets are shown. This means
3272 that you can use :hg:`heads foo` to see the heads on a branch
3277 that you can use :hg:`heads foo` to see the heads on a branch
3273 named ``foo``.
3278 named ``foo``.
3274
3279
3275 If -c/--closed is specified, also show branch heads marked closed
3280 If -c/--closed is specified, also show branch heads marked closed
3276 (see :hg:`commit --close-branch`).
3281 (see :hg:`commit --close-branch`).
3277
3282
3278 If STARTREV is specified, only those heads that are descendants of
3283 If STARTREV is specified, only those heads that are descendants of
3279 STARTREV will be displayed.
3284 STARTREV will be displayed.
3280
3285
3281 If -t/--topo is specified, named branch mechanics will be ignored and only
3286 If -t/--topo is specified, named branch mechanics will be ignored and only
3282 changesets without children will be shown.
3287 changesets without children will be shown.
3283
3288
3284 Returns 0 if matching heads are found, 1 if not.
3289 Returns 0 if matching heads are found, 1 if not.
3285 """
3290 """
3286
3291
3287 start = None
3292 start = None
3288 if 'rev' in opts:
3293 if 'rev' in opts:
3289 start = scmutil.revsingle(repo, opts['rev'], None).node()
3294 start = scmutil.revsingle(repo, opts['rev'], None).node()
3290
3295
3291 if opts.get('topo'):
3296 if opts.get('topo'):
3292 heads = [repo[h] for h in repo.heads(start)]
3297 heads = [repo[h] for h in repo.heads(start)]
3293 else:
3298 else:
3294 heads = []
3299 heads = []
3295 for branch in repo.branchmap():
3300 for branch in repo.branchmap():
3296 heads += repo.branchheads(branch, start, opts.get('closed'))
3301 heads += repo.branchheads(branch, start, opts.get('closed'))
3297 heads = [repo[h] for h in heads]
3302 heads = [repo[h] for h in heads]
3298
3303
3299 if branchrevs:
3304 if branchrevs:
3300 branches = set(repo[br].branch() for br in branchrevs)
3305 branches = set(repo[br].branch() for br in branchrevs)
3301 heads = [h for h in heads if h.branch() in branches]
3306 heads = [h for h in heads if h.branch() in branches]
3302
3307
3303 if opts.get('active') and branchrevs:
3308 if opts.get('active') and branchrevs:
3304 dagheads = repo.heads(start)
3309 dagheads = repo.heads(start)
3305 heads = [h for h in heads if h.node() in dagheads]
3310 heads = [h for h in heads if h.node() in dagheads]
3306
3311
3307 if branchrevs:
3312 if branchrevs:
3308 haveheads = set(h.branch() for h in heads)
3313 haveheads = set(h.branch() for h in heads)
3309 if branches - haveheads:
3314 if branches - haveheads:
3310 headless = ', '.join(b for b in branches - haveheads)
3315 headless = ', '.join(b for b in branches - haveheads)
3311 msg = _('no open branch heads found on branches %s')
3316 msg = _('no open branch heads found on branches %s')
3312 if opts.get('rev'):
3317 if opts.get('rev'):
3313 msg += _(' (started at %s)') % opts['rev']
3318 msg += _(' (started at %s)') % opts['rev']
3314 ui.warn((msg + '\n') % headless)
3319 ui.warn((msg + '\n') % headless)
3315
3320
3316 if not heads:
3321 if not heads:
3317 return 1
3322 return 1
3318
3323
3319 heads = sorted(heads, key=lambda x: -x.rev())
3324 heads = sorted(heads, key=lambda x: -x.rev())
3320 displayer = cmdutil.show_changeset(ui, repo, opts)
3325 displayer = cmdutil.show_changeset(ui, repo, opts)
3321 for ctx in heads:
3326 for ctx in heads:
3322 displayer.show(ctx)
3327 displayer.show(ctx)
3323 displayer.close()
3328 displayer.close()
3324
3329
3325 @command('help',
3330 @command('help',
3326 [('e', 'extension', None, _('show only help for extensions')),
3331 [('e', 'extension', None, _('show only help for extensions')),
3327 ('c', 'command', None, _('show only help for commands')),
3332 ('c', 'command', None, _('show only help for commands')),
3328 ('k', 'keyword', '', _('show topics matching keyword')),
3333 ('k', 'keyword', '', _('show topics matching keyword')),
3329 ],
3334 ],
3330 _('[-ec] [TOPIC]'))
3335 _('[-ec] [TOPIC]'))
3331 def help_(ui, name=None, **opts):
3336 def help_(ui, name=None, **opts):
3332 """show help for a given topic or a help overview
3337 """show help for a given topic or a help overview
3333
3338
3334 With no arguments, print a list of commands with short help messages.
3339 With no arguments, print a list of commands with short help messages.
3335
3340
3336 Given a topic, extension, or command name, print help for that
3341 Given a topic, extension, or command name, print help for that
3337 topic.
3342 topic.
3338
3343
3339 Returns 0 if successful.
3344 Returns 0 if successful.
3340 """
3345 """
3341
3346
3342 textwidth = min(ui.termwidth(), 80) - 2
3347 textwidth = min(ui.termwidth(), 80) - 2
3343
3348
3344 keep = ui.verbose and ['verbose'] or []
3349 keep = ui.verbose and ['verbose'] or []
3345 text = help.help_(ui, name, **opts)
3350 text = help.help_(ui, name, **opts)
3346
3351
3347 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3352 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3348 if 'verbose' in pruned:
3353 if 'verbose' in pruned:
3349 keep.append('omitted')
3354 keep.append('omitted')
3350 else:
3355 else:
3351 keep.append('notomitted')
3356 keep.append('notomitted')
3352 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3357 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3353 ui.write(formatted)
3358 ui.write(formatted)
3354
3359
3355
3360
3356 @command('identify|id',
3361 @command('identify|id',
3357 [('r', 'rev', '',
3362 [('r', 'rev', '',
3358 _('identify the specified revision'), _('REV')),
3363 _('identify the specified revision'), _('REV')),
3359 ('n', 'num', None, _('show local revision number')),
3364 ('n', 'num', None, _('show local revision number')),
3360 ('i', 'id', None, _('show global revision id')),
3365 ('i', 'id', None, _('show global revision id')),
3361 ('b', 'branch', None, _('show branch')),
3366 ('b', 'branch', None, _('show branch')),
3362 ('t', 'tags', None, _('show tags')),
3367 ('t', 'tags', None, _('show tags')),
3363 ('B', 'bookmarks', None, _('show bookmarks')),
3368 ('B', 'bookmarks', None, _('show bookmarks')),
3364 ] + remoteopts,
3369 ] + remoteopts,
3365 _('[-nibtB] [-r REV] [SOURCE]'))
3370 _('[-nibtB] [-r REV] [SOURCE]'))
3366 def identify(ui, repo, source=None, rev=None,
3371 def identify(ui, repo, source=None, rev=None,
3367 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3372 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3368 """identify the working copy or specified revision
3373 """identify the working copy or specified revision
3369
3374
3370 Print a summary identifying the repository state at REV using one or
3375 Print a summary identifying the repository state at REV using one or
3371 two parent hash identifiers, followed by a "+" if the working
3376 two parent hash identifiers, followed by a "+" if the working
3372 directory has uncommitted changes, the branch name (if not default),
3377 directory has uncommitted changes, the branch name (if not default),
3373 a list of tags, and a list of bookmarks.
3378 a list of tags, and a list of bookmarks.
3374
3379
3375 When REV is not given, print a summary of the current state of the
3380 When REV is not given, print a summary of the current state of the
3376 repository.
3381 repository.
3377
3382
3378 Specifying a path to a repository root or Mercurial bundle will
3383 Specifying a path to a repository root or Mercurial bundle will
3379 cause lookup to operate on that repository/bundle.
3384 cause lookup to operate on that repository/bundle.
3380
3385
3381 .. container:: verbose
3386 .. container:: verbose
3382
3387
3383 Examples:
3388 Examples:
3384
3389
3385 - generate a build identifier for the working directory::
3390 - generate a build identifier for the working directory::
3386
3391
3387 hg id --id > build-id.dat
3392 hg id --id > build-id.dat
3388
3393
3389 - find the revision corresponding to a tag::
3394 - find the revision corresponding to a tag::
3390
3395
3391 hg id -n -r 1.3
3396 hg id -n -r 1.3
3392
3397
3393 - check the most recent revision of a remote repository::
3398 - check the most recent revision of a remote repository::
3394
3399
3395 hg id -r tip http://selenic.com/hg/
3400 hg id -r tip http://selenic.com/hg/
3396
3401
3397 Returns 0 if successful.
3402 Returns 0 if successful.
3398 """
3403 """
3399
3404
3400 if not repo and not source:
3405 if not repo and not source:
3401 raise util.Abort(_("there is no Mercurial repository here "
3406 raise util.Abort(_("there is no Mercurial repository here "
3402 "(.hg not found)"))
3407 "(.hg not found)"))
3403
3408
3404 hexfunc = ui.debugflag and hex or short
3409 hexfunc = ui.debugflag and hex or short
3405 default = not (num or id or branch or tags or bookmarks)
3410 default = not (num or id or branch or tags or bookmarks)
3406 output = []
3411 output = []
3407 revs = []
3412 revs = []
3408
3413
3409 if source:
3414 if source:
3410 source, branches = hg.parseurl(ui.expandpath(source))
3415 source, branches = hg.parseurl(ui.expandpath(source))
3411 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3416 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3412 repo = peer.local()
3417 repo = peer.local()
3413 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3418 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3414
3419
3415 if not repo:
3420 if not repo:
3416 if num or branch or tags:
3421 if num or branch or tags:
3417 raise util.Abort(
3422 raise util.Abort(
3418 _("can't query remote revision number, branch, or tags"))
3423 _("can't query remote revision number, branch, or tags"))
3419 if not rev and revs:
3424 if not rev and revs:
3420 rev = revs[0]
3425 rev = revs[0]
3421 if not rev:
3426 if not rev:
3422 rev = "tip"
3427 rev = "tip"
3423
3428
3424 remoterev = peer.lookup(rev)
3429 remoterev = peer.lookup(rev)
3425 if default or id:
3430 if default or id:
3426 output = [hexfunc(remoterev)]
3431 output = [hexfunc(remoterev)]
3427
3432
3428 def getbms():
3433 def getbms():
3429 bms = []
3434 bms = []
3430
3435
3431 if 'bookmarks' in peer.listkeys('namespaces'):
3436 if 'bookmarks' in peer.listkeys('namespaces'):
3432 hexremoterev = hex(remoterev)
3437 hexremoterev = hex(remoterev)
3433 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3438 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3434 if bmr == hexremoterev]
3439 if bmr == hexremoterev]
3435
3440
3436 return sorted(bms)
3441 return sorted(bms)
3437
3442
3438 if bookmarks:
3443 if bookmarks:
3439 output.extend(getbms())
3444 output.extend(getbms())
3440 elif default and not ui.quiet:
3445 elif default and not ui.quiet:
3441 # multiple bookmarks for a single parent separated by '/'
3446 # multiple bookmarks for a single parent separated by '/'
3442 bm = '/'.join(getbms())
3447 bm = '/'.join(getbms())
3443 if bm:
3448 if bm:
3444 output.append(bm)
3449 output.append(bm)
3445 else:
3450 else:
3446 if not rev:
3451 if not rev:
3447 ctx = repo[None]
3452 ctx = repo[None]
3448 parents = ctx.parents()
3453 parents = ctx.parents()
3449 changed = ""
3454 changed = ""
3450 if default or id or num:
3455 if default or id or num:
3451 if (util.any(repo.status())
3456 if (util.any(repo.status())
3452 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3457 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3453 changed = '+'
3458 changed = '+'
3454 if default or id:
3459 if default or id:
3455 output = ["%s%s" %
3460 output = ["%s%s" %
3456 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3461 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3457 if num:
3462 if num:
3458 output.append("%s%s" %
3463 output.append("%s%s" %
3459 ('+'.join([str(p.rev()) for p in parents]), changed))
3464 ('+'.join([str(p.rev()) for p in parents]), changed))
3460 else:
3465 else:
3461 ctx = scmutil.revsingle(repo, rev)
3466 ctx = scmutil.revsingle(repo, rev)
3462 if default or id:
3467 if default or id:
3463 output = [hexfunc(ctx.node())]
3468 output = [hexfunc(ctx.node())]
3464 if num:
3469 if num:
3465 output.append(str(ctx.rev()))
3470 output.append(str(ctx.rev()))
3466
3471
3467 if default and not ui.quiet:
3472 if default and not ui.quiet:
3468 b = ctx.branch()
3473 b = ctx.branch()
3469 if b != 'default':
3474 if b != 'default':
3470 output.append("(%s)" % b)
3475 output.append("(%s)" % b)
3471
3476
3472 # multiple tags for a single parent separated by '/'
3477 # multiple tags for a single parent separated by '/'
3473 t = '/'.join(ctx.tags())
3478 t = '/'.join(ctx.tags())
3474 if t:
3479 if t:
3475 output.append(t)
3480 output.append(t)
3476
3481
3477 # multiple bookmarks for a single parent separated by '/'
3482 # multiple bookmarks for a single parent separated by '/'
3478 bm = '/'.join(ctx.bookmarks())
3483 bm = '/'.join(ctx.bookmarks())
3479 if bm:
3484 if bm:
3480 output.append(bm)
3485 output.append(bm)
3481 else:
3486 else:
3482 if branch:
3487 if branch:
3483 output.append(ctx.branch())
3488 output.append(ctx.branch())
3484
3489
3485 if tags:
3490 if tags:
3486 output.extend(ctx.tags())
3491 output.extend(ctx.tags())
3487
3492
3488 if bookmarks:
3493 if bookmarks:
3489 output.extend(ctx.bookmarks())
3494 output.extend(ctx.bookmarks())
3490
3495
3491 ui.write("%s\n" % ' '.join(output))
3496 ui.write("%s\n" % ' '.join(output))
3492
3497
3493 @command('import|patch',
3498 @command('import|patch',
3494 [('p', 'strip', 1,
3499 [('p', 'strip', 1,
3495 _('directory strip option for patch. This has the same '
3500 _('directory strip option for patch. This has the same '
3496 'meaning as the corresponding patch option'), _('NUM')),
3501 'meaning as the corresponding patch option'), _('NUM')),
3497 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3502 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3498 ('e', 'edit', False, _('invoke editor on commit messages')),
3503 ('e', 'edit', False, _('invoke editor on commit messages')),
3499 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3504 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3500 ('', 'no-commit', None,
3505 ('', 'no-commit', None,
3501 _("don't commit, just update the working directory")),
3506 _("don't commit, just update the working directory")),
3502 ('', 'bypass', None,
3507 ('', 'bypass', None,
3503 _("apply patch without touching the working directory")),
3508 _("apply patch without touching the working directory")),
3504 ('', 'exact', None,
3509 ('', 'exact', None,
3505 _('apply patch to the nodes from which it was generated')),
3510 _('apply patch to the nodes from which it was generated')),
3506 ('', 'import-branch', None,
3511 ('', 'import-branch', None,
3507 _('use any branch information in patch (implied by --exact)'))] +
3512 _('use any branch information in patch (implied by --exact)'))] +
3508 commitopts + commitopts2 + similarityopts,
3513 commitopts + commitopts2 + similarityopts,
3509 _('[OPTION]... PATCH...'))
3514 _('[OPTION]... PATCH...'))
3510 def import_(ui, repo, patch1=None, *patches, **opts):
3515 def import_(ui, repo, patch1=None, *patches, **opts):
3511 """import an ordered set of patches
3516 """import an ordered set of patches
3512
3517
3513 Import a list of patches and commit them individually (unless
3518 Import a list of patches and commit them individually (unless
3514 --no-commit is specified).
3519 --no-commit is specified).
3515
3520
3516 If there are outstanding changes in the working directory, import
3521 If there are outstanding changes in the working directory, import
3517 will abort unless given the -f/--force flag.
3522 will abort unless given the -f/--force flag.
3518
3523
3519 You can import a patch straight from a mail message. Even patches
3524 You can import a patch straight from a mail message. Even patches
3520 as attachments work (to use the body part, it must have type
3525 as attachments work (to use the body part, it must have type
3521 text/plain or text/x-patch). From and Subject headers of email
3526 text/plain or text/x-patch). From and Subject headers of email
3522 message are used as default committer and commit message. All
3527 message are used as default committer and commit message. All
3523 text/plain body parts before first diff are added to commit
3528 text/plain body parts before first diff are added to commit
3524 message.
3529 message.
3525
3530
3526 If the imported patch was generated by :hg:`export`, user and
3531 If the imported patch was generated by :hg:`export`, user and
3527 description from patch override values from message headers and
3532 description from patch override values from message headers and
3528 body. Values given on command line with -m/--message and -u/--user
3533 body. Values given on command line with -m/--message and -u/--user
3529 override these.
3534 override these.
3530
3535
3531 If --exact is specified, import will set the working directory to
3536 If --exact is specified, import will set the working directory to
3532 the parent of each patch before applying it, and will abort if the
3537 the parent of each patch before applying it, and will abort if the
3533 resulting changeset has a different ID than the one recorded in
3538 resulting changeset has a different ID than the one recorded in
3534 the patch. This may happen due to character set problems or other
3539 the patch. This may happen due to character set problems or other
3535 deficiencies in the text patch format.
3540 deficiencies in the text patch format.
3536
3541
3537 Use --bypass to apply and commit patches directly to the
3542 Use --bypass to apply and commit patches directly to the
3538 repository, not touching the working directory. Without --exact,
3543 repository, not touching the working directory. Without --exact,
3539 patches will be applied on top of the working directory parent
3544 patches will be applied on top of the working directory parent
3540 revision.
3545 revision.
3541
3546
3542 With -s/--similarity, hg will attempt to discover renames and
3547 With -s/--similarity, hg will attempt to discover renames and
3543 copies in the patch in the same way as :hg:`addremove`.
3548 copies in the patch in the same way as :hg:`addremove`.
3544
3549
3545 To read a patch from standard input, use "-" as the patch name. If
3550 To read a patch from standard input, use "-" as the patch name. If
3546 a URL is specified, the patch will be downloaded from it.
3551 a URL is specified, the patch will be downloaded from it.
3547 See :hg:`help dates` for a list of formats valid for -d/--date.
3552 See :hg:`help dates` for a list of formats valid for -d/--date.
3548
3553
3549 .. container:: verbose
3554 .. container:: verbose
3550
3555
3551 Examples:
3556 Examples:
3552
3557
3553 - import a traditional patch from a website and detect renames::
3558 - import a traditional patch from a website and detect renames::
3554
3559
3555 hg import -s 80 http://example.com/bugfix.patch
3560 hg import -s 80 http://example.com/bugfix.patch
3556
3561
3557 - import a changeset from an hgweb server::
3562 - import a changeset from an hgweb server::
3558
3563
3559 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3564 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3560
3565
3561 - import all the patches in an Unix-style mbox::
3566 - import all the patches in an Unix-style mbox::
3562
3567
3563 hg import incoming-patches.mbox
3568 hg import incoming-patches.mbox
3564
3569
3565 - attempt to exactly restore an exported changeset (not always
3570 - attempt to exactly restore an exported changeset (not always
3566 possible)::
3571 possible)::
3567
3572
3568 hg import --exact proposed-fix.patch
3573 hg import --exact proposed-fix.patch
3569
3574
3570 Returns 0 on success.
3575 Returns 0 on success.
3571 """
3576 """
3572
3577
3573 if not patch1:
3578 if not patch1:
3574 raise util.Abort(_('need at least one patch to import'))
3579 raise util.Abort(_('need at least one patch to import'))
3575
3580
3576 patches = (patch1,) + patches
3581 patches = (patch1,) + patches
3577
3582
3578 date = opts.get('date')
3583 date = opts.get('date')
3579 if date:
3584 if date:
3580 opts['date'] = util.parsedate(date)
3585 opts['date'] = util.parsedate(date)
3581
3586
3582 editor = cmdutil.commiteditor
3587 editor = cmdutil.commiteditor
3583 if opts.get('edit'):
3588 if opts.get('edit'):
3584 editor = cmdutil.commitforceeditor
3589 editor = cmdutil.commitforceeditor
3585
3590
3586 update = not opts.get('bypass')
3591 update = not opts.get('bypass')
3587 if not update and opts.get('no_commit'):
3592 if not update and opts.get('no_commit'):
3588 raise util.Abort(_('cannot use --no-commit with --bypass'))
3593 raise util.Abort(_('cannot use --no-commit with --bypass'))
3589 try:
3594 try:
3590 sim = float(opts.get('similarity') or 0)
3595 sim = float(opts.get('similarity') or 0)
3591 except ValueError:
3596 except ValueError:
3592 raise util.Abort(_('similarity must be a number'))
3597 raise util.Abort(_('similarity must be a number'))
3593 if sim < 0 or sim > 100:
3598 if sim < 0 or sim > 100:
3594 raise util.Abort(_('similarity must be between 0 and 100'))
3599 raise util.Abort(_('similarity must be between 0 and 100'))
3595 if sim and not update:
3600 if sim and not update:
3596 raise util.Abort(_('cannot use --similarity with --bypass'))
3601 raise util.Abort(_('cannot use --similarity with --bypass'))
3597
3602
3598 if (opts.get('exact') or not opts.get('force')) and update:
3603 if (opts.get('exact') or not opts.get('force')) and update:
3599 cmdutil.bailifchanged(repo)
3604 cmdutil.bailifchanged(repo)
3600
3605
3601 base = opts["base"]
3606 base = opts["base"]
3602 strip = opts["strip"]
3607 strip = opts["strip"]
3603 wlock = lock = tr = None
3608 wlock = lock = tr = None
3604 msgs = []
3609 msgs = []
3605
3610
3606 def tryone(ui, hunk, parents):
3611 def tryone(ui, hunk, parents):
3607 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3612 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3608 patch.extract(ui, hunk)
3613 patch.extract(ui, hunk)
3609
3614
3610 if not tmpname:
3615 if not tmpname:
3611 return (None, None)
3616 return (None, None)
3612 msg = _('applied to working directory')
3617 msg = _('applied to working directory')
3613
3618
3614 try:
3619 try:
3615 cmdline_message = cmdutil.logmessage(ui, opts)
3620 cmdline_message = cmdutil.logmessage(ui, opts)
3616 if cmdline_message:
3621 if cmdline_message:
3617 # pickup the cmdline msg
3622 # pickup the cmdline msg
3618 message = cmdline_message
3623 message = cmdline_message
3619 elif message:
3624 elif message:
3620 # pickup the patch msg
3625 # pickup the patch msg
3621 message = message.strip()
3626 message = message.strip()
3622 else:
3627 else:
3623 # launch the editor
3628 # launch the editor
3624 message = None
3629 message = None
3625 ui.debug('message:\n%s\n' % message)
3630 ui.debug('message:\n%s\n' % message)
3626
3631
3627 if len(parents) == 1:
3632 if len(parents) == 1:
3628 parents.append(repo[nullid])
3633 parents.append(repo[nullid])
3629 if opts.get('exact'):
3634 if opts.get('exact'):
3630 if not nodeid or not p1:
3635 if not nodeid or not p1:
3631 raise util.Abort(_('not a Mercurial patch'))
3636 raise util.Abort(_('not a Mercurial patch'))
3632 p1 = repo[p1]
3637 p1 = repo[p1]
3633 p2 = repo[p2 or nullid]
3638 p2 = repo[p2 or nullid]
3634 elif p2:
3639 elif p2:
3635 try:
3640 try:
3636 p1 = repo[p1]
3641 p1 = repo[p1]
3637 p2 = repo[p2]
3642 p2 = repo[p2]
3638 # Without any options, consider p2 only if the
3643 # Without any options, consider p2 only if the
3639 # patch is being applied on top of the recorded
3644 # patch is being applied on top of the recorded
3640 # first parent.
3645 # first parent.
3641 if p1 != parents[0]:
3646 if p1 != parents[0]:
3642 p1 = parents[0]
3647 p1 = parents[0]
3643 p2 = repo[nullid]
3648 p2 = repo[nullid]
3644 except error.RepoError:
3649 except error.RepoError:
3645 p1, p2 = parents
3650 p1, p2 = parents
3646 else:
3651 else:
3647 p1, p2 = parents
3652 p1, p2 = parents
3648
3653
3649 n = None
3654 n = None
3650 if update:
3655 if update:
3651 if p1 != parents[0]:
3656 if p1 != parents[0]:
3652 hg.clean(repo, p1.node())
3657 hg.clean(repo, p1.node())
3653 if p2 != parents[1]:
3658 if p2 != parents[1]:
3654 repo.setparents(p1.node(), p2.node())
3659 repo.setparents(p1.node(), p2.node())
3655
3660
3656 if opts.get('exact') or opts.get('import_branch'):
3661 if opts.get('exact') or opts.get('import_branch'):
3657 repo.dirstate.setbranch(branch or 'default')
3662 repo.dirstate.setbranch(branch or 'default')
3658
3663
3659 files = set()
3664 files = set()
3660 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3665 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3661 eolmode=None, similarity=sim / 100.0)
3666 eolmode=None, similarity=sim / 100.0)
3662 files = list(files)
3667 files = list(files)
3663 if opts.get('no_commit'):
3668 if opts.get('no_commit'):
3664 if message:
3669 if message:
3665 msgs.append(message)
3670 msgs.append(message)
3666 else:
3671 else:
3667 if opts.get('exact') or p2:
3672 if opts.get('exact') or p2:
3668 # If you got here, you either use --force and know what
3673 # If you got here, you either use --force and know what
3669 # you are doing or used --exact or a merge patch while
3674 # you are doing or used --exact or a merge patch while
3670 # being updated to its first parent.
3675 # being updated to its first parent.
3671 m = None
3676 m = None
3672 else:
3677 else:
3673 m = scmutil.matchfiles(repo, files or [])
3678 m = scmutil.matchfiles(repo, files or [])
3674 n = repo.commit(message, opts.get('user') or user,
3679 n = repo.commit(message, opts.get('user') or user,
3675 opts.get('date') or date, match=m,
3680 opts.get('date') or date, match=m,
3676 editor=editor)
3681 editor=editor)
3677 else:
3682 else:
3678 if opts.get('exact') or opts.get('import_branch'):
3683 if opts.get('exact') or opts.get('import_branch'):
3679 branch = branch or 'default'
3684 branch = branch or 'default'
3680 else:
3685 else:
3681 branch = p1.branch()
3686 branch = p1.branch()
3682 store = patch.filestore()
3687 store = patch.filestore()
3683 try:
3688 try:
3684 files = set()
3689 files = set()
3685 try:
3690 try:
3686 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3691 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3687 files, eolmode=None)
3692 files, eolmode=None)
3688 except patch.PatchError, e:
3693 except patch.PatchError, e:
3689 raise util.Abort(str(e))
3694 raise util.Abort(str(e))
3690 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3695 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3691 message,
3696 message,
3692 opts.get('user') or user,
3697 opts.get('user') or user,
3693 opts.get('date') or date,
3698 opts.get('date') or date,
3694 branch, files, store,
3699 branch, files, store,
3695 editor=cmdutil.commiteditor)
3700 editor=cmdutil.commiteditor)
3696 repo.savecommitmessage(memctx.description())
3701 repo.savecommitmessage(memctx.description())
3697 n = memctx.commit()
3702 n = memctx.commit()
3698 finally:
3703 finally:
3699 store.close()
3704 store.close()
3700 if opts.get('exact') and hex(n) != nodeid:
3705 if opts.get('exact') and hex(n) != nodeid:
3701 raise util.Abort(_('patch is damaged or loses information'))
3706 raise util.Abort(_('patch is damaged or loses information'))
3702 if n:
3707 if n:
3703 # i18n: refers to a short changeset id
3708 # i18n: refers to a short changeset id
3704 msg = _('created %s') % short(n)
3709 msg = _('created %s') % short(n)
3705 return (msg, n)
3710 return (msg, n)
3706 finally:
3711 finally:
3707 os.unlink(tmpname)
3712 os.unlink(tmpname)
3708
3713
3709 try:
3714 try:
3710 try:
3715 try:
3711 wlock = repo.wlock()
3716 wlock = repo.wlock()
3712 if not opts.get('no_commit'):
3717 if not opts.get('no_commit'):
3713 lock = repo.lock()
3718 lock = repo.lock()
3714 tr = repo.transaction('import')
3719 tr = repo.transaction('import')
3715 parents = repo.parents()
3720 parents = repo.parents()
3716 for patchurl in patches:
3721 for patchurl in patches:
3717 if patchurl == '-':
3722 if patchurl == '-':
3718 ui.status(_('applying patch from stdin\n'))
3723 ui.status(_('applying patch from stdin\n'))
3719 patchfile = ui.fin
3724 patchfile = ui.fin
3720 patchurl = 'stdin' # for error message
3725 patchurl = 'stdin' # for error message
3721 else:
3726 else:
3722 patchurl = os.path.join(base, patchurl)
3727 patchurl = os.path.join(base, patchurl)
3723 ui.status(_('applying %s\n') % patchurl)
3728 ui.status(_('applying %s\n') % patchurl)
3724 patchfile = hg.openpath(ui, patchurl)
3729 patchfile = hg.openpath(ui, patchurl)
3725
3730
3726 haspatch = False
3731 haspatch = False
3727 for hunk in patch.split(patchfile):
3732 for hunk in patch.split(patchfile):
3728 (msg, node) = tryone(ui, hunk, parents)
3733 (msg, node) = tryone(ui, hunk, parents)
3729 if msg:
3734 if msg:
3730 haspatch = True
3735 haspatch = True
3731 ui.note(msg + '\n')
3736 ui.note(msg + '\n')
3732 if update or opts.get('exact'):
3737 if update or opts.get('exact'):
3733 parents = repo.parents()
3738 parents = repo.parents()
3734 else:
3739 else:
3735 parents = [repo[node]]
3740 parents = [repo[node]]
3736
3741
3737 if not haspatch:
3742 if not haspatch:
3738 raise util.Abort(_('%s: no diffs found') % patchurl)
3743 raise util.Abort(_('%s: no diffs found') % patchurl)
3739
3744
3740 if tr:
3745 if tr:
3741 tr.close()
3746 tr.close()
3742 if msgs:
3747 if msgs:
3743 repo.savecommitmessage('\n* * *\n'.join(msgs))
3748 repo.savecommitmessage('\n* * *\n'.join(msgs))
3744 except: # re-raises
3749 except: # re-raises
3745 # wlock.release() indirectly calls dirstate.write(): since
3750 # wlock.release() indirectly calls dirstate.write(): since
3746 # we're crashing, we do not want to change the working dir
3751 # we're crashing, we do not want to change the working dir
3747 # parent after all, so make sure it writes nothing
3752 # parent after all, so make sure it writes nothing
3748 repo.dirstate.invalidate()
3753 repo.dirstate.invalidate()
3749 raise
3754 raise
3750 finally:
3755 finally:
3751 if tr:
3756 if tr:
3752 tr.release()
3757 tr.release()
3753 release(lock, wlock)
3758 release(lock, wlock)
3754
3759
3755 @command('incoming|in',
3760 @command('incoming|in',
3756 [('f', 'force', None,
3761 [('f', 'force', None,
3757 _('run even if remote repository is unrelated')),
3762 _('run even if remote repository is unrelated')),
3758 ('n', 'newest-first', None, _('show newest record first')),
3763 ('n', 'newest-first', None, _('show newest record first')),
3759 ('', 'bundle', '',
3764 ('', 'bundle', '',
3760 _('file to store the bundles into'), _('FILE')),
3765 _('file to store the bundles into'), _('FILE')),
3761 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3766 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3762 ('B', 'bookmarks', False, _("compare bookmarks")),
3767 ('B', 'bookmarks', False, _("compare bookmarks")),
3763 ('b', 'branch', [],
3768 ('b', 'branch', [],
3764 _('a specific branch you would like to pull'), _('BRANCH')),
3769 _('a specific branch you would like to pull'), _('BRANCH')),
3765 ] + logopts + remoteopts + subrepoopts,
3770 ] + logopts + remoteopts + subrepoopts,
3766 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3771 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3767 def incoming(ui, repo, source="default", **opts):
3772 def incoming(ui, repo, source="default", **opts):
3768 """show new changesets found in source
3773 """show new changesets found in source
3769
3774
3770 Show new changesets found in the specified path/URL or the default
3775 Show new changesets found in the specified path/URL or the default
3771 pull location. These are the changesets that would have been pulled
3776 pull location. These are the changesets that would have been pulled
3772 if a pull at the time you issued this command.
3777 if a pull at the time you issued this command.
3773
3778
3774 For remote repository, using --bundle avoids downloading the
3779 For remote repository, using --bundle avoids downloading the
3775 changesets twice if the incoming is followed by a pull.
3780 changesets twice if the incoming is followed by a pull.
3776
3781
3777 See pull for valid source format details.
3782 See pull for valid source format details.
3778
3783
3779 Returns 0 if there are incoming changes, 1 otherwise.
3784 Returns 0 if there are incoming changes, 1 otherwise.
3780 """
3785 """
3781 if opts.get('graph'):
3786 if opts.get('graph'):
3782 cmdutil.checkunsupportedgraphflags([], opts)
3787 cmdutil.checkunsupportedgraphflags([], opts)
3783 def display(other, chlist, displayer):
3788 def display(other, chlist, displayer):
3784 revdag = cmdutil.graphrevs(other, chlist, opts)
3789 revdag = cmdutil.graphrevs(other, chlist, opts)
3785 showparents = [ctx.node() for ctx in repo[None].parents()]
3790 showparents = [ctx.node() for ctx in repo[None].parents()]
3786 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3791 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3787 graphmod.asciiedges)
3792 graphmod.asciiedges)
3788
3793
3789 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3794 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3790 return 0
3795 return 0
3791
3796
3792 if opts.get('bundle') and opts.get('subrepos'):
3797 if opts.get('bundle') and opts.get('subrepos'):
3793 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3798 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3794
3799
3795 if opts.get('bookmarks'):
3800 if opts.get('bookmarks'):
3796 source, branches = hg.parseurl(ui.expandpath(source),
3801 source, branches = hg.parseurl(ui.expandpath(source),
3797 opts.get('branch'))
3802 opts.get('branch'))
3798 other = hg.peer(repo, opts, source)
3803 other = hg.peer(repo, opts, source)
3799 if 'bookmarks' not in other.listkeys('namespaces'):
3804 if 'bookmarks' not in other.listkeys('namespaces'):
3800 ui.warn(_("remote doesn't support bookmarks\n"))
3805 ui.warn(_("remote doesn't support bookmarks\n"))
3801 return 0
3806 return 0
3802 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3807 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3803 return bookmarks.diff(ui, repo, other)
3808 return bookmarks.diff(ui, repo, other)
3804
3809
3805 repo._subtoppath = ui.expandpath(source)
3810 repo._subtoppath = ui.expandpath(source)
3806 try:
3811 try:
3807 return hg.incoming(ui, repo, source, opts)
3812 return hg.incoming(ui, repo, source, opts)
3808 finally:
3813 finally:
3809 del repo._subtoppath
3814 del repo._subtoppath
3810
3815
3811
3816
3812 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3817 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3813 def init(ui, dest=".", **opts):
3818 def init(ui, dest=".", **opts):
3814 """create a new repository in the given directory
3819 """create a new repository in the given directory
3815
3820
3816 Initialize a new repository in the given directory. If the given
3821 Initialize a new repository in the given directory. If the given
3817 directory does not exist, it will be created.
3822 directory does not exist, it will be created.
3818
3823
3819 If no directory is given, the current directory is used.
3824 If no directory is given, the current directory is used.
3820
3825
3821 It is possible to specify an ``ssh://`` URL as the destination.
3826 It is possible to specify an ``ssh://`` URL as the destination.
3822 See :hg:`help urls` for more information.
3827 See :hg:`help urls` for more information.
3823
3828
3824 Returns 0 on success.
3829 Returns 0 on success.
3825 """
3830 """
3826 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3831 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3827
3832
3828 @command('locate',
3833 @command('locate',
3829 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3834 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3830 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3835 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3831 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3836 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3832 ] + walkopts,
3837 ] + walkopts,
3833 _('[OPTION]... [PATTERN]...'))
3838 _('[OPTION]... [PATTERN]...'))
3834 def locate(ui, repo, *pats, **opts):
3839 def locate(ui, repo, *pats, **opts):
3835 """locate files matching specific patterns
3840 """locate files matching specific patterns
3836
3841
3837 Print files under Mercurial control in the working directory whose
3842 Print files under Mercurial control in the working directory whose
3838 names match the given patterns.
3843 names match the given patterns.
3839
3844
3840 By default, this command searches all directories in the working
3845 By default, this command searches all directories in the working
3841 directory. To search just the current directory and its
3846 directory. To search just the current directory and its
3842 subdirectories, use "--include .".
3847 subdirectories, use "--include .".
3843
3848
3844 If no patterns are given to match, this command prints the names
3849 If no patterns are given to match, this command prints the names
3845 of all files under Mercurial control in the working directory.
3850 of all files under Mercurial control in the working directory.
3846
3851
3847 If you want to feed the output of this command into the "xargs"
3852 If you want to feed the output of this command into the "xargs"
3848 command, use the -0 option to both this command and "xargs". This
3853 command, use the -0 option to both this command and "xargs". This
3849 will avoid the problem of "xargs" treating single filenames that
3854 will avoid the problem of "xargs" treating single filenames that
3850 contain whitespace as multiple filenames.
3855 contain whitespace as multiple filenames.
3851
3856
3852 Returns 0 if a match is found, 1 otherwise.
3857 Returns 0 if a match is found, 1 otherwise.
3853 """
3858 """
3854 end = opts.get('print0') and '\0' or '\n'
3859 end = opts.get('print0') and '\0' or '\n'
3855 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3860 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3856
3861
3857 ret = 1
3862 ret = 1
3858 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3863 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3859 m.bad = lambda x, y: False
3864 m.bad = lambda x, y: False
3860 for abs in repo[rev].walk(m):
3865 for abs in repo[rev].walk(m):
3861 if not rev and abs not in repo.dirstate:
3866 if not rev and abs not in repo.dirstate:
3862 continue
3867 continue
3863 if opts.get('fullpath'):
3868 if opts.get('fullpath'):
3864 ui.write(repo.wjoin(abs), end)
3869 ui.write(repo.wjoin(abs), end)
3865 else:
3870 else:
3866 ui.write(((pats and m.rel(abs)) or abs), end)
3871 ui.write(((pats and m.rel(abs)) or abs), end)
3867 ret = 0
3872 ret = 0
3868
3873
3869 return ret
3874 return ret
3870
3875
3871 @command('^log|history',
3876 @command('^log|history',
3872 [('f', 'follow', None,
3877 [('f', 'follow', None,
3873 _('follow changeset history, or file history across copies and renames')),
3878 _('follow changeset history, or file history across copies and renames')),
3874 ('', 'follow-first', None,
3879 ('', 'follow-first', None,
3875 _('only follow the first parent of merge changesets (DEPRECATED)')),
3880 _('only follow the first parent of merge changesets (DEPRECATED)')),
3876 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3881 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3877 ('C', 'copies', None, _('show copied files')),
3882 ('C', 'copies', None, _('show copied files')),
3878 ('k', 'keyword', [],
3883 ('k', 'keyword', [],
3879 _('do case-insensitive search for a given text'), _('TEXT')),
3884 _('do case-insensitive search for a given text'), _('TEXT')),
3880 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3885 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3881 ('', 'removed', None, _('include revisions where files were removed')),
3886 ('', 'removed', None, _('include revisions where files were removed')),
3882 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3887 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3883 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3888 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3884 ('', 'only-branch', [],
3889 ('', 'only-branch', [],
3885 _('show only changesets within the given named branch (DEPRECATED)'),
3890 _('show only changesets within the given named branch (DEPRECATED)'),
3886 _('BRANCH')),
3891 _('BRANCH')),
3887 ('b', 'branch', [],
3892 ('b', 'branch', [],
3888 _('show changesets within the given named branch'), _('BRANCH')),
3893 _('show changesets within the given named branch'), _('BRANCH')),
3889 ('P', 'prune', [],
3894 ('P', 'prune', [],
3890 _('do not display revision or any of its ancestors'), _('REV')),
3895 _('do not display revision or any of its ancestors'), _('REV')),
3891 ] + logopts + walkopts,
3896 ] + logopts + walkopts,
3892 _('[OPTION]... [FILE]'))
3897 _('[OPTION]... [FILE]'))
3893 def log(ui, repo, *pats, **opts):
3898 def log(ui, repo, *pats, **opts):
3894 """show revision history of entire repository or files
3899 """show revision history of entire repository or files
3895
3900
3896 Print the revision history of the specified files or the entire
3901 Print the revision history of the specified files or the entire
3897 project.
3902 project.
3898
3903
3899 If no revision range is specified, the default is ``tip:0`` unless
3904 If no revision range is specified, the default is ``tip:0`` unless
3900 --follow is set, in which case the working directory parent is
3905 --follow is set, in which case the working directory parent is
3901 used as the starting revision.
3906 used as the starting revision.
3902
3907
3903 File history is shown without following rename or copy history of
3908 File history is shown without following rename or copy history of
3904 files. Use -f/--follow with a filename to follow history across
3909 files. Use -f/--follow with a filename to follow history across
3905 renames and copies. --follow without a filename will only show
3910 renames and copies. --follow without a filename will only show
3906 ancestors or descendants of the starting revision.
3911 ancestors or descendants of the starting revision.
3907
3912
3908 By default this command prints revision number and changeset id,
3913 By default this command prints revision number and changeset id,
3909 tags, non-trivial parents, user, date and time, and a summary for
3914 tags, non-trivial parents, user, date and time, and a summary for
3910 each commit. When the -v/--verbose switch is used, the list of
3915 each commit. When the -v/--verbose switch is used, the list of
3911 changed files and full commit message are shown.
3916 changed files and full commit message are shown.
3912
3917
3913 .. note::
3918 .. note::
3914 log -p/--patch may generate unexpected diff output for merge
3919 log -p/--patch may generate unexpected diff output for merge
3915 changesets, as it will only compare the merge changeset against
3920 changesets, as it will only compare the merge changeset against
3916 its first parent. Also, only files different from BOTH parents
3921 its first parent. Also, only files different from BOTH parents
3917 will appear in files:.
3922 will appear in files:.
3918
3923
3919 .. note::
3924 .. note::
3920 for performance reasons, log FILE may omit duplicate changes
3925 for performance reasons, log FILE may omit duplicate changes
3921 made on branches and will not show deletions. To see all
3926 made on branches and will not show deletions. To see all
3922 changes including duplicates and deletions, use the --removed
3927 changes including duplicates and deletions, use the --removed
3923 switch.
3928 switch.
3924
3929
3925 .. container:: verbose
3930 .. container:: verbose
3926
3931
3927 Some examples:
3932 Some examples:
3928
3933
3929 - changesets with full descriptions and file lists::
3934 - changesets with full descriptions and file lists::
3930
3935
3931 hg log -v
3936 hg log -v
3932
3937
3933 - changesets ancestral to the working directory::
3938 - changesets ancestral to the working directory::
3934
3939
3935 hg log -f
3940 hg log -f
3936
3941
3937 - last 10 commits on the current branch::
3942 - last 10 commits on the current branch::
3938
3943
3939 hg log -l 10 -b .
3944 hg log -l 10 -b .
3940
3945
3941 - changesets showing all modifications of a file, including removals::
3946 - changesets showing all modifications of a file, including removals::
3942
3947
3943 hg log --removed file.c
3948 hg log --removed file.c
3944
3949
3945 - all changesets that touch a directory, with diffs, excluding merges::
3950 - all changesets that touch a directory, with diffs, excluding merges::
3946
3951
3947 hg log -Mp lib/
3952 hg log -Mp lib/
3948
3953
3949 - all revision numbers that match a keyword::
3954 - all revision numbers that match a keyword::
3950
3955
3951 hg log -k bug --template "{rev}\\n"
3956 hg log -k bug --template "{rev}\\n"
3952
3957
3953 - check if a given changeset is included is a tagged release::
3958 - check if a given changeset is included is a tagged release::
3954
3959
3955 hg log -r "a21ccf and ancestor(1.9)"
3960 hg log -r "a21ccf and ancestor(1.9)"
3956
3961
3957 - find all changesets by some user in a date range::
3962 - find all changesets by some user in a date range::
3958
3963
3959 hg log -k alice -d "may 2008 to jul 2008"
3964 hg log -k alice -d "may 2008 to jul 2008"
3960
3965
3961 - summary of all changesets after the last tag::
3966 - summary of all changesets after the last tag::
3962
3967
3963 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3968 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3964
3969
3965 See :hg:`help dates` for a list of formats valid for -d/--date.
3970 See :hg:`help dates` for a list of formats valid for -d/--date.
3966
3971
3967 See :hg:`help revisions` and :hg:`help revsets` for more about
3972 See :hg:`help revisions` and :hg:`help revsets` for more about
3968 specifying revisions.
3973 specifying revisions.
3969
3974
3970 See :hg:`help templates` for more about pre-packaged styles and
3975 See :hg:`help templates` for more about pre-packaged styles and
3971 specifying custom templates.
3976 specifying custom templates.
3972
3977
3973 Returns 0 on success.
3978 Returns 0 on success.
3974 """
3979 """
3975 if opts.get('graph'):
3980 if opts.get('graph'):
3976 return cmdutil.graphlog(ui, repo, *pats, **opts)
3981 return cmdutil.graphlog(ui, repo, *pats, **opts)
3977
3982
3978 matchfn = scmutil.match(repo[None], pats, opts)
3983 matchfn = scmutil.match(repo[None], pats, opts)
3979 limit = cmdutil.loglimit(opts)
3984 limit = cmdutil.loglimit(opts)
3980 count = 0
3985 count = 0
3981
3986
3982 getrenamed, endrev = None, None
3987 getrenamed, endrev = None, None
3983 if opts.get('copies'):
3988 if opts.get('copies'):
3984 if opts.get('rev'):
3989 if opts.get('rev'):
3985 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3990 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3986 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3991 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3987
3992
3988 df = False
3993 df = False
3989 if opts.get("date"):
3994 if opts.get("date"):
3990 df = util.matchdate(opts["date"])
3995 df = util.matchdate(opts["date"])
3991
3996
3992 branches = opts.get('branch', []) + opts.get('only_branch', [])
3997 branches = opts.get('branch', []) + opts.get('only_branch', [])
3993 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3998 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3994
3999
3995 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4000 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3996 def prep(ctx, fns):
4001 def prep(ctx, fns):
3997 rev = ctx.rev()
4002 rev = ctx.rev()
3998 parents = [p for p in repo.changelog.parentrevs(rev)
4003 parents = [p for p in repo.changelog.parentrevs(rev)
3999 if p != nullrev]
4004 if p != nullrev]
4000 if opts.get('no_merges') and len(parents) == 2:
4005 if opts.get('no_merges') and len(parents) == 2:
4001 return
4006 return
4002 if opts.get('only_merges') and len(parents) != 2:
4007 if opts.get('only_merges') and len(parents) != 2:
4003 return
4008 return
4004 if opts.get('branch') and ctx.branch() not in opts['branch']:
4009 if opts.get('branch') and ctx.branch() not in opts['branch']:
4005 return
4010 return
4006 if df and not df(ctx.date()[0]):
4011 if df and not df(ctx.date()[0]):
4007 return
4012 return
4008
4013
4009 lower = encoding.lower
4014 lower = encoding.lower
4010 if opts.get('user'):
4015 if opts.get('user'):
4011 luser = lower(ctx.user())
4016 luser = lower(ctx.user())
4012 for k in [lower(x) for x in opts['user']]:
4017 for k in [lower(x) for x in opts['user']]:
4013 if (k in luser):
4018 if (k in luser):
4014 break
4019 break
4015 else:
4020 else:
4016 return
4021 return
4017 if opts.get('keyword'):
4022 if opts.get('keyword'):
4018 luser = lower(ctx.user())
4023 luser = lower(ctx.user())
4019 ldesc = lower(ctx.description())
4024 ldesc = lower(ctx.description())
4020 lfiles = lower(" ".join(ctx.files()))
4025 lfiles = lower(" ".join(ctx.files()))
4021 for k in [lower(x) for x in opts['keyword']]:
4026 for k in [lower(x) for x in opts['keyword']]:
4022 if (k in luser or k in ldesc or k in lfiles):
4027 if (k in luser or k in ldesc or k in lfiles):
4023 break
4028 break
4024 else:
4029 else:
4025 return
4030 return
4026
4031
4027 copies = None
4032 copies = None
4028 if getrenamed is not None and rev:
4033 if getrenamed is not None and rev:
4029 copies = []
4034 copies = []
4030 for fn in ctx.files():
4035 for fn in ctx.files():
4031 rename = getrenamed(fn, rev)
4036 rename = getrenamed(fn, rev)
4032 if rename:
4037 if rename:
4033 copies.append((fn, rename[0]))
4038 copies.append((fn, rename[0]))
4034
4039
4035 revmatchfn = None
4040 revmatchfn = None
4036 if opts.get('patch') or opts.get('stat'):
4041 if opts.get('patch') or opts.get('stat'):
4037 if opts.get('follow') or opts.get('follow_first'):
4042 if opts.get('follow') or opts.get('follow_first'):
4038 # note: this might be wrong when following through merges
4043 # note: this might be wrong when following through merges
4039 revmatchfn = scmutil.match(repo[None], fns, default='path')
4044 revmatchfn = scmutil.match(repo[None], fns, default='path')
4040 else:
4045 else:
4041 revmatchfn = matchfn
4046 revmatchfn = matchfn
4042
4047
4043 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4048 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4044
4049
4045 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4050 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4046 if displayer.flush(ctx.rev()):
4051 if displayer.flush(ctx.rev()):
4047 count += 1
4052 count += 1
4048 if count == limit:
4053 if count == limit:
4049 break
4054 break
4050 displayer.close()
4055 displayer.close()
4051
4056
4052 @command('manifest',
4057 @command('manifest',
4053 [('r', 'rev', '', _('revision to display'), _('REV')),
4058 [('r', 'rev', '', _('revision to display'), _('REV')),
4054 ('', 'all', False, _("list files from all revisions"))],
4059 ('', 'all', False, _("list files from all revisions"))],
4055 _('[-r REV]'))
4060 _('[-r REV]'))
4056 def manifest(ui, repo, node=None, rev=None, **opts):
4061 def manifest(ui, repo, node=None, rev=None, **opts):
4057 """output the current or given revision of the project manifest
4062 """output the current or given revision of the project manifest
4058
4063
4059 Print a list of version controlled files for the given revision.
4064 Print a list of version controlled files for the given revision.
4060 If no revision is given, the first parent of the working directory
4065 If no revision is given, the first parent of the working directory
4061 is used, or the null revision if no revision is checked out.
4066 is used, or the null revision if no revision is checked out.
4062
4067
4063 With -v, print file permissions, symlink and executable bits.
4068 With -v, print file permissions, symlink and executable bits.
4064 With --debug, print file revision hashes.
4069 With --debug, print file revision hashes.
4065
4070
4066 If option --all is specified, the list of all files from all revisions
4071 If option --all is specified, the list of all files from all revisions
4067 is printed. This includes deleted and renamed files.
4072 is printed. This includes deleted and renamed files.
4068
4073
4069 Returns 0 on success.
4074 Returns 0 on success.
4070 """
4075 """
4071
4076
4072 fm = ui.formatter('manifest', opts)
4077 fm = ui.formatter('manifest', opts)
4073
4078
4074 if opts.get('all'):
4079 if opts.get('all'):
4075 if rev or node:
4080 if rev or node:
4076 raise util.Abort(_("can't specify a revision with --all"))
4081 raise util.Abort(_("can't specify a revision with --all"))
4077
4082
4078 res = []
4083 res = []
4079 prefix = "data/"
4084 prefix = "data/"
4080 suffix = ".i"
4085 suffix = ".i"
4081 plen = len(prefix)
4086 plen = len(prefix)
4082 slen = len(suffix)
4087 slen = len(suffix)
4083 lock = repo.lock()
4088 lock = repo.lock()
4084 try:
4089 try:
4085 for fn, b, size in repo.store.datafiles():
4090 for fn, b, size in repo.store.datafiles():
4086 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4091 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4087 res.append(fn[plen:-slen])
4092 res.append(fn[plen:-slen])
4088 finally:
4093 finally:
4089 lock.release()
4094 lock.release()
4090 for f in res:
4095 for f in res:
4091 fm.startitem()
4096 fm.startitem()
4092 fm.write("path", '%s\n', f)
4097 fm.write("path", '%s\n', f)
4093 fm.end()
4098 fm.end()
4094 return
4099 return
4095
4100
4096 if rev and node:
4101 if rev and node:
4097 raise util.Abort(_("please specify just one revision"))
4102 raise util.Abort(_("please specify just one revision"))
4098
4103
4099 if not node:
4104 if not node:
4100 node = rev
4105 node = rev
4101
4106
4102 char = {'l': '@', 'x': '*', '': ''}
4107 char = {'l': '@', 'x': '*', '': ''}
4103 mode = {'l': '644', 'x': '755', '': '644'}
4108 mode = {'l': '644', 'x': '755', '': '644'}
4104 ctx = scmutil.revsingle(repo, node)
4109 ctx = scmutil.revsingle(repo, node)
4105 mf = ctx.manifest()
4110 mf = ctx.manifest()
4106 for f in ctx:
4111 for f in ctx:
4107 fm.startitem()
4112 fm.startitem()
4108 fl = ctx[f].flags()
4113 fl = ctx[f].flags()
4109 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4114 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4110 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4115 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4111 fm.write('path', '%s\n', f)
4116 fm.write('path', '%s\n', f)
4112 fm.end()
4117 fm.end()
4113
4118
4114 @command('^merge',
4119 @command('^merge',
4115 [('f', 'force', None, _('force a merge with outstanding changes')),
4120 [('f', 'force', None, _('force a merge with outstanding changes')),
4116 ('r', 'rev', '', _('revision to merge'), _('REV')),
4121 ('r', 'rev', '', _('revision to merge'), _('REV')),
4117 ('P', 'preview', None,
4122 ('P', 'preview', None,
4118 _('review revisions to merge (no merge is performed)'))
4123 _('review revisions to merge (no merge is performed)'))
4119 ] + mergetoolopts,
4124 ] + mergetoolopts,
4120 _('[-P] [-f] [[-r] REV]'))
4125 _('[-P] [-f] [[-r] REV]'))
4121 def merge(ui, repo, node=None, **opts):
4126 def merge(ui, repo, node=None, **opts):
4122 """merge working directory with another revision
4127 """merge working directory with another revision
4123
4128
4124 The current working directory is updated with all changes made in
4129 The current working directory is updated with all changes made in
4125 the requested revision since the last common predecessor revision.
4130 the requested revision since the last common predecessor revision.
4126
4131
4127 Files that changed between either parent are marked as changed for
4132 Files that changed between either parent are marked as changed for
4128 the next commit and a commit must be performed before any further
4133 the next commit and a commit must be performed before any further
4129 updates to the repository are allowed. The next commit will have
4134 updates to the repository are allowed. The next commit will have
4130 two parents.
4135 two parents.
4131
4136
4132 ``--tool`` can be used to specify the merge tool used for file
4137 ``--tool`` can be used to specify the merge tool used for file
4133 merges. It overrides the HGMERGE environment variable and your
4138 merges. It overrides the HGMERGE environment variable and your
4134 configuration files. See :hg:`help merge-tools` for options.
4139 configuration files. See :hg:`help merge-tools` for options.
4135
4140
4136 If no revision is specified, the working directory's parent is a
4141 If no revision is specified, the working directory's parent is a
4137 head revision, and the current branch contains exactly one other
4142 head revision, and the current branch contains exactly one other
4138 head, the other head is merged with by default. Otherwise, an
4143 head, the other head is merged with by default. Otherwise, an
4139 explicit revision with which to merge with must be provided.
4144 explicit revision with which to merge with must be provided.
4140
4145
4141 :hg:`resolve` must be used to resolve unresolved files.
4146 :hg:`resolve` must be used to resolve unresolved files.
4142
4147
4143 To undo an uncommitted merge, use :hg:`update --clean .` which
4148 To undo an uncommitted merge, use :hg:`update --clean .` which
4144 will check out a clean copy of the original merge parent, losing
4149 will check out a clean copy of the original merge parent, losing
4145 all changes.
4150 all changes.
4146
4151
4147 Returns 0 on success, 1 if there are unresolved files.
4152 Returns 0 on success, 1 if there are unresolved files.
4148 """
4153 """
4149
4154
4150 if opts.get('rev') and node:
4155 if opts.get('rev') and node:
4151 raise util.Abort(_("please specify just one revision"))
4156 raise util.Abort(_("please specify just one revision"))
4152 if not node:
4157 if not node:
4153 node = opts.get('rev')
4158 node = opts.get('rev')
4154
4159
4155 if node:
4160 if node:
4156 node = scmutil.revsingle(repo, node).node()
4161 node = scmutil.revsingle(repo, node).node()
4157
4162
4158 if not node and repo._bookmarkcurrent:
4163 if not node and repo._bookmarkcurrent:
4159 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4164 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4160 curhead = repo[repo._bookmarkcurrent].node()
4165 curhead = repo[repo._bookmarkcurrent].node()
4161 if len(bmheads) == 2:
4166 if len(bmheads) == 2:
4162 if curhead == bmheads[0]:
4167 if curhead == bmheads[0]:
4163 node = bmheads[1]
4168 node = bmheads[1]
4164 else:
4169 else:
4165 node = bmheads[0]
4170 node = bmheads[0]
4166 elif len(bmheads) > 2:
4171 elif len(bmheads) > 2:
4167 raise util.Abort(_("multiple matching bookmarks to merge - "
4172 raise util.Abort(_("multiple matching bookmarks to merge - "
4168 "please merge with an explicit rev or bookmark"),
4173 "please merge with an explicit rev or bookmark"),
4169 hint=_("run 'hg heads' to see all heads"))
4174 hint=_("run 'hg heads' to see all heads"))
4170 elif len(bmheads) <= 1:
4175 elif len(bmheads) <= 1:
4171 raise util.Abort(_("no matching bookmark to merge - "
4176 raise util.Abort(_("no matching bookmark to merge - "
4172 "please merge with an explicit rev or bookmark"),
4177 "please merge with an explicit rev or bookmark"),
4173 hint=_("run 'hg heads' to see all heads"))
4178 hint=_("run 'hg heads' to see all heads"))
4174
4179
4175 if not node and not repo._bookmarkcurrent:
4180 if not node and not repo._bookmarkcurrent:
4176 branch = repo[None].branch()
4181 branch = repo[None].branch()
4177 bheads = repo.branchheads(branch)
4182 bheads = repo.branchheads(branch)
4178 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4183 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4179
4184
4180 if len(nbhs) > 2:
4185 if len(nbhs) > 2:
4181 raise util.Abort(_("branch '%s' has %d heads - "
4186 raise util.Abort(_("branch '%s' has %d heads - "
4182 "please merge with an explicit rev")
4187 "please merge with an explicit rev")
4183 % (branch, len(bheads)),
4188 % (branch, len(bheads)),
4184 hint=_("run 'hg heads .' to see heads"))
4189 hint=_("run 'hg heads .' to see heads"))
4185
4190
4186 parent = repo.dirstate.p1()
4191 parent = repo.dirstate.p1()
4187 if len(nbhs) <= 1:
4192 if len(nbhs) <= 1:
4188 if len(bheads) > 1:
4193 if len(bheads) > 1:
4189 raise util.Abort(_("heads are bookmarked - "
4194 raise util.Abort(_("heads are bookmarked - "
4190 "please merge with an explicit rev"),
4195 "please merge with an explicit rev"),
4191 hint=_("run 'hg heads' to see all heads"))
4196 hint=_("run 'hg heads' to see all heads"))
4192 if len(repo.heads()) > 1:
4197 if len(repo.heads()) > 1:
4193 raise util.Abort(_("branch '%s' has one head - "
4198 raise util.Abort(_("branch '%s' has one head - "
4194 "please merge with an explicit rev")
4199 "please merge with an explicit rev")
4195 % branch,
4200 % branch,
4196 hint=_("run 'hg heads' to see all heads"))
4201 hint=_("run 'hg heads' to see all heads"))
4197 msg, hint = _('nothing to merge'), None
4202 msg, hint = _('nothing to merge'), None
4198 if parent != repo.lookup(branch):
4203 if parent != repo.lookup(branch):
4199 hint = _("use 'hg update' instead")
4204 hint = _("use 'hg update' instead")
4200 raise util.Abort(msg, hint=hint)
4205 raise util.Abort(msg, hint=hint)
4201
4206
4202 if parent not in bheads:
4207 if parent not in bheads:
4203 raise util.Abort(_('working directory not at a head revision'),
4208 raise util.Abort(_('working directory not at a head revision'),
4204 hint=_("use 'hg update' or merge with an "
4209 hint=_("use 'hg update' or merge with an "
4205 "explicit revision"))
4210 "explicit revision"))
4206 if parent == nbhs[0]:
4211 if parent == nbhs[0]:
4207 node = nbhs[-1]
4212 node = nbhs[-1]
4208 else:
4213 else:
4209 node = nbhs[0]
4214 node = nbhs[0]
4210
4215
4211 if opts.get('preview'):
4216 if opts.get('preview'):
4212 # find nodes that are ancestors of p2 but not of p1
4217 # find nodes that are ancestors of p2 but not of p1
4213 p1 = repo.lookup('.')
4218 p1 = repo.lookup('.')
4214 p2 = repo.lookup(node)
4219 p2 = repo.lookup(node)
4215 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4220 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4216
4221
4217 displayer = cmdutil.show_changeset(ui, repo, opts)
4222 displayer = cmdutil.show_changeset(ui, repo, opts)
4218 for node in nodes:
4223 for node in nodes:
4219 displayer.show(repo[node])
4224 displayer.show(repo[node])
4220 displayer.close()
4225 displayer.close()
4221 return 0
4226 return 0
4222
4227
4223 try:
4228 try:
4224 # ui.forcemerge is an internal variable, do not document
4229 # ui.forcemerge is an internal variable, do not document
4225 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4230 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4226 return hg.merge(repo, node, force=opts.get('force'))
4231 return hg.merge(repo, node, force=opts.get('force'))
4227 finally:
4232 finally:
4228 ui.setconfig('ui', 'forcemerge', '')
4233 ui.setconfig('ui', 'forcemerge', '')
4229
4234
4230 @command('outgoing|out',
4235 @command('outgoing|out',
4231 [('f', 'force', None, _('run even when the destination is unrelated')),
4236 [('f', 'force', None, _('run even when the destination is unrelated')),
4232 ('r', 'rev', [],
4237 ('r', 'rev', [],
4233 _('a changeset intended to be included in the destination'), _('REV')),
4238 _('a changeset intended to be included in the destination'), _('REV')),
4234 ('n', 'newest-first', None, _('show newest record first')),
4239 ('n', 'newest-first', None, _('show newest record first')),
4235 ('B', 'bookmarks', False, _('compare bookmarks')),
4240 ('B', 'bookmarks', False, _('compare bookmarks')),
4236 ('b', 'branch', [], _('a specific branch you would like to push'),
4241 ('b', 'branch', [], _('a specific branch you would like to push'),
4237 _('BRANCH')),
4242 _('BRANCH')),
4238 ] + logopts + remoteopts + subrepoopts,
4243 ] + logopts + remoteopts + subrepoopts,
4239 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4244 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4240 def outgoing(ui, repo, dest=None, **opts):
4245 def outgoing(ui, repo, dest=None, **opts):
4241 """show changesets not found in the destination
4246 """show changesets not found in the destination
4242
4247
4243 Show changesets not found in the specified destination repository
4248 Show changesets not found in the specified destination repository
4244 or the default push location. These are the changesets that would
4249 or the default push location. These are the changesets that would
4245 be pushed if a push was requested.
4250 be pushed if a push was requested.
4246
4251
4247 See pull for details of valid destination formats.
4252 See pull for details of valid destination formats.
4248
4253
4249 Returns 0 if there are outgoing changes, 1 otherwise.
4254 Returns 0 if there are outgoing changes, 1 otherwise.
4250 """
4255 """
4251 if opts.get('graph'):
4256 if opts.get('graph'):
4252 cmdutil.checkunsupportedgraphflags([], opts)
4257 cmdutil.checkunsupportedgraphflags([], opts)
4253 o = hg._outgoing(ui, repo, dest, opts)
4258 o = hg._outgoing(ui, repo, dest, opts)
4254 if o is None:
4259 if o is None:
4255 return
4260 return
4256
4261
4257 revdag = cmdutil.graphrevs(repo, o, opts)
4262 revdag = cmdutil.graphrevs(repo, o, opts)
4258 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4263 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4259 showparents = [ctx.node() for ctx in repo[None].parents()]
4264 showparents = [ctx.node() for ctx in repo[None].parents()]
4260 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4265 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4261 graphmod.asciiedges)
4266 graphmod.asciiedges)
4262 return 0
4267 return 0
4263
4268
4264 if opts.get('bookmarks'):
4269 if opts.get('bookmarks'):
4265 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4270 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4266 dest, branches = hg.parseurl(dest, opts.get('branch'))
4271 dest, branches = hg.parseurl(dest, opts.get('branch'))
4267 other = hg.peer(repo, opts, dest)
4272 other = hg.peer(repo, opts, dest)
4268 if 'bookmarks' not in other.listkeys('namespaces'):
4273 if 'bookmarks' not in other.listkeys('namespaces'):
4269 ui.warn(_("remote doesn't support bookmarks\n"))
4274 ui.warn(_("remote doesn't support bookmarks\n"))
4270 return 0
4275 return 0
4271 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4276 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4272 return bookmarks.diff(ui, other, repo)
4277 return bookmarks.diff(ui, other, repo)
4273
4278
4274 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4279 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4275 try:
4280 try:
4276 return hg.outgoing(ui, repo, dest, opts)
4281 return hg.outgoing(ui, repo, dest, opts)
4277 finally:
4282 finally:
4278 del repo._subtoppath
4283 del repo._subtoppath
4279
4284
4280 @command('parents',
4285 @command('parents',
4281 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4286 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4282 ] + templateopts,
4287 ] + templateopts,
4283 _('[-r REV] [FILE]'))
4288 _('[-r REV] [FILE]'))
4284 def parents(ui, repo, file_=None, **opts):
4289 def parents(ui, repo, file_=None, **opts):
4285 """show the parents of the working directory or revision
4290 """show the parents of the working directory or revision
4286
4291
4287 Print the working directory's parent revisions. If a revision is
4292 Print the working directory's parent revisions. If a revision is
4288 given via -r/--rev, the parent of that revision will be printed.
4293 given via -r/--rev, the parent of that revision will be printed.
4289 If a file argument is given, the revision in which the file was
4294 If a file argument is given, the revision in which the file was
4290 last changed (before the working directory revision or the
4295 last changed (before the working directory revision or the
4291 argument to --rev if given) is printed.
4296 argument to --rev if given) is printed.
4292
4297
4293 Returns 0 on success.
4298 Returns 0 on success.
4294 """
4299 """
4295
4300
4296 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4301 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4297
4302
4298 if file_:
4303 if file_:
4299 m = scmutil.match(ctx, (file_,), opts)
4304 m = scmutil.match(ctx, (file_,), opts)
4300 if m.anypats() or len(m.files()) != 1:
4305 if m.anypats() or len(m.files()) != 1:
4301 raise util.Abort(_('can only specify an explicit filename'))
4306 raise util.Abort(_('can only specify an explicit filename'))
4302 file_ = m.files()[0]
4307 file_ = m.files()[0]
4303 filenodes = []
4308 filenodes = []
4304 for cp in ctx.parents():
4309 for cp in ctx.parents():
4305 if not cp:
4310 if not cp:
4306 continue
4311 continue
4307 try:
4312 try:
4308 filenodes.append(cp.filenode(file_))
4313 filenodes.append(cp.filenode(file_))
4309 except error.LookupError:
4314 except error.LookupError:
4310 pass
4315 pass
4311 if not filenodes:
4316 if not filenodes:
4312 raise util.Abort(_("'%s' not found in manifest!") % file_)
4317 raise util.Abort(_("'%s' not found in manifest!") % file_)
4313 fl = repo.file(file_)
4318 fl = repo.file(file_)
4314 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4319 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4315 else:
4320 else:
4316 p = [cp.node() for cp in ctx.parents()]
4321 p = [cp.node() for cp in ctx.parents()]
4317
4322
4318 displayer = cmdutil.show_changeset(ui, repo, opts)
4323 displayer = cmdutil.show_changeset(ui, repo, opts)
4319 for n in p:
4324 for n in p:
4320 if n != nullid:
4325 if n != nullid:
4321 displayer.show(repo[n])
4326 displayer.show(repo[n])
4322 displayer.close()
4327 displayer.close()
4323
4328
4324 @command('paths', [], _('[NAME]'))
4329 @command('paths', [], _('[NAME]'))
4325 def paths(ui, repo, search=None):
4330 def paths(ui, repo, search=None):
4326 """show aliases for remote repositories
4331 """show aliases for remote repositories
4327
4332
4328 Show definition of symbolic path name NAME. If no name is given,
4333 Show definition of symbolic path name NAME. If no name is given,
4329 show definition of all available names.
4334 show definition of all available names.
4330
4335
4331 Option -q/--quiet suppresses all output when searching for NAME
4336 Option -q/--quiet suppresses all output when searching for NAME
4332 and shows only the path names when listing all definitions.
4337 and shows only the path names when listing all definitions.
4333
4338
4334 Path names are defined in the [paths] section of your
4339 Path names are defined in the [paths] section of your
4335 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4340 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4336 repository, ``.hg/hgrc`` is used, too.
4341 repository, ``.hg/hgrc`` is used, too.
4337
4342
4338 The path names ``default`` and ``default-push`` have a special
4343 The path names ``default`` and ``default-push`` have a special
4339 meaning. When performing a push or pull operation, they are used
4344 meaning. When performing a push or pull operation, they are used
4340 as fallbacks if no location is specified on the command-line.
4345 as fallbacks if no location is specified on the command-line.
4341 When ``default-push`` is set, it will be used for push and
4346 When ``default-push`` is set, it will be used for push and
4342 ``default`` will be used for pull; otherwise ``default`` is used
4347 ``default`` will be used for pull; otherwise ``default`` is used
4343 as the fallback for both. When cloning a repository, the clone
4348 as the fallback for both. When cloning a repository, the clone
4344 source is written as ``default`` in ``.hg/hgrc``. Note that
4349 source is written as ``default`` in ``.hg/hgrc``. Note that
4345 ``default`` and ``default-push`` apply to all inbound (e.g.
4350 ``default`` and ``default-push`` apply to all inbound (e.g.
4346 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4351 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4347 :hg:`bundle`) operations.
4352 :hg:`bundle`) operations.
4348
4353
4349 See :hg:`help urls` for more information.
4354 See :hg:`help urls` for more information.
4350
4355
4351 Returns 0 on success.
4356 Returns 0 on success.
4352 """
4357 """
4353 if search:
4358 if search:
4354 for name, path in ui.configitems("paths"):
4359 for name, path in ui.configitems("paths"):
4355 if name == search:
4360 if name == search:
4356 ui.status("%s\n" % util.hidepassword(path))
4361 ui.status("%s\n" % util.hidepassword(path))
4357 return
4362 return
4358 if not ui.quiet:
4363 if not ui.quiet:
4359 ui.warn(_("not found!\n"))
4364 ui.warn(_("not found!\n"))
4360 return 1
4365 return 1
4361 else:
4366 else:
4362 for name, path in ui.configitems("paths"):
4367 for name, path in ui.configitems("paths"):
4363 if ui.quiet:
4368 if ui.quiet:
4364 ui.write("%s\n" % name)
4369 ui.write("%s\n" % name)
4365 else:
4370 else:
4366 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4371 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4367
4372
4368 @command('phase',
4373 @command('phase',
4369 [('p', 'public', False, _('set changeset phase to public')),
4374 [('p', 'public', False, _('set changeset phase to public')),
4370 ('d', 'draft', False, _('set changeset phase to draft')),
4375 ('d', 'draft', False, _('set changeset phase to draft')),
4371 ('s', 'secret', False, _('set changeset phase to secret')),
4376 ('s', 'secret', False, _('set changeset phase to secret')),
4372 ('f', 'force', False, _('allow to move boundary backward')),
4377 ('f', 'force', False, _('allow to move boundary backward')),
4373 ('r', 'rev', [], _('target revision'), _('REV')),
4378 ('r', 'rev', [], _('target revision'), _('REV')),
4374 ],
4379 ],
4375 _('[-p|-d|-s] [-f] [-r] REV...'))
4380 _('[-p|-d|-s] [-f] [-r] REV...'))
4376 def phase(ui, repo, *revs, **opts):
4381 def phase(ui, repo, *revs, **opts):
4377 """set or show the current phase name
4382 """set or show the current phase name
4378
4383
4379 With no argument, show the phase name of specified revisions.
4384 With no argument, show the phase name of specified revisions.
4380
4385
4381 With one of -p/--public, -d/--draft or -s/--secret, change the
4386 With one of -p/--public, -d/--draft or -s/--secret, change the
4382 phase value of the specified revisions.
4387 phase value of the specified revisions.
4383
4388
4384 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4389 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4385 lower phase to an higher phase. Phases are ordered as follows::
4390 lower phase to an higher phase. Phases are ordered as follows::
4386
4391
4387 public < draft < secret
4392 public < draft < secret
4388
4393
4389 Return 0 on success, 1 if no phases were changed or some could not
4394 Return 0 on success, 1 if no phases were changed or some could not
4390 be changed.
4395 be changed.
4391 """
4396 """
4392 # search for a unique phase argument
4397 # search for a unique phase argument
4393 targetphase = None
4398 targetphase = None
4394 for idx, name in enumerate(phases.phasenames):
4399 for idx, name in enumerate(phases.phasenames):
4395 if opts[name]:
4400 if opts[name]:
4396 if targetphase is not None:
4401 if targetphase is not None:
4397 raise util.Abort(_('only one phase can be specified'))
4402 raise util.Abort(_('only one phase can be specified'))
4398 targetphase = idx
4403 targetphase = idx
4399
4404
4400 # look for specified revision
4405 # look for specified revision
4401 revs = list(revs)
4406 revs = list(revs)
4402 revs.extend(opts['rev'])
4407 revs.extend(opts['rev'])
4403 if not revs:
4408 if not revs:
4404 raise util.Abort(_('no revisions specified'))
4409 raise util.Abort(_('no revisions specified'))
4405
4410
4406 revs = scmutil.revrange(repo, revs)
4411 revs = scmutil.revrange(repo, revs)
4407
4412
4408 lock = None
4413 lock = None
4409 ret = 0
4414 ret = 0
4410 if targetphase is None:
4415 if targetphase is None:
4411 # display
4416 # display
4412 for r in revs:
4417 for r in revs:
4413 ctx = repo[r]
4418 ctx = repo[r]
4414 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4419 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4415 else:
4420 else:
4416 lock = repo.lock()
4421 lock = repo.lock()
4417 try:
4422 try:
4418 # set phase
4423 # set phase
4419 if not revs:
4424 if not revs:
4420 raise util.Abort(_('empty revision set'))
4425 raise util.Abort(_('empty revision set'))
4421 nodes = [repo[r].node() for r in revs]
4426 nodes = [repo[r].node() for r in revs]
4422 olddata = repo._phasecache.getphaserevs(repo)[:]
4427 olddata = repo._phasecache.getphaserevs(repo)[:]
4423 phases.advanceboundary(repo, targetphase, nodes)
4428 phases.advanceboundary(repo, targetphase, nodes)
4424 if opts['force']:
4429 if opts['force']:
4425 phases.retractboundary(repo, targetphase, nodes)
4430 phases.retractboundary(repo, targetphase, nodes)
4426 finally:
4431 finally:
4427 lock.release()
4432 lock.release()
4428 # moving revision from public to draft may hide them
4433 # moving revision from public to draft may hide them
4429 # We have to check result on an unfiltered repository
4434 # We have to check result on an unfiltered repository
4430 unfi = repo.unfiltered()
4435 unfi = repo.unfiltered()
4431 newdata = repo._phasecache.getphaserevs(unfi)
4436 newdata = repo._phasecache.getphaserevs(unfi)
4432 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4437 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4433 cl = unfi.changelog
4438 cl = unfi.changelog
4434 rejected = [n for n in nodes
4439 rejected = [n for n in nodes
4435 if newdata[cl.rev(n)] < targetphase]
4440 if newdata[cl.rev(n)] < targetphase]
4436 if rejected:
4441 if rejected:
4437 ui.warn(_('cannot move %i changesets to a more permissive '
4442 ui.warn(_('cannot move %i changesets to a more permissive '
4438 'phase, use --force\n') % len(rejected))
4443 'phase, use --force\n') % len(rejected))
4439 ret = 1
4444 ret = 1
4440 if changes:
4445 if changes:
4441 msg = _('phase changed for %i changesets\n') % changes
4446 msg = _('phase changed for %i changesets\n') % changes
4442 if ret:
4447 if ret:
4443 ui.status(msg)
4448 ui.status(msg)
4444 else:
4449 else:
4445 ui.note(msg)
4450 ui.note(msg)
4446 else:
4451 else:
4447 ui.warn(_('no phases changed\n'))
4452 ui.warn(_('no phases changed\n'))
4448 ret = 1
4453 ret = 1
4449 return ret
4454 return ret
4450
4455
4451 def postincoming(ui, repo, modheads, optupdate, checkout):
4456 def postincoming(ui, repo, modheads, optupdate, checkout):
4452 if modheads == 0:
4457 if modheads == 0:
4453 return
4458 return
4454 if optupdate:
4459 if optupdate:
4455 movemarkfrom = repo['.'].node()
4460 movemarkfrom = repo['.'].node()
4456 try:
4461 try:
4457 ret = hg.update(repo, checkout)
4462 ret = hg.update(repo, checkout)
4458 except util.Abort, inst:
4463 except util.Abort, inst:
4459 ui.warn(_("not updating: %s\n") % str(inst))
4464 ui.warn(_("not updating: %s\n") % str(inst))
4460 return 0
4465 return 0
4461 if not ret and not checkout:
4466 if not ret and not checkout:
4462 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4467 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4463 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4468 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4464 return ret
4469 return ret
4465 if modheads > 1:
4470 if modheads > 1:
4466 currentbranchheads = len(repo.branchheads())
4471 currentbranchheads = len(repo.branchheads())
4467 if currentbranchheads == modheads:
4472 if currentbranchheads == modheads:
4468 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4473 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4469 elif currentbranchheads > 1:
4474 elif currentbranchheads > 1:
4470 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4475 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4471 "merge)\n"))
4476 "merge)\n"))
4472 else:
4477 else:
4473 ui.status(_("(run 'hg heads' to see heads)\n"))
4478 ui.status(_("(run 'hg heads' to see heads)\n"))
4474 else:
4479 else:
4475 ui.status(_("(run 'hg update' to get a working copy)\n"))
4480 ui.status(_("(run 'hg update' to get a working copy)\n"))
4476
4481
4477 @command('^pull',
4482 @command('^pull',
4478 [('u', 'update', None,
4483 [('u', 'update', None,
4479 _('update to new branch head if changesets were pulled')),
4484 _('update to new branch head if changesets were pulled')),
4480 ('f', 'force', None, _('run even when remote repository is unrelated')),
4485 ('f', 'force', None, _('run even when remote repository is unrelated')),
4481 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4486 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4482 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4487 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4483 ('b', 'branch', [], _('a specific branch you would like to pull'),
4488 ('b', 'branch', [], _('a specific branch you would like to pull'),
4484 _('BRANCH')),
4489 _('BRANCH')),
4485 ] + remoteopts,
4490 ] + remoteopts,
4486 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4491 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4487 def pull(ui, repo, source="default", **opts):
4492 def pull(ui, repo, source="default", **opts):
4488 """pull changes from the specified source
4493 """pull changes from the specified source
4489
4494
4490 Pull changes from a remote repository to a local one.
4495 Pull changes from a remote repository to a local one.
4491
4496
4492 This finds all changes from the repository at the specified path
4497 This finds all changes from the repository at the specified path
4493 or URL and adds them to a local repository (the current one unless
4498 or URL and adds them to a local repository (the current one unless
4494 -R is specified). By default, this does not update the copy of the
4499 -R is specified). By default, this does not update the copy of the
4495 project in the working directory.
4500 project in the working directory.
4496
4501
4497 Use :hg:`incoming` if you want to see what would have been added
4502 Use :hg:`incoming` if you want to see what would have been added
4498 by a pull at the time you issued this command. If you then decide
4503 by a pull at the time you issued this command. If you then decide
4499 to add those changes to the repository, you should use :hg:`pull
4504 to add those changes to the repository, you should use :hg:`pull
4500 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4505 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4501
4506
4502 If SOURCE is omitted, the 'default' path will be used.
4507 If SOURCE is omitted, the 'default' path will be used.
4503 See :hg:`help urls` for more information.
4508 See :hg:`help urls` for more information.
4504
4509
4505 Returns 0 on success, 1 if an update had unresolved files.
4510 Returns 0 on success, 1 if an update had unresolved files.
4506 """
4511 """
4507 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4512 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4508 other = hg.peer(repo, opts, source)
4513 other = hg.peer(repo, opts, source)
4509 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4514 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4510 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4515 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4511
4516
4512 remotebookmarks = other.listkeys('bookmarks')
4517 remotebookmarks = other.listkeys('bookmarks')
4513
4518
4514 if opts.get('bookmark'):
4519 if opts.get('bookmark'):
4515 if not revs:
4520 if not revs:
4516 revs = []
4521 revs = []
4517 for b in opts['bookmark']:
4522 for b in opts['bookmark']:
4518 if b not in remotebookmarks:
4523 if b not in remotebookmarks:
4519 raise util.Abort(_('remote bookmark %s not found!') % b)
4524 raise util.Abort(_('remote bookmark %s not found!') % b)
4520 revs.append(remotebookmarks[b])
4525 revs.append(remotebookmarks[b])
4521
4526
4522 if revs:
4527 if revs:
4523 try:
4528 try:
4524 revs = [other.lookup(rev) for rev in revs]
4529 revs = [other.lookup(rev) for rev in revs]
4525 except error.CapabilityError:
4530 except error.CapabilityError:
4526 err = _("other repository doesn't support revision lookup, "
4531 err = _("other repository doesn't support revision lookup, "
4527 "so a rev cannot be specified.")
4532 "so a rev cannot be specified.")
4528 raise util.Abort(err)
4533 raise util.Abort(err)
4529
4534
4530 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4535 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4531 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4536 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4532 if checkout:
4537 if checkout:
4533 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4538 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4534 repo._subtoppath = source
4539 repo._subtoppath = source
4535 try:
4540 try:
4536 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4541 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4537
4542
4538 finally:
4543 finally:
4539 del repo._subtoppath
4544 del repo._subtoppath
4540
4545
4541 # update specified bookmarks
4546 # update specified bookmarks
4542 if opts.get('bookmark'):
4547 if opts.get('bookmark'):
4543 marks = repo._bookmarks
4548 marks = repo._bookmarks
4544 for b in opts['bookmark']:
4549 for b in opts['bookmark']:
4545 # explicit pull overrides local bookmark if any
4550 # explicit pull overrides local bookmark if any
4546 ui.status(_("importing bookmark %s\n") % b)
4551 ui.status(_("importing bookmark %s\n") % b)
4547 marks[b] = repo[remotebookmarks[b]].node()
4552 marks[b] = repo[remotebookmarks[b]].node()
4548 marks.write()
4553 marks.write()
4549
4554
4550 return ret
4555 return ret
4551
4556
4552 @command('^push',
4557 @command('^push',
4553 [('f', 'force', None, _('force push')),
4558 [('f', 'force', None, _('force push')),
4554 ('r', 'rev', [],
4559 ('r', 'rev', [],
4555 _('a changeset intended to be included in the destination'),
4560 _('a changeset intended to be included in the destination'),
4556 _('REV')),
4561 _('REV')),
4557 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4562 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4558 ('b', 'branch', [],
4563 ('b', 'branch', [],
4559 _('a specific branch you would like to push'), _('BRANCH')),
4564 _('a specific branch you would like to push'), _('BRANCH')),
4560 ('', 'new-branch', False, _('allow pushing a new branch')),
4565 ('', 'new-branch', False, _('allow pushing a new branch')),
4561 ] + remoteopts,
4566 ] + remoteopts,
4562 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4567 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4563 def push(ui, repo, dest=None, **opts):
4568 def push(ui, repo, dest=None, **opts):
4564 """push changes to the specified destination
4569 """push changes to the specified destination
4565
4570
4566 Push changesets from the local repository to the specified
4571 Push changesets from the local repository to the specified
4567 destination.
4572 destination.
4568
4573
4569 This operation is symmetrical to pull: it is identical to a pull
4574 This operation is symmetrical to pull: it is identical to a pull
4570 in the destination repository from the current one.
4575 in the destination repository from the current one.
4571
4576
4572 By default, push will not allow creation of new heads at the
4577 By default, push will not allow creation of new heads at the
4573 destination, since multiple heads would make it unclear which head
4578 destination, since multiple heads would make it unclear which head
4574 to use. In this situation, it is recommended to pull and merge
4579 to use. In this situation, it is recommended to pull and merge
4575 before pushing.
4580 before pushing.
4576
4581
4577 Use --new-branch if you want to allow push to create a new named
4582 Use --new-branch if you want to allow push to create a new named
4578 branch that is not present at the destination. This allows you to
4583 branch that is not present at the destination. This allows you to
4579 only create a new branch without forcing other changes.
4584 only create a new branch without forcing other changes.
4580
4585
4581 Use -f/--force to override the default behavior and push all
4586 Use -f/--force to override the default behavior and push all
4582 changesets on all branches.
4587 changesets on all branches.
4583
4588
4584 If -r/--rev is used, the specified revision and all its ancestors
4589 If -r/--rev is used, the specified revision and all its ancestors
4585 will be pushed to the remote repository.
4590 will be pushed to the remote repository.
4586
4591
4587 If -B/--bookmark is used, the specified bookmarked revision, its
4592 If -B/--bookmark is used, the specified bookmarked revision, its
4588 ancestors, and the bookmark will be pushed to the remote
4593 ancestors, and the bookmark will be pushed to the remote
4589 repository.
4594 repository.
4590
4595
4591 Please see :hg:`help urls` for important details about ``ssh://``
4596 Please see :hg:`help urls` for important details about ``ssh://``
4592 URLs. If DESTINATION is omitted, a default path will be used.
4597 URLs. If DESTINATION is omitted, a default path will be used.
4593
4598
4594 Returns 0 if push was successful, 1 if nothing to push.
4599 Returns 0 if push was successful, 1 if nothing to push.
4595 """
4600 """
4596
4601
4597 if opts.get('bookmark'):
4602 if opts.get('bookmark'):
4598 for b in opts['bookmark']:
4603 for b in opts['bookmark']:
4599 # translate -B options to -r so changesets get pushed
4604 # translate -B options to -r so changesets get pushed
4600 if b in repo._bookmarks:
4605 if b in repo._bookmarks:
4601 opts.setdefault('rev', []).append(b)
4606 opts.setdefault('rev', []).append(b)
4602 else:
4607 else:
4603 # if we try to push a deleted bookmark, translate it to null
4608 # if we try to push a deleted bookmark, translate it to null
4604 # this lets simultaneous -r, -b options continue working
4609 # this lets simultaneous -r, -b options continue working
4605 opts.setdefault('rev', []).append("null")
4610 opts.setdefault('rev', []).append("null")
4606
4611
4607 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4612 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4608 dest, branches = hg.parseurl(dest, opts.get('branch'))
4613 dest, branches = hg.parseurl(dest, opts.get('branch'))
4609 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4614 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4610 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4615 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4611 other = hg.peer(repo, opts, dest)
4616 other = hg.peer(repo, opts, dest)
4612 if revs:
4617 if revs:
4613 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4618 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4614
4619
4615 repo._subtoppath = dest
4620 repo._subtoppath = dest
4616 try:
4621 try:
4617 # push subrepos depth-first for coherent ordering
4622 # push subrepos depth-first for coherent ordering
4618 c = repo['']
4623 c = repo['']
4619 subs = c.substate # only repos that are committed
4624 subs = c.substate # only repos that are committed
4620 for s in sorted(subs):
4625 for s in sorted(subs):
4621 if c.sub(s).push(opts) == 0:
4626 if c.sub(s).push(opts) == 0:
4622 return False
4627 return False
4623 finally:
4628 finally:
4624 del repo._subtoppath
4629 del repo._subtoppath
4625 result = repo.push(other, opts.get('force'), revs=revs,
4630 result = repo.push(other, opts.get('force'), revs=revs,
4626 newbranch=opts.get('new_branch'))
4631 newbranch=opts.get('new_branch'))
4627
4632
4628 result = not result
4633 result = not result
4629
4634
4630 if opts.get('bookmark'):
4635 if opts.get('bookmark'):
4631 rb = other.listkeys('bookmarks')
4636 rb = other.listkeys('bookmarks')
4632 for b in opts['bookmark']:
4637 for b in opts['bookmark']:
4633 # explicit push overrides remote bookmark if any
4638 # explicit push overrides remote bookmark if any
4634 if b in repo._bookmarks:
4639 if b in repo._bookmarks:
4635 ui.status(_("exporting bookmark %s\n") % b)
4640 ui.status(_("exporting bookmark %s\n") % b)
4636 new = repo[b].hex()
4641 new = repo[b].hex()
4637 elif b in rb:
4642 elif b in rb:
4638 ui.status(_("deleting remote bookmark %s\n") % b)
4643 ui.status(_("deleting remote bookmark %s\n") % b)
4639 new = '' # delete
4644 new = '' # delete
4640 else:
4645 else:
4641 ui.warn(_('bookmark %s does not exist on the local '
4646 ui.warn(_('bookmark %s does not exist on the local '
4642 'or remote repository!\n') % b)
4647 'or remote repository!\n') % b)
4643 return 2
4648 return 2
4644 old = rb.get(b, '')
4649 old = rb.get(b, '')
4645 r = other.pushkey('bookmarks', b, old, new)
4650 r = other.pushkey('bookmarks', b, old, new)
4646 if not r:
4651 if not r:
4647 ui.warn(_('updating bookmark %s failed!\n') % b)
4652 ui.warn(_('updating bookmark %s failed!\n') % b)
4648 if not result:
4653 if not result:
4649 result = 2
4654 result = 2
4650
4655
4651 return result
4656 return result
4652
4657
4653 @command('recover', [])
4658 @command('recover', [])
4654 def recover(ui, repo):
4659 def recover(ui, repo):
4655 """roll back an interrupted transaction
4660 """roll back an interrupted transaction
4656
4661
4657 Recover from an interrupted commit or pull.
4662 Recover from an interrupted commit or pull.
4658
4663
4659 This command tries to fix the repository status after an
4664 This command tries to fix the repository status after an
4660 interrupted operation. It should only be necessary when Mercurial
4665 interrupted operation. It should only be necessary when Mercurial
4661 suggests it.
4666 suggests it.
4662
4667
4663 Returns 0 if successful, 1 if nothing to recover or verify fails.
4668 Returns 0 if successful, 1 if nothing to recover or verify fails.
4664 """
4669 """
4665 if repo.recover():
4670 if repo.recover():
4666 return hg.verify(repo)
4671 return hg.verify(repo)
4667 return 1
4672 return 1
4668
4673
4669 @command('^remove|rm',
4674 @command('^remove|rm',
4670 [('A', 'after', None, _('record delete for missing files')),
4675 [('A', 'after', None, _('record delete for missing files')),
4671 ('f', 'force', None,
4676 ('f', 'force', None,
4672 _('remove (and delete) file even if added or modified')),
4677 _('remove (and delete) file even if added or modified')),
4673 ] + walkopts,
4678 ] + walkopts,
4674 _('[OPTION]... FILE...'))
4679 _('[OPTION]... FILE...'))
4675 def remove(ui, repo, *pats, **opts):
4680 def remove(ui, repo, *pats, **opts):
4676 """remove the specified files on the next commit
4681 """remove the specified files on the next commit
4677
4682
4678 Schedule the indicated files for removal from the current branch.
4683 Schedule the indicated files for removal from the current branch.
4679
4684
4680 This command schedules the files to be removed at the next commit.
4685 This command schedules the files to be removed at the next commit.
4681 To undo a remove before that, see :hg:`revert`. To undo added
4686 To undo a remove before that, see :hg:`revert`. To undo added
4682 files, see :hg:`forget`.
4687 files, see :hg:`forget`.
4683
4688
4684 .. container:: verbose
4689 .. container:: verbose
4685
4690
4686 -A/--after can be used to remove only files that have already
4691 -A/--after can be used to remove only files that have already
4687 been deleted, -f/--force can be used to force deletion, and -Af
4692 been deleted, -f/--force can be used to force deletion, and -Af
4688 can be used to remove files from the next revision without
4693 can be used to remove files from the next revision without
4689 deleting them from the working directory.
4694 deleting them from the working directory.
4690
4695
4691 The following table details the behavior of remove for different
4696 The following table details the behavior of remove for different
4692 file states (columns) and option combinations (rows). The file
4697 file states (columns) and option combinations (rows). The file
4693 states are Added [A], Clean [C], Modified [M] and Missing [!]
4698 states are Added [A], Clean [C], Modified [M] and Missing [!]
4694 (as reported by :hg:`status`). The actions are Warn, Remove
4699 (as reported by :hg:`status`). The actions are Warn, Remove
4695 (from branch) and Delete (from disk):
4700 (from branch) and Delete (from disk):
4696
4701
4697 ======= == == == ==
4702 ======= == == == ==
4698 A C M !
4703 A C M !
4699 ======= == == == ==
4704 ======= == == == ==
4700 none W RD W R
4705 none W RD W R
4701 -f R RD RD R
4706 -f R RD RD R
4702 -A W W W R
4707 -A W W W R
4703 -Af R R R R
4708 -Af R R R R
4704 ======= == == == ==
4709 ======= == == == ==
4705
4710
4706 Note that remove never deletes files in Added [A] state from the
4711 Note that remove never deletes files in Added [A] state from the
4707 working directory, not even if option --force is specified.
4712 working directory, not even if option --force is specified.
4708
4713
4709 Returns 0 on success, 1 if any warnings encountered.
4714 Returns 0 on success, 1 if any warnings encountered.
4710 """
4715 """
4711
4716
4712 ret = 0
4717 ret = 0
4713 after, force = opts.get('after'), opts.get('force')
4718 after, force = opts.get('after'), opts.get('force')
4714 if not pats and not after:
4719 if not pats and not after:
4715 raise util.Abort(_('no files specified'))
4720 raise util.Abort(_('no files specified'))
4716
4721
4717 m = scmutil.match(repo[None], pats, opts)
4722 m = scmutil.match(repo[None], pats, opts)
4718 s = repo.status(match=m, clean=True)
4723 s = repo.status(match=m, clean=True)
4719 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4724 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4720
4725
4721 # warn about failure to delete explicit files/dirs
4726 # warn about failure to delete explicit files/dirs
4722 wctx = repo[None]
4727 wctx = repo[None]
4723 for f in m.files():
4728 for f in m.files():
4724 if f in repo.dirstate or f in wctx.dirs():
4729 if f in repo.dirstate or f in wctx.dirs():
4725 continue
4730 continue
4726 if os.path.exists(m.rel(f)):
4731 if os.path.exists(m.rel(f)):
4727 if os.path.isdir(m.rel(f)):
4732 if os.path.isdir(m.rel(f)):
4728 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4733 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4729 else:
4734 else:
4730 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4735 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4731 # missing files will generate a warning elsewhere
4736 # missing files will generate a warning elsewhere
4732 ret = 1
4737 ret = 1
4733
4738
4734 if force:
4739 if force:
4735 list = modified + deleted + clean + added
4740 list = modified + deleted + clean + added
4736 elif after:
4741 elif after:
4737 list = deleted
4742 list = deleted
4738 for f in modified + added + clean:
4743 for f in modified + added + clean:
4739 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4744 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4740 ret = 1
4745 ret = 1
4741 else:
4746 else:
4742 list = deleted + clean
4747 list = deleted + clean
4743 for f in modified:
4748 for f in modified:
4744 ui.warn(_('not removing %s: file is modified (use -f'
4749 ui.warn(_('not removing %s: file is modified (use -f'
4745 ' to force removal)\n') % m.rel(f))
4750 ' to force removal)\n') % m.rel(f))
4746 ret = 1
4751 ret = 1
4747 for f in added:
4752 for f in added:
4748 ui.warn(_('not removing %s: file has been marked for add'
4753 ui.warn(_('not removing %s: file has been marked for add'
4749 ' (use forget to undo)\n') % m.rel(f))
4754 ' (use forget to undo)\n') % m.rel(f))
4750 ret = 1
4755 ret = 1
4751
4756
4752 for f in sorted(list):
4757 for f in sorted(list):
4753 if ui.verbose or not m.exact(f):
4758 if ui.verbose or not m.exact(f):
4754 ui.status(_('removing %s\n') % m.rel(f))
4759 ui.status(_('removing %s\n') % m.rel(f))
4755
4760
4756 wlock = repo.wlock()
4761 wlock = repo.wlock()
4757 try:
4762 try:
4758 if not after:
4763 if not after:
4759 for f in list:
4764 for f in list:
4760 if f in added:
4765 if f in added:
4761 continue # we never unlink added files on remove
4766 continue # we never unlink added files on remove
4762 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4767 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4763 repo[None].forget(list)
4768 repo[None].forget(list)
4764 finally:
4769 finally:
4765 wlock.release()
4770 wlock.release()
4766
4771
4767 return ret
4772 return ret
4768
4773
4769 @command('rename|move|mv',
4774 @command('rename|move|mv',
4770 [('A', 'after', None, _('record a rename that has already occurred')),
4775 [('A', 'after', None, _('record a rename that has already occurred')),
4771 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4776 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4772 ] + walkopts + dryrunopts,
4777 ] + walkopts + dryrunopts,
4773 _('[OPTION]... SOURCE... DEST'))
4778 _('[OPTION]... SOURCE... DEST'))
4774 def rename(ui, repo, *pats, **opts):
4779 def rename(ui, repo, *pats, **opts):
4775 """rename files; equivalent of copy + remove
4780 """rename files; equivalent of copy + remove
4776
4781
4777 Mark dest as copies of sources; mark sources for deletion. If dest
4782 Mark dest as copies of sources; mark sources for deletion. If dest
4778 is a directory, copies are put in that directory. If dest is a
4783 is a directory, copies are put in that directory. If dest is a
4779 file, there can only be one source.
4784 file, there can only be one source.
4780
4785
4781 By default, this command copies the contents of files as they
4786 By default, this command copies the contents of files as they
4782 exist in the working directory. If invoked with -A/--after, the
4787 exist in the working directory. If invoked with -A/--after, the
4783 operation is recorded, but no copying is performed.
4788 operation is recorded, but no copying is performed.
4784
4789
4785 This command takes effect at the next commit. To undo a rename
4790 This command takes effect at the next commit. To undo a rename
4786 before that, see :hg:`revert`.
4791 before that, see :hg:`revert`.
4787
4792
4788 Returns 0 on success, 1 if errors are encountered.
4793 Returns 0 on success, 1 if errors are encountered.
4789 """
4794 """
4790 wlock = repo.wlock(False)
4795 wlock = repo.wlock(False)
4791 try:
4796 try:
4792 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4797 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4793 finally:
4798 finally:
4794 wlock.release()
4799 wlock.release()
4795
4800
4796 @command('resolve',
4801 @command('resolve',
4797 [('a', 'all', None, _('select all unresolved files')),
4802 [('a', 'all', None, _('select all unresolved files')),
4798 ('l', 'list', None, _('list state of files needing merge')),
4803 ('l', 'list', None, _('list state of files needing merge')),
4799 ('m', 'mark', None, _('mark files as resolved')),
4804 ('m', 'mark', None, _('mark files as resolved')),
4800 ('u', 'unmark', None, _('mark files as unresolved')),
4805 ('u', 'unmark', None, _('mark files as unresolved')),
4801 ('n', 'no-status', None, _('hide status prefix'))]
4806 ('n', 'no-status', None, _('hide status prefix'))]
4802 + mergetoolopts + walkopts,
4807 + mergetoolopts + walkopts,
4803 _('[OPTION]... [FILE]...'))
4808 _('[OPTION]... [FILE]...'))
4804 def resolve(ui, repo, *pats, **opts):
4809 def resolve(ui, repo, *pats, **opts):
4805 """redo merges or set/view the merge status of files
4810 """redo merges or set/view the merge status of files
4806
4811
4807 Merges with unresolved conflicts are often the result of
4812 Merges with unresolved conflicts are often the result of
4808 non-interactive merging using the ``internal:merge`` configuration
4813 non-interactive merging using the ``internal:merge`` configuration
4809 setting, or a command-line merge tool like ``diff3``. The resolve
4814 setting, or a command-line merge tool like ``diff3``. The resolve
4810 command is used to manage the files involved in a merge, after
4815 command is used to manage the files involved in a merge, after
4811 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4816 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4812 working directory must have two parents). See :hg:`help
4817 working directory must have two parents). See :hg:`help
4813 merge-tools` for information on configuring merge tools.
4818 merge-tools` for information on configuring merge tools.
4814
4819
4815 The resolve command can be used in the following ways:
4820 The resolve command can be used in the following ways:
4816
4821
4817 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4822 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4818 files, discarding any previous merge attempts. Re-merging is not
4823 files, discarding any previous merge attempts. Re-merging is not
4819 performed for files already marked as resolved. Use ``--all/-a``
4824 performed for files already marked as resolved. Use ``--all/-a``
4820 to select all unresolved files. ``--tool`` can be used to specify
4825 to select all unresolved files. ``--tool`` can be used to specify
4821 the merge tool used for the given files. It overrides the HGMERGE
4826 the merge tool used for the given files. It overrides the HGMERGE
4822 environment variable and your configuration files. Previous file
4827 environment variable and your configuration files. Previous file
4823 contents are saved with a ``.orig`` suffix.
4828 contents are saved with a ``.orig`` suffix.
4824
4829
4825 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4830 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4826 (e.g. after having manually fixed-up the files). The default is
4831 (e.g. after having manually fixed-up the files). The default is
4827 to mark all unresolved files.
4832 to mark all unresolved files.
4828
4833
4829 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4834 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4830 default is to mark all resolved files.
4835 default is to mark all resolved files.
4831
4836
4832 - :hg:`resolve -l`: list files which had or still have conflicts.
4837 - :hg:`resolve -l`: list files which had or still have conflicts.
4833 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4838 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4834
4839
4835 Note that Mercurial will not let you commit files with unresolved
4840 Note that Mercurial will not let you commit files with unresolved
4836 merge conflicts. You must use :hg:`resolve -m ...` before you can
4841 merge conflicts. You must use :hg:`resolve -m ...` before you can
4837 commit after a conflicting merge.
4842 commit after a conflicting merge.
4838
4843
4839 Returns 0 on success, 1 if any files fail a resolve attempt.
4844 Returns 0 on success, 1 if any files fail a resolve attempt.
4840 """
4845 """
4841
4846
4842 all, mark, unmark, show, nostatus = \
4847 all, mark, unmark, show, nostatus = \
4843 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4848 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4844
4849
4845 if (show and (mark or unmark)) or (mark and unmark):
4850 if (show and (mark or unmark)) or (mark and unmark):
4846 raise util.Abort(_("too many options specified"))
4851 raise util.Abort(_("too many options specified"))
4847 if pats and all:
4852 if pats and all:
4848 raise util.Abort(_("can't specify --all and patterns"))
4853 raise util.Abort(_("can't specify --all and patterns"))
4849 if not (all or pats or show or mark or unmark):
4854 if not (all or pats or show or mark or unmark):
4850 raise util.Abort(_('no files or directories specified; '
4855 raise util.Abort(_('no files or directories specified; '
4851 'use --all to remerge all files'))
4856 'use --all to remerge all files'))
4852
4857
4853 ms = mergemod.mergestate(repo)
4858 ms = mergemod.mergestate(repo)
4854 m = scmutil.match(repo[None], pats, opts)
4859 m = scmutil.match(repo[None], pats, opts)
4855 ret = 0
4860 ret = 0
4856
4861
4857 for f in ms:
4862 for f in ms:
4858 if m(f):
4863 if m(f):
4859 if show:
4864 if show:
4860 if nostatus:
4865 if nostatus:
4861 ui.write("%s\n" % f)
4866 ui.write("%s\n" % f)
4862 else:
4867 else:
4863 ui.write("%s %s\n" % (ms[f].upper(), f),
4868 ui.write("%s %s\n" % (ms[f].upper(), f),
4864 label='resolve.' +
4869 label='resolve.' +
4865 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4870 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4866 elif mark:
4871 elif mark:
4867 ms.mark(f, "r")
4872 ms.mark(f, "r")
4868 elif unmark:
4873 elif unmark:
4869 ms.mark(f, "u")
4874 ms.mark(f, "u")
4870 else:
4875 else:
4871 wctx = repo[None]
4876 wctx = repo[None]
4872 mctx = wctx.parents()[-1]
4877 mctx = wctx.parents()[-1]
4873
4878
4874 # backup pre-resolve (merge uses .orig for its own purposes)
4879 # backup pre-resolve (merge uses .orig for its own purposes)
4875 a = repo.wjoin(f)
4880 a = repo.wjoin(f)
4876 util.copyfile(a, a + ".resolve")
4881 util.copyfile(a, a + ".resolve")
4877
4882
4878 try:
4883 try:
4879 # resolve file
4884 # resolve file
4880 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4885 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4881 if ms.resolve(f, wctx, mctx):
4886 if ms.resolve(f, wctx, mctx):
4882 ret = 1
4887 ret = 1
4883 finally:
4888 finally:
4884 ui.setconfig('ui', 'forcemerge', '')
4889 ui.setconfig('ui', 'forcemerge', '')
4885 ms.commit()
4890 ms.commit()
4886
4891
4887 # replace filemerge's .orig file with our resolve file
4892 # replace filemerge's .orig file with our resolve file
4888 util.rename(a + ".resolve", a + ".orig")
4893 util.rename(a + ".resolve", a + ".orig")
4889
4894
4890 ms.commit()
4895 ms.commit()
4891 return ret
4896 return ret
4892
4897
4893 @command('revert',
4898 @command('revert',
4894 [('a', 'all', None, _('revert all changes when no arguments given')),
4899 [('a', 'all', None, _('revert all changes when no arguments given')),
4895 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4900 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4896 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4901 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4897 ('C', 'no-backup', None, _('do not save backup copies of files')),
4902 ('C', 'no-backup', None, _('do not save backup copies of files')),
4898 ] + walkopts + dryrunopts,
4903 ] + walkopts + dryrunopts,
4899 _('[OPTION]... [-r REV] [NAME]...'))
4904 _('[OPTION]... [-r REV] [NAME]...'))
4900 def revert(ui, repo, *pats, **opts):
4905 def revert(ui, repo, *pats, **opts):
4901 """restore files to their checkout state
4906 """restore files to their checkout state
4902
4907
4903 .. note::
4908 .. note::
4904
4909
4905 To check out earlier revisions, you should use :hg:`update REV`.
4910 To check out earlier revisions, you should use :hg:`update REV`.
4906 To cancel an uncommitted merge (and lose your changes), use
4911 To cancel an uncommitted merge (and lose your changes), use
4907 :hg:`update --clean .`.
4912 :hg:`update --clean .`.
4908
4913
4909 With no revision specified, revert the specified files or directories
4914 With no revision specified, revert the specified files or directories
4910 to the contents they had in the parent of the working directory.
4915 to the contents they had in the parent of the working directory.
4911 This restores the contents of files to an unmodified
4916 This restores the contents of files to an unmodified
4912 state and unschedules adds, removes, copies, and renames. If the
4917 state and unschedules adds, removes, copies, and renames. If the
4913 working directory has two parents, you must explicitly specify a
4918 working directory has two parents, you must explicitly specify a
4914 revision.
4919 revision.
4915
4920
4916 Using the -r/--rev or -d/--date options, revert the given files or
4921 Using the -r/--rev or -d/--date options, revert the given files or
4917 directories to their states as of a specific revision. Because
4922 directories to their states as of a specific revision. Because
4918 revert does not change the working directory parents, this will
4923 revert does not change the working directory parents, this will
4919 cause these files to appear modified. This can be helpful to "back
4924 cause these files to appear modified. This can be helpful to "back
4920 out" some or all of an earlier change. See :hg:`backout` for a
4925 out" some or all of an earlier change. See :hg:`backout` for a
4921 related method.
4926 related method.
4922
4927
4923 Modified files are saved with a .orig suffix before reverting.
4928 Modified files are saved with a .orig suffix before reverting.
4924 To disable these backups, use --no-backup.
4929 To disable these backups, use --no-backup.
4925
4930
4926 See :hg:`help dates` for a list of formats valid for -d/--date.
4931 See :hg:`help dates` for a list of formats valid for -d/--date.
4927
4932
4928 Returns 0 on success.
4933 Returns 0 on success.
4929 """
4934 """
4930
4935
4931 if opts.get("date"):
4936 if opts.get("date"):
4932 if opts.get("rev"):
4937 if opts.get("rev"):
4933 raise util.Abort(_("you can't specify a revision and a date"))
4938 raise util.Abort(_("you can't specify a revision and a date"))
4934 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4939 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4935
4940
4936 parent, p2 = repo.dirstate.parents()
4941 parent, p2 = repo.dirstate.parents()
4937 if not opts.get('rev') and p2 != nullid:
4942 if not opts.get('rev') and p2 != nullid:
4938 # revert after merge is a trap for new users (issue2915)
4943 # revert after merge is a trap for new users (issue2915)
4939 raise util.Abort(_('uncommitted merge with no revision specified'),
4944 raise util.Abort(_('uncommitted merge with no revision specified'),
4940 hint=_('use "hg update" or see "hg help revert"'))
4945 hint=_('use "hg update" or see "hg help revert"'))
4941
4946
4942 ctx = scmutil.revsingle(repo, opts.get('rev'))
4947 ctx = scmutil.revsingle(repo, opts.get('rev'))
4943
4948
4944 if not pats and not opts.get('all'):
4949 if not pats and not opts.get('all'):
4945 msg = _("no files or directories specified")
4950 msg = _("no files or directories specified")
4946 if p2 != nullid:
4951 if p2 != nullid:
4947 hint = _("uncommitted merge, use --all to discard all changes,"
4952 hint = _("uncommitted merge, use --all to discard all changes,"
4948 " or 'hg update -C .' to abort the merge")
4953 " or 'hg update -C .' to abort the merge")
4949 raise util.Abort(msg, hint=hint)
4954 raise util.Abort(msg, hint=hint)
4950 dirty = util.any(repo.status())
4955 dirty = util.any(repo.status())
4951 node = ctx.node()
4956 node = ctx.node()
4952 if node != parent:
4957 if node != parent:
4953 if dirty:
4958 if dirty:
4954 hint = _("uncommitted changes, use --all to discard all"
4959 hint = _("uncommitted changes, use --all to discard all"
4955 " changes, or 'hg update %s' to update") % ctx.rev()
4960 " changes, or 'hg update %s' to update") % ctx.rev()
4956 else:
4961 else:
4957 hint = _("use --all to revert all files,"
4962 hint = _("use --all to revert all files,"
4958 " or 'hg update %s' to update") % ctx.rev()
4963 " or 'hg update %s' to update") % ctx.rev()
4959 elif dirty:
4964 elif dirty:
4960 hint = _("uncommitted changes, use --all to discard all changes")
4965 hint = _("uncommitted changes, use --all to discard all changes")
4961 else:
4966 else:
4962 hint = _("use --all to revert all files")
4967 hint = _("use --all to revert all files")
4963 raise util.Abort(msg, hint=hint)
4968 raise util.Abort(msg, hint=hint)
4964
4969
4965 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4970 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4966
4971
4967 @command('rollback', dryrunopts +
4972 @command('rollback', dryrunopts +
4968 [('f', 'force', False, _('ignore safety measures'))])
4973 [('f', 'force', False, _('ignore safety measures'))])
4969 def rollback(ui, repo, **opts):
4974 def rollback(ui, repo, **opts):
4970 """roll back the last transaction (dangerous)
4975 """roll back the last transaction (dangerous)
4971
4976
4972 This command should be used with care. There is only one level of
4977 This command should be used with care. There is only one level of
4973 rollback, and there is no way to undo a rollback. It will also
4978 rollback, and there is no way to undo a rollback. It will also
4974 restore the dirstate at the time of the last transaction, losing
4979 restore the dirstate at the time of the last transaction, losing
4975 any dirstate changes since that time. This command does not alter
4980 any dirstate changes since that time. This command does not alter
4976 the working directory.
4981 the working directory.
4977
4982
4978 Transactions are used to encapsulate the effects of all commands
4983 Transactions are used to encapsulate the effects of all commands
4979 that create new changesets or propagate existing changesets into a
4984 that create new changesets or propagate existing changesets into a
4980 repository.
4985 repository.
4981
4986
4982 .. container:: verbose
4987 .. container:: verbose
4983
4988
4984 For example, the following commands are transactional, and their
4989 For example, the following commands are transactional, and their
4985 effects can be rolled back:
4990 effects can be rolled back:
4986
4991
4987 - commit
4992 - commit
4988 - import
4993 - import
4989 - pull
4994 - pull
4990 - push (with this repository as the destination)
4995 - push (with this repository as the destination)
4991 - unbundle
4996 - unbundle
4992
4997
4993 To avoid permanent data loss, rollback will refuse to rollback a
4998 To avoid permanent data loss, rollback will refuse to rollback a
4994 commit transaction if it isn't checked out. Use --force to
4999 commit transaction if it isn't checked out. Use --force to
4995 override this protection.
5000 override this protection.
4996
5001
4997 This command is not intended for use on public repositories. Once
5002 This command is not intended for use on public repositories. Once
4998 changes are visible for pull by other users, rolling a transaction
5003 changes are visible for pull by other users, rolling a transaction
4999 back locally is ineffective (someone else may already have pulled
5004 back locally is ineffective (someone else may already have pulled
5000 the changes). Furthermore, a race is possible with readers of the
5005 the changes). Furthermore, a race is possible with readers of the
5001 repository; for example an in-progress pull from the repository
5006 repository; for example an in-progress pull from the repository
5002 may fail if a rollback is performed.
5007 may fail if a rollback is performed.
5003
5008
5004 Returns 0 on success, 1 if no rollback data is available.
5009 Returns 0 on success, 1 if no rollback data is available.
5005 """
5010 """
5006 return repo.rollback(dryrun=opts.get('dry_run'),
5011 return repo.rollback(dryrun=opts.get('dry_run'),
5007 force=opts.get('force'))
5012 force=opts.get('force'))
5008
5013
5009 @command('root', [])
5014 @command('root', [])
5010 def root(ui, repo):
5015 def root(ui, repo):
5011 """print the root (top) of the current working directory
5016 """print the root (top) of the current working directory
5012
5017
5013 Print the root directory of the current repository.
5018 Print the root directory of the current repository.
5014
5019
5015 Returns 0 on success.
5020 Returns 0 on success.
5016 """
5021 """
5017 ui.write(repo.root + "\n")
5022 ui.write(repo.root + "\n")
5018
5023
5019 @command('^serve',
5024 @command('^serve',
5020 [('A', 'accesslog', '', _('name of access log file to write to'),
5025 [('A', 'accesslog', '', _('name of access log file to write to'),
5021 _('FILE')),
5026 _('FILE')),
5022 ('d', 'daemon', None, _('run server in background')),
5027 ('d', 'daemon', None, _('run server in background')),
5023 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5028 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5024 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5029 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5025 # use string type, then we can check if something was passed
5030 # use string type, then we can check if something was passed
5026 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5031 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5027 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5032 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5028 _('ADDR')),
5033 _('ADDR')),
5029 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5034 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5030 _('PREFIX')),
5035 _('PREFIX')),
5031 ('n', 'name', '',
5036 ('n', 'name', '',
5032 _('name to show in web pages (default: working directory)'), _('NAME')),
5037 _('name to show in web pages (default: working directory)'), _('NAME')),
5033 ('', 'web-conf', '',
5038 ('', 'web-conf', '',
5034 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5039 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5035 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5040 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5036 _('FILE')),
5041 _('FILE')),
5037 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5042 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5038 ('', 'stdio', None, _('for remote clients')),
5043 ('', 'stdio', None, _('for remote clients')),
5039 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5044 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5040 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5045 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5041 ('', 'style', '', _('template style to use'), _('STYLE')),
5046 ('', 'style', '', _('template style to use'), _('STYLE')),
5042 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5047 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5043 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5048 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5044 _('[OPTION]...'))
5049 _('[OPTION]...'))
5045 def serve(ui, repo, **opts):
5050 def serve(ui, repo, **opts):
5046 """start stand-alone webserver
5051 """start stand-alone webserver
5047
5052
5048 Start a local HTTP repository browser and pull server. You can use
5053 Start a local HTTP repository browser and pull server. You can use
5049 this for ad-hoc sharing and browsing of repositories. It is
5054 this for ad-hoc sharing and browsing of repositories. It is
5050 recommended to use a real web server to serve a repository for
5055 recommended to use a real web server to serve a repository for
5051 longer periods of time.
5056 longer periods of time.
5052
5057
5053 Please note that the server does not implement access control.
5058 Please note that the server does not implement access control.
5054 This means that, by default, anybody can read from the server and
5059 This means that, by default, anybody can read from the server and
5055 nobody can write to it by default. Set the ``web.allow_push``
5060 nobody can write to it by default. Set the ``web.allow_push``
5056 option to ``*`` to allow everybody to push to the server. You
5061 option to ``*`` to allow everybody to push to the server. You
5057 should use a real web server if you need to authenticate users.
5062 should use a real web server if you need to authenticate users.
5058
5063
5059 By default, the server logs accesses to stdout and errors to
5064 By default, the server logs accesses to stdout and errors to
5060 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5065 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5061 files.
5066 files.
5062
5067
5063 To have the server choose a free port number to listen on, specify
5068 To have the server choose a free port number to listen on, specify
5064 a port number of 0; in this case, the server will print the port
5069 a port number of 0; in this case, the server will print the port
5065 number it uses.
5070 number it uses.
5066
5071
5067 Returns 0 on success.
5072 Returns 0 on success.
5068 """
5073 """
5069
5074
5070 if opts["stdio"] and opts["cmdserver"]:
5075 if opts["stdio"] and opts["cmdserver"]:
5071 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5076 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5072
5077
5073 def checkrepo():
5078 def checkrepo():
5074 if repo is None:
5079 if repo is None:
5075 raise error.RepoError(_("there is no Mercurial repository here"
5080 raise error.RepoError(_("there is no Mercurial repository here"
5076 " (.hg not found)"))
5081 " (.hg not found)"))
5077
5082
5078 if opts["stdio"]:
5083 if opts["stdio"]:
5079 checkrepo()
5084 checkrepo()
5080 s = sshserver.sshserver(ui, repo)
5085 s = sshserver.sshserver(ui, repo)
5081 s.serve_forever()
5086 s.serve_forever()
5082
5087
5083 if opts["cmdserver"]:
5088 if opts["cmdserver"]:
5084 checkrepo()
5089 checkrepo()
5085 s = commandserver.server(ui, repo, opts["cmdserver"])
5090 s = commandserver.server(ui, repo, opts["cmdserver"])
5086 return s.serve()
5091 return s.serve()
5087
5092
5088 # this way we can check if something was given in the command-line
5093 # this way we can check if something was given in the command-line
5089 if opts.get('port'):
5094 if opts.get('port'):
5090 opts['port'] = util.getport(opts.get('port'))
5095 opts['port'] = util.getport(opts.get('port'))
5091
5096
5092 baseui = repo and repo.baseui or ui
5097 baseui = repo and repo.baseui or ui
5093 optlist = ("name templates style address port prefix ipv6"
5098 optlist = ("name templates style address port prefix ipv6"
5094 " accesslog errorlog certificate encoding")
5099 " accesslog errorlog certificate encoding")
5095 for o in optlist.split():
5100 for o in optlist.split():
5096 val = opts.get(o, '')
5101 val = opts.get(o, '')
5097 if val in (None, ''): # should check against default options instead
5102 if val in (None, ''): # should check against default options instead
5098 continue
5103 continue
5099 baseui.setconfig("web", o, val)
5104 baseui.setconfig("web", o, val)
5100 if repo and repo.ui != baseui:
5105 if repo and repo.ui != baseui:
5101 repo.ui.setconfig("web", o, val)
5106 repo.ui.setconfig("web", o, val)
5102
5107
5103 o = opts.get('web_conf') or opts.get('webdir_conf')
5108 o = opts.get('web_conf') or opts.get('webdir_conf')
5104 if not o:
5109 if not o:
5105 if not repo:
5110 if not repo:
5106 raise error.RepoError(_("there is no Mercurial repository"
5111 raise error.RepoError(_("there is no Mercurial repository"
5107 " here (.hg not found)"))
5112 " here (.hg not found)"))
5108 o = repo
5113 o = repo
5109
5114
5110 app = hgweb.hgweb(o, baseui=baseui)
5115 app = hgweb.hgweb(o, baseui=baseui)
5111
5116
5112 class service(object):
5117 class service(object):
5113 def init(self):
5118 def init(self):
5114 util.setsignalhandler()
5119 util.setsignalhandler()
5115 self.httpd = hgweb.server.create_server(ui, app)
5120 self.httpd = hgweb.server.create_server(ui, app)
5116
5121
5117 if opts['port'] and not ui.verbose:
5122 if opts['port'] and not ui.verbose:
5118 return
5123 return
5119
5124
5120 if self.httpd.prefix:
5125 if self.httpd.prefix:
5121 prefix = self.httpd.prefix.strip('/') + '/'
5126 prefix = self.httpd.prefix.strip('/') + '/'
5122 else:
5127 else:
5123 prefix = ''
5128 prefix = ''
5124
5129
5125 port = ':%d' % self.httpd.port
5130 port = ':%d' % self.httpd.port
5126 if port == ':80':
5131 if port == ':80':
5127 port = ''
5132 port = ''
5128
5133
5129 bindaddr = self.httpd.addr
5134 bindaddr = self.httpd.addr
5130 if bindaddr == '0.0.0.0':
5135 if bindaddr == '0.0.0.0':
5131 bindaddr = '*'
5136 bindaddr = '*'
5132 elif ':' in bindaddr: # IPv6
5137 elif ':' in bindaddr: # IPv6
5133 bindaddr = '[%s]' % bindaddr
5138 bindaddr = '[%s]' % bindaddr
5134
5139
5135 fqaddr = self.httpd.fqaddr
5140 fqaddr = self.httpd.fqaddr
5136 if ':' in fqaddr:
5141 if ':' in fqaddr:
5137 fqaddr = '[%s]' % fqaddr
5142 fqaddr = '[%s]' % fqaddr
5138 if opts['port']:
5143 if opts['port']:
5139 write = ui.status
5144 write = ui.status
5140 else:
5145 else:
5141 write = ui.write
5146 write = ui.write
5142 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5147 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5143 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5148 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5144
5149
5145 def run(self):
5150 def run(self):
5146 self.httpd.serve_forever()
5151 self.httpd.serve_forever()
5147
5152
5148 service = service()
5153 service = service()
5149
5154
5150 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5155 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5151
5156
5152 @command('showconfig|debugconfig',
5157 @command('showconfig|debugconfig',
5153 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5158 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5154 _('[-u] [NAME]...'))
5159 _('[-u] [NAME]...'))
5155 def showconfig(ui, repo, *values, **opts):
5160 def showconfig(ui, repo, *values, **opts):
5156 """show combined config settings from all hgrc files
5161 """show combined config settings from all hgrc files
5157
5162
5158 With no arguments, print names and values of all config items.
5163 With no arguments, print names and values of all config items.
5159
5164
5160 With one argument of the form section.name, print just the value
5165 With one argument of the form section.name, print just the value
5161 of that config item.
5166 of that config item.
5162
5167
5163 With multiple arguments, print names and values of all config
5168 With multiple arguments, print names and values of all config
5164 items with matching section names.
5169 items with matching section names.
5165
5170
5166 With --debug, the source (filename and line number) is printed
5171 With --debug, the source (filename and line number) is printed
5167 for each config item.
5172 for each config item.
5168
5173
5169 Returns 0 on success.
5174 Returns 0 on success.
5170 """
5175 """
5171
5176
5172 for f in scmutil.rcpath():
5177 for f in scmutil.rcpath():
5173 ui.debug('read config from: %s\n' % f)
5178 ui.debug('read config from: %s\n' % f)
5174 untrusted = bool(opts.get('untrusted'))
5179 untrusted = bool(opts.get('untrusted'))
5175 if values:
5180 if values:
5176 sections = [v for v in values if '.' not in v]
5181 sections = [v for v in values if '.' not in v]
5177 items = [v for v in values if '.' in v]
5182 items = [v for v in values if '.' in v]
5178 if len(items) > 1 or items and sections:
5183 if len(items) > 1 or items and sections:
5179 raise util.Abort(_('only one config item permitted'))
5184 raise util.Abort(_('only one config item permitted'))
5180 for section, name, value in ui.walkconfig(untrusted=untrusted):
5185 for section, name, value in ui.walkconfig(untrusted=untrusted):
5181 value = str(value).replace('\n', '\\n')
5186 value = str(value).replace('\n', '\\n')
5182 sectname = section + '.' + name
5187 sectname = section + '.' + name
5183 if values:
5188 if values:
5184 for v in values:
5189 for v in values:
5185 if v == section:
5190 if v == section:
5186 ui.debug('%s: ' %
5191 ui.debug('%s: ' %
5187 ui.configsource(section, name, untrusted))
5192 ui.configsource(section, name, untrusted))
5188 ui.write('%s=%s\n' % (sectname, value))
5193 ui.write('%s=%s\n' % (sectname, value))
5189 elif v == sectname:
5194 elif v == sectname:
5190 ui.debug('%s: ' %
5195 ui.debug('%s: ' %
5191 ui.configsource(section, name, untrusted))
5196 ui.configsource(section, name, untrusted))
5192 ui.write(value, '\n')
5197 ui.write(value, '\n')
5193 else:
5198 else:
5194 ui.debug('%s: ' %
5199 ui.debug('%s: ' %
5195 ui.configsource(section, name, untrusted))
5200 ui.configsource(section, name, untrusted))
5196 ui.write('%s=%s\n' % (sectname, value))
5201 ui.write('%s=%s\n' % (sectname, value))
5197
5202
5198 @command('^status|st',
5203 @command('^status|st',
5199 [('A', 'all', None, _('show status of all files')),
5204 [('A', 'all', None, _('show status of all files')),
5200 ('m', 'modified', None, _('show only modified files')),
5205 ('m', 'modified', None, _('show only modified files')),
5201 ('a', 'added', None, _('show only added files')),
5206 ('a', 'added', None, _('show only added files')),
5202 ('r', 'removed', None, _('show only removed files')),
5207 ('r', 'removed', None, _('show only removed files')),
5203 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5208 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5204 ('c', 'clean', None, _('show only files without changes')),
5209 ('c', 'clean', None, _('show only files without changes')),
5205 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5210 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5206 ('i', 'ignored', None, _('show only ignored files')),
5211 ('i', 'ignored', None, _('show only ignored files')),
5207 ('n', 'no-status', None, _('hide status prefix')),
5212 ('n', 'no-status', None, _('hide status prefix')),
5208 ('C', 'copies', None, _('show source of copied files')),
5213 ('C', 'copies', None, _('show source of copied files')),
5209 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5214 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5210 ('', 'rev', [], _('show difference from revision'), _('REV')),
5215 ('', 'rev', [], _('show difference from revision'), _('REV')),
5211 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5216 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5212 ] + walkopts + subrepoopts,
5217 ] + walkopts + subrepoopts,
5213 _('[OPTION]... [FILE]...'))
5218 _('[OPTION]... [FILE]...'))
5214 def status(ui, repo, *pats, **opts):
5219 def status(ui, repo, *pats, **opts):
5215 """show changed files in the working directory
5220 """show changed files in the working directory
5216
5221
5217 Show status of files in the repository. If names are given, only
5222 Show status of files in the repository. If names are given, only
5218 files that match are shown. Files that are clean or ignored or
5223 files that match are shown. Files that are clean or ignored or
5219 the source of a copy/move operation, are not listed unless
5224 the source of a copy/move operation, are not listed unless
5220 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5225 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5221 Unless options described with "show only ..." are given, the
5226 Unless options described with "show only ..." are given, the
5222 options -mardu are used.
5227 options -mardu are used.
5223
5228
5224 Option -q/--quiet hides untracked (unknown and ignored) files
5229 Option -q/--quiet hides untracked (unknown and ignored) files
5225 unless explicitly requested with -u/--unknown or -i/--ignored.
5230 unless explicitly requested with -u/--unknown or -i/--ignored.
5226
5231
5227 .. note::
5232 .. note::
5228 status may appear to disagree with diff if permissions have
5233 status may appear to disagree with diff if permissions have
5229 changed or a merge has occurred. The standard diff format does
5234 changed or a merge has occurred. The standard diff format does
5230 not report permission changes and diff only reports changes
5235 not report permission changes and diff only reports changes
5231 relative to one merge parent.
5236 relative to one merge parent.
5232
5237
5233 If one revision is given, it is used as the base revision.
5238 If one revision is given, it is used as the base revision.
5234 If two revisions are given, the differences between them are
5239 If two revisions are given, the differences between them are
5235 shown. The --change option can also be used as a shortcut to list
5240 shown. The --change option can also be used as a shortcut to list
5236 the changed files of a revision from its first parent.
5241 the changed files of a revision from its first parent.
5237
5242
5238 The codes used to show the status of files are::
5243 The codes used to show the status of files are::
5239
5244
5240 M = modified
5245 M = modified
5241 A = added
5246 A = added
5242 R = removed
5247 R = removed
5243 C = clean
5248 C = clean
5244 ! = missing (deleted by non-hg command, but still tracked)
5249 ! = missing (deleted by non-hg command, but still tracked)
5245 ? = not tracked
5250 ? = not tracked
5246 I = ignored
5251 I = ignored
5247 = origin of the previous file listed as A (added)
5252 = origin of the previous file listed as A (added)
5248
5253
5249 .. container:: verbose
5254 .. container:: verbose
5250
5255
5251 Examples:
5256 Examples:
5252
5257
5253 - show changes in the working directory relative to a
5258 - show changes in the working directory relative to a
5254 changeset::
5259 changeset::
5255
5260
5256 hg status --rev 9353
5261 hg status --rev 9353
5257
5262
5258 - show all changes including copies in an existing changeset::
5263 - show all changes including copies in an existing changeset::
5259
5264
5260 hg status --copies --change 9353
5265 hg status --copies --change 9353
5261
5266
5262 - get a NUL separated list of added files, suitable for xargs::
5267 - get a NUL separated list of added files, suitable for xargs::
5263
5268
5264 hg status -an0
5269 hg status -an0
5265
5270
5266 Returns 0 on success.
5271 Returns 0 on success.
5267 """
5272 """
5268
5273
5269 revs = opts.get('rev')
5274 revs = opts.get('rev')
5270 change = opts.get('change')
5275 change = opts.get('change')
5271
5276
5272 if revs and change:
5277 if revs and change:
5273 msg = _('cannot specify --rev and --change at the same time')
5278 msg = _('cannot specify --rev and --change at the same time')
5274 raise util.Abort(msg)
5279 raise util.Abort(msg)
5275 elif change:
5280 elif change:
5276 node2 = scmutil.revsingle(repo, change, None).node()
5281 node2 = scmutil.revsingle(repo, change, None).node()
5277 node1 = repo[node2].p1().node()
5282 node1 = repo[node2].p1().node()
5278 else:
5283 else:
5279 node1, node2 = scmutil.revpair(repo, revs)
5284 node1, node2 = scmutil.revpair(repo, revs)
5280
5285
5281 cwd = (pats and repo.getcwd()) or ''
5286 cwd = (pats and repo.getcwd()) or ''
5282 end = opts.get('print0') and '\0' or '\n'
5287 end = opts.get('print0') and '\0' or '\n'
5283 copy = {}
5288 copy = {}
5284 states = 'modified added removed deleted unknown ignored clean'.split()
5289 states = 'modified added removed deleted unknown ignored clean'.split()
5285 show = [k for k in states if opts.get(k)]
5290 show = [k for k in states if opts.get(k)]
5286 if opts.get('all'):
5291 if opts.get('all'):
5287 show += ui.quiet and (states[:4] + ['clean']) or states
5292 show += ui.quiet and (states[:4] + ['clean']) or states
5288 if not show:
5293 if not show:
5289 show = ui.quiet and states[:4] or states[:5]
5294 show = ui.quiet and states[:4] or states[:5]
5290
5295
5291 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5296 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5292 'ignored' in show, 'clean' in show, 'unknown' in show,
5297 'ignored' in show, 'clean' in show, 'unknown' in show,
5293 opts.get('subrepos'))
5298 opts.get('subrepos'))
5294 changestates = zip(states, 'MAR!?IC', stat)
5299 changestates = zip(states, 'MAR!?IC', stat)
5295
5300
5296 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5301 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5297 copy = copies.pathcopies(repo[node1], repo[node2])
5302 copy = copies.pathcopies(repo[node1], repo[node2])
5298
5303
5299 fm = ui.formatter('status', opts)
5304 fm = ui.formatter('status', opts)
5300 fmt = '%s' + end
5305 fmt = '%s' + end
5301 showchar = not opts.get('no_status')
5306 showchar = not opts.get('no_status')
5302
5307
5303 for state, char, files in changestates:
5308 for state, char, files in changestates:
5304 if state in show:
5309 if state in show:
5305 label = 'status.' + state
5310 label = 'status.' + state
5306 for f in files:
5311 for f in files:
5307 fm.startitem()
5312 fm.startitem()
5308 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5313 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5309 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5314 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5310 if f in copy:
5315 if f in copy:
5311 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5316 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5312 label='status.copied')
5317 label='status.copied')
5313 fm.end()
5318 fm.end()
5314
5319
5315 @command('^summary|sum',
5320 @command('^summary|sum',
5316 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5321 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5317 def summary(ui, repo, **opts):
5322 def summary(ui, repo, **opts):
5318 """summarize working directory state
5323 """summarize working directory state
5319
5324
5320 This generates a brief summary of the working directory state,
5325 This generates a brief summary of the working directory state,
5321 including parents, branch, commit status, and available updates.
5326 including parents, branch, commit status, and available updates.
5322
5327
5323 With the --remote option, this will check the default paths for
5328 With the --remote option, this will check the default paths for
5324 incoming and outgoing changes. This can be time-consuming.
5329 incoming and outgoing changes. This can be time-consuming.
5325
5330
5326 Returns 0 on success.
5331 Returns 0 on success.
5327 """
5332 """
5328
5333
5329 ctx = repo[None]
5334 ctx = repo[None]
5330 parents = ctx.parents()
5335 parents = ctx.parents()
5331 pnode = parents[0].node()
5336 pnode = parents[0].node()
5332 marks = []
5337 marks = []
5333
5338
5334 for p in parents:
5339 for p in parents:
5335 # label with log.changeset (instead of log.parent) since this
5340 # label with log.changeset (instead of log.parent) since this
5336 # shows a working directory parent *changeset*:
5341 # shows a working directory parent *changeset*:
5337 # i18n: column positioning for "hg summary"
5342 # i18n: column positioning for "hg summary"
5338 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5343 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5339 label='log.changeset changeset.%s' % p.phasestr())
5344 label='log.changeset changeset.%s' % p.phasestr())
5340 ui.write(' '.join(p.tags()), label='log.tag')
5345 ui.write(' '.join(p.tags()), label='log.tag')
5341 if p.bookmarks():
5346 if p.bookmarks():
5342 marks.extend(p.bookmarks())
5347 marks.extend(p.bookmarks())
5343 if p.rev() == -1:
5348 if p.rev() == -1:
5344 if not len(repo):
5349 if not len(repo):
5345 ui.write(_(' (empty repository)'))
5350 ui.write(_(' (empty repository)'))
5346 else:
5351 else:
5347 ui.write(_(' (no revision checked out)'))
5352 ui.write(_(' (no revision checked out)'))
5348 ui.write('\n')
5353 ui.write('\n')
5349 if p.description():
5354 if p.description():
5350 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5355 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5351 label='log.summary')
5356 label='log.summary')
5352
5357
5353 branch = ctx.branch()
5358 branch = ctx.branch()
5354 bheads = repo.branchheads(branch)
5359 bheads = repo.branchheads(branch)
5355 # i18n: column positioning for "hg summary"
5360 # i18n: column positioning for "hg summary"
5356 m = _('branch: %s\n') % branch
5361 m = _('branch: %s\n') % branch
5357 if branch != 'default':
5362 if branch != 'default':
5358 ui.write(m, label='log.branch')
5363 ui.write(m, label='log.branch')
5359 else:
5364 else:
5360 ui.status(m, label='log.branch')
5365 ui.status(m, label='log.branch')
5361
5366
5362 if marks:
5367 if marks:
5363 current = repo._bookmarkcurrent
5368 current = repo._bookmarkcurrent
5364 # i18n: column positioning for "hg summary"
5369 # i18n: column positioning for "hg summary"
5365 ui.write(_('bookmarks:'), label='log.bookmark')
5370 ui.write(_('bookmarks:'), label='log.bookmark')
5366 if current is not None:
5371 if current is not None:
5367 if current in marks:
5372 if current in marks:
5368 ui.write(' *' + current, label='bookmarks.current')
5373 ui.write(' *' + current, label='bookmarks.current')
5369 marks.remove(current)
5374 marks.remove(current)
5370 else:
5375 else:
5371 ui.write(' [%s]' % current, label='bookmarks.current')
5376 ui.write(' [%s]' % current, label='bookmarks.current')
5372 for m in marks:
5377 for m in marks:
5373 ui.write(' ' + m, label='log.bookmark')
5378 ui.write(' ' + m, label='log.bookmark')
5374 ui.write('\n', label='log.bookmark')
5379 ui.write('\n', label='log.bookmark')
5375
5380
5376 st = list(repo.status(unknown=True))[:6]
5381 st = list(repo.status(unknown=True))[:6]
5377
5382
5378 c = repo.dirstate.copies()
5383 c = repo.dirstate.copies()
5379 copied, renamed = [], []
5384 copied, renamed = [], []
5380 for d, s in c.iteritems():
5385 for d, s in c.iteritems():
5381 if s in st[2]:
5386 if s in st[2]:
5382 st[2].remove(s)
5387 st[2].remove(s)
5383 renamed.append(d)
5388 renamed.append(d)
5384 else:
5389 else:
5385 copied.append(d)
5390 copied.append(d)
5386 if d in st[1]:
5391 if d in st[1]:
5387 st[1].remove(d)
5392 st[1].remove(d)
5388 st.insert(3, renamed)
5393 st.insert(3, renamed)
5389 st.insert(4, copied)
5394 st.insert(4, copied)
5390
5395
5391 ms = mergemod.mergestate(repo)
5396 ms = mergemod.mergestate(repo)
5392 st.append([f for f in ms if ms[f] == 'u'])
5397 st.append([f for f in ms if ms[f] == 'u'])
5393
5398
5394 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5399 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5395 st.append(subs)
5400 st.append(subs)
5396
5401
5397 labels = [ui.label(_('%d modified'), 'status.modified'),
5402 labels = [ui.label(_('%d modified'), 'status.modified'),
5398 ui.label(_('%d added'), 'status.added'),
5403 ui.label(_('%d added'), 'status.added'),
5399 ui.label(_('%d removed'), 'status.removed'),
5404 ui.label(_('%d removed'), 'status.removed'),
5400 ui.label(_('%d renamed'), 'status.copied'),
5405 ui.label(_('%d renamed'), 'status.copied'),
5401 ui.label(_('%d copied'), 'status.copied'),
5406 ui.label(_('%d copied'), 'status.copied'),
5402 ui.label(_('%d deleted'), 'status.deleted'),
5407 ui.label(_('%d deleted'), 'status.deleted'),
5403 ui.label(_('%d unknown'), 'status.unknown'),
5408 ui.label(_('%d unknown'), 'status.unknown'),
5404 ui.label(_('%d ignored'), 'status.ignored'),
5409 ui.label(_('%d ignored'), 'status.ignored'),
5405 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5410 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5406 ui.label(_('%d subrepos'), 'status.modified')]
5411 ui.label(_('%d subrepos'), 'status.modified')]
5407 t = []
5412 t = []
5408 for s, l in zip(st, labels):
5413 for s, l in zip(st, labels):
5409 if s:
5414 if s:
5410 t.append(l % len(s))
5415 t.append(l % len(s))
5411
5416
5412 t = ', '.join(t)
5417 t = ', '.join(t)
5413 cleanworkdir = False
5418 cleanworkdir = False
5414
5419
5415 if len(parents) > 1:
5420 if len(parents) > 1:
5416 t += _(' (merge)')
5421 t += _(' (merge)')
5417 elif branch != parents[0].branch():
5422 elif branch != parents[0].branch():
5418 t += _(' (new branch)')
5423 t += _(' (new branch)')
5419 elif (parents[0].closesbranch() and
5424 elif (parents[0].closesbranch() and
5420 pnode in repo.branchheads(branch, closed=True)):
5425 pnode in repo.branchheads(branch, closed=True)):
5421 t += _(' (head closed)')
5426 t += _(' (head closed)')
5422 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5427 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5423 t += _(' (clean)')
5428 t += _(' (clean)')
5424 cleanworkdir = True
5429 cleanworkdir = True
5425 elif pnode not in bheads:
5430 elif pnode not in bheads:
5426 t += _(' (new branch head)')
5431 t += _(' (new branch head)')
5427
5432
5428 if cleanworkdir:
5433 if cleanworkdir:
5429 # i18n: column positioning for "hg summary"
5434 # i18n: column positioning for "hg summary"
5430 ui.status(_('commit: %s\n') % t.strip())
5435 ui.status(_('commit: %s\n') % t.strip())
5431 else:
5436 else:
5432 # i18n: column positioning for "hg summary"
5437 # i18n: column positioning for "hg summary"
5433 ui.write(_('commit: %s\n') % t.strip())
5438 ui.write(_('commit: %s\n') % t.strip())
5434
5439
5435 # all ancestors of branch heads - all ancestors of parent = new csets
5440 # all ancestors of branch heads - all ancestors of parent = new csets
5436 new = [0] * len(repo)
5441 new = [0] * len(repo)
5437 cl = repo.changelog
5442 cl = repo.changelog
5438 for a in [cl.rev(n) for n in bheads]:
5443 for a in [cl.rev(n) for n in bheads]:
5439 new[a] = 1
5444 new[a] = 1
5440 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5445 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5441 new[a] = 1
5446 new[a] = 1
5442 for a in [p.rev() for p in parents]:
5447 for a in [p.rev() for p in parents]:
5443 if a >= 0:
5448 if a >= 0:
5444 new[a] = 0
5449 new[a] = 0
5445 for a in cl.ancestors([p.rev() for p in parents]):
5450 for a in cl.ancestors([p.rev() for p in parents]):
5446 new[a] = 0
5451 new[a] = 0
5447 new = sum(new)
5452 new = sum(new)
5448
5453
5449 if new == 0:
5454 if new == 0:
5450 # i18n: column positioning for "hg summary"
5455 # i18n: column positioning for "hg summary"
5451 ui.status(_('update: (current)\n'))
5456 ui.status(_('update: (current)\n'))
5452 elif pnode not in bheads:
5457 elif pnode not in bheads:
5453 # i18n: column positioning for "hg summary"
5458 # i18n: column positioning for "hg summary"
5454 ui.write(_('update: %d new changesets (update)\n') % new)
5459 ui.write(_('update: %d new changesets (update)\n') % new)
5455 else:
5460 else:
5456 # i18n: column positioning for "hg summary"
5461 # i18n: column positioning for "hg summary"
5457 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5462 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5458 (new, len(bheads)))
5463 (new, len(bheads)))
5459
5464
5460 if opts.get('remote'):
5465 if opts.get('remote'):
5461 t = []
5466 t = []
5462 source, branches = hg.parseurl(ui.expandpath('default'))
5467 source, branches = hg.parseurl(ui.expandpath('default'))
5463 sbranch = branches[0]
5468 sbranch = branches[0]
5464 other = hg.peer(repo, {}, source)
5469 other = hg.peer(repo, {}, source)
5465 revs, checkout = hg.addbranchrevs(repo, other, branches,
5470 revs, checkout = hg.addbranchrevs(repo, other, branches,
5466 opts.get('rev'))
5471 opts.get('rev'))
5467 if revs:
5472 if revs:
5468 revs = [other.lookup(rev) for rev in revs]
5473 revs = [other.lookup(rev) for rev in revs]
5469 ui.debug('comparing with %s\n' % util.hidepassword(source))
5474 ui.debug('comparing with %s\n' % util.hidepassword(source))
5470 repo.ui.pushbuffer()
5475 repo.ui.pushbuffer()
5471 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5476 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5472 _common, incoming, _rheads = commoninc
5477 _common, incoming, _rheads = commoninc
5473 repo.ui.popbuffer()
5478 repo.ui.popbuffer()
5474 if incoming:
5479 if incoming:
5475 t.append(_('1 or more incoming'))
5480 t.append(_('1 or more incoming'))
5476
5481
5477 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5482 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5478 dbranch = branches[0]
5483 dbranch = branches[0]
5479 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5484 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5480 if source != dest:
5485 if source != dest:
5481 other = hg.peer(repo, {}, dest)
5486 other = hg.peer(repo, {}, dest)
5482 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5487 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5483 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5488 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5484 commoninc = None
5489 commoninc = None
5485 if revs:
5490 if revs:
5486 revs = [repo.lookup(rev) for rev in revs]
5491 revs = [repo.lookup(rev) for rev in revs]
5487 repo.ui.pushbuffer()
5492 repo.ui.pushbuffer()
5488 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5493 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5489 commoninc=commoninc)
5494 commoninc=commoninc)
5490 repo.ui.popbuffer()
5495 repo.ui.popbuffer()
5491 o = outgoing.missing
5496 o = outgoing.missing
5492 if o:
5497 if o:
5493 t.append(_('%d outgoing') % len(o))
5498 t.append(_('%d outgoing') % len(o))
5494 if 'bookmarks' in other.listkeys('namespaces'):
5499 if 'bookmarks' in other.listkeys('namespaces'):
5495 lmarks = repo.listkeys('bookmarks')
5500 lmarks = repo.listkeys('bookmarks')
5496 rmarks = other.listkeys('bookmarks')
5501 rmarks = other.listkeys('bookmarks')
5497 diff = set(rmarks) - set(lmarks)
5502 diff = set(rmarks) - set(lmarks)
5498 if len(diff) > 0:
5503 if len(diff) > 0:
5499 t.append(_('%d incoming bookmarks') % len(diff))
5504 t.append(_('%d incoming bookmarks') % len(diff))
5500 diff = set(lmarks) - set(rmarks)
5505 diff = set(lmarks) - set(rmarks)
5501 if len(diff) > 0:
5506 if len(diff) > 0:
5502 t.append(_('%d outgoing bookmarks') % len(diff))
5507 t.append(_('%d outgoing bookmarks') % len(diff))
5503
5508
5504 if t:
5509 if t:
5505 # i18n: column positioning for "hg summary"
5510 # i18n: column positioning for "hg summary"
5506 ui.write(_('remote: %s\n') % (', '.join(t)))
5511 ui.write(_('remote: %s\n') % (', '.join(t)))
5507 else:
5512 else:
5508 # i18n: column positioning for "hg summary"
5513 # i18n: column positioning for "hg summary"
5509 ui.status(_('remote: (synced)\n'))
5514 ui.status(_('remote: (synced)\n'))
5510
5515
5511 @command('tag',
5516 @command('tag',
5512 [('f', 'force', None, _('force tag')),
5517 [('f', 'force', None, _('force tag')),
5513 ('l', 'local', None, _('make the tag local')),
5518 ('l', 'local', None, _('make the tag local')),
5514 ('r', 'rev', '', _('revision to tag'), _('REV')),
5519 ('r', 'rev', '', _('revision to tag'), _('REV')),
5515 ('', 'remove', None, _('remove a tag')),
5520 ('', 'remove', None, _('remove a tag')),
5516 # -l/--local is already there, commitopts cannot be used
5521 # -l/--local is already there, commitopts cannot be used
5517 ('e', 'edit', None, _('edit commit message')),
5522 ('e', 'edit', None, _('edit commit message')),
5518 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5523 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5519 ] + commitopts2,
5524 ] + commitopts2,
5520 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5525 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5521 def tag(ui, repo, name1, *names, **opts):
5526 def tag(ui, repo, name1, *names, **opts):
5522 """add one or more tags for the current or given revision
5527 """add one or more tags for the current or given revision
5523
5528
5524 Name a particular revision using <name>.
5529 Name a particular revision using <name>.
5525
5530
5526 Tags are used to name particular revisions of the repository and are
5531 Tags are used to name particular revisions of the repository and are
5527 very useful to compare different revisions, to go back to significant
5532 very useful to compare different revisions, to go back to significant
5528 earlier versions or to mark branch points as releases, etc. Changing
5533 earlier versions or to mark branch points as releases, etc. Changing
5529 an existing tag is normally disallowed; use -f/--force to override.
5534 an existing tag is normally disallowed; use -f/--force to override.
5530
5535
5531 If no revision is given, the parent of the working directory is
5536 If no revision is given, the parent of the working directory is
5532 used, or tip if no revision is checked out.
5537 used, or tip if no revision is checked out.
5533
5538
5534 To facilitate version control, distribution, and merging of tags,
5539 To facilitate version control, distribution, and merging of tags,
5535 they are stored as a file named ".hgtags" which is managed similarly
5540 they are stored as a file named ".hgtags" which is managed similarly
5536 to other project files and can be hand-edited if necessary. This
5541 to other project files and can be hand-edited if necessary. This
5537 also means that tagging creates a new commit. The file
5542 also means that tagging creates a new commit. The file
5538 ".hg/localtags" is used for local tags (not shared among
5543 ".hg/localtags" is used for local tags (not shared among
5539 repositories).
5544 repositories).
5540
5545
5541 Tag commits are usually made at the head of a branch. If the parent
5546 Tag commits are usually made at the head of a branch. If the parent
5542 of the working directory is not a branch head, :hg:`tag` aborts; use
5547 of the working directory is not a branch head, :hg:`tag` aborts; use
5543 -f/--force to force the tag commit to be based on a non-head
5548 -f/--force to force the tag commit to be based on a non-head
5544 changeset.
5549 changeset.
5545
5550
5546 See :hg:`help dates` for a list of formats valid for -d/--date.
5551 See :hg:`help dates` for a list of formats valid for -d/--date.
5547
5552
5548 Since tag names have priority over branch names during revision
5553 Since tag names have priority over branch names during revision
5549 lookup, using an existing branch name as a tag name is discouraged.
5554 lookup, using an existing branch name as a tag name is discouraged.
5550
5555
5551 Returns 0 on success.
5556 Returns 0 on success.
5552 """
5557 """
5553 wlock = lock = None
5558 wlock = lock = None
5554 try:
5559 try:
5555 wlock = repo.wlock()
5560 wlock = repo.wlock()
5556 lock = repo.lock()
5561 lock = repo.lock()
5557 rev_ = "."
5562 rev_ = "."
5558 names = [t.strip() for t in (name1,) + names]
5563 names = [t.strip() for t in (name1,) + names]
5559 if len(names) != len(set(names)):
5564 if len(names) != len(set(names)):
5560 raise util.Abort(_('tag names must be unique'))
5565 raise util.Abort(_('tag names must be unique'))
5561 for n in names:
5566 for n in names:
5562 scmutil.checknewlabel(repo, n, 'tag')
5567 scmutil.checknewlabel(repo, n, 'tag')
5563 if not n:
5568 if not n:
5564 raise util.Abort(_('tag names cannot consist entirely of '
5569 raise util.Abort(_('tag names cannot consist entirely of '
5565 'whitespace'))
5570 'whitespace'))
5566 if opts.get('rev') and opts.get('remove'):
5571 if opts.get('rev') and opts.get('remove'):
5567 raise util.Abort(_("--rev and --remove are incompatible"))
5572 raise util.Abort(_("--rev and --remove are incompatible"))
5568 if opts.get('rev'):
5573 if opts.get('rev'):
5569 rev_ = opts['rev']
5574 rev_ = opts['rev']
5570 message = opts.get('message')
5575 message = opts.get('message')
5571 if opts.get('remove'):
5576 if opts.get('remove'):
5572 expectedtype = opts.get('local') and 'local' or 'global'
5577 expectedtype = opts.get('local') and 'local' or 'global'
5573 for n in names:
5578 for n in names:
5574 if not repo.tagtype(n):
5579 if not repo.tagtype(n):
5575 raise util.Abort(_("tag '%s' does not exist") % n)
5580 raise util.Abort(_("tag '%s' does not exist") % n)
5576 if repo.tagtype(n) != expectedtype:
5581 if repo.tagtype(n) != expectedtype:
5577 if expectedtype == 'global':
5582 if expectedtype == 'global':
5578 raise util.Abort(_("tag '%s' is not a global tag") % n)
5583 raise util.Abort(_("tag '%s' is not a global tag") % n)
5579 else:
5584 else:
5580 raise util.Abort(_("tag '%s' is not a local tag") % n)
5585 raise util.Abort(_("tag '%s' is not a local tag") % n)
5581 rev_ = nullid
5586 rev_ = nullid
5582 if not message:
5587 if not message:
5583 # we don't translate commit messages
5588 # we don't translate commit messages
5584 message = 'Removed tag %s' % ', '.join(names)
5589 message = 'Removed tag %s' % ', '.join(names)
5585 elif not opts.get('force'):
5590 elif not opts.get('force'):
5586 for n in names:
5591 for n in names:
5587 if n in repo.tags():
5592 if n in repo.tags():
5588 raise util.Abort(_("tag '%s' already exists "
5593 raise util.Abort(_("tag '%s' already exists "
5589 "(use -f to force)") % n)
5594 "(use -f to force)") % n)
5590 if not opts.get('local'):
5595 if not opts.get('local'):
5591 p1, p2 = repo.dirstate.parents()
5596 p1, p2 = repo.dirstate.parents()
5592 if p2 != nullid:
5597 if p2 != nullid:
5593 raise util.Abort(_('uncommitted merge'))
5598 raise util.Abort(_('uncommitted merge'))
5594 bheads = repo.branchheads()
5599 bheads = repo.branchheads()
5595 if not opts.get('force') and bheads and p1 not in bheads:
5600 if not opts.get('force') and bheads and p1 not in bheads:
5596 raise util.Abort(_('not at a branch head (use -f to force)'))
5601 raise util.Abort(_('not at a branch head (use -f to force)'))
5597 r = scmutil.revsingle(repo, rev_).node()
5602 r = scmutil.revsingle(repo, rev_).node()
5598
5603
5599 if not message:
5604 if not message:
5600 # we don't translate commit messages
5605 # we don't translate commit messages
5601 message = ('Added tag %s for changeset %s' %
5606 message = ('Added tag %s for changeset %s' %
5602 (', '.join(names), short(r)))
5607 (', '.join(names), short(r)))
5603
5608
5604 date = opts.get('date')
5609 date = opts.get('date')
5605 if date:
5610 if date:
5606 date = util.parsedate(date)
5611 date = util.parsedate(date)
5607
5612
5608 if opts.get('edit'):
5613 if opts.get('edit'):
5609 message = ui.edit(message, ui.username())
5614 message = ui.edit(message, ui.username())
5610
5615
5611 # don't allow tagging the null rev
5616 # don't allow tagging the null rev
5612 if (not opts.get('remove') and
5617 if (not opts.get('remove') and
5613 scmutil.revsingle(repo, rev_).rev() == nullrev):
5618 scmutil.revsingle(repo, rev_).rev() == nullrev):
5614 raise util.Abort(_("cannot tag null revision"))
5619 raise util.Abort(_("cannot tag null revision"))
5615
5620
5616 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5621 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5617 finally:
5622 finally:
5618 release(lock, wlock)
5623 release(lock, wlock)
5619
5624
5620 @command('tags', [], '')
5625 @command('tags', [], '')
5621 def tags(ui, repo, **opts):
5626 def tags(ui, repo, **opts):
5622 """list repository tags
5627 """list repository tags
5623
5628
5624 This lists both regular and local tags. When the -v/--verbose
5629 This lists both regular and local tags. When the -v/--verbose
5625 switch is used, a third column "local" is printed for local tags.
5630 switch is used, a third column "local" is printed for local tags.
5626
5631
5627 Returns 0 on success.
5632 Returns 0 on success.
5628 """
5633 """
5629
5634
5630 fm = ui.formatter('tags', opts)
5635 fm = ui.formatter('tags', opts)
5631 hexfunc = ui.debugflag and hex or short
5636 hexfunc = ui.debugflag and hex or short
5632 tagtype = ""
5637 tagtype = ""
5633
5638
5634 for t, n in reversed(repo.tagslist()):
5639 for t, n in reversed(repo.tagslist()):
5635 hn = hexfunc(n)
5640 hn = hexfunc(n)
5636 label = 'tags.normal'
5641 label = 'tags.normal'
5637 tagtype = ''
5642 tagtype = ''
5638 if repo.tagtype(t) == 'local':
5643 if repo.tagtype(t) == 'local':
5639 label = 'tags.local'
5644 label = 'tags.local'
5640 tagtype = 'local'
5645 tagtype = 'local'
5641
5646
5642 fm.startitem()
5647 fm.startitem()
5643 fm.write('tag', '%s', t, label=label)
5648 fm.write('tag', '%s', t, label=label)
5644 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5649 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5645 fm.condwrite(not ui.quiet, 'rev id', fmt,
5650 fm.condwrite(not ui.quiet, 'rev id', fmt,
5646 repo.changelog.rev(n), hn, label=label)
5651 repo.changelog.rev(n), hn, label=label)
5647 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5652 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5648 tagtype, label=label)
5653 tagtype, label=label)
5649 fm.plain('\n')
5654 fm.plain('\n')
5650 fm.end()
5655 fm.end()
5651
5656
5652 @command('tip',
5657 @command('tip',
5653 [('p', 'patch', None, _('show patch')),
5658 [('p', 'patch', None, _('show patch')),
5654 ('g', 'git', None, _('use git extended diff format')),
5659 ('g', 'git', None, _('use git extended diff format')),
5655 ] + templateopts,
5660 ] + templateopts,
5656 _('[-p] [-g]'))
5661 _('[-p] [-g]'))
5657 def tip(ui, repo, **opts):
5662 def tip(ui, repo, **opts):
5658 """show the tip revision
5663 """show the tip revision
5659
5664
5660 The tip revision (usually just called the tip) is the changeset
5665 The tip revision (usually just called the tip) is the changeset
5661 most recently added to the repository (and therefore the most
5666 most recently added to the repository (and therefore the most
5662 recently changed head).
5667 recently changed head).
5663
5668
5664 If you have just made a commit, that commit will be the tip. If
5669 If you have just made a commit, that commit will be the tip. If
5665 you have just pulled changes from another repository, the tip of
5670 you have just pulled changes from another repository, the tip of
5666 that repository becomes the current tip. The "tip" tag is special
5671 that repository becomes the current tip. The "tip" tag is special
5667 and cannot be renamed or assigned to a different changeset.
5672 and cannot be renamed or assigned to a different changeset.
5668
5673
5669 Returns 0 on success.
5674 Returns 0 on success.
5670 """
5675 """
5671 displayer = cmdutil.show_changeset(ui, repo, opts)
5676 displayer = cmdutil.show_changeset(ui, repo, opts)
5672 displayer.show(repo['tip'])
5677 displayer.show(repo['tip'])
5673 displayer.close()
5678 displayer.close()
5674
5679
5675 @command('unbundle',
5680 @command('unbundle',
5676 [('u', 'update', None,
5681 [('u', 'update', None,
5677 _('update to new branch head if changesets were unbundled'))],
5682 _('update to new branch head if changesets were unbundled'))],
5678 _('[-u] FILE...'))
5683 _('[-u] FILE...'))
5679 def unbundle(ui, repo, fname1, *fnames, **opts):
5684 def unbundle(ui, repo, fname1, *fnames, **opts):
5680 """apply one or more changegroup files
5685 """apply one or more changegroup files
5681
5686
5682 Apply one or more compressed changegroup files generated by the
5687 Apply one or more compressed changegroup files generated by the
5683 bundle command.
5688 bundle command.
5684
5689
5685 Returns 0 on success, 1 if an update has unresolved files.
5690 Returns 0 on success, 1 if an update has unresolved files.
5686 """
5691 """
5687 fnames = (fname1,) + fnames
5692 fnames = (fname1,) + fnames
5688
5693
5689 lock = repo.lock()
5694 lock = repo.lock()
5690 wc = repo['.']
5695 wc = repo['.']
5691 try:
5696 try:
5692 for fname in fnames:
5697 for fname in fnames:
5693 f = hg.openpath(ui, fname)
5698 f = hg.openpath(ui, fname)
5694 gen = changegroup.readbundle(f, fname)
5699 gen = changegroup.readbundle(f, fname)
5695 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5700 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5696 finally:
5701 finally:
5697 lock.release()
5702 lock.release()
5698 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5703 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5699 return postincoming(ui, repo, modheads, opts.get('update'), None)
5704 return postincoming(ui, repo, modheads, opts.get('update'), None)
5700
5705
5701 @command('^update|up|checkout|co',
5706 @command('^update|up|checkout|co',
5702 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5707 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5703 ('c', 'check', None,
5708 ('c', 'check', None,
5704 _('update across branches if no uncommitted changes')),
5709 _('update across branches if no uncommitted changes')),
5705 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5710 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5706 ('r', 'rev', '', _('revision'), _('REV'))],
5711 ('r', 'rev', '', _('revision'), _('REV'))],
5707 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5712 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5708 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5713 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5709 """update working directory (or switch revisions)
5714 """update working directory (or switch revisions)
5710
5715
5711 Update the repository's working directory to the specified
5716 Update the repository's working directory to the specified
5712 changeset. If no changeset is specified, update to the tip of the
5717 changeset. If no changeset is specified, update to the tip of the
5713 current named branch and move the current bookmark (see :hg:`help
5718 current named branch and move the current bookmark (see :hg:`help
5714 bookmarks`).
5719 bookmarks`).
5715
5720
5716 Update sets the working directory's parent revision to the specified
5721 Update sets the working directory's parent revision to the specified
5717 changeset (see :hg:`help parents`).
5722 changeset (see :hg:`help parents`).
5718
5723
5719 If the changeset is not a descendant or ancestor of the working
5724 If the changeset is not a descendant or ancestor of the working
5720 directory's parent, the update is aborted. With the -c/--check
5725 directory's parent, the update is aborted. With the -c/--check
5721 option, the working directory is checked for uncommitted changes; if
5726 option, the working directory is checked for uncommitted changes; if
5722 none are found, the working directory is updated to the specified
5727 none are found, the working directory is updated to the specified
5723 changeset.
5728 changeset.
5724
5729
5725 .. container:: verbose
5730 .. container:: verbose
5726
5731
5727 The following rules apply when the working directory contains
5732 The following rules apply when the working directory contains
5728 uncommitted changes:
5733 uncommitted changes:
5729
5734
5730 1. If neither -c/--check nor -C/--clean is specified, and if
5735 1. If neither -c/--check nor -C/--clean is specified, and if
5731 the requested changeset is an ancestor or descendant of
5736 the requested changeset is an ancestor or descendant of
5732 the working directory's parent, the uncommitted changes
5737 the working directory's parent, the uncommitted changes
5733 are merged into the requested changeset and the merged
5738 are merged into the requested changeset and the merged
5734 result is left uncommitted. If the requested changeset is
5739 result is left uncommitted. If the requested changeset is
5735 not an ancestor or descendant (that is, it is on another
5740 not an ancestor or descendant (that is, it is on another
5736 branch), the update is aborted and the uncommitted changes
5741 branch), the update is aborted and the uncommitted changes
5737 are preserved.
5742 are preserved.
5738
5743
5739 2. With the -c/--check option, the update is aborted and the
5744 2. With the -c/--check option, the update is aborted and the
5740 uncommitted changes are preserved.
5745 uncommitted changes are preserved.
5741
5746
5742 3. With the -C/--clean option, uncommitted changes are discarded and
5747 3. With the -C/--clean option, uncommitted changes are discarded and
5743 the working directory is updated to the requested changeset.
5748 the working directory is updated to the requested changeset.
5744
5749
5745 To cancel an uncommitted merge (and lose your changes), use
5750 To cancel an uncommitted merge (and lose your changes), use
5746 :hg:`update --clean .`.
5751 :hg:`update --clean .`.
5747
5752
5748 Use null as the changeset to remove the working directory (like
5753 Use null as the changeset to remove the working directory (like
5749 :hg:`clone -U`).
5754 :hg:`clone -U`).
5750
5755
5751 If you want to revert just one file to an older revision, use
5756 If you want to revert just one file to an older revision, use
5752 :hg:`revert [-r REV] NAME`.
5757 :hg:`revert [-r REV] NAME`.
5753
5758
5754 See :hg:`help dates` for a list of formats valid for -d/--date.
5759 See :hg:`help dates` for a list of formats valid for -d/--date.
5755
5760
5756 Returns 0 on success, 1 if there are unresolved files.
5761 Returns 0 on success, 1 if there are unresolved files.
5757 """
5762 """
5758 if rev and node:
5763 if rev and node:
5759 raise util.Abort(_("please specify just one revision"))
5764 raise util.Abort(_("please specify just one revision"))
5760
5765
5761 if rev is None or rev == '':
5766 if rev is None or rev == '':
5762 rev = node
5767 rev = node
5763
5768
5764 # with no argument, we also move the current bookmark, if any
5769 # with no argument, we also move the current bookmark, if any
5765 movemarkfrom = None
5770 movemarkfrom = None
5766 if rev is None:
5771 if rev is None:
5767 curmark = repo._bookmarkcurrent
5772 curmark = repo._bookmarkcurrent
5768 if bookmarks.iscurrent(repo):
5773 if bookmarks.iscurrent(repo):
5769 movemarkfrom = repo['.'].node()
5774 movemarkfrom = repo['.'].node()
5770 elif curmark:
5775 elif curmark:
5771 ui.status(_("updating to active bookmark %s\n") % curmark)
5776 ui.status(_("updating to active bookmark %s\n") % curmark)
5772 rev = curmark
5777 rev = curmark
5773
5778
5774 # if we defined a bookmark, we have to remember the original bookmark name
5779 # if we defined a bookmark, we have to remember the original bookmark name
5775 brev = rev
5780 brev = rev
5776 rev = scmutil.revsingle(repo, rev, rev).rev()
5781 rev = scmutil.revsingle(repo, rev, rev).rev()
5777
5782
5778 if check and clean:
5783 if check and clean:
5779 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5784 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5780
5785
5781 if date:
5786 if date:
5782 if rev is not None:
5787 if rev is not None:
5783 raise util.Abort(_("you can't specify a revision and a date"))
5788 raise util.Abort(_("you can't specify a revision and a date"))
5784 rev = cmdutil.finddate(ui, repo, date)
5789 rev = cmdutil.finddate(ui, repo, date)
5785
5790
5786 if check:
5791 if check:
5787 c = repo[None]
5792 c = repo[None]
5788 if c.dirty(merge=False, branch=False, missing=True):
5793 if c.dirty(merge=False, branch=False, missing=True):
5789 raise util.Abort(_("uncommitted local changes"))
5794 raise util.Abort(_("uncommitted local changes"))
5790 if rev is None:
5795 if rev is None:
5791 rev = repo[repo[None].branch()].rev()
5796 rev = repo[repo[None].branch()].rev()
5792 mergemod._checkunknown(repo, repo[None], repo[rev])
5797 mergemod._checkunknown(repo, repo[None], repo[rev])
5793
5798
5794 if clean:
5799 if clean:
5795 ret = hg.clean(repo, rev)
5800 ret = hg.clean(repo, rev)
5796 else:
5801 else:
5797 ret = hg.update(repo, rev)
5802 ret = hg.update(repo, rev)
5798
5803
5799 if not ret and movemarkfrom:
5804 if not ret and movemarkfrom:
5800 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5805 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5801 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5806 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5802 elif brev in repo._bookmarks:
5807 elif brev in repo._bookmarks:
5803 bookmarks.setcurrent(repo, brev)
5808 bookmarks.setcurrent(repo, brev)
5804 elif brev:
5809 elif brev:
5805 bookmarks.unsetcurrent(repo)
5810 bookmarks.unsetcurrent(repo)
5806
5811
5807 return ret
5812 return ret
5808
5813
5809 @command('verify', [])
5814 @command('verify', [])
5810 def verify(ui, repo):
5815 def verify(ui, repo):
5811 """verify the integrity of the repository
5816 """verify the integrity of the repository
5812
5817
5813 Verify the integrity of the current repository.
5818 Verify the integrity of the current repository.
5814
5819
5815 This will perform an extensive check of the repository's
5820 This will perform an extensive check of the repository's
5816 integrity, validating the hashes and checksums of each entry in
5821 integrity, validating the hashes and checksums of each entry in
5817 the changelog, manifest, and tracked files, as well as the
5822 the changelog, manifest, and tracked files, as well as the
5818 integrity of their crosslinks and indices.
5823 integrity of their crosslinks and indices.
5819
5824
5820 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5825 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5821 for more information about recovery from corruption of the
5826 for more information about recovery from corruption of the
5822 repository.
5827 repository.
5823
5828
5824 Returns 0 on success, 1 if errors are encountered.
5829 Returns 0 on success, 1 if errors are encountered.
5825 """
5830 """
5826 return hg.verify(repo)
5831 return hg.verify(repo)
5827
5832
5828 @command('version', [])
5833 @command('version', [])
5829 def version_(ui):
5834 def version_(ui):
5830 """output version and copyright information"""
5835 """output version and copyright information"""
5831 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5836 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5832 % util.version())
5837 % util.version())
5833 ui.status(_(
5838 ui.status(_(
5834 "(see http://mercurial.selenic.com for more information)\n"
5839 "(see http://mercurial.selenic.com for more information)\n"
5835 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5840 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5836 "This is free software; see the source for copying conditions. "
5841 "This is free software; see the source for copying conditions. "
5837 "There is NO\nwarranty; "
5842 "There is NO\nwarranty; "
5838 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5843 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5839 ))
5844 ))
5840
5845
5841 norepo = ("clone init version help debugcommands debugcomplete"
5846 norepo = ("clone init version help debugcommands debugcomplete"
5842 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5847 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5843 " debugknown debuggetbundle debugbundle")
5848 " debugknown debuggetbundle debugbundle")
5844 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5849 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5845 " debugdata debugindex debugindexdot debugrevlog")
5850 " debugdata debugindex debugindexdot debugrevlog")
5846 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5851 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5847 " remove resolve status debugwalk")
5852 " remove resolve status debugwalk")
@@ -1,592 +1,613 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 bookmarks
160 $ hg bookmarks
161 REVSET 0:f7b1eb17ad24
161 REVSET 0:f7b1eb17ad24
162 * TIP 2:db815d6d32e6
162 * TIP 2:db815d6d32e6
163 X2 1:925d80f479bb
163 X2 1:925d80f479bb
164 Y 2:db815d6d32e6
164 Y 2:db815d6d32e6
165 Z 0:f7b1eb17ad24
165 Z 0:f7b1eb17ad24
166
166
167 $ hg bookmark -d REVSET
167 $ hg bookmark -d REVSET
168 $ hg bookmark -d TIP
168 $ hg bookmark -d TIP
169
169
170 rename without new name
170 rename without new name
171
171
172 $ hg bookmark -m Y
172 $ hg bookmark -m Y
173 abort: new bookmark name required
173 abort: new bookmark name required
174 [255]
174 [255]
175
175
176 delete without name
176 delete without name
177
177
178 $ hg bookmark -d
178 $ hg bookmark -d
179 abort: bookmark name required
179 abort: bookmark name required
180 [255]
180 [255]
181
181
182 delete nonexistent bookmark
182 delete nonexistent bookmark
183
183
184 $ hg bookmark -d A
184 $ hg bookmark -d A
185 abort: bookmark 'A' does not exist
185 abort: bookmark 'A' does not exist
186 [255]
186 [255]
187
187
188 bookmark name with spaces should be stripped
188 bookmark name with spaces should be stripped
189
189
190 $ hg bookmark ' x y '
190 $ hg bookmark ' x y '
191
191
192 list bookmarks
192 list bookmarks
193
193
194 $ hg bookmarks
194 $ hg bookmarks
195 X2 1:925d80f479bb
195 X2 1:925d80f479bb
196 Y 2:db815d6d32e6
196 Y 2:db815d6d32e6
197 Z 0:f7b1eb17ad24
197 Z 0:f7b1eb17ad24
198 * x y 2:db815d6d32e6
198 * x y 2:db815d6d32e6
199
199
200 look up stripped bookmark name
200 look up stripped bookmark name
201
201
202 $ hg log -r '"x y"'
202 $ hg log -r '"x y"'
203 changeset: 2:db815d6d32e6
203 changeset: 2:db815d6d32e6
204 bookmark: Y
204 bookmark: Y
205 bookmark: x y
205 bookmark: x y
206 tag: tip
206 tag: tip
207 parent: 0:f7b1eb17ad24
207 parent: 0:f7b1eb17ad24
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:00 1970 +0000
209 date: Thu Jan 01 00:00:00 1970 +0000
210 summary: 2
210 summary: 2
211
211
212
212
213 reject bookmark name with newline
213 reject bookmark name with newline
214
214
215 $ hg bookmark '
215 $ hg bookmark '
216 > '
216 > '
217 abort: bookmark names cannot consist entirely of whitespace
217 abort: bookmark names cannot consist entirely of whitespace
218 [255]
218 [255]
219
219
220 $ hg bookmark -m Z '
220 $ hg bookmark -m Z '
221 > '
221 > '
222 abort: bookmark names cannot consist entirely of whitespace
222 abort: bookmark names cannot consist entirely of whitespace
223 [255]
223 [255]
224
224
225 bookmark with reserved name
225 bookmark with reserved name
226
226
227 $ hg bookmark tip
227 $ hg bookmark tip
228 abort: the name 'tip' is reserved
228 abort: the name 'tip' is reserved
229 [255]
229 [255]
230
230
231 $ hg bookmark .
231 $ hg bookmark .
232 abort: the name '.' is reserved
232 abort: the name '.' is reserved
233 [255]
233 [255]
234
234
235 $ hg bookmark null
235 $ hg bookmark null
236 abort: the name 'null' is reserved
236 abort: the name 'null' is reserved
237 [255]
237 [255]
238
238
239
239
240 bookmark with existing name
240 bookmark with existing name
241
241
242 $ hg bookmark X2
242 $ hg bookmark X2
243 abort: bookmark 'X2' already exists (use -f to force)
243 abort: bookmark 'X2' already exists (use -f to force)
244 [255]
244 [255]
245
245
246 $ hg bookmark -m Y Z
246 $ hg bookmark -m Y Z
247 abort: bookmark 'Z' already exists (use -f to force)
247 abort: bookmark 'Z' already exists (use -f to force)
248 [255]
248 [255]
249
249
250 bookmark with name of branch
250 bookmark with name of branch
251
251
252 $ hg bookmark default
252 $ hg bookmark default
253 abort: a bookmark cannot have the name of an existing branch
253 abort: a bookmark cannot have the name of an existing branch
254 [255]
254 [255]
255
255
256 $ hg bookmark -m Y default
256 $ hg bookmark -m Y default
257 abort: a bookmark cannot have the name of an existing branch
257 abort: a bookmark cannot have the name of an existing branch
258 [255]
258 [255]
259
259
260 bookmark with integer name
260 bookmark with integer name
261
261
262 $ hg bookmark 10
262 $ hg bookmark 10
263 abort: cannot use an integer as a name
263 abort: cannot use an integer as a name
264 [255]
264 [255]
265
265
266 incompatible options
266 incompatible options
267
267
268 $ hg bookmark -m Y -d Z
268 $ hg bookmark -m Y -d Z
269 abort: --delete and --rename are incompatible
269 abort: --delete and --rename are incompatible
270 [255]
270 [255]
271
271
272 $ hg bookmark -r 1 -d Z
272 $ hg bookmark -r 1 -d Z
273 abort: --rev is incompatible with --delete
273 abort: --rev is incompatible with --delete
274 [255]
274 [255]
275
275
276 $ hg bookmark -r 1 -m Z Y
276 $ hg bookmark -r 1 -m Z Y
277 abort: --rev is incompatible with --rename
277 abort: --rev is incompatible with --rename
278 [255]
278 [255]
279
279
280 force bookmark with existing name
280 force bookmark with existing name
281
281
282 $ hg bookmark -f X2
282 $ hg bookmark -f X2
283
283
284 force bookmark back to where it was, should deactivate it
284 force bookmark back to where it was, should deactivate it
285
285
286 $ hg bookmark -fr1 X2
286 $ hg bookmark -fr1 X2
287 $ hg bookmarks
287 $ hg bookmarks
288 X2 1:925d80f479bb
288 X2 1:925d80f479bb
289 Y 2:db815d6d32e6
289 Y 2:db815d6d32e6
290 Z 0:f7b1eb17ad24
290 Z 0:f7b1eb17ad24
291 x y 2:db815d6d32e6
291 x y 2:db815d6d32e6
292
292
293 forward bookmark to descendant without --force
293 forward bookmark to descendant without --force
294
294
295 $ hg bookmark Z
295 $ hg bookmark Z
296 moving bookmark 'Z' forward from f7b1eb17ad24
296 moving bookmark 'Z' forward from f7b1eb17ad24
297
297
298 list bookmarks
298 list bookmarks
299
299
300 $ hg bookmark
300 $ hg bookmark
301 X2 1:925d80f479bb
301 X2 1:925d80f479bb
302 Y 2:db815d6d32e6
302 Y 2:db815d6d32e6
303 * Z 2:db815d6d32e6
303 * Z 2:db815d6d32e6
304 x y 2:db815d6d32e6
304 x y 2:db815d6d32e6
305
305
306 revision but no bookmark name
306 revision but no bookmark name
307
307
308 $ hg bookmark -r .
308 $ hg bookmark -r .
309 abort: bookmark name required
309 abort: bookmark name required
310 [255]
310 [255]
311
311
312 bookmark name with whitespace only
312 bookmark name with whitespace only
313
313
314 $ hg bookmark ' '
314 $ hg bookmark ' '
315 abort: bookmark names cannot consist entirely of whitespace
315 abort: bookmark names cannot consist entirely of whitespace
316 [255]
316 [255]
317
317
318 $ hg bookmark -m Y ' '
318 $ hg bookmark -m Y ' '
319 abort: bookmark names cannot consist entirely of whitespace
319 abort: bookmark names cannot consist entirely of whitespace
320 [255]
320 [255]
321
321
322 invalid bookmark
322 invalid bookmark
323
323
324 $ hg bookmark 'foo:bar'
324 $ hg bookmark 'foo:bar'
325 abort: ':' cannot be used in a name
325 abort: ':' cannot be used in a name
326 [255]
326 [255]
327
327
328 $ hg bookmark 'foo
328 $ hg bookmark 'foo
329 > bar'
329 > bar'
330 abort: '\n' cannot be used in a name
330 abort: '\n' cannot be used in a name
331 [255]
331 [255]
332
332
333 the bookmark extension should be ignored now that it is part of core
333 the bookmark extension should be ignored now that it is part of core
334
334
335 $ echo "[extensions]" >> $HGRCPATH
335 $ echo "[extensions]" >> $HGRCPATH
336 $ echo "bookmarks=" >> $HGRCPATH
336 $ echo "bookmarks=" >> $HGRCPATH
337 $ hg bookmarks
337 $ hg bookmarks
338 X2 1:925d80f479bb
338 X2 1:925d80f479bb
339 Y 2:db815d6d32e6
339 Y 2:db815d6d32e6
340 * Z 2:db815d6d32e6
340 * Z 2:db815d6d32e6
341 x y 2:db815d6d32e6
341 x y 2:db815d6d32e6
342
342
343 test summary
343 test summary
344
344
345 $ hg summary
345 $ hg summary
346 parent: 2:db815d6d32e6 tip
346 parent: 2:db815d6d32e6 tip
347 2
347 2
348 branch: default
348 branch: default
349 bookmarks: *Z Y x y
349 bookmarks: *Z Y x y
350 commit: (clean)
350 commit: (clean)
351 update: 1 new changesets, 2 branch heads (merge)
351 update: 1 new changesets, 2 branch heads (merge)
352
352
353 test id
353 test id
354
354
355 $ hg id
355 $ hg id
356 db815d6d32e6 tip Y/Z/x y
356 db815d6d32e6 tip Y/Z/x y
357
357
358 test rollback
358 test rollback
359
359
360 $ echo foo > f1
360 $ echo foo > f1
361 $ hg ci -Amr
361 $ hg ci -Amr
362 adding f1
362 adding f1
363 $ hg bookmark -f Y -r 1
363 $ hg bookmark -f Y -r 1
364 $ hg bookmark -f Z -r 1
364 $ hg bookmark -f Z -r 1
365 $ hg rollback
365 $ hg rollback
366 repository tip rolled back to revision 2 (undo commit)
366 repository tip rolled back to revision 2 (undo commit)
367 working directory now based on revision 2
367 working directory now based on revision 2
368 $ hg bookmarks
368 $ hg bookmarks
369 X2 1:925d80f479bb
369 X2 1:925d80f479bb
370 Y 2:db815d6d32e6
370 Y 2:db815d6d32e6
371 Z 2:db815d6d32e6
371 Z 2:db815d6d32e6
372 x y 2:db815d6d32e6
372 x y 2:db815d6d32e6
373
373
374 activate bookmark on working dir parent without --force
374 activate bookmark on working dir parent without --force
375
375
376 $ hg bookmark --inactive Z
376 $ hg bookmark --inactive Z
377 $ hg bookmark Z
377 $ hg bookmark Z
378
378
379 test clone
379 test clone
380
380
381 $ hg bookmark -r 2 -i @
381 $ hg bookmark -r 2 -i @
382 $ hg bookmark -r 2 -i a@
382 $ hg bookmark -r 2 -i a@
383 $ hg bookmarks
383 $ hg bookmarks
384 @ 2:db815d6d32e6
384 @ 2:db815d6d32e6
385 X2 1:925d80f479bb
385 X2 1:925d80f479bb
386 Y 2:db815d6d32e6
386 Y 2:db815d6d32e6
387 * Z 2:db815d6d32e6
387 * Z 2:db815d6d32e6
388 a@ 2:db815d6d32e6
388 a@ 2:db815d6d32e6
389 x y 2:db815d6d32e6
389 x y 2:db815d6d32e6
390 $ hg clone . cloned-bookmarks
390 $ hg clone . cloned-bookmarks
391 updating to bookmark @
391 updating to bookmark @
392 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
393 $ hg -R cloned-bookmarks bookmarks
393 $ hg -R cloned-bookmarks bookmarks
394 * @ 2:db815d6d32e6
394 * @ 2:db815d6d32e6
395 X2 1:925d80f479bb
395 X2 1:925d80f479bb
396 Y 2:db815d6d32e6
396 Y 2:db815d6d32e6
397 Z 2:db815d6d32e6
397 Z 2:db815d6d32e6
398 a@ 2:db815d6d32e6
398 a@ 2:db815d6d32e6
399 x y 2:db815d6d32e6
399 x y 2:db815d6d32e6
400
400
401 test clone with pull protocol
401 test clone with pull protocol
402
402
403 $ hg clone --pull . cloned-bookmarks-pull
403 $ hg clone --pull . cloned-bookmarks-pull
404 requesting all changes
404 requesting all changes
405 adding changesets
405 adding changesets
406 adding manifests
406 adding manifests
407 adding file changes
407 adding file changes
408 added 3 changesets with 3 changes to 3 files (+1 heads)
408 added 3 changesets with 3 changes to 3 files (+1 heads)
409 updating to bookmark @
409 updating to bookmark @
410 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 $ hg -R cloned-bookmarks-pull bookmarks
411 $ hg -R cloned-bookmarks-pull bookmarks
412 * @ 2:db815d6d32e6
412 * @ 2:db815d6d32e6
413 X2 1:925d80f479bb
413 X2 1:925d80f479bb
414 Y 2:db815d6d32e6
414 Y 2:db815d6d32e6
415 Z 2:db815d6d32e6
415 Z 2:db815d6d32e6
416 a@ 2:db815d6d32e6
416 a@ 2:db815d6d32e6
417 x y 2:db815d6d32e6
417 x y 2:db815d6d32e6
418
418
419 $ hg bookmark -d @
419 $ hg bookmark -d @
420 $ hg bookmark -d a@
420 $ hg bookmark -d a@
421
421
422 test clone with a bookmark named "default" (issue3677)
422 test clone with a bookmark named "default" (issue3677)
423
423
424 $ hg bookmark -r 1 -f -i default
424 $ hg bookmark -r 1 -f -i default
425 $ hg clone . cloned-bookmark-default
425 $ hg clone . cloned-bookmark-default
426 updating to branch default
426 updating to branch default
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 $ hg -R cloned-bookmark-default bookmarks
428 $ hg -R cloned-bookmark-default bookmarks
429 X2 1:925d80f479bb
429 X2 1:925d80f479bb
430 Y 2:db815d6d32e6
430 Y 2:db815d6d32e6
431 Z 2:db815d6d32e6
431 Z 2:db815d6d32e6
432 default 1:925d80f479bb
432 default 1:925d80f479bb
433 x y 2:db815d6d32e6
433 x y 2:db815d6d32e6
434 $ hg -R cloned-bookmark-default parents -q
434 $ hg -R cloned-bookmark-default parents -q
435 2:db815d6d32e6
435 2:db815d6d32e6
436 $ hg bookmark -d default
436 $ hg bookmark -d default
437
437
438 test clone with a specific revision
438 test clone with a specific revision
439
439
440 $ hg clone -r 925d80 . cloned-bookmarks-rev
440 $ hg clone -r 925d80 . cloned-bookmarks-rev
441 adding changesets
441 adding changesets
442 adding manifests
442 adding manifests
443 adding file changes
443 adding file changes
444 added 2 changesets with 2 changes to 2 files
444 added 2 changesets with 2 changes to 2 files
445 updating to branch default
445 updating to branch default
446 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
446 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 $ hg -R cloned-bookmarks-rev bookmarks
447 $ hg -R cloned-bookmarks-rev bookmarks
448 X2 1:925d80f479bb
448 X2 1:925d80f479bb
449
449
450 test clone with update to a bookmark
450 test clone with update to a bookmark
451
451
452 $ hg clone -u Z . cloned-bookmarks-update
452 $ hg clone -u Z . cloned-bookmarks-update
453 updating to branch default
453 updating to branch default
454 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
454 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 $ hg -R cloned-bookmarks-update bookmarks
455 $ hg -R cloned-bookmarks-update bookmarks
456 X2 1:925d80f479bb
456 X2 1:925d80f479bb
457 Y 2:db815d6d32e6
457 Y 2:db815d6d32e6
458 * Z 2:db815d6d32e6
458 * Z 2:db815d6d32e6
459 x y 2:db815d6d32e6
459 x y 2:db815d6d32e6
460
460
461 create bundle with two heads
461 create bundle with two heads
462
462
463 $ hg clone . tobundle
463 $ hg clone . tobundle
464 updating to branch default
464 updating to branch default
465 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
465 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 $ echo x > tobundle/x
466 $ echo x > tobundle/x
467 $ hg -R tobundle add tobundle/x
467 $ hg -R tobundle add tobundle/x
468 $ hg -R tobundle commit -m'x'
468 $ hg -R tobundle commit -m'x'
469 $ hg -R tobundle update -r -2
469 $ hg -R tobundle update -r -2
470 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
470 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
471 $ echo y > tobundle/y
471 $ echo y > tobundle/y
472 $ hg -R tobundle branch test
472 $ hg -R tobundle branch test
473 marked working directory as branch test
473 marked working directory as branch test
474 (branches are permanent and global, did you want a bookmark?)
474 (branches are permanent and global, did you want a bookmark?)
475 $ hg -R tobundle add tobundle/y
475 $ hg -R tobundle add tobundle/y
476 $ hg -R tobundle commit -m'y'
476 $ hg -R tobundle commit -m'y'
477 $ hg -R tobundle bundle tobundle.hg
477 $ hg -R tobundle bundle tobundle.hg
478 searching for changes
478 searching for changes
479 2 changesets found
479 2 changesets found
480 $ hg unbundle tobundle.hg
480 $ hg unbundle tobundle.hg
481 adding changesets
481 adding changesets
482 adding manifests
482 adding manifests
483 adding file changes
483 adding file changes
484 added 2 changesets with 2 changes to 2 files (+1 heads)
484 added 2 changesets with 2 changes to 2 files (+1 heads)
485 (run 'hg heads' to see heads, 'hg merge' to merge)
485 (run 'hg heads' to see heads, 'hg merge' to merge)
486
486
487 update to current bookmark if it's not the parent
487 update to current bookmark if it's not the parent
488
488
489 $ hg summary
489 $ hg summary
490 parent: 2:db815d6d32e6
490 parent: 2:db815d6d32e6
491 2
491 2
492 branch: default
492 branch: default
493 bookmarks: [Z] Y x y
493 bookmarks: [Z] Y x y
494 commit: 1 added, 1 unknown (new branch head)
494 commit: 1 added, 1 unknown (new branch head)
495 update: 2 new changesets (update)
495 update: 2 new changesets (update)
496 $ hg update
496 $ hg update
497 updating to active bookmark Z
497 updating to active bookmark Z
498 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 $ hg bookmarks
499 $ hg bookmarks
500 X2 1:925d80f479bb
500 X2 1:925d80f479bb
501 Y 2:db815d6d32e6
501 Y 2:db815d6d32e6
502 * Z 3:125c9a1d6df6
502 * Z 3:125c9a1d6df6
503 x y 2:db815d6d32e6
503 x y 2:db815d6d32e6
504
504
505 test wrongly formated bookmark
505 test wrongly formated bookmark
506
506
507 $ echo '' >> .hg/bookmarks
507 $ echo '' >> .hg/bookmarks
508 $ hg bookmarks
508 $ hg bookmarks
509 X2 1:925d80f479bb
509 X2 1:925d80f479bb
510 Y 2:db815d6d32e6
510 Y 2:db815d6d32e6
511 * Z 3:125c9a1d6df6
511 * Z 3:125c9a1d6df6
512 x y 2:db815d6d32e6
512 x y 2:db815d6d32e6
513 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
513 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
514 $ hg bookmarks
514 $ hg bookmarks
515 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
515 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
516 X2 1:925d80f479bb
516 X2 1:925d80f479bb
517 Y 2:db815d6d32e6
517 Y 2:db815d6d32e6
518 * Z 3:125c9a1d6df6
518 * Z 3:125c9a1d6df6
519 x y 2:db815d6d32e6
519 x y 2:db815d6d32e6
520
520
521 test missing revisions
521 test missing revisions
522
522
523 $ echo "925d80f479bc z" > .hg/bookmarks
523 $ echo "925d80f479bc z" > .hg/bookmarks
524 $ hg book
524 $ hg book
525 no bookmarks set
525 no bookmarks set
526
526
527 test stripping a non-checked-out but bookmarked revision
527 test stripping a non-checked-out but bookmarked revision
528
528
529 $ hg --config extensions.graphlog= log --graph
529 $ hg --config extensions.graphlog= log --graph
530 o changeset: 4:9ba5f110a0b3
530 o changeset: 4:9ba5f110a0b3
531 | branch: test
531 | branch: test
532 | tag: tip
532 | tag: tip
533 | parent: 2:db815d6d32e6
533 | parent: 2:db815d6d32e6
534 | user: test
534 | user: test
535 | date: Thu Jan 01 00:00:00 1970 +0000
535 | date: Thu Jan 01 00:00:00 1970 +0000
536 | summary: y
536 | summary: y
537 |
537 |
538 | @ changeset: 3:125c9a1d6df6
538 | @ changeset: 3:125c9a1d6df6
539 |/ user: test
539 |/ user: test
540 | date: Thu Jan 01 00:00:00 1970 +0000
540 | date: Thu Jan 01 00:00:00 1970 +0000
541 | summary: x
541 | summary: x
542 |
542 |
543 o changeset: 2:db815d6d32e6
543 o changeset: 2:db815d6d32e6
544 | parent: 0:f7b1eb17ad24
544 | parent: 0:f7b1eb17ad24
545 | user: test
545 | user: test
546 | date: Thu Jan 01 00:00:00 1970 +0000
546 | date: Thu Jan 01 00:00:00 1970 +0000
547 | summary: 2
547 | summary: 2
548 |
548 |
549 | o changeset: 1:925d80f479bb
549 | o changeset: 1:925d80f479bb
550 |/ user: test
550 |/ user: test
551 | date: Thu Jan 01 00:00:00 1970 +0000
551 | date: Thu Jan 01 00:00:00 1970 +0000
552 | summary: 1
552 | summary: 1
553 |
553 |
554 o changeset: 0:f7b1eb17ad24
554 o changeset: 0:f7b1eb17ad24
555 user: test
555 user: test
556 date: Thu Jan 01 00:00:00 1970 +0000
556 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 0
557 summary: 0
558
558
559 $ hg book should-end-on-two
559 $ hg book should-end-on-two
560 $ hg co --clean 4
560 $ hg co --clean 4
561 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
561 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
562 $ hg book four
562 $ hg book four
563 $ hg --config extensions.mq= strip 3
563 $ hg --config extensions.mq= strip 3
564 saved backup bundle to * (glob)
564 saved backup bundle to * (glob)
565 should-end-on-two should end up pointing to revision 2, as that's the
565 should-end-on-two should end up pointing to revision 2, as that's the
566 tipmost surviving ancestor of the stripped revision.
566 tipmost surviving ancestor of the stripped revision.
567 $ hg --config extensions.graphlog= log --graph
567 $ hg --config extensions.graphlog= log --graph
568 @ changeset: 3:9ba5f110a0b3
568 @ changeset: 3:9ba5f110a0b3
569 | branch: test
569 | branch: test
570 | bookmark: four
570 | bookmark: four
571 | tag: tip
571 | tag: tip
572 | user: test
572 | user: test
573 | date: Thu Jan 01 00:00:00 1970 +0000
573 | date: Thu Jan 01 00:00:00 1970 +0000
574 | summary: y
574 | summary: y
575 |
575 |
576 o changeset: 2:db815d6d32e6
576 o changeset: 2:db815d6d32e6
577 | bookmark: should-end-on-two
577 | bookmark: should-end-on-two
578 | parent: 0:f7b1eb17ad24
578 | parent: 0:f7b1eb17ad24
579 | user: test
579 | user: test
580 | date: Thu Jan 01 00:00:00 1970 +0000
580 | date: Thu Jan 01 00:00:00 1970 +0000
581 | summary: 2
581 | summary: 2
582 |
582 |
583 | o changeset: 1:925d80f479bb
583 | o changeset: 1:925d80f479bb
584 |/ user: test
584 |/ user: test
585 | date: Thu Jan 01 00:00:00 1970 +0000
585 | date: Thu Jan 01 00:00:00 1970 +0000
586 | summary: 1
586 | summary: 1
587 |
587 |
588 o changeset: 0:f7b1eb17ad24
588 o changeset: 0:f7b1eb17ad24
589 user: test
589 user: test
590 date: Thu Jan 01 00:00:00 1970 +0000
590 date: Thu Jan 01 00:00:00 1970 +0000
591 summary: 0
591 summary: 0
592
592
593
594 test clearing divergent bookmarks of linear ancestors
595
596 $ hg bookmark Z -r 0
597 $ hg bookmark Z@1 -r 1
598 $ hg bookmark Z@2 -r 2
599 $ hg bookmark Z@3 -r 3
600 $ hg book
601 Z 0:f7b1eb17ad24
602 Z@1 1:925d80f479bb
603 Z@2 2:db815d6d32e6
604 * Z@3 3:9ba5f110a0b3
605 four 3:9ba5f110a0b3
606 should-end-on-two 2:db815d6d32e6
607 $ hg bookmark Z
608 moving bookmark 'Z' forward from f7b1eb17ad24
609 $ hg book
610 * Z 3:9ba5f110a0b3
611 Z@1 1:925d80f479bb
612 four 3:9ba5f110a0b3
613 should-end-on-two 2:db815d6d32e6
General Comments 0
You need to be logged in to leave comments. Login now