##// END OF EJS Templates
backout: use "getcommiteditor()" instead of explicit editor choice...
FUJIWARA Katsunori -
r21413:edc55317 default
parent child Browse files
Show More
@@ -1,5948 +1,5948 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 sys
12 import sys
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 from hgweb import server as hgweb_server
17 from hgweb import server as hgweb_server
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod
20 import dagparser, context, simplemerge, graphmod
21 import random
21 import random
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import phases, obsolete, exchange
23 import phases, obsolete, exchange
24
24
25 table = {}
25 table = {}
26
26
27 command = cmdutil.command(table)
27 command = cmdutil.command(table)
28
28
29 # common command options
29 # common command options
30
30
31 globalopts = [
31 globalopts = [
32 ('R', 'repository', '',
32 ('R', 'repository', '',
33 _('repository root directory or name of overlay bundle file'),
33 _('repository root directory or name of overlay bundle file'),
34 _('REPO')),
34 _('REPO')),
35 ('', 'cwd', '',
35 ('', 'cwd', '',
36 _('change working directory'), _('DIR')),
36 _('change working directory'), _('DIR')),
37 ('y', 'noninteractive', None,
37 ('y', 'noninteractive', None,
38 _('do not prompt, automatically pick the first choice for all prompts')),
38 _('do not prompt, automatically pick the first choice for all prompts')),
39 ('q', 'quiet', None, _('suppress output')),
39 ('q', 'quiet', None, _('suppress output')),
40 ('v', 'verbose', None, _('enable additional output')),
40 ('v', 'verbose', None, _('enable additional output')),
41 ('', 'config', [],
41 ('', 'config', [],
42 _('set/override config option (use \'section.name=value\')'),
42 _('set/override config option (use \'section.name=value\')'),
43 _('CONFIG')),
43 _('CONFIG')),
44 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debug', None, _('enable debugging output')),
45 ('', 'debugger', None, _('start debugger')),
45 ('', 'debugger', None, _('start debugger')),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
47 _('ENCODE')),
47 _('ENCODE')),
48 ('', 'encodingmode', encoding.encodingmode,
48 ('', 'encodingmode', encoding.encodingmode,
49 _('set the charset encoding mode'), _('MODE')),
49 _('set the charset encoding mode'), _('MODE')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'traceback', None, _('always print a traceback on exception')),
51 ('', 'time', None, _('time how long the command takes')),
51 ('', 'time', None, _('time how long the command takes')),
52 ('', 'profile', None, _('print command execution profile')),
52 ('', 'profile', None, _('print command execution profile')),
53 ('', 'version', None, _('output version information and exit')),
53 ('', 'version', None, _('output version information and exit')),
54 ('h', 'help', None, _('display help and exit')),
54 ('h', 'help', None, _('display help and exit')),
55 ('', 'hidden', False, _('consider hidden changesets')),
55 ('', 'hidden', False, _('consider hidden changesets')),
56 ]
56 ]
57
57
58 dryrunopts = [('n', 'dry-run', None,
58 dryrunopts = [('n', 'dry-run', None,
59 _('do not perform actions, just print output'))]
59 _('do not perform actions, just print output'))]
60
60
61 remoteopts = [
61 remoteopts = [
62 ('e', 'ssh', '',
62 ('e', 'ssh', '',
63 _('specify ssh command to use'), _('CMD')),
63 _('specify ssh command to use'), _('CMD')),
64 ('', 'remotecmd', '',
64 ('', 'remotecmd', '',
65 _('specify hg command to run on the remote side'), _('CMD')),
65 _('specify hg command to run on the remote side'), _('CMD')),
66 ('', 'insecure', None,
66 ('', 'insecure', None,
67 _('do not verify server certificate (ignoring web.cacerts config)')),
67 _('do not verify server certificate (ignoring web.cacerts config)')),
68 ]
68 ]
69
69
70 walkopts = [
70 walkopts = [
71 ('I', 'include', [],
71 ('I', 'include', [],
72 _('include names matching the given patterns'), _('PATTERN')),
72 _('include names matching the given patterns'), _('PATTERN')),
73 ('X', 'exclude', [],
73 ('X', 'exclude', [],
74 _('exclude names matching the given patterns'), _('PATTERN')),
74 _('exclude names matching the given patterns'), _('PATTERN')),
75 ]
75 ]
76
76
77 commitopts = [
77 commitopts = [
78 ('m', 'message', '',
78 ('m', 'message', '',
79 _('use text as commit message'), _('TEXT')),
79 _('use text as commit message'), _('TEXT')),
80 ('l', 'logfile', '',
80 ('l', 'logfile', '',
81 _('read commit message from file'), _('FILE')),
81 _('read commit message from file'), _('FILE')),
82 ]
82 ]
83
83
84 commitopts2 = [
84 commitopts2 = [
85 ('d', 'date', '',
85 ('d', 'date', '',
86 _('record the specified date as commit date'), _('DATE')),
86 _('record the specified date as commit date'), _('DATE')),
87 ('u', 'user', '',
87 ('u', 'user', '',
88 _('record the specified user as committer'), _('USER')),
88 _('record the specified user as committer'), _('USER')),
89 ]
89 ]
90
90
91 templateopts = [
91 templateopts = [
92 ('', 'style', '',
92 ('', 'style', '',
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
93 _('display using template map file (DEPRECATED)'), _('STYLE')),
94 ('T', 'template', '',
94 ('T', 'template', '',
95 _('display with template'), _('TEMPLATE')),
95 _('display with template'), _('TEMPLATE')),
96 ]
96 ]
97
97
98 logopts = [
98 logopts = [
99 ('p', 'patch', None, _('show patch')),
99 ('p', 'patch', None, _('show patch')),
100 ('g', 'git', None, _('use git extended diff format')),
100 ('g', 'git', None, _('use git extended diff format')),
101 ('l', 'limit', '',
101 ('l', 'limit', '',
102 _('limit number of changes displayed'), _('NUM')),
102 _('limit number of changes displayed'), _('NUM')),
103 ('M', 'no-merges', None, _('do not show merges')),
103 ('M', 'no-merges', None, _('do not show merges')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('', 'stat', None, _('output diffstat-style summary of changes')),
105 ('G', 'graph', None, _("show the revision DAG")),
105 ('G', 'graph', None, _("show the revision DAG")),
106 ] + templateopts
106 ] + templateopts
107
107
108 diffopts = [
108 diffopts = [
109 ('a', 'text', None, _('treat all files as text')),
109 ('a', 'text', None, _('treat all files as text')),
110 ('g', 'git', None, _('use git extended diff format')),
110 ('g', 'git', None, _('use git extended diff format')),
111 ('', 'nodates', None, _('omit dates from diff headers'))
111 ('', 'nodates', None, _('omit dates from diff headers'))
112 ]
112 ]
113
113
114 diffwsopts = [
114 diffwsopts = [
115 ('w', 'ignore-all-space', None,
115 ('w', 'ignore-all-space', None,
116 _('ignore white space when comparing lines')),
116 _('ignore white space when comparing lines')),
117 ('b', 'ignore-space-change', None,
117 ('b', 'ignore-space-change', None,
118 _('ignore changes in the amount of white space')),
118 _('ignore changes in the amount of white space')),
119 ('B', 'ignore-blank-lines', None,
119 ('B', 'ignore-blank-lines', None,
120 _('ignore changes whose lines are all blank')),
120 _('ignore changes whose lines are all blank')),
121 ]
121 ]
122
122
123 diffopts2 = [
123 diffopts2 = [
124 ('p', 'show-function', None, _('show which function each change is in')),
124 ('p', 'show-function', None, _('show which function each change is in')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ('', 'reverse', None, _('produce a diff that undoes the changes')),
126 ] + diffwsopts + [
126 ] + diffwsopts + [
127 ('U', 'unified', '',
127 ('U', 'unified', '',
128 _('number of lines of context to show'), _('NUM')),
128 _('number of lines of context to show'), _('NUM')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ('', 'stat', None, _('output diffstat-style summary of changes')),
130 ]
130 ]
131
131
132 mergetoolopts = [
132 mergetoolopts = [
133 ('t', 'tool', '', _('specify merge tool')),
133 ('t', 'tool', '', _('specify merge tool')),
134 ]
134 ]
135
135
136 similarityopts = [
136 similarityopts = [
137 ('s', 'similarity', '',
137 ('s', 'similarity', '',
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
139 ]
139 ]
140
140
141 subrepoopts = [
141 subrepoopts = [
142 ('S', 'subrepos', None,
142 ('S', 'subrepos', None,
143 _('recurse into subrepositories'))
143 _('recurse into subrepositories'))
144 ]
144 ]
145
145
146 # Commands start here, listed alphabetically
146 # Commands start here, listed alphabetically
147
147
148 @command('^add',
148 @command('^add',
149 walkopts + subrepoopts + dryrunopts,
149 walkopts + subrepoopts + dryrunopts,
150 _('[OPTION]... [FILE]...'))
150 _('[OPTION]... [FILE]...'))
151 def add(ui, repo, *pats, **opts):
151 def add(ui, repo, *pats, **opts):
152 """add the specified files on the next commit
152 """add the specified files on the next commit
153
153
154 Schedule files to be version controlled and added to the
154 Schedule files to be version controlled and added to the
155 repository.
155 repository.
156
156
157 The files will be added to the repository at the next commit. To
157 The files will be added to the repository at the next commit. To
158 undo an add before that, see :hg:`forget`.
158 undo an add before that, see :hg:`forget`.
159
159
160 If no names are given, add all files to the repository.
160 If no names are given, add all files to the repository.
161
161
162 .. container:: verbose
162 .. container:: verbose
163
163
164 An example showing how new (unknown) files are added
164 An example showing how new (unknown) files are added
165 automatically by :hg:`add`::
165 automatically by :hg:`add`::
166
166
167 $ ls
167 $ ls
168 foo.c
168 foo.c
169 $ hg status
169 $ hg status
170 ? foo.c
170 ? foo.c
171 $ hg add
171 $ hg add
172 adding foo.c
172 adding foo.c
173 $ hg status
173 $ hg status
174 A foo.c
174 A foo.c
175
175
176 Returns 0 if all files are successfully added.
176 Returns 0 if all files are successfully added.
177 """
177 """
178
178
179 m = scmutil.match(repo[None], pats, opts)
179 m = scmutil.match(repo[None], pats, opts)
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
181 opts.get('subrepos'), prefix="", explicitonly=False)
181 opts.get('subrepos'), prefix="", explicitonly=False)
182 return rejected and 1 or 0
182 return rejected and 1 or 0
183
183
184 @command('addremove',
184 @command('addremove',
185 similarityopts + walkopts + dryrunopts,
185 similarityopts + walkopts + dryrunopts,
186 _('[OPTION]... [FILE]...'))
186 _('[OPTION]... [FILE]...'))
187 def addremove(ui, repo, *pats, **opts):
187 def addremove(ui, repo, *pats, **opts):
188 """add all new files, delete all missing files
188 """add all new files, delete all missing files
189
189
190 Add all new files and remove all missing files from the
190 Add all new files and remove all missing files from the
191 repository.
191 repository.
192
192
193 New files are ignored if they match any of the patterns in
193 New files are ignored if they match any of the patterns in
194 ``.hgignore``. As with add, these changes take effect at the next
194 ``.hgignore``. As with add, these changes take effect at the next
195 commit.
195 commit.
196
196
197 Use the -s/--similarity option to detect renamed files. This
197 Use the -s/--similarity option to detect renamed files. This
198 option takes a percentage between 0 (disabled) and 100 (files must
198 option takes a percentage between 0 (disabled) and 100 (files must
199 be identical) as its parameter. With a parameter greater than 0,
199 be identical) as its parameter. With a parameter greater than 0,
200 this compares every removed file with every added file and records
200 this compares every removed file with every added file and records
201 those similar enough as renames. Detecting renamed files this way
201 those similar enough as renames. Detecting renamed files this way
202 can be expensive. After using this option, :hg:`status -C` can be
202 can be expensive. After using this option, :hg:`status -C` can be
203 used to check which files were identified as moved or renamed. If
203 used to check which files were identified as moved or renamed. If
204 not specified, -s/--similarity defaults to 100 and only renames of
204 not specified, -s/--similarity defaults to 100 and only renames of
205 identical files are detected.
205 identical files are detected.
206
206
207 Returns 0 if all files are successfully added.
207 Returns 0 if all files are successfully added.
208 """
208 """
209 try:
209 try:
210 sim = float(opts.get('similarity') or 100)
210 sim = float(opts.get('similarity') or 100)
211 except ValueError:
211 except ValueError:
212 raise util.Abort(_('similarity must be a number'))
212 raise util.Abort(_('similarity must be a number'))
213 if sim < 0 or sim > 100:
213 if sim < 0 or sim > 100:
214 raise util.Abort(_('similarity must be between 0 and 100'))
214 raise util.Abort(_('similarity must be between 0 and 100'))
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
216
216
217 @command('^annotate|blame',
217 @command('^annotate|blame',
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
219 ('', 'follow', None,
219 ('', 'follow', None,
220 _('follow copies/renames and list the filename (DEPRECATED)')),
220 _('follow copies/renames and list the filename (DEPRECATED)')),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('', 'no-follow', None, _("don't follow copies and renames")),
222 ('a', 'text', None, _('treat all files as text')),
222 ('a', 'text', None, _('treat all files as text')),
223 ('u', 'user', None, _('list the author (long with -v)')),
223 ('u', 'user', None, _('list the author (long with -v)')),
224 ('f', 'file', None, _('list the filename')),
224 ('f', 'file', None, _('list the filename')),
225 ('d', 'date', None, _('list the date (short with -q)')),
225 ('d', 'date', None, _('list the date (short with -q)')),
226 ('n', 'number', None, _('list the revision number (default)')),
226 ('n', 'number', None, _('list the revision number (default)')),
227 ('c', 'changeset', None, _('list the changeset')),
227 ('c', 'changeset', None, _('list the changeset')),
228 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ('l', 'line-number', None, _('show line number at the first appearance'))
229 ] + diffwsopts + walkopts,
229 ] + diffwsopts + walkopts,
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
231 def annotate(ui, repo, *pats, **opts):
231 def annotate(ui, repo, *pats, **opts):
232 """show changeset information by line for each file
232 """show changeset information by line for each file
233
233
234 List changes in files, showing the revision id responsible for
234 List changes in files, showing the revision id responsible for
235 each line
235 each line
236
236
237 This command is useful for discovering when a change was made and
237 This command is useful for discovering when a change was made and
238 by whom.
238 by whom.
239
239
240 Without the -a/--text option, annotate will avoid processing files
240 Without the -a/--text option, annotate will avoid processing files
241 it detects as binary. With -a, annotate will annotate the file
241 it detects as binary. With -a, annotate will annotate the file
242 anyway, although the results will probably be neither useful
242 anyway, although the results will probably be neither useful
243 nor desirable.
243 nor desirable.
244
244
245 Returns 0 on success.
245 Returns 0 on success.
246 """
246 """
247 if opts.get('follow'):
247 if opts.get('follow'):
248 # --follow is deprecated and now just an alias for -f/--file
248 # --follow is deprecated and now just an alias for -f/--file
249 # to mimic the behavior of Mercurial before version 1.5
249 # to mimic the behavior of Mercurial before version 1.5
250 opts['file'] = True
250 opts['file'] = True
251
251
252 datefunc = ui.quiet and util.shortdate or util.datestr
252 datefunc = ui.quiet and util.shortdate or util.datestr
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
254
254
255 if not pats:
255 if not pats:
256 raise util.Abort(_('at least one filename or pattern is required'))
256 raise util.Abort(_('at least one filename or pattern is required'))
257
257
258 hexfn = ui.debugflag and hex or short
258 hexfn = ui.debugflag and hex or short
259
259
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
261 ('number', ' ', lambda x: str(x[0].rev())),
261 ('number', ' ', lambda x: str(x[0].rev())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('changeset', ' ', lambda x: hexfn(x[0].node())),
263 ('date', ' ', getdate),
263 ('date', ' ', getdate),
264 ('file', ' ', lambda x: x[0].path()),
264 ('file', ' ', lambda x: x[0].path()),
265 ('line_number', ':', lambda x: str(x[1])),
265 ('line_number', ':', lambda x: str(x[1])),
266 ]
266 ]
267
267
268 if (not opts.get('user') and not opts.get('changeset')
268 if (not opts.get('user') and not opts.get('changeset')
269 and not opts.get('date') and not opts.get('file')):
269 and not opts.get('date') and not opts.get('file')):
270 opts['number'] = True
270 opts['number'] = True
271
271
272 linenumber = opts.get('line_number') is not None
272 linenumber = opts.get('line_number') is not None
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
274 raise util.Abort(_('at least one of -n/-c is required for -l'))
275
275
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
278
278
279 def bad(x, y):
279 def bad(x, y):
280 raise util.Abort("%s: %s" % (x, y))
280 raise util.Abort("%s: %s" % (x, y))
281
281
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 m = scmutil.match(ctx, pats, opts)
283 m = scmutil.match(ctx, pats, opts)
284 m.bad = bad
284 m.bad = bad
285 follow = not opts.get('no_follow')
285 follow = not opts.get('no_follow')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
286 diffopts = patch.diffopts(ui, opts, section='annotate')
287 for abs in ctx.walk(m):
287 for abs in ctx.walk(m):
288 fctx = ctx[abs]
288 fctx = ctx[abs]
289 if not opts.get('text') and util.binary(fctx.data()):
289 if not opts.get('text') and util.binary(fctx.data()):
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
291 continue
291 continue
292
292
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 lines = fctx.annotate(follow=follow, linenumber=linenumber,
294 diffopts=diffopts)
294 diffopts=diffopts)
295 pieces = []
295 pieces = []
296
296
297 for f, sep in funcmap:
297 for f, sep in funcmap:
298 l = [f(n) for n, dummy in lines]
298 l = [f(n) for n, dummy in lines]
299 if l:
299 if l:
300 sized = [(x, encoding.colwidth(x)) for x in l]
300 sized = [(x, encoding.colwidth(x)) for x in l]
301 ml = max([w for x, w in sized])
301 ml = max([w for x, w in sized])
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
303 for x, w in sized])
303 for x, w in sized])
304
304
305 if pieces:
305 if pieces:
306 for p, l in zip(zip(*pieces), lines):
306 for p, l in zip(zip(*pieces), lines):
307 ui.write("%s: %s" % ("".join(p), l[1]))
307 ui.write("%s: %s" % ("".join(p), l[1]))
308
308
309 if lines and not lines[-1][1].endswith('\n'):
309 if lines and not lines[-1][1].endswith('\n'):
310 ui.write('\n')
310 ui.write('\n')
311
311
312 @command('archive',
312 @command('archive',
313 [('', 'no-decode', None, _('do not pass files through decoders')),
313 [('', 'no-decode', None, _('do not pass files through decoders')),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 ('p', 'prefix', '', _('directory prefix for files in archive'),
315 _('PREFIX')),
315 _('PREFIX')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('r', 'rev', '', _('revision to distribute'), _('REV')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
318 ] + subrepoopts + walkopts,
318 ] + subrepoopts + walkopts,
319 _('[OPTION]... DEST'))
319 _('[OPTION]... DEST'))
320 def archive(ui, repo, dest, **opts):
320 def archive(ui, repo, dest, **opts):
321 '''create an unversioned archive of a repository revision
321 '''create an unversioned archive of a repository revision
322
322
323 By default, the revision used is the parent of the working
323 By default, the revision used is the parent of the working
324 directory; use -r/--rev to specify a different revision.
324 directory; use -r/--rev to specify a different revision.
325
325
326 The archive type is automatically detected based on file
326 The archive type is automatically detected based on file
327 extension (or override using -t/--type).
327 extension (or override using -t/--type).
328
328
329 .. container:: verbose
329 .. container:: verbose
330
330
331 Examples:
331 Examples:
332
332
333 - create a zip file containing the 1.0 release::
333 - create a zip file containing the 1.0 release::
334
334
335 hg archive -r 1.0 project-1.0.zip
335 hg archive -r 1.0 project-1.0.zip
336
336
337 - create a tarball excluding .hg files::
337 - create a tarball excluding .hg files::
338
338
339 hg archive project.tar.gz -X ".hg*"
339 hg archive project.tar.gz -X ".hg*"
340
340
341 Valid types are:
341 Valid types are:
342
342
343 :``files``: a directory full of files (default)
343 :``files``: a directory full of files (default)
344 :``tar``: tar archive, uncompressed
344 :``tar``: tar archive, uncompressed
345 :``tbz2``: tar archive, compressed using bzip2
345 :``tbz2``: tar archive, compressed using bzip2
346 :``tgz``: tar archive, compressed using gzip
346 :``tgz``: tar archive, compressed using gzip
347 :``uzip``: zip archive, uncompressed
347 :``uzip``: zip archive, uncompressed
348 :``zip``: zip archive, compressed using deflate
348 :``zip``: zip archive, compressed using deflate
349
349
350 The exact name of the destination archive or directory is given
350 The exact name of the destination archive or directory is given
351 using a format string; see :hg:`help export` for details.
351 using a format string; see :hg:`help export` for details.
352
352
353 Each member added to an archive file has a directory prefix
353 Each member added to an archive file has a directory prefix
354 prepended. Use -p/--prefix to specify a format string for the
354 prepended. Use -p/--prefix to specify a format string for the
355 prefix. The default is the basename of the archive, with suffixes
355 prefix. The default is the basename of the archive, with suffixes
356 removed.
356 removed.
357
357
358 Returns 0 on success.
358 Returns 0 on success.
359 '''
359 '''
360
360
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 ctx = scmutil.revsingle(repo, opts.get('rev'))
362 if not ctx:
362 if not ctx:
363 raise util.Abort(_('no working directory: please specify a revision'))
363 raise util.Abort(_('no working directory: please specify a revision'))
364 node = ctx.node()
364 node = ctx.node()
365 dest = cmdutil.makefilename(repo, dest, node)
365 dest = cmdutil.makefilename(repo, dest, node)
366 if os.path.realpath(dest) == repo.root:
366 if os.path.realpath(dest) == repo.root:
367 raise util.Abort(_('repository root cannot be destination'))
367 raise util.Abort(_('repository root cannot be destination'))
368
368
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 kind = opts.get('type') or archival.guesskind(dest) or 'files'
370 prefix = opts.get('prefix')
370 prefix = opts.get('prefix')
371
371
372 if dest == '-':
372 if dest == '-':
373 if kind == 'files':
373 if kind == 'files':
374 raise util.Abort(_('cannot archive plain files to stdout'))
374 raise util.Abort(_('cannot archive plain files to stdout'))
375 dest = cmdutil.makefileobj(repo, dest)
375 dest = cmdutil.makefileobj(repo, dest)
376 if not prefix:
376 if not prefix:
377 prefix = os.path.basename(repo.root) + '-%h'
377 prefix = os.path.basename(repo.root) + '-%h'
378
378
379 prefix = cmdutil.makefilename(repo, prefix, node)
379 prefix = cmdutil.makefilename(repo, prefix, node)
380 matchfn = scmutil.match(ctx, [], opts)
380 matchfn = scmutil.match(ctx, [], opts)
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
382 matchfn, prefix, subrepos=opts.get('subrepos'))
382 matchfn, prefix, subrepos=opts.get('subrepos'))
383
383
384 @command('backout',
384 @command('backout',
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 [('', 'merge', None, _('merge with old dirstate parent after backout')),
386 ('', 'parent', '',
386 ('', 'parent', '',
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ('r', 'rev', '', _('revision to backout'), _('REV')),
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 ] + mergetoolopts + walkopts + commitopts + commitopts2,
390 _('[OPTION]... [-r] REV'))
390 _('[OPTION]... [-r] REV'))
391 def backout(ui, repo, node=None, rev=None, **opts):
391 def backout(ui, repo, node=None, rev=None, **opts):
392 '''reverse effect of earlier changeset
392 '''reverse effect of earlier changeset
393
393
394 Prepare a new changeset with the effect of REV undone in the
394 Prepare a new changeset with the effect of REV undone in the
395 current working directory.
395 current working directory.
396
396
397 If REV is the parent of the working directory, then this new changeset
397 If REV is the parent of the working directory, then this new changeset
398 is committed automatically. Otherwise, hg needs to merge the
398 is committed automatically. Otherwise, hg needs to merge the
399 changes and the merged result is left uncommitted.
399 changes and the merged result is left uncommitted.
400
400
401 .. note::
401 .. note::
402
402
403 backout cannot be used to fix either an unwanted or
403 backout cannot be used to fix either an unwanted or
404 incorrect merge.
404 incorrect merge.
405
405
406 .. container:: verbose
406 .. container:: verbose
407
407
408 By default, the pending changeset will have one parent,
408 By default, the pending changeset will have one parent,
409 maintaining a linear history. With --merge, the pending
409 maintaining a linear history. With --merge, the pending
410 changeset will instead have two parents: the old parent of the
410 changeset will instead have two parents: the old parent of the
411 working directory and a new child of REV that simply undoes REV.
411 working directory and a new child of REV that simply undoes REV.
412
412
413 Before version 1.7, the behavior without --merge was equivalent
413 Before version 1.7, the behavior without --merge was equivalent
414 to specifying --merge followed by :hg:`update --clean .` to
414 to specifying --merge followed by :hg:`update --clean .` to
415 cancel the merge and leave the child of REV as a head to be
415 cancel the merge and leave the child of REV as a head to be
416 merged separately.
416 merged separately.
417
417
418 See :hg:`help dates` for a list of formats valid for -d/--date.
418 See :hg:`help dates` for a list of formats valid for -d/--date.
419
419
420 Returns 0 on success, 1 if nothing to backout or there are unresolved
420 Returns 0 on success, 1 if nothing to backout or there are unresolved
421 files.
421 files.
422 '''
422 '''
423 if rev and node:
423 if rev and node:
424 raise util.Abort(_("please specify just one revision"))
424 raise util.Abort(_("please specify just one revision"))
425
425
426 if not rev:
426 if not rev:
427 rev = node
427 rev = node
428
428
429 if not rev:
429 if not rev:
430 raise util.Abort(_("please specify a revision to backout"))
430 raise util.Abort(_("please specify a revision to backout"))
431
431
432 date = opts.get('date')
432 date = opts.get('date')
433 if date:
433 if date:
434 opts['date'] = util.parsedate(date)
434 opts['date'] = util.parsedate(date)
435
435
436 cmdutil.checkunfinished(repo)
436 cmdutil.checkunfinished(repo)
437 cmdutil.bailifchanged(repo)
437 cmdutil.bailifchanged(repo)
438 node = scmutil.revsingle(repo, rev).node()
438 node = scmutil.revsingle(repo, rev).node()
439
439
440 op1, op2 = repo.dirstate.parents()
440 op1, op2 = repo.dirstate.parents()
441 if node not in repo.changelog.commonancestorsheads(op1, node):
441 if node not in repo.changelog.commonancestorsheads(op1, node):
442 raise util.Abort(_('cannot backout change that is not an ancestor'))
442 raise util.Abort(_('cannot backout change that is not an ancestor'))
443
443
444 p1, p2 = repo.changelog.parents(node)
444 p1, p2 = repo.changelog.parents(node)
445 if p1 == nullid:
445 if p1 == nullid:
446 raise util.Abort(_('cannot backout a change with no parents'))
446 raise util.Abort(_('cannot backout a change with no parents'))
447 if p2 != nullid:
447 if p2 != nullid:
448 if not opts.get('parent'):
448 if not opts.get('parent'):
449 raise util.Abort(_('cannot backout a merge changeset'))
449 raise util.Abort(_('cannot backout a merge changeset'))
450 p = repo.lookup(opts['parent'])
450 p = repo.lookup(opts['parent'])
451 if p not in (p1, p2):
451 if p not in (p1, p2):
452 raise util.Abort(_('%s is not a parent of %s') %
452 raise util.Abort(_('%s is not a parent of %s') %
453 (short(p), short(node)))
453 (short(p), short(node)))
454 parent = p
454 parent = p
455 else:
455 else:
456 if opts.get('parent'):
456 if opts.get('parent'):
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 raise util.Abort(_('cannot use --parent on non-merge changeset'))
458 parent = p1
458 parent = p1
459
459
460 # the backout should appear on the same branch
460 # the backout should appear on the same branch
461 wlock = repo.wlock()
461 wlock = repo.wlock()
462 try:
462 try:
463 branch = repo.dirstate.branch()
463 branch = repo.dirstate.branch()
464 bheads = repo.branchheads(branch)
464 bheads = repo.branchheads(branch)
465 rctx = scmutil.revsingle(repo, hex(parent))
465 rctx = scmutil.revsingle(repo, hex(parent))
466 if not opts.get('merge') and op1 != node:
466 if not opts.get('merge') and op1 != node:
467 try:
467 try:
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
468 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
469 'backout')
469 'backout')
470 stats = mergemod.update(repo, parent, True, True, False,
470 stats = mergemod.update(repo, parent, True, True, False,
471 node, False)
471 node, False)
472 repo.setparents(op1, op2)
472 repo.setparents(op1, op2)
473 hg._showstats(repo, stats)
473 hg._showstats(repo, stats)
474 if stats[3]:
474 if stats[3]:
475 repo.ui.status(_("use 'hg resolve' to retry unresolved "
475 repo.ui.status(_("use 'hg resolve' to retry unresolved "
476 "file merges\n"))
476 "file merges\n"))
477 else:
477 else:
478 msg = _("changeset %s backed out, "
478 msg = _("changeset %s backed out, "
479 "don't forget to commit.\n")
479 "don't forget to commit.\n")
480 ui.status(msg % short(node))
480 ui.status(msg % short(node))
481 return stats[3] > 0
481 return stats[3] > 0
482 finally:
482 finally:
483 ui.setconfig('ui', 'forcemerge', '', '')
483 ui.setconfig('ui', 'forcemerge', '', '')
484 else:
484 else:
485 hg.clean(repo, node, show_stats=False)
485 hg.clean(repo, node, show_stats=False)
486 repo.dirstate.setbranch(branch)
486 repo.dirstate.setbranch(branch)
487 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
487 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
488
488
489
489
490 def commitfunc(ui, repo, message, match, opts):
490 def commitfunc(ui, repo, message, match, opts):
491 e = cmdutil.commiteditor
491 e = cmdutil.getcommiteditor()
492 if not message:
492 if not message:
493 # we don't translate commit messages
493 # we don't translate commit messages
494 message = "Backed out changeset %s" % short(node)
494 message = "Backed out changeset %s" % short(node)
495 e = cmdutil.commitforceeditor
495 e = cmdutil.getcommiteditor(edit=True)
496 return repo.commit(message, opts.get('user'), opts.get('date'),
496 return repo.commit(message, opts.get('user'), opts.get('date'),
497 match, editor=e)
497 match, editor=e)
498 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
498 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
499 if not newnode:
499 if not newnode:
500 ui.status(_("nothing changed\n"))
500 ui.status(_("nothing changed\n"))
501 return 1
501 return 1
502 cmdutil.commitstatus(repo, newnode, branch, bheads)
502 cmdutil.commitstatus(repo, newnode, branch, bheads)
503
503
504 def nice(node):
504 def nice(node):
505 return '%d:%s' % (repo.changelog.rev(node), short(node))
505 return '%d:%s' % (repo.changelog.rev(node), short(node))
506 ui.status(_('changeset %s backs out changeset %s\n') %
506 ui.status(_('changeset %s backs out changeset %s\n') %
507 (nice(repo.changelog.tip()), nice(node)))
507 (nice(repo.changelog.tip()), nice(node)))
508 if opts.get('merge') and op1 != node:
508 if opts.get('merge') and op1 != node:
509 hg.clean(repo, op1, show_stats=False)
509 hg.clean(repo, op1, show_stats=False)
510 ui.status(_('merging with changeset %s\n')
510 ui.status(_('merging with changeset %s\n')
511 % nice(repo.changelog.tip()))
511 % nice(repo.changelog.tip()))
512 try:
512 try:
513 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
513 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
514 'backout')
514 'backout')
515 return hg.merge(repo, hex(repo.changelog.tip()))
515 return hg.merge(repo, hex(repo.changelog.tip()))
516 finally:
516 finally:
517 ui.setconfig('ui', 'forcemerge', '', '')
517 ui.setconfig('ui', 'forcemerge', '', '')
518 finally:
518 finally:
519 wlock.release()
519 wlock.release()
520 return 0
520 return 0
521
521
522 @command('bisect',
522 @command('bisect',
523 [('r', 'reset', False, _('reset bisect state')),
523 [('r', 'reset', False, _('reset bisect state')),
524 ('g', 'good', False, _('mark changeset good')),
524 ('g', 'good', False, _('mark changeset good')),
525 ('b', 'bad', False, _('mark changeset bad')),
525 ('b', 'bad', False, _('mark changeset bad')),
526 ('s', 'skip', False, _('skip testing changeset')),
526 ('s', 'skip', False, _('skip testing changeset')),
527 ('e', 'extend', False, _('extend the bisect range')),
527 ('e', 'extend', False, _('extend the bisect range')),
528 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
528 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
529 ('U', 'noupdate', False, _('do not update to target'))],
529 ('U', 'noupdate', False, _('do not update to target'))],
530 _("[-gbsr] [-U] [-c CMD] [REV]"))
530 _("[-gbsr] [-U] [-c CMD] [REV]"))
531 def bisect(ui, repo, rev=None, extra=None, command=None,
531 def bisect(ui, repo, rev=None, extra=None, command=None,
532 reset=None, good=None, bad=None, skip=None, extend=None,
532 reset=None, good=None, bad=None, skip=None, extend=None,
533 noupdate=None):
533 noupdate=None):
534 """subdivision search of changesets
534 """subdivision search of changesets
535
535
536 This command helps to find changesets which introduce problems. To
536 This command helps to find changesets which introduce problems. To
537 use, mark the earliest changeset you know exhibits the problem as
537 use, mark the earliest changeset you know exhibits the problem as
538 bad, then mark the latest changeset which is free from the problem
538 bad, then mark the latest changeset which is free from the problem
539 as good. Bisect will update your working directory to a revision
539 as good. Bisect will update your working directory to a revision
540 for testing (unless the -U/--noupdate option is specified). Once
540 for testing (unless the -U/--noupdate option is specified). Once
541 you have performed tests, mark the working directory as good or
541 you have performed tests, mark the working directory as good or
542 bad, and bisect will either update to another candidate changeset
542 bad, and bisect will either update to another candidate changeset
543 or announce that it has found the bad revision.
543 or announce that it has found the bad revision.
544
544
545 As a shortcut, you can also use the revision argument to mark a
545 As a shortcut, you can also use the revision argument to mark a
546 revision as good or bad without checking it out first.
546 revision as good or bad without checking it out first.
547
547
548 If you supply a command, it will be used for automatic bisection.
548 If you supply a command, it will be used for automatic bisection.
549 The environment variable HG_NODE will contain the ID of the
549 The environment variable HG_NODE will contain the ID of the
550 changeset being tested. The exit status of the command will be
550 changeset being tested. The exit status of the command will be
551 used to mark revisions as good or bad: status 0 means good, 125
551 used to mark revisions as good or bad: status 0 means good, 125
552 means to skip the revision, 127 (command not found) will abort the
552 means to skip the revision, 127 (command not found) will abort the
553 bisection, and any other non-zero exit status means the revision
553 bisection, and any other non-zero exit status means the revision
554 is bad.
554 is bad.
555
555
556 .. container:: verbose
556 .. container:: verbose
557
557
558 Some examples:
558 Some examples:
559
559
560 - start a bisection with known bad revision 34, and good revision 12::
560 - start a bisection with known bad revision 34, and good revision 12::
561
561
562 hg bisect --bad 34
562 hg bisect --bad 34
563 hg bisect --good 12
563 hg bisect --good 12
564
564
565 - advance the current bisection by marking current revision as good or
565 - advance the current bisection by marking current revision as good or
566 bad::
566 bad::
567
567
568 hg bisect --good
568 hg bisect --good
569 hg bisect --bad
569 hg bisect --bad
570
570
571 - mark the current revision, or a known revision, to be skipped (e.g. if
571 - mark the current revision, or a known revision, to be skipped (e.g. if
572 that revision is not usable because of another issue)::
572 that revision is not usable because of another issue)::
573
573
574 hg bisect --skip
574 hg bisect --skip
575 hg bisect --skip 23
575 hg bisect --skip 23
576
576
577 - skip all revisions that do not touch directories ``foo`` or ``bar``::
577 - skip all revisions that do not touch directories ``foo`` or ``bar``::
578
578
579 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
579 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
580
580
581 - forget the current bisection::
581 - forget the current bisection::
582
582
583 hg bisect --reset
583 hg bisect --reset
584
584
585 - use 'make && make tests' to automatically find the first broken
585 - use 'make && make tests' to automatically find the first broken
586 revision::
586 revision::
587
587
588 hg bisect --reset
588 hg bisect --reset
589 hg bisect --bad 34
589 hg bisect --bad 34
590 hg bisect --good 12
590 hg bisect --good 12
591 hg bisect --command "make && make tests"
591 hg bisect --command "make && make tests"
592
592
593 - see all changesets whose states are already known in the current
593 - see all changesets whose states are already known in the current
594 bisection::
594 bisection::
595
595
596 hg log -r "bisect(pruned)"
596 hg log -r "bisect(pruned)"
597
597
598 - see the changeset currently being bisected (especially useful
598 - see the changeset currently being bisected (especially useful
599 if running with -U/--noupdate)::
599 if running with -U/--noupdate)::
600
600
601 hg log -r "bisect(current)"
601 hg log -r "bisect(current)"
602
602
603 - see all changesets that took part in the current bisection::
603 - see all changesets that took part in the current bisection::
604
604
605 hg log -r "bisect(range)"
605 hg log -r "bisect(range)"
606
606
607 - you can even get a nice graph::
607 - you can even get a nice graph::
608
608
609 hg log --graph -r "bisect(range)"
609 hg log --graph -r "bisect(range)"
610
610
611 See :hg:`help revsets` for more about the `bisect()` keyword.
611 See :hg:`help revsets` for more about the `bisect()` keyword.
612
612
613 Returns 0 on success.
613 Returns 0 on success.
614 """
614 """
615 def extendbisectrange(nodes, good):
615 def extendbisectrange(nodes, good):
616 # bisect is incomplete when it ends on a merge node and
616 # bisect is incomplete when it ends on a merge node and
617 # one of the parent was not checked.
617 # one of the parent was not checked.
618 parents = repo[nodes[0]].parents()
618 parents = repo[nodes[0]].parents()
619 if len(parents) > 1:
619 if len(parents) > 1:
620 side = good and state['bad'] or state['good']
620 side = good and state['bad'] or state['good']
621 num = len(set(i.node() for i in parents) & set(side))
621 num = len(set(i.node() for i in parents) & set(side))
622 if num == 1:
622 if num == 1:
623 return parents[0].ancestor(parents[1])
623 return parents[0].ancestor(parents[1])
624 return None
624 return None
625
625
626 def print_result(nodes, good):
626 def print_result(nodes, good):
627 displayer = cmdutil.show_changeset(ui, repo, {})
627 displayer = cmdutil.show_changeset(ui, repo, {})
628 if len(nodes) == 1:
628 if len(nodes) == 1:
629 # narrowed it down to a single revision
629 # narrowed it down to a single revision
630 if good:
630 if good:
631 ui.write(_("The first good revision is:\n"))
631 ui.write(_("The first good revision is:\n"))
632 else:
632 else:
633 ui.write(_("The first bad revision is:\n"))
633 ui.write(_("The first bad revision is:\n"))
634 displayer.show(repo[nodes[0]])
634 displayer.show(repo[nodes[0]])
635 extendnode = extendbisectrange(nodes, good)
635 extendnode = extendbisectrange(nodes, good)
636 if extendnode is not None:
636 if extendnode is not None:
637 ui.write(_('Not all ancestors of this changeset have been'
637 ui.write(_('Not all ancestors of this changeset have been'
638 ' checked.\nUse bisect --extend to continue the '
638 ' checked.\nUse bisect --extend to continue the '
639 'bisection from\nthe common ancestor, %s.\n')
639 'bisection from\nthe common ancestor, %s.\n')
640 % extendnode)
640 % extendnode)
641 else:
641 else:
642 # multiple possible revisions
642 # multiple possible revisions
643 if good:
643 if good:
644 ui.write(_("Due to skipped revisions, the first "
644 ui.write(_("Due to skipped revisions, the first "
645 "good revision could be any of:\n"))
645 "good revision could be any of:\n"))
646 else:
646 else:
647 ui.write(_("Due to skipped revisions, the first "
647 ui.write(_("Due to skipped revisions, the first "
648 "bad revision could be any of:\n"))
648 "bad revision could be any of:\n"))
649 for n in nodes:
649 for n in nodes:
650 displayer.show(repo[n])
650 displayer.show(repo[n])
651 displayer.close()
651 displayer.close()
652
652
653 def check_state(state, interactive=True):
653 def check_state(state, interactive=True):
654 if not state['good'] or not state['bad']:
654 if not state['good'] or not state['bad']:
655 if (good or bad or skip or reset) and interactive:
655 if (good or bad or skip or reset) and interactive:
656 return
656 return
657 if not state['good']:
657 if not state['good']:
658 raise util.Abort(_('cannot bisect (no known good revisions)'))
658 raise util.Abort(_('cannot bisect (no known good revisions)'))
659 else:
659 else:
660 raise util.Abort(_('cannot bisect (no known bad revisions)'))
660 raise util.Abort(_('cannot bisect (no known bad revisions)'))
661 return True
661 return True
662
662
663 # backward compatibility
663 # backward compatibility
664 if rev in "good bad reset init".split():
664 if rev in "good bad reset init".split():
665 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
665 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
666 cmd, rev, extra = rev, extra, None
666 cmd, rev, extra = rev, extra, None
667 if cmd == "good":
667 if cmd == "good":
668 good = True
668 good = True
669 elif cmd == "bad":
669 elif cmd == "bad":
670 bad = True
670 bad = True
671 else:
671 else:
672 reset = True
672 reset = True
673 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
673 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
674 raise util.Abort(_('incompatible arguments'))
674 raise util.Abort(_('incompatible arguments'))
675
675
676 cmdutil.checkunfinished(repo)
676 cmdutil.checkunfinished(repo)
677
677
678 if reset:
678 if reset:
679 p = repo.join("bisect.state")
679 p = repo.join("bisect.state")
680 if os.path.exists(p):
680 if os.path.exists(p):
681 os.unlink(p)
681 os.unlink(p)
682 return
682 return
683
683
684 state = hbisect.load_state(repo)
684 state = hbisect.load_state(repo)
685
685
686 if command:
686 if command:
687 changesets = 1
687 changesets = 1
688 if noupdate:
688 if noupdate:
689 try:
689 try:
690 node = state['current'][0]
690 node = state['current'][0]
691 except LookupError:
691 except LookupError:
692 raise util.Abort(_('current bisect revision is unknown - '
692 raise util.Abort(_('current bisect revision is unknown - '
693 'start a new bisect to fix'))
693 'start a new bisect to fix'))
694 else:
694 else:
695 node, p2 = repo.dirstate.parents()
695 node, p2 = repo.dirstate.parents()
696 if p2 != nullid:
696 if p2 != nullid:
697 raise util.Abort(_('current bisect revision is a merge'))
697 raise util.Abort(_('current bisect revision is a merge'))
698 try:
698 try:
699 while changesets:
699 while changesets:
700 # update state
700 # update state
701 state['current'] = [node]
701 state['current'] = [node]
702 hbisect.save_state(repo, state)
702 hbisect.save_state(repo, state)
703 status = util.system(command,
703 status = util.system(command,
704 environ={'HG_NODE': hex(node)},
704 environ={'HG_NODE': hex(node)},
705 out=ui.fout)
705 out=ui.fout)
706 if status == 125:
706 if status == 125:
707 transition = "skip"
707 transition = "skip"
708 elif status == 0:
708 elif status == 0:
709 transition = "good"
709 transition = "good"
710 # status < 0 means process was killed
710 # status < 0 means process was killed
711 elif status == 127:
711 elif status == 127:
712 raise util.Abort(_("failed to execute %s") % command)
712 raise util.Abort(_("failed to execute %s") % command)
713 elif status < 0:
713 elif status < 0:
714 raise util.Abort(_("%s killed") % command)
714 raise util.Abort(_("%s killed") % command)
715 else:
715 else:
716 transition = "bad"
716 transition = "bad"
717 ctx = scmutil.revsingle(repo, rev, node)
717 ctx = scmutil.revsingle(repo, rev, node)
718 rev = None # clear for future iterations
718 rev = None # clear for future iterations
719 state[transition].append(ctx.node())
719 state[transition].append(ctx.node())
720 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
720 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
721 check_state(state, interactive=False)
721 check_state(state, interactive=False)
722 # bisect
722 # bisect
723 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
723 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
724 # update to next check
724 # update to next check
725 node = nodes[0]
725 node = nodes[0]
726 if not noupdate:
726 if not noupdate:
727 cmdutil.bailifchanged(repo)
727 cmdutil.bailifchanged(repo)
728 hg.clean(repo, node, show_stats=False)
728 hg.clean(repo, node, show_stats=False)
729 finally:
729 finally:
730 state['current'] = [node]
730 state['current'] = [node]
731 hbisect.save_state(repo, state)
731 hbisect.save_state(repo, state)
732 print_result(nodes, bgood)
732 print_result(nodes, bgood)
733 return
733 return
734
734
735 # update state
735 # update state
736
736
737 if rev:
737 if rev:
738 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
738 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
739 else:
739 else:
740 nodes = [repo.lookup('.')]
740 nodes = [repo.lookup('.')]
741
741
742 if good or bad or skip:
742 if good or bad or skip:
743 if good:
743 if good:
744 state['good'] += nodes
744 state['good'] += nodes
745 elif bad:
745 elif bad:
746 state['bad'] += nodes
746 state['bad'] += nodes
747 elif skip:
747 elif skip:
748 state['skip'] += nodes
748 state['skip'] += nodes
749 hbisect.save_state(repo, state)
749 hbisect.save_state(repo, state)
750
750
751 if not check_state(state):
751 if not check_state(state):
752 return
752 return
753
753
754 # actually bisect
754 # actually bisect
755 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
755 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
756 if extend:
756 if extend:
757 if not changesets:
757 if not changesets:
758 extendnode = extendbisectrange(nodes, good)
758 extendnode = extendbisectrange(nodes, good)
759 if extendnode is not None:
759 if extendnode is not None:
760 ui.write(_("Extending search to changeset %d:%s\n")
760 ui.write(_("Extending search to changeset %d:%s\n")
761 % (extendnode.rev(), extendnode))
761 % (extendnode.rev(), extendnode))
762 state['current'] = [extendnode.node()]
762 state['current'] = [extendnode.node()]
763 hbisect.save_state(repo, state)
763 hbisect.save_state(repo, state)
764 if noupdate:
764 if noupdate:
765 return
765 return
766 cmdutil.bailifchanged(repo)
766 cmdutil.bailifchanged(repo)
767 return hg.clean(repo, extendnode.node())
767 return hg.clean(repo, extendnode.node())
768 raise util.Abort(_("nothing to extend"))
768 raise util.Abort(_("nothing to extend"))
769
769
770 if changesets == 0:
770 if changesets == 0:
771 print_result(nodes, good)
771 print_result(nodes, good)
772 else:
772 else:
773 assert len(nodes) == 1 # only a single node can be tested next
773 assert len(nodes) == 1 # only a single node can be tested next
774 node = nodes[0]
774 node = nodes[0]
775 # compute the approximate number of remaining tests
775 # compute the approximate number of remaining tests
776 tests, size = 0, 2
776 tests, size = 0, 2
777 while size <= changesets:
777 while size <= changesets:
778 tests, size = tests + 1, size * 2
778 tests, size = tests + 1, size * 2
779 rev = repo.changelog.rev(node)
779 rev = repo.changelog.rev(node)
780 ui.write(_("Testing changeset %d:%s "
780 ui.write(_("Testing changeset %d:%s "
781 "(%d changesets remaining, ~%d tests)\n")
781 "(%d changesets remaining, ~%d tests)\n")
782 % (rev, short(node), changesets, tests))
782 % (rev, short(node), changesets, tests))
783 state['current'] = [node]
783 state['current'] = [node]
784 hbisect.save_state(repo, state)
784 hbisect.save_state(repo, state)
785 if not noupdate:
785 if not noupdate:
786 cmdutil.bailifchanged(repo)
786 cmdutil.bailifchanged(repo)
787 return hg.clean(repo, node)
787 return hg.clean(repo, node)
788
788
789 @command('bookmarks|bookmark',
789 @command('bookmarks|bookmark',
790 [('f', 'force', False, _('force')),
790 [('f', 'force', False, _('force')),
791 ('r', 'rev', '', _('revision'), _('REV')),
791 ('r', 'rev', '', _('revision'), _('REV')),
792 ('d', 'delete', False, _('delete a given bookmark')),
792 ('d', 'delete', False, _('delete a given bookmark')),
793 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
793 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
794 ('i', 'inactive', False, _('mark a bookmark inactive'))],
794 ('i', 'inactive', False, _('mark a bookmark inactive'))],
795 _('hg bookmarks [OPTIONS]... [NAME]...'))
795 _('hg bookmarks [OPTIONS]... [NAME]...'))
796 def bookmark(ui, repo, *names, **opts):
796 def bookmark(ui, repo, *names, **opts):
797 '''track a line of development with movable markers
797 '''track a line of development with movable markers
798
798
799 Bookmarks are pointers to certain commits that move when committing.
799 Bookmarks are pointers to certain commits that move when committing.
800 Bookmarks are local. They can be renamed, copied and deleted. It is
800 Bookmarks are local. They can be renamed, copied and deleted. It is
801 possible to use :hg:`merge NAME` to merge from a given bookmark, and
801 possible to use :hg:`merge NAME` to merge from a given bookmark, and
802 :hg:`update NAME` to update to a given bookmark.
802 :hg:`update NAME` to update to a given bookmark.
803
803
804 You can use :hg:`bookmark NAME` to set a bookmark on the working
804 You can use :hg:`bookmark NAME` to set a bookmark on the working
805 directory's parent revision with the given name. If you specify
805 directory's parent revision with the given name. If you specify
806 a revision using -r REV (where REV may be an existing bookmark),
806 a revision using -r REV (where REV may be an existing bookmark),
807 the bookmark is assigned to that revision.
807 the bookmark is assigned to that revision.
808
808
809 Bookmarks can be pushed and pulled between repositories (see :hg:`help
809 Bookmarks can be pushed and pulled between repositories (see :hg:`help
810 push` and :hg:`help pull`). This requires both the local and remote
810 push` and :hg:`help pull`). This requires both the local and remote
811 repositories to support bookmarks. For versions prior to 1.8, this means
811 repositories to support bookmarks. For versions prior to 1.8, this means
812 the bookmarks extension must be enabled.
812 the bookmarks extension must be enabled.
813
813
814 If you set a bookmark called '@', new clones of the repository will
814 If you set a bookmark called '@', new clones of the repository will
815 have that revision checked out (and the bookmark made active) by
815 have that revision checked out (and the bookmark made active) by
816 default.
816 default.
817
817
818 With -i/--inactive, the new bookmark will not be made the active
818 With -i/--inactive, the new bookmark will not be made the active
819 bookmark. If -r/--rev is given, the new bookmark will not be made
819 bookmark. If -r/--rev is given, the new bookmark will not be made
820 active even if -i/--inactive is not given. If no NAME is given, the
820 active even if -i/--inactive is not given. If no NAME is given, the
821 current active bookmark will be marked inactive.
821 current active bookmark will be marked inactive.
822 '''
822 '''
823 force = opts.get('force')
823 force = opts.get('force')
824 rev = opts.get('rev')
824 rev = opts.get('rev')
825 delete = opts.get('delete')
825 delete = opts.get('delete')
826 rename = opts.get('rename')
826 rename = opts.get('rename')
827 inactive = opts.get('inactive')
827 inactive = opts.get('inactive')
828
828
829 def checkformat(mark):
829 def checkformat(mark):
830 mark = mark.strip()
830 mark = mark.strip()
831 if not mark:
831 if not mark:
832 raise util.Abort(_("bookmark names cannot consist entirely of "
832 raise util.Abort(_("bookmark names cannot consist entirely of "
833 "whitespace"))
833 "whitespace"))
834 scmutil.checknewlabel(repo, mark, 'bookmark')
834 scmutil.checknewlabel(repo, mark, 'bookmark')
835 return mark
835 return mark
836
836
837 def checkconflict(repo, mark, cur, force=False, target=None):
837 def checkconflict(repo, mark, cur, force=False, target=None):
838 if mark in marks and not force:
838 if mark in marks and not force:
839 if target:
839 if target:
840 if marks[mark] == target and target == cur:
840 if marks[mark] == target and target == cur:
841 # re-activating a bookmark
841 # re-activating a bookmark
842 return
842 return
843 anc = repo.changelog.ancestors([repo[target].rev()])
843 anc = repo.changelog.ancestors([repo[target].rev()])
844 bmctx = repo[marks[mark]]
844 bmctx = repo[marks[mark]]
845 divs = [repo[b].node() for b in marks
845 divs = [repo[b].node() for b in marks
846 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
846 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
847
847
848 # allow resolving a single divergent bookmark even if moving
848 # allow resolving a single divergent bookmark even if moving
849 # the bookmark across branches when a revision is specified
849 # the bookmark across branches when a revision is specified
850 # that contains a divergent bookmark
850 # that contains a divergent bookmark
851 if bmctx.rev() not in anc and target in divs:
851 if bmctx.rev() not in anc and target in divs:
852 bookmarks.deletedivergent(repo, [target], mark)
852 bookmarks.deletedivergent(repo, [target], mark)
853 return
853 return
854
854
855 deletefrom = [b for b in divs
855 deletefrom = [b for b in divs
856 if repo[b].rev() in anc or b == target]
856 if repo[b].rev() in anc or b == target]
857 bookmarks.deletedivergent(repo, deletefrom, mark)
857 bookmarks.deletedivergent(repo, deletefrom, mark)
858 if bookmarks.validdest(repo, bmctx, repo[target]):
858 if bookmarks.validdest(repo, bmctx, repo[target]):
859 ui.status(_("moving bookmark '%s' forward from %s\n") %
859 ui.status(_("moving bookmark '%s' forward from %s\n") %
860 (mark, short(bmctx.node())))
860 (mark, short(bmctx.node())))
861 return
861 return
862 raise util.Abort(_("bookmark '%s' already exists "
862 raise util.Abort(_("bookmark '%s' already exists "
863 "(use -f to force)") % mark)
863 "(use -f to force)") % mark)
864 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
864 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
865 and not force):
865 and not force):
866 raise util.Abort(
866 raise util.Abort(
867 _("a bookmark cannot have the name of an existing branch"))
867 _("a bookmark cannot have the name of an existing branch"))
868
868
869 if delete and rename:
869 if delete and rename:
870 raise util.Abort(_("--delete and --rename are incompatible"))
870 raise util.Abort(_("--delete and --rename are incompatible"))
871 if delete and rev:
871 if delete and rev:
872 raise util.Abort(_("--rev is incompatible with --delete"))
872 raise util.Abort(_("--rev is incompatible with --delete"))
873 if rename and rev:
873 if rename and rev:
874 raise util.Abort(_("--rev is incompatible with --rename"))
874 raise util.Abort(_("--rev is incompatible with --rename"))
875 if not names and (delete or rev):
875 if not names and (delete or rev):
876 raise util.Abort(_("bookmark name required"))
876 raise util.Abort(_("bookmark name required"))
877
877
878 if delete or rename or names or inactive:
878 if delete or rename or names or inactive:
879 wlock = repo.wlock()
879 wlock = repo.wlock()
880 try:
880 try:
881 cur = repo.changectx('.').node()
881 cur = repo.changectx('.').node()
882 marks = repo._bookmarks
882 marks = repo._bookmarks
883 if delete:
883 if delete:
884 for mark in names:
884 for mark in names:
885 if mark not in marks:
885 if mark not in marks:
886 raise util.Abort(_("bookmark '%s' does not exist") %
886 raise util.Abort(_("bookmark '%s' does not exist") %
887 mark)
887 mark)
888 if mark == repo._bookmarkcurrent:
888 if mark == repo._bookmarkcurrent:
889 bookmarks.unsetcurrent(repo)
889 bookmarks.unsetcurrent(repo)
890 del marks[mark]
890 del marks[mark]
891 marks.write()
891 marks.write()
892
892
893 elif rename:
893 elif rename:
894 if not names:
894 if not names:
895 raise util.Abort(_("new bookmark name required"))
895 raise util.Abort(_("new bookmark name required"))
896 elif len(names) > 1:
896 elif len(names) > 1:
897 raise util.Abort(_("only one new bookmark name allowed"))
897 raise util.Abort(_("only one new bookmark name allowed"))
898 mark = checkformat(names[0])
898 mark = checkformat(names[0])
899 if rename not in marks:
899 if rename not in marks:
900 raise util.Abort(_("bookmark '%s' does not exist") % rename)
900 raise util.Abort(_("bookmark '%s' does not exist") % rename)
901 checkconflict(repo, mark, cur, force)
901 checkconflict(repo, mark, cur, force)
902 marks[mark] = marks[rename]
902 marks[mark] = marks[rename]
903 if repo._bookmarkcurrent == rename and not inactive:
903 if repo._bookmarkcurrent == rename and not inactive:
904 bookmarks.setcurrent(repo, mark)
904 bookmarks.setcurrent(repo, mark)
905 del marks[rename]
905 del marks[rename]
906 marks.write()
906 marks.write()
907
907
908 elif names:
908 elif names:
909 newact = None
909 newact = None
910 for mark in names:
910 for mark in names:
911 mark = checkformat(mark)
911 mark = checkformat(mark)
912 if newact is None:
912 if newact is None:
913 newact = mark
913 newact = mark
914 if inactive and mark == repo._bookmarkcurrent:
914 if inactive and mark == repo._bookmarkcurrent:
915 bookmarks.unsetcurrent(repo)
915 bookmarks.unsetcurrent(repo)
916 return
916 return
917 tgt = cur
917 tgt = cur
918 if rev:
918 if rev:
919 tgt = scmutil.revsingle(repo, rev).node()
919 tgt = scmutil.revsingle(repo, rev).node()
920 checkconflict(repo, mark, cur, force, tgt)
920 checkconflict(repo, mark, cur, force, tgt)
921 marks[mark] = tgt
921 marks[mark] = tgt
922 if not inactive and cur == marks[newact] and not rev:
922 if not inactive and cur == marks[newact] and not rev:
923 bookmarks.setcurrent(repo, newact)
923 bookmarks.setcurrent(repo, newact)
924 elif cur != tgt and newact == repo._bookmarkcurrent:
924 elif cur != tgt and newact == repo._bookmarkcurrent:
925 bookmarks.unsetcurrent(repo)
925 bookmarks.unsetcurrent(repo)
926 marks.write()
926 marks.write()
927
927
928 elif inactive:
928 elif inactive:
929 if len(marks) == 0:
929 if len(marks) == 0:
930 ui.status(_("no bookmarks set\n"))
930 ui.status(_("no bookmarks set\n"))
931 elif not repo._bookmarkcurrent:
931 elif not repo._bookmarkcurrent:
932 ui.status(_("no active bookmark\n"))
932 ui.status(_("no active bookmark\n"))
933 else:
933 else:
934 bookmarks.unsetcurrent(repo)
934 bookmarks.unsetcurrent(repo)
935 finally:
935 finally:
936 wlock.release()
936 wlock.release()
937 else: # show bookmarks
937 else: # show bookmarks
938 hexfn = ui.debugflag and hex or short
938 hexfn = ui.debugflag and hex or short
939 marks = repo._bookmarks
939 marks = repo._bookmarks
940 if len(marks) == 0:
940 if len(marks) == 0:
941 ui.status(_("no bookmarks set\n"))
941 ui.status(_("no bookmarks set\n"))
942 else:
942 else:
943 for bmark, n in sorted(marks.iteritems()):
943 for bmark, n in sorted(marks.iteritems()):
944 current = repo._bookmarkcurrent
944 current = repo._bookmarkcurrent
945 if bmark == current:
945 if bmark == current:
946 prefix, label = '*', 'bookmarks.current'
946 prefix, label = '*', 'bookmarks.current'
947 else:
947 else:
948 prefix, label = ' ', ''
948 prefix, label = ' ', ''
949
949
950 if ui.quiet:
950 if ui.quiet:
951 ui.write("%s\n" % bmark, label=label)
951 ui.write("%s\n" % bmark, label=label)
952 else:
952 else:
953 ui.write(" %s %-25s %d:%s\n" % (
953 ui.write(" %s %-25s %d:%s\n" % (
954 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
954 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
955 label=label)
955 label=label)
956
956
957 @command('branch',
957 @command('branch',
958 [('f', 'force', None,
958 [('f', 'force', None,
959 _('set branch name even if it shadows an existing branch')),
959 _('set branch name even if it shadows an existing branch')),
960 ('C', 'clean', None, _('reset branch name to parent branch name'))],
960 ('C', 'clean', None, _('reset branch name to parent branch name'))],
961 _('[-fC] [NAME]'))
961 _('[-fC] [NAME]'))
962 def branch(ui, repo, label=None, **opts):
962 def branch(ui, repo, label=None, **opts):
963 """set or show the current branch name
963 """set or show the current branch name
964
964
965 .. note::
965 .. note::
966
966
967 Branch names are permanent and global. Use :hg:`bookmark` to create a
967 Branch names are permanent and global. Use :hg:`bookmark` to create a
968 light-weight bookmark instead. See :hg:`help glossary` for more
968 light-weight bookmark instead. See :hg:`help glossary` for more
969 information about named branches and bookmarks.
969 information about named branches and bookmarks.
970
970
971 With no argument, show the current branch name. With one argument,
971 With no argument, show the current branch name. With one argument,
972 set the working directory branch name (the branch will not exist
972 set the working directory branch name (the branch will not exist
973 in the repository until the next commit). Standard practice
973 in the repository until the next commit). Standard practice
974 recommends that primary development take place on the 'default'
974 recommends that primary development take place on the 'default'
975 branch.
975 branch.
976
976
977 Unless -f/--force is specified, branch will not let you set a
977 Unless -f/--force is specified, branch will not let you set a
978 branch name that already exists, even if it's inactive.
978 branch name that already exists, even if it's inactive.
979
979
980 Use -C/--clean to reset the working directory branch to that of
980 Use -C/--clean to reset the working directory branch to that of
981 the parent of the working directory, negating a previous branch
981 the parent of the working directory, negating a previous branch
982 change.
982 change.
983
983
984 Use the command :hg:`update` to switch to an existing branch. Use
984 Use the command :hg:`update` to switch to an existing branch. Use
985 :hg:`commit --close-branch` to mark this branch as closed.
985 :hg:`commit --close-branch` to mark this branch as closed.
986
986
987 Returns 0 on success.
987 Returns 0 on success.
988 """
988 """
989 if label:
989 if label:
990 label = label.strip()
990 label = label.strip()
991
991
992 if not opts.get('clean') and not label:
992 if not opts.get('clean') and not label:
993 ui.write("%s\n" % repo.dirstate.branch())
993 ui.write("%s\n" % repo.dirstate.branch())
994 return
994 return
995
995
996 wlock = repo.wlock()
996 wlock = repo.wlock()
997 try:
997 try:
998 if opts.get('clean'):
998 if opts.get('clean'):
999 label = repo[None].p1().branch()
999 label = repo[None].p1().branch()
1000 repo.dirstate.setbranch(label)
1000 repo.dirstate.setbranch(label)
1001 ui.status(_('reset working directory to branch %s\n') % label)
1001 ui.status(_('reset working directory to branch %s\n') % label)
1002 elif label:
1002 elif label:
1003 if not opts.get('force') and label in repo.branchmap():
1003 if not opts.get('force') and label in repo.branchmap():
1004 if label not in [p.branch() for p in repo.parents()]:
1004 if label not in [p.branch() for p in repo.parents()]:
1005 raise util.Abort(_('a branch of the same name already'
1005 raise util.Abort(_('a branch of the same name already'
1006 ' exists'),
1006 ' exists'),
1007 # i18n: "it" refers to an existing branch
1007 # i18n: "it" refers to an existing branch
1008 hint=_("use 'hg update' to switch to it"))
1008 hint=_("use 'hg update' to switch to it"))
1009 scmutil.checknewlabel(repo, label, 'branch')
1009 scmutil.checknewlabel(repo, label, 'branch')
1010 repo.dirstate.setbranch(label)
1010 repo.dirstate.setbranch(label)
1011 ui.status(_('marked working directory as branch %s\n') % label)
1011 ui.status(_('marked working directory as branch %s\n') % label)
1012 ui.status(_('(branches are permanent and global, '
1012 ui.status(_('(branches are permanent and global, '
1013 'did you want a bookmark?)\n'))
1013 'did you want a bookmark?)\n'))
1014 finally:
1014 finally:
1015 wlock.release()
1015 wlock.release()
1016
1016
1017 @command('branches',
1017 @command('branches',
1018 [('a', 'active', False, _('show only branches that have unmerged heads')),
1018 [('a', 'active', False, _('show only branches that have unmerged heads')),
1019 ('c', 'closed', False, _('show normal and closed branches'))],
1019 ('c', 'closed', False, _('show normal and closed branches'))],
1020 _('[-ac]'))
1020 _('[-ac]'))
1021 def branches(ui, repo, active=False, closed=False):
1021 def branches(ui, repo, active=False, closed=False):
1022 """list repository named branches
1022 """list repository named branches
1023
1023
1024 List the repository's named branches, indicating which ones are
1024 List the repository's named branches, indicating which ones are
1025 inactive. If -c/--closed is specified, also list branches which have
1025 inactive. If -c/--closed is specified, also list branches which have
1026 been marked closed (see :hg:`commit --close-branch`).
1026 been marked closed (see :hg:`commit --close-branch`).
1027
1027
1028 If -a/--active is specified, only show active branches. A branch
1028 If -a/--active is specified, only show active branches. A branch
1029 is considered active if it contains repository heads.
1029 is considered active if it contains repository heads.
1030
1030
1031 Use the command :hg:`update` to switch to an existing branch.
1031 Use the command :hg:`update` to switch to an existing branch.
1032
1032
1033 Returns 0.
1033 Returns 0.
1034 """
1034 """
1035
1035
1036 hexfunc = ui.debugflag and hex or short
1036 hexfunc = ui.debugflag and hex or short
1037
1037
1038 allheads = set(repo.heads())
1038 allheads = set(repo.heads())
1039 branches = []
1039 branches = []
1040 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1040 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1041 isactive = not isclosed and bool(set(heads) & allheads)
1041 isactive = not isclosed and bool(set(heads) & allheads)
1042 branches.append((tag, repo[tip], isactive, not isclosed))
1042 branches.append((tag, repo[tip], isactive, not isclosed))
1043 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1043 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1044 reverse=True)
1044 reverse=True)
1045
1045
1046 for tag, ctx, isactive, isopen in branches:
1046 for tag, ctx, isactive, isopen in branches:
1047 if (not active) or isactive:
1047 if (not active) or isactive:
1048 if isactive:
1048 if isactive:
1049 label = 'branches.active'
1049 label = 'branches.active'
1050 notice = ''
1050 notice = ''
1051 elif not isopen:
1051 elif not isopen:
1052 if not closed:
1052 if not closed:
1053 continue
1053 continue
1054 label = 'branches.closed'
1054 label = 'branches.closed'
1055 notice = _(' (closed)')
1055 notice = _(' (closed)')
1056 else:
1056 else:
1057 label = 'branches.inactive'
1057 label = 'branches.inactive'
1058 notice = _(' (inactive)')
1058 notice = _(' (inactive)')
1059 if tag == repo.dirstate.branch():
1059 if tag == repo.dirstate.branch():
1060 label = 'branches.current'
1060 label = 'branches.current'
1061 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1061 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1062 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1062 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1063 'log.changeset changeset.%s' % ctx.phasestr())
1063 'log.changeset changeset.%s' % ctx.phasestr())
1064 labeledtag = ui.label(tag, label)
1064 labeledtag = ui.label(tag, label)
1065 if ui.quiet:
1065 if ui.quiet:
1066 ui.write("%s\n" % labeledtag)
1066 ui.write("%s\n" % labeledtag)
1067 else:
1067 else:
1068 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1068 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1069
1069
1070 @command('bundle',
1070 @command('bundle',
1071 [('f', 'force', None, _('run even when the destination is unrelated')),
1071 [('f', 'force', None, _('run even when the destination is unrelated')),
1072 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1072 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1073 _('REV')),
1073 _('REV')),
1074 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1074 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1075 _('BRANCH')),
1075 _('BRANCH')),
1076 ('', 'base', [],
1076 ('', 'base', [],
1077 _('a base changeset assumed to be available at the destination'),
1077 _('a base changeset assumed to be available at the destination'),
1078 _('REV')),
1078 _('REV')),
1079 ('a', 'all', None, _('bundle all changesets in the repository')),
1079 ('a', 'all', None, _('bundle all changesets in the repository')),
1080 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1080 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1081 ] + remoteopts,
1081 ] + remoteopts,
1082 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1082 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1083 def bundle(ui, repo, fname, dest=None, **opts):
1083 def bundle(ui, repo, fname, dest=None, **opts):
1084 """create a changegroup file
1084 """create a changegroup file
1085
1085
1086 Generate a compressed changegroup file collecting changesets not
1086 Generate a compressed changegroup file collecting changesets not
1087 known to be in another repository.
1087 known to be in another repository.
1088
1088
1089 If you omit the destination repository, then hg assumes the
1089 If you omit the destination repository, then hg assumes the
1090 destination will have all the nodes you specify with --base
1090 destination will have all the nodes you specify with --base
1091 parameters. To create a bundle containing all changesets, use
1091 parameters. To create a bundle containing all changesets, use
1092 -a/--all (or --base null).
1092 -a/--all (or --base null).
1093
1093
1094 You can change compression method with the -t/--type option.
1094 You can change compression method with the -t/--type option.
1095 The available compression methods are: none, bzip2, and
1095 The available compression methods are: none, bzip2, and
1096 gzip (by default, bundles are compressed using bzip2).
1096 gzip (by default, bundles are compressed using bzip2).
1097
1097
1098 The bundle file can then be transferred using conventional means
1098 The bundle file can then be transferred using conventional means
1099 and applied to another repository with the unbundle or pull
1099 and applied to another repository with the unbundle or pull
1100 command. This is useful when direct push and pull are not
1100 command. This is useful when direct push and pull are not
1101 available or when exporting an entire repository is undesirable.
1101 available or when exporting an entire repository is undesirable.
1102
1102
1103 Applying bundles preserves all changeset contents including
1103 Applying bundles preserves all changeset contents including
1104 permissions, copy/rename information, and revision history.
1104 permissions, copy/rename information, and revision history.
1105
1105
1106 Returns 0 on success, 1 if no changes found.
1106 Returns 0 on success, 1 if no changes found.
1107 """
1107 """
1108 revs = None
1108 revs = None
1109 if 'rev' in opts:
1109 if 'rev' in opts:
1110 revs = scmutil.revrange(repo, opts['rev'])
1110 revs = scmutil.revrange(repo, opts['rev'])
1111
1111
1112 bundletype = opts.get('type', 'bzip2').lower()
1112 bundletype = opts.get('type', 'bzip2').lower()
1113 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1113 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1114 bundletype = btypes.get(bundletype)
1114 bundletype = btypes.get(bundletype)
1115 if bundletype not in changegroup.bundletypes:
1115 if bundletype not in changegroup.bundletypes:
1116 raise util.Abort(_('unknown bundle type specified with --type'))
1116 raise util.Abort(_('unknown bundle type specified with --type'))
1117
1117
1118 if opts.get('all'):
1118 if opts.get('all'):
1119 base = ['null']
1119 base = ['null']
1120 else:
1120 else:
1121 base = scmutil.revrange(repo, opts.get('base'))
1121 base = scmutil.revrange(repo, opts.get('base'))
1122 # TODO: get desired bundlecaps from command line.
1122 # TODO: get desired bundlecaps from command line.
1123 bundlecaps = None
1123 bundlecaps = None
1124 if base:
1124 if base:
1125 if dest:
1125 if dest:
1126 raise util.Abort(_("--base is incompatible with specifying "
1126 raise util.Abort(_("--base is incompatible with specifying "
1127 "a destination"))
1127 "a destination"))
1128 common = [repo.lookup(rev) for rev in base]
1128 common = [repo.lookup(rev) for rev in base]
1129 heads = revs and map(repo.lookup, revs) or revs
1129 heads = revs and map(repo.lookup, revs) or revs
1130 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1130 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1131 bundlecaps=bundlecaps)
1131 bundlecaps=bundlecaps)
1132 outgoing = None
1132 outgoing = None
1133 else:
1133 else:
1134 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1134 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1135 dest, branches = hg.parseurl(dest, opts.get('branch'))
1135 dest, branches = hg.parseurl(dest, opts.get('branch'))
1136 other = hg.peer(repo, opts, dest)
1136 other = hg.peer(repo, opts, dest)
1137 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1137 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1138 heads = revs and map(repo.lookup, revs) or revs
1138 heads = revs and map(repo.lookup, revs) or revs
1139 outgoing = discovery.findcommonoutgoing(repo, other,
1139 outgoing = discovery.findcommonoutgoing(repo, other,
1140 onlyheads=heads,
1140 onlyheads=heads,
1141 force=opts.get('force'),
1141 force=opts.get('force'),
1142 portable=True)
1142 portable=True)
1143 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1143 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1144 if not cg:
1144 if not cg:
1145 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1145 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1146 return 1
1146 return 1
1147
1147
1148 changegroup.writebundle(cg, fname, bundletype)
1148 changegroup.writebundle(cg, fname, bundletype)
1149
1149
1150 @command('cat',
1150 @command('cat',
1151 [('o', 'output', '',
1151 [('o', 'output', '',
1152 _('print output to file with formatted name'), _('FORMAT')),
1152 _('print output to file with formatted name'), _('FORMAT')),
1153 ('r', 'rev', '', _('print the given revision'), _('REV')),
1153 ('r', 'rev', '', _('print the given revision'), _('REV')),
1154 ('', 'decode', None, _('apply any matching decode filter')),
1154 ('', 'decode', None, _('apply any matching decode filter')),
1155 ] + walkopts,
1155 ] + walkopts,
1156 _('[OPTION]... FILE...'))
1156 _('[OPTION]... FILE...'))
1157 def cat(ui, repo, file1, *pats, **opts):
1157 def cat(ui, repo, file1, *pats, **opts):
1158 """output the current or given revision of files
1158 """output the current or given revision of files
1159
1159
1160 Print the specified files as they were at the given revision. If
1160 Print the specified files as they were at the given revision. If
1161 no revision is given, the parent of the working directory is used.
1161 no revision is given, the parent of the working directory is used.
1162
1162
1163 Output may be to a file, in which case the name of the file is
1163 Output may be to a file, in which case the name of the file is
1164 given using a format string. The formatting rules as follows:
1164 given using a format string. The formatting rules as follows:
1165
1165
1166 :``%%``: literal "%" character
1166 :``%%``: literal "%" character
1167 :``%s``: basename of file being printed
1167 :``%s``: basename of file being printed
1168 :``%d``: dirname of file being printed, or '.' if in repository root
1168 :``%d``: dirname of file being printed, or '.' if in repository root
1169 :``%p``: root-relative path name of file being printed
1169 :``%p``: root-relative path name of file being printed
1170 :``%H``: changeset hash (40 hexadecimal digits)
1170 :``%H``: changeset hash (40 hexadecimal digits)
1171 :``%R``: changeset revision number
1171 :``%R``: changeset revision number
1172 :``%h``: short-form changeset hash (12 hexadecimal digits)
1172 :``%h``: short-form changeset hash (12 hexadecimal digits)
1173 :``%r``: zero-padded changeset revision number
1173 :``%r``: zero-padded changeset revision number
1174 :``%b``: basename of the exporting repository
1174 :``%b``: basename of the exporting repository
1175
1175
1176 Returns 0 on success.
1176 Returns 0 on success.
1177 """
1177 """
1178 ctx = scmutil.revsingle(repo, opts.get('rev'))
1178 ctx = scmutil.revsingle(repo, opts.get('rev'))
1179 m = scmutil.match(ctx, (file1,) + pats, opts)
1179 m = scmutil.match(ctx, (file1,) + pats, opts)
1180
1180
1181 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1181 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1182
1182
1183 @command('^clone',
1183 @command('^clone',
1184 [('U', 'noupdate', None,
1184 [('U', 'noupdate', None,
1185 _('the clone will include an empty working copy (only a repository)')),
1185 _('the clone will include an empty working copy (only a repository)')),
1186 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1186 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1187 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1187 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1188 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1188 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1189 ('', 'pull', None, _('use pull protocol to copy metadata')),
1189 ('', 'pull', None, _('use pull protocol to copy metadata')),
1190 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1190 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1191 ] + remoteopts,
1191 ] + remoteopts,
1192 _('[OPTION]... SOURCE [DEST]'))
1192 _('[OPTION]... SOURCE [DEST]'))
1193 def clone(ui, source, dest=None, **opts):
1193 def clone(ui, source, dest=None, **opts):
1194 """make a copy of an existing repository
1194 """make a copy of an existing repository
1195
1195
1196 Create a copy of an existing repository in a new directory.
1196 Create a copy of an existing repository in a new directory.
1197
1197
1198 If no destination directory name is specified, it defaults to the
1198 If no destination directory name is specified, it defaults to the
1199 basename of the source.
1199 basename of the source.
1200
1200
1201 The location of the source is added to the new repository's
1201 The location of the source is added to the new repository's
1202 ``.hg/hgrc`` file, as the default to be used for future pulls.
1202 ``.hg/hgrc`` file, as the default to be used for future pulls.
1203
1203
1204 Only local paths and ``ssh://`` URLs are supported as
1204 Only local paths and ``ssh://`` URLs are supported as
1205 destinations. For ``ssh://`` destinations, no working directory or
1205 destinations. For ``ssh://`` destinations, no working directory or
1206 ``.hg/hgrc`` will be created on the remote side.
1206 ``.hg/hgrc`` will be created on the remote side.
1207
1207
1208 To pull only a subset of changesets, specify one or more revisions
1208 To pull only a subset of changesets, specify one or more revisions
1209 identifiers with -r/--rev or branches with -b/--branch. The
1209 identifiers with -r/--rev or branches with -b/--branch. The
1210 resulting clone will contain only the specified changesets and
1210 resulting clone will contain only the specified changesets and
1211 their ancestors. These options (or 'clone src#rev dest') imply
1211 their ancestors. These options (or 'clone src#rev dest') imply
1212 --pull, even for local source repositories. Note that specifying a
1212 --pull, even for local source repositories. Note that specifying a
1213 tag will include the tagged changeset but not the changeset
1213 tag will include the tagged changeset but not the changeset
1214 containing the tag.
1214 containing the tag.
1215
1215
1216 If the source repository has a bookmark called '@' set, that
1216 If the source repository has a bookmark called '@' set, that
1217 revision will be checked out in the new repository by default.
1217 revision will be checked out in the new repository by default.
1218
1218
1219 To check out a particular version, use -u/--update, or
1219 To check out a particular version, use -u/--update, or
1220 -U/--noupdate to create a clone with no working directory.
1220 -U/--noupdate to create a clone with no working directory.
1221
1221
1222 .. container:: verbose
1222 .. container:: verbose
1223
1223
1224 For efficiency, hardlinks are used for cloning whenever the
1224 For efficiency, hardlinks are used for cloning whenever the
1225 source and destination are on the same filesystem (note this
1225 source and destination are on the same filesystem (note this
1226 applies only to the repository data, not to the working
1226 applies only to the repository data, not to the working
1227 directory). Some filesystems, such as AFS, implement hardlinking
1227 directory). Some filesystems, such as AFS, implement hardlinking
1228 incorrectly, but do not report errors. In these cases, use the
1228 incorrectly, but do not report errors. In these cases, use the
1229 --pull option to avoid hardlinking.
1229 --pull option to avoid hardlinking.
1230
1230
1231 In some cases, you can clone repositories and the working
1231 In some cases, you can clone repositories and the working
1232 directory using full hardlinks with ::
1232 directory using full hardlinks with ::
1233
1233
1234 $ cp -al REPO REPOCLONE
1234 $ cp -al REPO REPOCLONE
1235
1235
1236 This is the fastest way to clone, but it is not always safe. The
1236 This is the fastest way to clone, but it is not always safe. The
1237 operation is not atomic (making sure REPO is not modified during
1237 operation is not atomic (making sure REPO is not modified during
1238 the operation is up to you) and you have to make sure your
1238 the operation is up to you) and you have to make sure your
1239 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1239 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1240 so). Also, this is not compatible with certain extensions that
1240 so). Also, this is not compatible with certain extensions that
1241 place their metadata under the .hg directory, such as mq.
1241 place their metadata under the .hg directory, such as mq.
1242
1242
1243 Mercurial will update the working directory to the first applicable
1243 Mercurial will update the working directory to the first applicable
1244 revision from this list:
1244 revision from this list:
1245
1245
1246 a) null if -U or the source repository has no changesets
1246 a) null if -U or the source repository has no changesets
1247 b) if -u . and the source repository is local, the first parent of
1247 b) if -u . and the source repository is local, the first parent of
1248 the source repository's working directory
1248 the source repository's working directory
1249 c) the changeset specified with -u (if a branch name, this means the
1249 c) the changeset specified with -u (if a branch name, this means the
1250 latest head of that branch)
1250 latest head of that branch)
1251 d) the changeset specified with -r
1251 d) the changeset specified with -r
1252 e) the tipmost head specified with -b
1252 e) the tipmost head specified with -b
1253 f) the tipmost head specified with the url#branch source syntax
1253 f) the tipmost head specified with the url#branch source syntax
1254 g) the revision marked with the '@' bookmark, if present
1254 g) the revision marked with the '@' bookmark, if present
1255 h) the tipmost head of the default branch
1255 h) the tipmost head of the default branch
1256 i) tip
1256 i) tip
1257
1257
1258 Examples:
1258 Examples:
1259
1259
1260 - clone a remote repository to a new directory named hg/::
1260 - clone a remote repository to a new directory named hg/::
1261
1261
1262 hg clone http://selenic.com/hg
1262 hg clone http://selenic.com/hg
1263
1263
1264 - create a lightweight local clone::
1264 - create a lightweight local clone::
1265
1265
1266 hg clone project/ project-feature/
1266 hg clone project/ project-feature/
1267
1267
1268 - clone from an absolute path on an ssh server (note double-slash)::
1268 - clone from an absolute path on an ssh server (note double-slash)::
1269
1269
1270 hg clone ssh://user@server//home/projects/alpha/
1270 hg clone ssh://user@server//home/projects/alpha/
1271
1271
1272 - do a high-speed clone over a LAN while checking out a
1272 - do a high-speed clone over a LAN while checking out a
1273 specified version::
1273 specified version::
1274
1274
1275 hg clone --uncompressed http://server/repo -u 1.5
1275 hg clone --uncompressed http://server/repo -u 1.5
1276
1276
1277 - create a repository without changesets after a particular revision::
1277 - create a repository without changesets after a particular revision::
1278
1278
1279 hg clone -r 04e544 experimental/ good/
1279 hg clone -r 04e544 experimental/ good/
1280
1280
1281 - clone (and track) a particular named branch::
1281 - clone (and track) a particular named branch::
1282
1282
1283 hg clone http://selenic.com/hg#stable
1283 hg clone http://selenic.com/hg#stable
1284
1284
1285 See :hg:`help urls` for details on specifying URLs.
1285 See :hg:`help urls` for details on specifying URLs.
1286
1286
1287 Returns 0 on success.
1287 Returns 0 on success.
1288 """
1288 """
1289 if opts.get('noupdate') and opts.get('updaterev'):
1289 if opts.get('noupdate') and opts.get('updaterev'):
1290 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1290 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1291
1291
1292 r = hg.clone(ui, opts, source, dest,
1292 r = hg.clone(ui, opts, source, dest,
1293 pull=opts.get('pull'),
1293 pull=opts.get('pull'),
1294 stream=opts.get('uncompressed'),
1294 stream=opts.get('uncompressed'),
1295 rev=opts.get('rev'),
1295 rev=opts.get('rev'),
1296 update=opts.get('updaterev') or not opts.get('noupdate'),
1296 update=opts.get('updaterev') or not opts.get('noupdate'),
1297 branch=opts.get('branch'))
1297 branch=opts.get('branch'))
1298
1298
1299 return r is None
1299 return r is None
1300
1300
1301 @command('^commit|ci',
1301 @command('^commit|ci',
1302 [('A', 'addremove', None,
1302 [('A', 'addremove', None,
1303 _('mark new/missing files as added/removed before committing')),
1303 _('mark new/missing files as added/removed before committing')),
1304 ('', 'close-branch', None,
1304 ('', 'close-branch', None,
1305 _('mark a branch as closed, hiding it from the branch list')),
1305 _('mark a branch as closed, hiding it from the branch list')),
1306 ('', 'amend', None, _('amend the parent of the working dir')),
1306 ('', 'amend', None, _('amend the parent of the working dir')),
1307 ('s', 'secret', None, _('use the secret phase for committing')),
1307 ('s', 'secret', None, _('use the secret phase for committing')),
1308 ('e', 'edit', None,
1308 ('e', 'edit', None,
1309 _('further edit commit message already specified')),
1309 _('further edit commit message already specified')),
1310 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1310 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1311 _('[OPTION]... [FILE]...'))
1311 _('[OPTION]... [FILE]...'))
1312 def commit(ui, repo, *pats, **opts):
1312 def commit(ui, repo, *pats, **opts):
1313 """commit the specified files or all outstanding changes
1313 """commit the specified files or all outstanding changes
1314
1314
1315 Commit changes to the given files into the repository. Unlike a
1315 Commit changes to the given files into the repository. Unlike a
1316 centralized SCM, this operation is a local operation. See
1316 centralized SCM, this operation is a local operation. See
1317 :hg:`push` for a way to actively distribute your changes.
1317 :hg:`push` for a way to actively distribute your changes.
1318
1318
1319 If a list of files is omitted, all changes reported by :hg:`status`
1319 If a list of files is omitted, all changes reported by :hg:`status`
1320 will be committed.
1320 will be committed.
1321
1321
1322 If you are committing the result of a merge, do not provide any
1322 If you are committing the result of a merge, do not provide any
1323 filenames or -I/-X filters.
1323 filenames or -I/-X filters.
1324
1324
1325 If no commit message is specified, Mercurial starts your
1325 If no commit message is specified, Mercurial starts your
1326 configured editor where you can enter a message. In case your
1326 configured editor where you can enter a message. In case your
1327 commit fails, you will find a backup of your message in
1327 commit fails, you will find a backup of your message in
1328 ``.hg/last-message.txt``.
1328 ``.hg/last-message.txt``.
1329
1329
1330 The --amend flag can be used to amend the parent of the
1330 The --amend flag can be used to amend the parent of the
1331 working directory with a new commit that contains the changes
1331 working directory with a new commit that contains the changes
1332 in the parent in addition to those currently reported by :hg:`status`,
1332 in the parent in addition to those currently reported by :hg:`status`,
1333 if there are any. The old commit is stored in a backup bundle in
1333 if there are any. The old commit is stored in a backup bundle in
1334 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1334 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1335 on how to restore it).
1335 on how to restore it).
1336
1336
1337 Message, user and date are taken from the amended commit unless
1337 Message, user and date are taken from the amended commit unless
1338 specified. When a message isn't specified on the command line,
1338 specified. When a message isn't specified on the command line,
1339 the editor will open with the message of the amended commit.
1339 the editor will open with the message of the amended commit.
1340
1340
1341 It is not possible to amend public changesets (see :hg:`help phases`)
1341 It is not possible to amend public changesets (see :hg:`help phases`)
1342 or changesets that have children.
1342 or changesets that have children.
1343
1343
1344 See :hg:`help dates` for a list of formats valid for -d/--date.
1344 See :hg:`help dates` for a list of formats valid for -d/--date.
1345
1345
1346 Returns 0 on success, 1 if nothing changed.
1346 Returns 0 on success, 1 if nothing changed.
1347 """
1347 """
1348 forceeditor = opts.get('edit')
1348 forceeditor = opts.get('edit')
1349
1349
1350 if opts.get('subrepos'):
1350 if opts.get('subrepos'):
1351 if opts.get('amend'):
1351 if opts.get('amend'):
1352 raise util.Abort(_('cannot amend with --subrepos'))
1352 raise util.Abort(_('cannot amend with --subrepos'))
1353 # Let --subrepos on the command line override config setting.
1353 # Let --subrepos on the command line override config setting.
1354 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1354 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1355
1355
1356 # Save this for restoring it later
1356 # Save this for restoring it later
1357 oldcommitphase = ui.config('phases', 'new-commit')
1357 oldcommitphase = ui.config('phases', 'new-commit')
1358
1358
1359 cmdutil.checkunfinished(repo, commit=True)
1359 cmdutil.checkunfinished(repo, commit=True)
1360
1360
1361 branch = repo[None].branch()
1361 branch = repo[None].branch()
1362 bheads = repo.branchheads(branch)
1362 bheads = repo.branchheads(branch)
1363
1363
1364 extra = {}
1364 extra = {}
1365 if opts.get('close_branch'):
1365 if opts.get('close_branch'):
1366 extra['close'] = 1
1366 extra['close'] = 1
1367
1367
1368 if not bheads:
1368 if not bheads:
1369 raise util.Abort(_('can only close branch heads'))
1369 raise util.Abort(_('can only close branch heads'))
1370 elif opts.get('amend'):
1370 elif opts.get('amend'):
1371 if repo.parents()[0].p1().branch() != branch and \
1371 if repo.parents()[0].p1().branch() != branch and \
1372 repo.parents()[0].p2().branch() != branch:
1372 repo.parents()[0].p2().branch() != branch:
1373 raise util.Abort(_('can only close branch heads'))
1373 raise util.Abort(_('can only close branch heads'))
1374
1374
1375 if opts.get('amend'):
1375 if opts.get('amend'):
1376 if ui.configbool('ui', 'commitsubrepos'):
1376 if ui.configbool('ui', 'commitsubrepos'):
1377 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1377 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1378
1378
1379 old = repo['.']
1379 old = repo['.']
1380 if old.phase() == phases.public:
1380 if old.phase() == phases.public:
1381 raise util.Abort(_('cannot amend public changesets'))
1381 raise util.Abort(_('cannot amend public changesets'))
1382 if len(repo[None].parents()) > 1:
1382 if len(repo[None].parents()) > 1:
1383 raise util.Abort(_('cannot amend while merging'))
1383 raise util.Abort(_('cannot amend while merging'))
1384 if (not obsolete._enabled) and old.children():
1384 if (not obsolete._enabled) and old.children():
1385 raise util.Abort(_('cannot amend changeset with children'))
1385 raise util.Abort(_('cannot amend changeset with children'))
1386
1386
1387 # commitfunc is used only for temporary amend commit by cmdutil.amend
1387 # commitfunc is used only for temporary amend commit by cmdutil.amend
1388 def commitfunc(ui, repo, message, match, opts):
1388 def commitfunc(ui, repo, message, match, opts):
1389 return repo.commit(message,
1389 return repo.commit(message,
1390 opts.get('user') or old.user(),
1390 opts.get('user') or old.user(),
1391 opts.get('date') or old.date(),
1391 opts.get('date') or old.date(),
1392 match,
1392 match,
1393 extra=extra)
1393 extra=extra)
1394
1394
1395 current = repo._bookmarkcurrent
1395 current = repo._bookmarkcurrent
1396 marks = old.bookmarks()
1396 marks = old.bookmarks()
1397 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1397 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1398 if node == old.node():
1398 if node == old.node():
1399 ui.status(_("nothing changed\n"))
1399 ui.status(_("nothing changed\n"))
1400 return 1
1400 return 1
1401 elif marks:
1401 elif marks:
1402 ui.debug('moving bookmarks %r from %s to %s\n' %
1402 ui.debug('moving bookmarks %r from %s to %s\n' %
1403 (marks, old.hex(), hex(node)))
1403 (marks, old.hex(), hex(node)))
1404 newmarks = repo._bookmarks
1404 newmarks = repo._bookmarks
1405 for bm in marks:
1405 for bm in marks:
1406 newmarks[bm] = node
1406 newmarks[bm] = node
1407 if bm == current:
1407 if bm == current:
1408 bookmarks.setcurrent(repo, bm)
1408 bookmarks.setcurrent(repo, bm)
1409 newmarks.write()
1409 newmarks.write()
1410 else:
1410 else:
1411 e = cmdutil.commiteditor
1411 e = cmdutil.commiteditor
1412 if forceeditor:
1412 if forceeditor:
1413 e = cmdutil.commitforceeditor
1413 e = cmdutil.commitforceeditor
1414
1414
1415 def commitfunc(ui, repo, message, match, opts):
1415 def commitfunc(ui, repo, message, match, opts):
1416 try:
1416 try:
1417 if opts.get('secret'):
1417 if opts.get('secret'):
1418 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1418 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1419 # Propagate to subrepos
1419 # Propagate to subrepos
1420 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1420 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1421 'commit')
1421 'commit')
1422
1422
1423 return repo.commit(message, opts.get('user'), opts.get('date'),
1423 return repo.commit(message, opts.get('user'), opts.get('date'),
1424 match, editor=e, extra=extra)
1424 match, editor=e, extra=extra)
1425 finally:
1425 finally:
1426 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1426 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1427 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1427 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1428 'commit')
1428 'commit')
1429
1429
1430
1430
1431 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1431 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1432
1432
1433 if not node:
1433 if not node:
1434 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1434 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1435 if stat[3]:
1435 if stat[3]:
1436 ui.status(_("nothing changed (%d missing files, see "
1436 ui.status(_("nothing changed (%d missing files, see "
1437 "'hg status')\n") % len(stat[3]))
1437 "'hg status')\n") % len(stat[3]))
1438 else:
1438 else:
1439 ui.status(_("nothing changed\n"))
1439 ui.status(_("nothing changed\n"))
1440 return 1
1440 return 1
1441
1441
1442 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1442 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1443
1443
1444 @command('config|showconfig|debugconfig',
1444 @command('config|showconfig|debugconfig',
1445 [('u', 'untrusted', None, _('show untrusted configuration options')),
1445 [('u', 'untrusted', None, _('show untrusted configuration options')),
1446 ('e', 'edit', None, _('edit user config')),
1446 ('e', 'edit', None, _('edit user config')),
1447 ('l', 'local', None, _('edit repository config')),
1447 ('l', 'local', None, _('edit repository config')),
1448 ('g', 'global', None, _('edit global config'))],
1448 ('g', 'global', None, _('edit global config'))],
1449 _('[-u] [NAME]...'))
1449 _('[-u] [NAME]...'))
1450 def config(ui, repo, *values, **opts):
1450 def config(ui, repo, *values, **opts):
1451 """show combined config settings from all hgrc files
1451 """show combined config settings from all hgrc files
1452
1452
1453 With no arguments, print names and values of all config items.
1453 With no arguments, print names and values of all config items.
1454
1454
1455 With one argument of the form section.name, print just the value
1455 With one argument of the form section.name, print just the value
1456 of that config item.
1456 of that config item.
1457
1457
1458 With multiple arguments, print names and values of all config
1458 With multiple arguments, print names and values of all config
1459 items with matching section names.
1459 items with matching section names.
1460
1460
1461 With --edit, start an editor on the user-level config file. With
1461 With --edit, start an editor on the user-level config file. With
1462 --global, edit the system-wide config file. With --local, edit the
1462 --global, edit the system-wide config file. With --local, edit the
1463 repository-level config file.
1463 repository-level config file.
1464
1464
1465 With --debug, the source (filename and line number) is printed
1465 With --debug, the source (filename and line number) is printed
1466 for each config item.
1466 for each config item.
1467
1467
1468 See :hg:`help config` for more information about config files.
1468 See :hg:`help config` for more information about config files.
1469
1469
1470 Returns 0 on success.
1470 Returns 0 on success.
1471
1471
1472 """
1472 """
1473
1473
1474 if opts.get('edit') or opts.get('local') or opts.get('global'):
1474 if opts.get('edit') or opts.get('local') or opts.get('global'):
1475 if opts.get('local') and opts.get('global'):
1475 if opts.get('local') and opts.get('global'):
1476 raise util.Abort(_("can't use --local and --global together"))
1476 raise util.Abort(_("can't use --local and --global together"))
1477
1477
1478 if opts.get('local'):
1478 if opts.get('local'):
1479 if not repo:
1479 if not repo:
1480 raise util.Abort(_("can't use --local outside a repository"))
1480 raise util.Abort(_("can't use --local outside a repository"))
1481 paths = [repo.join('hgrc')]
1481 paths = [repo.join('hgrc')]
1482 elif opts.get('global'):
1482 elif opts.get('global'):
1483 paths = scmutil.systemrcpath()
1483 paths = scmutil.systemrcpath()
1484 else:
1484 else:
1485 paths = scmutil.userrcpath()
1485 paths = scmutil.userrcpath()
1486
1486
1487 for f in paths:
1487 for f in paths:
1488 if os.path.exists(f):
1488 if os.path.exists(f):
1489 break
1489 break
1490 else:
1490 else:
1491 f = paths[0]
1491 f = paths[0]
1492 fp = open(f, "w")
1492 fp = open(f, "w")
1493 fp.write(
1493 fp.write(
1494 '# example config (see "hg help config" for more info)\n'
1494 '# example config (see "hg help config" for more info)\n'
1495 '\n'
1495 '\n'
1496 '[ui]\n'
1496 '[ui]\n'
1497 '# name and email, e.g.\n'
1497 '# name and email, e.g.\n'
1498 '# username = Jane Doe <jdoe@example.com>\n'
1498 '# username = Jane Doe <jdoe@example.com>\n'
1499 'username =\n'
1499 'username =\n'
1500 '\n'
1500 '\n'
1501 '[extensions]\n'
1501 '[extensions]\n'
1502 '# uncomment these lines to enable some popular extensions\n'
1502 '# uncomment these lines to enable some popular extensions\n'
1503 '# (see "hg help extensions" for more info)\n'
1503 '# (see "hg help extensions" for more info)\n'
1504 '# pager =\n'
1504 '# pager =\n'
1505 '# progress =\n'
1505 '# progress =\n'
1506 '# color =\n')
1506 '# color =\n')
1507 fp.close()
1507 fp.close()
1508
1508
1509 editor = ui.geteditor()
1509 editor = ui.geteditor()
1510 util.system("%s \"%s\"" % (editor, f),
1510 util.system("%s \"%s\"" % (editor, f),
1511 onerr=util.Abort, errprefix=_("edit failed"),
1511 onerr=util.Abort, errprefix=_("edit failed"),
1512 out=ui.fout)
1512 out=ui.fout)
1513 return
1513 return
1514
1514
1515 for f in scmutil.rcpath():
1515 for f in scmutil.rcpath():
1516 ui.debug('read config from: %s\n' % f)
1516 ui.debug('read config from: %s\n' % f)
1517 untrusted = bool(opts.get('untrusted'))
1517 untrusted = bool(opts.get('untrusted'))
1518 if values:
1518 if values:
1519 sections = [v for v in values if '.' not in v]
1519 sections = [v for v in values if '.' not in v]
1520 items = [v for v in values if '.' in v]
1520 items = [v for v in values if '.' in v]
1521 if len(items) > 1 or items and sections:
1521 if len(items) > 1 or items and sections:
1522 raise util.Abort(_('only one config item permitted'))
1522 raise util.Abort(_('only one config item permitted'))
1523 for section, name, value in ui.walkconfig(untrusted=untrusted):
1523 for section, name, value in ui.walkconfig(untrusted=untrusted):
1524 value = str(value).replace('\n', '\\n')
1524 value = str(value).replace('\n', '\\n')
1525 sectname = section + '.' + name
1525 sectname = section + '.' + name
1526 if values:
1526 if values:
1527 for v in values:
1527 for v in values:
1528 if v == section:
1528 if v == section:
1529 ui.debug('%s: ' %
1529 ui.debug('%s: ' %
1530 ui.configsource(section, name, untrusted))
1530 ui.configsource(section, name, untrusted))
1531 ui.write('%s=%s\n' % (sectname, value))
1531 ui.write('%s=%s\n' % (sectname, value))
1532 elif v == sectname:
1532 elif v == sectname:
1533 ui.debug('%s: ' %
1533 ui.debug('%s: ' %
1534 ui.configsource(section, name, untrusted))
1534 ui.configsource(section, name, untrusted))
1535 ui.write(value, '\n')
1535 ui.write(value, '\n')
1536 else:
1536 else:
1537 ui.debug('%s: ' %
1537 ui.debug('%s: ' %
1538 ui.configsource(section, name, untrusted))
1538 ui.configsource(section, name, untrusted))
1539 ui.write('%s=%s\n' % (sectname, value))
1539 ui.write('%s=%s\n' % (sectname, value))
1540
1540
1541 @command('copy|cp',
1541 @command('copy|cp',
1542 [('A', 'after', None, _('record a copy that has already occurred')),
1542 [('A', 'after', None, _('record a copy that has already occurred')),
1543 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1543 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1544 ] + walkopts + dryrunopts,
1544 ] + walkopts + dryrunopts,
1545 _('[OPTION]... [SOURCE]... DEST'))
1545 _('[OPTION]... [SOURCE]... DEST'))
1546 def copy(ui, repo, *pats, **opts):
1546 def copy(ui, repo, *pats, **opts):
1547 """mark files as copied for the next commit
1547 """mark files as copied for the next commit
1548
1548
1549 Mark dest as having copies of source files. If dest is a
1549 Mark dest as having copies of source files. If dest is a
1550 directory, copies are put in that directory. If dest is a file,
1550 directory, copies are put in that directory. If dest is a file,
1551 the source must be a single file.
1551 the source must be a single file.
1552
1552
1553 By default, this command copies the contents of files as they
1553 By default, this command copies the contents of files as they
1554 exist in the working directory. If invoked with -A/--after, the
1554 exist in the working directory. If invoked with -A/--after, the
1555 operation is recorded, but no copying is performed.
1555 operation is recorded, but no copying is performed.
1556
1556
1557 This command takes effect with the next commit. To undo a copy
1557 This command takes effect with the next commit. To undo a copy
1558 before that, see :hg:`revert`.
1558 before that, see :hg:`revert`.
1559
1559
1560 Returns 0 on success, 1 if errors are encountered.
1560 Returns 0 on success, 1 if errors are encountered.
1561 """
1561 """
1562 wlock = repo.wlock(False)
1562 wlock = repo.wlock(False)
1563 try:
1563 try:
1564 return cmdutil.copy(ui, repo, pats, opts)
1564 return cmdutil.copy(ui, repo, pats, opts)
1565 finally:
1565 finally:
1566 wlock.release()
1566 wlock.release()
1567
1567
1568 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1568 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1569 def debugancestor(ui, repo, *args):
1569 def debugancestor(ui, repo, *args):
1570 """find the ancestor revision of two revisions in a given index"""
1570 """find the ancestor revision of two revisions in a given index"""
1571 if len(args) == 3:
1571 if len(args) == 3:
1572 index, rev1, rev2 = args
1572 index, rev1, rev2 = args
1573 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1573 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1574 lookup = r.lookup
1574 lookup = r.lookup
1575 elif len(args) == 2:
1575 elif len(args) == 2:
1576 if not repo:
1576 if not repo:
1577 raise util.Abort(_("there is no Mercurial repository here "
1577 raise util.Abort(_("there is no Mercurial repository here "
1578 "(.hg not found)"))
1578 "(.hg not found)"))
1579 rev1, rev2 = args
1579 rev1, rev2 = args
1580 r = repo.changelog
1580 r = repo.changelog
1581 lookup = repo.lookup
1581 lookup = repo.lookup
1582 else:
1582 else:
1583 raise util.Abort(_('either two or three arguments required'))
1583 raise util.Abort(_('either two or three arguments required'))
1584 a = r.ancestor(lookup(rev1), lookup(rev2))
1584 a = r.ancestor(lookup(rev1), lookup(rev2))
1585 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1585 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1586
1586
1587 @command('debugbuilddag',
1587 @command('debugbuilddag',
1588 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1588 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1589 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1589 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1590 ('n', 'new-file', None, _('add new file at each rev'))],
1590 ('n', 'new-file', None, _('add new file at each rev'))],
1591 _('[OPTION]... [TEXT]'))
1591 _('[OPTION]... [TEXT]'))
1592 def debugbuilddag(ui, repo, text=None,
1592 def debugbuilddag(ui, repo, text=None,
1593 mergeable_file=False,
1593 mergeable_file=False,
1594 overwritten_file=False,
1594 overwritten_file=False,
1595 new_file=False):
1595 new_file=False):
1596 """builds a repo with a given DAG from scratch in the current empty repo
1596 """builds a repo with a given DAG from scratch in the current empty repo
1597
1597
1598 The description of the DAG is read from stdin if not given on the
1598 The description of the DAG is read from stdin if not given on the
1599 command line.
1599 command line.
1600
1600
1601 Elements:
1601 Elements:
1602
1602
1603 - "+n" is a linear run of n nodes based on the current default parent
1603 - "+n" is a linear run of n nodes based on the current default parent
1604 - "." is a single node based on the current default parent
1604 - "." is a single node based on the current default parent
1605 - "$" resets the default parent to null (implied at the start);
1605 - "$" resets the default parent to null (implied at the start);
1606 otherwise the default parent is always the last node created
1606 otherwise the default parent is always the last node created
1607 - "<p" sets the default parent to the backref p
1607 - "<p" sets the default parent to the backref p
1608 - "*p" is a fork at parent p, which is a backref
1608 - "*p" is a fork at parent p, which is a backref
1609 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1609 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1610 - "/p2" is a merge of the preceding node and p2
1610 - "/p2" is a merge of the preceding node and p2
1611 - ":tag" defines a local tag for the preceding node
1611 - ":tag" defines a local tag for the preceding node
1612 - "@branch" sets the named branch for subsequent nodes
1612 - "@branch" sets the named branch for subsequent nodes
1613 - "#...\\n" is a comment up to the end of the line
1613 - "#...\\n" is a comment up to the end of the line
1614
1614
1615 Whitespace between the above elements is ignored.
1615 Whitespace between the above elements is ignored.
1616
1616
1617 A backref is either
1617 A backref is either
1618
1618
1619 - a number n, which references the node curr-n, where curr is the current
1619 - a number n, which references the node curr-n, where curr is the current
1620 node, or
1620 node, or
1621 - the name of a local tag you placed earlier using ":tag", or
1621 - the name of a local tag you placed earlier using ":tag", or
1622 - empty to denote the default parent.
1622 - empty to denote the default parent.
1623
1623
1624 All string valued-elements are either strictly alphanumeric, or must
1624 All string valued-elements are either strictly alphanumeric, or must
1625 be enclosed in double quotes ("..."), with "\\" as escape character.
1625 be enclosed in double quotes ("..."), with "\\" as escape character.
1626 """
1626 """
1627
1627
1628 if text is None:
1628 if text is None:
1629 ui.status(_("reading DAG from stdin\n"))
1629 ui.status(_("reading DAG from stdin\n"))
1630 text = ui.fin.read()
1630 text = ui.fin.read()
1631
1631
1632 cl = repo.changelog
1632 cl = repo.changelog
1633 if len(cl) > 0:
1633 if len(cl) > 0:
1634 raise util.Abort(_('repository is not empty'))
1634 raise util.Abort(_('repository is not empty'))
1635
1635
1636 # determine number of revs in DAG
1636 # determine number of revs in DAG
1637 total = 0
1637 total = 0
1638 for type, data in dagparser.parsedag(text):
1638 for type, data in dagparser.parsedag(text):
1639 if type == 'n':
1639 if type == 'n':
1640 total += 1
1640 total += 1
1641
1641
1642 if mergeable_file:
1642 if mergeable_file:
1643 linesperrev = 2
1643 linesperrev = 2
1644 # make a file with k lines per rev
1644 # make a file with k lines per rev
1645 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1645 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1646 initialmergedlines.append("")
1646 initialmergedlines.append("")
1647
1647
1648 tags = []
1648 tags = []
1649
1649
1650 lock = tr = None
1650 lock = tr = None
1651 try:
1651 try:
1652 lock = repo.lock()
1652 lock = repo.lock()
1653 tr = repo.transaction("builddag")
1653 tr = repo.transaction("builddag")
1654
1654
1655 at = -1
1655 at = -1
1656 atbranch = 'default'
1656 atbranch = 'default'
1657 nodeids = []
1657 nodeids = []
1658 id = 0
1658 id = 0
1659 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1659 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1660 for type, data in dagparser.parsedag(text):
1660 for type, data in dagparser.parsedag(text):
1661 if type == 'n':
1661 if type == 'n':
1662 ui.note(('node %s\n' % str(data)))
1662 ui.note(('node %s\n' % str(data)))
1663 id, ps = data
1663 id, ps = data
1664
1664
1665 files = []
1665 files = []
1666 fctxs = {}
1666 fctxs = {}
1667
1667
1668 p2 = None
1668 p2 = None
1669 if mergeable_file:
1669 if mergeable_file:
1670 fn = "mf"
1670 fn = "mf"
1671 p1 = repo[ps[0]]
1671 p1 = repo[ps[0]]
1672 if len(ps) > 1:
1672 if len(ps) > 1:
1673 p2 = repo[ps[1]]
1673 p2 = repo[ps[1]]
1674 pa = p1.ancestor(p2)
1674 pa = p1.ancestor(p2)
1675 base, local, other = [x[fn].data() for x in (pa, p1,
1675 base, local, other = [x[fn].data() for x in (pa, p1,
1676 p2)]
1676 p2)]
1677 m3 = simplemerge.Merge3Text(base, local, other)
1677 m3 = simplemerge.Merge3Text(base, local, other)
1678 ml = [l.strip() for l in m3.merge_lines()]
1678 ml = [l.strip() for l in m3.merge_lines()]
1679 ml.append("")
1679 ml.append("")
1680 elif at > 0:
1680 elif at > 0:
1681 ml = p1[fn].data().split("\n")
1681 ml = p1[fn].data().split("\n")
1682 else:
1682 else:
1683 ml = initialmergedlines
1683 ml = initialmergedlines
1684 ml[id * linesperrev] += " r%i" % id
1684 ml[id * linesperrev] += " r%i" % id
1685 mergedtext = "\n".join(ml)
1685 mergedtext = "\n".join(ml)
1686 files.append(fn)
1686 files.append(fn)
1687 fctxs[fn] = context.memfilectx(fn, mergedtext)
1687 fctxs[fn] = context.memfilectx(fn, mergedtext)
1688
1688
1689 if overwritten_file:
1689 if overwritten_file:
1690 fn = "of"
1690 fn = "of"
1691 files.append(fn)
1691 files.append(fn)
1692 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1692 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1693
1693
1694 if new_file:
1694 if new_file:
1695 fn = "nf%i" % id
1695 fn = "nf%i" % id
1696 files.append(fn)
1696 files.append(fn)
1697 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1697 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1698 if len(ps) > 1:
1698 if len(ps) > 1:
1699 if not p2:
1699 if not p2:
1700 p2 = repo[ps[1]]
1700 p2 = repo[ps[1]]
1701 for fn in p2:
1701 for fn in p2:
1702 if fn.startswith("nf"):
1702 if fn.startswith("nf"):
1703 files.append(fn)
1703 files.append(fn)
1704 fctxs[fn] = p2[fn]
1704 fctxs[fn] = p2[fn]
1705
1705
1706 def fctxfn(repo, cx, path):
1706 def fctxfn(repo, cx, path):
1707 return fctxs.get(path)
1707 return fctxs.get(path)
1708
1708
1709 if len(ps) == 0 or ps[0] < 0:
1709 if len(ps) == 0 or ps[0] < 0:
1710 pars = [None, None]
1710 pars = [None, None]
1711 elif len(ps) == 1:
1711 elif len(ps) == 1:
1712 pars = [nodeids[ps[0]], None]
1712 pars = [nodeids[ps[0]], None]
1713 else:
1713 else:
1714 pars = [nodeids[p] for p in ps]
1714 pars = [nodeids[p] for p in ps]
1715 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1715 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1716 date=(id, 0),
1716 date=(id, 0),
1717 user="debugbuilddag",
1717 user="debugbuilddag",
1718 extra={'branch': atbranch})
1718 extra={'branch': atbranch})
1719 nodeid = repo.commitctx(cx)
1719 nodeid = repo.commitctx(cx)
1720 nodeids.append(nodeid)
1720 nodeids.append(nodeid)
1721 at = id
1721 at = id
1722 elif type == 'l':
1722 elif type == 'l':
1723 id, name = data
1723 id, name = data
1724 ui.note(('tag %s\n' % name))
1724 ui.note(('tag %s\n' % name))
1725 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1725 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1726 elif type == 'a':
1726 elif type == 'a':
1727 ui.note(('branch %s\n' % data))
1727 ui.note(('branch %s\n' % data))
1728 atbranch = data
1728 atbranch = data
1729 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1729 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1730 tr.close()
1730 tr.close()
1731
1731
1732 if tags:
1732 if tags:
1733 repo.opener.write("localtags", "".join(tags))
1733 repo.opener.write("localtags", "".join(tags))
1734 finally:
1734 finally:
1735 ui.progress(_('building'), None)
1735 ui.progress(_('building'), None)
1736 release(tr, lock)
1736 release(tr, lock)
1737
1737
1738 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1738 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1739 def debugbundle(ui, bundlepath, all=None, **opts):
1739 def debugbundle(ui, bundlepath, all=None, **opts):
1740 """lists the contents of a bundle"""
1740 """lists the contents of a bundle"""
1741 f = hg.openpath(ui, bundlepath)
1741 f = hg.openpath(ui, bundlepath)
1742 try:
1742 try:
1743 gen = exchange.readbundle(ui, f, bundlepath)
1743 gen = exchange.readbundle(ui, f, bundlepath)
1744 if all:
1744 if all:
1745 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1745 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1746
1746
1747 def showchunks(named):
1747 def showchunks(named):
1748 ui.write("\n%s\n" % named)
1748 ui.write("\n%s\n" % named)
1749 chain = None
1749 chain = None
1750 while True:
1750 while True:
1751 chunkdata = gen.deltachunk(chain)
1751 chunkdata = gen.deltachunk(chain)
1752 if not chunkdata:
1752 if not chunkdata:
1753 break
1753 break
1754 node = chunkdata['node']
1754 node = chunkdata['node']
1755 p1 = chunkdata['p1']
1755 p1 = chunkdata['p1']
1756 p2 = chunkdata['p2']
1756 p2 = chunkdata['p2']
1757 cs = chunkdata['cs']
1757 cs = chunkdata['cs']
1758 deltabase = chunkdata['deltabase']
1758 deltabase = chunkdata['deltabase']
1759 delta = chunkdata['delta']
1759 delta = chunkdata['delta']
1760 ui.write("%s %s %s %s %s %s\n" %
1760 ui.write("%s %s %s %s %s %s\n" %
1761 (hex(node), hex(p1), hex(p2),
1761 (hex(node), hex(p1), hex(p2),
1762 hex(cs), hex(deltabase), len(delta)))
1762 hex(cs), hex(deltabase), len(delta)))
1763 chain = node
1763 chain = node
1764
1764
1765 chunkdata = gen.changelogheader()
1765 chunkdata = gen.changelogheader()
1766 showchunks("changelog")
1766 showchunks("changelog")
1767 chunkdata = gen.manifestheader()
1767 chunkdata = gen.manifestheader()
1768 showchunks("manifest")
1768 showchunks("manifest")
1769 while True:
1769 while True:
1770 chunkdata = gen.filelogheader()
1770 chunkdata = gen.filelogheader()
1771 if not chunkdata:
1771 if not chunkdata:
1772 break
1772 break
1773 fname = chunkdata['filename']
1773 fname = chunkdata['filename']
1774 showchunks(fname)
1774 showchunks(fname)
1775 else:
1775 else:
1776 chunkdata = gen.changelogheader()
1776 chunkdata = gen.changelogheader()
1777 chain = None
1777 chain = None
1778 while True:
1778 while True:
1779 chunkdata = gen.deltachunk(chain)
1779 chunkdata = gen.deltachunk(chain)
1780 if not chunkdata:
1780 if not chunkdata:
1781 break
1781 break
1782 node = chunkdata['node']
1782 node = chunkdata['node']
1783 ui.write("%s\n" % hex(node))
1783 ui.write("%s\n" % hex(node))
1784 chain = node
1784 chain = node
1785 finally:
1785 finally:
1786 f.close()
1786 f.close()
1787
1787
1788 @command('debugcheckstate', [], '')
1788 @command('debugcheckstate', [], '')
1789 def debugcheckstate(ui, repo):
1789 def debugcheckstate(ui, repo):
1790 """validate the correctness of the current dirstate"""
1790 """validate the correctness of the current dirstate"""
1791 parent1, parent2 = repo.dirstate.parents()
1791 parent1, parent2 = repo.dirstate.parents()
1792 m1 = repo[parent1].manifest()
1792 m1 = repo[parent1].manifest()
1793 m2 = repo[parent2].manifest()
1793 m2 = repo[parent2].manifest()
1794 errors = 0
1794 errors = 0
1795 for f in repo.dirstate:
1795 for f in repo.dirstate:
1796 state = repo.dirstate[f]
1796 state = repo.dirstate[f]
1797 if state in "nr" and f not in m1:
1797 if state in "nr" and f not in m1:
1798 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1798 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1799 errors += 1
1799 errors += 1
1800 if state in "a" and f in m1:
1800 if state in "a" and f in m1:
1801 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1801 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1802 errors += 1
1802 errors += 1
1803 if state in "m" and f not in m1 and f not in m2:
1803 if state in "m" and f not in m1 and f not in m2:
1804 ui.warn(_("%s in state %s, but not in either manifest\n") %
1804 ui.warn(_("%s in state %s, but not in either manifest\n") %
1805 (f, state))
1805 (f, state))
1806 errors += 1
1806 errors += 1
1807 for f in m1:
1807 for f in m1:
1808 state = repo.dirstate[f]
1808 state = repo.dirstate[f]
1809 if state not in "nrm":
1809 if state not in "nrm":
1810 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1810 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1811 errors += 1
1811 errors += 1
1812 if errors:
1812 if errors:
1813 error = _(".hg/dirstate inconsistent with current parent's manifest")
1813 error = _(".hg/dirstate inconsistent with current parent's manifest")
1814 raise util.Abort(error)
1814 raise util.Abort(error)
1815
1815
1816 @command('debugcommands', [], _('[COMMAND]'))
1816 @command('debugcommands', [], _('[COMMAND]'))
1817 def debugcommands(ui, cmd='', *args):
1817 def debugcommands(ui, cmd='', *args):
1818 """list all available commands and options"""
1818 """list all available commands and options"""
1819 for cmd, vals in sorted(table.iteritems()):
1819 for cmd, vals in sorted(table.iteritems()):
1820 cmd = cmd.split('|')[0].strip('^')
1820 cmd = cmd.split('|')[0].strip('^')
1821 opts = ', '.join([i[1] for i in vals[1]])
1821 opts = ', '.join([i[1] for i in vals[1]])
1822 ui.write('%s: %s\n' % (cmd, opts))
1822 ui.write('%s: %s\n' % (cmd, opts))
1823
1823
1824 @command('debugcomplete',
1824 @command('debugcomplete',
1825 [('o', 'options', None, _('show the command options'))],
1825 [('o', 'options', None, _('show the command options'))],
1826 _('[-o] CMD'))
1826 _('[-o] CMD'))
1827 def debugcomplete(ui, cmd='', **opts):
1827 def debugcomplete(ui, cmd='', **opts):
1828 """returns the completion list associated with the given command"""
1828 """returns the completion list associated with the given command"""
1829
1829
1830 if opts.get('options'):
1830 if opts.get('options'):
1831 options = []
1831 options = []
1832 otables = [globalopts]
1832 otables = [globalopts]
1833 if cmd:
1833 if cmd:
1834 aliases, entry = cmdutil.findcmd(cmd, table, False)
1834 aliases, entry = cmdutil.findcmd(cmd, table, False)
1835 otables.append(entry[1])
1835 otables.append(entry[1])
1836 for t in otables:
1836 for t in otables:
1837 for o in t:
1837 for o in t:
1838 if "(DEPRECATED)" in o[3]:
1838 if "(DEPRECATED)" in o[3]:
1839 continue
1839 continue
1840 if o[0]:
1840 if o[0]:
1841 options.append('-%s' % o[0])
1841 options.append('-%s' % o[0])
1842 options.append('--%s' % o[1])
1842 options.append('--%s' % o[1])
1843 ui.write("%s\n" % "\n".join(options))
1843 ui.write("%s\n" % "\n".join(options))
1844 return
1844 return
1845
1845
1846 cmdlist = cmdutil.findpossible(cmd, table)
1846 cmdlist = cmdutil.findpossible(cmd, table)
1847 if ui.verbose:
1847 if ui.verbose:
1848 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1848 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1849 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1849 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1850
1850
1851 @command('debugdag',
1851 @command('debugdag',
1852 [('t', 'tags', None, _('use tags as labels')),
1852 [('t', 'tags', None, _('use tags as labels')),
1853 ('b', 'branches', None, _('annotate with branch names')),
1853 ('b', 'branches', None, _('annotate with branch names')),
1854 ('', 'dots', None, _('use dots for runs')),
1854 ('', 'dots', None, _('use dots for runs')),
1855 ('s', 'spaces', None, _('separate elements by spaces'))],
1855 ('s', 'spaces', None, _('separate elements by spaces'))],
1856 _('[OPTION]... [FILE [REV]...]'))
1856 _('[OPTION]... [FILE [REV]...]'))
1857 def debugdag(ui, repo, file_=None, *revs, **opts):
1857 def debugdag(ui, repo, file_=None, *revs, **opts):
1858 """format the changelog or an index DAG as a concise textual description
1858 """format the changelog or an index DAG as a concise textual description
1859
1859
1860 If you pass a revlog index, the revlog's DAG is emitted. If you list
1860 If you pass a revlog index, the revlog's DAG is emitted. If you list
1861 revision numbers, they get labeled in the output as rN.
1861 revision numbers, they get labeled in the output as rN.
1862
1862
1863 Otherwise, the changelog DAG of the current repo is emitted.
1863 Otherwise, the changelog DAG of the current repo is emitted.
1864 """
1864 """
1865 spaces = opts.get('spaces')
1865 spaces = opts.get('spaces')
1866 dots = opts.get('dots')
1866 dots = opts.get('dots')
1867 if file_:
1867 if file_:
1868 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1868 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1869 revs = set((int(r) for r in revs))
1869 revs = set((int(r) for r in revs))
1870 def events():
1870 def events():
1871 for r in rlog:
1871 for r in rlog:
1872 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1872 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1873 if p != -1)))
1873 if p != -1)))
1874 if r in revs:
1874 if r in revs:
1875 yield 'l', (r, "r%i" % r)
1875 yield 'l', (r, "r%i" % r)
1876 elif repo:
1876 elif repo:
1877 cl = repo.changelog
1877 cl = repo.changelog
1878 tags = opts.get('tags')
1878 tags = opts.get('tags')
1879 branches = opts.get('branches')
1879 branches = opts.get('branches')
1880 if tags:
1880 if tags:
1881 labels = {}
1881 labels = {}
1882 for l, n in repo.tags().items():
1882 for l, n in repo.tags().items():
1883 labels.setdefault(cl.rev(n), []).append(l)
1883 labels.setdefault(cl.rev(n), []).append(l)
1884 def events():
1884 def events():
1885 b = "default"
1885 b = "default"
1886 for r in cl:
1886 for r in cl:
1887 if branches:
1887 if branches:
1888 newb = cl.read(cl.node(r))[5]['branch']
1888 newb = cl.read(cl.node(r))[5]['branch']
1889 if newb != b:
1889 if newb != b:
1890 yield 'a', newb
1890 yield 'a', newb
1891 b = newb
1891 b = newb
1892 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1892 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1893 if p != -1)))
1893 if p != -1)))
1894 if tags:
1894 if tags:
1895 ls = labels.get(r)
1895 ls = labels.get(r)
1896 if ls:
1896 if ls:
1897 for l in ls:
1897 for l in ls:
1898 yield 'l', (r, l)
1898 yield 'l', (r, l)
1899 else:
1899 else:
1900 raise util.Abort(_('need repo for changelog dag'))
1900 raise util.Abort(_('need repo for changelog dag'))
1901
1901
1902 for line in dagparser.dagtextlines(events(),
1902 for line in dagparser.dagtextlines(events(),
1903 addspaces=spaces,
1903 addspaces=spaces,
1904 wraplabels=True,
1904 wraplabels=True,
1905 wrapannotations=True,
1905 wrapannotations=True,
1906 wrapnonlinear=dots,
1906 wrapnonlinear=dots,
1907 usedots=dots,
1907 usedots=dots,
1908 maxlinewidth=70):
1908 maxlinewidth=70):
1909 ui.write(line)
1909 ui.write(line)
1910 ui.write("\n")
1910 ui.write("\n")
1911
1911
1912 @command('debugdata',
1912 @command('debugdata',
1913 [('c', 'changelog', False, _('open changelog')),
1913 [('c', 'changelog', False, _('open changelog')),
1914 ('m', 'manifest', False, _('open manifest'))],
1914 ('m', 'manifest', False, _('open manifest'))],
1915 _('-c|-m|FILE REV'))
1915 _('-c|-m|FILE REV'))
1916 def debugdata(ui, repo, file_, rev=None, **opts):
1916 def debugdata(ui, repo, file_, rev=None, **opts):
1917 """dump the contents of a data file revision"""
1917 """dump the contents of a data file revision"""
1918 if opts.get('changelog') or opts.get('manifest'):
1918 if opts.get('changelog') or opts.get('manifest'):
1919 file_, rev = None, file_
1919 file_, rev = None, file_
1920 elif rev is None:
1920 elif rev is None:
1921 raise error.CommandError('debugdata', _('invalid arguments'))
1921 raise error.CommandError('debugdata', _('invalid arguments'))
1922 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1922 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1923 try:
1923 try:
1924 ui.write(r.revision(r.lookup(rev)))
1924 ui.write(r.revision(r.lookup(rev)))
1925 except KeyError:
1925 except KeyError:
1926 raise util.Abort(_('invalid revision identifier %s') % rev)
1926 raise util.Abort(_('invalid revision identifier %s') % rev)
1927
1927
1928 @command('debugdate',
1928 @command('debugdate',
1929 [('e', 'extended', None, _('try extended date formats'))],
1929 [('e', 'extended', None, _('try extended date formats'))],
1930 _('[-e] DATE [RANGE]'))
1930 _('[-e] DATE [RANGE]'))
1931 def debugdate(ui, date, range=None, **opts):
1931 def debugdate(ui, date, range=None, **opts):
1932 """parse and display a date"""
1932 """parse and display a date"""
1933 if opts["extended"]:
1933 if opts["extended"]:
1934 d = util.parsedate(date, util.extendeddateformats)
1934 d = util.parsedate(date, util.extendeddateformats)
1935 else:
1935 else:
1936 d = util.parsedate(date)
1936 d = util.parsedate(date)
1937 ui.write(("internal: %s %s\n") % d)
1937 ui.write(("internal: %s %s\n") % d)
1938 ui.write(("standard: %s\n") % util.datestr(d))
1938 ui.write(("standard: %s\n") % util.datestr(d))
1939 if range:
1939 if range:
1940 m = util.matchdate(range)
1940 m = util.matchdate(range)
1941 ui.write(("match: %s\n") % m(d[0]))
1941 ui.write(("match: %s\n") % m(d[0]))
1942
1942
1943 @command('debugdiscovery',
1943 @command('debugdiscovery',
1944 [('', 'old', None, _('use old-style discovery')),
1944 [('', 'old', None, _('use old-style discovery')),
1945 ('', 'nonheads', None,
1945 ('', 'nonheads', None,
1946 _('use old-style discovery with non-heads included')),
1946 _('use old-style discovery with non-heads included')),
1947 ] + remoteopts,
1947 ] + remoteopts,
1948 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1948 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1949 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1949 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1950 """runs the changeset discovery protocol in isolation"""
1950 """runs the changeset discovery protocol in isolation"""
1951 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1951 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1952 opts.get('branch'))
1952 opts.get('branch'))
1953 remote = hg.peer(repo, opts, remoteurl)
1953 remote = hg.peer(repo, opts, remoteurl)
1954 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1954 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1955
1955
1956 # make sure tests are repeatable
1956 # make sure tests are repeatable
1957 random.seed(12323)
1957 random.seed(12323)
1958
1958
1959 def doit(localheads, remoteheads, remote=remote):
1959 def doit(localheads, remoteheads, remote=remote):
1960 if opts.get('old'):
1960 if opts.get('old'):
1961 if localheads:
1961 if localheads:
1962 raise util.Abort('cannot use localheads with old style '
1962 raise util.Abort('cannot use localheads with old style '
1963 'discovery')
1963 'discovery')
1964 if not util.safehasattr(remote, 'branches'):
1964 if not util.safehasattr(remote, 'branches'):
1965 # enable in-client legacy support
1965 # enable in-client legacy support
1966 remote = localrepo.locallegacypeer(remote.local())
1966 remote = localrepo.locallegacypeer(remote.local())
1967 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1967 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1968 force=True)
1968 force=True)
1969 common = set(common)
1969 common = set(common)
1970 if not opts.get('nonheads'):
1970 if not opts.get('nonheads'):
1971 ui.write(("unpruned common: %s\n") %
1971 ui.write(("unpruned common: %s\n") %
1972 " ".join(sorted(short(n) for n in common)))
1972 " ".join(sorted(short(n) for n in common)))
1973 dag = dagutil.revlogdag(repo.changelog)
1973 dag = dagutil.revlogdag(repo.changelog)
1974 all = dag.ancestorset(dag.internalizeall(common))
1974 all = dag.ancestorset(dag.internalizeall(common))
1975 common = dag.externalizeall(dag.headsetofconnecteds(all))
1975 common = dag.externalizeall(dag.headsetofconnecteds(all))
1976 else:
1976 else:
1977 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1977 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1978 common = set(common)
1978 common = set(common)
1979 rheads = set(hds)
1979 rheads = set(hds)
1980 lheads = set(repo.heads())
1980 lheads = set(repo.heads())
1981 ui.write(("common heads: %s\n") %
1981 ui.write(("common heads: %s\n") %
1982 " ".join(sorted(short(n) for n in common)))
1982 " ".join(sorted(short(n) for n in common)))
1983 if lheads <= common:
1983 if lheads <= common:
1984 ui.write(("local is subset\n"))
1984 ui.write(("local is subset\n"))
1985 elif rheads <= common:
1985 elif rheads <= common:
1986 ui.write(("remote is subset\n"))
1986 ui.write(("remote is subset\n"))
1987
1987
1988 serverlogs = opts.get('serverlog')
1988 serverlogs = opts.get('serverlog')
1989 if serverlogs:
1989 if serverlogs:
1990 for filename in serverlogs:
1990 for filename in serverlogs:
1991 logfile = open(filename, 'r')
1991 logfile = open(filename, 'r')
1992 try:
1992 try:
1993 line = logfile.readline()
1993 line = logfile.readline()
1994 while line:
1994 while line:
1995 parts = line.strip().split(';')
1995 parts = line.strip().split(';')
1996 op = parts[1]
1996 op = parts[1]
1997 if op == 'cg':
1997 if op == 'cg':
1998 pass
1998 pass
1999 elif op == 'cgss':
1999 elif op == 'cgss':
2000 doit(parts[2].split(' '), parts[3].split(' '))
2000 doit(parts[2].split(' '), parts[3].split(' '))
2001 elif op == 'unb':
2001 elif op == 'unb':
2002 doit(parts[3].split(' '), parts[2].split(' '))
2002 doit(parts[3].split(' '), parts[2].split(' '))
2003 line = logfile.readline()
2003 line = logfile.readline()
2004 finally:
2004 finally:
2005 logfile.close()
2005 logfile.close()
2006
2006
2007 else:
2007 else:
2008 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2008 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2009 opts.get('remote_head'))
2009 opts.get('remote_head'))
2010 localrevs = opts.get('local_head')
2010 localrevs = opts.get('local_head')
2011 doit(localrevs, remoterevs)
2011 doit(localrevs, remoterevs)
2012
2012
2013 @command('debugfileset',
2013 @command('debugfileset',
2014 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2014 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2015 _('[-r REV] FILESPEC'))
2015 _('[-r REV] FILESPEC'))
2016 def debugfileset(ui, repo, expr, **opts):
2016 def debugfileset(ui, repo, expr, **opts):
2017 '''parse and apply a fileset specification'''
2017 '''parse and apply a fileset specification'''
2018 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2018 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2019 if ui.verbose:
2019 if ui.verbose:
2020 tree = fileset.parse(expr)[0]
2020 tree = fileset.parse(expr)[0]
2021 ui.note(tree, "\n")
2021 ui.note(tree, "\n")
2022
2022
2023 for f in ctx.getfileset(expr):
2023 for f in ctx.getfileset(expr):
2024 ui.write("%s\n" % f)
2024 ui.write("%s\n" % f)
2025
2025
2026 @command('debugfsinfo', [], _('[PATH]'))
2026 @command('debugfsinfo', [], _('[PATH]'))
2027 def debugfsinfo(ui, path="."):
2027 def debugfsinfo(ui, path="."):
2028 """show information detected about current filesystem"""
2028 """show information detected about current filesystem"""
2029 util.writefile('.debugfsinfo', '')
2029 util.writefile('.debugfsinfo', '')
2030 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2030 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2031 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2031 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2032 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2032 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2033 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2033 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2034 and 'yes' or 'no'))
2034 and 'yes' or 'no'))
2035 os.unlink('.debugfsinfo')
2035 os.unlink('.debugfsinfo')
2036
2036
2037 @command('debuggetbundle',
2037 @command('debuggetbundle',
2038 [('H', 'head', [], _('id of head node'), _('ID')),
2038 [('H', 'head', [], _('id of head node'), _('ID')),
2039 ('C', 'common', [], _('id of common node'), _('ID')),
2039 ('C', 'common', [], _('id of common node'), _('ID')),
2040 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2040 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2041 _('REPO FILE [-H|-C ID]...'))
2041 _('REPO FILE [-H|-C ID]...'))
2042 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2042 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2043 """retrieves a bundle from a repo
2043 """retrieves a bundle from a repo
2044
2044
2045 Every ID must be a full-length hex node id string. Saves the bundle to the
2045 Every ID must be a full-length hex node id string. Saves the bundle to the
2046 given file.
2046 given file.
2047 """
2047 """
2048 repo = hg.peer(ui, opts, repopath)
2048 repo = hg.peer(ui, opts, repopath)
2049 if not repo.capable('getbundle'):
2049 if not repo.capable('getbundle'):
2050 raise util.Abort("getbundle() not supported by target repository")
2050 raise util.Abort("getbundle() not supported by target repository")
2051 args = {}
2051 args = {}
2052 if common:
2052 if common:
2053 args['common'] = [bin(s) for s in common]
2053 args['common'] = [bin(s) for s in common]
2054 if head:
2054 if head:
2055 args['heads'] = [bin(s) for s in head]
2055 args['heads'] = [bin(s) for s in head]
2056 # TODO: get desired bundlecaps from command line.
2056 # TODO: get desired bundlecaps from command line.
2057 args['bundlecaps'] = None
2057 args['bundlecaps'] = None
2058 bundle = repo.getbundle('debug', **args)
2058 bundle = repo.getbundle('debug', **args)
2059
2059
2060 bundletype = opts.get('type', 'bzip2').lower()
2060 bundletype = opts.get('type', 'bzip2').lower()
2061 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2061 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2062 bundletype = btypes.get(bundletype)
2062 bundletype = btypes.get(bundletype)
2063 if bundletype not in changegroup.bundletypes:
2063 if bundletype not in changegroup.bundletypes:
2064 raise util.Abort(_('unknown bundle type specified with --type'))
2064 raise util.Abort(_('unknown bundle type specified with --type'))
2065 changegroup.writebundle(bundle, bundlepath, bundletype)
2065 changegroup.writebundle(bundle, bundlepath, bundletype)
2066
2066
2067 @command('debugignore', [], '')
2067 @command('debugignore', [], '')
2068 def debugignore(ui, repo, *values, **opts):
2068 def debugignore(ui, repo, *values, **opts):
2069 """display the combined ignore pattern"""
2069 """display the combined ignore pattern"""
2070 ignore = repo.dirstate._ignore
2070 ignore = repo.dirstate._ignore
2071 includepat = getattr(ignore, 'includepat', None)
2071 includepat = getattr(ignore, 'includepat', None)
2072 if includepat is not None:
2072 if includepat is not None:
2073 ui.write("%s\n" % includepat)
2073 ui.write("%s\n" % includepat)
2074 else:
2074 else:
2075 raise util.Abort(_("no ignore patterns found"))
2075 raise util.Abort(_("no ignore patterns found"))
2076
2076
2077 @command('debugindex',
2077 @command('debugindex',
2078 [('c', 'changelog', False, _('open changelog')),
2078 [('c', 'changelog', False, _('open changelog')),
2079 ('m', 'manifest', False, _('open manifest')),
2079 ('m', 'manifest', False, _('open manifest')),
2080 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2080 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2081 _('[-f FORMAT] -c|-m|FILE'))
2081 _('[-f FORMAT] -c|-m|FILE'))
2082 def debugindex(ui, repo, file_=None, **opts):
2082 def debugindex(ui, repo, file_=None, **opts):
2083 """dump the contents of an index file"""
2083 """dump the contents of an index file"""
2084 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2084 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2085 format = opts.get('format', 0)
2085 format = opts.get('format', 0)
2086 if format not in (0, 1):
2086 if format not in (0, 1):
2087 raise util.Abort(_("unknown format %d") % format)
2087 raise util.Abort(_("unknown format %d") % format)
2088
2088
2089 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2089 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2090 if generaldelta:
2090 if generaldelta:
2091 basehdr = ' delta'
2091 basehdr = ' delta'
2092 else:
2092 else:
2093 basehdr = ' base'
2093 basehdr = ' base'
2094
2094
2095 if format == 0:
2095 if format == 0:
2096 ui.write(" rev offset length " + basehdr + " linkrev"
2096 ui.write(" rev offset length " + basehdr + " linkrev"
2097 " nodeid p1 p2\n")
2097 " nodeid p1 p2\n")
2098 elif format == 1:
2098 elif format == 1:
2099 ui.write(" rev flag offset length"
2099 ui.write(" rev flag offset length"
2100 " size " + basehdr + " link p1 p2"
2100 " size " + basehdr + " link p1 p2"
2101 " nodeid\n")
2101 " nodeid\n")
2102
2102
2103 for i in r:
2103 for i in r:
2104 node = r.node(i)
2104 node = r.node(i)
2105 if generaldelta:
2105 if generaldelta:
2106 base = r.deltaparent(i)
2106 base = r.deltaparent(i)
2107 else:
2107 else:
2108 base = r.chainbase(i)
2108 base = r.chainbase(i)
2109 if format == 0:
2109 if format == 0:
2110 try:
2110 try:
2111 pp = r.parents(node)
2111 pp = r.parents(node)
2112 except Exception:
2112 except Exception:
2113 pp = [nullid, nullid]
2113 pp = [nullid, nullid]
2114 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2114 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2115 i, r.start(i), r.length(i), base, r.linkrev(i),
2115 i, r.start(i), r.length(i), base, r.linkrev(i),
2116 short(node), short(pp[0]), short(pp[1])))
2116 short(node), short(pp[0]), short(pp[1])))
2117 elif format == 1:
2117 elif format == 1:
2118 pr = r.parentrevs(i)
2118 pr = r.parentrevs(i)
2119 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2119 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2120 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2120 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2121 base, r.linkrev(i), pr[0], pr[1], short(node)))
2121 base, r.linkrev(i), pr[0], pr[1], short(node)))
2122
2122
2123 @command('debugindexdot', [], _('FILE'))
2123 @command('debugindexdot', [], _('FILE'))
2124 def debugindexdot(ui, repo, file_):
2124 def debugindexdot(ui, repo, file_):
2125 """dump an index DAG as a graphviz dot file"""
2125 """dump an index DAG as a graphviz dot file"""
2126 r = None
2126 r = None
2127 if repo:
2127 if repo:
2128 filelog = repo.file(file_)
2128 filelog = repo.file(file_)
2129 if len(filelog):
2129 if len(filelog):
2130 r = filelog
2130 r = filelog
2131 if not r:
2131 if not r:
2132 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2132 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2133 ui.write(("digraph G {\n"))
2133 ui.write(("digraph G {\n"))
2134 for i in r:
2134 for i in r:
2135 node = r.node(i)
2135 node = r.node(i)
2136 pp = r.parents(node)
2136 pp = r.parents(node)
2137 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2137 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2138 if pp[1] != nullid:
2138 if pp[1] != nullid:
2139 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2139 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2140 ui.write("}\n")
2140 ui.write("}\n")
2141
2141
2142 @command('debuginstall', [], '')
2142 @command('debuginstall', [], '')
2143 def debuginstall(ui):
2143 def debuginstall(ui):
2144 '''test Mercurial installation
2144 '''test Mercurial installation
2145
2145
2146 Returns 0 on success.
2146 Returns 0 on success.
2147 '''
2147 '''
2148
2148
2149 def writetemp(contents):
2149 def writetemp(contents):
2150 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2150 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2151 f = os.fdopen(fd, "wb")
2151 f = os.fdopen(fd, "wb")
2152 f.write(contents)
2152 f.write(contents)
2153 f.close()
2153 f.close()
2154 return name
2154 return name
2155
2155
2156 problems = 0
2156 problems = 0
2157
2157
2158 # encoding
2158 # encoding
2159 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2159 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2160 try:
2160 try:
2161 encoding.fromlocal("test")
2161 encoding.fromlocal("test")
2162 except util.Abort, inst:
2162 except util.Abort, inst:
2163 ui.write(" %s\n" % inst)
2163 ui.write(" %s\n" % inst)
2164 ui.write(_(" (check that your locale is properly set)\n"))
2164 ui.write(_(" (check that your locale is properly set)\n"))
2165 problems += 1
2165 problems += 1
2166
2166
2167 # Python
2167 # Python
2168 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2168 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2169 ui.status(_("checking Python version (%s)\n")
2169 ui.status(_("checking Python version (%s)\n")
2170 % ("%s.%s.%s" % sys.version_info[:3]))
2170 % ("%s.%s.%s" % sys.version_info[:3]))
2171 ui.status(_("checking Python lib (%s)...\n")
2171 ui.status(_("checking Python lib (%s)...\n")
2172 % os.path.dirname(os.__file__))
2172 % os.path.dirname(os.__file__))
2173
2173
2174 # compiled modules
2174 # compiled modules
2175 ui.status(_("checking installed modules (%s)...\n")
2175 ui.status(_("checking installed modules (%s)...\n")
2176 % os.path.dirname(__file__))
2176 % os.path.dirname(__file__))
2177 try:
2177 try:
2178 import bdiff, mpatch, base85, osutil
2178 import bdiff, mpatch, base85, osutil
2179 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2179 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2180 except Exception, inst:
2180 except Exception, inst:
2181 ui.write(" %s\n" % inst)
2181 ui.write(" %s\n" % inst)
2182 ui.write(_(" One or more extensions could not be found"))
2182 ui.write(_(" One or more extensions could not be found"))
2183 ui.write(_(" (check that you compiled the extensions)\n"))
2183 ui.write(_(" (check that you compiled the extensions)\n"))
2184 problems += 1
2184 problems += 1
2185
2185
2186 # templates
2186 # templates
2187 import templater
2187 import templater
2188 p = templater.templatepath()
2188 p = templater.templatepath()
2189 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2189 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2190 if p:
2190 if p:
2191 m = templater.templatepath("map-cmdline.default")
2191 m = templater.templatepath("map-cmdline.default")
2192 if m:
2192 if m:
2193 # template found, check if it is working
2193 # template found, check if it is working
2194 try:
2194 try:
2195 templater.templater(m)
2195 templater.templater(m)
2196 except Exception, inst:
2196 except Exception, inst:
2197 ui.write(" %s\n" % inst)
2197 ui.write(" %s\n" % inst)
2198 p = None
2198 p = None
2199 else:
2199 else:
2200 ui.write(_(" template 'default' not found\n"))
2200 ui.write(_(" template 'default' not found\n"))
2201 p = None
2201 p = None
2202 else:
2202 else:
2203 ui.write(_(" no template directories found\n"))
2203 ui.write(_(" no template directories found\n"))
2204 if not p:
2204 if not p:
2205 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2205 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2206 problems += 1
2206 problems += 1
2207
2207
2208 # editor
2208 # editor
2209 ui.status(_("checking commit editor...\n"))
2209 ui.status(_("checking commit editor...\n"))
2210 editor = ui.geteditor()
2210 editor = ui.geteditor()
2211 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2211 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2212 if not cmdpath:
2212 if not cmdpath:
2213 if editor == 'vi':
2213 if editor == 'vi':
2214 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2214 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2215 ui.write(_(" (specify a commit editor in your configuration"
2215 ui.write(_(" (specify a commit editor in your configuration"
2216 " file)\n"))
2216 " file)\n"))
2217 else:
2217 else:
2218 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2218 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2219 ui.write(_(" (specify a commit editor in your configuration"
2219 ui.write(_(" (specify a commit editor in your configuration"
2220 " file)\n"))
2220 " file)\n"))
2221 problems += 1
2221 problems += 1
2222
2222
2223 # check username
2223 # check username
2224 ui.status(_("checking username...\n"))
2224 ui.status(_("checking username...\n"))
2225 try:
2225 try:
2226 ui.username()
2226 ui.username()
2227 except util.Abort, e:
2227 except util.Abort, e:
2228 ui.write(" %s\n" % e)
2228 ui.write(" %s\n" % e)
2229 ui.write(_(" (specify a username in your configuration file)\n"))
2229 ui.write(_(" (specify a username in your configuration file)\n"))
2230 problems += 1
2230 problems += 1
2231
2231
2232 if not problems:
2232 if not problems:
2233 ui.status(_("no problems detected\n"))
2233 ui.status(_("no problems detected\n"))
2234 else:
2234 else:
2235 ui.write(_("%s problems detected,"
2235 ui.write(_("%s problems detected,"
2236 " please check your install!\n") % problems)
2236 " please check your install!\n") % problems)
2237
2237
2238 return problems
2238 return problems
2239
2239
2240 @command('debugknown', [], _('REPO ID...'))
2240 @command('debugknown', [], _('REPO ID...'))
2241 def debugknown(ui, repopath, *ids, **opts):
2241 def debugknown(ui, repopath, *ids, **opts):
2242 """test whether node ids are known to a repo
2242 """test whether node ids are known to a repo
2243
2243
2244 Every ID must be a full-length hex node id string. Returns a list of 0s
2244 Every ID must be a full-length hex node id string. Returns a list of 0s
2245 and 1s indicating unknown/known.
2245 and 1s indicating unknown/known.
2246 """
2246 """
2247 repo = hg.peer(ui, opts, repopath)
2247 repo = hg.peer(ui, opts, repopath)
2248 if not repo.capable('known'):
2248 if not repo.capable('known'):
2249 raise util.Abort("known() not supported by target repository")
2249 raise util.Abort("known() not supported by target repository")
2250 flags = repo.known([bin(s) for s in ids])
2250 flags = repo.known([bin(s) for s in ids])
2251 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2251 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2252
2252
2253 @command('debuglabelcomplete', [], _('LABEL...'))
2253 @command('debuglabelcomplete', [], _('LABEL...'))
2254 def debuglabelcomplete(ui, repo, *args):
2254 def debuglabelcomplete(ui, repo, *args):
2255 '''complete "labels" - tags, open branch names, bookmark names'''
2255 '''complete "labels" - tags, open branch names, bookmark names'''
2256
2256
2257 labels = set()
2257 labels = set()
2258 labels.update(t[0] for t in repo.tagslist())
2258 labels.update(t[0] for t in repo.tagslist())
2259 labels.update(repo._bookmarks.keys())
2259 labels.update(repo._bookmarks.keys())
2260 labels.update(tag for (tag, heads, tip, closed)
2260 labels.update(tag for (tag, heads, tip, closed)
2261 in repo.branchmap().iterbranches() if not closed)
2261 in repo.branchmap().iterbranches() if not closed)
2262 completions = set()
2262 completions = set()
2263 if not args:
2263 if not args:
2264 args = ['']
2264 args = ['']
2265 for a in args:
2265 for a in args:
2266 completions.update(l for l in labels if l.startswith(a))
2266 completions.update(l for l in labels if l.startswith(a))
2267 ui.write('\n'.join(sorted(completions)))
2267 ui.write('\n'.join(sorted(completions)))
2268 ui.write('\n')
2268 ui.write('\n')
2269
2269
2270 @command('debugobsolete',
2270 @command('debugobsolete',
2271 [('', 'flags', 0, _('markers flag')),
2271 [('', 'flags', 0, _('markers flag')),
2272 ] + commitopts2,
2272 ] + commitopts2,
2273 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2273 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2274 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2274 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2275 """create arbitrary obsolete marker
2275 """create arbitrary obsolete marker
2276
2276
2277 With no arguments, displays the list of obsolescence markers."""
2277 With no arguments, displays the list of obsolescence markers."""
2278 def parsenodeid(s):
2278 def parsenodeid(s):
2279 try:
2279 try:
2280 # We do not use revsingle/revrange functions here to accept
2280 # We do not use revsingle/revrange functions here to accept
2281 # arbitrary node identifiers, possibly not present in the
2281 # arbitrary node identifiers, possibly not present in the
2282 # local repository.
2282 # local repository.
2283 n = bin(s)
2283 n = bin(s)
2284 if len(n) != len(nullid):
2284 if len(n) != len(nullid):
2285 raise TypeError()
2285 raise TypeError()
2286 return n
2286 return n
2287 except TypeError:
2287 except TypeError:
2288 raise util.Abort('changeset references must be full hexadecimal '
2288 raise util.Abort('changeset references must be full hexadecimal '
2289 'node identifiers')
2289 'node identifiers')
2290
2290
2291 if precursor is not None:
2291 if precursor is not None:
2292 metadata = {}
2292 metadata = {}
2293 if 'date' in opts:
2293 if 'date' in opts:
2294 metadata['date'] = opts['date']
2294 metadata['date'] = opts['date']
2295 metadata['user'] = opts['user'] or ui.username()
2295 metadata['user'] = opts['user'] or ui.username()
2296 succs = tuple(parsenodeid(succ) for succ in successors)
2296 succs = tuple(parsenodeid(succ) for succ in successors)
2297 l = repo.lock()
2297 l = repo.lock()
2298 try:
2298 try:
2299 tr = repo.transaction('debugobsolete')
2299 tr = repo.transaction('debugobsolete')
2300 try:
2300 try:
2301 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2301 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2302 opts['flags'], metadata)
2302 opts['flags'], metadata)
2303 tr.close()
2303 tr.close()
2304 finally:
2304 finally:
2305 tr.release()
2305 tr.release()
2306 finally:
2306 finally:
2307 l.release()
2307 l.release()
2308 else:
2308 else:
2309 for m in obsolete.allmarkers(repo):
2309 for m in obsolete.allmarkers(repo):
2310 cmdutil.showmarker(ui, m)
2310 cmdutil.showmarker(ui, m)
2311
2311
2312 @command('debugpathcomplete',
2312 @command('debugpathcomplete',
2313 [('f', 'full', None, _('complete an entire path')),
2313 [('f', 'full', None, _('complete an entire path')),
2314 ('n', 'normal', None, _('show only normal files')),
2314 ('n', 'normal', None, _('show only normal files')),
2315 ('a', 'added', None, _('show only added files')),
2315 ('a', 'added', None, _('show only added files')),
2316 ('r', 'removed', None, _('show only removed files'))],
2316 ('r', 'removed', None, _('show only removed files'))],
2317 _('FILESPEC...'))
2317 _('FILESPEC...'))
2318 def debugpathcomplete(ui, repo, *specs, **opts):
2318 def debugpathcomplete(ui, repo, *specs, **opts):
2319 '''complete part or all of a tracked path
2319 '''complete part or all of a tracked path
2320
2320
2321 This command supports shells that offer path name completion. It
2321 This command supports shells that offer path name completion. It
2322 currently completes only files already known to the dirstate.
2322 currently completes only files already known to the dirstate.
2323
2323
2324 Completion extends only to the next path segment unless
2324 Completion extends only to the next path segment unless
2325 --full is specified, in which case entire paths are used.'''
2325 --full is specified, in which case entire paths are used.'''
2326
2326
2327 def complete(path, acceptable):
2327 def complete(path, acceptable):
2328 dirstate = repo.dirstate
2328 dirstate = repo.dirstate
2329 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2329 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2330 rootdir = repo.root + os.sep
2330 rootdir = repo.root + os.sep
2331 if spec != repo.root and not spec.startswith(rootdir):
2331 if spec != repo.root and not spec.startswith(rootdir):
2332 return [], []
2332 return [], []
2333 if os.path.isdir(spec):
2333 if os.path.isdir(spec):
2334 spec += '/'
2334 spec += '/'
2335 spec = spec[len(rootdir):]
2335 spec = spec[len(rootdir):]
2336 fixpaths = os.sep != '/'
2336 fixpaths = os.sep != '/'
2337 if fixpaths:
2337 if fixpaths:
2338 spec = spec.replace(os.sep, '/')
2338 spec = spec.replace(os.sep, '/')
2339 speclen = len(spec)
2339 speclen = len(spec)
2340 fullpaths = opts['full']
2340 fullpaths = opts['full']
2341 files, dirs = set(), set()
2341 files, dirs = set(), set()
2342 adddir, addfile = dirs.add, files.add
2342 adddir, addfile = dirs.add, files.add
2343 for f, st in dirstate.iteritems():
2343 for f, st in dirstate.iteritems():
2344 if f.startswith(spec) and st[0] in acceptable:
2344 if f.startswith(spec) and st[0] in acceptable:
2345 if fixpaths:
2345 if fixpaths:
2346 f = f.replace('/', os.sep)
2346 f = f.replace('/', os.sep)
2347 if fullpaths:
2347 if fullpaths:
2348 addfile(f)
2348 addfile(f)
2349 continue
2349 continue
2350 s = f.find(os.sep, speclen)
2350 s = f.find(os.sep, speclen)
2351 if s >= 0:
2351 if s >= 0:
2352 adddir(f[:s])
2352 adddir(f[:s])
2353 else:
2353 else:
2354 addfile(f)
2354 addfile(f)
2355 return files, dirs
2355 return files, dirs
2356
2356
2357 acceptable = ''
2357 acceptable = ''
2358 if opts['normal']:
2358 if opts['normal']:
2359 acceptable += 'nm'
2359 acceptable += 'nm'
2360 if opts['added']:
2360 if opts['added']:
2361 acceptable += 'a'
2361 acceptable += 'a'
2362 if opts['removed']:
2362 if opts['removed']:
2363 acceptable += 'r'
2363 acceptable += 'r'
2364 cwd = repo.getcwd()
2364 cwd = repo.getcwd()
2365 if not specs:
2365 if not specs:
2366 specs = ['.']
2366 specs = ['.']
2367
2367
2368 files, dirs = set(), set()
2368 files, dirs = set(), set()
2369 for spec in specs:
2369 for spec in specs:
2370 f, d = complete(spec, acceptable or 'nmar')
2370 f, d = complete(spec, acceptable or 'nmar')
2371 files.update(f)
2371 files.update(f)
2372 dirs.update(d)
2372 dirs.update(d)
2373 files.update(dirs)
2373 files.update(dirs)
2374 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2374 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2375 ui.write('\n')
2375 ui.write('\n')
2376
2376
2377 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2377 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2378 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2378 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2379 '''access the pushkey key/value protocol
2379 '''access the pushkey key/value protocol
2380
2380
2381 With two args, list the keys in the given namespace.
2381 With two args, list the keys in the given namespace.
2382
2382
2383 With five args, set a key to new if it currently is set to old.
2383 With five args, set a key to new if it currently is set to old.
2384 Reports success or failure.
2384 Reports success or failure.
2385 '''
2385 '''
2386
2386
2387 target = hg.peer(ui, {}, repopath)
2387 target = hg.peer(ui, {}, repopath)
2388 if keyinfo:
2388 if keyinfo:
2389 key, old, new = keyinfo
2389 key, old, new = keyinfo
2390 r = target.pushkey(namespace, key, old, new)
2390 r = target.pushkey(namespace, key, old, new)
2391 ui.status(str(r) + '\n')
2391 ui.status(str(r) + '\n')
2392 return not r
2392 return not r
2393 else:
2393 else:
2394 for k, v in sorted(target.listkeys(namespace).iteritems()):
2394 for k, v in sorted(target.listkeys(namespace).iteritems()):
2395 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2395 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2396 v.encode('string-escape')))
2396 v.encode('string-escape')))
2397
2397
2398 @command('debugpvec', [], _('A B'))
2398 @command('debugpvec', [], _('A B'))
2399 def debugpvec(ui, repo, a, b=None):
2399 def debugpvec(ui, repo, a, b=None):
2400 ca = scmutil.revsingle(repo, a)
2400 ca = scmutil.revsingle(repo, a)
2401 cb = scmutil.revsingle(repo, b)
2401 cb = scmutil.revsingle(repo, b)
2402 pa = pvec.ctxpvec(ca)
2402 pa = pvec.ctxpvec(ca)
2403 pb = pvec.ctxpvec(cb)
2403 pb = pvec.ctxpvec(cb)
2404 if pa == pb:
2404 if pa == pb:
2405 rel = "="
2405 rel = "="
2406 elif pa > pb:
2406 elif pa > pb:
2407 rel = ">"
2407 rel = ">"
2408 elif pa < pb:
2408 elif pa < pb:
2409 rel = "<"
2409 rel = "<"
2410 elif pa | pb:
2410 elif pa | pb:
2411 rel = "|"
2411 rel = "|"
2412 ui.write(_("a: %s\n") % pa)
2412 ui.write(_("a: %s\n") % pa)
2413 ui.write(_("b: %s\n") % pb)
2413 ui.write(_("b: %s\n") % pb)
2414 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2414 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2415 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2415 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2416 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2416 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2417 pa.distance(pb), rel))
2417 pa.distance(pb), rel))
2418
2418
2419 @command('debugrebuilddirstate|debugrebuildstate',
2419 @command('debugrebuilddirstate|debugrebuildstate',
2420 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2420 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2421 _('[-r REV]'))
2421 _('[-r REV]'))
2422 def debugrebuilddirstate(ui, repo, rev):
2422 def debugrebuilddirstate(ui, repo, rev):
2423 """rebuild the dirstate as it would look like for the given revision
2423 """rebuild the dirstate as it would look like for the given revision
2424
2424
2425 If no revision is specified the first current parent will be used.
2425 If no revision is specified the first current parent will be used.
2426
2426
2427 The dirstate will be set to the files of the given revision.
2427 The dirstate will be set to the files of the given revision.
2428 The actual working directory content or existing dirstate
2428 The actual working directory content or existing dirstate
2429 information such as adds or removes is not considered.
2429 information such as adds or removes is not considered.
2430
2430
2431 One use of this command is to make the next :hg:`status` invocation
2431 One use of this command is to make the next :hg:`status` invocation
2432 check the actual file content.
2432 check the actual file content.
2433 """
2433 """
2434 ctx = scmutil.revsingle(repo, rev)
2434 ctx = scmutil.revsingle(repo, rev)
2435 wlock = repo.wlock()
2435 wlock = repo.wlock()
2436 try:
2436 try:
2437 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2437 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2438 finally:
2438 finally:
2439 wlock.release()
2439 wlock.release()
2440
2440
2441 @command('debugrename',
2441 @command('debugrename',
2442 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2442 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2443 _('[-r REV] FILE'))
2443 _('[-r REV] FILE'))
2444 def debugrename(ui, repo, file1, *pats, **opts):
2444 def debugrename(ui, repo, file1, *pats, **opts):
2445 """dump rename information"""
2445 """dump rename information"""
2446
2446
2447 ctx = scmutil.revsingle(repo, opts.get('rev'))
2447 ctx = scmutil.revsingle(repo, opts.get('rev'))
2448 m = scmutil.match(ctx, (file1,) + pats, opts)
2448 m = scmutil.match(ctx, (file1,) + pats, opts)
2449 for abs in ctx.walk(m):
2449 for abs in ctx.walk(m):
2450 fctx = ctx[abs]
2450 fctx = ctx[abs]
2451 o = fctx.filelog().renamed(fctx.filenode())
2451 o = fctx.filelog().renamed(fctx.filenode())
2452 rel = m.rel(abs)
2452 rel = m.rel(abs)
2453 if o:
2453 if o:
2454 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2454 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2455 else:
2455 else:
2456 ui.write(_("%s not renamed\n") % rel)
2456 ui.write(_("%s not renamed\n") % rel)
2457
2457
2458 @command('debugrevlog',
2458 @command('debugrevlog',
2459 [('c', 'changelog', False, _('open changelog')),
2459 [('c', 'changelog', False, _('open changelog')),
2460 ('m', 'manifest', False, _('open manifest')),
2460 ('m', 'manifest', False, _('open manifest')),
2461 ('d', 'dump', False, _('dump index data'))],
2461 ('d', 'dump', False, _('dump index data'))],
2462 _('-c|-m|FILE'))
2462 _('-c|-m|FILE'))
2463 def debugrevlog(ui, repo, file_=None, **opts):
2463 def debugrevlog(ui, repo, file_=None, **opts):
2464 """show data and statistics about a revlog"""
2464 """show data and statistics about a revlog"""
2465 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2465 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2466
2466
2467 if opts.get("dump"):
2467 if opts.get("dump"):
2468 numrevs = len(r)
2468 numrevs = len(r)
2469 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2469 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2470 " rawsize totalsize compression heads\n")
2470 " rawsize totalsize compression heads\n")
2471 ts = 0
2471 ts = 0
2472 heads = set()
2472 heads = set()
2473 for rev in xrange(numrevs):
2473 for rev in xrange(numrevs):
2474 dbase = r.deltaparent(rev)
2474 dbase = r.deltaparent(rev)
2475 if dbase == -1:
2475 if dbase == -1:
2476 dbase = rev
2476 dbase = rev
2477 cbase = r.chainbase(rev)
2477 cbase = r.chainbase(rev)
2478 p1, p2 = r.parentrevs(rev)
2478 p1, p2 = r.parentrevs(rev)
2479 rs = r.rawsize(rev)
2479 rs = r.rawsize(rev)
2480 ts = ts + rs
2480 ts = ts + rs
2481 heads -= set(r.parentrevs(rev))
2481 heads -= set(r.parentrevs(rev))
2482 heads.add(rev)
2482 heads.add(rev)
2483 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2483 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2484 (rev, p1, p2, r.start(rev), r.end(rev),
2484 (rev, p1, p2, r.start(rev), r.end(rev),
2485 r.start(dbase), r.start(cbase),
2485 r.start(dbase), r.start(cbase),
2486 r.start(p1), r.start(p2),
2486 r.start(p1), r.start(p2),
2487 rs, ts, ts / r.end(rev), len(heads)))
2487 rs, ts, ts / r.end(rev), len(heads)))
2488 return 0
2488 return 0
2489
2489
2490 v = r.version
2490 v = r.version
2491 format = v & 0xFFFF
2491 format = v & 0xFFFF
2492 flags = []
2492 flags = []
2493 gdelta = False
2493 gdelta = False
2494 if v & revlog.REVLOGNGINLINEDATA:
2494 if v & revlog.REVLOGNGINLINEDATA:
2495 flags.append('inline')
2495 flags.append('inline')
2496 if v & revlog.REVLOGGENERALDELTA:
2496 if v & revlog.REVLOGGENERALDELTA:
2497 gdelta = True
2497 gdelta = True
2498 flags.append('generaldelta')
2498 flags.append('generaldelta')
2499 if not flags:
2499 if not flags:
2500 flags = ['(none)']
2500 flags = ['(none)']
2501
2501
2502 nummerges = 0
2502 nummerges = 0
2503 numfull = 0
2503 numfull = 0
2504 numprev = 0
2504 numprev = 0
2505 nump1 = 0
2505 nump1 = 0
2506 nump2 = 0
2506 nump2 = 0
2507 numother = 0
2507 numother = 0
2508 nump1prev = 0
2508 nump1prev = 0
2509 nump2prev = 0
2509 nump2prev = 0
2510 chainlengths = []
2510 chainlengths = []
2511
2511
2512 datasize = [None, 0, 0L]
2512 datasize = [None, 0, 0L]
2513 fullsize = [None, 0, 0L]
2513 fullsize = [None, 0, 0L]
2514 deltasize = [None, 0, 0L]
2514 deltasize = [None, 0, 0L]
2515
2515
2516 def addsize(size, l):
2516 def addsize(size, l):
2517 if l[0] is None or size < l[0]:
2517 if l[0] is None or size < l[0]:
2518 l[0] = size
2518 l[0] = size
2519 if size > l[1]:
2519 if size > l[1]:
2520 l[1] = size
2520 l[1] = size
2521 l[2] += size
2521 l[2] += size
2522
2522
2523 numrevs = len(r)
2523 numrevs = len(r)
2524 for rev in xrange(numrevs):
2524 for rev in xrange(numrevs):
2525 p1, p2 = r.parentrevs(rev)
2525 p1, p2 = r.parentrevs(rev)
2526 delta = r.deltaparent(rev)
2526 delta = r.deltaparent(rev)
2527 if format > 0:
2527 if format > 0:
2528 addsize(r.rawsize(rev), datasize)
2528 addsize(r.rawsize(rev), datasize)
2529 if p2 != nullrev:
2529 if p2 != nullrev:
2530 nummerges += 1
2530 nummerges += 1
2531 size = r.length(rev)
2531 size = r.length(rev)
2532 if delta == nullrev:
2532 if delta == nullrev:
2533 chainlengths.append(0)
2533 chainlengths.append(0)
2534 numfull += 1
2534 numfull += 1
2535 addsize(size, fullsize)
2535 addsize(size, fullsize)
2536 else:
2536 else:
2537 chainlengths.append(chainlengths[delta] + 1)
2537 chainlengths.append(chainlengths[delta] + 1)
2538 addsize(size, deltasize)
2538 addsize(size, deltasize)
2539 if delta == rev - 1:
2539 if delta == rev - 1:
2540 numprev += 1
2540 numprev += 1
2541 if delta == p1:
2541 if delta == p1:
2542 nump1prev += 1
2542 nump1prev += 1
2543 elif delta == p2:
2543 elif delta == p2:
2544 nump2prev += 1
2544 nump2prev += 1
2545 elif delta == p1:
2545 elif delta == p1:
2546 nump1 += 1
2546 nump1 += 1
2547 elif delta == p2:
2547 elif delta == p2:
2548 nump2 += 1
2548 nump2 += 1
2549 elif delta != nullrev:
2549 elif delta != nullrev:
2550 numother += 1
2550 numother += 1
2551
2551
2552 # Adjust size min value for empty cases
2552 # Adjust size min value for empty cases
2553 for size in (datasize, fullsize, deltasize):
2553 for size in (datasize, fullsize, deltasize):
2554 if size[0] is None:
2554 if size[0] is None:
2555 size[0] = 0
2555 size[0] = 0
2556
2556
2557 numdeltas = numrevs - numfull
2557 numdeltas = numrevs - numfull
2558 numoprev = numprev - nump1prev - nump2prev
2558 numoprev = numprev - nump1prev - nump2prev
2559 totalrawsize = datasize[2]
2559 totalrawsize = datasize[2]
2560 datasize[2] /= numrevs
2560 datasize[2] /= numrevs
2561 fulltotal = fullsize[2]
2561 fulltotal = fullsize[2]
2562 fullsize[2] /= numfull
2562 fullsize[2] /= numfull
2563 deltatotal = deltasize[2]
2563 deltatotal = deltasize[2]
2564 if numrevs - numfull > 0:
2564 if numrevs - numfull > 0:
2565 deltasize[2] /= numrevs - numfull
2565 deltasize[2] /= numrevs - numfull
2566 totalsize = fulltotal + deltatotal
2566 totalsize = fulltotal + deltatotal
2567 avgchainlen = sum(chainlengths) / numrevs
2567 avgchainlen = sum(chainlengths) / numrevs
2568 compratio = totalrawsize / totalsize
2568 compratio = totalrawsize / totalsize
2569
2569
2570 basedfmtstr = '%%%dd\n'
2570 basedfmtstr = '%%%dd\n'
2571 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2571 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2572
2572
2573 def dfmtstr(max):
2573 def dfmtstr(max):
2574 return basedfmtstr % len(str(max))
2574 return basedfmtstr % len(str(max))
2575 def pcfmtstr(max, padding=0):
2575 def pcfmtstr(max, padding=0):
2576 return basepcfmtstr % (len(str(max)), ' ' * padding)
2576 return basepcfmtstr % (len(str(max)), ' ' * padding)
2577
2577
2578 def pcfmt(value, total):
2578 def pcfmt(value, total):
2579 return (value, 100 * float(value) / total)
2579 return (value, 100 * float(value) / total)
2580
2580
2581 ui.write(('format : %d\n') % format)
2581 ui.write(('format : %d\n') % format)
2582 ui.write(('flags : %s\n') % ', '.join(flags))
2582 ui.write(('flags : %s\n') % ', '.join(flags))
2583
2583
2584 ui.write('\n')
2584 ui.write('\n')
2585 fmt = pcfmtstr(totalsize)
2585 fmt = pcfmtstr(totalsize)
2586 fmt2 = dfmtstr(totalsize)
2586 fmt2 = dfmtstr(totalsize)
2587 ui.write(('revisions : ') + fmt2 % numrevs)
2587 ui.write(('revisions : ') + fmt2 % numrevs)
2588 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2588 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2589 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2589 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2590 ui.write(('revisions : ') + fmt2 % numrevs)
2590 ui.write(('revisions : ') + fmt2 % numrevs)
2591 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2591 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2592 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2592 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2593 ui.write(('revision size : ') + fmt2 % totalsize)
2593 ui.write(('revision size : ') + fmt2 % totalsize)
2594 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2594 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2595 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2595 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2596
2596
2597 ui.write('\n')
2597 ui.write('\n')
2598 fmt = dfmtstr(max(avgchainlen, compratio))
2598 fmt = dfmtstr(max(avgchainlen, compratio))
2599 ui.write(('avg chain length : ') + fmt % avgchainlen)
2599 ui.write(('avg chain length : ') + fmt % avgchainlen)
2600 ui.write(('compression ratio : ') + fmt % compratio)
2600 ui.write(('compression ratio : ') + fmt % compratio)
2601
2601
2602 if format > 0:
2602 if format > 0:
2603 ui.write('\n')
2603 ui.write('\n')
2604 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2604 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2605 % tuple(datasize))
2605 % tuple(datasize))
2606 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2606 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2607 % tuple(fullsize))
2607 % tuple(fullsize))
2608 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2608 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2609 % tuple(deltasize))
2609 % tuple(deltasize))
2610
2610
2611 if numdeltas > 0:
2611 if numdeltas > 0:
2612 ui.write('\n')
2612 ui.write('\n')
2613 fmt = pcfmtstr(numdeltas)
2613 fmt = pcfmtstr(numdeltas)
2614 fmt2 = pcfmtstr(numdeltas, 4)
2614 fmt2 = pcfmtstr(numdeltas, 4)
2615 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2615 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2616 if numprev > 0:
2616 if numprev > 0:
2617 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2617 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2618 numprev))
2618 numprev))
2619 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2619 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2620 numprev))
2620 numprev))
2621 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2621 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2622 numprev))
2622 numprev))
2623 if gdelta:
2623 if gdelta:
2624 ui.write(('deltas against p1 : ')
2624 ui.write(('deltas against p1 : ')
2625 + fmt % pcfmt(nump1, numdeltas))
2625 + fmt % pcfmt(nump1, numdeltas))
2626 ui.write(('deltas against p2 : ')
2626 ui.write(('deltas against p2 : ')
2627 + fmt % pcfmt(nump2, numdeltas))
2627 + fmt % pcfmt(nump2, numdeltas))
2628 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2628 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2629 numdeltas))
2629 numdeltas))
2630
2630
2631 @command('debugrevspec',
2631 @command('debugrevspec',
2632 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2632 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2633 ('REVSPEC'))
2633 ('REVSPEC'))
2634 def debugrevspec(ui, repo, expr, **opts):
2634 def debugrevspec(ui, repo, expr, **opts):
2635 """parse and apply a revision specification
2635 """parse and apply a revision specification
2636
2636
2637 Use --verbose to print the parsed tree before and after aliases
2637 Use --verbose to print the parsed tree before and after aliases
2638 expansion.
2638 expansion.
2639 """
2639 """
2640 if ui.verbose:
2640 if ui.verbose:
2641 tree = revset.parse(expr)[0]
2641 tree = revset.parse(expr)[0]
2642 ui.note(revset.prettyformat(tree), "\n")
2642 ui.note(revset.prettyformat(tree), "\n")
2643 newtree = revset.findaliases(ui, tree)
2643 newtree = revset.findaliases(ui, tree)
2644 if newtree != tree:
2644 if newtree != tree:
2645 ui.note(revset.prettyformat(newtree), "\n")
2645 ui.note(revset.prettyformat(newtree), "\n")
2646 if opts["optimize"]:
2646 if opts["optimize"]:
2647 weight, optimizedtree = revset.optimize(newtree, True)
2647 weight, optimizedtree = revset.optimize(newtree, True)
2648 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2648 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2649 func = revset.match(ui, expr)
2649 func = revset.match(ui, expr)
2650 for c in func(repo, revset.spanset(repo)):
2650 for c in func(repo, revset.spanset(repo)):
2651 ui.write("%s\n" % c)
2651 ui.write("%s\n" % c)
2652
2652
2653 @command('debugsetparents', [], _('REV1 [REV2]'))
2653 @command('debugsetparents', [], _('REV1 [REV2]'))
2654 def debugsetparents(ui, repo, rev1, rev2=None):
2654 def debugsetparents(ui, repo, rev1, rev2=None):
2655 """manually set the parents of the current working directory
2655 """manually set the parents of the current working directory
2656
2656
2657 This is useful for writing repository conversion tools, but should
2657 This is useful for writing repository conversion tools, but should
2658 be used with care.
2658 be used with care.
2659
2659
2660 Returns 0 on success.
2660 Returns 0 on success.
2661 """
2661 """
2662
2662
2663 r1 = scmutil.revsingle(repo, rev1).node()
2663 r1 = scmutil.revsingle(repo, rev1).node()
2664 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2664 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2665
2665
2666 wlock = repo.wlock()
2666 wlock = repo.wlock()
2667 try:
2667 try:
2668 repo.setparents(r1, r2)
2668 repo.setparents(r1, r2)
2669 finally:
2669 finally:
2670 wlock.release()
2670 wlock.release()
2671
2671
2672 @command('debugdirstate|debugstate',
2672 @command('debugdirstate|debugstate',
2673 [('', 'nodates', None, _('do not display the saved mtime')),
2673 [('', 'nodates', None, _('do not display the saved mtime')),
2674 ('', 'datesort', None, _('sort by saved mtime'))],
2674 ('', 'datesort', None, _('sort by saved mtime'))],
2675 _('[OPTION]...'))
2675 _('[OPTION]...'))
2676 def debugstate(ui, repo, nodates=None, datesort=None):
2676 def debugstate(ui, repo, nodates=None, datesort=None):
2677 """show the contents of the current dirstate"""
2677 """show the contents of the current dirstate"""
2678 timestr = ""
2678 timestr = ""
2679 showdate = not nodates
2679 showdate = not nodates
2680 if datesort:
2680 if datesort:
2681 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2681 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2682 else:
2682 else:
2683 keyfunc = None # sort by filename
2683 keyfunc = None # sort by filename
2684 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2684 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2685 if showdate:
2685 if showdate:
2686 if ent[3] == -1:
2686 if ent[3] == -1:
2687 # Pad or slice to locale representation
2687 # Pad or slice to locale representation
2688 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2688 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2689 time.localtime(0)))
2689 time.localtime(0)))
2690 timestr = 'unset'
2690 timestr = 'unset'
2691 timestr = (timestr[:locale_len] +
2691 timestr = (timestr[:locale_len] +
2692 ' ' * (locale_len - len(timestr)))
2692 ' ' * (locale_len - len(timestr)))
2693 else:
2693 else:
2694 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2694 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2695 time.localtime(ent[3]))
2695 time.localtime(ent[3]))
2696 if ent[1] & 020000:
2696 if ent[1] & 020000:
2697 mode = 'lnk'
2697 mode = 'lnk'
2698 else:
2698 else:
2699 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2699 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2700 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2700 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2701 for f in repo.dirstate.copies():
2701 for f in repo.dirstate.copies():
2702 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2702 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2703
2703
2704 @command('debugsub',
2704 @command('debugsub',
2705 [('r', 'rev', '',
2705 [('r', 'rev', '',
2706 _('revision to check'), _('REV'))],
2706 _('revision to check'), _('REV'))],
2707 _('[-r REV] [REV]'))
2707 _('[-r REV] [REV]'))
2708 def debugsub(ui, repo, rev=None):
2708 def debugsub(ui, repo, rev=None):
2709 ctx = scmutil.revsingle(repo, rev, None)
2709 ctx = scmutil.revsingle(repo, rev, None)
2710 for k, v in sorted(ctx.substate.items()):
2710 for k, v in sorted(ctx.substate.items()):
2711 ui.write(('path %s\n') % k)
2711 ui.write(('path %s\n') % k)
2712 ui.write((' source %s\n') % v[0])
2712 ui.write((' source %s\n') % v[0])
2713 ui.write((' revision %s\n') % v[1])
2713 ui.write((' revision %s\n') % v[1])
2714
2714
2715 @command('debugsuccessorssets',
2715 @command('debugsuccessorssets',
2716 [],
2716 [],
2717 _('[REV]'))
2717 _('[REV]'))
2718 def debugsuccessorssets(ui, repo, *revs):
2718 def debugsuccessorssets(ui, repo, *revs):
2719 """show set of successors for revision
2719 """show set of successors for revision
2720
2720
2721 A successors set of changeset A is a consistent group of revisions that
2721 A successors set of changeset A is a consistent group of revisions that
2722 succeed A. It contains non-obsolete changesets only.
2722 succeed A. It contains non-obsolete changesets only.
2723
2723
2724 In most cases a changeset A has a single successors set containing a single
2724 In most cases a changeset A has a single successors set containing a single
2725 successor (changeset A replaced by A').
2725 successor (changeset A replaced by A').
2726
2726
2727 A changeset that is made obsolete with no successors are called "pruned".
2727 A changeset that is made obsolete with no successors are called "pruned".
2728 Such changesets have no successors sets at all.
2728 Such changesets have no successors sets at all.
2729
2729
2730 A changeset that has been "split" will have a successors set containing
2730 A changeset that has been "split" will have a successors set containing
2731 more than one successor.
2731 more than one successor.
2732
2732
2733 A changeset that has been rewritten in multiple different ways is called
2733 A changeset that has been rewritten in multiple different ways is called
2734 "divergent". Such changesets have multiple successor sets (each of which
2734 "divergent". Such changesets have multiple successor sets (each of which
2735 may also be split, i.e. have multiple successors).
2735 may also be split, i.e. have multiple successors).
2736
2736
2737 Results are displayed as follows::
2737 Results are displayed as follows::
2738
2738
2739 <rev1>
2739 <rev1>
2740 <successors-1A>
2740 <successors-1A>
2741 <rev2>
2741 <rev2>
2742 <successors-2A>
2742 <successors-2A>
2743 <successors-2B1> <successors-2B2> <successors-2B3>
2743 <successors-2B1> <successors-2B2> <successors-2B3>
2744
2744
2745 Here rev2 has two possible (i.e. divergent) successors sets. The first
2745 Here rev2 has two possible (i.e. divergent) successors sets. The first
2746 holds one element, whereas the second holds three (i.e. the changeset has
2746 holds one element, whereas the second holds three (i.e. the changeset has
2747 been split).
2747 been split).
2748 """
2748 """
2749 # passed to successorssets caching computation from one call to another
2749 # passed to successorssets caching computation from one call to another
2750 cache = {}
2750 cache = {}
2751 ctx2str = str
2751 ctx2str = str
2752 node2str = short
2752 node2str = short
2753 if ui.debug():
2753 if ui.debug():
2754 def ctx2str(ctx):
2754 def ctx2str(ctx):
2755 return ctx.hex()
2755 return ctx.hex()
2756 node2str = hex
2756 node2str = hex
2757 for rev in scmutil.revrange(repo, revs):
2757 for rev in scmutil.revrange(repo, revs):
2758 ctx = repo[rev]
2758 ctx = repo[rev]
2759 ui.write('%s\n'% ctx2str(ctx))
2759 ui.write('%s\n'% ctx2str(ctx))
2760 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2760 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2761 if succsset:
2761 if succsset:
2762 ui.write(' ')
2762 ui.write(' ')
2763 ui.write(node2str(succsset[0]))
2763 ui.write(node2str(succsset[0]))
2764 for node in succsset[1:]:
2764 for node in succsset[1:]:
2765 ui.write(' ')
2765 ui.write(' ')
2766 ui.write(node2str(node))
2766 ui.write(node2str(node))
2767 ui.write('\n')
2767 ui.write('\n')
2768
2768
2769 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2769 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2770 def debugwalk(ui, repo, *pats, **opts):
2770 def debugwalk(ui, repo, *pats, **opts):
2771 """show how files match on given patterns"""
2771 """show how files match on given patterns"""
2772 m = scmutil.match(repo[None], pats, opts)
2772 m = scmutil.match(repo[None], pats, opts)
2773 items = list(repo.walk(m))
2773 items = list(repo.walk(m))
2774 if not items:
2774 if not items:
2775 return
2775 return
2776 f = lambda fn: fn
2776 f = lambda fn: fn
2777 if ui.configbool('ui', 'slash') and os.sep != '/':
2777 if ui.configbool('ui', 'slash') and os.sep != '/':
2778 f = lambda fn: util.normpath(fn)
2778 f = lambda fn: util.normpath(fn)
2779 fmt = 'f %%-%ds %%-%ds %%s' % (
2779 fmt = 'f %%-%ds %%-%ds %%s' % (
2780 max([len(abs) for abs in items]),
2780 max([len(abs) for abs in items]),
2781 max([len(m.rel(abs)) for abs in items]))
2781 max([len(m.rel(abs)) for abs in items]))
2782 for abs in items:
2782 for abs in items:
2783 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2783 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2784 ui.write("%s\n" % line.rstrip())
2784 ui.write("%s\n" % line.rstrip())
2785
2785
2786 @command('debugwireargs',
2786 @command('debugwireargs',
2787 [('', 'three', '', 'three'),
2787 [('', 'three', '', 'three'),
2788 ('', 'four', '', 'four'),
2788 ('', 'four', '', 'four'),
2789 ('', 'five', '', 'five'),
2789 ('', 'five', '', 'five'),
2790 ] + remoteopts,
2790 ] + remoteopts,
2791 _('REPO [OPTIONS]... [ONE [TWO]]'))
2791 _('REPO [OPTIONS]... [ONE [TWO]]'))
2792 def debugwireargs(ui, repopath, *vals, **opts):
2792 def debugwireargs(ui, repopath, *vals, **opts):
2793 repo = hg.peer(ui, opts, repopath)
2793 repo = hg.peer(ui, opts, repopath)
2794 for opt in remoteopts:
2794 for opt in remoteopts:
2795 del opts[opt[1]]
2795 del opts[opt[1]]
2796 args = {}
2796 args = {}
2797 for k, v in opts.iteritems():
2797 for k, v in opts.iteritems():
2798 if v:
2798 if v:
2799 args[k] = v
2799 args[k] = v
2800 # run twice to check that we don't mess up the stream for the next command
2800 # run twice to check that we don't mess up the stream for the next command
2801 res1 = repo.debugwireargs(*vals, **args)
2801 res1 = repo.debugwireargs(*vals, **args)
2802 res2 = repo.debugwireargs(*vals, **args)
2802 res2 = repo.debugwireargs(*vals, **args)
2803 ui.write("%s\n" % res1)
2803 ui.write("%s\n" % res1)
2804 if res1 != res2:
2804 if res1 != res2:
2805 ui.warn("%s\n" % res2)
2805 ui.warn("%s\n" % res2)
2806
2806
2807 @command('^diff',
2807 @command('^diff',
2808 [('r', 'rev', [], _('revision'), _('REV')),
2808 [('r', 'rev', [], _('revision'), _('REV')),
2809 ('c', 'change', '', _('change made by revision'), _('REV'))
2809 ('c', 'change', '', _('change made by revision'), _('REV'))
2810 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2810 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2811 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2811 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2812 def diff(ui, repo, *pats, **opts):
2812 def diff(ui, repo, *pats, **opts):
2813 """diff repository (or selected files)
2813 """diff repository (or selected files)
2814
2814
2815 Show differences between revisions for the specified files.
2815 Show differences between revisions for the specified files.
2816
2816
2817 Differences between files are shown using the unified diff format.
2817 Differences between files are shown using the unified diff format.
2818
2818
2819 .. note::
2819 .. note::
2820
2820
2821 diff may generate unexpected results for merges, as it will
2821 diff may generate unexpected results for merges, as it will
2822 default to comparing against the working directory's first
2822 default to comparing against the working directory's first
2823 parent changeset if no revisions are specified.
2823 parent changeset if no revisions are specified.
2824
2824
2825 When two revision arguments are given, then changes are shown
2825 When two revision arguments are given, then changes are shown
2826 between those revisions. If only one revision is specified then
2826 between those revisions. If only one revision is specified then
2827 that revision is compared to the working directory, and, when no
2827 that revision is compared to the working directory, and, when no
2828 revisions are specified, the working directory files are compared
2828 revisions are specified, the working directory files are compared
2829 to its parent.
2829 to its parent.
2830
2830
2831 Alternatively you can specify -c/--change with a revision to see
2831 Alternatively you can specify -c/--change with a revision to see
2832 the changes in that changeset relative to its first parent.
2832 the changes in that changeset relative to its first parent.
2833
2833
2834 Without the -a/--text option, diff will avoid generating diffs of
2834 Without the -a/--text option, diff will avoid generating diffs of
2835 files it detects as binary. With -a, diff will generate a diff
2835 files it detects as binary. With -a, diff will generate a diff
2836 anyway, probably with undesirable results.
2836 anyway, probably with undesirable results.
2837
2837
2838 Use the -g/--git option to generate diffs in the git extended diff
2838 Use the -g/--git option to generate diffs in the git extended diff
2839 format. For more information, read :hg:`help diffs`.
2839 format. For more information, read :hg:`help diffs`.
2840
2840
2841 .. container:: verbose
2841 .. container:: verbose
2842
2842
2843 Examples:
2843 Examples:
2844
2844
2845 - compare a file in the current working directory to its parent::
2845 - compare a file in the current working directory to its parent::
2846
2846
2847 hg diff foo.c
2847 hg diff foo.c
2848
2848
2849 - compare two historical versions of a directory, with rename info::
2849 - compare two historical versions of a directory, with rename info::
2850
2850
2851 hg diff --git -r 1.0:1.2 lib/
2851 hg diff --git -r 1.0:1.2 lib/
2852
2852
2853 - get change stats relative to the last change on some date::
2853 - get change stats relative to the last change on some date::
2854
2854
2855 hg diff --stat -r "date('may 2')"
2855 hg diff --stat -r "date('may 2')"
2856
2856
2857 - diff all newly-added files that contain a keyword::
2857 - diff all newly-added files that contain a keyword::
2858
2858
2859 hg diff "set:added() and grep(GNU)"
2859 hg diff "set:added() and grep(GNU)"
2860
2860
2861 - compare a revision and its parents::
2861 - compare a revision and its parents::
2862
2862
2863 hg diff -c 9353 # compare against first parent
2863 hg diff -c 9353 # compare against first parent
2864 hg diff -r 9353^:9353 # same using revset syntax
2864 hg diff -r 9353^:9353 # same using revset syntax
2865 hg diff -r 9353^2:9353 # compare against the second parent
2865 hg diff -r 9353^2:9353 # compare against the second parent
2866
2866
2867 Returns 0 on success.
2867 Returns 0 on success.
2868 """
2868 """
2869
2869
2870 revs = opts.get('rev')
2870 revs = opts.get('rev')
2871 change = opts.get('change')
2871 change = opts.get('change')
2872 stat = opts.get('stat')
2872 stat = opts.get('stat')
2873 reverse = opts.get('reverse')
2873 reverse = opts.get('reverse')
2874
2874
2875 if revs and change:
2875 if revs and change:
2876 msg = _('cannot specify --rev and --change at the same time')
2876 msg = _('cannot specify --rev and --change at the same time')
2877 raise util.Abort(msg)
2877 raise util.Abort(msg)
2878 elif change:
2878 elif change:
2879 node2 = scmutil.revsingle(repo, change, None).node()
2879 node2 = scmutil.revsingle(repo, change, None).node()
2880 node1 = repo[node2].p1().node()
2880 node1 = repo[node2].p1().node()
2881 else:
2881 else:
2882 node1, node2 = scmutil.revpair(repo, revs)
2882 node1, node2 = scmutil.revpair(repo, revs)
2883
2883
2884 if reverse:
2884 if reverse:
2885 node1, node2 = node2, node1
2885 node1, node2 = node2, node1
2886
2886
2887 diffopts = patch.diffopts(ui, opts)
2887 diffopts = patch.diffopts(ui, opts)
2888 m = scmutil.match(repo[node2], pats, opts)
2888 m = scmutil.match(repo[node2], pats, opts)
2889 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2889 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2890 listsubrepos=opts.get('subrepos'))
2890 listsubrepos=opts.get('subrepos'))
2891
2891
2892 @command('^export',
2892 @command('^export',
2893 [('o', 'output', '',
2893 [('o', 'output', '',
2894 _('print output to file with formatted name'), _('FORMAT')),
2894 _('print output to file with formatted name'), _('FORMAT')),
2895 ('', 'switch-parent', None, _('diff against the second parent')),
2895 ('', 'switch-parent', None, _('diff against the second parent')),
2896 ('r', 'rev', [], _('revisions to export'), _('REV')),
2896 ('r', 'rev', [], _('revisions to export'), _('REV')),
2897 ] + diffopts,
2897 ] + diffopts,
2898 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2898 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2899 def export(ui, repo, *changesets, **opts):
2899 def export(ui, repo, *changesets, **opts):
2900 """dump the header and diffs for one or more changesets
2900 """dump the header and diffs for one or more changesets
2901
2901
2902 Print the changeset header and diffs for one or more revisions.
2902 Print the changeset header and diffs for one or more revisions.
2903 If no revision is given, the parent of the working directory is used.
2903 If no revision is given, the parent of the working directory is used.
2904
2904
2905 The information shown in the changeset header is: author, date,
2905 The information shown in the changeset header is: author, date,
2906 branch name (if non-default), changeset hash, parent(s) and commit
2906 branch name (if non-default), changeset hash, parent(s) and commit
2907 comment.
2907 comment.
2908
2908
2909 .. note::
2909 .. note::
2910
2910
2911 export may generate unexpected diff output for merge
2911 export may generate unexpected diff output for merge
2912 changesets, as it will compare the merge changeset against its
2912 changesets, as it will compare the merge changeset against its
2913 first parent only.
2913 first parent only.
2914
2914
2915 Output may be to a file, in which case the name of the file is
2915 Output may be to a file, in which case the name of the file is
2916 given using a format string. The formatting rules are as follows:
2916 given using a format string. The formatting rules are as follows:
2917
2917
2918 :``%%``: literal "%" character
2918 :``%%``: literal "%" character
2919 :``%H``: changeset hash (40 hexadecimal digits)
2919 :``%H``: changeset hash (40 hexadecimal digits)
2920 :``%N``: number of patches being generated
2920 :``%N``: number of patches being generated
2921 :``%R``: changeset revision number
2921 :``%R``: changeset revision number
2922 :``%b``: basename of the exporting repository
2922 :``%b``: basename of the exporting repository
2923 :``%h``: short-form changeset hash (12 hexadecimal digits)
2923 :``%h``: short-form changeset hash (12 hexadecimal digits)
2924 :``%m``: first line of the commit message (only alphanumeric characters)
2924 :``%m``: first line of the commit message (only alphanumeric characters)
2925 :``%n``: zero-padded sequence number, starting at 1
2925 :``%n``: zero-padded sequence number, starting at 1
2926 :``%r``: zero-padded changeset revision number
2926 :``%r``: zero-padded changeset revision number
2927
2927
2928 Without the -a/--text option, export will avoid generating diffs
2928 Without the -a/--text option, export will avoid generating diffs
2929 of files it detects as binary. With -a, export will generate a
2929 of files it detects as binary. With -a, export will generate a
2930 diff anyway, probably with undesirable results.
2930 diff anyway, probably with undesirable results.
2931
2931
2932 Use the -g/--git option to generate diffs in the git extended diff
2932 Use the -g/--git option to generate diffs in the git extended diff
2933 format. See :hg:`help diffs` for more information.
2933 format. See :hg:`help diffs` for more information.
2934
2934
2935 With the --switch-parent option, the diff will be against the
2935 With the --switch-parent option, the diff will be against the
2936 second parent. It can be useful to review a merge.
2936 second parent. It can be useful to review a merge.
2937
2937
2938 .. container:: verbose
2938 .. container:: verbose
2939
2939
2940 Examples:
2940 Examples:
2941
2941
2942 - use export and import to transplant a bugfix to the current
2942 - use export and import to transplant a bugfix to the current
2943 branch::
2943 branch::
2944
2944
2945 hg export -r 9353 | hg import -
2945 hg export -r 9353 | hg import -
2946
2946
2947 - export all the changesets between two revisions to a file with
2947 - export all the changesets between two revisions to a file with
2948 rename information::
2948 rename information::
2949
2949
2950 hg export --git -r 123:150 > changes.txt
2950 hg export --git -r 123:150 > changes.txt
2951
2951
2952 - split outgoing changes into a series of patches with
2952 - split outgoing changes into a series of patches with
2953 descriptive names::
2953 descriptive names::
2954
2954
2955 hg export -r "outgoing()" -o "%n-%m.patch"
2955 hg export -r "outgoing()" -o "%n-%m.patch"
2956
2956
2957 Returns 0 on success.
2957 Returns 0 on success.
2958 """
2958 """
2959 changesets += tuple(opts.get('rev', []))
2959 changesets += tuple(opts.get('rev', []))
2960 if not changesets:
2960 if not changesets:
2961 changesets = ['.']
2961 changesets = ['.']
2962 revs = scmutil.revrange(repo, changesets)
2962 revs = scmutil.revrange(repo, changesets)
2963 if not revs:
2963 if not revs:
2964 raise util.Abort(_("export requires at least one changeset"))
2964 raise util.Abort(_("export requires at least one changeset"))
2965 if len(revs) > 1:
2965 if len(revs) > 1:
2966 ui.note(_('exporting patches:\n'))
2966 ui.note(_('exporting patches:\n'))
2967 else:
2967 else:
2968 ui.note(_('exporting patch:\n'))
2968 ui.note(_('exporting patch:\n'))
2969 cmdutil.export(repo, revs, template=opts.get('output'),
2969 cmdutil.export(repo, revs, template=opts.get('output'),
2970 switch_parent=opts.get('switch_parent'),
2970 switch_parent=opts.get('switch_parent'),
2971 opts=patch.diffopts(ui, opts))
2971 opts=patch.diffopts(ui, opts))
2972
2972
2973 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2973 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2974 def forget(ui, repo, *pats, **opts):
2974 def forget(ui, repo, *pats, **opts):
2975 """forget the specified files on the next commit
2975 """forget the specified files on the next commit
2976
2976
2977 Mark the specified files so they will no longer be tracked
2977 Mark the specified files so they will no longer be tracked
2978 after the next commit.
2978 after the next commit.
2979
2979
2980 This only removes files from the current branch, not from the
2980 This only removes files from the current branch, not from the
2981 entire project history, and it does not delete them from the
2981 entire project history, and it does not delete them from the
2982 working directory.
2982 working directory.
2983
2983
2984 To undo a forget before the next commit, see :hg:`add`.
2984 To undo a forget before the next commit, see :hg:`add`.
2985
2985
2986 .. container:: verbose
2986 .. container:: verbose
2987
2987
2988 Examples:
2988 Examples:
2989
2989
2990 - forget newly-added binary files::
2990 - forget newly-added binary files::
2991
2991
2992 hg forget "set:added() and binary()"
2992 hg forget "set:added() and binary()"
2993
2993
2994 - forget files that would be excluded by .hgignore::
2994 - forget files that would be excluded by .hgignore::
2995
2995
2996 hg forget "set:hgignore()"
2996 hg forget "set:hgignore()"
2997
2997
2998 Returns 0 on success.
2998 Returns 0 on success.
2999 """
2999 """
3000
3000
3001 if not pats:
3001 if not pats:
3002 raise util.Abort(_('no files specified'))
3002 raise util.Abort(_('no files specified'))
3003
3003
3004 m = scmutil.match(repo[None], pats, opts)
3004 m = scmutil.match(repo[None], pats, opts)
3005 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3005 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3006 return rejected and 1 or 0
3006 return rejected and 1 or 0
3007
3007
3008 @command(
3008 @command(
3009 'graft',
3009 'graft',
3010 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3010 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3011 ('c', 'continue', False, _('resume interrupted graft')),
3011 ('c', 'continue', False, _('resume interrupted graft')),
3012 ('e', 'edit', False, _('invoke editor on commit messages')),
3012 ('e', 'edit', False, _('invoke editor on commit messages')),
3013 ('', 'log', None, _('append graft info to log message')),
3013 ('', 'log', None, _('append graft info to log message')),
3014 ('D', 'currentdate', False,
3014 ('D', 'currentdate', False,
3015 _('record the current date as commit date')),
3015 _('record the current date as commit date')),
3016 ('U', 'currentuser', False,
3016 ('U', 'currentuser', False,
3017 _('record the current user as committer'), _('DATE'))]
3017 _('record the current user as committer'), _('DATE'))]
3018 + commitopts2 + mergetoolopts + dryrunopts,
3018 + commitopts2 + mergetoolopts + dryrunopts,
3019 _('[OPTION]... [-r] REV...'))
3019 _('[OPTION]... [-r] REV...'))
3020 def graft(ui, repo, *revs, **opts):
3020 def graft(ui, repo, *revs, **opts):
3021 '''copy changes from other branches onto the current branch
3021 '''copy changes from other branches onto the current branch
3022
3022
3023 This command uses Mercurial's merge logic to copy individual
3023 This command uses Mercurial's merge logic to copy individual
3024 changes from other branches without merging branches in the
3024 changes from other branches without merging branches in the
3025 history graph. This is sometimes known as 'backporting' or
3025 history graph. This is sometimes known as 'backporting' or
3026 'cherry-picking'. By default, graft will copy user, date, and
3026 'cherry-picking'. By default, graft will copy user, date, and
3027 description from the source changesets.
3027 description from the source changesets.
3028
3028
3029 Changesets that are ancestors of the current revision, that have
3029 Changesets that are ancestors of the current revision, that have
3030 already been grafted, or that are merges will be skipped.
3030 already been grafted, or that are merges will be skipped.
3031
3031
3032 If --log is specified, log messages will have a comment appended
3032 If --log is specified, log messages will have a comment appended
3033 of the form::
3033 of the form::
3034
3034
3035 (grafted from CHANGESETHASH)
3035 (grafted from CHANGESETHASH)
3036
3036
3037 If a graft merge results in conflicts, the graft process is
3037 If a graft merge results in conflicts, the graft process is
3038 interrupted so that the current merge can be manually resolved.
3038 interrupted so that the current merge can be manually resolved.
3039 Once all conflicts are addressed, the graft process can be
3039 Once all conflicts are addressed, the graft process can be
3040 continued with the -c/--continue option.
3040 continued with the -c/--continue option.
3041
3041
3042 .. note::
3042 .. note::
3043
3043
3044 The -c/--continue option does not reapply earlier options.
3044 The -c/--continue option does not reapply earlier options.
3045
3045
3046 .. container:: verbose
3046 .. container:: verbose
3047
3047
3048 Examples:
3048 Examples:
3049
3049
3050 - copy a single change to the stable branch and edit its description::
3050 - copy a single change to the stable branch and edit its description::
3051
3051
3052 hg update stable
3052 hg update stable
3053 hg graft --edit 9393
3053 hg graft --edit 9393
3054
3054
3055 - graft a range of changesets with one exception, updating dates::
3055 - graft a range of changesets with one exception, updating dates::
3056
3056
3057 hg graft -D "2085::2093 and not 2091"
3057 hg graft -D "2085::2093 and not 2091"
3058
3058
3059 - continue a graft after resolving conflicts::
3059 - continue a graft after resolving conflicts::
3060
3060
3061 hg graft -c
3061 hg graft -c
3062
3062
3063 - show the source of a grafted changeset::
3063 - show the source of a grafted changeset::
3064
3064
3065 hg log --debug -r .
3065 hg log --debug -r .
3066
3066
3067 Returns 0 on successful completion.
3067 Returns 0 on successful completion.
3068 '''
3068 '''
3069
3069
3070 revs = list(revs)
3070 revs = list(revs)
3071 revs.extend(opts['rev'])
3071 revs.extend(opts['rev'])
3072
3072
3073 if not opts.get('user') and opts.get('currentuser'):
3073 if not opts.get('user') and opts.get('currentuser'):
3074 opts['user'] = ui.username()
3074 opts['user'] = ui.username()
3075 if not opts.get('date') and opts.get('currentdate'):
3075 if not opts.get('date') and opts.get('currentdate'):
3076 opts['date'] = "%d %d" % util.makedate()
3076 opts['date'] = "%d %d" % util.makedate()
3077
3077
3078 editor = None
3078 editor = None
3079 if opts.get('edit'):
3079 if opts.get('edit'):
3080 editor = cmdutil.commitforceeditor
3080 editor = cmdutil.commitforceeditor
3081
3081
3082 cont = False
3082 cont = False
3083 if opts['continue']:
3083 if opts['continue']:
3084 cont = True
3084 cont = True
3085 if revs:
3085 if revs:
3086 raise util.Abort(_("can't specify --continue and revisions"))
3086 raise util.Abort(_("can't specify --continue and revisions"))
3087 # read in unfinished revisions
3087 # read in unfinished revisions
3088 try:
3088 try:
3089 nodes = repo.opener.read('graftstate').splitlines()
3089 nodes = repo.opener.read('graftstate').splitlines()
3090 revs = [repo[node].rev() for node in nodes]
3090 revs = [repo[node].rev() for node in nodes]
3091 except IOError, inst:
3091 except IOError, inst:
3092 if inst.errno != errno.ENOENT:
3092 if inst.errno != errno.ENOENT:
3093 raise
3093 raise
3094 raise util.Abort(_("no graft state found, can't continue"))
3094 raise util.Abort(_("no graft state found, can't continue"))
3095 else:
3095 else:
3096 cmdutil.checkunfinished(repo)
3096 cmdutil.checkunfinished(repo)
3097 cmdutil.bailifchanged(repo)
3097 cmdutil.bailifchanged(repo)
3098 if not revs:
3098 if not revs:
3099 raise util.Abort(_('no revisions specified'))
3099 raise util.Abort(_('no revisions specified'))
3100 revs = scmutil.revrange(repo, revs)
3100 revs = scmutil.revrange(repo, revs)
3101
3101
3102 # check for merges
3102 # check for merges
3103 for rev in repo.revs('%ld and merge()', revs):
3103 for rev in repo.revs('%ld and merge()', revs):
3104 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3104 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3105 revs.remove(rev)
3105 revs.remove(rev)
3106 if not revs:
3106 if not revs:
3107 return -1
3107 return -1
3108
3108
3109 # check for ancestors of dest branch
3109 # check for ancestors of dest branch
3110 crev = repo['.'].rev()
3110 crev = repo['.'].rev()
3111 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3111 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3112 # Cannot use x.remove(y) on smart set, this has to be a list.
3112 # Cannot use x.remove(y) on smart set, this has to be a list.
3113 # XXX make this lazy in the future
3113 # XXX make this lazy in the future
3114 revs = list(revs)
3114 revs = list(revs)
3115 # don't mutate while iterating, create a copy
3115 # don't mutate while iterating, create a copy
3116 for rev in list(revs):
3116 for rev in list(revs):
3117 if rev in ancestors:
3117 if rev in ancestors:
3118 ui.warn(_('skipping ancestor revision %s\n') % rev)
3118 ui.warn(_('skipping ancestor revision %s\n') % rev)
3119 # XXX remove on list is slow
3119 # XXX remove on list is slow
3120 revs.remove(rev)
3120 revs.remove(rev)
3121 if not revs:
3121 if not revs:
3122 return -1
3122 return -1
3123
3123
3124 # analyze revs for earlier grafts
3124 # analyze revs for earlier grafts
3125 ids = {}
3125 ids = {}
3126 for ctx in repo.set("%ld", revs):
3126 for ctx in repo.set("%ld", revs):
3127 ids[ctx.hex()] = ctx.rev()
3127 ids[ctx.hex()] = ctx.rev()
3128 n = ctx.extra().get('source')
3128 n = ctx.extra().get('source')
3129 if n:
3129 if n:
3130 ids[n] = ctx.rev()
3130 ids[n] = ctx.rev()
3131
3131
3132 # check ancestors for earlier grafts
3132 # check ancestors for earlier grafts
3133 ui.debug('scanning for duplicate grafts\n')
3133 ui.debug('scanning for duplicate grafts\n')
3134
3134
3135 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3135 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3136 ctx = repo[rev]
3136 ctx = repo[rev]
3137 n = ctx.extra().get('source')
3137 n = ctx.extra().get('source')
3138 if n in ids:
3138 if n in ids:
3139 r = repo[n].rev()
3139 r = repo[n].rev()
3140 if r in revs:
3140 if r in revs:
3141 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3141 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3142 % (r, rev))
3142 % (r, rev))
3143 revs.remove(r)
3143 revs.remove(r)
3144 elif ids[n] in revs:
3144 elif ids[n] in revs:
3145 ui.warn(_('skipping already grafted revision %s '
3145 ui.warn(_('skipping already grafted revision %s '
3146 '(%s also has origin %d)\n') % (ids[n], rev, r))
3146 '(%s also has origin %d)\n') % (ids[n], rev, r))
3147 revs.remove(ids[n])
3147 revs.remove(ids[n])
3148 elif ctx.hex() in ids:
3148 elif ctx.hex() in ids:
3149 r = ids[ctx.hex()]
3149 r = ids[ctx.hex()]
3150 ui.warn(_('skipping already grafted revision %s '
3150 ui.warn(_('skipping already grafted revision %s '
3151 '(was grafted from %d)\n') % (r, rev))
3151 '(was grafted from %d)\n') % (r, rev))
3152 revs.remove(r)
3152 revs.remove(r)
3153 if not revs:
3153 if not revs:
3154 return -1
3154 return -1
3155
3155
3156 wlock = repo.wlock()
3156 wlock = repo.wlock()
3157 try:
3157 try:
3158 current = repo['.']
3158 current = repo['.']
3159 for pos, ctx in enumerate(repo.set("%ld", revs)):
3159 for pos, ctx in enumerate(repo.set("%ld", revs)):
3160
3160
3161 ui.status(_('grafting revision %s\n') % ctx.rev())
3161 ui.status(_('grafting revision %s\n') % ctx.rev())
3162 if opts.get('dry_run'):
3162 if opts.get('dry_run'):
3163 continue
3163 continue
3164
3164
3165 source = ctx.extra().get('source')
3165 source = ctx.extra().get('source')
3166 if not source:
3166 if not source:
3167 source = ctx.hex()
3167 source = ctx.hex()
3168 extra = {'source': source}
3168 extra = {'source': source}
3169 user = ctx.user()
3169 user = ctx.user()
3170 if opts.get('user'):
3170 if opts.get('user'):
3171 user = opts['user']
3171 user = opts['user']
3172 date = ctx.date()
3172 date = ctx.date()
3173 if opts.get('date'):
3173 if opts.get('date'):
3174 date = opts['date']
3174 date = opts['date']
3175 message = ctx.description()
3175 message = ctx.description()
3176 if opts.get('log'):
3176 if opts.get('log'):
3177 message += '\n(grafted from %s)' % ctx.hex()
3177 message += '\n(grafted from %s)' % ctx.hex()
3178
3178
3179 # we don't merge the first commit when continuing
3179 # we don't merge the first commit when continuing
3180 if not cont:
3180 if not cont:
3181 # perform the graft merge with p1(rev) as 'ancestor'
3181 # perform the graft merge with p1(rev) as 'ancestor'
3182 try:
3182 try:
3183 # ui.forcemerge is an internal variable, do not document
3183 # ui.forcemerge is an internal variable, do not document
3184 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3184 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3185 'graft')
3185 'graft')
3186 stats = mergemod.update(repo, ctx.node(), True, True, False,
3186 stats = mergemod.update(repo, ctx.node(), True, True, False,
3187 ctx.p1().node())
3187 ctx.p1().node())
3188 finally:
3188 finally:
3189 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3189 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3190 # report any conflicts
3190 # report any conflicts
3191 if stats and stats[3] > 0:
3191 if stats and stats[3] > 0:
3192 # write out state for --continue
3192 # write out state for --continue
3193 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3193 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3194 repo.opener.write('graftstate', ''.join(nodelines))
3194 repo.opener.write('graftstate', ''.join(nodelines))
3195 raise util.Abort(
3195 raise util.Abort(
3196 _("unresolved conflicts, can't continue"),
3196 _("unresolved conflicts, can't continue"),
3197 hint=_('use hg resolve and hg graft --continue'))
3197 hint=_('use hg resolve and hg graft --continue'))
3198 else:
3198 else:
3199 cont = False
3199 cont = False
3200
3200
3201 # drop the second merge parent
3201 # drop the second merge parent
3202 repo.setparents(current.node(), nullid)
3202 repo.setparents(current.node(), nullid)
3203 repo.dirstate.write()
3203 repo.dirstate.write()
3204 # fix up dirstate for copies and renames
3204 # fix up dirstate for copies and renames
3205 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3205 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3206
3206
3207 # commit
3207 # commit
3208 node = repo.commit(text=message, user=user,
3208 node = repo.commit(text=message, user=user,
3209 date=date, extra=extra, editor=editor)
3209 date=date, extra=extra, editor=editor)
3210 if node is None:
3210 if node is None:
3211 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3211 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3212 else:
3212 else:
3213 current = repo[node]
3213 current = repo[node]
3214 finally:
3214 finally:
3215 wlock.release()
3215 wlock.release()
3216
3216
3217 # remove state when we complete successfully
3217 # remove state when we complete successfully
3218 if not opts.get('dry_run'):
3218 if not opts.get('dry_run'):
3219 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3219 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3220
3220
3221 return 0
3221 return 0
3222
3222
3223 @command('grep',
3223 @command('grep',
3224 [('0', 'print0', None, _('end fields with NUL')),
3224 [('0', 'print0', None, _('end fields with NUL')),
3225 ('', 'all', None, _('print all revisions that match')),
3225 ('', 'all', None, _('print all revisions that match')),
3226 ('a', 'text', None, _('treat all files as text')),
3226 ('a', 'text', None, _('treat all files as text')),
3227 ('f', 'follow', None,
3227 ('f', 'follow', None,
3228 _('follow changeset history,'
3228 _('follow changeset history,'
3229 ' or file history across copies and renames')),
3229 ' or file history across copies and renames')),
3230 ('i', 'ignore-case', None, _('ignore case when matching')),
3230 ('i', 'ignore-case', None, _('ignore case when matching')),
3231 ('l', 'files-with-matches', None,
3231 ('l', 'files-with-matches', None,
3232 _('print only filenames and revisions that match')),
3232 _('print only filenames and revisions that match')),
3233 ('n', 'line-number', None, _('print matching line numbers')),
3233 ('n', 'line-number', None, _('print matching line numbers')),
3234 ('r', 'rev', [],
3234 ('r', 'rev', [],
3235 _('only search files changed within revision range'), _('REV')),
3235 _('only search files changed within revision range'), _('REV')),
3236 ('u', 'user', None, _('list the author (long with -v)')),
3236 ('u', 'user', None, _('list the author (long with -v)')),
3237 ('d', 'date', None, _('list the date (short with -q)')),
3237 ('d', 'date', None, _('list the date (short with -q)')),
3238 ] + walkopts,
3238 ] + walkopts,
3239 _('[OPTION]... PATTERN [FILE]...'))
3239 _('[OPTION]... PATTERN [FILE]...'))
3240 def grep(ui, repo, pattern, *pats, **opts):
3240 def grep(ui, repo, pattern, *pats, **opts):
3241 """search for a pattern in specified files and revisions
3241 """search for a pattern in specified files and revisions
3242
3242
3243 Search revisions of files for a regular expression.
3243 Search revisions of files for a regular expression.
3244
3244
3245 This command behaves differently than Unix grep. It only accepts
3245 This command behaves differently than Unix grep. It only accepts
3246 Python/Perl regexps. It searches repository history, not the
3246 Python/Perl regexps. It searches repository history, not the
3247 working directory. It always prints the revision number in which a
3247 working directory. It always prints the revision number in which a
3248 match appears.
3248 match appears.
3249
3249
3250 By default, grep only prints output for the first revision of a
3250 By default, grep only prints output for the first revision of a
3251 file in which it finds a match. To get it to print every revision
3251 file in which it finds a match. To get it to print every revision
3252 that contains a change in match status ("-" for a match that
3252 that contains a change in match status ("-" for a match that
3253 becomes a non-match, or "+" for a non-match that becomes a match),
3253 becomes a non-match, or "+" for a non-match that becomes a match),
3254 use the --all flag.
3254 use the --all flag.
3255
3255
3256 Returns 0 if a match is found, 1 otherwise.
3256 Returns 0 if a match is found, 1 otherwise.
3257 """
3257 """
3258 reflags = re.M
3258 reflags = re.M
3259 if opts.get('ignore_case'):
3259 if opts.get('ignore_case'):
3260 reflags |= re.I
3260 reflags |= re.I
3261 try:
3261 try:
3262 regexp = util.compilere(pattern, reflags)
3262 regexp = util.compilere(pattern, reflags)
3263 except re.error, inst:
3263 except re.error, inst:
3264 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3264 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3265 return 1
3265 return 1
3266 sep, eol = ':', '\n'
3266 sep, eol = ':', '\n'
3267 if opts.get('print0'):
3267 if opts.get('print0'):
3268 sep = eol = '\0'
3268 sep = eol = '\0'
3269
3269
3270 getfile = util.lrucachefunc(repo.file)
3270 getfile = util.lrucachefunc(repo.file)
3271
3271
3272 def matchlines(body):
3272 def matchlines(body):
3273 begin = 0
3273 begin = 0
3274 linenum = 0
3274 linenum = 0
3275 while begin < len(body):
3275 while begin < len(body):
3276 match = regexp.search(body, begin)
3276 match = regexp.search(body, begin)
3277 if not match:
3277 if not match:
3278 break
3278 break
3279 mstart, mend = match.span()
3279 mstart, mend = match.span()
3280 linenum += body.count('\n', begin, mstart) + 1
3280 linenum += body.count('\n', begin, mstart) + 1
3281 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3281 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3282 begin = body.find('\n', mend) + 1 or len(body) + 1
3282 begin = body.find('\n', mend) + 1 or len(body) + 1
3283 lend = begin - 1
3283 lend = begin - 1
3284 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3284 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3285
3285
3286 class linestate(object):
3286 class linestate(object):
3287 def __init__(self, line, linenum, colstart, colend):
3287 def __init__(self, line, linenum, colstart, colend):
3288 self.line = line
3288 self.line = line
3289 self.linenum = linenum
3289 self.linenum = linenum
3290 self.colstart = colstart
3290 self.colstart = colstart
3291 self.colend = colend
3291 self.colend = colend
3292
3292
3293 def __hash__(self):
3293 def __hash__(self):
3294 return hash((self.linenum, self.line))
3294 return hash((self.linenum, self.line))
3295
3295
3296 def __eq__(self, other):
3296 def __eq__(self, other):
3297 return self.line == other.line
3297 return self.line == other.line
3298
3298
3299 def __iter__(self):
3299 def __iter__(self):
3300 yield (self.line[:self.colstart], '')
3300 yield (self.line[:self.colstart], '')
3301 yield (self.line[self.colstart:self.colend], 'grep.match')
3301 yield (self.line[self.colstart:self.colend], 'grep.match')
3302 rest = self.line[self.colend:]
3302 rest = self.line[self.colend:]
3303 while rest != '':
3303 while rest != '':
3304 match = regexp.search(rest)
3304 match = regexp.search(rest)
3305 if not match:
3305 if not match:
3306 yield (rest, '')
3306 yield (rest, '')
3307 break
3307 break
3308 mstart, mend = match.span()
3308 mstart, mend = match.span()
3309 yield (rest[:mstart], '')
3309 yield (rest[:mstart], '')
3310 yield (rest[mstart:mend], 'grep.match')
3310 yield (rest[mstart:mend], 'grep.match')
3311 rest = rest[mend:]
3311 rest = rest[mend:]
3312
3312
3313 matches = {}
3313 matches = {}
3314 copies = {}
3314 copies = {}
3315 def grepbody(fn, rev, body):
3315 def grepbody(fn, rev, body):
3316 matches[rev].setdefault(fn, [])
3316 matches[rev].setdefault(fn, [])
3317 m = matches[rev][fn]
3317 m = matches[rev][fn]
3318 for lnum, cstart, cend, line in matchlines(body):
3318 for lnum, cstart, cend, line in matchlines(body):
3319 s = linestate(line, lnum, cstart, cend)
3319 s = linestate(line, lnum, cstart, cend)
3320 m.append(s)
3320 m.append(s)
3321
3321
3322 def difflinestates(a, b):
3322 def difflinestates(a, b):
3323 sm = difflib.SequenceMatcher(None, a, b)
3323 sm = difflib.SequenceMatcher(None, a, b)
3324 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3324 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3325 if tag == 'insert':
3325 if tag == 'insert':
3326 for i in xrange(blo, bhi):
3326 for i in xrange(blo, bhi):
3327 yield ('+', b[i])
3327 yield ('+', b[i])
3328 elif tag == 'delete':
3328 elif tag == 'delete':
3329 for i in xrange(alo, ahi):
3329 for i in xrange(alo, ahi):
3330 yield ('-', a[i])
3330 yield ('-', a[i])
3331 elif tag == 'replace':
3331 elif tag == 'replace':
3332 for i in xrange(alo, ahi):
3332 for i in xrange(alo, ahi):
3333 yield ('-', a[i])
3333 yield ('-', a[i])
3334 for i in xrange(blo, bhi):
3334 for i in xrange(blo, bhi):
3335 yield ('+', b[i])
3335 yield ('+', b[i])
3336
3336
3337 def display(fn, ctx, pstates, states):
3337 def display(fn, ctx, pstates, states):
3338 rev = ctx.rev()
3338 rev = ctx.rev()
3339 datefunc = ui.quiet and util.shortdate or util.datestr
3339 datefunc = ui.quiet and util.shortdate or util.datestr
3340 found = False
3340 found = False
3341 @util.cachefunc
3341 @util.cachefunc
3342 def binary():
3342 def binary():
3343 flog = getfile(fn)
3343 flog = getfile(fn)
3344 return util.binary(flog.read(ctx.filenode(fn)))
3344 return util.binary(flog.read(ctx.filenode(fn)))
3345
3345
3346 if opts.get('all'):
3346 if opts.get('all'):
3347 iter = difflinestates(pstates, states)
3347 iter = difflinestates(pstates, states)
3348 else:
3348 else:
3349 iter = [('', l) for l in states]
3349 iter = [('', l) for l in states]
3350 for change, l in iter:
3350 for change, l in iter:
3351 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3351 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3352
3352
3353 if opts.get('line_number'):
3353 if opts.get('line_number'):
3354 cols.append((str(l.linenum), 'grep.linenumber'))
3354 cols.append((str(l.linenum), 'grep.linenumber'))
3355 if opts.get('all'):
3355 if opts.get('all'):
3356 cols.append((change, 'grep.change'))
3356 cols.append((change, 'grep.change'))
3357 if opts.get('user'):
3357 if opts.get('user'):
3358 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3358 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3359 if opts.get('date'):
3359 if opts.get('date'):
3360 cols.append((datefunc(ctx.date()), 'grep.date'))
3360 cols.append((datefunc(ctx.date()), 'grep.date'))
3361 for col, label in cols[:-1]:
3361 for col, label in cols[:-1]:
3362 ui.write(col, label=label)
3362 ui.write(col, label=label)
3363 ui.write(sep, label='grep.sep')
3363 ui.write(sep, label='grep.sep')
3364 ui.write(cols[-1][0], label=cols[-1][1])
3364 ui.write(cols[-1][0], label=cols[-1][1])
3365 if not opts.get('files_with_matches'):
3365 if not opts.get('files_with_matches'):
3366 ui.write(sep, label='grep.sep')
3366 ui.write(sep, label='grep.sep')
3367 if not opts.get('text') and binary():
3367 if not opts.get('text') and binary():
3368 ui.write(" Binary file matches")
3368 ui.write(" Binary file matches")
3369 else:
3369 else:
3370 for s, label in l:
3370 for s, label in l:
3371 ui.write(s, label=label)
3371 ui.write(s, label=label)
3372 ui.write(eol)
3372 ui.write(eol)
3373 found = True
3373 found = True
3374 if opts.get('files_with_matches'):
3374 if opts.get('files_with_matches'):
3375 break
3375 break
3376 return found
3376 return found
3377
3377
3378 skip = {}
3378 skip = {}
3379 revfiles = {}
3379 revfiles = {}
3380 matchfn = scmutil.match(repo[None], pats, opts)
3380 matchfn = scmutil.match(repo[None], pats, opts)
3381 found = False
3381 found = False
3382 follow = opts.get('follow')
3382 follow = opts.get('follow')
3383
3383
3384 def prep(ctx, fns):
3384 def prep(ctx, fns):
3385 rev = ctx.rev()
3385 rev = ctx.rev()
3386 pctx = ctx.p1()
3386 pctx = ctx.p1()
3387 parent = pctx.rev()
3387 parent = pctx.rev()
3388 matches.setdefault(rev, {})
3388 matches.setdefault(rev, {})
3389 matches.setdefault(parent, {})
3389 matches.setdefault(parent, {})
3390 files = revfiles.setdefault(rev, [])
3390 files = revfiles.setdefault(rev, [])
3391 for fn in fns:
3391 for fn in fns:
3392 flog = getfile(fn)
3392 flog = getfile(fn)
3393 try:
3393 try:
3394 fnode = ctx.filenode(fn)
3394 fnode = ctx.filenode(fn)
3395 except error.LookupError:
3395 except error.LookupError:
3396 continue
3396 continue
3397
3397
3398 copied = flog.renamed(fnode)
3398 copied = flog.renamed(fnode)
3399 copy = follow and copied and copied[0]
3399 copy = follow and copied and copied[0]
3400 if copy:
3400 if copy:
3401 copies.setdefault(rev, {})[fn] = copy
3401 copies.setdefault(rev, {})[fn] = copy
3402 if fn in skip:
3402 if fn in skip:
3403 if copy:
3403 if copy:
3404 skip[copy] = True
3404 skip[copy] = True
3405 continue
3405 continue
3406 files.append(fn)
3406 files.append(fn)
3407
3407
3408 if fn not in matches[rev]:
3408 if fn not in matches[rev]:
3409 grepbody(fn, rev, flog.read(fnode))
3409 grepbody(fn, rev, flog.read(fnode))
3410
3410
3411 pfn = copy or fn
3411 pfn = copy or fn
3412 if pfn not in matches[parent]:
3412 if pfn not in matches[parent]:
3413 try:
3413 try:
3414 fnode = pctx.filenode(pfn)
3414 fnode = pctx.filenode(pfn)
3415 grepbody(pfn, parent, flog.read(fnode))
3415 grepbody(pfn, parent, flog.read(fnode))
3416 except error.LookupError:
3416 except error.LookupError:
3417 pass
3417 pass
3418
3418
3419 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3419 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3420 rev = ctx.rev()
3420 rev = ctx.rev()
3421 parent = ctx.p1().rev()
3421 parent = ctx.p1().rev()
3422 for fn in sorted(revfiles.get(rev, [])):
3422 for fn in sorted(revfiles.get(rev, [])):
3423 states = matches[rev][fn]
3423 states = matches[rev][fn]
3424 copy = copies.get(rev, {}).get(fn)
3424 copy = copies.get(rev, {}).get(fn)
3425 if fn in skip:
3425 if fn in skip:
3426 if copy:
3426 if copy:
3427 skip[copy] = True
3427 skip[copy] = True
3428 continue
3428 continue
3429 pstates = matches.get(parent, {}).get(copy or fn, [])
3429 pstates = matches.get(parent, {}).get(copy or fn, [])
3430 if pstates or states:
3430 if pstates or states:
3431 r = display(fn, ctx, pstates, states)
3431 r = display(fn, ctx, pstates, states)
3432 found = found or r
3432 found = found or r
3433 if r and not opts.get('all'):
3433 if r and not opts.get('all'):
3434 skip[fn] = True
3434 skip[fn] = True
3435 if copy:
3435 if copy:
3436 skip[copy] = True
3436 skip[copy] = True
3437 del matches[rev]
3437 del matches[rev]
3438 del revfiles[rev]
3438 del revfiles[rev]
3439
3439
3440 return not found
3440 return not found
3441
3441
3442 @command('heads',
3442 @command('heads',
3443 [('r', 'rev', '',
3443 [('r', 'rev', '',
3444 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3444 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3445 ('t', 'topo', False, _('show topological heads only')),
3445 ('t', 'topo', False, _('show topological heads only')),
3446 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3446 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3447 ('c', 'closed', False, _('show normal and closed branch heads')),
3447 ('c', 'closed', False, _('show normal and closed branch heads')),
3448 ] + templateopts,
3448 ] + templateopts,
3449 _('[-ct] [-r STARTREV] [REV]...'))
3449 _('[-ct] [-r STARTREV] [REV]...'))
3450 def heads(ui, repo, *branchrevs, **opts):
3450 def heads(ui, repo, *branchrevs, **opts):
3451 """show branch heads
3451 """show branch heads
3452
3452
3453 With no arguments, show all open branch heads in the repository.
3453 With no arguments, show all open branch heads in the repository.
3454 Branch heads are changesets that have no descendants on the
3454 Branch heads are changesets that have no descendants on the
3455 same branch. They are where development generally takes place and
3455 same branch. They are where development generally takes place and
3456 are the usual targets for update and merge operations.
3456 are the usual targets for update and merge operations.
3457
3457
3458 If one or more REVs are given, only open branch heads on the
3458 If one or more REVs are given, only open branch heads on the
3459 branches associated with the specified changesets are shown. This
3459 branches associated with the specified changesets are shown. This
3460 means that you can use :hg:`heads .` to see the heads on the
3460 means that you can use :hg:`heads .` to see the heads on the
3461 currently checked-out branch.
3461 currently checked-out branch.
3462
3462
3463 If -c/--closed is specified, also show branch heads marked closed
3463 If -c/--closed is specified, also show branch heads marked closed
3464 (see :hg:`commit --close-branch`).
3464 (see :hg:`commit --close-branch`).
3465
3465
3466 If STARTREV is specified, only those heads that are descendants of
3466 If STARTREV is specified, only those heads that are descendants of
3467 STARTREV will be displayed.
3467 STARTREV will be displayed.
3468
3468
3469 If -t/--topo is specified, named branch mechanics will be ignored and only
3469 If -t/--topo is specified, named branch mechanics will be ignored and only
3470 topological heads (changesets with no children) will be shown.
3470 topological heads (changesets with no children) will be shown.
3471
3471
3472 Returns 0 if matching heads are found, 1 if not.
3472 Returns 0 if matching heads are found, 1 if not.
3473 """
3473 """
3474
3474
3475 start = None
3475 start = None
3476 if 'rev' in opts:
3476 if 'rev' in opts:
3477 start = scmutil.revsingle(repo, opts['rev'], None).node()
3477 start = scmutil.revsingle(repo, opts['rev'], None).node()
3478
3478
3479 if opts.get('topo'):
3479 if opts.get('topo'):
3480 heads = [repo[h] for h in repo.heads(start)]
3480 heads = [repo[h] for h in repo.heads(start)]
3481 else:
3481 else:
3482 heads = []
3482 heads = []
3483 for branch in repo.branchmap():
3483 for branch in repo.branchmap():
3484 heads += repo.branchheads(branch, start, opts.get('closed'))
3484 heads += repo.branchheads(branch, start, opts.get('closed'))
3485 heads = [repo[h] for h in heads]
3485 heads = [repo[h] for h in heads]
3486
3486
3487 if branchrevs:
3487 if branchrevs:
3488 branches = set(repo[br].branch() for br in branchrevs)
3488 branches = set(repo[br].branch() for br in branchrevs)
3489 heads = [h for h in heads if h.branch() in branches]
3489 heads = [h for h in heads if h.branch() in branches]
3490
3490
3491 if opts.get('active') and branchrevs:
3491 if opts.get('active') and branchrevs:
3492 dagheads = repo.heads(start)
3492 dagheads = repo.heads(start)
3493 heads = [h for h in heads if h.node() in dagheads]
3493 heads = [h for h in heads if h.node() in dagheads]
3494
3494
3495 if branchrevs:
3495 if branchrevs:
3496 haveheads = set(h.branch() for h in heads)
3496 haveheads = set(h.branch() for h in heads)
3497 if branches - haveheads:
3497 if branches - haveheads:
3498 headless = ', '.join(b for b in branches - haveheads)
3498 headless = ', '.join(b for b in branches - haveheads)
3499 msg = _('no open branch heads found on branches %s')
3499 msg = _('no open branch heads found on branches %s')
3500 if opts.get('rev'):
3500 if opts.get('rev'):
3501 msg += _(' (started at %s)') % opts['rev']
3501 msg += _(' (started at %s)') % opts['rev']
3502 ui.warn((msg + '\n') % headless)
3502 ui.warn((msg + '\n') % headless)
3503
3503
3504 if not heads:
3504 if not heads:
3505 return 1
3505 return 1
3506
3506
3507 heads = sorted(heads, key=lambda x: -x.rev())
3507 heads = sorted(heads, key=lambda x: -x.rev())
3508 displayer = cmdutil.show_changeset(ui, repo, opts)
3508 displayer = cmdutil.show_changeset(ui, repo, opts)
3509 for ctx in heads:
3509 for ctx in heads:
3510 displayer.show(ctx)
3510 displayer.show(ctx)
3511 displayer.close()
3511 displayer.close()
3512
3512
3513 @command('help',
3513 @command('help',
3514 [('e', 'extension', None, _('show only help for extensions')),
3514 [('e', 'extension', None, _('show only help for extensions')),
3515 ('c', 'command', None, _('show only help for commands')),
3515 ('c', 'command', None, _('show only help for commands')),
3516 ('k', 'keyword', '', _('show topics matching keyword')),
3516 ('k', 'keyword', '', _('show topics matching keyword')),
3517 ],
3517 ],
3518 _('[-ec] [TOPIC]'))
3518 _('[-ec] [TOPIC]'))
3519 def help_(ui, name=None, **opts):
3519 def help_(ui, name=None, **opts):
3520 """show help for a given topic or a help overview
3520 """show help for a given topic or a help overview
3521
3521
3522 With no arguments, print a list of commands with short help messages.
3522 With no arguments, print a list of commands with short help messages.
3523
3523
3524 Given a topic, extension, or command name, print help for that
3524 Given a topic, extension, or command name, print help for that
3525 topic.
3525 topic.
3526
3526
3527 Returns 0 if successful.
3527 Returns 0 if successful.
3528 """
3528 """
3529
3529
3530 textwidth = min(ui.termwidth(), 80) - 2
3530 textwidth = min(ui.termwidth(), 80) - 2
3531
3531
3532 keep = ui.verbose and ['verbose'] or []
3532 keep = ui.verbose and ['verbose'] or []
3533 text = help.help_(ui, name, **opts)
3533 text = help.help_(ui, name, **opts)
3534
3534
3535 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3535 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3536 if 'verbose' in pruned:
3536 if 'verbose' in pruned:
3537 keep.append('omitted')
3537 keep.append('omitted')
3538 else:
3538 else:
3539 keep.append('notomitted')
3539 keep.append('notomitted')
3540 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3540 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3541 ui.write(formatted)
3541 ui.write(formatted)
3542
3542
3543
3543
3544 @command('identify|id',
3544 @command('identify|id',
3545 [('r', 'rev', '',
3545 [('r', 'rev', '',
3546 _('identify the specified revision'), _('REV')),
3546 _('identify the specified revision'), _('REV')),
3547 ('n', 'num', None, _('show local revision number')),
3547 ('n', 'num', None, _('show local revision number')),
3548 ('i', 'id', None, _('show global revision id')),
3548 ('i', 'id', None, _('show global revision id')),
3549 ('b', 'branch', None, _('show branch')),
3549 ('b', 'branch', None, _('show branch')),
3550 ('t', 'tags', None, _('show tags')),
3550 ('t', 'tags', None, _('show tags')),
3551 ('B', 'bookmarks', None, _('show bookmarks')),
3551 ('B', 'bookmarks', None, _('show bookmarks')),
3552 ] + remoteopts,
3552 ] + remoteopts,
3553 _('[-nibtB] [-r REV] [SOURCE]'))
3553 _('[-nibtB] [-r REV] [SOURCE]'))
3554 def identify(ui, repo, source=None, rev=None,
3554 def identify(ui, repo, source=None, rev=None,
3555 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3555 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3556 """identify the working copy or specified revision
3556 """identify the working copy or specified revision
3557
3557
3558 Print a summary identifying the repository state at REV using one or
3558 Print a summary identifying the repository state at REV using one or
3559 two parent hash identifiers, followed by a "+" if the working
3559 two parent hash identifiers, followed by a "+" if the working
3560 directory has uncommitted changes, the branch name (if not default),
3560 directory has uncommitted changes, the branch name (if not default),
3561 a list of tags, and a list of bookmarks.
3561 a list of tags, and a list of bookmarks.
3562
3562
3563 When REV is not given, print a summary of the current state of the
3563 When REV is not given, print a summary of the current state of the
3564 repository.
3564 repository.
3565
3565
3566 Specifying a path to a repository root or Mercurial bundle will
3566 Specifying a path to a repository root or Mercurial bundle will
3567 cause lookup to operate on that repository/bundle.
3567 cause lookup to operate on that repository/bundle.
3568
3568
3569 .. container:: verbose
3569 .. container:: verbose
3570
3570
3571 Examples:
3571 Examples:
3572
3572
3573 - generate a build identifier for the working directory::
3573 - generate a build identifier for the working directory::
3574
3574
3575 hg id --id > build-id.dat
3575 hg id --id > build-id.dat
3576
3576
3577 - find the revision corresponding to a tag::
3577 - find the revision corresponding to a tag::
3578
3578
3579 hg id -n -r 1.3
3579 hg id -n -r 1.3
3580
3580
3581 - check the most recent revision of a remote repository::
3581 - check the most recent revision of a remote repository::
3582
3582
3583 hg id -r tip http://selenic.com/hg/
3583 hg id -r tip http://selenic.com/hg/
3584
3584
3585 Returns 0 if successful.
3585 Returns 0 if successful.
3586 """
3586 """
3587
3587
3588 if not repo and not source:
3588 if not repo and not source:
3589 raise util.Abort(_("there is no Mercurial repository here "
3589 raise util.Abort(_("there is no Mercurial repository here "
3590 "(.hg not found)"))
3590 "(.hg not found)"))
3591
3591
3592 hexfunc = ui.debugflag and hex or short
3592 hexfunc = ui.debugflag and hex or short
3593 default = not (num or id or branch or tags or bookmarks)
3593 default = not (num or id or branch or tags or bookmarks)
3594 output = []
3594 output = []
3595 revs = []
3595 revs = []
3596
3596
3597 if source:
3597 if source:
3598 source, branches = hg.parseurl(ui.expandpath(source))
3598 source, branches = hg.parseurl(ui.expandpath(source))
3599 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3599 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3600 repo = peer.local()
3600 repo = peer.local()
3601 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3601 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3602
3602
3603 if not repo:
3603 if not repo:
3604 if num or branch or tags:
3604 if num or branch or tags:
3605 raise util.Abort(
3605 raise util.Abort(
3606 _("can't query remote revision number, branch, or tags"))
3606 _("can't query remote revision number, branch, or tags"))
3607 if not rev and revs:
3607 if not rev and revs:
3608 rev = revs[0]
3608 rev = revs[0]
3609 if not rev:
3609 if not rev:
3610 rev = "tip"
3610 rev = "tip"
3611
3611
3612 remoterev = peer.lookup(rev)
3612 remoterev = peer.lookup(rev)
3613 if default or id:
3613 if default or id:
3614 output = [hexfunc(remoterev)]
3614 output = [hexfunc(remoterev)]
3615
3615
3616 def getbms():
3616 def getbms():
3617 bms = []
3617 bms = []
3618
3618
3619 if 'bookmarks' in peer.listkeys('namespaces'):
3619 if 'bookmarks' in peer.listkeys('namespaces'):
3620 hexremoterev = hex(remoterev)
3620 hexremoterev = hex(remoterev)
3621 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3621 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3622 if bmr == hexremoterev]
3622 if bmr == hexremoterev]
3623
3623
3624 return sorted(bms)
3624 return sorted(bms)
3625
3625
3626 if bookmarks:
3626 if bookmarks:
3627 output.extend(getbms())
3627 output.extend(getbms())
3628 elif default and not ui.quiet:
3628 elif default and not ui.quiet:
3629 # multiple bookmarks for a single parent separated by '/'
3629 # multiple bookmarks for a single parent separated by '/'
3630 bm = '/'.join(getbms())
3630 bm = '/'.join(getbms())
3631 if bm:
3631 if bm:
3632 output.append(bm)
3632 output.append(bm)
3633 else:
3633 else:
3634 if not rev:
3634 if not rev:
3635 ctx = repo[None]
3635 ctx = repo[None]
3636 parents = ctx.parents()
3636 parents = ctx.parents()
3637 changed = ""
3637 changed = ""
3638 if default or id or num:
3638 if default or id or num:
3639 if (util.any(repo.status())
3639 if (util.any(repo.status())
3640 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3640 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3641 changed = '+'
3641 changed = '+'
3642 if default or id:
3642 if default or id:
3643 output = ["%s%s" %
3643 output = ["%s%s" %
3644 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3644 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3645 if num:
3645 if num:
3646 output.append("%s%s" %
3646 output.append("%s%s" %
3647 ('+'.join([str(p.rev()) for p in parents]), changed))
3647 ('+'.join([str(p.rev()) for p in parents]), changed))
3648 else:
3648 else:
3649 ctx = scmutil.revsingle(repo, rev)
3649 ctx = scmutil.revsingle(repo, rev)
3650 if default or id:
3650 if default or id:
3651 output = [hexfunc(ctx.node())]
3651 output = [hexfunc(ctx.node())]
3652 if num:
3652 if num:
3653 output.append(str(ctx.rev()))
3653 output.append(str(ctx.rev()))
3654
3654
3655 if default and not ui.quiet:
3655 if default and not ui.quiet:
3656 b = ctx.branch()
3656 b = ctx.branch()
3657 if b != 'default':
3657 if b != 'default':
3658 output.append("(%s)" % b)
3658 output.append("(%s)" % b)
3659
3659
3660 # multiple tags for a single parent separated by '/'
3660 # multiple tags for a single parent separated by '/'
3661 t = '/'.join(ctx.tags())
3661 t = '/'.join(ctx.tags())
3662 if t:
3662 if t:
3663 output.append(t)
3663 output.append(t)
3664
3664
3665 # multiple bookmarks for a single parent separated by '/'
3665 # multiple bookmarks for a single parent separated by '/'
3666 bm = '/'.join(ctx.bookmarks())
3666 bm = '/'.join(ctx.bookmarks())
3667 if bm:
3667 if bm:
3668 output.append(bm)
3668 output.append(bm)
3669 else:
3669 else:
3670 if branch:
3670 if branch:
3671 output.append(ctx.branch())
3671 output.append(ctx.branch())
3672
3672
3673 if tags:
3673 if tags:
3674 output.extend(ctx.tags())
3674 output.extend(ctx.tags())
3675
3675
3676 if bookmarks:
3676 if bookmarks:
3677 output.extend(ctx.bookmarks())
3677 output.extend(ctx.bookmarks())
3678
3678
3679 ui.write("%s\n" % ' '.join(output))
3679 ui.write("%s\n" % ' '.join(output))
3680
3680
3681 @command('import|patch',
3681 @command('import|patch',
3682 [('p', 'strip', 1,
3682 [('p', 'strip', 1,
3683 _('directory strip option for patch. This has the same '
3683 _('directory strip option for patch. This has the same '
3684 'meaning as the corresponding patch option'), _('NUM')),
3684 'meaning as the corresponding patch option'), _('NUM')),
3685 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3685 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3686 ('e', 'edit', False, _('invoke editor on commit messages')),
3686 ('e', 'edit', False, _('invoke editor on commit messages')),
3687 ('f', 'force', None,
3687 ('f', 'force', None,
3688 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3688 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3689 ('', 'no-commit', None,
3689 ('', 'no-commit', None,
3690 _("don't commit, just update the working directory")),
3690 _("don't commit, just update the working directory")),
3691 ('', 'bypass', None,
3691 ('', 'bypass', None,
3692 _("apply patch without touching the working directory")),
3692 _("apply patch without touching the working directory")),
3693 ('', 'exact', None,
3693 ('', 'exact', None,
3694 _('apply patch to the nodes from which it was generated')),
3694 _('apply patch to the nodes from which it was generated')),
3695 ('', 'import-branch', None,
3695 ('', 'import-branch', None,
3696 _('use any branch information in patch (implied by --exact)'))] +
3696 _('use any branch information in patch (implied by --exact)'))] +
3697 commitopts + commitopts2 + similarityopts,
3697 commitopts + commitopts2 + similarityopts,
3698 _('[OPTION]... PATCH...'))
3698 _('[OPTION]... PATCH...'))
3699 def import_(ui, repo, patch1=None, *patches, **opts):
3699 def import_(ui, repo, patch1=None, *patches, **opts):
3700 """import an ordered set of patches
3700 """import an ordered set of patches
3701
3701
3702 Import a list of patches and commit them individually (unless
3702 Import a list of patches and commit them individually (unless
3703 --no-commit is specified).
3703 --no-commit is specified).
3704
3704
3705 Because import first applies changes to the working directory,
3705 Because import first applies changes to the working directory,
3706 import will abort if there are outstanding changes.
3706 import will abort if there are outstanding changes.
3707
3707
3708 You can import a patch straight from a mail message. Even patches
3708 You can import a patch straight from a mail message. Even patches
3709 as attachments work (to use the body part, it must have type
3709 as attachments work (to use the body part, it must have type
3710 text/plain or text/x-patch). From and Subject headers of email
3710 text/plain or text/x-patch). From and Subject headers of email
3711 message are used as default committer and commit message. All
3711 message are used as default committer and commit message. All
3712 text/plain body parts before first diff are added to commit
3712 text/plain body parts before first diff are added to commit
3713 message.
3713 message.
3714
3714
3715 If the imported patch was generated by :hg:`export`, user and
3715 If the imported patch was generated by :hg:`export`, user and
3716 description from patch override values from message headers and
3716 description from patch override values from message headers and
3717 body. Values given on command line with -m/--message and -u/--user
3717 body. Values given on command line with -m/--message and -u/--user
3718 override these.
3718 override these.
3719
3719
3720 If --exact is specified, import will set the working directory to
3720 If --exact is specified, import will set the working directory to
3721 the parent of each patch before applying it, and will abort if the
3721 the parent of each patch before applying it, and will abort if the
3722 resulting changeset has a different ID than the one recorded in
3722 resulting changeset has a different ID than the one recorded in
3723 the patch. This may happen due to character set problems or other
3723 the patch. This may happen due to character set problems or other
3724 deficiencies in the text patch format.
3724 deficiencies in the text patch format.
3725
3725
3726 Use --bypass to apply and commit patches directly to the
3726 Use --bypass to apply and commit patches directly to the
3727 repository, not touching the working directory. Without --exact,
3727 repository, not touching the working directory. Without --exact,
3728 patches will be applied on top of the working directory parent
3728 patches will be applied on top of the working directory parent
3729 revision.
3729 revision.
3730
3730
3731 With -s/--similarity, hg will attempt to discover renames and
3731 With -s/--similarity, hg will attempt to discover renames and
3732 copies in the patch in the same way as :hg:`addremove`.
3732 copies in the patch in the same way as :hg:`addremove`.
3733
3733
3734 To read a patch from standard input, use "-" as the patch name. If
3734 To read a patch from standard input, use "-" as the patch name. If
3735 a URL is specified, the patch will be downloaded from it.
3735 a URL is specified, the patch will be downloaded from it.
3736 See :hg:`help dates` for a list of formats valid for -d/--date.
3736 See :hg:`help dates` for a list of formats valid for -d/--date.
3737
3737
3738 .. container:: verbose
3738 .. container:: verbose
3739
3739
3740 Examples:
3740 Examples:
3741
3741
3742 - import a traditional patch from a website and detect renames::
3742 - import a traditional patch from a website and detect renames::
3743
3743
3744 hg import -s 80 http://example.com/bugfix.patch
3744 hg import -s 80 http://example.com/bugfix.patch
3745
3745
3746 - import a changeset from an hgweb server::
3746 - import a changeset from an hgweb server::
3747
3747
3748 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3748 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3749
3749
3750 - import all the patches in an Unix-style mbox::
3750 - import all the patches in an Unix-style mbox::
3751
3751
3752 hg import incoming-patches.mbox
3752 hg import incoming-patches.mbox
3753
3753
3754 - attempt to exactly restore an exported changeset (not always
3754 - attempt to exactly restore an exported changeset (not always
3755 possible)::
3755 possible)::
3756
3756
3757 hg import --exact proposed-fix.patch
3757 hg import --exact proposed-fix.patch
3758
3758
3759 Returns 0 on success.
3759 Returns 0 on success.
3760 """
3760 """
3761
3761
3762 if not patch1:
3762 if not patch1:
3763 raise util.Abort(_('need at least one patch to import'))
3763 raise util.Abort(_('need at least one patch to import'))
3764
3764
3765 patches = (patch1,) + patches
3765 patches = (patch1,) + patches
3766
3766
3767 date = opts.get('date')
3767 date = opts.get('date')
3768 if date:
3768 if date:
3769 opts['date'] = util.parsedate(date)
3769 opts['date'] = util.parsedate(date)
3770
3770
3771 update = not opts.get('bypass')
3771 update = not opts.get('bypass')
3772 if not update and opts.get('no_commit'):
3772 if not update and opts.get('no_commit'):
3773 raise util.Abort(_('cannot use --no-commit with --bypass'))
3773 raise util.Abort(_('cannot use --no-commit with --bypass'))
3774 try:
3774 try:
3775 sim = float(opts.get('similarity') or 0)
3775 sim = float(opts.get('similarity') or 0)
3776 except ValueError:
3776 except ValueError:
3777 raise util.Abort(_('similarity must be a number'))
3777 raise util.Abort(_('similarity must be a number'))
3778 if sim < 0 or sim > 100:
3778 if sim < 0 or sim > 100:
3779 raise util.Abort(_('similarity must be between 0 and 100'))
3779 raise util.Abort(_('similarity must be between 0 and 100'))
3780 if sim and not update:
3780 if sim and not update:
3781 raise util.Abort(_('cannot use --similarity with --bypass'))
3781 raise util.Abort(_('cannot use --similarity with --bypass'))
3782
3782
3783 if update:
3783 if update:
3784 cmdutil.checkunfinished(repo)
3784 cmdutil.checkunfinished(repo)
3785 if (opts.get('exact') or not opts.get('force')) and update:
3785 if (opts.get('exact') or not opts.get('force')) and update:
3786 cmdutil.bailifchanged(repo)
3786 cmdutil.bailifchanged(repo)
3787
3787
3788 base = opts["base"]
3788 base = opts["base"]
3789 wlock = lock = tr = None
3789 wlock = lock = tr = None
3790 msgs = []
3790 msgs = []
3791
3791
3792
3792
3793 try:
3793 try:
3794 try:
3794 try:
3795 wlock = repo.wlock()
3795 wlock = repo.wlock()
3796 if not opts.get('no_commit'):
3796 if not opts.get('no_commit'):
3797 lock = repo.lock()
3797 lock = repo.lock()
3798 tr = repo.transaction('import')
3798 tr = repo.transaction('import')
3799 parents = repo.parents()
3799 parents = repo.parents()
3800 for patchurl in patches:
3800 for patchurl in patches:
3801 if patchurl == '-':
3801 if patchurl == '-':
3802 ui.status(_('applying patch from stdin\n'))
3802 ui.status(_('applying patch from stdin\n'))
3803 patchfile = ui.fin
3803 patchfile = ui.fin
3804 patchurl = 'stdin' # for error message
3804 patchurl = 'stdin' # for error message
3805 else:
3805 else:
3806 patchurl = os.path.join(base, patchurl)
3806 patchurl = os.path.join(base, patchurl)
3807 ui.status(_('applying %s\n') % patchurl)
3807 ui.status(_('applying %s\n') % patchurl)
3808 patchfile = hg.openpath(ui, patchurl)
3808 patchfile = hg.openpath(ui, patchurl)
3809
3809
3810 haspatch = False
3810 haspatch = False
3811 for hunk in patch.split(patchfile):
3811 for hunk in patch.split(patchfile):
3812 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3812 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3813 opts, msgs, hg.clean)
3813 opts, msgs, hg.clean)
3814 if msg:
3814 if msg:
3815 haspatch = True
3815 haspatch = True
3816 ui.note(msg + '\n')
3816 ui.note(msg + '\n')
3817 if update or opts.get('exact'):
3817 if update or opts.get('exact'):
3818 parents = repo.parents()
3818 parents = repo.parents()
3819 else:
3819 else:
3820 parents = [repo[node]]
3820 parents = [repo[node]]
3821
3821
3822 if not haspatch:
3822 if not haspatch:
3823 raise util.Abort(_('%s: no diffs found') % patchurl)
3823 raise util.Abort(_('%s: no diffs found') % patchurl)
3824
3824
3825 if tr:
3825 if tr:
3826 tr.close()
3826 tr.close()
3827 if msgs:
3827 if msgs:
3828 repo.savecommitmessage('\n* * *\n'.join(msgs))
3828 repo.savecommitmessage('\n* * *\n'.join(msgs))
3829 except: # re-raises
3829 except: # re-raises
3830 # wlock.release() indirectly calls dirstate.write(): since
3830 # wlock.release() indirectly calls dirstate.write(): since
3831 # we're crashing, we do not want to change the working dir
3831 # we're crashing, we do not want to change the working dir
3832 # parent after all, so make sure it writes nothing
3832 # parent after all, so make sure it writes nothing
3833 repo.dirstate.invalidate()
3833 repo.dirstate.invalidate()
3834 raise
3834 raise
3835 finally:
3835 finally:
3836 if tr:
3836 if tr:
3837 tr.release()
3837 tr.release()
3838 release(lock, wlock)
3838 release(lock, wlock)
3839
3839
3840 @command('incoming|in',
3840 @command('incoming|in',
3841 [('f', 'force', None,
3841 [('f', 'force', None,
3842 _('run even if remote repository is unrelated')),
3842 _('run even if remote repository is unrelated')),
3843 ('n', 'newest-first', None, _('show newest record first')),
3843 ('n', 'newest-first', None, _('show newest record first')),
3844 ('', 'bundle', '',
3844 ('', 'bundle', '',
3845 _('file to store the bundles into'), _('FILE')),
3845 _('file to store the bundles into'), _('FILE')),
3846 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3846 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3847 ('B', 'bookmarks', False, _("compare bookmarks")),
3847 ('B', 'bookmarks', False, _("compare bookmarks")),
3848 ('b', 'branch', [],
3848 ('b', 'branch', [],
3849 _('a specific branch you would like to pull'), _('BRANCH')),
3849 _('a specific branch you would like to pull'), _('BRANCH')),
3850 ] + logopts + remoteopts + subrepoopts,
3850 ] + logopts + remoteopts + subrepoopts,
3851 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3851 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3852 def incoming(ui, repo, source="default", **opts):
3852 def incoming(ui, repo, source="default", **opts):
3853 """show new changesets found in source
3853 """show new changesets found in source
3854
3854
3855 Show new changesets found in the specified path/URL or the default
3855 Show new changesets found in the specified path/URL or the default
3856 pull location. These are the changesets that would have been pulled
3856 pull location. These are the changesets that would have been pulled
3857 if a pull at the time you issued this command.
3857 if a pull at the time you issued this command.
3858
3858
3859 For remote repository, using --bundle avoids downloading the
3859 For remote repository, using --bundle avoids downloading the
3860 changesets twice if the incoming is followed by a pull.
3860 changesets twice if the incoming is followed by a pull.
3861
3861
3862 See pull for valid source format details.
3862 See pull for valid source format details.
3863
3863
3864 .. container:: verbose
3864 .. container:: verbose
3865
3865
3866 Examples:
3866 Examples:
3867
3867
3868 - show incoming changes with patches and full description::
3868 - show incoming changes with patches and full description::
3869
3869
3870 hg incoming -vp
3870 hg incoming -vp
3871
3871
3872 - show incoming changes excluding merges, store a bundle::
3872 - show incoming changes excluding merges, store a bundle::
3873
3873
3874 hg in -vpM --bundle incoming.hg
3874 hg in -vpM --bundle incoming.hg
3875 hg pull incoming.hg
3875 hg pull incoming.hg
3876
3876
3877 - briefly list changes inside a bundle::
3877 - briefly list changes inside a bundle::
3878
3878
3879 hg in changes.hg -T "{desc|firstline}\\n"
3879 hg in changes.hg -T "{desc|firstline}\\n"
3880
3880
3881 Returns 0 if there are incoming changes, 1 otherwise.
3881 Returns 0 if there are incoming changes, 1 otherwise.
3882 """
3882 """
3883 if opts.get('graph'):
3883 if opts.get('graph'):
3884 cmdutil.checkunsupportedgraphflags([], opts)
3884 cmdutil.checkunsupportedgraphflags([], opts)
3885 def display(other, chlist, displayer):
3885 def display(other, chlist, displayer):
3886 revdag = cmdutil.graphrevs(other, chlist, opts)
3886 revdag = cmdutil.graphrevs(other, chlist, opts)
3887 showparents = [ctx.node() for ctx in repo[None].parents()]
3887 showparents = [ctx.node() for ctx in repo[None].parents()]
3888 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3888 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3889 graphmod.asciiedges)
3889 graphmod.asciiedges)
3890
3890
3891 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3891 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3892 return 0
3892 return 0
3893
3893
3894 if opts.get('bundle') and opts.get('subrepos'):
3894 if opts.get('bundle') and opts.get('subrepos'):
3895 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3895 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3896
3896
3897 if opts.get('bookmarks'):
3897 if opts.get('bookmarks'):
3898 source, branches = hg.parseurl(ui.expandpath(source),
3898 source, branches = hg.parseurl(ui.expandpath(source),
3899 opts.get('branch'))
3899 opts.get('branch'))
3900 other = hg.peer(repo, opts, source)
3900 other = hg.peer(repo, opts, source)
3901 if 'bookmarks' not in other.listkeys('namespaces'):
3901 if 'bookmarks' not in other.listkeys('namespaces'):
3902 ui.warn(_("remote doesn't support bookmarks\n"))
3902 ui.warn(_("remote doesn't support bookmarks\n"))
3903 return 0
3903 return 0
3904 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3904 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3905 return bookmarks.diff(ui, repo, other)
3905 return bookmarks.diff(ui, repo, other)
3906
3906
3907 repo._subtoppath = ui.expandpath(source)
3907 repo._subtoppath = ui.expandpath(source)
3908 try:
3908 try:
3909 return hg.incoming(ui, repo, source, opts)
3909 return hg.incoming(ui, repo, source, opts)
3910 finally:
3910 finally:
3911 del repo._subtoppath
3911 del repo._subtoppath
3912
3912
3913
3913
3914 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3914 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3915 def init(ui, dest=".", **opts):
3915 def init(ui, dest=".", **opts):
3916 """create a new repository in the given directory
3916 """create a new repository in the given directory
3917
3917
3918 Initialize a new repository in the given directory. If the given
3918 Initialize a new repository in the given directory. If the given
3919 directory does not exist, it will be created.
3919 directory does not exist, it will be created.
3920
3920
3921 If no directory is given, the current directory is used.
3921 If no directory is given, the current directory is used.
3922
3922
3923 It is possible to specify an ``ssh://`` URL as the destination.
3923 It is possible to specify an ``ssh://`` URL as the destination.
3924 See :hg:`help urls` for more information.
3924 See :hg:`help urls` for more information.
3925
3925
3926 Returns 0 on success.
3926 Returns 0 on success.
3927 """
3927 """
3928 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3928 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3929
3929
3930 @command('locate',
3930 @command('locate',
3931 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3931 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3932 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3932 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3933 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3933 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3934 ] + walkopts,
3934 ] + walkopts,
3935 _('[OPTION]... [PATTERN]...'))
3935 _('[OPTION]... [PATTERN]...'))
3936 def locate(ui, repo, *pats, **opts):
3936 def locate(ui, repo, *pats, **opts):
3937 """locate files matching specific patterns
3937 """locate files matching specific patterns
3938
3938
3939 Print files under Mercurial control in the working directory whose
3939 Print files under Mercurial control in the working directory whose
3940 names match the given patterns.
3940 names match the given patterns.
3941
3941
3942 By default, this command searches all directories in the working
3942 By default, this command searches all directories in the working
3943 directory. To search just the current directory and its
3943 directory. To search just the current directory and its
3944 subdirectories, use "--include .".
3944 subdirectories, use "--include .".
3945
3945
3946 If no patterns are given to match, this command prints the names
3946 If no patterns are given to match, this command prints the names
3947 of all files under Mercurial control in the working directory.
3947 of all files under Mercurial control in the working directory.
3948
3948
3949 If you want to feed the output of this command into the "xargs"
3949 If you want to feed the output of this command into the "xargs"
3950 command, use the -0 option to both this command and "xargs". This
3950 command, use the -0 option to both this command and "xargs". This
3951 will avoid the problem of "xargs" treating single filenames that
3951 will avoid the problem of "xargs" treating single filenames that
3952 contain whitespace as multiple filenames.
3952 contain whitespace as multiple filenames.
3953
3953
3954 Returns 0 if a match is found, 1 otherwise.
3954 Returns 0 if a match is found, 1 otherwise.
3955 """
3955 """
3956 end = opts.get('print0') and '\0' or '\n'
3956 end = opts.get('print0') and '\0' or '\n'
3957 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3957 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3958
3958
3959 ret = 1
3959 ret = 1
3960 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3960 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3961 m.bad = lambda x, y: False
3961 m.bad = lambda x, y: False
3962 for abs in repo[rev].walk(m):
3962 for abs in repo[rev].walk(m):
3963 if not rev and abs not in repo.dirstate:
3963 if not rev and abs not in repo.dirstate:
3964 continue
3964 continue
3965 if opts.get('fullpath'):
3965 if opts.get('fullpath'):
3966 ui.write(repo.wjoin(abs), end)
3966 ui.write(repo.wjoin(abs), end)
3967 else:
3967 else:
3968 ui.write(((pats and m.rel(abs)) or abs), end)
3968 ui.write(((pats and m.rel(abs)) or abs), end)
3969 ret = 0
3969 ret = 0
3970
3970
3971 return ret
3971 return ret
3972
3972
3973 @command('^log|history',
3973 @command('^log|history',
3974 [('f', 'follow', None,
3974 [('f', 'follow', None,
3975 _('follow changeset history, or file history across copies and renames')),
3975 _('follow changeset history, or file history across copies and renames')),
3976 ('', 'follow-first', None,
3976 ('', 'follow-first', None,
3977 _('only follow the first parent of merge changesets (DEPRECATED)')),
3977 _('only follow the first parent of merge changesets (DEPRECATED)')),
3978 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3978 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3979 ('C', 'copies', None, _('show copied files')),
3979 ('C', 'copies', None, _('show copied files')),
3980 ('k', 'keyword', [],
3980 ('k', 'keyword', [],
3981 _('do case-insensitive search for a given text'), _('TEXT')),
3981 _('do case-insensitive search for a given text'), _('TEXT')),
3982 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3982 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3983 ('', 'removed', None, _('include revisions where files were removed')),
3983 ('', 'removed', None, _('include revisions where files were removed')),
3984 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3984 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3985 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3985 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3986 ('', 'only-branch', [],
3986 ('', 'only-branch', [],
3987 _('show only changesets within the given named branch (DEPRECATED)'),
3987 _('show only changesets within the given named branch (DEPRECATED)'),
3988 _('BRANCH')),
3988 _('BRANCH')),
3989 ('b', 'branch', [],
3989 ('b', 'branch', [],
3990 _('show changesets within the given named branch'), _('BRANCH')),
3990 _('show changesets within the given named branch'), _('BRANCH')),
3991 ('P', 'prune', [],
3991 ('P', 'prune', [],
3992 _('do not display revision or any of its ancestors'), _('REV')),
3992 _('do not display revision or any of its ancestors'), _('REV')),
3993 ] + logopts + walkopts,
3993 ] + logopts + walkopts,
3994 _('[OPTION]... [FILE]'))
3994 _('[OPTION]... [FILE]'))
3995 def log(ui, repo, *pats, **opts):
3995 def log(ui, repo, *pats, **opts):
3996 """show revision history of entire repository or files
3996 """show revision history of entire repository or files
3997
3997
3998 Print the revision history of the specified files or the entire
3998 Print the revision history of the specified files or the entire
3999 project.
3999 project.
4000
4000
4001 If no revision range is specified, the default is ``tip:0`` unless
4001 If no revision range is specified, the default is ``tip:0`` unless
4002 --follow is set, in which case the working directory parent is
4002 --follow is set, in which case the working directory parent is
4003 used as the starting revision.
4003 used as the starting revision.
4004
4004
4005 File history is shown without following rename or copy history of
4005 File history is shown without following rename or copy history of
4006 files. Use -f/--follow with a filename to follow history across
4006 files. Use -f/--follow with a filename to follow history across
4007 renames and copies. --follow without a filename will only show
4007 renames and copies. --follow without a filename will only show
4008 ancestors or descendants of the starting revision.
4008 ancestors or descendants of the starting revision.
4009
4009
4010 By default this command prints revision number and changeset id,
4010 By default this command prints revision number and changeset id,
4011 tags, non-trivial parents, user, date and time, and a summary for
4011 tags, non-trivial parents, user, date and time, and a summary for
4012 each commit. When the -v/--verbose switch is used, the list of
4012 each commit. When the -v/--verbose switch is used, the list of
4013 changed files and full commit message are shown.
4013 changed files and full commit message are shown.
4014
4014
4015 With --graph the revisions are shown as an ASCII art DAG with the most
4015 With --graph the revisions are shown as an ASCII art DAG with the most
4016 recent changeset at the top.
4016 recent changeset at the top.
4017 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4017 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4018 and '+' represents a fork where the changeset from the lines below is a
4018 and '+' represents a fork where the changeset from the lines below is a
4019 parent of the 'o' merge on the same line.
4019 parent of the 'o' merge on the same line.
4020
4020
4021 .. note::
4021 .. note::
4022
4022
4023 log -p/--patch may generate unexpected diff output for merge
4023 log -p/--patch may generate unexpected diff output for merge
4024 changesets, as it will only compare the merge changeset against
4024 changesets, as it will only compare the merge changeset against
4025 its first parent. Also, only files different from BOTH parents
4025 its first parent. Also, only files different from BOTH parents
4026 will appear in files:.
4026 will appear in files:.
4027
4027
4028 .. note::
4028 .. note::
4029
4029
4030 for performance reasons, log FILE may omit duplicate changes
4030 for performance reasons, log FILE may omit duplicate changes
4031 made on branches and will not show deletions. To see all
4031 made on branches and will not show deletions. To see all
4032 changes including duplicates and deletions, use the --removed
4032 changes including duplicates and deletions, use the --removed
4033 switch.
4033 switch.
4034
4034
4035 .. container:: verbose
4035 .. container:: verbose
4036
4036
4037 Some examples:
4037 Some examples:
4038
4038
4039 - changesets with full descriptions and file lists::
4039 - changesets with full descriptions and file lists::
4040
4040
4041 hg log -v
4041 hg log -v
4042
4042
4043 - changesets ancestral to the working directory::
4043 - changesets ancestral to the working directory::
4044
4044
4045 hg log -f
4045 hg log -f
4046
4046
4047 - last 10 commits on the current branch::
4047 - last 10 commits on the current branch::
4048
4048
4049 hg log -l 10 -b .
4049 hg log -l 10 -b .
4050
4050
4051 - changesets showing all modifications of a file, including removals::
4051 - changesets showing all modifications of a file, including removals::
4052
4052
4053 hg log --removed file.c
4053 hg log --removed file.c
4054
4054
4055 - all changesets that touch a directory, with diffs, excluding merges::
4055 - all changesets that touch a directory, with diffs, excluding merges::
4056
4056
4057 hg log -Mp lib/
4057 hg log -Mp lib/
4058
4058
4059 - all revision numbers that match a keyword::
4059 - all revision numbers that match a keyword::
4060
4060
4061 hg log -k bug --template "{rev}\\n"
4061 hg log -k bug --template "{rev}\\n"
4062
4062
4063 - check if a given changeset is included is a tagged release::
4063 - check if a given changeset is included is a tagged release::
4064
4064
4065 hg log -r "a21ccf and ancestor(1.9)"
4065 hg log -r "a21ccf and ancestor(1.9)"
4066
4066
4067 - find all changesets by some user in a date range::
4067 - find all changesets by some user in a date range::
4068
4068
4069 hg log -k alice -d "may 2008 to jul 2008"
4069 hg log -k alice -d "may 2008 to jul 2008"
4070
4070
4071 - summary of all changesets after the last tag::
4071 - summary of all changesets after the last tag::
4072
4072
4073 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4073 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4074
4074
4075 See :hg:`help dates` for a list of formats valid for -d/--date.
4075 See :hg:`help dates` for a list of formats valid for -d/--date.
4076
4076
4077 See :hg:`help revisions` and :hg:`help revsets` for more about
4077 See :hg:`help revisions` and :hg:`help revsets` for more about
4078 specifying revisions.
4078 specifying revisions.
4079
4079
4080 See :hg:`help templates` for more about pre-packaged styles and
4080 See :hg:`help templates` for more about pre-packaged styles and
4081 specifying custom templates.
4081 specifying custom templates.
4082
4082
4083 Returns 0 on success.
4083 Returns 0 on success.
4084 """
4084 """
4085 if opts.get('graph'):
4085 if opts.get('graph'):
4086 return cmdutil.graphlog(ui, repo, *pats, **opts)
4086 return cmdutil.graphlog(ui, repo, *pats, **opts)
4087
4087
4088 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4088 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4089 limit = cmdutil.loglimit(opts)
4089 limit = cmdutil.loglimit(opts)
4090 count = 0
4090 count = 0
4091
4091
4092 getrenamed = None
4092 getrenamed = None
4093 if opts.get('copies'):
4093 if opts.get('copies'):
4094 endrev = None
4094 endrev = None
4095 if opts.get('rev'):
4095 if opts.get('rev'):
4096 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4096 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4097 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4097 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4098
4098
4099 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4099 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4100 for rev in revs:
4100 for rev in revs:
4101 if count == limit:
4101 if count == limit:
4102 break
4102 break
4103 ctx = repo[rev]
4103 ctx = repo[rev]
4104 copies = None
4104 copies = None
4105 if getrenamed is not None and rev:
4105 if getrenamed is not None and rev:
4106 copies = []
4106 copies = []
4107 for fn in ctx.files():
4107 for fn in ctx.files():
4108 rename = getrenamed(fn, rev)
4108 rename = getrenamed(fn, rev)
4109 if rename:
4109 if rename:
4110 copies.append((fn, rename[0]))
4110 copies.append((fn, rename[0]))
4111 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4111 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4112 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4112 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4113 if displayer.flush(rev):
4113 if displayer.flush(rev):
4114 count += 1
4114 count += 1
4115
4115
4116 displayer.close()
4116 displayer.close()
4117
4117
4118 @command('manifest',
4118 @command('manifest',
4119 [('r', 'rev', '', _('revision to display'), _('REV')),
4119 [('r', 'rev', '', _('revision to display'), _('REV')),
4120 ('', 'all', False, _("list files from all revisions"))],
4120 ('', 'all', False, _("list files from all revisions"))],
4121 _('[-r REV]'))
4121 _('[-r REV]'))
4122 def manifest(ui, repo, node=None, rev=None, **opts):
4122 def manifest(ui, repo, node=None, rev=None, **opts):
4123 """output the current or given revision of the project manifest
4123 """output the current or given revision of the project manifest
4124
4124
4125 Print a list of version controlled files for the given revision.
4125 Print a list of version controlled files for the given revision.
4126 If no revision is given, the first parent of the working directory
4126 If no revision is given, the first parent of the working directory
4127 is used, or the null revision if no revision is checked out.
4127 is used, or the null revision if no revision is checked out.
4128
4128
4129 With -v, print file permissions, symlink and executable bits.
4129 With -v, print file permissions, symlink and executable bits.
4130 With --debug, print file revision hashes.
4130 With --debug, print file revision hashes.
4131
4131
4132 If option --all is specified, the list of all files from all revisions
4132 If option --all is specified, the list of all files from all revisions
4133 is printed. This includes deleted and renamed files.
4133 is printed. This includes deleted and renamed files.
4134
4134
4135 Returns 0 on success.
4135 Returns 0 on success.
4136 """
4136 """
4137
4137
4138 fm = ui.formatter('manifest', opts)
4138 fm = ui.formatter('manifest', opts)
4139
4139
4140 if opts.get('all'):
4140 if opts.get('all'):
4141 if rev or node:
4141 if rev or node:
4142 raise util.Abort(_("can't specify a revision with --all"))
4142 raise util.Abort(_("can't specify a revision with --all"))
4143
4143
4144 res = []
4144 res = []
4145 prefix = "data/"
4145 prefix = "data/"
4146 suffix = ".i"
4146 suffix = ".i"
4147 plen = len(prefix)
4147 plen = len(prefix)
4148 slen = len(suffix)
4148 slen = len(suffix)
4149 lock = repo.lock()
4149 lock = repo.lock()
4150 try:
4150 try:
4151 for fn, b, size in repo.store.datafiles():
4151 for fn, b, size in repo.store.datafiles():
4152 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4152 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4153 res.append(fn[plen:-slen])
4153 res.append(fn[plen:-slen])
4154 finally:
4154 finally:
4155 lock.release()
4155 lock.release()
4156 for f in res:
4156 for f in res:
4157 fm.startitem()
4157 fm.startitem()
4158 fm.write("path", '%s\n', f)
4158 fm.write("path", '%s\n', f)
4159 fm.end()
4159 fm.end()
4160 return
4160 return
4161
4161
4162 if rev and node:
4162 if rev and node:
4163 raise util.Abort(_("please specify just one revision"))
4163 raise util.Abort(_("please specify just one revision"))
4164
4164
4165 if not node:
4165 if not node:
4166 node = rev
4166 node = rev
4167
4167
4168 char = {'l': '@', 'x': '*', '': ''}
4168 char = {'l': '@', 'x': '*', '': ''}
4169 mode = {'l': '644', 'x': '755', '': '644'}
4169 mode = {'l': '644', 'x': '755', '': '644'}
4170 ctx = scmutil.revsingle(repo, node)
4170 ctx = scmutil.revsingle(repo, node)
4171 mf = ctx.manifest()
4171 mf = ctx.manifest()
4172 for f in ctx:
4172 for f in ctx:
4173 fm.startitem()
4173 fm.startitem()
4174 fl = ctx[f].flags()
4174 fl = ctx[f].flags()
4175 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4175 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4176 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4176 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4177 fm.write('path', '%s\n', f)
4177 fm.write('path', '%s\n', f)
4178 fm.end()
4178 fm.end()
4179
4179
4180 @command('^merge',
4180 @command('^merge',
4181 [('f', 'force', None,
4181 [('f', 'force', None,
4182 _('force a merge including outstanding changes (DEPRECATED)')),
4182 _('force a merge including outstanding changes (DEPRECATED)')),
4183 ('r', 'rev', '', _('revision to merge'), _('REV')),
4183 ('r', 'rev', '', _('revision to merge'), _('REV')),
4184 ('P', 'preview', None,
4184 ('P', 'preview', None,
4185 _('review revisions to merge (no merge is performed)'))
4185 _('review revisions to merge (no merge is performed)'))
4186 ] + mergetoolopts,
4186 ] + mergetoolopts,
4187 _('[-P] [-f] [[-r] REV]'))
4187 _('[-P] [-f] [[-r] REV]'))
4188 def merge(ui, repo, node=None, **opts):
4188 def merge(ui, repo, node=None, **opts):
4189 """merge working directory with another revision
4189 """merge working directory with another revision
4190
4190
4191 The current working directory is updated with all changes made in
4191 The current working directory is updated with all changes made in
4192 the requested revision since the last common predecessor revision.
4192 the requested revision since the last common predecessor revision.
4193
4193
4194 Files that changed between either parent are marked as changed for
4194 Files that changed between either parent are marked as changed for
4195 the next commit and a commit must be performed before any further
4195 the next commit and a commit must be performed before any further
4196 updates to the repository are allowed. The next commit will have
4196 updates to the repository are allowed. The next commit will have
4197 two parents.
4197 two parents.
4198
4198
4199 ``--tool`` can be used to specify the merge tool used for file
4199 ``--tool`` can be used to specify the merge tool used for file
4200 merges. It overrides the HGMERGE environment variable and your
4200 merges. It overrides the HGMERGE environment variable and your
4201 configuration files. See :hg:`help merge-tools` for options.
4201 configuration files. See :hg:`help merge-tools` for options.
4202
4202
4203 If no revision is specified, the working directory's parent is a
4203 If no revision is specified, the working directory's parent is a
4204 head revision, and the current branch contains exactly one other
4204 head revision, and the current branch contains exactly one other
4205 head, the other head is merged with by default. Otherwise, an
4205 head, the other head is merged with by default. Otherwise, an
4206 explicit revision with which to merge with must be provided.
4206 explicit revision with which to merge with must be provided.
4207
4207
4208 :hg:`resolve` must be used to resolve unresolved files.
4208 :hg:`resolve` must be used to resolve unresolved files.
4209
4209
4210 To undo an uncommitted merge, use :hg:`update --clean .` which
4210 To undo an uncommitted merge, use :hg:`update --clean .` which
4211 will check out a clean copy of the original merge parent, losing
4211 will check out a clean copy of the original merge parent, losing
4212 all changes.
4212 all changes.
4213
4213
4214 Returns 0 on success, 1 if there are unresolved files.
4214 Returns 0 on success, 1 if there are unresolved files.
4215 """
4215 """
4216
4216
4217 if opts.get('rev') and node:
4217 if opts.get('rev') and node:
4218 raise util.Abort(_("please specify just one revision"))
4218 raise util.Abort(_("please specify just one revision"))
4219 if not node:
4219 if not node:
4220 node = opts.get('rev')
4220 node = opts.get('rev')
4221
4221
4222 if node:
4222 if node:
4223 node = scmutil.revsingle(repo, node).node()
4223 node = scmutil.revsingle(repo, node).node()
4224
4224
4225 if not node and repo._bookmarkcurrent:
4225 if not node and repo._bookmarkcurrent:
4226 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4226 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4227 curhead = repo[repo._bookmarkcurrent].node()
4227 curhead = repo[repo._bookmarkcurrent].node()
4228 if len(bmheads) == 2:
4228 if len(bmheads) == 2:
4229 if curhead == bmheads[0]:
4229 if curhead == bmheads[0]:
4230 node = bmheads[1]
4230 node = bmheads[1]
4231 else:
4231 else:
4232 node = bmheads[0]
4232 node = bmheads[0]
4233 elif len(bmheads) > 2:
4233 elif len(bmheads) > 2:
4234 raise util.Abort(_("multiple matching bookmarks to merge - "
4234 raise util.Abort(_("multiple matching bookmarks to merge - "
4235 "please merge with an explicit rev or bookmark"),
4235 "please merge with an explicit rev or bookmark"),
4236 hint=_("run 'hg heads' to see all heads"))
4236 hint=_("run 'hg heads' to see all heads"))
4237 elif len(bmheads) <= 1:
4237 elif len(bmheads) <= 1:
4238 raise util.Abort(_("no matching bookmark to merge - "
4238 raise util.Abort(_("no matching bookmark to merge - "
4239 "please merge with an explicit rev or bookmark"),
4239 "please merge with an explicit rev or bookmark"),
4240 hint=_("run 'hg heads' to see all heads"))
4240 hint=_("run 'hg heads' to see all heads"))
4241
4241
4242 if not node and not repo._bookmarkcurrent:
4242 if not node and not repo._bookmarkcurrent:
4243 branch = repo[None].branch()
4243 branch = repo[None].branch()
4244 bheads = repo.branchheads(branch)
4244 bheads = repo.branchheads(branch)
4245 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4245 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4246
4246
4247 if len(nbhs) > 2:
4247 if len(nbhs) > 2:
4248 raise util.Abort(_("branch '%s' has %d heads - "
4248 raise util.Abort(_("branch '%s' has %d heads - "
4249 "please merge with an explicit rev")
4249 "please merge with an explicit rev")
4250 % (branch, len(bheads)),
4250 % (branch, len(bheads)),
4251 hint=_("run 'hg heads .' to see heads"))
4251 hint=_("run 'hg heads .' to see heads"))
4252
4252
4253 parent = repo.dirstate.p1()
4253 parent = repo.dirstate.p1()
4254 if len(nbhs) <= 1:
4254 if len(nbhs) <= 1:
4255 if len(bheads) > 1:
4255 if len(bheads) > 1:
4256 raise util.Abort(_("heads are bookmarked - "
4256 raise util.Abort(_("heads are bookmarked - "
4257 "please merge with an explicit rev"),
4257 "please merge with an explicit rev"),
4258 hint=_("run 'hg heads' to see all heads"))
4258 hint=_("run 'hg heads' to see all heads"))
4259 if len(repo.heads()) > 1:
4259 if len(repo.heads()) > 1:
4260 raise util.Abort(_("branch '%s' has one head - "
4260 raise util.Abort(_("branch '%s' has one head - "
4261 "please merge with an explicit rev")
4261 "please merge with an explicit rev")
4262 % branch,
4262 % branch,
4263 hint=_("run 'hg heads' to see all heads"))
4263 hint=_("run 'hg heads' to see all heads"))
4264 msg, hint = _('nothing to merge'), None
4264 msg, hint = _('nothing to merge'), None
4265 if parent != repo.lookup(branch):
4265 if parent != repo.lookup(branch):
4266 hint = _("use 'hg update' instead")
4266 hint = _("use 'hg update' instead")
4267 raise util.Abort(msg, hint=hint)
4267 raise util.Abort(msg, hint=hint)
4268
4268
4269 if parent not in bheads:
4269 if parent not in bheads:
4270 raise util.Abort(_('working directory not at a head revision'),
4270 raise util.Abort(_('working directory not at a head revision'),
4271 hint=_("use 'hg update' or merge with an "
4271 hint=_("use 'hg update' or merge with an "
4272 "explicit revision"))
4272 "explicit revision"))
4273 if parent == nbhs[0]:
4273 if parent == nbhs[0]:
4274 node = nbhs[-1]
4274 node = nbhs[-1]
4275 else:
4275 else:
4276 node = nbhs[0]
4276 node = nbhs[0]
4277
4277
4278 if opts.get('preview'):
4278 if opts.get('preview'):
4279 # find nodes that are ancestors of p2 but not of p1
4279 # find nodes that are ancestors of p2 but not of p1
4280 p1 = repo.lookup('.')
4280 p1 = repo.lookup('.')
4281 p2 = repo.lookup(node)
4281 p2 = repo.lookup(node)
4282 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4282 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4283
4283
4284 displayer = cmdutil.show_changeset(ui, repo, opts)
4284 displayer = cmdutil.show_changeset(ui, repo, opts)
4285 for node in nodes:
4285 for node in nodes:
4286 displayer.show(repo[node])
4286 displayer.show(repo[node])
4287 displayer.close()
4287 displayer.close()
4288 return 0
4288 return 0
4289
4289
4290 try:
4290 try:
4291 # ui.forcemerge is an internal variable, do not document
4291 # ui.forcemerge is an internal variable, do not document
4292 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4292 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4293 return hg.merge(repo, node, force=opts.get('force'))
4293 return hg.merge(repo, node, force=opts.get('force'))
4294 finally:
4294 finally:
4295 ui.setconfig('ui', 'forcemerge', '', 'merge')
4295 ui.setconfig('ui', 'forcemerge', '', 'merge')
4296
4296
4297 @command('outgoing|out',
4297 @command('outgoing|out',
4298 [('f', 'force', None, _('run even when the destination is unrelated')),
4298 [('f', 'force', None, _('run even when the destination is unrelated')),
4299 ('r', 'rev', [],
4299 ('r', 'rev', [],
4300 _('a changeset intended to be included in the destination'), _('REV')),
4300 _('a changeset intended to be included in the destination'), _('REV')),
4301 ('n', 'newest-first', None, _('show newest record first')),
4301 ('n', 'newest-first', None, _('show newest record first')),
4302 ('B', 'bookmarks', False, _('compare bookmarks')),
4302 ('B', 'bookmarks', False, _('compare bookmarks')),
4303 ('b', 'branch', [], _('a specific branch you would like to push'),
4303 ('b', 'branch', [], _('a specific branch you would like to push'),
4304 _('BRANCH')),
4304 _('BRANCH')),
4305 ] + logopts + remoteopts + subrepoopts,
4305 ] + logopts + remoteopts + subrepoopts,
4306 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4306 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4307 def outgoing(ui, repo, dest=None, **opts):
4307 def outgoing(ui, repo, dest=None, **opts):
4308 """show changesets not found in the destination
4308 """show changesets not found in the destination
4309
4309
4310 Show changesets not found in the specified destination repository
4310 Show changesets not found in the specified destination repository
4311 or the default push location. These are the changesets that would
4311 or the default push location. These are the changesets that would
4312 be pushed if a push was requested.
4312 be pushed if a push was requested.
4313
4313
4314 See pull for details of valid destination formats.
4314 See pull for details of valid destination formats.
4315
4315
4316 Returns 0 if there are outgoing changes, 1 otherwise.
4316 Returns 0 if there are outgoing changes, 1 otherwise.
4317 """
4317 """
4318 if opts.get('graph'):
4318 if opts.get('graph'):
4319 cmdutil.checkunsupportedgraphflags([], opts)
4319 cmdutil.checkunsupportedgraphflags([], opts)
4320 o, other = hg._outgoing(ui, repo, dest, opts)
4320 o, other = hg._outgoing(ui, repo, dest, opts)
4321 if not o:
4321 if not o:
4322 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4322 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4323 return
4323 return
4324
4324
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4325 revdag = cmdutil.graphrevs(repo, o, opts)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4326 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4329 graphmod.asciiedges)
4329 graphmod.asciiedges)
4330 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4330 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4331 return 0
4331 return 0
4332
4332
4333 if opts.get('bookmarks'):
4333 if opts.get('bookmarks'):
4334 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4334 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4335 dest, branches = hg.parseurl(dest, opts.get('branch'))
4335 dest, branches = hg.parseurl(dest, opts.get('branch'))
4336 other = hg.peer(repo, opts, dest)
4336 other = hg.peer(repo, opts, dest)
4337 if 'bookmarks' not in other.listkeys('namespaces'):
4337 if 'bookmarks' not in other.listkeys('namespaces'):
4338 ui.warn(_("remote doesn't support bookmarks\n"))
4338 ui.warn(_("remote doesn't support bookmarks\n"))
4339 return 0
4339 return 0
4340 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4340 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4341 return bookmarks.diff(ui, other, repo)
4341 return bookmarks.diff(ui, other, repo)
4342
4342
4343 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4343 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4344 try:
4344 try:
4345 return hg.outgoing(ui, repo, dest, opts)
4345 return hg.outgoing(ui, repo, dest, opts)
4346 finally:
4346 finally:
4347 del repo._subtoppath
4347 del repo._subtoppath
4348
4348
4349 @command('parents',
4349 @command('parents',
4350 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4350 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4351 ] + templateopts,
4351 ] + templateopts,
4352 _('[-r REV] [FILE]'))
4352 _('[-r REV] [FILE]'))
4353 def parents(ui, repo, file_=None, **opts):
4353 def parents(ui, repo, file_=None, **opts):
4354 """show the parents of the working directory or revision
4354 """show the parents of the working directory or revision
4355
4355
4356 Print the working directory's parent revisions. If a revision is
4356 Print the working directory's parent revisions. If a revision is
4357 given via -r/--rev, the parent of that revision will be printed.
4357 given via -r/--rev, the parent of that revision will be printed.
4358 If a file argument is given, the revision in which the file was
4358 If a file argument is given, the revision in which the file was
4359 last changed (before the working directory revision or the
4359 last changed (before the working directory revision or the
4360 argument to --rev if given) is printed.
4360 argument to --rev if given) is printed.
4361
4361
4362 Returns 0 on success.
4362 Returns 0 on success.
4363 """
4363 """
4364
4364
4365 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4365 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4366
4366
4367 if file_:
4367 if file_:
4368 m = scmutil.match(ctx, (file_,), opts)
4368 m = scmutil.match(ctx, (file_,), opts)
4369 if m.anypats() or len(m.files()) != 1:
4369 if m.anypats() or len(m.files()) != 1:
4370 raise util.Abort(_('can only specify an explicit filename'))
4370 raise util.Abort(_('can only specify an explicit filename'))
4371 file_ = m.files()[0]
4371 file_ = m.files()[0]
4372 filenodes = []
4372 filenodes = []
4373 for cp in ctx.parents():
4373 for cp in ctx.parents():
4374 if not cp:
4374 if not cp:
4375 continue
4375 continue
4376 try:
4376 try:
4377 filenodes.append(cp.filenode(file_))
4377 filenodes.append(cp.filenode(file_))
4378 except error.LookupError:
4378 except error.LookupError:
4379 pass
4379 pass
4380 if not filenodes:
4380 if not filenodes:
4381 raise util.Abort(_("'%s' not found in manifest!") % file_)
4381 raise util.Abort(_("'%s' not found in manifest!") % file_)
4382 p = []
4382 p = []
4383 for fn in filenodes:
4383 for fn in filenodes:
4384 fctx = repo.filectx(file_, fileid=fn)
4384 fctx = repo.filectx(file_, fileid=fn)
4385 p.append(fctx.node())
4385 p.append(fctx.node())
4386 else:
4386 else:
4387 p = [cp.node() for cp in ctx.parents()]
4387 p = [cp.node() for cp in ctx.parents()]
4388
4388
4389 displayer = cmdutil.show_changeset(ui, repo, opts)
4389 displayer = cmdutil.show_changeset(ui, repo, opts)
4390 for n in p:
4390 for n in p:
4391 if n != nullid:
4391 if n != nullid:
4392 displayer.show(repo[n])
4392 displayer.show(repo[n])
4393 displayer.close()
4393 displayer.close()
4394
4394
4395 @command('paths', [], _('[NAME]'))
4395 @command('paths', [], _('[NAME]'))
4396 def paths(ui, repo, search=None):
4396 def paths(ui, repo, search=None):
4397 """show aliases for remote repositories
4397 """show aliases for remote repositories
4398
4398
4399 Show definition of symbolic path name NAME. If no name is given,
4399 Show definition of symbolic path name NAME. If no name is given,
4400 show definition of all available names.
4400 show definition of all available names.
4401
4401
4402 Option -q/--quiet suppresses all output when searching for NAME
4402 Option -q/--quiet suppresses all output when searching for NAME
4403 and shows only the path names when listing all definitions.
4403 and shows only the path names when listing all definitions.
4404
4404
4405 Path names are defined in the [paths] section of your
4405 Path names are defined in the [paths] section of your
4406 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4406 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4407 repository, ``.hg/hgrc`` is used, too.
4407 repository, ``.hg/hgrc`` is used, too.
4408
4408
4409 The path names ``default`` and ``default-push`` have a special
4409 The path names ``default`` and ``default-push`` have a special
4410 meaning. When performing a push or pull operation, they are used
4410 meaning. When performing a push or pull operation, they are used
4411 as fallbacks if no location is specified on the command-line.
4411 as fallbacks if no location is specified on the command-line.
4412 When ``default-push`` is set, it will be used for push and
4412 When ``default-push`` is set, it will be used for push and
4413 ``default`` will be used for pull; otherwise ``default`` is used
4413 ``default`` will be used for pull; otherwise ``default`` is used
4414 as the fallback for both. When cloning a repository, the clone
4414 as the fallback for both. When cloning a repository, the clone
4415 source is written as ``default`` in ``.hg/hgrc``. Note that
4415 source is written as ``default`` in ``.hg/hgrc``. Note that
4416 ``default`` and ``default-push`` apply to all inbound (e.g.
4416 ``default`` and ``default-push`` apply to all inbound (e.g.
4417 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4417 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4418 :hg:`bundle`) operations.
4418 :hg:`bundle`) operations.
4419
4419
4420 See :hg:`help urls` for more information.
4420 See :hg:`help urls` for more information.
4421
4421
4422 Returns 0 on success.
4422 Returns 0 on success.
4423 """
4423 """
4424 if search:
4424 if search:
4425 for name, path in ui.configitems("paths"):
4425 for name, path in ui.configitems("paths"):
4426 if name == search:
4426 if name == search:
4427 ui.status("%s\n" % util.hidepassword(path))
4427 ui.status("%s\n" % util.hidepassword(path))
4428 return
4428 return
4429 if not ui.quiet:
4429 if not ui.quiet:
4430 ui.warn(_("not found!\n"))
4430 ui.warn(_("not found!\n"))
4431 return 1
4431 return 1
4432 else:
4432 else:
4433 for name, path in ui.configitems("paths"):
4433 for name, path in ui.configitems("paths"):
4434 if ui.quiet:
4434 if ui.quiet:
4435 ui.write("%s\n" % name)
4435 ui.write("%s\n" % name)
4436 else:
4436 else:
4437 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4437 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4438
4438
4439 @command('phase',
4439 @command('phase',
4440 [('p', 'public', False, _('set changeset phase to public')),
4440 [('p', 'public', False, _('set changeset phase to public')),
4441 ('d', 'draft', False, _('set changeset phase to draft')),
4441 ('d', 'draft', False, _('set changeset phase to draft')),
4442 ('s', 'secret', False, _('set changeset phase to secret')),
4442 ('s', 'secret', False, _('set changeset phase to secret')),
4443 ('f', 'force', False, _('allow to move boundary backward')),
4443 ('f', 'force', False, _('allow to move boundary backward')),
4444 ('r', 'rev', [], _('target revision'), _('REV')),
4444 ('r', 'rev', [], _('target revision'), _('REV')),
4445 ],
4445 ],
4446 _('[-p|-d|-s] [-f] [-r] REV...'))
4446 _('[-p|-d|-s] [-f] [-r] REV...'))
4447 def phase(ui, repo, *revs, **opts):
4447 def phase(ui, repo, *revs, **opts):
4448 """set or show the current phase name
4448 """set or show the current phase name
4449
4449
4450 With no argument, show the phase name of specified revisions.
4450 With no argument, show the phase name of specified revisions.
4451
4451
4452 With one of -p/--public, -d/--draft or -s/--secret, change the
4452 With one of -p/--public, -d/--draft or -s/--secret, change the
4453 phase value of the specified revisions.
4453 phase value of the specified revisions.
4454
4454
4455 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4455 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4456 lower phase to an higher phase. Phases are ordered as follows::
4456 lower phase to an higher phase. Phases are ordered as follows::
4457
4457
4458 public < draft < secret
4458 public < draft < secret
4459
4459
4460 Returns 0 on success, 1 if no phases were changed or some could not
4460 Returns 0 on success, 1 if no phases were changed or some could not
4461 be changed.
4461 be changed.
4462 """
4462 """
4463 # search for a unique phase argument
4463 # search for a unique phase argument
4464 targetphase = None
4464 targetphase = None
4465 for idx, name in enumerate(phases.phasenames):
4465 for idx, name in enumerate(phases.phasenames):
4466 if opts[name]:
4466 if opts[name]:
4467 if targetphase is not None:
4467 if targetphase is not None:
4468 raise util.Abort(_('only one phase can be specified'))
4468 raise util.Abort(_('only one phase can be specified'))
4469 targetphase = idx
4469 targetphase = idx
4470
4470
4471 # look for specified revision
4471 # look for specified revision
4472 revs = list(revs)
4472 revs = list(revs)
4473 revs.extend(opts['rev'])
4473 revs.extend(opts['rev'])
4474 if not revs:
4474 if not revs:
4475 raise util.Abort(_('no revisions specified'))
4475 raise util.Abort(_('no revisions specified'))
4476
4476
4477 revs = scmutil.revrange(repo, revs)
4477 revs = scmutil.revrange(repo, revs)
4478
4478
4479 lock = None
4479 lock = None
4480 ret = 0
4480 ret = 0
4481 if targetphase is None:
4481 if targetphase is None:
4482 # display
4482 # display
4483 for r in revs:
4483 for r in revs:
4484 ctx = repo[r]
4484 ctx = repo[r]
4485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4486 else:
4486 else:
4487 lock = repo.lock()
4487 lock = repo.lock()
4488 try:
4488 try:
4489 # set phase
4489 # set phase
4490 if not revs:
4490 if not revs:
4491 raise util.Abort(_('empty revision set'))
4491 raise util.Abort(_('empty revision set'))
4492 nodes = [repo[r].node() for r in revs]
4492 nodes = [repo[r].node() for r in revs]
4493 olddata = repo._phasecache.getphaserevs(repo)[:]
4493 olddata = repo._phasecache.getphaserevs(repo)[:]
4494 phases.advanceboundary(repo, targetphase, nodes)
4494 phases.advanceboundary(repo, targetphase, nodes)
4495 if opts['force']:
4495 if opts['force']:
4496 phases.retractboundary(repo, targetphase, nodes)
4496 phases.retractboundary(repo, targetphase, nodes)
4497 finally:
4497 finally:
4498 lock.release()
4498 lock.release()
4499 # moving revision from public to draft may hide them
4499 # moving revision from public to draft may hide them
4500 # We have to check result on an unfiltered repository
4500 # We have to check result on an unfiltered repository
4501 unfi = repo.unfiltered()
4501 unfi = repo.unfiltered()
4502 newdata = repo._phasecache.getphaserevs(unfi)
4502 newdata = repo._phasecache.getphaserevs(unfi)
4503 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4503 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4504 cl = unfi.changelog
4504 cl = unfi.changelog
4505 rejected = [n for n in nodes
4505 rejected = [n for n in nodes
4506 if newdata[cl.rev(n)] < targetphase]
4506 if newdata[cl.rev(n)] < targetphase]
4507 if rejected:
4507 if rejected:
4508 ui.warn(_('cannot move %i changesets to a higher '
4508 ui.warn(_('cannot move %i changesets to a higher '
4509 'phase, use --force\n') % len(rejected))
4509 'phase, use --force\n') % len(rejected))
4510 ret = 1
4510 ret = 1
4511 if changes:
4511 if changes:
4512 msg = _('phase changed for %i changesets\n') % changes
4512 msg = _('phase changed for %i changesets\n') % changes
4513 if ret:
4513 if ret:
4514 ui.status(msg)
4514 ui.status(msg)
4515 else:
4515 else:
4516 ui.note(msg)
4516 ui.note(msg)
4517 else:
4517 else:
4518 ui.warn(_('no phases changed\n'))
4518 ui.warn(_('no phases changed\n'))
4519 ret = 1
4519 ret = 1
4520 return ret
4520 return ret
4521
4521
4522 def postincoming(ui, repo, modheads, optupdate, checkout):
4522 def postincoming(ui, repo, modheads, optupdate, checkout):
4523 if modheads == 0:
4523 if modheads == 0:
4524 return
4524 return
4525 if optupdate:
4525 if optupdate:
4526 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4526 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4527 try:
4527 try:
4528 ret = hg.update(repo, checkout)
4528 ret = hg.update(repo, checkout)
4529 except util.Abort, inst:
4529 except util.Abort, inst:
4530 ui.warn(_("not updating: %s\n") % str(inst))
4530 ui.warn(_("not updating: %s\n") % str(inst))
4531 if inst.hint:
4531 if inst.hint:
4532 ui.warn(_("(%s)\n") % inst.hint)
4532 ui.warn(_("(%s)\n") % inst.hint)
4533 return 0
4533 return 0
4534 if not ret and not checkout:
4534 if not ret and not checkout:
4535 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4535 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4536 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4536 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4537 return ret
4537 return ret
4538 if modheads > 1:
4538 if modheads > 1:
4539 currentbranchheads = len(repo.branchheads())
4539 currentbranchheads = len(repo.branchheads())
4540 if currentbranchheads == modheads:
4540 if currentbranchheads == modheads:
4541 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4541 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4542 elif currentbranchheads > 1:
4542 elif currentbranchheads > 1:
4543 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4543 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4544 "merge)\n"))
4544 "merge)\n"))
4545 else:
4545 else:
4546 ui.status(_("(run 'hg heads' to see heads)\n"))
4546 ui.status(_("(run 'hg heads' to see heads)\n"))
4547 else:
4547 else:
4548 ui.status(_("(run 'hg update' to get a working copy)\n"))
4548 ui.status(_("(run 'hg update' to get a working copy)\n"))
4549
4549
4550 @command('^pull',
4550 @command('^pull',
4551 [('u', 'update', None,
4551 [('u', 'update', None,
4552 _('update to new branch head if changesets were pulled')),
4552 _('update to new branch head if changesets were pulled')),
4553 ('f', 'force', None, _('run even when remote repository is unrelated')),
4553 ('f', 'force', None, _('run even when remote repository is unrelated')),
4554 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4554 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4555 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4555 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4556 ('b', 'branch', [], _('a specific branch you would like to pull'),
4556 ('b', 'branch', [], _('a specific branch you would like to pull'),
4557 _('BRANCH')),
4557 _('BRANCH')),
4558 ] + remoteopts,
4558 ] + remoteopts,
4559 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4559 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4560 def pull(ui, repo, source="default", **opts):
4560 def pull(ui, repo, source="default", **opts):
4561 """pull changes from the specified source
4561 """pull changes from the specified source
4562
4562
4563 Pull changes from a remote repository to a local one.
4563 Pull changes from a remote repository to a local one.
4564
4564
4565 This finds all changes from the repository at the specified path
4565 This finds all changes from the repository at the specified path
4566 or URL and adds them to a local repository (the current one unless
4566 or URL and adds them to a local repository (the current one unless
4567 -R is specified). By default, this does not update the copy of the
4567 -R is specified). By default, this does not update the copy of the
4568 project in the working directory.
4568 project in the working directory.
4569
4569
4570 Use :hg:`incoming` if you want to see what would have been added
4570 Use :hg:`incoming` if you want to see what would have been added
4571 by a pull at the time you issued this command. If you then decide
4571 by a pull at the time you issued this command. If you then decide
4572 to add those changes to the repository, you should use :hg:`pull
4572 to add those changes to the repository, you should use :hg:`pull
4573 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4573 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4574
4574
4575 If SOURCE is omitted, the 'default' path will be used.
4575 If SOURCE is omitted, the 'default' path will be used.
4576 See :hg:`help urls` for more information.
4576 See :hg:`help urls` for more information.
4577
4577
4578 Returns 0 on success, 1 if an update had unresolved files.
4578 Returns 0 on success, 1 if an update had unresolved files.
4579 """
4579 """
4580 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4580 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4581 other = hg.peer(repo, opts, source)
4581 other = hg.peer(repo, opts, source)
4582 try:
4582 try:
4583 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4583 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4584 revs, checkout = hg.addbranchrevs(repo, other, branches,
4584 revs, checkout = hg.addbranchrevs(repo, other, branches,
4585 opts.get('rev'))
4585 opts.get('rev'))
4586
4586
4587 remotebookmarks = other.listkeys('bookmarks')
4587 remotebookmarks = other.listkeys('bookmarks')
4588
4588
4589 if opts.get('bookmark'):
4589 if opts.get('bookmark'):
4590 if not revs:
4590 if not revs:
4591 revs = []
4591 revs = []
4592 for b in opts['bookmark']:
4592 for b in opts['bookmark']:
4593 if b not in remotebookmarks:
4593 if b not in remotebookmarks:
4594 raise util.Abort(_('remote bookmark %s not found!') % b)
4594 raise util.Abort(_('remote bookmark %s not found!') % b)
4595 revs.append(remotebookmarks[b])
4595 revs.append(remotebookmarks[b])
4596
4596
4597 if revs:
4597 if revs:
4598 try:
4598 try:
4599 revs = [other.lookup(rev) for rev in revs]
4599 revs = [other.lookup(rev) for rev in revs]
4600 except error.CapabilityError:
4600 except error.CapabilityError:
4601 err = _("other repository doesn't support revision lookup, "
4601 err = _("other repository doesn't support revision lookup, "
4602 "so a rev cannot be specified.")
4602 "so a rev cannot be specified.")
4603 raise util.Abort(err)
4603 raise util.Abort(err)
4604
4604
4605 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4605 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4606 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4606 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4607 if checkout:
4607 if checkout:
4608 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4608 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4609 repo._subtoppath = source
4609 repo._subtoppath = source
4610 try:
4610 try:
4611 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4611 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4612
4612
4613 finally:
4613 finally:
4614 del repo._subtoppath
4614 del repo._subtoppath
4615
4615
4616 # update specified bookmarks
4616 # update specified bookmarks
4617 if opts.get('bookmark'):
4617 if opts.get('bookmark'):
4618 marks = repo._bookmarks
4618 marks = repo._bookmarks
4619 for b in opts['bookmark']:
4619 for b in opts['bookmark']:
4620 # explicit pull overrides local bookmark if any
4620 # explicit pull overrides local bookmark if any
4621 ui.status(_("importing bookmark %s\n") % b)
4621 ui.status(_("importing bookmark %s\n") % b)
4622 marks[b] = repo[remotebookmarks[b]].node()
4622 marks[b] = repo[remotebookmarks[b]].node()
4623 marks.write()
4623 marks.write()
4624 finally:
4624 finally:
4625 other.close()
4625 other.close()
4626 return ret
4626 return ret
4627
4627
4628 @command('^push',
4628 @command('^push',
4629 [('f', 'force', None, _('force push')),
4629 [('f', 'force', None, _('force push')),
4630 ('r', 'rev', [],
4630 ('r', 'rev', [],
4631 _('a changeset intended to be included in the destination'),
4631 _('a changeset intended to be included in the destination'),
4632 _('REV')),
4632 _('REV')),
4633 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4633 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4634 ('b', 'branch', [],
4634 ('b', 'branch', [],
4635 _('a specific branch you would like to push'), _('BRANCH')),
4635 _('a specific branch you would like to push'), _('BRANCH')),
4636 ('', 'new-branch', False, _('allow pushing a new branch')),
4636 ('', 'new-branch', False, _('allow pushing a new branch')),
4637 ] + remoteopts,
4637 ] + remoteopts,
4638 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4638 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4639 def push(ui, repo, dest=None, **opts):
4639 def push(ui, repo, dest=None, **opts):
4640 """push changes to the specified destination
4640 """push changes to the specified destination
4641
4641
4642 Push changesets from the local repository to the specified
4642 Push changesets from the local repository to the specified
4643 destination.
4643 destination.
4644
4644
4645 This operation is symmetrical to pull: it is identical to a pull
4645 This operation is symmetrical to pull: it is identical to a pull
4646 in the destination repository from the current one.
4646 in the destination repository from the current one.
4647
4647
4648 By default, push will not allow creation of new heads at the
4648 By default, push will not allow creation of new heads at the
4649 destination, since multiple heads would make it unclear which head
4649 destination, since multiple heads would make it unclear which head
4650 to use. In this situation, it is recommended to pull and merge
4650 to use. In this situation, it is recommended to pull and merge
4651 before pushing.
4651 before pushing.
4652
4652
4653 Use --new-branch if you want to allow push to create a new named
4653 Use --new-branch if you want to allow push to create a new named
4654 branch that is not present at the destination. This allows you to
4654 branch that is not present at the destination. This allows you to
4655 only create a new branch without forcing other changes.
4655 only create a new branch without forcing other changes.
4656
4656
4657 .. note::
4657 .. note::
4658
4658
4659 Extra care should be taken with the -f/--force option,
4659 Extra care should be taken with the -f/--force option,
4660 which will push all new heads on all branches, an action which will
4660 which will push all new heads on all branches, an action which will
4661 almost always cause confusion for collaborators.
4661 almost always cause confusion for collaborators.
4662
4662
4663 If -r/--rev is used, the specified revision and all its ancestors
4663 If -r/--rev is used, the specified revision and all its ancestors
4664 will be pushed to the remote repository.
4664 will be pushed to the remote repository.
4665
4665
4666 If -B/--bookmark is used, the specified bookmarked revision, its
4666 If -B/--bookmark is used, the specified bookmarked revision, its
4667 ancestors, and the bookmark will be pushed to the remote
4667 ancestors, and the bookmark will be pushed to the remote
4668 repository.
4668 repository.
4669
4669
4670 Please see :hg:`help urls` for important details about ``ssh://``
4670 Please see :hg:`help urls` for important details about ``ssh://``
4671 URLs. If DESTINATION is omitted, a default path will be used.
4671 URLs. If DESTINATION is omitted, a default path will be used.
4672
4672
4673 Returns 0 if push was successful, 1 if nothing to push.
4673 Returns 0 if push was successful, 1 if nothing to push.
4674 """
4674 """
4675
4675
4676 if opts.get('bookmark'):
4676 if opts.get('bookmark'):
4677 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4677 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4678 for b in opts['bookmark']:
4678 for b in opts['bookmark']:
4679 # translate -B options to -r so changesets get pushed
4679 # translate -B options to -r so changesets get pushed
4680 if b in repo._bookmarks:
4680 if b in repo._bookmarks:
4681 opts.setdefault('rev', []).append(b)
4681 opts.setdefault('rev', []).append(b)
4682 else:
4682 else:
4683 # if we try to push a deleted bookmark, translate it to null
4683 # if we try to push a deleted bookmark, translate it to null
4684 # this lets simultaneous -r, -b options continue working
4684 # this lets simultaneous -r, -b options continue working
4685 opts.setdefault('rev', []).append("null")
4685 opts.setdefault('rev', []).append("null")
4686
4686
4687 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4687 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4688 dest, branches = hg.parseurl(dest, opts.get('branch'))
4688 dest, branches = hg.parseurl(dest, opts.get('branch'))
4689 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4689 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4690 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4690 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4691 try:
4691 try:
4692 other = hg.peer(repo, opts, dest)
4692 other = hg.peer(repo, opts, dest)
4693 except error.RepoError:
4693 except error.RepoError:
4694 if dest == "default-push":
4694 if dest == "default-push":
4695 raise util.Abort(_("default repository not configured!"),
4695 raise util.Abort(_("default repository not configured!"),
4696 hint=_('see the "path" section in "hg help config"'))
4696 hint=_('see the "path" section in "hg help config"'))
4697 else:
4697 else:
4698 raise
4698 raise
4699
4699
4700 if revs:
4700 if revs:
4701 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4701 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4702
4702
4703 repo._subtoppath = dest
4703 repo._subtoppath = dest
4704 try:
4704 try:
4705 # push subrepos depth-first for coherent ordering
4705 # push subrepos depth-first for coherent ordering
4706 c = repo['']
4706 c = repo['']
4707 subs = c.substate # only repos that are committed
4707 subs = c.substate # only repos that are committed
4708 for s in sorted(subs):
4708 for s in sorted(subs):
4709 result = c.sub(s).push(opts)
4709 result = c.sub(s).push(opts)
4710 if result == 0:
4710 if result == 0:
4711 return not result
4711 return not result
4712 finally:
4712 finally:
4713 del repo._subtoppath
4713 del repo._subtoppath
4714 result = repo.push(other, opts.get('force'), revs=revs,
4714 result = repo.push(other, opts.get('force'), revs=revs,
4715 newbranch=opts.get('new_branch'))
4715 newbranch=opts.get('new_branch'))
4716
4716
4717 result = not result
4717 result = not result
4718
4718
4719 if opts.get('bookmark'):
4719 if opts.get('bookmark'):
4720 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4720 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4721 if bresult == 2:
4721 if bresult == 2:
4722 return 2
4722 return 2
4723 if not result and bresult:
4723 if not result and bresult:
4724 result = 2
4724 result = 2
4725
4725
4726 return result
4726 return result
4727
4727
4728 @command('recover', [])
4728 @command('recover', [])
4729 def recover(ui, repo):
4729 def recover(ui, repo):
4730 """roll back an interrupted transaction
4730 """roll back an interrupted transaction
4731
4731
4732 Recover from an interrupted commit or pull.
4732 Recover from an interrupted commit or pull.
4733
4733
4734 This command tries to fix the repository status after an
4734 This command tries to fix the repository status after an
4735 interrupted operation. It should only be necessary when Mercurial
4735 interrupted operation. It should only be necessary when Mercurial
4736 suggests it.
4736 suggests it.
4737
4737
4738 Returns 0 if successful, 1 if nothing to recover or verify fails.
4738 Returns 0 if successful, 1 if nothing to recover or verify fails.
4739 """
4739 """
4740 if repo.recover():
4740 if repo.recover():
4741 return hg.verify(repo)
4741 return hg.verify(repo)
4742 return 1
4742 return 1
4743
4743
4744 @command('^remove|rm',
4744 @command('^remove|rm',
4745 [('A', 'after', None, _('record delete for missing files')),
4745 [('A', 'after', None, _('record delete for missing files')),
4746 ('f', 'force', None,
4746 ('f', 'force', None,
4747 _('remove (and delete) file even if added or modified')),
4747 _('remove (and delete) file even if added or modified')),
4748 ] + walkopts,
4748 ] + walkopts,
4749 _('[OPTION]... FILE...'))
4749 _('[OPTION]... FILE...'))
4750 def remove(ui, repo, *pats, **opts):
4750 def remove(ui, repo, *pats, **opts):
4751 """remove the specified files on the next commit
4751 """remove the specified files on the next commit
4752
4752
4753 Schedule the indicated files for removal from the current branch.
4753 Schedule the indicated files for removal from the current branch.
4754
4754
4755 This command schedules the files to be removed at the next commit.
4755 This command schedules the files to be removed at the next commit.
4756 To undo a remove before that, see :hg:`revert`. To undo added
4756 To undo a remove before that, see :hg:`revert`. To undo added
4757 files, see :hg:`forget`.
4757 files, see :hg:`forget`.
4758
4758
4759 .. container:: verbose
4759 .. container:: verbose
4760
4760
4761 -A/--after can be used to remove only files that have already
4761 -A/--after can be used to remove only files that have already
4762 been deleted, -f/--force can be used to force deletion, and -Af
4762 been deleted, -f/--force can be used to force deletion, and -Af
4763 can be used to remove files from the next revision without
4763 can be used to remove files from the next revision without
4764 deleting them from the working directory.
4764 deleting them from the working directory.
4765
4765
4766 The following table details the behavior of remove for different
4766 The following table details the behavior of remove for different
4767 file states (columns) and option combinations (rows). The file
4767 file states (columns) and option combinations (rows). The file
4768 states are Added [A], Clean [C], Modified [M] and Missing [!]
4768 states are Added [A], Clean [C], Modified [M] and Missing [!]
4769 (as reported by :hg:`status`). The actions are Warn, Remove
4769 (as reported by :hg:`status`). The actions are Warn, Remove
4770 (from branch) and Delete (from disk):
4770 (from branch) and Delete (from disk):
4771
4771
4772 ========= == == == ==
4772 ========= == == == ==
4773 opt/state A C M !
4773 opt/state A C M !
4774 ========= == == == ==
4774 ========= == == == ==
4775 none W RD W R
4775 none W RD W R
4776 -f R RD RD R
4776 -f R RD RD R
4777 -A W W W R
4777 -A W W W R
4778 -Af R R R R
4778 -Af R R R R
4779 ========= == == == ==
4779 ========= == == == ==
4780
4780
4781 Note that remove never deletes files in Added [A] state from the
4781 Note that remove never deletes files in Added [A] state from the
4782 working directory, not even if option --force is specified.
4782 working directory, not even if option --force is specified.
4783
4783
4784 Returns 0 on success, 1 if any warnings encountered.
4784 Returns 0 on success, 1 if any warnings encountered.
4785 """
4785 """
4786
4786
4787 ret = 0
4787 ret = 0
4788 after, force = opts.get('after'), opts.get('force')
4788 after, force = opts.get('after'), opts.get('force')
4789 if not pats and not after:
4789 if not pats and not after:
4790 raise util.Abort(_('no files specified'))
4790 raise util.Abort(_('no files specified'))
4791
4791
4792 m = scmutil.match(repo[None], pats, opts)
4792 m = scmutil.match(repo[None], pats, opts)
4793 s = repo.status(match=m, clean=True)
4793 s = repo.status(match=m, clean=True)
4794 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4794 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4795
4795
4796 # warn about failure to delete explicit files/dirs
4796 # warn about failure to delete explicit files/dirs
4797 wctx = repo[None]
4797 wctx = repo[None]
4798 for f in m.files():
4798 for f in m.files():
4799 if f in repo.dirstate or f in wctx.dirs():
4799 if f in repo.dirstate or f in wctx.dirs():
4800 continue
4800 continue
4801 if os.path.exists(m.rel(f)):
4801 if os.path.exists(m.rel(f)):
4802 if os.path.isdir(m.rel(f)):
4802 if os.path.isdir(m.rel(f)):
4803 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4803 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4804 else:
4804 else:
4805 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4805 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4806 # missing files will generate a warning elsewhere
4806 # missing files will generate a warning elsewhere
4807 ret = 1
4807 ret = 1
4808
4808
4809 if force:
4809 if force:
4810 list = modified + deleted + clean + added
4810 list = modified + deleted + clean + added
4811 elif after:
4811 elif after:
4812 list = deleted
4812 list = deleted
4813 for f in modified + added + clean:
4813 for f in modified + added + clean:
4814 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4814 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4815 ret = 1
4815 ret = 1
4816 else:
4816 else:
4817 list = deleted + clean
4817 list = deleted + clean
4818 for f in modified:
4818 for f in modified:
4819 ui.warn(_('not removing %s: file is modified (use -f'
4819 ui.warn(_('not removing %s: file is modified (use -f'
4820 ' to force removal)\n') % m.rel(f))
4820 ' to force removal)\n') % m.rel(f))
4821 ret = 1
4821 ret = 1
4822 for f in added:
4822 for f in added:
4823 ui.warn(_('not removing %s: file has been marked for add'
4823 ui.warn(_('not removing %s: file has been marked for add'
4824 ' (use forget to undo)\n') % m.rel(f))
4824 ' (use forget to undo)\n') % m.rel(f))
4825 ret = 1
4825 ret = 1
4826
4826
4827 for f in sorted(list):
4827 for f in sorted(list):
4828 if ui.verbose or not m.exact(f):
4828 if ui.verbose or not m.exact(f):
4829 ui.status(_('removing %s\n') % m.rel(f))
4829 ui.status(_('removing %s\n') % m.rel(f))
4830
4830
4831 wlock = repo.wlock()
4831 wlock = repo.wlock()
4832 try:
4832 try:
4833 if not after:
4833 if not after:
4834 for f in list:
4834 for f in list:
4835 if f in added:
4835 if f in added:
4836 continue # we never unlink added files on remove
4836 continue # we never unlink added files on remove
4837 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4837 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4838 repo[None].forget(list)
4838 repo[None].forget(list)
4839 finally:
4839 finally:
4840 wlock.release()
4840 wlock.release()
4841
4841
4842 return ret
4842 return ret
4843
4843
4844 @command('rename|move|mv',
4844 @command('rename|move|mv',
4845 [('A', 'after', None, _('record a rename that has already occurred')),
4845 [('A', 'after', None, _('record a rename that has already occurred')),
4846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4847 ] + walkopts + dryrunopts,
4847 ] + walkopts + dryrunopts,
4848 _('[OPTION]... SOURCE... DEST'))
4848 _('[OPTION]... SOURCE... DEST'))
4849 def rename(ui, repo, *pats, **opts):
4849 def rename(ui, repo, *pats, **opts):
4850 """rename files; equivalent of copy + remove
4850 """rename files; equivalent of copy + remove
4851
4851
4852 Mark dest as copies of sources; mark sources for deletion. If dest
4852 Mark dest as copies of sources; mark sources for deletion. If dest
4853 is a directory, copies are put in that directory. If dest is a
4853 is a directory, copies are put in that directory. If dest is a
4854 file, there can only be one source.
4854 file, there can only be one source.
4855
4855
4856 By default, this command copies the contents of files as they
4856 By default, this command copies the contents of files as they
4857 exist in the working directory. If invoked with -A/--after, the
4857 exist in the working directory. If invoked with -A/--after, the
4858 operation is recorded, but no copying is performed.
4858 operation is recorded, but no copying is performed.
4859
4859
4860 This command takes effect at the next commit. To undo a rename
4860 This command takes effect at the next commit. To undo a rename
4861 before that, see :hg:`revert`.
4861 before that, see :hg:`revert`.
4862
4862
4863 Returns 0 on success, 1 if errors are encountered.
4863 Returns 0 on success, 1 if errors are encountered.
4864 """
4864 """
4865 wlock = repo.wlock(False)
4865 wlock = repo.wlock(False)
4866 try:
4866 try:
4867 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4867 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4868 finally:
4868 finally:
4869 wlock.release()
4869 wlock.release()
4870
4870
4871 @command('resolve',
4871 @command('resolve',
4872 [('a', 'all', None, _('select all unresolved files')),
4872 [('a', 'all', None, _('select all unresolved files')),
4873 ('l', 'list', None, _('list state of files needing merge')),
4873 ('l', 'list', None, _('list state of files needing merge')),
4874 ('m', 'mark', None, _('mark files as resolved')),
4874 ('m', 'mark', None, _('mark files as resolved')),
4875 ('u', 'unmark', None, _('mark files as unresolved')),
4875 ('u', 'unmark', None, _('mark files as unresolved')),
4876 ('n', 'no-status', None, _('hide status prefix'))]
4876 ('n', 'no-status', None, _('hide status prefix'))]
4877 + mergetoolopts + walkopts,
4877 + mergetoolopts + walkopts,
4878 _('[OPTION]... [FILE]...'))
4878 _('[OPTION]... [FILE]...'))
4879 def resolve(ui, repo, *pats, **opts):
4879 def resolve(ui, repo, *pats, **opts):
4880 """redo merges or set/view the merge status of files
4880 """redo merges or set/view the merge status of files
4881
4881
4882 Merges with unresolved conflicts are often the result of
4882 Merges with unresolved conflicts are often the result of
4883 non-interactive merging using the ``internal:merge`` configuration
4883 non-interactive merging using the ``internal:merge`` configuration
4884 setting, or a command-line merge tool like ``diff3``. The resolve
4884 setting, or a command-line merge tool like ``diff3``. The resolve
4885 command is used to manage the files involved in a merge, after
4885 command is used to manage the files involved in a merge, after
4886 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4886 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4887 working directory must have two parents). See :hg:`help
4887 working directory must have two parents). See :hg:`help
4888 merge-tools` for information on configuring merge tools.
4888 merge-tools` for information on configuring merge tools.
4889
4889
4890 The resolve command can be used in the following ways:
4890 The resolve command can be used in the following ways:
4891
4891
4892 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4892 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4893 files, discarding any previous merge attempts. Re-merging is not
4893 files, discarding any previous merge attempts. Re-merging is not
4894 performed for files already marked as resolved. Use ``--all/-a``
4894 performed for files already marked as resolved. Use ``--all/-a``
4895 to select all unresolved files. ``--tool`` can be used to specify
4895 to select all unresolved files. ``--tool`` can be used to specify
4896 the merge tool used for the given files. It overrides the HGMERGE
4896 the merge tool used for the given files. It overrides the HGMERGE
4897 environment variable and your configuration files. Previous file
4897 environment variable and your configuration files. Previous file
4898 contents are saved with a ``.orig`` suffix.
4898 contents are saved with a ``.orig`` suffix.
4899
4899
4900 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4900 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4901 (e.g. after having manually fixed-up the files). The default is
4901 (e.g. after having manually fixed-up the files). The default is
4902 to mark all unresolved files.
4902 to mark all unresolved files.
4903
4903
4904 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4904 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4905 default is to mark all resolved files.
4905 default is to mark all resolved files.
4906
4906
4907 - :hg:`resolve -l`: list files which had or still have conflicts.
4907 - :hg:`resolve -l`: list files which had or still have conflicts.
4908 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4908 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4909
4909
4910 Note that Mercurial will not let you commit files with unresolved
4910 Note that Mercurial will not let you commit files with unresolved
4911 merge conflicts. You must use :hg:`resolve -m ...` before you can
4911 merge conflicts. You must use :hg:`resolve -m ...` before you can
4912 commit after a conflicting merge.
4912 commit after a conflicting merge.
4913
4913
4914 Returns 0 on success, 1 if any files fail a resolve attempt.
4914 Returns 0 on success, 1 if any files fail a resolve attempt.
4915 """
4915 """
4916
4916
4917 all, mark, unmark, show, nostatus = \
4917 all, mark, unmark, show, nostatus = \
4918 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4918 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4919
4919
4920 if (show and (mark or unmark)) or (mark and unmark):
4920 if (show and (mark or unmark)) or (mark and unmark):
4921 raise util.Abort(_("too many options specified"))
4921 raise util.Abort(_("too many options specified"))
4922 if pats and all:
4922 if pats and all:
4923 raise util.Abort(_("can't specify --all and patterns"))
4923 raise util.Abort(_("can't specify --all and patterns"))
4924 if not (all or pats or show or mark or unmark):
4924 if not (all or pats or show or mark or unmark):
4925 raise util.Abort(_('no files or directories specified; '
4925 raise util.Abort(_('no files or directories specified; '
4926 'use --all to remerge all files'))
4926 'use --all to remerge all files'))
4927
4927
4928 ms = mergemod.mergestate(repo)
4928 ms = mergemod.mergestate(repo)
4929
4929
4930 if not ms.active():
4930 if not ms.active():
4931 raise util.Abort(_('resolve command not applicable when not merging'))
4931 raise util.Abort(_('resolve command not applicable when not merging'))
4932
4932
4933 m = scmutil.match(repo[None], pats, opts)
4933 m = scmutil.match(repo[None], pats, opts)
4934 ret = 0
4934 ret = 0
4935
4935
4936 didwork = False
4936 didwork = False
4937 for f in ms:
4937 for f in ms:
4938 if not m(f):
4938 if not m(f):
4939 continue
4939 continue
4940
4940
4941 didwork = True
4941 didwork = True
4942
4942
4943 if show:
4943 if show:
4944 if nostatus:
4944 if nostatus:
4945 ui.write("%s\n" % f)
4945 ui.write("%s\n" % f)
4946 else:
4946 else:
4947 ui.write("%s %s\n" % (ms[f].upper(), f),
4947 ui.write("%s %s\n" % (ms[f].upper(), f),
4948 label='resolve.' +
4948 label='resolve.' +
4949 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4949 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4950 elif mark:
4950 elif mark:
4951 ms.mark(f, "r")
4951 ms.mark(f, "r")
4952 elif unmark:
4952 elif unmark:
4953 ms.mark(f, "u")
4953 ms.mark(f, "u")
4954 else:
4954 else:
4955 wctx = repo[None]
4955 wctx = repo[None]
4956
4956
4957 # backup pre-resolve (merge uses .orig for its own purposes)
4957 # backup pre-resolve (merge uses .orig for its own purposes)
4958 a = repo.wjoin(f)
4958 a = repo.wjoin(f)
4959 util.copyfile(a, a + ".resolve")
4959 util.copyfile(a, a + ".resolve")
4960
4960
4961 try:
4961 try:
4962 # resolve file
4962 # resolve file
4963 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4963 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4964 'resolve')
4964 'resolve')
4965 if ms.resolve(f, wctx):
4965 if ms.resolve(f, wctx):
4966 ret = 1
4966 ret = 1
4967 finally:
4967 finally:
4968 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4968 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4969 ms.commit()
4969 ms.commit()
4970
4970
4971 # replace filemerge's .orig file with our resolve file
4971 # replace filemerge's .orig file with our resolve file
4972 util.rename(a + ".resolve", a + ".orig")
4972 util.rename(a + ".resolve", a + ".orig")
4973
4973
4974 ms.commit()
4974 ms.commit()
4975
4975
4976 if not didwork and pats:
4976 if not didwork and pats:
4977 ui.warn(_("arguments do not match paths that need resolved\n"))
4977 ui.warn(_("arguments do not match paths that need resolved\n"))
4978
4978
4979 # Nudge users into finishing an unfinished operation. We don't print
4979 # Nudge users into finishing an unfinished operation. We don't print
4980 # this with the list/show operation because we want list/show to remain
4980 # this with the list/show operation because we want list/show to remain
4981 # machine readable.
4981 # machine readable.
4982 if not list(ms.unresolved()) and not show:
4982 if not list(ms.unresolved()) and not show:
4983 ui.status(_('no more unresolved files\n'))
4983 ui.status(_('no more unresolved files\n'))
4984
4984
4985 return ret
4985 return ret
4986
4986
4987 @command('revert',
4987 @command('revert',
4988 [('a', 'all', None, _('revert all changes when no arguments given')),
4988 [('a', 'all', None, _('revert all changes when no arguments given')),
4989 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4989 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4990 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4990 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4991 ('C', 'no-backup', None, _('do not save backup copies of files')),
4991 ('C', 'no-backup', None, _('do not save backup copies of files')),
4992 ] + walkopts + dryrunopts,
4992 ] + walkopts + dryrunopts,
4993 _('[OPTION]... [-r REV] [NAME]...'))
4993 _('[OPTION]... [-r REV] [NAME]...'))
4994 def revert(ui, repo, *pats, **opts):
4994 def revert(ui, repo, *pats, **opts):
4995 """restore files to their checkout state
4995 """restore files to their checkout state
4996
4996
4997 .. note::
4997 .. note::
4998
4998
4999 To check out earlier revisions, you should use :hg:`update REV`.
4999 To check out earlier revisions, you should use :hg:`update REV`.
5000 To cancel an uncommitted merge (and lose your changes),
5000 To cancel an uncommitted merge (and lose your changes),
5001 use :hg:`update --clean .`.
5001 use :hg:`update --clean .`.
5002
5002
5003 With no revision specified, revert the specified files or directories
5003 With no revision specified, revert the specified files or directories
5004 to the contents they had in the parent of the working directory.
5004 to the contents they had in the parent of the working directory.
5005 This restores the contents of files to an unmodified
5005 This restores the contents of files to an unmodified
5006 state and unschedules adds, removes, copies, and renames. If the
5006 state and unschedules adds, removes, copies, and renames. If the
5007 working directory has two parents, you must explicitly specify a
5007 working directory has two parents, you must explicitly specify a
5008 revision.
5008 revision.
5009
5009
5010 Using the -r/--rev or -d/--date options, revert the given files or
5010 Using the -r/--rev or -d/--date options, revert the given files or
5011 directories to their states as of a specific revision. Because
5011 directories to their states as of a specific revision. Because
5012 revert does not change the working directory parents, this will
5012 revert does not change the working directory parents, this will
5013 cause these files to appear modified. This can be helpful to "back
5013 cause these files to appear modified. This can be helpful to "back
5014 out" some or all of an earlier change. See :hg:`backout` for a
5014 out" some or all of an earlier change. See :hg:`backout` for a
5015 related method.
5015 related method.
5016
5016
5017 Modified files are saved with a .orig suffix before reverting.
5017 Modified files are saved with a .orig suffix before reverting.
5018 To disable these backups, use --no-backup.
5018 To disable these backups, use --no-backup.
5019
5019
5020 See :hg:`help dates` for a list of formats valid for -d/--date.
5020 See :hg:`help dates` for a list of formats valid for -d/--date.
5021
5021
5022 Returns 0 on success.
5022 Returns 0 on success.
5023 """
5023 """
5024
5024
5025 if opts.get("date"):
5025 if opts.get("date"):
5026 if opts.get("rev"):
5026 if opts.get("rev"):
5027 raise util.Abort(_("you can't specify a revision and a date"))
5027 raise util.Abort(_("you can't specify a revision and a date"))
5028 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5028 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5029
5029
5030 parent, p2 = repo.dirstate.parents()
5030 parent, p2 = repo.dirstate.parents()
5031 if not opts.get('rev') and p2 != nullid:
5031 if not opts.get('rev') and p2 != nullid:
5032 # revert after merge is a trap for new users (issue2915)
5032 # revert after merge is a trap for new users (issue2915)
5033 raise util.Abort(_('uncommitted merge with no revision specified'),
5033 raise util.Abort(_('uncommitted merge with no revision specified'),
5034 hint=_('use "hg update" or see "hg help revert"'))
5034 hint=_('use "hg update" or see "hg help revert"'))
5035
5035
5036 ctx = scmutil.revsingle(repo, opts.get('rev'))
5036 ctx = scmutil.revsingle(repo, opts.get('rev'))
5037
5037
5038 if not pats and not opts.get('all'):
5038 if not pats and not opts.get('all'):
5039 msg = _("no files or directories specified")
5039 msg = _("no files or directories specified")
5040 if p2 != nullid:
5040 if p2 != nullid:
5041 hint = _("uncommitted merge, use --all to discard all changes,"
5041 hint = _("uncommitted merge, use --all to discard all changes,"
5042 " or 'hg update -C .' to abort the merge")
5042 " or 'hg update -C .' to abort the merge")
5043 raise util.Abort(msg, hint=hint)
5043 raise util.Abort(msg, hint=hint)
5044 dirty = util.any(repo.status())
5044 dirty = util.any(repo.status())
5045 node = ctx.node()
5045 node = ctx.node()
5046 if node != parent:
5046 if node != parent:
5047 if dirty:
5047 if dirty:
5048 hint = _("uncommitted changes, use --all to discard all"
5048 hint = _("uncommitted changes, use --all to discard all"
5049 " changes, or 'hg update %s' to update") % ctx.rev()
5049 " changes, or 'hg update %s' to update") % ctx.rev()
5050 else:
5050 else:
5051 hint = _("use --all to revert all files,"
5051 hint = _("use --all to revert all files,"
5052 " or 'hg update %s' to update") % ctx.rev()
5052 " or 'hg update %s' to update") % ctx.rev()
5053 elif dirty:
5053 elif dirty:
5054 hint = _("uncommitted changes, use --all to discard all changes")
5054 hint = _("uncommitted changes, use --all to discard all changes")
5055 else:
5055 else:
5056 hint = _("use --all to revert all files")
5056 hint = _("use --all to revert all files")
5057 raise util.Abort(msg, hint=hint)
5057 raise util.Abort(msg, hint=hint)
5058
5058
5059 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5059 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5060
5060
5061 @command('rollback', dryrunopts +
5061 @command('rollback', dryrunopts +
5062 [('f', 'force', False, _('ignore safety measures'))])
5062 [('f', 'force', False, _('ignore safety measures'))])
5063 def rollback(ui, repo, **opts):
5063 def rollback(ui, repo, **opts):
5064 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5064 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5065
5065
5066 Please use :hg:`commit --amend` instead of rollback to correct
5066 Please use :hg:`commit --amend` instead of rollback to correct
5067 mistakes in the last commit.
5067 mistakes in the last commit.
5068
5068
5069 This command should be used with care. There is only one level of
5069 This command should be used with care. There is only one level of
5070 rollback, and there is no way to undo a rollback. It will also
5070 rollback, and there is no way to undo a rollback. It will also
5071 restore the dirstate at the time of the last transaction, losing
5071 restore the dirstate at the time of the last transaction, losing
5072 any dirstate changes since that time. This command does not alter
5072 any dirstate changes since that time. This command does not alter
5073 the working directory.
5073 the working directory.
5074
5074
5075 Transactions are used to encapsulate the effects of all commands
5075 Transactions are used to encapsulate the effects of all commands
5076 that create new changesets or propagate existing changesets into a
5076 that create new changesets or propagate existing changesets into a
5077 repository.
5077 repository.
5078
5078
5079 .. container:: verbose
5079 .. container:: verbose
5080
5080
5081 For example, the following commands are transactional, and their
5081 For example, the following commands are transactional, and their
5082 effects can be rolled back:
5082 effects can be rolled back:
5083
5083
5084 - commit
5084 - commit
5085 - import
5085 - import
5086 - pull
5086 - pull
5087 - push (with this repository as the destination)
5087 - push (with this repository as the destination)
5088 - unbundle
5088 - unbundle
5089
5089
5090 To avoid permanent data loss, rollback will refuse to rollback a
5090 To avoid permanent data loss, rollback will refuse to rollback a
5091 commit transaction if it isn't checked out. Use --force to
5091 commit transaction if it isn't checked out. Use --force to
5092 override this protection.
5092 override this protection.
5093
5093
5094 This command is not intended for use on public repositories. Once
5094 This command is not intended for use on public repositories. Once
5095 changes are visible for pull by other users, rolling a transaction
5095 changes are visible for pull by other users, rolling a transaction
5096 back locally is ineffective (someone else may already have pulled
5096 back locally is ineffective (someone else may already have pulled
5097 the changes). Furthermore, a race is possible with readers of the
5097 the changes). Furthermore, a race is possible with readers of the
5098 repository; for example an in-progress pull from the repository
5098 repository; for example an in-progress pull from the repository
5099 may fail if a rollback is performed.
5099 may fail if a rollback is performed.
5100
5100
5101 Returns 0 on success, 1 if no rollback data is available.
5101 Returns 0 on success, 1 if no rollback data is available.
5102 """
5102 """
5103 return repo.rollback(dryrun=opts.get('dry_run'),
5103 return repo.rollback(dryrun=opts.get('dry_run'),
5104 force=opts.get('force'))
5104 force=opts.get('force'))
5105
5105
5106 @command('root', [])
5106 @command('root', [])
5107 def root(ui, repo):
5107 def root(ui, repo):
5108 """print the root (top) of the current working directory
5108 """print the root (top) of the current working directory
5109
5109
5110 Print the root directory of the current repository.
5110 Print the root directory of the current repository.
5111
5111
5112 Returns 0 on success.
5112 Returns 0 on success.
5113 """
5113 """
5114 ui.write(repo.root + "\n")
5114 ui.write(repo.root + "\n")
5115
5115
5116 @command('^serve',
5116 @command('^serve',
5117 [('A', 'accesslog', '', _('name of access log file to write to'),
5117 [('A', 'accesslog', '', _('name of access log file to write to'),
5118 _('FILE')),
5118 _('FILE')),
5119 ('d', 'daemon', None, _('run server in background')),
5119 ('d', 'daemon', None, _('run server in background')),
5120 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5120 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5121 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5121 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5122 # use string type, then we can check if something was passed
5122 # use string type, then we can check if something was passed
5123 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5123 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5124 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5124 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5125 _('ADDR')),
5125 _('ADDR')),
5126 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5126 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5127 _('PREFIX')),
5127 _('PREFIX')),
5128 ('n', 'name', '',
5128 ('n', 'name', '',
5129 _('name to show in web pages (default: working directory)'), _('NAME')),
5129 _('name to show in web pages (default: working directory)'), _('NAME')),
5130 ('', 'web-conf', '',
5130 ('', 'web-conf', '',
5131 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5131 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5132 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5132 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5133 _('FILE')),
5133 _('FILE')),
5134 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5134 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5135 ('', 'stdio', None, _('for remote clients')),
5135 ('', 'stdio', None, _('for remote clients')),
5136 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5136 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5137 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5137 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5138 ('', 'style', '', _('template style to use'), _('STYLE')),
5138 ('', 'style', '', _('template style to use'), _('STYLE')),
5139 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5139 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5140 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5140 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5141 _('[OPTION]...'))
5141 _('[OPTION]...'))
5142 def serve(ui, repo, **opts):
5142 def serve(ui, repo, **opts):
5143 """start stand-alone webserver
5143 """start stand-alone webserver
5144
5144
5145 Start a local HTTP repository browser and pull server. You can use
5145 Start a local HTTP repository browser and pull server. You can use
5146 this for ad-hoc sharing and browsing of repositories. It is
5146 this for ad-hoc sharing and browsing of repositories. It is
5147 recommended to use a real web server to serve a repository for
5147 recommended to use a real web server to serve a repository for
5148 longer periods of time.
5148 longer periods of time.
5149
5149
5150 Please note that the server does not implement access control.
5150 Please note that the server does not implement access control.
5151 This means that, by default, anybody can read from the server and
5151 This means that, by default, anybody can read from the server and
5152 nobody can write to it by default. Set the ``web.allow_push``
5152 nobody can write to it by default. Set the ``web.allow_push``
5153 option to ``*`` to allow everybody to push to the server. You
5153 option to ``*`` to allow everybody to push to the server. You
5154 should use a real web server if you need to authenticate users.
5154 should use a real web server if you need to authenticate users.
5155
5155
5156 By default, the server logs accesses to stdout and errors to
5156 By default, the server logs accesses to stdout and errors to
5157 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5157 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5158 files.
5158 files.
5159
5159
5160 To have the server choose a free port number to listen on, specify
5160 To have the server choose a free port number to listen on, specify
5161 a port number of 0; in this case, the server will print the port
5161 a port number of 0; in this case, the server will print the port
5162 number it uses.
5162 number it uses.
5163
5163
5164 Returns 0 on success.
5164 Returns 0 on success.
5165 """
5165 """
5166
5166
5167 if opts["stdio"] and opts["cmdserver"]:
5167 if opts["stdio"] and opts["cmdserver"]:
5168 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5168 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5169
5169
5170 def checkrepo():
5170 def checkrepo():
5171 if repo is None:
5171 if repo is None:
5172 raise error.RepoError(_("there is no Mercurial repository here"
5172 raise error.RepoError(_("there is no Mercurial repository here"
5173 " (.hg not found)"))
5173 " (.hg not found)"))
5174
5174
5175 if opts["stdio"]:
5175 if opts["stdio"]:
5176 checkrepo()
5176 checkrepo()
5177 s = sshserver.sshserver(ui, repo)
5177 s = sshserver.sshserver(ui, repo)
5178 s.serve_forever()
5178 s.serve_forever()
5179
5179
5180 if opts["cmdserver"]:
5180 if opts["cmdserver"]:
5181 s = commandserver.server(ui, repo, opts["cmdserver"])
5181 s = commandserver.server(ui, repo, opts["cmdserver"])
5182 return s.serve()
5182 return s.serve()
5183
5183
5184 # this way we can check if something was given in the command-line
5184 # this way we can check if something was given in the command-line
5185 if opts.get('port'):
5185 if opts.get('port'):
5186 opts['port'] = util.getport(opts.get('port'))
5186 opts['port'] = util.getport(opts.get('port'))
5187
5187
5188 baseui = repo and repo.baseui or ui
5188 baseui = repo and repo.baseui or ui
5189 optlist = ("name templates style address port prefix ipv6"
5189 optlist = ("name templates style address port prefix ipv6"
5190 " accesslog errorlog certificate encoding")
5190 " accesslog errorlog certificate encoding")
5191 for o in optlist.split():
5191 for o in optlist.split():
5192 val = opts.get(o, '')
5192 val = opts.get(o, '')
5193 if val in (None, ''): # should check against default options instead
5193 if val in (None, ''): # should check against default options instead
5194 continue
5194 continue
5195 baseui.setconfig("web", o, val, 'serve')
5195 baseui.setconfig("web", o, val, 'serve')
5196 if repo and repo.ui != baseui:
5196 if repo and repo.ui != baseui:
5197 repo.ui.setconfig("web", o, val, 'serve')
5197 repo.ui.setconfig("web", o, val, 'serve')
5198
5198
5199 o = opts.get('web_conf') or opts.get('webdir_conf')
5199 o = opts.get('web_conf') or opts.get('webdir_conf')
5200 if not o:
5200 if not o:
5201 if not repo:
5201 if not repo:
5202 raise error.RepoError(_("there is no Mercurial repository"
5202 raise error.RepoError(_("there is no Mercurial repository"
5203 " here (.hg not found)"))
5203 " here (.hg not found)"))
5204 o = repo
5204 o = repo
5205
5205
5206 app = hgweb.hgweb(o, baseui=baseui)
5206 app = hgweb.hgweb(o, baseui=baseui)
5207 service = httpservice(ui, app, opts)
5207 service = httpservice(ui, app, opts)
5208 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5208 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5209
5209
5210 class httpservice(object):
5210 class httpservice(object):
5211 def __init__(self, ui, app, opts):
5211 def __init__(self, ui, app, opts):
5212 self.ui = ui
5212 self.ui = ui
5213 self.app = app
5213 self.app = app
5214 self.opts = opts
5214 self.opts = opts
5215
5215
5216 def init(self):
5216 def init(self):
5217 util.setsignalhandler()
5217 util.setsignalhandler()
5218 self.httpd = hgweb_server.create_server(self.ui, self.app)
5218 self.httpd = hgweb_server.create_server(self.ui, self.app)
5219
5219
5220 if self.opts['port'] and not self.ui.verbose:
5220 if self.opts['port'] and not self.ui.verbose:
5221 return
5221 return
5222
5222
5223 if self.httpd.prefix:
5223 if self.httpd.prefix:
5224 prefix = self.httpd.prefix.strip('/') + '/'
5224 prefix = self.httpd.prefix.strip('/') + '/'
5225 else:
5225 else:
5226 prefix = ''
5226 prefix = ''
5227
5227
5228 port = ':%d' % self.httpd.port
5228 port = ':%d' % self.httpd.port
5229 if port == ':80':
5229 if port == ':80':
5230 port = ''
5230 port = ''
5231
5231
5232 bindaddr = self.httpd.addr
5232 bindaddr = self.httpd.addr
5233 if bindaddr == '0.0.0.0':
5233 if bindaddr == '0.0.0.0':
5234 bindaddr = '*'
5234 bindaddr = '*'
5235 elif ':' in bindaddr: # IPv6
5235 elif ':' in bindaddr: # IPv6
5236 bindaddr = '[%s]' % bindaddr
5236 bindaddr = '[%s]' % bindaddr
5237
5237
5238 fqaddr = self.httpd.fqaddr
5238 fqaddr = self.httpd.fqaddr
5239 if ':' in fqaddr:
5239 if ':' in fqaddr:
5240 fqaddr = '[%s]' % fqaddr
5240 fqaddr = '[%s]' % fqaddr
5241 if self.opts['port']:
5241 if self.opts['port']:
5242 write = self.ui.status
5242 write = self.ui.status
5243 else:
5243 else:
5244 write = self.ui.write
5244 write = self.ui.write
5245 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5245 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5246 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5246 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5247
5247
5248 def run(self):
5248 def run(self):
5249 self.httpd.serve_forever()
5249 self.httpd.serve_forever()
5250
5250
5251
5251
5252 @command('^status|st',
5252 @command('^status|st',
5253 [('A', 'all', None, _('show status of all files')),
5253 [('A', 'all', None, _('show status of all files')),
5254 ('m', 'modified', None, _('show only modified files')),
5254 ('m', 'modified', None, _('show only modified files')),
5255 ('a', 'added', None, _('show only added files')),
5255 ('a', 'added', None, _('show only added files')),
5256 ('r', 'removed', None, _('show only removed files')),
5256 ('r', 'removed', None, _('show only removed files')),
5257 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5257 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5258 ('c', 'clean', None, _('show only files without changes')),
5258 ('c', 'clean', None, _('show only files without changes')),
5259 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5259 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5260 ('i', 'ignored', None, _('show only ignored files')),
5260 ('i', 'ignored', None, _('show only ignored files')),
5261 ('n', 'no-status', None, _('hide status prefix')),
5261 ('n', 'no-status', None, _('hide status prefix')),
5262 ('C', 'copies', None, _('show source of copied files')),
5262 ('C', 'copies', None, _('show source of copied files')),
5263 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5263 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5264 ('', 'rev', [], _('show difference from revision'), _('REV')),
5264 ('', 'rev', [], _('show difference from revision'), _('REV')),
5265 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5265 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5266 ] + walkopts + subrepoopts,
5266 ] + walkopts + subrepoopts,
5267 _('[OPTION]... [FILE]...'))
5267 _('[OPTION]... [FILE]...'))
5268 def status(ui, repo, *pats, **opts):
5268 def status(ui, repo, *pats, **opts):
5269 """show changed files in the working directory
5269 """show changed files in the working directory
5270
5270
5271 Show status of files in the repository. If names are given, only
5271 Show status of files in the repository. If names are given, only
5272 files that match are shown. Files that are clean or ignored or
5272 files that match are shown. Files that are clean or ignored or
5273 the source of a copy/move operation, are not listed unless
5273 the source of a copy/move operation, are not listed unless
5274 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5274 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5275 Unless options described with "show only ..." are given, the
5275 Unless options described with "show only ..." are given, the
5276 options -mardu are used.
5276 options -mardu are used.
5277
5277
5278 Option -q/--quiet hides untracked (unknown and ignored) files
5278 Option -q/--quiet hides untracked (unknown and ignored) files
5279 unless explicitly requested with -u/--unknown or -i/--ignored.
5279 unless explicitly requested with -u/--unknown or -i/--ignored.
5280
5280
5281 .. note::
5281 .. note::
5282
5282
5283 status may appear to disagree with diff if permissions have
5283 status may appear to disagree with diff if permissions have
5284 changed or a merge has occurred. The standard diff format does
5284 changed or a merge has occurred. The standard diff format does
5285 not report permission changes and diff only reports changes
5285 not report permission changes and diff only reports changes
5286 relative to one merge parent.
5286 relative to one merge parent.
5287
5287
5288 If one revision is given, it is used as the base revision.
5288 If one revision is given, it is used as the base revision.
5289 If two revisions are given, the differences between them are
5289 If two revisions are given, the differences between them are
5290 shown. The --change option can also be used as a shortcut to list
5290 shown. The --change option can also be used as a shortcut to list
5291 the changed files of a revision from its first parent.
5291 the changed files of a revision from its first parent.
5292
5292
5293 The codes used to show the status of files are::
5293 The codes used to show the status of files are::
5294
5294
5295 M = modified
5295 M = modified
5296 A = added
5296 A = added
5297 R = removed
5297 R = removed
5298 C = clean
5298 C = clean
5299 ! = missing (deleted by non-hg command, but still tracked)
5299 ! = missing (deleted by non-hg command, but still tracked)
5300 ? = not tracked
5300 ? = not tracked
5301 I = ignored
5301 I = ignored
5302 = origin of the previous file (with --copies)
5302 = origin of the previous file (with --copies)
5303
5303
5304 .. container:: verbose
5304 .. container:: verbose
5305
5305
5306 Examples:
5306 Examples:
5307
5307
5308 - show changes in the working directory relative to a
5308 - show changes in the working directory relative to a
5309 changeset::
5309 changeset::
5310
5310
5311 hg status --rev 9353
5311 hg status --rev 9353
5312
5312
5313 - show all changes including copies in an existing changeset::
5313 - show all changes including copies in an existing changeset::
5314
5314
5315 hg status --copies --change 9353
5315 hg status --copies --change 9353
5316
5316
5317 - get a NUL separated list of added files, suitable for xargs::
5317 - get a NUL separated list of added files, suitable for xargs::
5318
5318
5319 hg status -an0
5319 hg status -an0
5320
5320
5321 Returns 0 on success.
5321 Returns 0 on success.
5322 """
5322 """
5323
5323
5324 revs = opts.get('rev')
5324 revs = opts.get('rev')
5325 change = opts.get('change')
5325 change = opts.get('change')
5326
5326
5327 if revs and change:
5327 if revs and change:
5328 msg = _('cannot specify --rev and --change at the same time')
5328 msg = _('cannot specify --rev and --change at the same time')
5329 raise util.Abort(msg)
5329 raise util.Abort(msg)
5330 elif change:
5330 elif change:
5331 node2 = scmutil.revsingle(repo, change, None).node()
5331 node2 = scmutil.revsingle(repo, change, None).node()
5332 node1 = repo[node2].p1().node()
5332 node1 = repo[node2].p1().node()
5333 else:
5333 else:
5334 node1, node2 = scmutil.revpair(repo, revs)
5334 node1, node2 = scmutil.revpair(repo, revs)
5335
5335
5336 cwd = (pats and repo.getcwd()) or ''
5336 cwd = (pats and repo.getcwd()) or ''
5337 end = opts.get('print0') and '\0' or '\n'
5337 end = opts.get('print0') and '\0' or '\n'
5338 copy = {}
5338 copy = {}
5339 states = 'modified added removed deleted unknown ignored clean'.split()
5339 states = 'modified added removed deleted unknown ignored clean'.split()
5340 show = [k for k in states if opts.get(k)]
5340 show = [k for k in states if opts.get(k)]
5341 if opts.get('all'):
5341 if opts.get('all'):
5342 show += ui.quiet and (states[:4] + ['clean']) or states
5342 show += ui.quiet and (states[:4] + ['clean']) or states
5343 if not show:
5343 if not show:
5344 show = ui.quiet and states[:4] or states[:5]
5344 show = ui.quiet and states[:4] or states[:5]
5345
5345
5346 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5346 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5347 'ignored' in show, 'clean' in show, 'unknown' in show,
5347 'ignored' in show, 'clean' in show, 'unknown' in show,
5348 opts.get('subrepos'))
5348 opts.get('subrepos'))
5349 changestates = zip(states, 'MAR!?IC', stat)
5349 changestates = zip(states, 'MAR!?IC', stat)
5350
5350
5351 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5351 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5352 copy = copies.pathcopies(repo[node1], repo[node2])
5352 copy = copies.pathcopies(repo[node1], repo[node2])
5353
5353
5354 fm = ui.formatter('status', opts)
5354 fm = ui.formatter('status', opts)
5355 fmt = '%s' + end
5355 fmt = '%s' + end
5356 showchar = not opts.get('no_status')
5356 showchar = not opts.get('no_status')
5357
5357
5358 for state, char, files in changestates:
5358 for state, char, files in changestates:
5359 if state in show:
5359 if state in show:
5360 label = 'status.' + state
5360 label = 'status.' + state
5361 for f in files:
5361 for f in files:
5362 fm.startitem()
5362 fm.startitem()
5363 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5363 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5364 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5364 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5365 if f in copy:
5365 if f in copy:
5366 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5366 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5367 label='status.copied')
5367 label='status.copied')
5368 fm.end()
5368 fm.end()
5369
5369
5370 @command('^summary|sum',
5370 @command('^summary|sum',
5371 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5371 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5372 def summary(ui, repo, **opts):
5372 def summary(ui, repo, **opts):
5373 """summarize working directory state
5373 """summarize working directory state
5374
5374
5375 This generates a brief summary of the working directory state,
5375 This generates a brief summary of the working directory state,
5376 including parents, branch, commit status, and available updates.
5376 including parents, branch, commit status, and available updates.
5377
5377
5378 With the --remote option, this will check the default paths for
5378 With the --remote option, this will check the default paths for
5379 incoming and outgoing changes. This can be time-consuming.
5379 incoming and outgoing changes. This can be time-consuming.
5380
5380
5381 Returns 0 on success.
5381 Returns 0 on success.
5382 """
5382 """
5383
5383
5384 ctx = repo[None]
5384 ctx = repo[None]
5385 parents = ctx.parents()
5385 parents = ctx.parents()
5386 pnode = parents[0].node()
5386 pnode = parents[0].node()
5387 marks = []
5387 marks = []
5388
5388
5389 for p in parents:
5389 for p in parents:
5390 # label with log.changeset (instead of log.parent) since this
5390 # label with log.changeset (instead of log.parent) since this
5391 # shows a working directory parent *changeset*:
5391 # shows a working directory parent *changeset*:
5392 # i18n: column positioning for "hg summary"
5392 # i18n: column positioning for "hg summary"
5393 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5393 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5394 label='log.changeset changeset.%s' % p.phasestr())
5394 label='log.changeset changeset.%s' % p.phasestr())
5395 ui.write(' '.join(p.tags()), label='log.tag')
5395 ui.write(' '.join(p.tags()), label='log.tag')
5396 if p.bookmarks():
5396 if p.bookmarks():
5397 marks.extend(p.bookmarks())
5397 marks.extend(p.bookmarks())
5398 if p.rev() == -1:
5398 if p.rev() == -1:
5399 if not len(repo):
5399 if not len(repo):
5400 ui.write(_(' (empty repository)'))
5400 ui.write(_(' (empty repository)'))
5401 else:
5401 else:
5402 ui.write(_(' (no revision checked out)'))
5402 ui.write(_(' (no revision checked out)'))
5403 ui.write('\n')
5403 ui.write('\n')
5404 if p.description():
5404 if p.description():
5405 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5405 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5406 label='log.summary')
5406 label='log.summary')
5407
5407
5408 branch = ctx.branch()
5408 branch = ctx.branch()
5409 bheads = repo.branchheads(branch)
5409 bheads = repo.branchheads(branch)
5410 # i18n: column positioning for "hg summary"
5410 # i18n: column positioning for "hg summary"
5411 m = _('branch: %s\n') % branch
5411 m = _('branch: %s\n') % branch
5412 if branch != 'default':
5412 if branch != 'default':
5413 ui.write(m, label='log.branch')
5413 ui.write(m, label='log.branch')
5414 else:
5414 else:
5415 ui.status(m, label='log.branch')
5415 ui.status(m, label='log.branch')
5416
5416
5417 if marks:
5417 if marks:
5418 current = repo._bookmarkcurrent
5418 current = repo._bookmarkcurrent
5419 # i18n: column positioning for "hg summary"
5419 # i18n: column positioning for "hg summary"
5420 ui.write(_('bookmarks:'), label='log.bookmark')
5420 ui.write(_('bookmarks:'), label='log.bookmark')
5421 if current is not None:
5421 if current is not None:
5422 if current in marks:
5422 if current in marks:
5423 ui.write(' *' + current, label='bookmarks.current')
5423 ui.write(' *' + current, label='bookmarks.current')
5424 marks.remove(current)
5424 marks.remove(current)
5425 else:
5425 else:
5426 ui.write(' [%s]' % current, label='bookmarks.current')
5426 ui.write(' [%s]' % current, label='bookmarks.current')
5427 for m in marks:
5427 for m in marks:
5428 ui.write(' ' + m, label='log.bookmark')
5428 ui.write(' ' + m, label='log.bookmark')
5429 ui.write('\n', label='log.bookmark')
5429 ui.write('\n', label='log.bookmark')
5430
5430
5431 st = list(repo.status(unknown=True))[:6]
5431 st = list(repo.status(unknown=True))[:6]
5432
5432
5433 c = repo.dirstate.copies()
5433 c = repo.dirstate.copies()
5434 copied, renamed = [], []
5434 copied, renamed = [], []
5435 for d, s in c.iteritems():
5435 for d, s in c.iteritems():
5436 if s in st[2]:
5436 if s in st[2]:
5437 st[2].remove(s)
5437 st[2].remove(s)
5438 renamed.append(d)
5438 renamed.append(d)
5439 else:
5439 else:
5440 copied.append(d)
5440 copied.append(d)
5441 if d in st[1]:
5441 if d in st[1]:
5442 st[1].remove(d)
5442 st[1].remove(d)
5443 st.insert(3, renamed)
5443 st.insert(3, renamed)
5444 st.insert(4, copied)
5444 st.insert(4, copied)
5445
5445
5446 ms = mergemod.mergestate(repo)
5446 ms = mergemod.mergestate(repo)
5447 st.append([f for f in ms if ms[f] == 'u'])
5447 st.append([f for f in ms if ms[f] == 'u'])
5448
5448
5449 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5449 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5450 st.append(subs)
5450 st.append(subs)
5451
5451
5452 labels = [ui.label(_('%d modified'), 'status.modified'),
5452 labels = [ui.label(_('%d modified'), 'status.modified'),
5453 ui.label(_('%d added'), 'status.added'),
5453 ui.label(_('%d added'), 'status.added'),
5454 ui.label(_('%d removed'), 'status.removed'),
5454 ui.label(_('%d removed'), 'status.removed'),
5455 ui.label(_('%d renamed'), 'status.copied'),
5455 ui.label(_('%d renamed'), 'status.copied'),
5456 ui.label(_('%d copied'), 'status.copied'),
5456 ui.label(_('%d copied'), 'status.copied'),
5457 ui.label(_('%d deleted'), 'status.deleted'),
5457 ui.label(_('%d deleted'), 'status.deleted'),
5458 ui.label(_('%d unknown'), 'status.unknown'),
5458 ui.label(_('%d unknown'), 'status.unknown'),
5459 ui.label(_('%d ignored'), 'status.ignored'),
5459 ui.label(_('%d ignored'), 'status.ignored'),
5460 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5460 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5461 ui.label(_('%d subrepos'), 'status.modified')]
5461 ui.label(_('%d subrepos'), 'status.modified')]
5462 t = []
5462 t = []
5463 for s, l in zip(st, labels):
5463 for s, l in zip(st, labels):
5464 if s:
5464 if s:
5465 t.append(l % len(s))
5465 t.append(l % len(s))
5466
5466
5467 t = ', '.join(t)
5467 t = ', '.join(t)
5468 cleanworkdir = False
5468 cleanworkdir = False
5469
5469
5470 if repo.vfs.exists('updatestate'):
5470 if repo.vfs.exists('updatestate'):
5471 t += _(' (interrupted update)')
5471 t += _(' (interrupted update)')
5472 elif len(parents) > 1:
5472 elif len(parents) > 1:
5473 t += _(' (merge)')
5473 t += _(' (merge)')
5474 elif branch != parents[0].branch():
5474 elif branch != parents[0].branch():
5475 t += _(' (new branch)')
5475 t += _(' (new branch)')
5476 elif (parents[0].closesbranch() and
5476 elif (parents[0].closesbranch() and
5477 pnode in repo.branchheads(branch, closed=True)):
5477 pnode in repo.branchheads(branch, closed=True)):
5478 t += _(' (head closed)')
5478 t += _(' (head closed)')
5479 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5479 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5480 t += _(' (clean)')
5480 t += _(' (clean)')
5481 cleanworkdir = True
5481 cleanworkdir = True
5482 elif pnode not in bheads:
5482 elif pnode not in bheads:
5483 t += _(' (new branch head)')
5483 t += _(' (new branch head)')
5484
5484
5485 if cleanworkdir:
5485 if cleanworkdir:
5486 # i18n: column positioning for "hg summary"
5486 # i18n: column positioning for "hg summary"
5487 ui.status(_('commit: %s\n') % t.strip())
5487 ui.status(_('commit: %s\n') % t.strip())
5488 else:
5488 else:
5489 # i18n: column positioning for "hg summary"
5489 # i18n: column positioning for "hg summary"
5490 ui.write(_('commit: %s\n') % t.strip())
5490 ui.write(_('commit: %s\n') % t.strip())
5491
5491
5492 # all ancestors of branch heads - all ancestors of parent = new csets
5492 # all ancestors of branch heads - all ancestors of parent = new csets
5493 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5493 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5494 bheads))
5494 bheads))
5495
5495
5496 if new == 0:
5496 if new == 0:
5497 # i18n: column positioning for "hg summary"
5497 # i18n: column positioning for "hg summary"
5498 ui.status(_('update: (current)\n'))
5498 ui.status(_('update: (current)\n'))
5499 elif pnode not in bheads:
5499 elif pnode not in bheads:
5500 # i18n: column positioning for "hg summary"
5500 # i18n: column positioning for "hg summary"
5501 ui.write(_('update: %d new changesets (update)\n') % new)
5501 ui.write(_('update: %d new changesets (update)\n') % new)
5502 else:
5502 else:
5503 # i18n: column positioning for "hg summary"
5503 # i18n: column positioning for "hg summary"
5504 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5504 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5505 (new, len(bheads)))
5505 (new, len(bheads)))
5506
5506
5507 cmdutil.summaryhooks(ui, repo)
5507 cmdutil.summaryhooks(ui, repo)
5508
5508
5509 if opts.get('remote'):
5509 if opts.get('remote'):
5510 needsincoming, needsoutgoing = True, True
5510 needsincoming, needsoutgoing = True, True
5511 else:
5511 else:
5512 needsincoming, needsoutgoing = False, False
5512 needsincoming, needsoutgoing = False, False
5513 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5513 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5514 if i:
5514 if i:
5515 needsincoming = True
5515 needsincoming = True
5516 if o:
5516 if o:
5517 needsoutgoing = True
5517 needsoutgoing = True
5518 if not needsincoming and not needsoutgoing:
5518 if not needsincoming and not needsoutgoing:
5519 return
5519 return
5520
5520
5521 def getincoming():
5521 def getincoming():
5522 source, branches = hg.parseurl(ui.expandpath('default'))
5522 source, branches = hg.parseurl(ui.expandpath('default'))
5523 sbranch = branches[0]
5523 sbranch = branches[0]
5524 try:
5524 try:
5525 other = hg.peer(repo, {}, source)
5525 other = hg.peer(repo, {}, source)
5526 except error.RepoError:
5526 except error.RepoError:
5527 if opts.get('remote'):
5527 if opts.get('remote'):
5528 raise
5528 raise
5529 return source, sbranch, None, None, None
5529 return source, sbranch, None, None, None
5530 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5530 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5531 if revs:
5531 if revs:
5532 revs = [other.lookup(rev) for rev in revs]
5532 revs = [other.lookup(rev) for rev in revs]
5533 ui.debug('comparing with %s\n' % util.hidepassword(source))
5533 ui.debug('comparing with %s\n' % util.hidepassword(source))
5534 repo.ui.pushbuffer()
5534 repo.ui.pushbuffer()
5535 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5535 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5536 repo.ui.popbuffer()
5536 repo.ui.popbuffer()
5537 return source, sbranch, other, commoninc, commoninc[1]
5537 return source, sbranch, other, commoninc, commoninc[1]
5538
5538
5539 if needsincoming:
5539 if needsincoming:
5540 source, sbranch, sother, commoninc, incoming = getincoming()
5540 source, sbranch, sother, commoninc, incoming = getincoming()
5541 else:
5541 else:
5542 source = sbranch = sother = commoninc = incoming = None
5542 source = sbranch = sother = commoninc = incoming = None
5543
5543
5544 def getoutgoing():
5544 def getoutgoing():
5545 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5545 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5546 dbranch = branches[0]
5546 dbranch = branches[0]
5547 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5547 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5548 if source != dest:
5548 if source != dest:
5549 try:
5549 try:
5550 dother = hg.peer(repo, {}, dest)
5550 dother = hg.peer(repo, {}, dest)
5551 except error.RepoError:
5551 except error.RepoError:
5552 if opts.get('remote'):
5552 if opts.get('remote'):
5553 raise
5553 raise
5554 return dest, dbranch, None, None
5554 return dest, dbranch, None, None
5555 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5555 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5556 elif sother is None:
5556 elif sother is None:
5557 # there is no explicit destination peer, but source one is invalid
5557 # there is no explicit destination peer, but source one is invalid
5558 return dest, dbranch, None, None
5558 return dest, dbranch, None, None
5559 else:
5559 else:
5560 dother = sother
5560 dother = sother
5561 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5561 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5562 common = None
5562 common = None
5563 else:
5563 else:
5564 common = commoninc
5564 common = commoninc
5565 if revs:
5565 if revs:
5566 revs = [repo.lookup(rev) for rev in revs]
5566 revs = [repo.lookup(rev) for rev in revs]
5567 repo.ui.pushbuffer()
5567 repo.ui.pushbuffer()
5568 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5568 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5569 commoninc=common)
5569 commoninc=common)
5570 repo.ui.popbuffer()
5570 repo.ui.popbuffer()
5571 return dest, dbranch, dother, outgoing
5571 return dest, dbranch, dother, outgoing
5572
5572
5573 if needsoutgoing:
5573 if needsoutgoing:
5574 dest, dbranch, dother, outgoing = getoutgoing()
5574 dest, dbranch, dother, outgoing = getoutgoing()
5575 else:
5575 else:
5576 dest = dbranch = dother = outgoing = None
5576 dest = dbranch = dother = outgoing = None
5577
5577
5578 if opts.get('remote'):
5578 if opts.get('remote'):
5579 t = []
5579 t = []
5580 if incoming:
5580 if incoming:
5581 t.append(_('1 or more incoming'))
5581 t.append(_('1 or more incoming'))
5582 o = outgoing.missing
5582 o = outgoing.missing
5583 if o:
5583 if o:
5584 t.append(_('%d outgoing') % len(o))
5584 t.append(_('%d outgoing') % len(o))
5585 other = dother or sother
5585 other = dother or sother
5586 if 'bookmarks' in other.listkeys('namespaces'):
5586 if 'bookmarks' in other.listkeys('namespaces'):
5587 lmarks = repo.listkeys('bookmarks')
5587 lmarks = repo.listkeys('bookmarks')
5588 rmarks = other.listkeys('bookmarks')
5588 rmarks = other.listkeys('bookmarks')
5589 diff = set(rmarks) - set(lmarks)
5589 diff = set(rmarks) - set(lmarks)
5590 if len(diff) > 0:
5590 if len(diff) > 0:
5591 t.append(_('%d incoming bookmarks') % len(diff))
5591 t.append(_('%d incoming bookmarks') % len(diff))
5592 diff = set(lmarks) - set(rmarks)
5592 diff = set(lmarks) - set(rmarks)
5593 if len(diff) > 0:
5593 if len(diff) > 0:
5594 t.append(_('%d outgoing bookmarks') % len(diff))
5594 t.append(_('%d outgoing bookmarks') % len(diff))
5595
5595
5596 if t:
5596 if t:
5597 # i18n: column positioning for "hg summary"
5597 # i18n: column positioning for "hg summary"
5598 ui.write(_('remote: %s\n') % (', '.join(t)))
5598 ui.write(_('remote: %s\n') % (', '.join(t)))
5599 else:
5599 else:
5600 # i18n: column positioning for "hg summary"
5600 # i18n: column positioning for "hg summary"
5601 ui.status(_('remote: (synced)\n'))
5601 ui.status(_('remote: (synced)\n'))
5602
5602
5603 cmdutil.summaryremotehooks(ui, repo, opts,
5603 cmdutil.summaryremotehooks(ui, repo, opts,
5604 ((source, sbranch, sother, commoninc),
5604 ((source, sbranch, sother, commoninc),
5605 (dest, dbranch, dother, outgoing)))
5605 (dest, dbranch, dother, outgoing)))
5606
5606
5607 @command('tag',
5607 @command('tag',
5608 [('f', 'force', None, _('force tag')),
5608 [('f', 'force', None, _('force tag')),
5609 ('l', 'local', None, _('make the tag local')),
5609 ('l', 'local', None, _('make the tag local')),
5610 ('r', 'rev', '', _('revision to tag'), _('REV')),
5610 ('r', 'rev', '', _('revision to tag'), _('REV')),
5611 ('', 'remove', None, _('remove a tag')),
5611 ('', 'remove', None, _('remove a tag')),
5612 # -l/--local is already there, commitopts cannot be used
5612 # -l/--local is already there, commitopts cannot be used
5613 ('e', 'edit', None, _('edit commit message')),
5613 ('e', 'edit', None, _('edit commit message')),
5614 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5614 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5615 ] + commitopts2,
5615 ] + commitopts2,
5616 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5616 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5617 def tag(ui, repo, name1, *names, **opts):
5617 def tag(ui, repo, name1, *names, **opts):
5618 """add one or more tags for the current or given revision
5618 """add one or more tags for the current or given revision
5619
5619
5620 Name a particular revision using <name>.
5620 Name a particular revision using <name>.
5621
5621
5622 Tags are used to name particular revisions of the repository and are
5622 Tags are used to name particular revisions of the repository and are
5623 very useful to compare different revisions, to go back to significant
5623 very useful to compare different revisions, to go back to significant
5624 earlier versions or to mark branch points as releases, etc. Changing
5624 earlier versions or to mark branch points as releases, etc. Changing
5625 an existing tag is normally disallowed; use -f/--force to override.
5625 an existing tag is normally disallowed; use -f/--force to override.
5626
5626
5627 If no revision is given, the parent of the working directory is
5627 If no revision is given, the parent of the working directory is
5628 used.
5628 used.
5629
5629
5630 To facilitate version control, distribution, and merging of tags,
5630 To facilitate version control, distribution, and merging of tags,
5631 they are stored as a file named ".hgtags" which is managed similarly
5631 they are stored as a file named ".hgtags" which is managed similarly
5632 to other project files and can be hand-edited if necessary. This
5632 to other project files and can be hand-edited if necessary. This
5633 also means that tagging creates a new commit. The file
5633 also means that tagging creates a new commit. The file
5634 ".hg/localtags" is used for local tags (not shared among
5634 ".hg/localtags" is used for local tags (not shared among
5635 repositories).
5635 repositories).
5636
5636
5637 Tag commits are usually made at the head of a branch. If the parent
5637 Tag commits are usually made at the head of a branch. If the parent
5638 of the working directory is not a branch head, :hg:`tag` aborts; use
5638 of the working directory is not a branch head, :hg:`tag` aborts; use
5639 -f/--force to force the tag commit to be based on a non-head
5639 -f/--force to force the tag commit to be based on a non-head
5640 changeset.
5640 changeset.
5641
5641
5642 See :hg:`help dates` for a list of formats valid for -d/--date.
5642 See :hg:`help dates` for a list of formats valid for -d/--date.
5643
5643
5644 Since tag names have priority over branch names during revision
5644 Since tag names have priority over branch names during revision
5645 lookup, using an existing branch name as a tag name is discouraged.
5645 lookup, using an existing branch name as a tag name is discouraged.
5646
5646
5647 Returns 0 on success.
5647 Returns 0 on success.
5648 """
5648 """
5649 wlock = lock = None
5649 wlock = lock = None
5650 try:
5650 try:
5651 wlock = repo.wlock()
5651 wlock = repo.wlock()
5652 lock = repo.lock()
5652 lock = repo.lock()
5653 rev_ = "."
5653 rev_ = "."
5654 names = [t.strip() for t in (name1,) + names]
5654 names = [t.strip() for t in (name1,) + names]
5655 if len(names) != len(set(names)):
5655 if len(names) != len(set(names)):
5656 raise util.Abort(_('tag names must be unique'))
5656 raise util.Abort(_('tag names must be unique'))
5657 for n in names:
5657 for n in names:
5658 scmutil.checknewlabel(repo, n, 'tag')
5658 scmutil.checknewlabel(repo, n, 'tag')
5659 if not n:
5659 if not n:
5660 raise util.Abort(_('tag names cannot consist entirely of '
5660 raise util.Abort(_('tag names cannot consist entirely of '
5661 'whitespace'))
5661 'whitespace'))
5662 if opts.get('rev') and opts.get('remove'):
5662 if opts.get('rev') and opts.get('remove'):
5663 raise util.Abort(_("--rev and --remove are incompatible"))
5663 raise util.Abort(_("--rev and --remove are incompatible"))
5664 if opts.get('rev'):
5664 if opts.get('rev'):
5665 rev_ = opts['rev']
5665 rev_ = opts['rev']
5666 message = opts.get('message')
5666 message = opts.get('message')
5667 if opts.get('remove'):
5667 if opts.get('remove'):
5668 expectedtype = opts.get('local') and 'local' or 'global'
5668 expectedtype = opts.get('local') and 'local' or 'global'
5669 for n in names:
5669 for n in names:
5670 if not repo.tagtype(n):
5670 if not repo.tagtype(n):
5671 raise util.Abort(_("tag '%s' does not exist") % n)
5671 raise util.Abort(_("tag '%s' does not exist") % n)
5672 if repo.tagtype(n) != expectedtype:
5672 if repo.tagtype(n) != expectedtype:
5673 if expectedtype == 'global':
5673 if expectedtype == 'global':
5674 raise util.Abort(_("tag '%s' is not a global tag") % n)
5674 raise util.Abort(_("tag '%s' is not a global tag") % n)
5675 else:
5675 else:
5676 raise util.Abort(_("tag '%s' is not a local tag") % n)
5676 raise util.Abort(_("tag '%s' is not a local tag") % n)
5677 rev_ = nullid
5677 rev_ = nullid
5678 if not message:
5678 if not message:
5679 # we don't translate commit messages
5679 # we don't translate commit messages
5680 message = 'Removed tag %s' % ', '.join(names)
5680 message = 'Removed tag %s' % ', '.join(names)
5681 elif not opts.get('force'):
5681 elif not opts.get('force'):
5682 for n in names:
5682 for n in names:
5683 if n in repo.tags():
5683 if n in repo.tags():
5684 raise util.Abort(_("tag '%s' already exists "
5684 raise util.Abort(_("tag '%s' already exists "
5685 "(use -f to force)") % n)
5685 "(use -f to force)") % n)
5686 if not opts.get('local'):
5686 if not opts.get('local'):
5687 p1, p2 = repo.dirstate.parents()
5687 p1, p2 = repo.dirstate.parents()
5688 if p2 != nullid:
5688 if p2 != nullid:
5689 raise util.Abort(_('uncommitted merge'))
5689 raise util.Abort(_('uncommitted merge'))
5690 bheads = repo.branchheads()
5690 bheads = repo.branchheads()
5691 if not opts.get('force') and bheads and p1 not in bheads:
5691 if not opts.get('force') and bheads and p1 not in bheads:
5692 raise util.Abort(_('not at a branch head (use -f to force)'))
5692 raise util.Abort(_('not at a branch head (use -f to force)'))
5693 r = scmutil.revsingle(repo, rev_).node()
5693 r = scmutil.revsingle(repo, rev_).node()
5694
5694
5695 if not message:
5695 if not message:
5696 # we don't translate commit messages
5696 # we don't translate commit messages
5697 message = ('Added tag %s for changeset %s' %
5697 message = ('Added tag %s for changeset %s' %
5698 (', '.join(names), short(r)))
5698 (', '.join(names), short(r)))
5699
5699
5700 date = opts.get('date')
5700 date = opts.get('date')
5701 if date:
5701 if date:
5702 date = util.parsedate(date)
5702 date = util.parsedate(date)
5703
5703
5704 if opts.get('edit'):
5704 if opts.get('edit'):
5705 def editor(repo, ctx, subs):
5705 def editor(repo, ctx, subs):
5706 return ui.edit(ctx.description() + "\n", ctx.user())
5706 return ui.edit(ctx.description() + "\n", ctx.user())
5707 else:
5707 else:
5708 editor = False
5708 editor = False
5709
5709
5710 # don't allow tagging the null rev
5710 # don't allow tagging the null rev
5711 if (not opts.get('remove') and
5711 if (not opts.get('remove') and
5712 scmutil.revsingle(repo, rev_).rev() == nullrev):
5712 scmutil.revsingle(repo, rev_).rev() == nullrev):
5713 raise util.Abort(_("cannot tag null revision"))
5713 raise util.Abort(_("cannot tag null revision"))
5714
5714
5715 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5715 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5716 editor=editor)
5716 editor=editor)
5717 finally:
5717 finally:
5718 release(lock, wlock)
5718 release(lock, wlock)
5719
5719
5720 @command('tags', [], '')
5720 @command('tags', [], '')
5721 def tags(ui, repo, **opts):
5721 def tags(ui, repo, **opts):
5722 """list repository tags
5722 """list repository tags
5723
5723
5724 This lists both regular and local tags. When the -v/--verbose
5724 This lists both regular and local tags. When the -v/--verbose
5725 switch is used, a third column "local" is printed for local tags.
5725 switch is used, a third column "local" is printed for local tags.
5726
5726
5727 Returns 0 on success.
5727 Returns 0 on success.
5728 """
5728 """
5729
5729
5730 fm = ui.formatter('tags', opts)
5730 fm = ui.formatter('tags', opts)
5731 hexfunc = ui.debugflag and hex or short
5731 hexfunc = ui.debugflag and hex or short
5732 tagtype = ""
5732 tagtype = ""
5733
5733
5734 for t, n in reversed(repo.tagslist()):
5734 for t, n in reversed(repo.tagslist()):
5735 hn = hexfunc(n)
5735 hn = hexfunc(n)
5736 label = 'tags.normal'
5736 label = 'tags.normal'
5737 tagtype = ''
5737 tagtype = ''
5738 if repo.tagtype(t) == 'local':
5738 if repo.tagtype(t) == 'local':
5739 label = 'tags.local'
5739 label = 'tags.local'
5740 tagtype = 'local'
5740 tagtype = 'local'
5741
5741
5742 fm.startitem()
5742 fm.startitem()
5743 fm.write('tag', '%s', t, label=label)
5743 fm.write('tag', '%s', t, label=label)
5744 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5744 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5745 fm.condwrite(not ui.quiet, 'rev id', fmt,
5745 fm.condwrite(not ui.quiet, 'rev id', fmt,
5746 repo.changelog.rev(n), hn, label=label)
5746 repo.changelog.rev(n), hn, label=label)
5747 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5747 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5748 tagtype, label=label)
5748 tagtype, label=label)
5749 fm.plain('\n')
5749 fm.plain('\n')
5750 fm.end()
5750 fm.end()
5751
5751
5752 @command('tip',
5752 @command('tip',
5753 [('p', 'patch', None, _('show patch')),
5753 [('p', 'patch', None, _('show patch')),
5754 ('g', 'git', None, _('use git extended diff format')),
5754 ('g', 'git', None, _('use git extended diff format')),
5755 ] + templateopts,
5755 ] + templateopts,
5756 _('[-p] [-g]'))
5756 _('[-p] [-g]'))
5757 def tip(ui, repo, **opts):
5757 def tip(ui, repo, **opts):
5758 """show the tip revision (DEPRECATED)
5758 """show the tip revision (DEPRECATED)
5759
5759
5760 The tip revision (usually just called the tip) is the changeset
5760 The tip revision (usually just called the tip) is the changeset
5761 most recently added to the repository (and therefore the most
5761 most recently added to the repository (and therefore the most
5762 recently changed head).
5762 recently changed head).
5763
5763
5764 If you have just made a commit, that commit will be the tip. If
5764 If you have just made a commit, that commit will be the tip. If
5765 you have just pulled changes from another repository, the tip of
5765 you have just pulled changes from another repository, the tip of
5766 that repository becomes the current tip. The "tip" tag is special
5766 that repository becomes the current tip. The "tip" tag is special
5767 and cannot be renamed or assigned to a different changeset.
5767 and cannot be renamed or assigned to a different changeset.
5768
5768
5769 This command is deprecated, please use :hg:`heads` instead.
5769 This command is deprecated, please use :hg:`heads` instead.
5770
5770
5771 Returns 0 on success.
5771 Returns 0 on success.
5772 """
5772 """
5773 displayer = cmdutil.show_changeset(ui, repo, opts)
5773 displayer = cmdutil.show_changeset(ui, repo, opts)
5774 displayer.show(repo['tip'])
5774 displayer.show(repo['tip'])
5775 displayer.close()
5775 displayer.close()
5776
5776
5777 @command('unbundle',
5777 @command('unbundle',
5778 [('u', 'update', None,
5778 [('u', 'update', None,
5779 _('update to new branch head if changesets were unbundled'))],
5779 _('update to new branch head if changesets were unbundled'))],
5780 _('[-u] FILE...'))
5780 _('[-u] FILE...'))
5781 def unbundle(ui, repo, fname1, *fnames, **opts):
5781 def unbundle(ui, repo, fname1, *fnames, **opts):
5782 """apply one or more changegroup files
5782 """apply one or more changegroup files
5783
5783
5784 Apply one or more compressed changegroup files generated by the
5784 Apply one or more compressed changegroup files generated by the
5785 bundle command.
5785 bundle command.
5786
5786
5787 Returns 0 on success, 1 if an update has unresolved files.
5787 Returns 0 on success, 1 if an update has unresolved files.
5788 """
5788 """
5789 fnames = (fname1,) + fnames
5789 fnames = (fname1,) + fnames
5790
5790
5791 lock = repo.lock()
5791 lock = repo.lock()
5792 wc = repo['.']
5792 wc = repo['.']
5793 try:
5793 try:
5794 for fname in fnames:
5794 for fname in fnames:
5795 f = hg.openpath(ui, fname)
5795 f = hg.openpath(ui, fname)
5796 gen = exchange.readbundle(ui, f, fname)
5796 gen = exchange.readbundle(ui, f, fname)
5797 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5797 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5798 'bundle:' + fname)
5798 'bundle:' + fname)
5799 finally:
5799 finally:
5800 lock.release()
5800 lock.release()
5801 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5801 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5802 return postincoming(ui, repo, modheads, opts.get('update'), None)
5802 return postincoming(ui, repo, modheads, opts.get('update'), None)
5803
5803
5804 @command('^update|up|checkout|co',
5804 @command('^update|up|checkout|co',
5805 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5805 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5806 ('c', 'check', None,
5806 ('c', 'check', None,
5807 _('update across branches if no uncommitted changes')),
5807 _('update across branches if no uncommitted changes')),
5808 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5808 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5809 ('r', 'rev', '', _('revision'), _('REV'))],
5809 ('r', 'rev', '', _('revision'), _('REV'))],
5810 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5810 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5811 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5811 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5812 """update working directory (or switch revisions)
5812 """update working directory (or switch revisions)
5813
5813
5814 Update the repository's working directory to the specified
5814 Update the repository's working directory to the specified
5815 changeset. If no changeset is specified, update to the tip of the
5815 changeset. If no changeset is specified, update to the tip of the
5816 current named branch and move the current bookmark (see :hg:`help
5816 current named branch and move the current bookmark (see :hg:`help
5817 bookmarks`).
5817 bookmarks`).
5818
5818
5819 Update sets the working directory's parent revision to the specified
5819 Update sets the working directory's parent revision to the specified
5820 changeset (see :hg:`help parents`).
5820 changeset (see :hg:`help parents`).
5821
5821
5822 If the changeset is not a descendant or ancestor of the working
5822 If the changeset is not a descendant or ancestor of the working
5823 directory's parent, the update is aborted. With the -c/--check
5823 directory's parent, the update is aborted. With the -c/--check
5824 option, the working directory is checked for uncommitted changes; if
5824 option, the working directory is checked for uncommitted changes; if
5825 none are found, the working directory is updated to the specified
5825 none are found, the working directory is updated to the specified
5826 changeset.
5826 changeset.
5827
5827
5828 .. container:: verbose
5828 .. container:: verbose
5829
5829
5830 The following rules apply when the working directory contains
5830 The following rules apply when the working directory contains
5831 uncommitted changes:
5831 uncommitted changes:
5832
5832
5833 1. If neither -c/--check nor -C/--clean is specified, and if
5833 1. If neither -c/--check nor -C/--clean is specified, and if
5834 the requested changeset is an ancestor or descendant of
5834 the requested changeset is an ancestor or descendant of
5835 the working directory's parent, the uncommitted changes
5835 the working directory's parent, the uncommitted changes
5836 are merged into the requested changeset and the merged
5836 are merged into the requested changeset and the merged
5837 result is left uncommitted. If the requested changeset is
5837 result is left uncommitted. If the requested changeset is
5838 not an ancestor or descendant (that is, it is on another
5838 not an ancestor or descendant (that is, it is on another
5839 branch), the update is aborted and the uncommitted changes
5839 branch), the update is aborted and the uncommitted changes
5840 are preserved.
5840 are preserved.
5841
5841
5842 2. With the -c/--check option, the update is aborted and the
5842 2. With the -c/--check option, the update is aborted and the
5843 uncommitted changes are preserved.
5843 uncommitted changes are preserved.
5844
5844
5845 3. With the -C/--clean option, uncommitted changes are discarded and
5845 3. With the -C/--clean option, uncommitted changes are discarded and
5846 the working directory is updated to the requested changeset.
5846 the working directory is updated to the requested changeset.
5847
5847
5848 To cancel an uncommitted merge (and lose your changes), use
5848 To cancel an uncommitted merge (and lose your changes), use
5849 :hg:`update --clean .`.
5849 :hg:`update --clean .`.
5850
5850
5851 Use null as the changeset to remove the working directory (like
5851 Use null as the changeset to remove the working directory (like
5852 :hg:`clone -U`).
5852 :hg:`clone -U`).
5853
5853
5854 If you want to revert just one file to an older revision, use
5854 If you want to revert just one file to an older revision, use
5855 :hg:`revert [-r REV] NAME`.
5855 :hg:`revert [-r REV] NAME`.
5856
5856
5857 See :hg:`help dates` for a list of formats valid for -d/--date.
5857 See :hg:`help dates` for a list of formats valid for -d/--date.
5858
5858
5859 Returns 0 on success, 1 if there are unresolved files.
5859 Returns 0 on success, 1 if there are unresolved files.
5860 """
5860 """
5861 if rev and node:
5861 if rev and node:
5862 raise util.Abort(_("please specify just one revision"))
5862 raise util.Abort(_("please specify just one revision"))
5863
5863
5864 if rev is None or rev == '':
5864 if rev is None or rev == '':
5865 rev = node
5865 rev = node
5866
5866
5867 cmdutil.clearunfinished(repo)
5867 cmdutil.clearunfinished(repo)
5868
5868
5869 # with no argument, we also move the current bookmark, if any
5869 # with no argument, we also move the current bookmark, if any
5870 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5870 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5871
5871
5872 # if we defined a bookmark, we have to remember the original bookmark name
5872 # if we defined a bookmark, we have to remember the original bookmark name
5873 brev = rev
5873 brev = rev
5874 rev = scmutil.revsingle(repo, rev, rev).rev()
5874 rev = scmutil.revsingle(repo, rev, rev).rev()
5875
5875
5876 if check and clean:
5876 if check and clean:
5877 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5877 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5878
5878
5879 if date:
5879 if date:
5880 if rev is not None:
5880 if rev is not None:
5881 raise util.Abort(_("you can't specify a revision and a date"))
5881 raise util.Abort(_("you can't specify a revision and a date"))
5882 rev = cmdutil.finddate(ui, repo, date)
5882 rev = cmdutil.finddate(ui, repo, date)
5883
5883
5884 if check:
5884 if check:
5885 c = repo[None]
5885 c = repo[None]
5886 if c.dirty(merge=False, branch=False, missing=True):
5886 if c.dirty(merge=False, branch=False, missing=True):
5887 raise util.Abort(_("uncommitted changes"))
5887 raise util.Abort(_("uncommitted changes"))
5888 if rev is None:
5888 if rev is None:
5889 rev = repo[repo[None].branch()].rev()
5889 rev = repo[repo[None].branch()].rev()
5890 mergemod._checkunknown(repo, repo[None], repo[rev])
5890 mergemod._checkunknown(repo, repo[None], repo[rev])
5891
5891
5892 if clean:
5892 if clean:
5893 ret = hg.clean(repo, rev)
5893 ret = hg.clean(repo, rev)
5894 else:
5894 else:
5895 ret = hg.update(repo, rev)
5895 ret = hg.update(repo, rev)
5896
5896
5897 if not ret and movemarkfrom:
5897 if not ret and movemarkfrom:
5898 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5898 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5899 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5899 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5900 elif brev in repo._bookmarks:
5900 elif brev in repo._bookmarks:
5901 bookmarks.setcurrent(repo, brev)
5901 bookmarks.setcurrent(repo, brev)
5902 elif brev:
5902 elif brev:
5903 if repo._bookmarkcurrent:
5903 if repo._bookmarkcurrent:
5904 ui.status(_("(leaving bookmark %s)\n") %
5904 ui.status(_("(leaving bookmark %s)\n") %
5905 repo._bookmarkcurrent)
5905 repo._bookmarkcurrent)
5906 bookmarks.unsetcurrent(repo)
5906 bookmarks.unsetcurrent(repo)
5907
5907
5908 return ret
5908 return ret
5909
5909
5910 @command('verify', [])
5910 @command('verify', [])
5911 def verify(ui, repo):
5911 def verify(ui, repo):
5912 """verify the integrity of the repository
5912 """verify the integrity of the repository
5913
5913
5914 Verify the integrity of the current repository.
5914 Verify the integrity of the current repository.
5915
5915
5916 This will perform an extensive check of the repository's
5916 This will perform an extensive check of the repository's
5917 integrity, validating the hashes and checksums of each entry in
5917 integrity, validating the hashes and checksums of each entry in
5918 the changelog, manifest, and tracked files, as well as the
5918 the changelog, manifest, and tracked files, as well as the
5919 integrity of their crosslinks and indices.
5919 integrity of their crosslinks and indices.
5920
5920
5921 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5921 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5922 for more information about recovery from corruption of the
5922 for more information about recovery from corruption of the
5923 repository.
5923 repository.
5924
5924
5925 Returns 0 on success, 1 if errors are encountered.
5925 Returns 0 on success, 1 if errors are encountered.
5926 """
5926 """
5927 return hg.verify(repo)
5927 return hg.verify(repo)
5928
5928
5929 @command('version', [])
5929 @command('version', [])
5930 def version_(ui):
5930 def version_(ui):
5931 """output version and copyright information"""
5931 """output version and copyright information"""
5932 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5932 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5933 % util.version())
5933 % util.version())
5934 ui.status(_(
5934 ui.status(_(
5935 "(see http://mercurial.selenic.com for more information)\n"
5935 "(see http://mercurial.selenic.com for more information)\n"
5936 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5936 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5937 "This is free software; see the source for copying conditions. "
5937 "This is free software; see the source for copying conditions. "
5938 "There is NO\nwarranty; "
5938 "There is NO\nwarranty; "
5939 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5939 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5940 ))
5940 ))
5941
5941
5942 norepo = ("clone init version help debugcommands debugcomplete"
5942 norepo = ("clone init version help debugcommands debugcomplete"
5943 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5943 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5944 " debugknown debuggetbundle debugbundle")
5944 " debugknown debuggetbundle debugbundle")
5945 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5945 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5946 " debugdata debugindex debugindexdot debugrevlog")
5946 " debugdata debugindex debugindexdot debugrevlog")
5947 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5947 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5948 " remove resolve status debugwalk")
5948 " remove resolve status debugwalk")
@@ -1,517 +1,532 b''
1 $ hg init basic
1 $ hg init basic
2 $ cd basic
2 $ cd basic
3
3
4 should complain
4 should complain
5
5
6 $ hg backout
6 $ hg backout
7 abort: please specify a revision to backout
7 abort: please specify a revision to backout
8 [255]
8 [255]
9 $ hg backout -r 0 0
9 $ hg backout -r 0 0
10 abort: please specify just one revision
10 abort: please specify just one revision
11 [255]
11 [255]
12
12
13 basic operation
13 basic operation
14 (this also tests that editor is invoked if the commit message is not
15 specified explicitly)
14
16
15 $ echo a > a
17 $ echo a > a
16 $ hg commit -d '0 0' -A -m a
18 $ hg commit -d '0 0' -A -m a
17 adding a
19 adding a
18 $ echo b >> a
20 $ echo b >> a
19 $ hg commit -d '1 0' -m b
21 $ hg commit -d '1 0' -m b
20
22
21 $ hg backout -d '2 0' tip --tool=true
23 $ hg status --rev tip --rev "tip^1"
24 M a
25 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true
22 reverting a
26 reverting a
27 Backed out changeset a820f4f40a57
28
29
30 HG: Enter commit message. Lines beginning with 'HG:' are removed.
31 HG: Leave message empty to abort commit.
32 HG: --
33 HG: user: test
34 HG: branch 'default'
35 HG: changed a
23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
36 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
24 $ cat a
37 $ cat a
25 a
38 a
26 $ hg summary
39 $ hg summary
27 parent: 2:2929462c3dff tip
40 parent: 2:2929462c3dff tip
28 Backed out changeset a820f4f40a57
41 Backed out changeset a820f4f40a57
29 branch: default
42 branch: default
30 commit: (clean)
43 commit: (clean)
31 update: (current)
44 update: (current)
32
45
33 file that was removed is recreated
46 file that was removed is recreated
47 (this also tests that editor is not invoked if the commit message is
48 specified explicitly)
34
49
35 $ cd ..
50 $ cd ..
36 $ hg init remove
51 $ hg init remove
37 $ cd remove
52 $ cd remove
38
53
39 $ echo content > a
54 $ echo content > a
40 $ hg commit -d '0 0' -A -m a
55 $ hg commit -d '0 0' -A -m a
41 adding a
56 adding a
42
57
43 $ hg rm a
58 $ hg rm a
44 $ hg commit -d '1 0' -m b
59 $ hg commit -d '1 0' -m b
45
60
46 $ hg backout -d '2 0' tip --tool=true
61 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true -m "Backed out changeset 76862dcce372"
47 adding a
62 adding a
48 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
63 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
49 $ cat a
64 $ cat a
50 content
65 content
51 $ hg summary
66 $ hg summary
52 parent: 2:de31bdc76c0d tip
67 parent: 2:de31bdc76c0d tip
53 Backed out changeset 76862dcce372
68 Backed out changeset 76862dcce372
54 branch: default
69 branch: default
55 commit: (clean)
70 commit: (clean)
56 update: (current)
71 update: (current)
57
72
58 backout of backout is as if nothing happened
73 backout of backout is as if nothing happened
59
74
60 $ hg backout -d '3 0' --merge tip --tool=true
75 $ hg backout -d '3 0' --merge tip --tool=true
61 removing a
76 removing a
62 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
77 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
63 $ test -f a
78 $ test -f a
64 [1]
79 [1]
65 $ hg summary
80 $ hg summary
66 parent: 3:7f6d0f120113 tip
81 parent: 3:7f6d0f120113 tip
67 Backed out changeset de31bdc76c0d
82 Backed out changeset de31bdc76c0d
68 branch: default
83 branch: default
69 commit: (clean)
84 commit: (clean)
70 update: (current)
85 update: (current)
71
86
72 across branch
87 across branch
73
88
74 $ cd ..
89 $ cd ..
75 $ hg init branch
90 $ hg init branch
76 $ cd branch
91 $ cd branch
77 $ echo a > a
92 $ echo a > a
78 $ hg ci -Am0
93 $ hg ci -Am0
79 adding a
94 adding a
80 $ echo b > b
95 $ echo b > b
81 $ hg ci -Am1
96 $ hg ci -Am1
82 adding b
97 adding b
83 $ hg co -C 0
98 $ hg co -C 0
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
99 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ hg summary
100 $ hg summary
86 parent: 0:f7b1eb17ad24
101 parent: 0:f7b1eb17ad24
87 0
102 0
88 branch: default
103 branch: default
89 commit: (clean)
104 commit: (clean)
90 update: 1 new changesets (update)
105 update: 1 new changesets (update)
91
106
92 should fail
107 should fail
93
108
94 $ hg backout 1
109 $ hg backout 1
95 abort: cannot backout change that is not an ancestor
110 abort: cannot backout change that is not an ancestor
96 [255]
111 [255]
97 $ echo c > c
112 $ echo c > c
98 $ hg ci -Am2
113 $ hg ci -Am2
99 adding c
114 adding c
100 created new head
115 created new head
101 $ hg summary
116 $ hg summary
102 parent: 2:db815d6d32e6 tip
117 parent: 2:db815d6d32e6 tip
103 2
118 2
104 branch: default
119 branch: default
105 commit: (clean)
120 commit: (clean)
106 update: 1 new changesets, 2 branch heads (merge)
121 update: 1 new changesets, 2 branch heads (merge)
107
122
108 should fail
123 should fail
109
124
110 $ hg backout 1
125 $ hg backout 1
111 abort: cannot backout change that is not an ancestor
126 abort: cannot backout change that is not an ancestor
112 [255]
127 [255]
113 $ hg summary
128 $ hg summary
114 parent: 2:db815d6d32e6 tip
129 parent: 2:db815d6d32e6 tip
115 2
130 2
116 branch: default
131 branch: default
117 commit: (clean)
132 commit: (clean)
118 update: 1 new changesets, 2 branch heads (merge)
133 update: 1 new changesets, 2 branch heads (merge)
119
134
120 backout with merge
135 backout with merge
121
136
122 $ cd ..
137 $ cd ..
123 $ hg init merge
138 $ hg init merge
124 $ cd merge
139 $ cd merge
125
140
126 $ echo line 1 > a
141 $ echo line 1 > a
127 $ echo line 2 >> a
142 $ echo line 2 >> a
128 $ hg commit -d '0 0' -A -m a
143 $ hg commit -d '0 0' -A -m a
129 adding a
144 adding a
130 $ hg summary
145 $ hg summary
131 parent: 0:59395513a13a tip
146 parent: 0:59395513a13a tip
132 a
147 a
133 branch: default
148 branch: default
134 commit: (clean)
149 commit: (clean)
135 update: (current)
150 update: (current)
136
151
137 remove line 1
152 remove line 1
138
153
139 $ echo line 2 > a
154 $ echo line 2 > a
140 $ hg commit -d '1 0' -m b
155 $ hg commit -d '1 0' -m b
141
156
142 $ echo line 3 >> a
157 $ echo line 3 >> a
143 $ hg commit -d '2 0' -m c
158 $ hg commit -d '2 0' -m c
144
159
145 $ hg backout --merge -d '3 0' 1 --tool=true
160 $ hg backout --merge -d '3 0' 1 --tool=true
146 reverting a
161 reverting a
147 created new head
162 created new head
148 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
163 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
149 merging with changeset 3:26b8ccb9ad91
164 merging with changeset 3:26b8ccb9ad91
150 merging a
165 merging a
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
166 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
152 (branch merge, don't forget to commit)
167 (branch merge, don't forget to commit)
153 $ hg commit -d '4 0' -m d
168 $ hg commit -d '4 0' -m d
154 $ hg summary
169 $ hg summary
155 parent: 4:c7df5e0b9c09 tip
170 parent: 4:c7df5e0b9c09 tip
156 d
171 d
157 branch: default
172 branch: default
158 commit: (clean)
173 commit: (clean)
159 update: (current)
174 update: (current)
160
175
161 check line 1 is back
176 check line 1 is back
162
177
163 $ cat a
178 $ cat a
164 line 1
179 line 1
165 line 2
180 line 2
166 line 3
181 line 3
167
182
168 $ cd ..
183 $ cd ..
169
184
170 backout should not back out subsequent changesets
185 backout should not back out subsequent changesets
171
186
172 $ hg init onecs
187 $ hg init onecs
173 $ cd onecs
188 $ cd onecs
174 $ echo 1 > a
189 $ echo 1 > a
175 $ hg commit -d '0 0' -A -m a
190 $ hg commit -d '0 0' -A -m a
176 adding a
191 adding a
177 $ echo 2 >> a
192 $ echo 2 >> a
178 $ hg commit -d '1 0' -m b
193 $ hg commit -d '1 0' -m b
179 $ echo 1 > b
194 $ echo 1 > b
180 $ hg commit -d '2 0' -A -m c
195 $ hg commit -d '2 0' -A -m c
181 adding b
196 adding b
182 $ hg summary
197 $ hg summary
183 parent: 2:882396649954 tip
198 parent: 2:882396649954 tip
184 c
199 c
185 branch: default
200 branch: default
186 commit: (clean)
201 commit: (clean)
187 update: (current)
202 update: (current)
188
203
189 without --merge
204 without --merge
190 $ hg backout -d '3 0' 1 --tool=true
205 $ hg backout -d '3 0' 1 --tool=true
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 changeset 22bca4c721e5 backed out, don't forget to commit.
207 changeset 22bca4c721e5 backed out, don't forget to commit.
193 $ hg locate b
208 $ hg locate b
194 b
209 b
195 $ hg update -C tip
210 $ hg update -C tip
196 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 $ hg locate b
212 $ hg locate b
198 b
213 b
199 $ hg summary
214 $ hg summary
200 parent: 2:882396649954 tip
215 parent: 2:882396649954 tip
201 c
216 c
202 branch: default
217 branch: default
203 commit: (clean)
218 commit: (clean)
204 update: (current)
219 update: (current)
205
220
206 with --merge
221 with --merge
207 $ hg backout --merge -d '3 0' 1 --tool=true
222 $ hg backout --merge -d '3 0' 1 --tool=true
208 reverting a
223 reverting a
209 created new head
224 created new head
210 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
225 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
211 merging with changeset 3:3202beb76721
226 merging with changeset 3:3202beb76721
212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 (branch merge, don't forget to commit)
228 (branch merge, don't forget to commit)
214 $ hg locate b
229 $ hg locate b
215 b
230 b
216 $ hg update -C tip
231 $ hg update -C tip
217 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
232 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
218 $ hg locate b
233 $ hg locate b
219 [1]
234 [1]
220
235
221 $ cd ..
236 $ cd ..
222 $ hg init m
237 $ hg init m
223 $ cd m
238 $ cd m
224 $ echo a > a
239 $ echo a > a
225 $ hg commit -d '0 0' -A -m a
240 $ hg commit -d '0 0' -A -m a
226 adding a
241 adding a
227 $ echo b > b
242 $ echo b > b
228 $ hg commit -d '1 0' -A -m b
243 $ hg commit -d '1 0' -A -m b
229 adding b
244 adding b
230 $ echo c > c
245 $ echo c > c
231 $ hg commit -d '2 0' -A -m b
246 $ hg commit -d '2 0' -A -m b
232 adding c
247 adding c
233 $ hg update 1
248 $ hg update 1
234 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
249 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
235 $ echo d > d
250 $ echo d > d
236 $ hg commit -d '3 0' -A -m c
251 $ hg commit -d '3 0' -A -m c
237 adding d
252 adding d
238 created new head
253 created new head
239 $ hg merge 2
254 $ hg merge 2
240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
256 (branch merge, don't forget to commit)
242 $ hg commit -d '4 0' -A -m d
257 $ hg commit -d '4 0' -A -m d
243 $ hg summary
258 $ hg summary
244 parent: 4:b2f3bb92043e tip
259 parent: 4:b2f3bb92043e tip
245 d
260 d
246 branch: default
261 branch: default
247 commit: (clean)
262 commit: (clean)
248 update: (current)
263 update: (current)
249
264
250 backout of merge should fail
265 backout of merge should fail
251
266
252 $ hg backout 4
267 $ hg backout 4
253 abort: cannot backout a merge changeset
268 abort: cannot backout a merge changeset
254 [255]
269 [255]
255
270
256 backout of merge with bad parent should fail
271 backout of merge with bad parent should fail
257
272
258 $ hg backout --parent 0 4
273 $ hg backout --parent 0 4
259 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
274 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
260 [255]
275 [255]
261
276
262 backout of non-merge with parent should fail
277 backout of non-merge with parent should fail
263
278
264 $ hg backout --parent 0 3
279 $ hg backout --parent 0 3
265 abort: cannot use --parent on non-merge changeset
280 abort: cannot use --parent on non-merge changeset
266 [255]
281 [255]
267
282
268 backout with valid parent should be ok
283 backout with valid parent should be ok
269
284
270 $ hg backout -d '5 0' --parent 2 4 --tool=true
285 $ hg backout -d '5 0' --parent 2 4 --tool=true
271 removing d
286 removing d
272 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
287 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
273 $ hg summary
288 $ hg summary
274 parent: 5:10e5328c8435 tip
289 parent: 5:10e5328c8435 tip
275 Backed out changeset b2f3bb92043e
290 Backed out changeset b2f3bb92043e
276 branch: default
291 branch: default
277 commit: (clean)
292 commit: (clean)
278 update: (current)
293 update: (current)
279
294
280 $ hg rollback
295 $ hg rollback
281 repository tip rolled back to revision 4 (undo commit)
296 repository tip rolled back to revision 4 (undo commit)
282 working directory now based on revision 4
297 working directory now based on revision 4
283 $ hg update -C
298 $ hg update -C
284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
299 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 $ hg summary
300 $ hg summary
286 parent: 4:b2f3bb92043e tip
301 parent: 4:b2f3bb92043e tip
287 d
302 d
288 branch: default
303 branch: default
289 commit: (clean)
304 commit: (clean)
290 update: (current)
305 update: (current)
291
306
292 $ hg backout -d '6 0' --parent 3 4 --tool=true
307 $ hg backout -d '6 0' --parent 3 4 --tool=true
293 removing c
308 removing c
294 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
309 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
295 $ hg summary
310 $ hg summary
296 parent: 5:033590168430 tip
311 parent: 5:033590168430 tip
297 Backed out changeset b2f3bb92043e
312 Backed out changeset b2f3bb92043e
298 branch: default
313 branch: default
299 commit: (clean)
314 commit: (clean)
300 update: (current)
315 update: (current)
301
316
302 $ cd ..
317 $ cd ..
303
318
304 named branches
319 named branches
305
320
306 $ hg init named_branches
321 $ hg init named_branches
307 $ cd named_branches
322 $ cd named_branches
308
323
309 $ echo default > default
324 $ echo default > default
310 $ hg ci -d '0 0' -Am default
325 $ hg ci -d '0 0' -Am default
311 adding default
326 adding default
312 $ hg branch branch1
327 $ hg branch branch1
313 marked working directory as branch branch1
328 marked working directory as branch branch1
314 (branches are permanent and global, did you want a bookmark?)
329 (branches are permanent and global, did you want a bookmark?)
315 $ echo branch1 > file1
330 $ echo branch1 > file1
316 $ hg ci -d '1 0' -Am file1
331 $ hg ci -d '1 0' -Am file1
317 adding file1
332 adding file1
318 $ hg branch branch2
333 $ hg branch branch2
319 marked working directory as branch branch2
334 marked working directory as branch branch2
320 (branches are permanent and global, did you want a bookmark?)
335 (branches are permanent and global, did you want a bookmark?)
321 $ echo branch2 > file2
336 $ echo branch2 > file2
322 $ hg ci -d '2 0' -Am file2
337 $ hg ci -d '2 0' -Am file2
323 adding file2
338 adding file2
324
339
325 without --merge
340 without --merge
326 $ hg backout -r 1 --tool=true
341 $ hg backout -r 1 --tool=true
327 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
342 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
328 changeset bf1602f437f3 backed out, don't forget to commit.
343 changeset bf1602f437f3 backed out, don't forget to commit.
329 $ hg branch
344 $ hg branch
330 branch2
345 branch2
331 $ hg status -A
346 $ hg status -A
332 R file1
347 R file1
333 C default
348 C default
334 C file2
349 C file2
335 $ hg summary
350 $ hg summary
336 parent: 2:45bbcd363bf0 tip
351 parent: 2:45bbcd363bf0 tip
337 file2
352 file2
338 branch: branch2
353 branch: branch2
339 commit: 1 removed
354 commit: 1 removed
340 update: (current)
355 update: (current)
341
356
342 with --merge
357 with --merge
343 $ hg update -qC
358 $ hg update -qC
344 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
359 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
345 removing file1
360 removing file1
346 created new head
361 created new head
347 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
362 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
348 merging with changeset 3:d4e8f6db59fb
363 merging with changeset 3:d4e8f6db59fb
349 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
364 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
350 (branch merge, don't forget to commit)
365 (branch merge, don't forget to commit)
351 $ hg summary
366 $ hg summary
352 parent: 2:45bbcd363bf0
367 parent: 2:45bbcd363bf0
353 file2
368 file2
354 parent: 3:d4e8f6db59fb tip
369 parent: 3:d4e8f6db59fb tip
355 backout on branch1
370 backout on branch1
356 branch: branch2
371 branch: branch2
357 commit: 1 removed (merge)
372 commit: 1 removed (merge)
358 update: (current)
373 update: (current)
359 $ hg update -q -C 2
374 $ hg update -q -C 2
360
375
361 on branch2 with branch1 not merged, so file1 should still exist:
376 on branch2 with branch1 not merged, so file1 should still exist:
362
377
363 $ hg id
378 $ hg id
364 45bbcd363bf0 (branch2)
379 45bbcd363bf0 (branch2)
365 $ hg st -A
380 $ hg st -A
366 C default
381 C default
367 C file1
382 C file1
368 C file2
383 C file2
369 $ hg summary
384 $ hg summary
370 parent: 2:45bbcd363bf0
385 parent: 2:45bbcd363bf0
371 file2
386 file2
372 branch: branch2
387 branch: branch2
373 commit: (clean)
388 commit: (clean)
374 update: 1 new changesets, 2 branch heads (merge)
389 update: 1 new changesets, 2 branch heads (merge)
375
390
376 on branch2 with branch1 merged, so file1 should be gone:
391 on branch2 with branch1 merged, so file1 should be gone:
377
392
378 $ hg merge
393 $ hg merge
379 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
394 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
380 (branch merge, don't forget to commit)
395 (branch merge, don't forget to commit)
381 $ hg ci -d '4 0' -m 'merge backout of branch1'
396 $ hg ci -d '4 0' -m 'merge backout of branch1'
382 $ hg id
397 $ hg id
383 22149cdde76d (branch2) tip
398 22149cdde76d (branch2) tip
384 $ hg st -A
399 $ hg st -A
385 C default
400 C default
386 C file2
401 C file2
387 $ hg summary
402 $ hg summary
388 parent: 4:22149cdde76d tip
403 parent: 4:22149cdde76d tip
389 merge backout of branch1
404 merge backout of branch1
390 branch: branch2
405 branch: branch2
391 commit: (clean)
406 commit: (clean)
392 update: (current)
407 update: (current)
393
408
394 on branch1, so no file1 and file2:
409 on branch1, so no file1 and file2:
395
410
396 $ hg co -C branch1
411 $ hg co -C branch1
397 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
412 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
398 $ hg id
413 $ hg id
399 bf1602f437f3 (branch1)
414 bf1602f437f3 (branch1)
400 $ hg st -A
415 $ hg st -A
401 C default
416 C default
402 C file1
417 C file1
403 $ hg summary
418 $ hg summary
404 parent: 1:bf1602f437f3
419 parent: 1:bf1602f437f3
405 file1
420 file1
406 branch: branch1
421 branch: branch1
407 commit: (clean)
422 commit: (clean)
408 update: (current)
423 update: (current)
409
424
410 $ cd ..
425 $ cd ..
411
426
412 backout of empty changeset (issue4190)
427 backout of empty changeset (issue4190)
413
428
414 $ hg init emptycommit
429 $ hg init emptycommit
415 $ cd emptycommit
430 $ cd emptycommit
416
431
417 $ touch file1
432 $ touch file1
418 $ hg ci -Aqm file1
433 $ hg ci -Aqm file1
419 $ hg branch -q branch1
434 $ hg branch -q branch1
420 $ hg ci -qm branch1
435 $ hg ci -qm branch1
421 $ hg backout -v 1
436 $ hg backout -v 1
422 resolving manifests
437 resolving manifests
423 nothing changed
438 nothing changed
424 [1]
439 [1]
425
440
426 $ cd ..
441 $ cd ..
427
442
428
443
429 Test usage of `hg resolve` in case of conflict
444 Test usage of `hg resolve` in case of conflict
430 (issue4163)
445 (issue4163)
431
446
432 $ hg init issue4163
447 $ hg init issue4163
433 $ cd issue4163
448 $ cd issue4163
434 $ touch foo
449 $ touch foo
435 $ hg add foo
450 $ hg add foo
436 $ cat > foo << EOF
451 $ cat > foo << EOF
437 > one
452 > one
438 > two
453 > two
439 > three
454 > three
440 > four
455 > four
441 > five
456 > five
442 > six
457 > six
443 > seven
458 > seven
444 > height
459 > height
445 > nine
460 > nine
446 > ten
461 > ten
447 > EOF
462 > EOF
448 $ hg ci -m 'initial'
463 $ hg ci -m 'initial'
449 $ cat > foo << EOF
464 $ cat > foo << EOF
450 > one
465 > one
451 > two
466 > two
452 > THREE
467 > THREE
453 > four
468 > four
454 > five
469 > five
455 > six
470 > six
456 > seven
471 > seven
457 > height
472 > height
458 > nine
473 > nine
459 > ten
474 > ten
460 > EOF
475 > EOF
461 $ hg ci -m 'capital three'
476 $ hg ci -m 'capital three'
462 $ cat > foo << EOF
477 $ cat > foo << EOF
463 > one
478 > one
464 > two
479 > two
465 > THREE
480 > THREE
466 > four
481 > four
467 > five
482 > five
468 > six
483 > six
469 > seven
484 > seven
470 > height
485 > height
471 > nine
486 > nine
472 > TEN
487 > TEN
473 > EOF
488 > EOF
474 $ hg ci -m 'capital ten'
489 $ hg ci -m 'capital ten'
475 $ hg backout -r 'desc("capital three")' --tool internal:fail
490 $ hg backout -r 'desc("capital three")' --tool internal:fail
476 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
491 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
477 use 'hg resolve' to retry unresolved file merges
492 use 'hg resolve' to retry unresolved file merges
478 [1]
493 [1]
479 $ hg status
494 $ hg status
480 $ hg resolve -l # still unresolved
495 $ hg resolve -l # still unresolved
481 U foo
496 U foo
482 $ hg summary
497 $ hg summary
483 parent: 2:b71750c4b0fd tip
498 parent: 2:b71750c4b0fd tip
484 capital ten
499 capital ten
485 branch: default
500 branch: default
486 commit: 1 unresolved (clean)
501 commit: 1 unresolved (clean)
487 update: (current)
502 update: (current)
488 $ hg resolve --all --debug
503 $ hg resolve --all --debug
489 picked tool 'internal:merge' for foo (binary False symlink False)
504 picked tool 'internal:merge' for foo (binary False symlink False)
490 merging foo
505 merging foo
491 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
506 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
492 premerge successful
507 premerge successful
493 no more unresolved files
508 no more unresolved files
494 $ hg status
509 $ hg status
495 M foo
510 M foo
496 ? foo.orig
511 ? foo.orig
497 $ hg resolve -l
512 $ hg resolve -l
498 R foo
513 R foo
499 $ hg summary
514 $ hg summary
500 parent: 2:b71750c4b0fd tip
515 parent: 2:b71750c4b0fd tip
501 capital ten
516 capital ten
502 branch: default
517 branch: default
503 commit: 1 modified, 1 unknown
518 commit: 1 modified, 1 unknown
504 update: (current)
519 update: (current)
505 $ cat foo
520 $ cat foo
506 one
521 one
507 two
522 two
508 three
523 three
509 four
524 four
510 five
525 five
511 six
526 six
512 seven
527 seven
513 height
528 height
514 nine
529 nine
515 TEN
530 TEN
516
531
517
532
General Comments 0
You need to be logged in to leave comments. Login now