##// END OF EJS Templates
backout: use commonancestorsheads for checking linear heritage...
Mads Kiilerich -
r21105:12312f06 default
parent child Browse files
Show More
@@ -1,5964 +1,5964 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.commonancestors(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 e = cmdutil.commiteditor
490 e = cmdutil.commiteditor
491 if not opts['message'] and not opts['logfile']:
491 if not opts['message'] and not opts['logfile']:
492 # we don't translate commit messages
492 # we don't translate commit messages
493 opts['message'] = "Backed out changeset %s" % short(node)
493 opts['message'] = "Backed out changeset %s" % short(node)
494 e = cmdutil.commitforceeditor
494 e = cmdutil.commitforceeditor
495
495
496 def commitfunc(ui, repo, message, match, opts):
496 def commitfunc(ui, repo, message, match, opts):
497 return repo.commit(message, opts.get('user'), opts.get('date'),
497 return repo.commit(message, opts.get('user'), opts.get('date'),
498 match, editor=e)
498 match, editor=e)
499 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
499 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
500 if not newnode:
500 if not newnode:
501 ui.status(_("nothing changed\n"))
501 ui.status(_("nothing changed\n"))
502 return 1
502 return 1
503 cmdutil.commitstatus(repo, newnode, branch, bheads)
503 cmdutil.commitstatus(repo, newnode, branch, bheads)
504
504
505 def nice(node):
505 def nice(node):
506 return '%d:%s' % (repo.changelog.rev(node), short(node))
506 return '%d:%s' % (repo.changelog.rev(node), short(node))
507 ui.status(_('changeset %s backs out changeset %s\n') %
507 ui.status(_('changeset %s backs out changeset %s\n') %
508 (nice(repo.changelog.tip()), nice(node)))
508 (nice(repo.changelog.tip()), nice(node)))
509 if opts.get('merge') and op1 != node:
509 if opts.get('merge') and op1 != node:
510 hg.clean(repo, op1, show_stats=False)
510 hg.clean(repo, op1, show_stats=False)
511 ui.status(_('merging with changeset %s\n')
511 ui.status(_('merging with changeset %s\n')
512 % nice(repo.changelog.tip()))
512 % nice(repo.changelog.tip()))
513 try:
513 try:
514 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
514 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
515 'backout')
515 'backout')
516 return hg.merge(repo, hex(repo.changelog.tip()))
516 return hg.merge(repo, hex(repo.changelog.tip()))
517 finally:
517 finally:
518 ui.setconfig('ui', 'forcemerge', '', '')
518 ui.setconfig('ui', 'forcemerge', '', '')
519 finally:
519 finally:
520 wlock.release()
520 wlock.release()
521 return 0
521 return 0
522
522
523 @command('bisect',
523 @command('bisect',
524 [('r', 'reset', False, _('reset bisect state')),
524 [('r', 'reset', False, _('reset bisect state')),
525 ('g', 'good', False, _('mark changeset good')),
525 ('g', 'good', False, _('mark changeset good')),
526 ('b', 'bad', False, _('mark changeset bad')),
526 ('b', 'bad', False, _('mark changeset bad')),
527 ('s', 'skip', False, _('skip testing changeset')),
527 ('s', 'skip', False, _('skip testing changeset')),
528 ('e', 'extend', False, _('extend the bisect range')),
528 ('e', 'extend', False, _('extend the bisect range')),
529 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
529 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
530 ('U', 'noupdate', False, _('do not update to target'))],
530 ('U', 'noupdate', False, _('do not update to target'))],
531 _("[-gbsr] [-U] [-c CMD] [REV]"))
531 _("[-gbsr] [-U] [-c CMD] [REV]"))
532 def bisect(ui, repo, rev=None, extra=None, command=None,
532 def bisect(ui, repo, rev=None, extra=None, command=None,
533 reset=None, good=None, bad=None, skip=None, extend=None,
533 reset=None, good=None, bad=None, skip=None, extend=None,
534 noupdate=None):
534 noupdate=None):
535 """subdivision search of changesets
535 """subdivision search of changesets
536
536
537 This command helps to find changesets which introduce problems. To
537 This command helps to find changesets which introduce problems. To
538 use, mark the earliest changeset you know exhibits the problem as
538 use, mark the earliest changeset you know exhibits the problem as
539 bad, then mark the latest changeset which is free from the problem
539 bad, then mark the latest changeset which is free from the problem
540 as good. Bisect will update your working directory to a revision
540 as good. Bisect will update your working directory to a revision
541 for testing (unless the -U/--noupdate option is specified). Once
541 for testing (unless the -U/--noupdate option is specified). Once
542 you have performed tests, mark the working directory as good or
542 you have performed tests, mark the working directory as good or
543 bad, and bisect will either update to another candidate changeset
543 bad, and bisect will either update to another candidate changeset
544 or announce that it has found the bad revision.
544 or announce that it has found the bad revision.
545
545
546 As a shortcut, you can also use the revision argument to mark a
546 As a shortcut, you can also use the revision argument to mark a
547 revision as good or bad without checking it out first.
547 revision as good or bad without checking it out first.
548
548
549 If you supply a command, it will be used for automatic bisection.
549 If you supply a command, it will be used for automatic bisection.
550 The environment variable HG_NODE will contain the ID of the
550 The environment variable HG_NODE will contain the ID of the
551 changeset being tested. The exit status of the command will be
551 changeset being tested. The exit status of the command will be
552 used to mark revisions as good or bad: status 0 means good, 125
552 used to mark revisions as good or bad: status 0 means good, 125
553 means to skip the revision, 127 (command not found) will abort the
553 means to skip the revision, 127 (command not found) will abort the
554 bisection, and any other non-zero exit status means the revision
554 bisection, and any other non-zero exit status means the revision
555 is bad.
555 is bad.
556
556
557 .. container:: verbose
557 .. container:: verbose
558
558
559 Some examples:
559 Some examples:
560
560
561 - start a bisection with known bad revision 34, and good revision 12::
561 - start a bisection with known bad revision 34, and good revision 12::
562
562
563 hg bisect --bad 34
563 hg bisect --bad 34
564 hg bisect --good 12
564 hg bisect --good 12
565
565
566 - advance the current bisection by marking current revision as good or
566 - advance the current bisection by marking current revision as good or
567 bad::
567 bad::
568
568
569 hg bisect --good
569 hg bisect --good
570 hg bisect --bad
570 hg bisect --bad
571
571
572 - mark the current revision, or a known revision, to be skipped (e.g. if
572 - mark the current revision, or a known revision, to be skipped (e.g. if
573 that revision is not usable because of another issue)::
573 that revision is not usable because of another issue)::
574
574
575 hg bisect --skip
575 hg bisect --skip
576 hg bisect --skip 23
576 hg bisect --skip 23
577
577
578 - skip all revisions that do not touch directories ``foo`` or ``bar``::
578 - skip all revisions that do not touch directories ``foo`` or ``bar``::
579
579
580 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
580 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
581
581
582 - forget the current bisection::
582 - forget the current bisection::
583
583
584 hg bisect --reset
584 hg bisect --reset
585
585
586 - use 'make && make tests' to automatically find the first broken
586 - use 'make && make tests' to automatically find the first broken
587 revision::
587 revision::
588
588
589 hg bisect --reset
589 hg bisect --reset
590 hg bisect --bad 34
590 hg bisect --bad 34
591 hg bisect --good 12
591 hg bisect --good 12
592 hg bisect --command "make && make tests"
592 hg bisect --command "make && make tests"
593
593
594 - see all changesets whose states are already known in the current
594 - see all changesets whose states are already known in the current
595 bisection::
595 bisection::
596
596
597 hg log -r "bisect(pruned)"
597 hg log -r "bisect(pruned)"
598
598
599 - see the changeset currently being bisected (especially useful
599 - see the changeset currently being bisected (especially useful
600 if running with -U/--noupdate)::
600 if running with -U/--noupdate)::
601
601
602 hg log -r "bisect(current)"
602 hg log -r "bisect(current)"
603
603
604 - see all changesets that took part in the current bisection::
604 - see all changesets that took part in the current bisection::
605
605
606 hg log -r "bisect(range)"
606 hg log -r "bisect(range)"
607
607
608 - you can even get a nice graph::
608 - you can even get a nice graph::
609
609
610 hg log --graph -r "bisect(range)"
610 hg log --graph -r "bisect(range)"
611
611
612 See :hg:`help revsets` for more about the `bisect()` keyword.
612 See :hg:`help revsets` for more about the `bisect()` keyword.
613
613
614 Returns 0 on success.
614 Returns 0 on success.
615 """
615 """
616 def extendbisectrange(nodes, good):
616 def extendbisectrange(nodes, good):
617 # bisect is incomplete when it ends on a merge node and
617 # bisect is incomplete when it ends on a merge node and
618 # one of the parent was not checked.
618 # one of the parent was not checked.
619 parents = repo[nodes[0]].parents()
619 parents = repo[nodes[0]].parents()
620 if len(parents) > 1:
620 if len(parents) > 1:
621 side = good and state['bad'] or state['good']
621 side = good and state['bad'] or state['good']
622 num = len(set(i.node() for i in parents) & set(side))
622 num = len(set(i.node() for i in parents) & set(side))
623 if num == 1:
623 if num == 1:
624 return parents[0].ancestor(parents[1])
624 return parents[0].ancestor(parents[1])
625 return None
625 return None
626
626
627 def print_result(nodes, good):
627 def print_result(nodes, good):
628 displayer = cmdutil.show_changeset(ui, repo, {})
628 displayer = cmdutil.show_changeset(ui, repo, {})
629 if len(nodes) == 1:
629 if len(nodes) == 1:
630 # narrowed it down to a single revision
630 # narrowed it down to a single revision
631 if good:
631 if good:
632 ui.write(_("The first good revision is:\n"))
632 ui.write(_("The first good revision is:\n"))
633 else:
633 else:
634 ui.write(_("The first bad revision is:\n"))
634 ui.write(_("The first bad revision is:\n"))
635 displayer.show(repo[nodes[0]])
635 displayer.show(repo[nodes[0]])
636 extendnode = extendbisectrange(nodes, good)
636 extendnode = extendbisectrange(nodes, good)
637 if extendnode is not None:
637 if extendnode is not None:
638 ui.write(_('Not all ancestors of this changeset have been'
638 ui.write(_('Not all ancestors of this changeset have been'
639 ' checked.\nUse bisect --extend to continue the '
639 ' checked.\nUse bisect --extend to continue the '
640 'bisection from\nthe common ancestor, %s.\n')
640 'bisection from\nthe common ancestor, %s.\n')
641 % extendnode)
641 % extendnode)
642 else:
642 else:
643 # multiple possible revisions
643 # multiple possible revisions
644 if good:
644 if good:
645 ui.write(_("Due to skipped revisions, the first "
645 ui.write(_("Due to skipped revisions, the first "
646 "good revision could be any of:\n"))
646 "good revision could be any of:\n"))
647 else:
647 else:
648 ui.write(_("Due to skipped revisions, the first "
648 ui.write(_("Due to skipped revisions, the first "
649 "bad revision could be any of:\n"))
649 "bad revision could be any of:\n"))
650 for n in nodes:
650 for n in nodes:
651 displayer.show(repo[n])
651 displayer.show(repo[n])
652 displayer.close()
652 displayer.close()
653
653
654 def check_state(state, interactive=True):
654 def check_state(state, interactive=True):
655 if not state['good'] or not state['bad']:
655 if not state['good'] or not state['bad']:
656 if (good or bad or skip or reset) and interactive:
656 if (good or bad or skip or reset) and interactive:
657 return
657 return
658 if not state['good']:
658 if not state['good']:
659 raise util.Abort(_('cannot bisect (no known good revisions)'))
659 raise util.Abort(_('cannot bisect (no known good revisions)'))
660 else:
660 else:
661 raise util.Abort(_('cannot bisect (no known bad revisions)'))
661 raise util.Abort(_('cannot bisect (no known bad revisions)'))
662 return True
662 return True
663
663
664 # backward compatibility
664 # backward compatibility
665 if rev in "good bad reset init".split():
665 if rev in "good bad reset init".split():
666 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
666 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
667 cmd, rev, extra = rev, extra, None
667 cmd, rev, extra = rev, extra, None
668 if cmd == "good":
668 if cmd == "good":
669 good = True
669 good = True
670 elif cmd == "bad":
670 elif cmd == "bad":
671 bad = True
671 bad = True
672 else:
672 else:
673 reset = True
673 reset = True
674 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
674 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
675 raise util.Abort(_('incompatible arguments'))
675 raise util.Abort(_('incompatible arguments'))
676
676
677 cmdutil.checkunfinished(repo)
677 cmdutil.checkunfinished(repo)
678
678
679 if reset:
679 if reset:
680 p = repo.join("bisect.state")
680 p = repo.join("bisect.state")
681 if os.path.exists(p):
681 if os.path.exists(p):
682 os.unlink(p)
682 os.unlink(p)
683 return
683 return
684
684
685 state = hbisect.load_state(repo)
685 state = hbisect.load_state(repo)
686
686
687 if command:
687 if command:
688 changesets = 1
688 changesets = 1
689 if noupdate:
689 if noupdate:
690 try:
690 try:
691 node = state['current'][0]
691 node = state['current'][0]
692 except LookupError:
692 except LookupError:
693 raise util.Abort(_('current bisect revision is unknown - '
693 raise util.Abort(_('current bisect revision is unknown - '
694 'start a new bisect to fix'))
694 'start a new bisect to fix'))
695 else:
695 else:
696 node, p2 = repo.dirstate.parents()
696 node, p2 = repo.dirstate.parents()
697 if p2 != nullid:
697 if p2 != nullid:
698 raise util.Abort(_('current bisect revision is a merge'))
698 raise util.Abort(_('current bisect revision is a merge'))
699 try:
699 try:
700 while changesets:
700 while changesets:
701 # update state
701 # update state
702 state['current'] = [node]
702 state['current'] = [node]
703 hbisect.save_state(repo, state)
703 hbisect.save_state(repo, state)
704 status = util.system(command,
704 status = util.system(command,
705 environ={'HG_NODE': hex(node)},
705 environ={'HG_NODE': hex(node)},
706 out=ui.fout)
706 out=ui.fout)
707 if status == 125:
707 if status == 125:
708 transition = "skip"
708 transition = "skip"
709 elif status == 0:
709 elif status == 0:
710 transition = "good"
710 transition = "good"
711 # status < 0 means process was killed
711 # status < 0 means process was killed
712 elif status == 127:
712 elif status == 127:
713 raise util.Abort(_("failed to execute %s") % command)
713 raise util.Abort(_("failed to execute %s") % command)
714 elif status < 0:
714 elif status < 0:
715 raise util.Abort(_("%s killed") % command)
715 raise util.Abort(_("%s killed") % command)
716 else:
716 else:
717 transition = "bad"
717 transition = "bad"
718 ctx = scmutil.revsingle(repo, rev, node)
718 ctx = scmutil.revsingle(repo, rev, node)
719 rev = None # clear for future iterations
719 rev = None # clear for future iterations
720 state[transition].append(ctx.node())
720 state[transition].append(ctx.node())
721 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
721 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
722 check_state(state, interactive=False)
722 check_state(state, interactive=False)
723 # bisect
723 # bisect
724 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
724 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
725 # update to next check
725 # update to next check
726 node = nodes[0]
726 node = nodes[0]
727 if not noupdate:
727 if not noupdate:
728 cmdutil.bailifchanged(repo)
728 cmdutil.bailifchanged(repo)
729 hg.clean(repo, node, show_stats=False)
729 hg.clean(repo, node, show_stats=False)
730 finally:
730 finally:
731 state['current'] = [node]
731 state['current'] = [node]
732 hbisect.save_state(repo, state)
732 hbisect.save_state(repo, state)
733 print_result(nodes, bgood)
733 print_result(nodes, bgood)
734 return
734 return
735
735
736 # update state
736 # update state
737
737
738 if rev:
738 if rev:
739 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
739 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
740 else:
740 else:
741 nodes = [repo.lookup('.')]
741 nodes = [repo.lookup('.')]
742
742
743 if good or bad or skip:
743 if good or bad or skip:
744 if good:
744 if good:
745 state['good'] += nodes
745 state['good'] += nodes
746 elif bad:
746 elif bad:
747 state['bad'] += nodes
747 state['bad'] += nodes
748 elif skip:
748 elif skip:
749 state['skip'] += nodes
749 state['skip'] += nodes
750 hbisect.save_state(repo, state)
750 hbisect.save_state(repo, state)
751
751
752 if not check_state(state):
752 if not check_state(state):
753 return
753 return
754
754
755 # actually bisect
755 # actually bisect
756 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
756 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
757 if extend:
757 if extend:
758 if not changesets:
758 if not changesets:
759 extendnode = extendbisectrange(nodes, good)
759 extendnode = extendbisectrange(nodes, good)
760 if extendnode is not None:
760 if extendnode is not None:
761 ui.write(_("Extending search to changeset %d:%s\n")
761 ui.write(_("Extending search to changeset %d:%s\n")
762 % (extendnode.rev(), extendnode))
762 % (extendnode.rev(), extendnode))
763 state['current'] = [extendnode.node()]
763 state['current'] = [extendnode.node()]
764 hbisect.save_state(repo, state)
764 hbisect.save_state(repo, state)
765 if noupdate:
765 if noupdate:
766 return
766 return
767 cmdutil.bailifchanged(repo)
767 cmdutil.bailifchanged(repo)
768 return hg.clean(repo, extendnode.node())
768 return hg.clean(repo, extendnode.node())
769 raise util.Abort(_("nothing to extend"))
769 raise util.Abort(_("nothing to extend"))
770
770
771 if changesets == 0:
771 if changesets == 0:
772 print_result(nodes, good)
772 print_result(nodes, good)
773 else:
773 else:
774 assert len(nodes) == 1 # only a single node can be tested next
774 assert len(nodes) == 1 # only a single node can be tested next
775 node = nodes[0]
775 node = nodes[0]
776 # compute the approximate number of remaining tests
776 # compute the approximate number of remaining tests
777 tests, size = 0, 2
777 tests, size = 0, 2
778 while size <= changesets:
778 while size <= changesets:
779 tests, size = tests + 1, size * 2
779 tests, size = tests + 1, size * 2
780 rev = repo.changelog.rev(node)
780 rev = repo.changelog.rev(node)
781 ui.write(_("Testing changeset %d:%s "
781 ui.write(_("Testing changeset %d:%s "
782 "(%d changesets remaining, ~%d tests)\n")
782 "(%d changesets remaining, ~%d tests)\n")
783 % (rev, short(node), changesets, tests))
783 % (rev, short(node), changesets, tests))
784 state['current'] = [node]
784 state['current'] = [node]
785 hbisect.save_state(repo, state)
785 hbisect.save_state(repo, state)
786 if not noupdate:
786 if not noupdate:
787 cmdutil.bailifchanged(repo)
787 cmdutil.bailifchanged(repo)
788 return hg.clean(repo, node)
788 return hg.clean(repo, node)
789
789
790 @command('bookmarks|bookmark',
790 @command('bookmarks|bookmark',
791 [('f', 'force', False, _('force')),
791 [('f', 'force', False, _('force')),
792 ('r', 'rev', '', _('revision'), _('REV')),
792 ('r', 'rev', '', _('revision'), _('REV')),
793 ('d', 'delete', False, _('delete a given bookmark')),
793 ('d', 'delete', False, _('delete a given bookmark')),
794 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
794 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
795 ('i', 'inactive', False, _('mark a bookmark inactive'))],
795 ('i', 'inactive', False, _('mark a bookmark inactive'))],
796 _('hg bookmarks [OPTIONS]... [NAME]...'))
796 _('hg bookmarks [OPTIONS]... [NAME]...'))
797 def bookmark(ui, repo, *names, **opts):
797 def bookmark(ui, repo, *names, **opts):
798 '''track a line of development with movable markers
798 '''track a line of development with movable markers
799
799
800 Bookmarks are pointers to certain commits that move when committing.
800 Bookmarks are pointers to certain commits that move when committing.
801 Bookmarks are local. They can be renamed, copied and deleted. It is
801 Bookmarks are local. They can be renamed, copied and deleted. It is
802 possible to use :hg:`merge NAME` to merge from a given bookmark, and
802 possible to use :hg:`merge NAME` to merge from a given bookmark, and
803 :hg:`update NAME` to update to a given bookmark.
803 :hg:`update NAME` to update to a given bookmark.
804
804
805 You can use :hg:`bookmark NAME` to set a bookmark on the working
805 You can use :hg:`bookmark NAME` to set a bookmark on the working
806 directory's parent revision with the given name. If you specify
806 directory's parent revision with the given name. If you specify
807 a revision using -r REV (where REV may be an existing bookmark),
807 a revision using -r REV (where REV may be an existing bookmark),
808 the bookmark is assigned to that revision.
808 the bookmark is assigned to that revision.
809
809
810 Bookmarks can be pushed and pulled between repositories (see :hg:`help
810 Bookmarks can be pushed and pulled between repositories (see :hg:`help
811 push` and :hg:`help pull`). This requires both the local and remote
811 push` and :hg:`help pull`). This requires both the local and remote
812 repositories to support bookmarks. For versions prior to 1.8, this means
812 repositories to support bookmarks. For versions prior to 1.8, this means
813 the bookmarks extension must be enabled.
813 the bookmarks extension must be enabled.
814
814
815 If you set a bookmark called '@', new clones of the repository will
815 If you set a bookmark called '@', new clones of the repository will
816 have that revision checked out (and the bookmark made active) by
816 have that revision checked out (and the bookmark made active) by
817 default.
817 default.
818
818
819 With -i/--inactive, the new bookmark will not be made the active
819 With -i/--inactive, the new bookmark will not be made the active
820 bookmark. If -r/--rev is given, the new bookmark will not be made
820 bookmark. If -r/--rev is given, the new bookmark will not be made
821 active even if -i/--inactive is not given. If no NAME is given, the
821 active even if -i/--inactive is not given. If no NAME is given, the
822 current active bookmark will be marked inactive.
822 current active bookmark will be marked inactive.
823 '''
823 '''
824 force = opts.get('force')
824 force = opts.get('force')
825 rev = opts.get('rev')
825 rev = opts.get('rev')
826 delete = opts.get('delete')
826 delete = opts.get('delete')
827 rename = opts.get('rename')
827 rename = opts.get('rename')
828 inactive = opts.get('inactive')
828 inactive = opts.get('inactive')
829
829
830 def checkformat(mark):
830 def checkformat(mark):
831 mark = mark.strip()
831 mark = mark.strip()
832 if not mark:
832 if not mark:
833 raise util.Abort(_("bookmark names cannot consist entirely of "
833 raise util.Abort(_("bookmark names cannot consist entirely of "
834 "whitespace"))
834 "whitespace"))
835 scmutil.checknewlabel(repo, mark, 'bookmark')
835 scmutil.checknewlabel(repo, mark, 'bookmark')
836 return mark
836 return mark
837
837
838 def checkconflict(repo, mark, cur, force=False, target=None):
838 def checkconflict(repo, mark, cur, force=False, target=None):
839 if mark in marks and not force:
839 if mark in marks and not force:
840 if target:
840 if target:
841 if marks[mark] == target and target == cur:
841 if marks[mark] == target and target == cur:
842 # re-activating a bookmark
842 # re-activating a bookmark
843 return
843 return
844 anc = repo.changelog.ancestors([repo[target].rev()])
844 anc = repo.changelog.ancestors([repo[target].rev()])
845 bmctx = repo[marks[mark]]
845 bmctx = repo[marks[mark]]
846 divs = [repo[b].node() for b in marks
846 divs = [repo[b].node() for b in marks
847 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
847 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
848
848
849 # allow resolving a single divergent bookmark even if moving
849 # allow resolving a single divergent bookmark even if moving
850 # the bookmark across branches when a revision is specified
850 # the bookmark across branches when a revision is specified
851 # that contains a divergent bookmark
851 # that contains a divergent bookmark
852 if bmctx.rev() not in anc and target in divs:
852 if bmctx.rev() not in anc and target in divs:
853 bookmarks.deletedivergent(repo, [target], mark)
853 bookmarks.deletedivergent(repo, [target], mark)
854 return
854 return
855
855
856 deletefrom = [b for b in divs
856 deletefrom = [b for b in divs
857 if repo[b].rev() in anc or b == target]
857 if repo[b].rev() in anc or b == target]
858 bookmarks.deletedivergent(repo, deletefrom, mark)
858 bookmarks.deletedivergent(repo, deletefrom, mark)
859 if bookmarks.validdest(repo, bmctx, repo[target]):
859 if bookmarks.validdest(repo, bmctx, repo[target]):
860 ui.status(_("moving bookmark '%s' forward from %s\n") %
860 ui.status(_("moving bookmark '%s' forward from %s\n") %
861 (mark, short(bmctx.node())))
861 (mark, short(bmctx.node())))
862 return
862 return
863 raise util.Abort(_("bookmark '%s' already exists "
863 raise util.Abort(_("bookmark '%s' already exists "
864 "(use -f to force)") % mark)
864 "(use -f to force)") % mark)
865 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
865 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
866 and not force):
866 and not force):
867 raise util.Abort(
867 raise util.Abort(
868 _("a bookmark cannot have the name of an existing branch"))
868 _("a bookmark cannot have the name of an existing branch"))
869
869
870 if delete and rename:
870 if delete and rename:
871 raise util.Abort(_("--delete and --rename are incompatible"))
871 raise util.Abort(_("--delete and --rename are incompatible"))
872 if delete and rev:
872 if delete and rev:
873 raise util.Abort(_("--rev is incompatible with --delete"))
873 raise util.Abort(_("--rev is incompatible with --delete"))
874 if rename and rev:
874 if rename and rev:
875 raise util.Abort(_("--rev is incompatible with --rename"))
875 raise util.Abort(_("--rev is incompatible with --rename"))
876 if not names and (delete or rev):
876 if not names and (delete or rev):
877 raise util.Abort(_("bookmark name required"))
877 raise util.Abort(_("bookmark name required"))
878
878
879 if delete or rename or names or inactive:
879 if delete or rename or names or inactive:
880 wlock = repo.wlock()
880 wlock = repo.wlock()
881 try:
881 try:
882 cur = repo.changectx('.').node()
882 cur = repo.changectx('.').node()
883 marks = repo._bookmarks
883 marks = repo._bookmarks
884 if delete:
884 if delete:
885 for mark in names:
885 for mark in names:
886 if mark not in marks:
886 if mark not in marks:
887 raise util.Abort(_("bookmark '%s' does not exist") %
887 raise util.Abort(_("bookmark '%s' does not exist") %
888 mark)
888 mark)
889 if mark == repo._bookmarkcurrent:
889 if mark == repo._bookmarkcurrent:
890 bookmarks.unsetcurrent(repo)
890 bookmarks.unsetcurrent(repo)
891 del marks[mark]
891 del marks[mark]
892 marks.write()
892 marks.write()
893
893
894 elif rename:
894 elif rename:
895 if not names:
895 if not names:
896 raise util.Abort(_("new bookmark name required"))
896 raise util.Abort(_("new bookmark name required"))
897 elif len(names) > 1:
897 elif len(names) > 1:
898 raise util.Abort(_("only one new bookmark name allowed"))
898 raise util.Abort(_("only one new bookmark name allowed"))
899 mark = checkformat(names[0])
899 mark = checkformat(names[0])
900 if rename not in marks:
900 if rename not in marks:
901 raise util.Abort(_("bookmark '%s' does not exist") % rename)
901 raise util.Abort(_("bookmark '%s' does not exist") % rename)
902 checkconflict(repo, mark, cur, force)
902 checkconflict(repo, mark, cur, force)
903 marks[mark] = marks[rename]
903 marks[mark] = marks[rename]
904 if repo._bookmarkcurrent == rename and not inactive:
904 if repo._bookmarkcurrent == rename and not inactive:
905 bookmarks.setcurrent(repo, mark)
905 bookmarks.setcurrent(repo, mark)
906 del marks[rename]
906 del marks[rename]
907 marks.write()
907 marks.write()
908
908
909 elif names:
909 elif names:
910 newact = None
910 newact = None
911 for mark in names:
911 for mark in names:
912 mark = checkformat(mark)
912 mark = checkformat(mark)
913 if newact is None:
913 if newact is None:
914 newact = mark
914 newact = mark
915 if inactive and mark == repo._bookmarkcurrent:
915 if inactive and mark == repo._bookmarkcurrent:
916 bookmarks.unsetcurrent(repo)
916 bookmarks.unsetcurrent(repo)
917 return
917 return
918 tgt = cur
918 tgt = cur
919 if rev:
919 if rev:
920 tgt = scmutil.revsingle(repo, rev).node()
920 tgt = scmutil.revsingle(repo, rev).node()
921 checkconflict(repo, mark, cur, force, tgt)
921 checkconflict(repo, mark, cur, force, tgt)
922 marks[mark] = tgt
922 marks[mark] = tgt
923 if not inactive and cur == marks[newact] and not rev:
923 if not inactive and cur == marks[newact] and not rev:
924 bookmarks.setcurrent(repo, newact)
924 bookmarks.setcurrent(repo, newact)
925 elif cur != tgt and newact == repo._bookmarkcurrent:
925 elif cur != tgt and newact == repo._bookmarkcurrent:
926 bookmarks.unsetcurrent(repo)
926 bookmarks.unsetcurrent(repo)
927 marks.write()
927 marks.write()
928
928
929 elif inactive:
929 elif inactive:
930 if len(marks) == 0:
930 if len(marks) == 0:
931 ui.status(_("no bookmarks set\n"))
931 ui.status(_("no bookmarks set\n"))
932 elif not repo._bookmarkcurrent:
932 elif not repo._bookmarkcurrent:
933 ui.status(_("no active bookmark\n"))
933 ui.status(_("no active bookmark\n"))
934 else:
934 else:
935 bookmarks.unsetcurrent(repo)
935 bookmarks.unsetcurrent(repo)
936 finally:
936 finally:
937 wlock.release()
937 wlock.release()
938 else: # show bookmarks
938 else: # show bookmarks
939 hexfn = ui.debugflag and hex or short
939 hexfn = ui.debugflag and hex or short
940 marks = repo._bookmarks
940 marks = repo._bookmarks
941 if len(marks) == 0:
941 if len(marks) == 0:
942 ui.status(_("no bookmarks set\n"))
942 ui.status(_("no bookmarks set\n"))
943 else:
943 else:
944 for bmark, n in sorted(marks.iteritems()):
944 for bmark, n in sorted(marks.iteritems()):
945 current = repo._bookmarkcurrent
945 current = repo._bookmarkcurrent
946 if bmark == current:
946 if bmark == current:
947 prefix, label = '*', 'bookmarks.current'
947 prefix, label = '*', 'bookmarks.current'
948 else:
948 else:
949 prefix, label = ' ', ''
949 prefix, label = ' ', ''
950
950
951 if ui.quiet:
951 if ui.quiet:
952 ui.write("%s\n" % bmark, label=label)
952 ui.write("%s\n" % bmark, label=label)
953 else:
953 else:
954 ui.write(" %s %-25s %d:%s\n" % (
954 ui.write(" %s %-25s %d:%s\n" % (
955 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
955 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
956 label=label)
956 label=label)
957
957
958 @command('branch',
958 @command('branch',
959 [('f', 'force', None,
959 [('f', 'force', None,
960 _('set branch name even if it shadows an existing branch')),
960 _('set branch name even if it shadows an existing branch')),
961 ('C', 'clean', None, _('reset branch name to parent branch name'))],
961 ('C', 'clean', None, _('reset branch name to parent branch name'))],
962 _('[-fC] [NAME]'))
962 _('[-fC] [NAME]'))
963 def branch(ui, repo, label=None, **opts):
963 def branch(ui, repo, label=None, **opts):
964 """set or show the current branch name
964 """set or show the current branch name
965
965
966 .. note::
966 .. note::
967
967
968 Branch names are permanent and global. Use :hg:`bookmark` to create a
968 Branch names are permanent and global. Use :hg:`bookmark` to create a
969 light-weight bookmark instead. See :hg:`help glossary` for more
969 light-weight bookmark instead. See :hg:`help glossary` for more
970 information about named branches and bookmarks.
970 information about named branches and bookmarks.
971
971
972 With no argument, show the current branch name. With one argument,
972 With no argument, show the current branch name. With one argument,
973 set the working directory branch name (the branch will not exist
973 set the working directory branch name (the branch will not exist
974 in the repository until the next commit). Standard practice
974 in the repository until the next commit). Standard practice
975 recommends that primary development take place on the 'default'
975 recommends that primary development take place on the 'default'
976 branch.
976 branch.
977
977
978 Unless -f/--force is specified, branch will not let you set a
978 Unless -f/--force is specified, branch will not let you set a
979 branch name that already exists, even if it's inactive.
979 branch name that already exists, even if it's inactive.
980
980
981 Use -C/--clean to reset the working directory branch to that of
981 Use -C/--clean to reset the working directory branch to that of
982 the parent of the working directory, negating a previous branch
982 the parent of the working directory, negating a previous branch
983 change.
983 change.
984
984
985 Use the command :hg:`update` to switch to an existing branch. Use
985 Use the command :hg:`update` to switch to an existing branch. Use
986 :hg:`commit --close-branch` to mark this branch as closed.
986 :hg:`commit --close-branch` to mark this branch as closed.
987
987
988 Returns 0 on success.
988 Returns 0 on success.
989 """
989 """
990 if label:
990 if label:
991 label = label.strip()
991 label = label.strip()
992
992
993 if not opts.get('clean') and not label:
993 if not opts.get('clean') and not label:
994 ui.write("%s\n" % repo.dirstate.branch())
994 ui.write("%s\n" % repo.dirstate.branch())
995 return
995 return
996
996
997 wlock = repo.wlock()
997 wlock = repo.wlock()
998 try:
998 try:
999 if opts.get('clean'):
999 if opts.get('clean'):
1000 label = repo[None].p1().branch()
1000 label = repo[None].p1().branch()
1001 repo.dirstate.setbranch(label)
1001 repo.dirstate.setbranch(label)
1002 ui.status(_('reset working directory to branch %s\n') % label)
1002 ui.status(_('reset working directory to branch %s\n') % label)
1003 elif label:
1003 elif label:
1004 if not opts.get('force') and label in repo.branchmap():
1004 if not opts.get('force') and label in repo.branchmap():
1005 if label not in [p.branch() for p in repo.parents()]:
1005 if label not in [p.branch() for p in repo.parents()]:
1006 raise util.Abort(_('a branch of the same name already'
1006 raise util.Abort(_('a branch of the same name already'
1007 ' exists'),
1007 ' exists'),
1008 # i18n: "it" refers to an existing branch
1008 # i18n: "it" refers to an existing branch
1009 hint=_("use 'hg update' to switch to it"))
1009 hint=_("use 'hg update' to switch to it"))
1010 scmutil.checknewlabel(repo, label, 'branch')
1010 scmutil.checknewlabel(repo, label, 'branch')
1011 repo.dirstate.setbranch(label)
1011 repo.dirstate.setbranch(label)
1012 ui.status(_('marked working directory as branch %s\n') % label)
1012 ui.status(_('marked working directory as branch %s\n') % label)
1013 ui.status(_('(branches are permanent and global, '
1013 ui.status(_('(branches are permanent and global, '
1014 'did you want a bookmark?)\n'))
1014 'did you want a bookmark?)\n'))
1015 finally:
1015 finally:
1016 wlock.release()
1016 wlock.release()
1017
1017
1018 @command('branches',
1018 @command('branches',
1019 [('a', 'active', False, _('show only branches that have unmerged heads')),
1019 [('a', 'active', False, _('show only branches that have unmerged heads')),
1020 ('c', 'closed', False, _('show normal and closed branches'))],
1020 ('c', 'closed', False, _('show normal and closed branches'))],
1021 _('[-ac]'))
1021 _('[-ac]'))
1022 def branches(ui, repo, active=False, closed=False):
1022 def branches(ui, repo, active=False, closed=False):
1023 """list repository named branches
1023 """list repository named branches
1024
1024
1025 List the repository's named branches, indicating which ones are
1025 List the repository's named branches, indicating which ones are
1026 inactive. If -c/--closed is specified, also list branches which have
1026 inactive. If -c/--closed is specified, also list branches which have
1027 been marked closed (see :hg:`commit --close-branch`).
1027 been marked closed (see :hg:`commit --close-branch`).
1028
1028
1029 If -a/--active is specified, only show active branches. A branch
1029 If -a/--active is specified, only show active branches. A branch
1030 is considered active if it contains repository heads.
1030 is considered active if it contains repository heads.
1031
1031
1032 Use the command :hg:`update` to switch to an existing branch.
1032 Use the command :hg:`update` to switch to an existing branch.
1033
1033
1034 Returns 0.
1034 Returns 0.
1035 """
1035 """
1036
1036
1037 hexfunc = ui.debugflag and hex or short
1037 hexfunc = ui.debugflag and hex or short
1038
1038
1039 allheads = set(repo.heads())
1039 allheads = set(repo.heads())
1040 branches = []
1040 branches = []
1041 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1041 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1042 isactive = not isclosed and bool(set(heads) & allheads)
1042 isactive = not isclosed and bool(set(heads) & allheads)
1043 branches.append((tag, repo[tip], isactive, not isclosed))
1043 branches.append((tag, repo[tip], isactive, not isclosed))
1044 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1044 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1045 reverse=True)
1045 reverse=True)
1046
1046
1047 for tag, ctx, isactive, isopen in branches:
1047 for tag, ctx, isactive, isopen in branches:
1048 if (not active) or isactive:
1048 if (not active) or isactive:
1049 if isactive:
1049 if isactive:
1050 label = 'branches.active'
1050 label = 'branches.active'
1051 notice = ''
1051 notice = ''
1052 elif not isopen:
1052 elif not isopen:
1053 if not closed:
1053 if not closed:
1054 continue
1054 continue
1055 label = 'branches.closed'
1055 label = 'branches.closed'
1056 notice = _(' (closed)')
1056 notice = _(' (closed)')
1057 else:
1057 else:
1058 label = 'branches.inactive'
1058 label = 'branches.inactive'
1059 notice = _(' (inactive)')
1059 notice = _(' (inactive)')
1060 if tag == repo.dirstate.branch():
1060 if tag == repo.dirstate.branch():
1061 label = 'branches.current'
1061 label = 'branches.current'
1062 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1062 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1063 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1063 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1064 'log.changeset changeset.%s' % ctx.phasestr())
1064 'log.changeset changeset.%s' % ctx.phasestr())
1065 labeledtag = ui.label(tag, label)
1065 labeledtag = ui.label(tag, label)
1066 if ui.quiet:
1066 if ui.quiet:
1067 ui.write("%s\n" % labeledtag)
1067 ui.write("%s\n" % labeledtag)
1068 else:
1068 else:
1069 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1069 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1070
1070
1071 @command('bundle',
1071 @command('bundle',
1072 [('f', 'force', None, _('run even when the destination is unrelated')),
1072 [('f', 'force', None, _('run even when the destination is unrelated')),
1073 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1073 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1074 _('REV')),
1074 _('REV')),
1075 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1075 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1076 _('BRANCH')),
1076 _('BRANCH')),
1077 ('', 'base', [],
1077 ('', 'base', [],
1078 _('a base changeset assumed to be available at the destination'),
1078 _('a base changeset assumed to be available at the destination'),
1079 _('REV')),
1079 _('REV')),
1080 ('a', 'all', None, _('bundle all changesets in the repository')),
1080 ('a', 'all', None, _('bundle all changesets in the repository')),
1081 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1081 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1082 ] + remoteopts,
1082 ] + remoteopts,
1083 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1083 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1084 def bundle(ui, repo, fname, dest=None, **opts):
1084 def bundle(ui, repo, fname, dest=None, **opts):
1085 """create a changegroup file
1085 """create a changegroup file
1086
1086
1087 Generate a compressed changegroup file collecting changesets not
1087 Generate a compressed changegroup file collecting changesets not
1088 known to be in another repository.
1088 known to be in another repository.
1089
1089
1090 If you omit the destination repository, then hg assumes the
1090 If you omit the destination repository, then hg assumes the
1091 destination will have all the nodes you specify with --base
1091 destination will have all the nodes you specify with --base
1092 parameters. To create a bundle containing all changesets, use
1092 parameters. To create a bundle containing all changesets, use
1093 -a/--all (or --base null).
1093 -a/--all (or --base null).
1094
1094
1095 You can change compression method with the -t/--type option.
1095 You can change compression method with the -t/--type option.
1096 The available compression methods are: none, bzip2, and
1096 The available compression methods are: none, bzip2, and
1097 gzip (by default, bundles are compressed using bzip2).
1097 gzip (by default, bundles are compressed using bzip2).
1098
1098
1099 The bundle file can then be transferred using conventional means
1099 The bundle file can then be transferred using conventional means
1100 and applied to another repository with the unbundle or pull
1100 and applied to another repository with the unbundle or pull
1101 command. This is useful when direct push and pull are not
1101 command. This is useful when direct push and pull are not
1102 available or when exporting an entire repository is undesirable.
1102 available or when exporting an entire repository is undesirable.
1103
1103
1104 Applying bundles preserves all changeset contents including
1104 Applying bundles preserves all changeset contents including
1105 permissions, copy/rename information, and revision history.
1105 permissions, copy/rename information, and revision history.
1106
1106
1107 Returns 0 on success, 1 if no changes found.
1107 Returns 0 on success, 1 if no changes found.
1108 """
1108 """
1109 revs = None
1109 revs = None
1110 if 'rev' in opts:
1110 if 'rev' in opts:
1111 revs = scmutil.revrange(repo, opts['rev'])
1111 revs = scmutil.revrange(repo, opts['rev'])
1112
1112
1113 bundletype = opts.get('type', 'bzip2').lower()
1113 bundletype = opts.get('type', 'bzip2').lower()
1114 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1114 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1115 bundletype = btypes.get(bundletype)
1115 bundletype = btypes.get(bundletype)
1116 if bundletype not in changegroup.bundletypes:
1116 if bundletype not in changegroup.bundletypes:
1117 raise util.Abort(_('unknown bundle type specified with --type'))
1117 raise util.Abort(_('unknown bundle type specified with --type'))
1118
1118
1119 if opts.get('all'):
1119 if opts.get('all'):
1120 base = ['null']
1120 base = ['null']
1121 else:
1121 else:
1122 base = scmutil.revrange(repo, opts.get('base'))
1122 base = scmutil.revrange(repo, opts.get('base'))
1123 # TODO: get desired bundlecaps from command line.
1123 # TODO: get desired bundlecaps from command line.
1124 bundlecaps = None
1124 bundlecaps = None
1125 if base:
1125 if base:
1126 if dest:
1126 if dest:
1127 raise util.Abort(_("--base is incompatible with specifying "
1127 raise util.Abort(_("--base is incompatible with specifying "
1128 "a destination"))
1128 "a destination"))
1129 common = [repo.lookup(rev) for rev in base]
1129 common = [repo.lookup(rev) for rev in base]
1130 heads = revs and map(repo.lookup, revs) or revs
1130 heads = revs and map(repo.lookup, revs) or revs
1131 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1131 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1132 bundlecaps=bundlecaps)
1132 bundlecaps=bundlecaps)
1133 outgoing = None
1133 outgoing = None
1134 else:
1134 else:
1135 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1135 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1136 dest, branches = hg.parseurl(dest, opts.get('branch'))
1136 dest, branches = hg.parseurl(dest, opts.get('branch'))
1137 other = hg.peer(repo, opts, dest)
1137 other = hg.peer(repo, opts, dest)
1138 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1138 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1139 heads = revs and map(repo.lookup, revs) or revs
1139 heads = revs and map(repo.lookup, revs) or revs
1140 outgoing = discovery.findcommonoutgoing(repo, other,
1140 outgoing = discovery.findcommonoutgoing(repo, other,
1141 onlyheads=heads,
1141 onlyheads=heads,
1142 force=opts.get('force'),
1142 force=opts.get('force'),
1143 portable=True)
1143 portable=True)
1144 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1144 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1145 if not cg:
1145 if not cg:
1146 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1146 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1147 return 1
1147 return 1
1148
1148
1149 changegroup.writebundle(cg, fname, bundletype)
1149 changegroup.writebundle(cg, fname, bundletype)
1150
1150
1151 @command('cat',
1151 @command('cat',
1152 [('o', 'output', '',
1152 [('o', 'output', '',
1153 _('print output to file with formatted name'), _('FORMAT')),
1153 _('print output to file with formatted name'), _('FORMAT')),
1154 ('r', 'rev', '', _('print the given revision'), _('REV')),
1154 ('r', 'rev', '', _('print the given revision'), _('REV')),
1155 ('', 'decode', None, _('apply any matching decode filter')),
1155 ('', 'decode', None, _('apply any matching decode filter')),
1156 ] + walkopts,
1156 ] + walkopts,
1157 _('[OPTION]... FILE...'))
1157 _('[OPTION]... FILE...'))
1158 def cat(ui, repo, file1, *pats, **opts):
1158 def cat(ui, repo, file1, *pats, **opts):
1159 """output the current or given revision of files
1159 """output the current or given revision of files
1160
1160
1161 Print the specified files as they were at the given revision. If
1161 Print the specified files as they were at the given revision. If
1162 no revision is given, the parent of the working directory is used.
1162 no revision is given, the parent of the working directory is used.
1163
1163
1164 Output may be to a file, in which case the name of the file is
1164 Output may be to a file, in which case the name of the file is
1165 given using a format string. The formatting rules as follows:
1165 given using a format string. The formatting rules as follows:
1166
1166
1167 :``%%``: literal "%" character
1167 :``%%``: literal "%" character
1168 :``%s``: basename of file being printed
1168 :``%s``: basename of file being printed
1169 :``%d``: dirname of file being printed, or '.' if in repository root
1169 :``%d``: dirname of file being printed, or '.' if in repository root
1170 :``%p``: root-relative path name of file being printed
1170 :``%p``: root-relative path name of file being printed
1171 :``%H``: changeset hash (40 hexadecimal digits)
1171 :``%H``: changeset hash (40 hexadecimal digits)
1172 :``%R``: changeset revision number
1172 :``%R``: changeset revision number
1173 :``%h``: short-form changeset hash (12 hexadecimal digits)
1173 :``%h``: short-form changeset hash (12 hexadecimal digits)
1174 :``%r``: zero-padded changeset revision number
1174 :``%r``: zero-padded changeset revision number
1175 :``%b``: basename of the exporting repository
1175 :``%b``: basename of the exporting repository
1176
1176
1177 Returns 0 on success.
1177 Returns 0 on success.
1178 """
1178 """
1179 ctx = scmutil.revsingle(repo, opts.get('rev'))
1179 ctx = scmutil.revsingle(repo, opts.get('rev'))
1180 m = scmutil.match(ctx, (file1,) + pats, opts)
1180 m = scmutil.match(ctx, (file1,) + pats, opts)
1181
1181
1182 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1182 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1183
1183
1184 @command('^clone',
1184 @command('^clone',
1185 [('U', 'noupdate', None,
1185 [('U', 'noupdate', None,
1186 _('the clone will include an empty working copy (only a repository)')),
1186 _('the clone will include an empty working copy (only a repository)')),
1187 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1187 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1188 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1188 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1189 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1189 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1190 ('', 'pull', None, _('use pull protocol to copy metadata')),
1190 ('', 'pull', None, _('use pull protocol to copy metadata')),
1191 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1191 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1192 ] + remoteopts,
1192 ] + remoteopts,
1193 _('[OPTION]... SOURCE [DEST]'))
1193 _('[OPTION]... SOURCE [DEST]'))
1194 def clone(ui, source, dest=None, **opts):
1194 def clone(ui, source, dest=None, **opts):
1195 """make a copy of an existing repository
1195 """make a copy of an existing repository
1196
1196
1197 Create a copy of an existing repository in a new directory.
1197 Create a copy of an existing repository in a new directory.
1198
1198
1199 If no destination directory name is specified, it defaults to the
1199 If no destination directory name is specified, it defaults to the
1200 basename of the source.
1200 basename of the source.
1201
1201
1202 The location of the source is added to the new repository's
1202 The location of the source is added to the new repository's
1203 ``.hg/hgrc`` file, as the default to be used for future pulls.
1203 ``.hg/hgrc`` file, as the default to be used for future pulls.
1204
1204
1205 Only local paths and ``ssh://`` URLs are supported as
1205 Only local paths and ``ssh://`` URLs are supported as
1206 destinations. For ``ssh://`` destinations, no working directory or
1206 destinations. For ``ssh://`` destinations, no working directory or
1207 ``.hg/hgrc`` will be created on the remote side.
1207 ``.hg/hgrc`` will be created on the remote side.
1208
1208
1209 To pull only a subset of changesets, specify one or more revisions
1209 To pull only a subset of changesets, specify one or more revisions
1210 identifiers with -r/--rev or branches with -b/--branch. The
1210 identifiers with -r/--rev or branches with -b/--branch. The
1211 resulting clone will contain only the specified changesets and
1211 resulting clone will contain only the specified changesets and
1212 their ancestors. These options (or 'clone src#rev dest') imply
1212 their ancestors. These options (or 'clone src#rev dest') imply
1213 --pull, even for local source repositories. Note that specifying a
1213 --pull, even for local source repositories. Note that specifying a
1214 tag will include the tagged changeset but not the changeset
1214 tag will include the tagged changeset but not the changeset
1215 containing the tag.
1215 containing the tag.
1216
1216
1217 If the source repository has a bookmark called '@' set, that
1217 If the source repository has a bookmark called '@' set, that
1218 revision will be checked out in the new repository by default.
1218 revision will be checked out in the new repository by default.
1219
1219
1220 To check out a particular version, use -u/--update, or
1220 To check out a particular version, use -u/--update, or
1221 -U/--noupdate to create a clone with no working directory.
1221 -U/--noupdate to create a clone with no working directory.
1222
1222
1223 .. container:: verbose
1223 .. container:: verbose
1224
1224
1225 For efficiency, hardlinks are used for cloning whenever the
1225 For efficiency, hardlinks are used for cloning whenever the
1226 source and destination are on the same filesystem (note this
1226 source and destination are on the same filesystem (note this
1227 applies only to the repository data, not to the working
1227 applies only to the repository data, not to the working
1228 directory). Some filesystems, such as AFS, implement hardlinking
1228 directory). Some filesystems, such as AFS, implement hardlinking
1229 incorrectly, but do not report errors. In these cases, use the
1229 incorrectly, but do not report errors. In these cases, use the
1230 --pull option to avoid hardlinking.
1230 --pull option to avoid hardlinking.
1231
1231
1232 In some cases, you can clone repositories and the working
1232 In some cases, you can clone repositories and the working
1233 directory using full hardlinks with ::
1233 directory using full hardlinks with ::
1234
1234
1235 $ cp -al REPO REPOCLONE
1235 $ cp -al REPO REPOCLONE
1236
1236
1237 This is the fastest way to clone, but it is not always safe. The
1237 This is the fastest way to clone, but it is not always safe. The
1238 operation is not atomic (making sure REPO is not modified during
1238 operation is not atomic (making sure REPO is not modified during
1239 the operation is up to you) and you have to make sure your
1239 the operation is up to you) and you have to make sure your
1240 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1240 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1241 so). Also, this is not compatible with certain extensions that
1241 so). Also, this is not compatible with certain extensions that
1242 place their metadata under the .hg directory, such as mq.
1242 place their metadata under the .hg directory, such as mq.
1243
1243
1244 Mercurial will update the working directory to the first applicable
1244 Mercurial will update the working directory to the first applicable
1245 revision from this list:
1245 revision from this list:
1246
1246
1247 a) null if -U or the source repository has no changesets
1247 a) null if -U or the source repository has no changesets
1248 b) if -u . and the source repository is local, the first parent of
1248 b) if -u . and the source repository is local, the first parent of
1249 the source repository's working directory
1249 the source repository's working directory
1250 c) the changeset specified with -u (if a branch name, this means the
1250 c) the changeset specified with -u (if a branch name, this means the
1251 latest head of that branch)
1251 latest head of that branch)
1252 d) the changeset specified with -r
1252 d) the changeset specified with -r
1253 e) the tipmost head specified with -b
1253 e) the tipmost head specified with -b
1254 f) the tipmost head specified with the url#branch source syntax
1254 f) the tipmost head specified with the url#branch source syntax
1255 g) the revision marked with the '@' bookmark, if present
1255 g) the revision marked with the '@' bookmark, if present
1256 h) the tipmost head of the default branch
1256 h) the tipmost head of the default branch
1257 i) tip
1257 i) tip
1258
1258
1259 Examples:
1259 Examples:
1260
1260
1261 - clone a remote repository to a new directory named hg/::
1261 - clone a remote repository to a new directory named hg/::
1262
1262
1263 hg clone http://selenic.com/hg
1263 hg clone http://selenic.com/hg
1264
1264
1265 - create a lightweight local clone::
1265 - create a lightweight local clone::
1266
1266
1267 hg clone project/ project-feature/
1267 hg clone project/ project-feature/
1268
1268
1269 - clone from an absolute path on an ssh server (note double-slash)::
1269 - clone from an absolute path on an ssh server (note double-slash)::
1270
1270
1271 hg clone ssh://user@server//home/projects/alpha/
1271 hg clone ssh://user@server//home/projects/alpha/
1272
1272
1273 - do a high-speed clone over a LAN while checking out a
1273 - do a high-speed clone over a LAN while checking out a
1274 specified version::
1274 specified version::
1275
1275
1276 hg clone --uncompressed http://server/repo -u 1.5
1276 hg clone --uncompressed http://server/repo -u 1.5
1277
1277
1278 - create a repository without changesets after a particular revision::
1278 - create a repository without changesets after a particular revision::
1279
1279
1280 hg clone -r 04e544 experimental/ good/
1280 hg clone -r 04e544 experimental/ good/
1281
1281
1282 - clone (and track) a particular named branch::
1282 - clone (and track) a particular named branch::
1283
1283
1284 hg clone http://selenic.com/hg#stable
1284 hg clone http://selenic.com/hg#stable
1285
1285
1286 See :hg:`help urls` for details on specifying URLs.
1286 See :hg:`help urls` for details on specifying URLs.
1287
1287
1288 Returns 0 on success.
1288 Returns 0 on success.
1289 """
1289 """
1290 if opts.get('noupdate') and opts.get('updaterev'):
1290 if opts.get('noupdate') and opts.get('updaterev'):
1291 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1291 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1292
1292
1293 r = hg.clone(ui, opts, source, dest,
1293 r = hg.clone(ui, opts, source, dest,
1294 pull=opts.get('pull'),
1294 pull=opts.get('pull'),
1295 stream=opts.get('uncompressed'),
1295 stream=opts.get('uncompressed'),
1296 rev=opts.get('rev'),
1296 rev=opts.get('rev'),
1297 update=opts.get('updaterev') or not opts.get('noupdate'),
1297 update=opts.get('updaterev') or not opts.get('noupdate'),
1298 branch=opts.get('branch'))
1298 branch=opts.get('branch'))
1299
1299
1300 return r is None
1300 return r is None
1301
1301
1302 @command('^commit|ci',
1302 @command('^commit|ci',
1303 [('A', 'addremove', None,
1303 [('A', 'addremove', None,
1304 _('mark new/missing files as added/removed before committing')),
1304 _('mark new/missing files as added/removed before committing')),
1305 ('', 'close-branch', None,
1305 ('', 'close-branch', None,
1306 _('mark a branch as closed, hiding it from the branch list')),
1306 _('mark a branch as closed, hiding it from the branch list')),
1307 ('', 'amend', None, _('amend the parent of the working dir')),
1307 ('', 'amend', None, _('amend the parent of the working dir')),
1308 ('s', 'secret', None, _('use the secret phase for committing')),
1308 ('s', 'secret', None, _('use the secret phase for committing')),
1309 ('e', 'edit', None,
1309 ('e', 'edit', None,
1310 _('further edit commit message already specified')),
1310 _('further edit commit message already specified')),
1311 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1311 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1312 _('[OPTION]... [FILE]...'))
1312 _('[OPTION]... [FILE]...'))
1313 def commit(ui, repo, *pats, **opts):
1313 def commit(ui, repo, *pats, **opts):
1314 """commit the specified files or all outstanding changes
1314 """commit the specified files or all outstanding changes
1315
1315
1316 Commit changes to the given files into the repository. Unlike a
1316 Commit changes to the given files into the repository. Unlike a
1317 centralized SCM, this operation is a local operation. See
1317 centralized SCM, this operation is a local operation. See
1318 :hg:`push` for a way to actively distribute your changes.
1318 :hg:`push` for a way to actively distribute your changes.
1319
1319
1320 If a list of files is omitted, all changes reported by :hg:`status`
1320 If a list of files is omitted, all changes reported by :hg:`status`
1321 will be committed.
1321 will be committed.
1322
1322
1323 If you are committing the result of a merge, do not provide any
1323 If you are committing the result of a merge, do not provide any
1324 filenames or -I/-X filters.
1324 filenames or -I/-X filters.
1325
1325
1326 If no commit message is specified, Mercurial starts your
1326 If no commit message is specified, Mercurial starts your
1327 configured editor where you can enter a message. In case your
1327 configured editor where you can enter a message. In case your
1328 commit fails, you will find a backup of your message in
1328 commit fails, you will find a backup of your message in
1329 ``.hg/last-message.txt``.
1329 ``.hg/last-message.txt``.
1330
1330
1331 The --amend flag can be used to amend the parent of the
1331 The --amend flag can be used to amend the parent of the
1332 working directory with a new commit that contains the changes
1332 working directory with a new commit that contains the changes
1333 in the parent in addition to those currently reported by :hg:`status`,
1333 in the parent in addition to those currently reported by :hg:`status`,
1334 if there are any. The old commit is stored in a backup bundle in
1334 if there are any. The old commit is stored in a backup bundle in
1335 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1335 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1336 on how to restore it).
1336 on how to restore it).
1337
1337
1338 Message, user and date are taken from the amended commit unless
1338 Message, user and date are taken from the amended commit unless
1339 specified. When a message isn't specified on the command line,
1339 specified. When a message isn't specified on the command line,
1340 the editor will open with the message of the amended commit.
1340 the editor will open with the message of the amended commit.
1341
1341
1342 It is not possible to amend public changesets (see :hg:`help phases`)
1342 It is not possible to amend public changesets (see :hg:`help phases`)
1343 or changesets that have children.
1343 or changesets that have children.
1344
1344
1345 See :hg:`help dates` for a list of formats valid for -d/--date.
1345 See :hg:`help dates` for a list of formats valid for -d/--date.
1346
1346
1347 Returns 0 on success, 1 if nothing changed.
1347 Returns 0 on success, 1 if nothing changed.
1348 """
1348 """
1349 forceeditor = opts.get('edit')
1349 forceeditor = opts.get('edit')
1350
1350
1351 if opts.get('subrepos'):
1351 if opts.get('subrepos'):
1352 if opts.get('amend'):
1352 if opts.get('amend'):
1353 raise util.Abort(_('cannot amend with --subrepos'))
1353 raise util.Abort(_('cannot amend with --subrepos'))
1354 # Let --subrepos on the command line override config setting.
1354 # Let --subrepos on the command line override config setting.
1355 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1355 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1356
1356
1357 # Save this for restoring it later
1357 # Save this for restoring it later
1358 oldcommitphase = ui.config('phases', 'new-commit')
1358 oldcommitphase = ui.config('phases', 'new-commit')
1359
1359
1360 cmdutil.checkunfinished(repo, commit=True)
1360 cmdutil.checkunfinished(repo, commit=True)
1361
1361
1362 branch = repo[None].branch()
1362 branch = repo[None].branch()
1363 bheads = repo.branchheads(branch)
1363 bheads = repo.branchheads(branch)
1364
1364
1365 extra = {}
1365 extra = {}
1366 if opts.get('close_branch'):
1366 if opts.get('close_branch'):
1367 extra['close'] = 1
1367 extra['close'] = 1
1368
1368
1369 if not bheads:
1369 if not bheads:
1370 raise util.Abort(_('can only close branch heads'))
1370 raise util.Abort(_('can only close branch heads'))
1371 elif opts.get('amend'):
1371 elif opts.get('amend'):
1372 if repo.parents()[0].p1().branch() != branch and \
1372 if repo.parents()[0].p1().branch() != branch and \
1373 repo.parents()[0].p2().branch() != branch:
1373 repo.parents()[0].p2().branch() != branch:
1374 raise util.Abort(_('can only close branch heads'))
1374 raise util.Abort(_('can only close branch heads'))
1375
1375
1376 if opts.get('amend'):
1376 if opts.get('amend'):
1377 if ui.configbool('ui', 'commitsubrepos'):
1377 if ui.configbool('ui', 'commitsubrepos'):
1378 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1378 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1379
1379
1380 old = repo['.']
1380 old = repo['.']
1381 if old.phase() == phases.public:
1381 if old.phase() == phases.public:
1382 raise util.Abort(_('cannot amend public changesets'))
1382 raise util.Abort(_('cannot amend public changesets'))
1383 if len(repo[None].parents()) > 1:
1383 if len(repo[None].parents()) > 1:
1384 raise util.Abort(_('cannot amend while merging'))
1384 raise util.Abort(_('cannot amend while merging'))
1385 if (not obsolete._enabled) and old.children():
1385 if (not obsolete._enabled) and old.children():
1386 raise util.Abort(_('cannot amend changeset with children'))
1386 raise util.Abort(_('cannot amend changeset with children'))
1387
1387
1388 # commitfunc is used only for temporary amend commit by cmdutil.amend
1388 # commitfunc is used only for temporary amend commit by cmdutil.amend
1389 def commitfunc(ui, repo, message, match, opts):
1389 def commitfunc(ui, repo, message, match, opts):
1390 return repo.commit(message,
1390 return repo.commit(message,
1391 opts.get('user') or old.user(),
1391 opts.get('user') or old.user(),
1392 opts.get('date') or old.date(),
1392 opts.get('date') or old.date(),
1393 match,
1393 match,
1394 extra=extra)
1394 extra=extra)
1395
1395
1396 current = repo._bookmarkcurrent
1396 current = repo._bookmarkcurrent
1397 marks = old.bookmarks()
1397 marks = old.bookmarks()
1398 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1398 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1399 if node == old.node():
1399 if node == old.node():
1400 ui.status(_("nothing changed\n"))
1400 ui.status(_("nothing changed\n"))
1401 return 1
1401 return 1
1402 elif marks:
1402 elif marks:
1403 ui.debug('moving bookmarks %r from %s to %s\n' %
1403 ui.debug('moving bookmarks %r from %s to %s\n' %
1404 (marks, old.hex(), hex(node)))
1404 (marks, old.hex(), hex(node)))
1405 newmarks = repo._bookmarks
1405 newmarks = repo._bookmarks
1406 for bm in marks:
1406 for bm in marks:
1407 newmarks[bm] = node
1407 newmarks[bm] = node
1408 if bm == current:
1408 if bm == current:
1409 bookmarks.setcurrent(repo, bm)
1409 bookmarks.setcurrent(repo, bm)
1410 newmarks.write()
1410 newmarks.write()
1411 else:
1411 else:
1412 e = cmdutil.commiteditor
1412 e = cmdutil.commiteditor
1413 if forceeditor:
1413 if forceeditor:
1414 e = cmdutil.commitforceeditor
1414 e = cmdutil.commitforceeditor
1415
1415
1416 def commitfunc(ui, repo, message, match, opts):
1416 def commitfunc(ui, repo, message, match, opts):
1417 try:
1417 try:
1418 if opts.get('secret'):
1418 if opts.get('secret'):
1419 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1419 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1420 # Propagate to subrepos
1420 # Propagate to subrepos
1421 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1421 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1422 'commit')
1422 'commit')
1423
1423
1424 return repo.commit(message, opts.get('user'), opts.get('date'),
1424 return repo.commit(message, opts.get('user'), opts.get('date'),
1425 match, editor=e, extra=extra)
1425 match, editor=e, extra=extra)
1426 finally:
1426 finally:
1427 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1427 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1428 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1428 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1429 'commit')
1429 'commit')
1430
1430
1431
1431
1432 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1432 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1433
1433
1434 if not node:
1434 if not node:
1435 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1435 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1436 if stat[3]:
1436 if stat[3]:
1437 ui.status(_("nothing changed (%d missing files, see "
1437 ui.status(_("nothing changed (%d missing files, see "
1438 "'hg status')\n") % len(stat[3]))
1438 "'hg status')\n") % len(stat[3]))
1439 else:
1439 else:
1440 ui.status(_("nothing changed\n"))
1440 ui.status(_("nothing changed\n"))
1441 return 1
1441 return 1
1442
1442
1443 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1443 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1444
1444
1445 @command('config|showconfig|debugconfig',
1445 @command('config|showconfig|debugconfig',
1446 [('u', 'untrusted', None, _('show untrusted configuration options')),
1446 [('u', 'untrusted', None, _('show untrusted configuration options')),
1447 ('e', 'edit', None, _('edit user config')),
1447 ('e', 'edit', None, _('edit user config')),
1448 ('l', 'local', None, _('edit repository config')),
1448 ('l', 'local', None, _('edit repository config')),
1449 ('g', 'global', None, _('edit global config'))],
1449 ('g', 'global', None, _('edit global config'))],
1450 _('[-u] [NAME]...'))
1450 _('[-u] [NAME]...'))
1451 def config(ui, repo, *values, **opts):
1451 def config(ui, repo, *values, **opts):
1452 """show combined config settings from all hgrc files
1452 """show combined config settings from all hgrc files
1453
1453
1454 With no arguments, print names and values of all config items.
1454 With no arguments, print names and values of all config items.
1455
1455
1456 With one argument of the form section.name, print just the value
1456 With one argument of the form section.name, print just the value
1457 of that config item.
1457 of that config item.
1458
1458
1459 With multiple arguments, print names and values of all config
1459 With multiple arguments, print names and values of all config
1460 items with matching section names.
1460 items with matching section names.
1461
1461
1462 With --edit, start an editor on the user-level config file. With
1462 With --edit, start an editor on the user-level config file. With
1463 --global, edit the system-wide config file. With --local, edit the
1463 --global, edit the system-wide config file. With --local, edit the
1464 repository-level config file.
1464 repository-level config file.
1465
1465
1466 With --debug, the source (filename and line number) is printed
1466 With --debug, the source (filename and line number) is printed
1467 for each config item.
1467 for each config item.
1468
1468
1469 See :hg:`help config` for more information about config files.
1469 See :hg:`help config` for more information about config files.
1470
1470
1471 Returns 0 on success.
1471 Returns 0 on success.
1472
1472
1473 """
1473 """
1474
1474
1475 if opts.get('edit') or opts.get('local') or opts.get('global'):
1475 if opts.get('edit') or opts.get('local') or opts.get('global'):
1476 if opts.get('local') and opts.get('global'):
1476 if opts.get('local') and opts.get('global'):
1477 raise util.Abort(_("can't use --local and --global together"))
1477 raise util.Abort(_("can't use --local and --global together"))
1478
1478
1479 if opts.get('local'):
1479 if opts.get('local'):
1480 if not repo:
1480 if not repo:
1481 raise util.Abort(_("can't use --local outside a repository"))
1481 raise util.Abort(_("can't use --local outside a repository"))
1482 paths = [repo.join('hgrc')]
1482 paths = [repo.join('hgrc')]
1483 elif opts.get('global'):
1483 elif opts.get('global'):
1484 paths = scmutil.systemrcpath()
1484 paths = scmutil.systemrcpath()
1485 else:
1485 else:
1486 paths = scmutil.userrcpath()
1486 paths = scmutil.userrcpath()
1487
1487
1488 for f in paths:
1488 for f in paths:
1489 if os.path.exists(f):
1489 if os.path.exists(f):
1490 break
1490 break
1491 else:
1491 else:
1492 f = paths[0]
1492 f = paths[0]
1493 fp = open(f, "w")
1493 fp = open(f, "w")
1494 fp.write(
1494 fp.write(
1495 '# example config (see "hg help config" for more info)\n'
1495 '# example config (see "hg help config" for more info)\n'
1496 '\n'
1496 '\n'
1497 '[ui]\n'
1497 '[ui]\n'
1498 '# name and email, e.g.\n'
1498 '# name and email, e.g.\n'
1499 '# username = Jane Doe <jdoe@example.com>\n'
1499 '# username = Jane Doe <jdoe@example.com>\n'
1500 'username =\n'
1500 'username =\n'
1501 '\n'
1501 '\n'
1502 '[extensions]\n'
1502 '[extensions]\n'
1503 '# uncomment these lines to enable some popular extensions\n'
1503 '# uncomment these lines to enable some popular extensions\n'
1504 '# (see "hg help extensions" for more info)\n'
1504 '# (see "hg help extensions" for more info)\n'
1505 '# pager =\n'
1505 '# pager =\n'
1506 '# progress =\n'
1506 '# progress =\n'
1507 '# color =\n')
1507 '# color =\n')
1508 fp.close()
1508 fp.close()
1509
1509
1510 editor = ui.geteditor()
1510 editor = ui.geteditor()
1511 util.system("%s \"%s\"" % (editor, f),
1511 util.system("%s \"%s\"" % (editor, f),
1512 onerr=util.Abort, errprefix=_("edit failed"),
1512 onerr=util.Abort, errprefix=_("edit failed"),
1513 out=ui.fout)
1513 out=ui.fout)
1514 return
1514 return
1515
1515
1516 for f in scmutil.rcpath():
1516 for f in scmutil.rcpath():
1517 ui.debug('read config from: %s\n' % f)
1517 ui.debug('read config from: %s\n' % f)
1518 untrusted = bool(opts.get('untrusted'))
1518 untrusted = bool(opts.get('untrusted'))
1519 if values:
1519 if values:
1520 sections = [v for v in values if '.' not in v]
1520 sections = [v for v in values if '.' not in v]
1521 items = [v for v in values if '.' in v]
1521 items = [v for v in values if '.' in v]
1522 if len(items) > 1 or items and sections:
1522 if len(items) > 1 or items and sections:
1523 raise util.Abort(_('only one config item permitted'))
1523 raise util.Abort(_('only one config item permitted'))
1524 for section, name, value in ui.walkconfig(untrusted=untrusted):
1524 for section, name, value in ui.walkconfig(untrusted=untrusted):
1525 value = str(value).replace('\n', '\\n')
1525 value = str(value).replace('\n', '\\n')
1526 sectname = section + '.' + name
1526 sectname = section + '.' + name
1527 if values:
1527 if values:
1528 for v in values:
1528 for v in values:
1529 if v == section:
1529 if v == section:
1530 ui.debug('%s: ' %
1530 ui.debug('%s: ' %
1531 ui.configsource(section, name, untrusted))
1531 ui.configsource(section, name, untrusted))
1532 ui.write('%s=%s\n' % (sectname, value))
1532 ui.write('%s=%s\n' % (sectname, value))
1533 elif v == sectname:
1533 elif v == sectname:
1534 ui.debug('%s: ' %
1534 ui.debug('%s: ' %
1535 ui.configsource(section, name, untrusted))
1535 ui.configsource(section, name, untrusted))
1536 ui.write(value, '\n')
1536 ui.write(value, '\n')
1537 else:
1537 else:
1538 ui.debug('%s: ' %
1538 ui.debug('%s: ' %
1539 ui.configsource(section, name, untrusted))
1539 ui.configsource(section, name, untrusted))
1540 ui.write('%s=%s\n' % (sectname, value))
1540 ui.write('%s=%s\n' % (sectname, value))
1541
1541
1542 @command('copy|cp',
1542 @command('copy|cp',
1543 [('A', 'after', None, _('record a copy that has already occurred')),
1543 [('A', 'after', None, _('record a copy that has already occurred')),
1544 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1544 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1545 ] + walkopts + dryrunopts,
1545 ] + walkopts + dryrunopts,
1546 _('[OPTION]... [SOURCE]... DEST'))
1546 _('[OPTION]... [SOURCE]... DEST'))
1547 def copy(ui, repo, *pats, **opts):
1547 def copy(ui, repo, *pats, **opts):
1548 """mark files as copied for the next commit
1548 """mark files as copied for the next commit
1549
1549
1550 Mark dest as having copies of source files. If dest is a
1550 Mark dest as having copies of source files. If dest is a
1551 directory, copies are put in that directory. If dest is a file,
1551 directory, copies are put in that directory. If dest is a file,
1552 the source must be a single file.
1552 the source must be a single file.
1553
1553
1554 By default, this command copies the contents of files as they
1554 By default, this command copies the contents of files as they
1555 exist in the working directory. If invoked with -A/--after, the
1555 exist in the working directory. If invoked with -A/--after, the
1556 operation is recorded, but no copying is performed.
1556 operation is recorded, but no copying is performed.
1557
1557
1558 This command takes effect with the next commit. To undo a copy
1558 This command takes effect with the next commit. To undo a copy
1559 before that, see :hg:`revert`.
1559 before that, see :hg:`revert`.
1560
1560
1561 Returns 0 on success, 1 if errors are encountered.
1561 Returns 0 on success, 1 if errors are encountered.
1562 """
1562 """
1563 wlock = repo.wlock(False)
1563 wlock = repo.wlock(False)
1564 try:
1564 try:
1565 return cmdutil.copy(ui, repo, pats, opts)
1565 return cmdutil.copy(ui, repo, pats, opts)
1566 finally:
1566 finally:
1567 wlock.release()
1567 wlock.release()
1568
1568
1569 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1569 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1570 def debugancestor(ui, repo, *args):
1570 def debugancestor(ui, repo, *args):
1571 """find the ancestor revision of two revisions in a given index"""
1571 """find the ancestor revision of two revisions in a given index"""
1572 if len(args) == 3:
1572 if len(args) == 3:
1573 index, rev1, rev2 = args
1573 index, rev1, rev2 = args
1574 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1574 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1575 lookup = r.lookup
1575 lookup = r.lookup
1576 elif len(args) == 2:
1576 elif len(args) == 2:
1577 if not repo:
1577 if not repo:
1578 raise util.Abort(_("there is no Mercurial repository here "
1578 raise util.Abort(_("there is no Mercurial repository here "
1579 "(.hg not found)"))
1579 "(.hg not found)"))
1580 rev1, rev2 = args
1580 rev1, rev2 = args
1581 r = repo.changelog
1581 r = repo.changelog
1582 lookup = repo.lookup
1582 lookup = repo.lookup
1583 else:
1583 else:
1584 raise util.Abort(_('either two or three arguments required'))
1584 raise util.Abort(_('either two or three arguments required'))
1585 a = r.ancestor(lookup(rev1), lookup(rev2))
1585 a = r.ancestor(lookup(rev1), lookup(rev2))
1586 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1586 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1587
1587
1588 @command('debugbuilddag',
1588 @command('debugbuilddag',
1589 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1589 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1590 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1590 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1591 ('n', 'new-file', None, _('add new file at each rev'))],
1591 ('n', 'new-file', None, _('add new file at each rev'))],
1592 _('[OPTION]... [TEXT]'))
1592 _('[OPTION]... [TEXT]'))
1593 def debugbuilddag(ui, repo, text=None,
1593 def debugbuilddag(ui, repo, text=None,
1594 mergeable_file=False,
1594 mergeable_file=False,
1595 overwritten_file=False,
1595 overwritten_file=False,
1596 new_file=False):
1596 new_file=False):
1597 """builds a repo with a given DAG from scratch in the current empty repo
1597 """builds a repo with a given DAG from scratch in the current empty repo
1598
1598
1599 The description of the DAG is read from stdin if not given on the
1599 The description of the DAG is read from stdin if not given on the
1600 command line.
1600 command line.
1601
1601
1602 Elements:
1602 Elements:
1603
1603
1604 - "+n" is a linear run of n nodes based on the current default parent
1604 - "+n" is a linear run of n nodes based on the current default parent
1605 - "." is a single node based on the current default parent
1605 - "." is a single node based on the current default parent
1606 - "$" resets the default parent to null (implied at the start);
1606 - "$" resets the default parent to null (implied at the start);
1607 otherwise the default parent is always the last node created
1607 otherwise the default parent is always the last node created
1608 - "<p" sets the default parent to the backref p
1608 - "<p" sets the default parent to the backref p
1609 - "*p" is a fork at parent p, which is a backref
1609 - "*p" is a fork at parent p, which is a backref
1610 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1610 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1611 - "/p2" is a merge of the preceding node and p2
1611 - "/p2" is a merge of the preceding node and p2
1612 - ":tag" defines a local tag for the preceding node
1612 - ":tag" defines a local tag for the preceding node
1613 - "@branch" sets the named branch for subsequent nodes
1613 - "@branch" sets the named branch for subsequent nodes
1614 - "#...\\n" is a comment up to the end of the line
1614 - "#...\\n" is a comment up to the end of the line
1615
1615
1616 Whitespace between the above elements is ignored.
1616 Whitespace between the above elements is ignored.
1617
1617
1618 A backref is either
1618 A backref is either
1619
1619
1620 - a number n, which references the node curr-n, where curr is the current
1620 - a number n, which references the node curr-n, where curr is the current
1621 node, or
1621 node, or
1622 - the name of a local tag you placed earlier using ":tag", or
1622 - the name of a local tag you placed earlier using ":tag", or
1623 - empty to denote the default parent.
1623 - empty to denote the default parent.
1624
1624
1625 All string valued-elements are either strictly alphanumeric, or must
1625 All string valued-elements are either strictly alphanumeric, or must
1626 be enclosed in double quotes ("..."), with "\\" as escape character.
1626 be enclosed in double quotes ("..."), with "\\" as escape character.
1627 """
1627 """
1628
1628
1629 if text is None:
1629 if text is None:
1630 ui.status(_("reading DAG from stdin\n"))
1630 ui.status(_("reading DAG from stdin\n"))
1631 text = ui.fin.read()
1631 text = ui.fin.read()
1632
1632
1633 cl = repo.changelog
1633 cl = repo.changelog
1634 if len(cl) > 0:
1634 if len(cl) > 0:
1635 raise util.Abort(_('repository is not empty'))
1635 raise util.Abort(_('repository is not empty'))
1636
1636
1637 # determine number of revs in DAG
1637 # determine number of revs in DAG
1638 total = 0
1638 total = 0
1639 for type, data in dagparser.parsedag(text):
1639 for type, data in dagparser.parsedag(text):
1640 if type == 'n':
1640 if type == 'n':
1641 total += 1
1641 total += 1
1642
1642
1643 if mergeable_file:
1643 if mergeable_file:
1644 linesperrev = 2
1644 linesperrev = 2
1645 # make a file with k lines per rev
1645 # make a file with k lines per rev
1646 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1646 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1647 initialmergedlines.append("")
1647 initialmergedlines.append("")
1648
1648
1649 tags = []
1649 tags = []
1650
1650
1651 lock = tr = None
1651 lock = tr = None
1652 try:
1652 try:
1653 lock = repo.lock()
1653 lock = repo.lock()
1654 tr = repo.transaction("builddag")
1654 tr = repo.transaction("builddag")
1655
1655
1656 at = -1
1656 at = -1
1657 atbranch = 'default'
1657 atbranch = 'default'
1658 nodeids = []
1658 nodeids = []
1659 id = 0
1659 id = 0
1660 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1660 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1661 for type, data in dagparser.parsedag(text):
1661 for type, data in dagparser.parsedag(text):
1662 if type == 'n':
1662 if type == 'n':
1663 ui.note(('node %s\n' % str(data)))
1663 ui.note(('node %s\n' % str(data)))
1664 id, ps = data
1664 id, ps = data
1665
1665
1666 files = []
1666 files = []
1667 fctxs = {}
1667 fctxs = {}
1668
1668
1669 p2 = None
1669 p2 = None
1670 if mergeable_file:
1670 if mergeable_file:
1671 fn = "mf"
1671 fn = "mf"
1672 p1 = repo[ps[0]]
1672 p1 = repo[ps[0]]
1673 if len(ps) > 1:
1673 if len(ps) > 1:
1674 p2 = repo[ps[1]]
1674 p2 = repo[ps[1]]
1675 pa = p1.ancestor(p2)
1675 pa = p1.ancestor(p2)
1676 base, local, other = [x[fn].data() for x in (pa, p1,
1676 base, local, other = [x[fn].data() for x in (pa, p1,
1677 p2)]
1677 p2)]
1678 m3 = simplemerge.Merge3Text(base, local, other)
1678 m3 = simplemerge.Merge3Text(base, local, other)
1679 ml = [l.strip() for l in m3.merge_lines()]
1679 ml = [l.strip() for l in m3.merge_lines()]
1680 ml.append("")
1680 ml.append("")
1681 elif at > 0:
1681 elif at > 0:
1682 ml = p1[fn].data().split("\n")
1682 ml = p1[fn].data().split("\n")
1683 else:
1683 else:
1684 ml = initialmergedlines
1684 ml = initialmergedlines
1685 ml[id * linesperrev] += " r%i" % id
1685 ml[id * linesperrev] += " r%i" % id
1686 mergedtext = "\n".join(ml)
1686 mergedtext = "\n".join(ml)
1687 files.append(fn)
1687 files.append(fn)
1688 fctxs[fn] = context.memfilectx(fn, mergedtext)
1688 fctxs[fn] = context.memfilectx(fn, mergedtext)
1689
1689
1690 if overwritten_file:
1690 if overwritten_file:
1691 fn = "of"
1691 fn = "of"
1692 files.append(fn)
1692 files.append(fn)
1693 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1693 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1694
1694
1695 if new_file:
1695 if new_file:
1696 fn = "nf%i" % id
1696 fn = "nf%i" % id
1697 files.append(fn)
1697 files.append(fn)
1698 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1698 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1699 if len(ps) > 1:
1699 if len(ps) > 1:
1700 if not p2:
1700 if not p2:
1701 p2 = repo[ps[1]]
1701 p2 = repo[ps[1]]
1702 for fn in p2:
1702 for fn in p2:
1703 if fn.startswith("nf"):
1703 if fn.startswith("nf"):
1704 files.append(fn)
1704 files.append(fn)
1705 fctxs[fn] = p2[fn]
1705 fctxs[fn] = p2[fn]
1706
1706
1707 def fctxfn(repo, cx, path):
1707 def fctxfn(repo, cx, path):
1708 return fctxs.get(path)
1708 return fctxs.get(path)
1709
1709
1710 if len(ps) == 0 or ps[0] < 0:
1710 if len(ps) == 0 or ps[0] < 0:
1711 pars = [None, None]
1711 pars = [None, None]
1712 elif len(ps) == 1:
1712 elif len(ps) == 1:
1713 pars = [nodeids[ps[0]], None]
1713 pars = [nodeids[ps[0]], None]
1714 else:
1714 else:
1715 pars = [nodeids[p] for p in ps]
1715 pars = [nodeids[p] for p in ps]
1716 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1716 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1717 date=(id, 0),
1717 date=(id, 0),
1718 user="debugbuilddag",
1718 user="debugbuilddag",
1719 extra={'branch': atbranch})
1719 extra={'branch': atbranch})
1720 nodeid = repo.commitctx(cx)
1720 nodeid = repo.commitctx(cx)
1721 nodeids.append(nodeid)
1721 nodeids.append(nodeid)
1722 at = id
1722 at = id
1723 elif type == 'l':
1723 elif type == 'l':
1724 id, name = data
1724 id, name = data
1725 ui.note(('tag %s\n' % name))
1725 ui.note(('tag %s\n' % name))
1726 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1726 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1727 elif type == 'a':
1727 elif type == 'a':
1728 ui.note(('branch %s\n' % data))
1728 ui.note(('branch %s\n' % data))
1729 atbranch = data
1729 atbranch = data
1730 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1730 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1731 tr.close()
1731 tr.close()
1732
1732
1733 if tags:
1733 if tags:
1734 repo.opener.write("localtags", "".join(tags))
1734 repo.opener.write("localtags", "".join(tags))
1735 finally:
1735 finally:
1736 ui.progress(_('building'), None)
1736 ui.progress(_('building'), None)
1737 release(tr, lock)
1737 release(tr, lock)
1738
1738
1739 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1739 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1740 def debugbundle(ui, bundlepath, all=None, **opts):
1740 def debugbundle(ui, bundlepath, all=None, **opts):
1741 """lists the contents of a bundle"""
1741 """lists the contents of a bundle"""
1742 f = hg.openpath(ui, bundlepath)
1742 f = hg.openpath(ui, bundlepath)
1743 try:
1743 try:
1744 gen = exchange.readbundle(ui, f, bundlepath)
1744 gen = exchange.readbundle(ui, f, bundlepath)
1745 if all:
1745 if all:
1746 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1746 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1747
1747
1748 def showchunks(named):
1748 def showchunks(named):
1749 ui.write("\n%s\n" % named)
1749 ui.write("\n%s\n" % named)
1750 chain = None
1750 chain = None
1751 while True:
1751 while True:
1752 chunkdata = gen.deltachunk(chain)
1752 chunkdata = gen.deltachunk(chain)
1753 if not chunkdata:
1753 if not chunkdata:
1754 break
1754 break
1755 node = chunkdata['node']
1755 node = chunkdata['node']
1756 p1 = chunkdata['p1']
1756 p1 = chunkdata['p1']
1757 p2 = chunkdata['p2']
1757 p2 = chunkdata['p2']
1758 cs = chunkdata['cs']
1758 cs = chunkdata['cs']
1759 deltabase = chunkdata['deltabase']
1759 deltabase = chunkdata['deltabase']
1760 delta = chunkdata['delta']
1760 delta = chunkdata['delta']
1761 ui.write("%s %s %s %s %s %s\n" %
1761 ui.write("%s %s %s %s %s %s\n" %
1762 (hex(node), hex(p1), hex(p2),
1762 (hex(node), hex(p1), hex(p2),
1763 hex(cs), hex(deltabase), len(delta)))
1763 hex(cs), hex(deltabase), len(delta)))
1764 chain = node
1764 chain = node
1765
1765
1766 chunkdata = gen.changelogheader()
1766 chunkdata = gen.changelogheader()
1767 showchunks("changelog")
1767 showchunks("changelog")
1768 chunkdata = gen.manifestheader()
1768 chunkdata = gen.manifestheader()
1769 showchunks("manifest")
1769 showchunks("manifest")
1770 while True:
1770 while True:
1771 chunkdata = gen.filelogheader()
1771 chunkdata = gen.filelogheader()
1772 if not chunkdata:
1772 if not chunkdata:
1773 break
1773 break
1774 fname = chunkdata['filename']
1774 fname = chunkdata['filename']
1775 showchunks(fname)
1775 showchunks(fname)
1776 else:
1776 else:
1777 chunkdata = gen.changelogheader()
1777 chunkdata = gen.changelogheader()
1778 chain = None
1778 chain = None
1779 while True:
1779 while True:
1780 chunkdata = gen.deltachunk(chain)
1780 chunkdata = gen.deltachunk(chain)
1781 if not chunkdata:
1781 if not chunkdata:
1782 break
1782 break
1783 node = chunkdata['node']
1783 node = chunkdata['node']
1784 ui.write("%s\n" % hex(node))
1784 ui.write("%s\n" % hex(node))
1785 chain = node
1785 chain = node
1786 finally:
1786 finally:
1787 f.close()
1787 f.close()
1788
1788
1789 @command('debugcheckstate', [], '')
1789 @command('debugcheckstate', [], '')
1790 def debugcheckstate(ui, repo):
1790 def debugcheckstate(ui, repo):
1791 """validate the correctness of the current dirstate"""
1791 """validate the correctness of the current dirstate"""
1792 parent1, parent2 = repo.dirstate.parents()
1792 parent1, parent2 = repo.dirstate.parents()
1793 m1 = repo[parent1].manifest()
1793 m1 = repo[parent1].manifest()
1794 m2 = repo[parent2].manifest()
1794 m2 = repo[parent2].manifest()
1795 errors = 0
1795 errors = 0
1796 for f in repo.dirstate:
1796 for f in repo.dirstate:
1797 state = repo.dirstate[f]
1797 state = repo.dirstate[f]
1798 if state in "nr" and f not in m1:
1798 if state in "nr" and f not in m1:
1799 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1799 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1800 errors += 1
1800 errors += 1
1801 if state in "a" and f in m1:
1801 if state in "a" and f in m1:
1802 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1802 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1803 errors += 1
1803 errors += 1
1804 if state in "m" and f not in m1 and f not in m2:
1804 if state in "m" and f not in m1 and f not in m2:
1805 ui.warn(_("%s in state %s, but not in either manifest\n") %
1805 ui.warn(_("%s in state %s, but not in either manifest\n") %
1806 (f, state))
1806 (f, state))
1807 errors += 1
1807 errors += 1
1808 for f in m1:
1808 for f in m1:
1809 state = repo.dirstate[f]
1809 state = repo.dirstate[f]
1810 if state not in "nrm":
1810 if state not in "nrm":
1811 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1811 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1812 errors += 1
1812 errors += 1
1813 if errors:
1813 if errors:
1814 error = _(".hg/dirstate inconsistent with current parent's manifest")
1814 error = _(".hg/dirstate inconsistent with current parent's manifest")
1815 raise util.Abort(error)
1815 raise util.Abort(error)
1816
1816
1817 @command('debugcommands', [], _('[COMMAND]'))
1817 @command('debugcommands', [], _('[COMMAND]'))
1818 def debugcommands(ui, cmd='', *args):
1818 def debugcommands(ui, cmd='', *args):
1819 """list all available commands and options"""
1819 """list all available commands and options"""
1820 for cmd, vals in sorted(table.iteritems()):
1820 for cmd, vals in sorted(table.iteritems()):
1821 cmd = cmd.split('|')[0].strip('^')
1821 cmd = cmd.split('|')[0].strip('^')
1822 opts = ', '.join([i[1] for i in vals[1]])
1822 opts = ', '.join([i[1] for i in vals[1]])
1823 ui.write('%s: %s\n' % (cmd, opts))
1823 ui.write('%s: %s\n' % (cmd, opts))
1824
1824
1825 @command('debugcomplete',
1825 @command('debugcomplete',
1826 [('o', 'options', None, _('show the command options'))],
1826 [('o', 'options', None, _('show the command options'))],
1827 _('[-o] CMD'))
1827 _('[-o] CMD'))
1828 def debugcomplete(ui, cmd='', **opts):
1828 def debugcomplete(ui, cmd='', **opts):
1829 """returns the completion list associated with the given command"""
1829 """returns the completion list associated with the given command"""
1830
1830
1831 if opts.get('options'):
1831 if opts.get('options'):
1832 options = []
1832 options = []
1833 otables = [globalopts]
1833 otables = [globalopts]
1834 if cmd:
1834 if cmd:
1835 aliases, entry = cmdutil.findcmd(cmd, table, False)
1835 aliases, entry = cmdutil.findcmd(cmd, table, False)
1836 otables.append(entry[1])
1836 otables.append(entry[1])
1837 for t in otables:
1837 for t in otables:
1838 for o in t:
1838 for o in t:
1839 if "(DEPRECATED)" in o[3]:
1839 if "(DEPRECATED)" in o[3]:
1840 continue
1840 continue
1841 if o[0]:
1841 if o[0]:
1842 options.append('-%s' % o[0])
1842 options.append('-%s' % o[0])
1843 options.append('--%s' % o[1])
1843 options.append('--%s' % o[1])
1844 ui.write("%s\n" % "\n".join(options))
1844 ui.write("%s\n" % "\n".join(options))
1845 return
1845 return
1846
1846
1847 cmdlist = cmdutil.findpossible(cmd, table)
1847 cmdlist = cmdutil.findpossible(cmd, table)
1848 if ui.verbose:
1848 if ui.verbose:
1849 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1849 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1850 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1850 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1851
1851
1852 @command('debugdag',
1852 @command('debugdag',
1853 [('t', 'tags', None, _('use tags as labels')),
1853 [('t', 'tags', None, _('use tags as labels')),
1854 ('b', 'branches', None, _('annotate with branch names')),
1854 ('b', 'branches', None, _('annotate with branch names')),
1855 ('', 'dots', None, _('use dots for runs')),
1855 ('', 'dots', None, _('use dots for runs')),
1856 ('s', 'spaces', None, _('separate elements by spaces'))],
1856 ('s', 'spaces', None, _('separate elements by spaces'))],
1857 _('[OPTION]... [FILE [REV]...]'))
1857 _('[OPTION]... [FILE [REV]...]'))
1858 def debugdag(ui, repo, file_=None, *revs, **opts):
1858 def debugdag(ui, repo, file_=None, *revs, **opts):
1859 """format the changelog or an index DAG as a concise textual description
1859 """format the changelog or an index DAG as a concise textual description
1860
1860
1861 If you pass a revlog index, the revlog's DAG is emitted. If you list
1861 If you pass a revlog index, the revlog's DAG is emitted. If you list
1862 revision numbers, they get labeled in the output as rN.
1862 revision numbers, they get labeled in the output as rN.
1863
1863
1864 Otherwise, the changelog DAG of the current repo is emitted.
1864 Otherwise, the changelog DAG of the current repo is emitted.
1865 """
1865 """
1866 spaces = opts.get('spaces')
1866 spaces = opts.get('spaces')
1867 dots = opts.get('dots')
1867 dots = opts.get('dots')
1868 if file_:
1868 if file_:
1869 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1869 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1870 revs = set((int(r) for r in revs))
1870 revs = set((int(r) for r in revs))
1871 def events():
1871 def events():
1872 for r in rlog:
1872 for r in rlog:
1873 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1873 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1874 if p != -1)))
1874 if p != -1)))
1875 if r in revs:
1875 if r in revs:
1876 yield 'l', (r, "r%i" % r)
1876 yield 'l', (r, "r%i" % r)
1877 elif repo:
1877 elif repo:
1878 cl = repo.changelog
1878 cl = repo.changelog
1879 tags = opts.get('tags')
1879 tags = opts.get('tags')
1880 branches = opts.get('branches')
1880 branches = opts.get('branches')
1881 if tags:
1881 if tags:
1882 labels = {}
1882 labels = {}
1883 for l, n in repo.tags().items():
1883 for l, n in repo.tags().items():
1884 labels.setdefault(cl.rev(n), []).append(l)
1884 labels.setdefault(cl.rev(n), []).append(l)
1885 def events():
1885 def events():
1886 b = "default"
1886 b = "default"
1887 for r in cl:
1887 for r in cl:
1888 if branches:
1888 if branches:
1889 newb = cl.read(cl.node(r))[5]['branch']
1889 newb = cl.read(cl.node(r))[5]['branch']
1890 if newb != b:
1890 if newb != b:
1891 yield 'a', newb
1891 yield 'a', newb
1892 b = newb
1892 b = newb
1893 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1893 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1894 if p != -1)))
1894 if p != -1)))
1895 if tags:
1895 if tags:
1896 ls = labels.get(r)
1896 ls = labels.get(r)
1897 if ls:
1897 if ls:
1898 for l in ls:
1898 for l in ls:
1899 yield 'l', (r, l)
1899 yield 'l', (r, l)
1900 else:
1900 else:
1901 raise util.Abort(_('need repo for changelog dag'))
1901 raise util.Abort(_('need repo for changelog dag'))
1902
1902
1903 for line in dagparser.dagtextlines(events(),
1903 for line in dagparser.dagtextlines(events(),
1904 addspaces=spaces,
1904 addspaces=spaces,
1905 wraplabels=True,
1905 wraplabels=True,
1906 wrapannotations=True,
1906 wrapannotations=True,
1907 wrapnonlinear=dots,
1907 wrapnonlinear=dots,
1908 usedots=dots,
1908 usedots=dots,
1909 maxlinewidth=70):
1909 maxlinewidth=70):
1910 ui.write(line)
1910 ui.write(line)
1911 ui.write("\n")
1911 ui.write("\n")
1912
1912
1913 @command('debugdata',
1913 @command('debugdata',
1914 [('c', 'changelog', False, _('open changelog')),
1914 [('c', 'changelog', False, _('open changelog')),
1915 ('m', 'manifest', False, _('open manifest'))],
1915 ('m', 'manifest', False, _('open manifest'))],
1916 _('-c|-m|FILE REV'))
1916 _('-c|-m|FILE REV'))
1917 def debugdata(ui, repo, file_, rev=None, **opts):
1917 def debugdata(ui, repo, file_, rev=None, **opts):
1918 """dump the contents of a data file revision"""
1918 """dump the contents of a data file revision"""
1919 if opts.get('changelog') or opts.get('manifest'):
1919 if opts.get('changelog') or opts.get('manifest'):
1920 file_, rev = None, file_
1920 file_, rev = None, file_
1921 elif rev is None:
1921 elif rev is None:
1922 raise error.CommandError('debugdata', _('invalid arguments'))
1922 raise error.CommandError('debugdata', _('invalid arguments'))
1923 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1923 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1924 try:
1924 try:
1925 ui.write(r.revision(r.lookup(rev)))
1925 ui.write(r.revision(r.lookup(rev)))
1926 except KeyError:
1926 except KeyError:
1927 raise util.Abort(_('invalid revision identifier %s') % rev)
1927 raise util.Abort(_('invalid revision identifier %s') % rev)
1928
1928
1929 @command('debugdate',
1929 @command('debugdate',
1930 [('e', 'extended', None, _('try extended date formats'))],
1930 [('e', 'extended', None, _('try extended date formats'))],
1931 _('[-e] DATE [RANGE]'))
1931 _('[-e] DATE [RANGE]'))
1932 def debugdate(ui, date, range=None, **opts):
1932 def debugdate(ui, date, range=None, **opts):
1933 """parse and display a date"""
1933 """parse and display a date"""
1934 if opts["extended"]:
1934 if opts["extended"]:
1935 d = util.parsedate(date, util.extendeddateformats)
1935 d = util.parsedate(date, util.extendeddateformats)
1936 else:
1936 else:
1937 d = util.parsedate(date)
1937 d = util.parsedate(date)
1938 ui.write(("internal: %s %s\n") % d)
1938 ui.write(("internal: %s %s\n") % d)
1939 ui.write(("standard: %s\n") % util.datestr(d))
1939 ui.write(("standard: %s\n") % util.datestr(d))
1940 if range:
1940 if range:
1941 m = util.matchdate(range)
1941 m = util.matchdate(range)
1942 ui.write(("match: %s\n") % m(d[0]))
1942 ui.write(("match: %s\n") % m(d[0]))
1943
1943
1944 @command('debugdiscovery',
1944 @command('debugdiscovery',
1945 [('', 'old', None, _('use old-style discovery')),
1945 [('', 'old', None, _('use old-style discovery')),
1946 ('', 'nonheads', None,
1946 ('', 'nonheads', None,
1947 _('use old-style discovery with non-heads included')),
1947 _('use old-style discovery with non-heads included')),
1948 ] + remoteopts,
1948 ] + remoteopts,
1949 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1949 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1950 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1950 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1951 """runs the changeset discovery protocol in isolation"""
1951 """runs the changeset discovery protocol in isolation"""
1952 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1952 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1953 opts.get('branch'))
1953 opts.get('branch'))
1954 remote = hg.peer(repo, opts, remoteurl)
1954 remote = hg.peer(repo, opts, remoteurl)
1955 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1955 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1956
1956
1957 # make sure tests are repeatable
1957 # make sure tests are repeatable
1958 random.seed(12323)
1958 random.seed(12323)
1959
1959
1960 def doit(localheads, remoteheads, remote=remote):
1960 def doit(localheads, remoteheads, remote=remote):
1961 if opts.get('old'):
1961 if opts.get('old'):
1962 if localheads:
1962 if localheads:
1963 raise util.Abort('cannot use localheads with old style '
1963 raise util.Abort('cannot use localheads with old style '
1964 'discovery')
1964 'discovery')
1965 if not util.safehasattr(remote, 'branches'):
1965 if not util.safehasattr(remote, 'branches'):
1966 # enable in-client legacy support
1966 # enable in-client legacy support
1967 remote = localrepo.locallegacypeer(remote.local())
1967 remote = localrepo.locallegacypeer(remote.local())
1968 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1968 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1969 force=True)
1969 force=True)
1970 common = set(common)
1970 common = set(common)
1971 if not opts.get('nonheads'):
1971 if not opts.get('nonheads'):
1972 ui.write(("unpruned common: %s\n") %
1972 ui.write(("unpruned common: %s\n") %
1973 " ".join(sorted(short(n) for n in common)))
1973 " ".join(sorted(short(n) for n in common)))
1974 dag = dagutil.revlogdag(repo.changelog)
1974 dag = dagutil.revlogdag(repo.changelog)
1975 all = dag.ancestorset(dag.internalizeall(common))
1975 all = dag.ancestorset(dag.internalizeall(common))
1976 common = dag.externalizeall(dag.headsetofconnecteds(all))
1976 common = dag.externalizeall(dag.headsetofconnecteds(all))
1977 else:
1977 else:
1978 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1978 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1979 common = set(common)
1979 common = set(common)
1980 rheads = set(hds)
1980 rheads = set(hds)
1981 lheads = set(repo.heads())
1981 lheads = set(repo.heads())
1982 ui.write(("common heads: %s\n") %
1982 ui.write(("common heads: %s\n") %
1983 " ".join(sorted(short(n) for n in common)))
1983 " ".join(sorted(short(n) for n in common)))
1984 if lheads <= common:
1984 if lheads <= common:
1985 ui.write(("local is subset\n"))
1985 ui.write(("local is subset\n"))
1986 elif rheads <= common:
1986 elif rheads <= common:
1987 ui.write(("remote is subset\n"))
1987 ui.write(("remote is subset\n"))
1988
1988
1989 serverlogs = opts.get('serverlog')
1989 serverlogs = opts.get('serverlog')
1990 if serverlogs:
1990 if serverlogs:
1991 for filename in serverlogs:
1991 for filename in serverlogs:
1992 logfile = open(filename, 'r')
1992 logfile = open(filename, 'r')
1993 try:
1993 try:
1994 line = logfile.readline()
1994 line = logfile.readline()
1995 while line:
1995 while line:
1996 parts = line.strip().split(';')
1996 parts = line.strip().split(';')
1997 op = parts[1]
1997 op = parts[1]
1998 if op == 'cg':
1998 if op == 'cg':
1999 pass
1999 pass
2000 elif op == 'cgss':
2000 elif op == 'cgss':
2001 doit(parts[2].split(' '), parts[3].split(' '))
2001 doit(parts[2].split(' '), parts[3].split(' '))
2002 elif op == 'unb':
2002 elif op == 'unb':
2003 doit(parts[3].split(' '), parts[2].split(' '))
2003 doit(parts[3].split(' '), parts[2].split(' '))
2004 line = logfile.readline()
2004 line = logfile.readline()
2005 finally:
2005 finally:
2006 logfile.close()
2006 logfile.close()
2007
2007
2008 else:
2008 else:
2009 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2009 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2010 opts.get('remote_head'))
2010 opts.get('remote_head'))
2011 localrevs = opts.get('local_head')
2011 localrevs = opts.get('local_head')
2012 doit(localrevs, remoterevs)
2012 doit(localrevs, remoterevs)
2013
2013
2014 @command('debugfileset',
2014 @command('debugfileset',
2015 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2015 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2016 _('[-r REV] FILESPEC'))
2016 _('[-r REV] FILESPEC'))
2017 def debugfileset(ui, repo, expr, **opts):
2017 def debugfileset(ui, repo, expr, **opts):
2018 '''parse and apply a fileset specification'''
2018 '''parse and apply a fileset specification'''
2019 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2019 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2020 if ui.verbose:
2020 if ui.verbose:
2021 tree = fileset.parse(expr)[0]
2021 tree = fileset.parse(expr)[0]
2022 ui.note(tree, "\n")
2022 ui.note(tree, "\n")
2023
2023
2024 for f in ctx.getfileset(expr):
2024 for f in ctx.getfileset(expr):
2025 ui.write("%s\n" % f)
2025 ui.write("%s\n" % f)
2026
2026
2027 @command('debugfsinfo', [], _('[PATH]'))
2027 @command('debugfsinfo', [], _('[PATH]'))
2028 def debugfsinfo(ui, path="."):
2028 def debugfsinfo(ui, path="."):
2029 """show information detected about current filesystem"""
2029 """show information detected about current filesystem"""
2030 util.writefile('.debugfsinfo', '')
2030 util.writefile('.debugfsinfo', '')
2031 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2031 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2032 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2032 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2033 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2033 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2034 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2034 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2035 and 'yes' or 'no'))
2035 and 'yes' or 'no'))
2036 os.unlink('.debugfsinfo')
2036 os.unlink('.debugfsinfo')
2037
2037
2038 @command('debuggetbundle',
2038 @command('debuggetbundle',
2039 [('H', 'head', [], _('id of head node'), _('ID')),
2039 [('H', 'head', [], _('id of head node'), _('ID')),
2040 ('C', 'common', [], _('id of common node'), _('ID')),
2040 ('C', 'common', [], _('id of common node'), _('ID')),
2041 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2041 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2042 _('REPO FILE [-H|-C ID]...'))
2042 _('REPO FILE [-H|-C ID]...'))
2043 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2043 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2044 """retrieves a bundle from a repo
2044 """retrieves a bundle from a repo
2045
2045
2046 Every ID must be a full-length hex node id string. Saves the bundle to the
2046 Every ID must be a full-length hex node id string. Saves the bundle to the
2047 given file.
2047 given file.
2048 """
2048 """
2049 repo = hg.peer(ui, opts, repopath)
2049 repo = hg.peer(ui, opts, repopath)
2050 if not repo.capable('getbundle'):
2050 if not repo.capable('getbundle'):
2051 raise util.Abort("getbundle() not supported by target repository")
2051 raise util.Abort("getbundle() not supported by target repository")
2052 args = {}
2052 args = {}
2053 if common:
2053 if common:
2054 args['common'] = [bin(s) for s in common]
2054 args['common'] = [bin(s) for s in common]
2055 if head:
2055 if head:
2056 args['heads'] = [bin(s) for s in head]
2056 args['heads'] = [bin(s) for s in head]
2057 # TODO: get desired bundlecaps from command line.
2057 # TODO: get desired bundlecaps from command line.
2058 args['bundlecaps'] = None
2058 args['bundlecaps'] = None
2059 bundle = repo.getbundle('debug', **args)
2059 bundle = repo.getbundle('debug', **args)
2060
2060
2061 bundletype = opts.get('type', 'bzip2').lower()
2061 bundletype = opts.get('type', 'bzip2').lower()
2062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2063 bundletype = btypes.get(bundletype)
2063 bundletype = btypes.get(bundletype)
2064 if bundletype not in changegroup.bundletypes:
2064 if bundletype not in changegroup.bundletypes:
2065 raise util.Abort(_('unknown bundle type specified with --type'))
2065 raise util.Abort(_('unknown bundle type specified with --type'))
2066 changegroup.writebundle(bundle, bundlepath, bundletype)
2066 changegroup.writebundle(bundle, bundlepath, bundletype)
2067
2067
2068 @command('debugignore', [], '')
2068 @command('debugignore', [], '')
2069 def debugignore(ui, repo, *values, **opts):
2069 def debugignore(ui, repo, *values, **opts):
2070 """display the combined ignore pattern"""
2070 """display the combined ignore pattern"""
2071 ignore = repo.dirstate._ignore
2071 ignore = repo.dirstate._ignore
2072 includepat = getattr(ignore, 'includepat', None)
2072 includepat = getattr(ignore, 'includepat', None)
2073 if includepat is not None:
2073 if includepat is not None:
2074 ui.write("%s\n" % includepat)
2074 ui.write("%s\n" % includepat)
2075 else:
2075 else:
2076 raise util.Abort(_("no ignore patterns found"))
2076 raise util.Abort(_("no ignore patterns found"))
2077
2077
2078 @command('debugindex',
2078 @command('debugindex',
2079 [('c', 'changelog', False, _('open changelog')),
2079 [('c', 'changelog', False, _('open changelog')),
2080 ('m', 'manifest', False, _('open manifest')),
2080 ('m', 'manifest', False, _('open manifest')),
2081 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2081 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2082 _('[-f FORMAT] -c|-m|FILE'))
2082 _('[-f FORMAT] -c|-m|FILE'))
2083 def debugindex(ui, repo, file_=None, **opts):
2083 def debugindex(ui, repo, file_=None, **opts):
2084 """dump the contents of an index file"""
2084 """dump the contents of an index file"""
2085 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2085 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2086 format = opts.get('format', 0)
2086 format = opts.get('format', 0)
2087 if format not in (0, 1):
2087 if format not in (0, 1):
2088 raise util.Abort(_("unknown format %d") % format)
2088 raise util.Abort(_("unknown format %d") % format)
2089
2089
2090 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2090 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2091 if generaldelta:
2091 if generaldelta:
2092 basehdr = ' delta'
2092 basehdr = ' delta'
2093 else:
2093 else:
2094 basehdr = ' base'
2094 basehdr = ' base'
2095
2095
2096 if format == 0:
2096 if format == 0:
2097 ui.write(" rev offset length " + basehdr + " linkrev"
2097 ui.write(" rev offset length " + basehdr + " linkrev"
2098 " nodeid p1 p2\n")
2098 " nodeid p1 p2\n")
2099 elif format == 1:
2099 elif format == 1:
2100 ui.write(" rev flag offset length"
2100 ui.write(" rev flag offset length"
2101 " size " + basehdr + " link p1 p2"
2101 " size " + basehdr + " link p1 p2"
2102 " nodeid\n")
2102 " nodeid\n")
2103
2103
2104 for i in r:
2104 for i in r:
2105 node = r.node(i)
2105 node = r.node(i)
2106 if generaldelta:
2106 if generaldelta:
2107 base = r.deltaparent(i)
2107 base = r.deltaparent(i)
2108 else:
2108 else:
2109 base = r.chainbase(i)
2109 base = r.chainbase(i)
2110 if format == 0:
2110 if format == 0:
2111 try:
2111 try:
2112 pp = r.parents(node)
2112 pp = r.parents(node)
2113 except Exception:
2113 except Exception:
2114 pp = [nullid, nullid]
2114 pp = [nullid, nullid]
2115 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2115 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2116 i, r.start(i), r.length(i), base, r.linkrev(i),
2116 i, r.start(i), r.length(i), base, r.linkrev(i),
2117 short(node), short(pp[0]), short(pp[1])))
2117 short(node), short(pp[0]), short(pp[1])))
2118 elif format == 1:
2118 elif format == 1:
2119 pr = r.parentrevs(i)
2119 pr = r.parentrevs(i)
2120 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2120 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2121 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2121 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2122 base, r.linkrev(i), pr[0], pr[1], short(node)))
2122 base, r.linkrev(i), pr[0], pr[1], short(node)))
2123
2123
2124 @command('debugindexdot', [], _('FILE'))
2124 @command('debugindexdot', [], _('FILE'))
2125 def debugindexdot(ui, repo, file_):
2125 def debugindexdot(ui, repo, file_):
2126 """dump an index DAG as a graphviz dot file"""
2126 """dump an index DAG as a graphviz dot file"""
2127 r = None
2127 r = None
2128 if repo:
2128 if repo:
2129 filelog = repo.file(file_)
2129 filelog = repo.file(file_)
2130 if len(filelog):
2130 if len(filelog):
2131 r = filelog
2131 r = filelog
2132 if not r:
2132 if not r:
2133 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2133 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2134 ui.write(("digraph G {\n"))
2134 ui.write(("digraph G {\n"))
2135 for i in r:
2135 for i in r:
2136 node = r.node(i)
2136 node = r.node(i)
2137 pp = r.parents(node)
2137 pp = r.parents(node)
2138 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2138 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2139 if pp[1] != nullid:
2139 if pp[1] != nullid:
2140 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2140 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2141 ui.write("}\n")
2141 ui.write("}\n")
2142
2142
2143 @command('debuginstall', [], '')
2143 @command('debuginstall', [], '')
2144 def debuginstall(ui):
2144 def debuginstall(ui):
2145 '''test Mercurial installation
2145 '''test Mercurial installation
2146
2146
2147 Returns 0 on success.
2147 Returns 0 on success.
2148 '''
2148 '''
2149
2149
2150 def writetemp(contents):
2150 def writetemp(contents):
2151 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2151 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2152 f = os.fdopen(fd, "wb")
2152 f = os.fdopen(fd, "wb")
2153 f.write(contents)
2153 f.write(contents)
2154 f.close()
2154 f.close()
2155 return name
2155 return name
2156
2156
2157 problems = 0
2157 problems = 0
2158
2158
2159 # encoding
2159 # encoding
2160 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2160 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2161 try:
2161 try:
2162 encoding.fromlocal("test")
2162 encoding.fromlocal("test")
2163 except util.Abort, inst:
2163 except util.Abort, inst:
2164 ui.write(" %s\n" % inst)
2164 ui.write(" %s\n" % inst)
2165 ui.write(_(" (check that your locale is properly set)\n"))
2165 ui.write(_(" (check that your locale is properly set)\n"))
2166 problems += 1
2166 problems += 1
2167
2167
2168 # Python
2168 # Python
2169 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2169 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2170 ui.status(_("checking Python version (%s)\n")
2170 ui.status(_("checking Python version (%s)\n")
2171 % ("%s.%s.%s" % sys.version_info[:3]))
2171 % ("%s.%s.%s" % sys.version_info[:3]))
2172 ui.status(_("checking Python lib (%s)...\n")
2172 ui.status(_("checking Python lib (%s)...\n")
2173 % os.path.dirname(os.__file__))
2173 % os.path.dirname(os.__file__))
2174
2174
2175 # compiled modules
2175 # compiled modules
2176 ui.status(_("checking installed modules (%s)...\n")
2176 ui.status(_("checking installed modules (%s)...\n")
2177 % os.path.dirname(__file__))
2177 % os.path.dirname(__file__))
2178 try:
2178 try:
2179 import bdiff, mpatch, base85, osutil
2179 import bdiff, mpatch, base85, osutil
2180 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2180 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2181 except Exception, inst:
2181 except Exception, inst:
2182 ui.write(" %s\n" % inst)
2182 ui.write(" %s\n" % inst)
2183 ui.write(_(" One or more extensions could not be found"))
2183 ui.write(_(" One or more extensions could not be found"))
2184 ui.write(_(" (check that you compiled the extensions)\n"))
2184 ui.write(_(" (check that you compiled the extensions)\n"))
2185 problems += 1
2185 problems += 1
2186
2186
2187 # templates
2187 # templates
2188 import templater
2188 import templater
2189 p = templater.templatepath()
2189 p = templater.templatepath()
2190 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2190 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2191 if p:
2191 if p:
2192 m = templater.templatepath("map-cmdline.default")
2192 m = templater.templatepath("map-cmdline.default")
2193 if m:
2193 if m:
2194 # template found, check if it is working
2194 # template found, check if it is working
2195 try:
2195 try:
2196 templater.templater(m)
2196 templater.templater(m)
2197 except Exception, inst:
2197 except Exception, inst:
2198 ui.write(" %s\n" % inst)
2198 ui.write(" %s\n" % inst)
2199 p = None
2199 p = None
2200 else:
2200 else:
2201 ui.write(_(" template 'default' not found\n"))
2201 ui.write(_(" template 'default' not found\n"))
2202 p = None
2202 p = None
2203 else:
2203 else:
2204 ui.write(_(" no template directories found\n"))
2204 ui.write(_(" no template directories found\n"))
2205 if not p:
2205 if not p:
2206 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2206 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2207 problems += 1
2207 problems += 1
2208
2208
2209 # editor
2209 # editor
2210 ui.status(_("checking commit editor...\n"))
2210 ui.status(_("checking commit editor...\n"))
2211 editor = ui.geteditor()
2211 editor = ui.geteditor()
2212 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2212 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2213 if not cmdpath:
2213 if not cmdpath:
2214 if editor == 'vi':
2214 if editor == 'vi':
2215 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2215 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2216 ui.write(_(" (specify a commit editor in your configuration"
2216 ui.write(_(" (specify a commit editor in your configuration"
2217 " file)\n"))
2217 " file)\n"))
2218 else:
2218 else:
2219 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2219 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2220 ui.write(_(" (specify a commit editor in your configuration"
2220 ui.write(_(" (specify a commit editor in your configuration"
2221 " file)\n"))
2221 " file)\n"))
2222 problems += 1
2222 problems += 1
2223
2223
2224 # check username
2224 # check username
2225 ui.status(_("checking username...\n"))
2225 ui.status(_("checking username...\n"))
2226 try:
2226 try:
2227 ui.username()
2227 ui.username()
2228 except util.Abort, e:
2228 except util.Abort, e:
2229 ui.write(" %s\n" % e)
2229 ui.write(" %s\n" % e)
2230 ui.write(_(" (specify a username in your configuration file)\n"))
2230 ui.write(_(" (specify a username in your configuration file)\n"))
2231 problems += 1
2231 problems += 1
2232
2232
2233 if not problems:
2233 if not problems:
2234 ui.status(_("no problems detected\n"))
2234 ui.status(_("no problems detected\n"))
2235 else:
2235 else:
2236 ui.write(_("%s problems detected,"
2236 ui.write(_("%s problems detected,"
2237 " please check your install!\n") % problems)
2237 " please check your install!\n") % problems)
2238
2238
2239 return problems
2239 return problems
2240
2240
2241 @command('debugknown', [], _('REPO ID...'))
2241 @command('debugknown', [], _('REPO ID...'))
2242 def debugknown(ui, repopath, *ids, **opts):
2242 def debugknown(ui, repopath, *ids, **opts):
2243 """test whether node ids are known to a repo
2243 """test whether node ids are known to a repo
2244
2244
2245 Every ID must be a full-length hex node id string. Returns a list of 0s
2245 Every ID must be a full-length hex node id string. Returns a list of 0s
2246 and 1s indicating unknown/known.
2246 and 1s indicating unknown/known.
2247 """
2247 """
2248 repo = hg.peer(ui, opts, repopath)
2248 repo = hg.peer(ui, opts, repopath)
2249 if not repo.capable('known'):
2249 if not repo.capable('known'):
2250 raise util.Abort("known() not supported by target repository")
2250 raise util.Abort("known() not supported by target repository")
2251 flags = repo.known([bin(s) for s in ids])
2251 flags = repo.known([bin(s) for s in ids])
2252 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2252 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2253
2253
2254 @command('debuglabelcomplete', [], _('LABEL...'))
2254 @command('debuglabelcomplete', [], _('LABEL...'))
2255 def debuglabelcomplete(ui, repo, *args):
2255 def debuglabelcomplete(ui, repo, *args):
2256 '''complete "labels" - tags, open branch names, bookmark names'''
2256 '''complete "labels" - tags, open branch names, bookmark names'''
2257
2257
2258 labels = set()
2258 labels = set()
2259 labels.update(t[0] for t in repo.tagslist())
2259 labels.update(t[0] for t in repo.tagslist())
2260 labels.update(repo._bookmarks.keys())
2260 labels.update(repo._bookmarks.keys())
2261 labels.update(tag for (tag, heads, tip, closed)
2261 labels.update(tag for (tag, heads, tip, closed)
2262 in repo.branchmap().iterbranches() if not closed)
2262 in repo.branchmap().iterbranches() if not closed)
2263 completions = set()
2263 completions = set()
2264 if not args:
2264 if not args:
2265 args = ['']
2265 args = ['']
2266 for a in args:
2266 for a in args:
2267 completions.update(l for l in labels if l.startswith(a))
2267 completions.update(l for l in labels if l.startswith(a))
2268 ui.write('\n'.join(sorted(completions)))
2268 ui.write('\n'.join(sorted(completions)))
2269 ui.write('\n')
2269 ui.write('\n')
2270
2270
2271 @command('debugobsolete',
2271 @command('debugobsolete',
2272 [('', 'flags', 0, _('markers flag')),
2272 [('', 'flags', 0, _('markers flag')),
2273 ] + commitopts2,
2273 ] + commitopts2,
2274 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2274 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2275 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2275 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2276 """create arbitrary obsolete marker
2276 """create arbitrary obsolete marker
2277
2277
2278 With no arguments, displays the list of obsolescence markers."""
2278 With no arguments, displays the list of obsolescence markers."""
2279 def parsenodeid(s):
2279 def parsenodeid(s):
2280 try:
2280 try:
2281 # We do not use revsingle/revrange functions here to accept
2281 # We do not use revsingle/revrange functions here to accept
2282 # arbitrary node identifiers, possibly not present in the
2282 # arbitrary node identifiers, possibly not present in the
2283 # local repository.
2283 # local repository.
2284 n = bin(s)
2284 n = bin(s)
2285 if len(n) != len(nullid):
2285 if len(n) != len(nullid):
2286 raise TypeError()
2286 raise TypeError()
2287 return n
2287 return n
2288 except TypeError:
2288 except TypeError:
2289 raise util.Abort('changeset references must be full hexadecimal '
2289 raise util.Abort('changeset references must be full hexadecimal '
2290 'node identifiers')
2290 'node identifiers')
2291
2291
2292 if precursor is not None:
2292 if precursor is not None:
2293 metadata = {}
2293 metadata = {}
2294 if 'date' in opts:
2294 if 'date' in opts:
2295 metadata['date'] = opts['date']
2295 metadata['date'] = opts['date']
2296 metadata['user'] = opts['user'] or ui.username()
2296 metadata['user'] = opts['user'] or ui.username()
2297 succs = tuple(parsenodeid(succ) for succ in successors)
2297 succs = tuple(parsenodeid(succ) for succ in successors)
2298 l = repo.lock()
2298 l = repo.lock()
2299 try:
2299 try:
2300 tr = repo.transaction('debugobsolete')
2300 tr = repo.transaction('debugobsolete')
2301 try:
2301 try:
2302 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2302 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2303 opts['flags'], metadata)
2303 opts['flags'], metadata)
2304 tr.close()
2304 tr.close()
2305 finally:
2305 finally:
2306 tr.release()
2306 tr.release()
2307 finally:
2307 finally:
2308 l.release()
2308 l.release()
2309 else:
2309 else:
2310 for m in obsolete.allmarkers(repo):
2310 for m in obsolete.allmarkers(repo):
2311 cmdutil.showmarker(ui, m)
2311 cmdutil.showmarker(ui, m)
2312
2312
2313 @command('debugpathcomplete',
2313 @command('debugpathcomplete',
2314 [('f', 'full', None, _('complete an entire path')),
2314 [('f', 'full', None, _('complete an entire path')),
2315 ('n', 'normal', None, _('show only normal files')),
2315 ('n', 'normal', None, _('show only normal files')),
2316 ('a', 'added', None, _('show only added files')),
2316 ('a', 'added', None, _('show only added files')),
2317 ('r', 'removed', None, _('show only removed files'))],
2317 ('r', 'removed', None, _('show only removed files'))],
2318 _('FILESPEC...'))
2318 _('FILESPEC...'))
2319 def debugpathcomplete(ui, repo, *specs, **opts):
2319 def debugpathcomplete(ui, repo, *specs, **opts):
2320 '''complete part or all of a tracked path
2320 '''complete part or all of a tracked path
2321
2321
2322 This command supports shells that offer path name completion. It
2322 This command supports shells that offer path name completion. It
2323 currently completes only files already known to the dirstate.
2323 currently completes only files already known to the dirstate.
2324
2324
2325 Completion extends only to the next path segment unless
2325 Completion extends only to the next path segment unless
2326 --full is specified, in which case entire paths are used.'''
2326 --full is specified, in which case entire paths are used.'''
2327
2327
2328 def complete(path, acceptable):
2328 def complete(path, acceptable):
2329 dirstate = repo.dirstate
2329 dirstate = repo.dirstate
2330 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2330 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2331 rootdir = repo.root + os.sep
2331 rootdir = repo.root + os.sep
2332 if spec != repo.root and not spec.startswith(rootdir):
2332 if spec != repo.root and not spec.startswith(rootdir):
2333 return [], []
2333 return [], []
2334 if os.path.isdir(spec):
2334 if os.path.isdir(spec):
2335 spec += '/'
2335 spec += '/'
2336 spec = spec[len(rootdir):]
2336 spec = spec[len(rootdir):]
2337 fixpaths = os.sep != '/'
2337 fixpaths = os.sep != '/'
2338 if fixpaths:
2338 if fixpaths:
2339 spec = spec.replace(os.sep, '/')
2339 spec = spec.replace(os.sep, '/')
2340 speclen = len(spec)
2340 speclen = len(spec)
2341 fullpaths = opts['full']
2341 fullpaths = opts['full']
2342 files, dirs = set(), set()
2342 files, dirs = set(), set()
2343 adddir, addfile = dirs.add, files.add
2343 adddir, addfile = dirs.add, files.add
2344 for f, st in dirstate.iteritems():
2344 for f, st in dirstate.iteritems():
2345 if f.startswith(spec) and st[0] in acceptable:
2345 if f.startswith(spec) and st[0] in acceptable:
2346 if fixpaths:
2346 if fixpaths:
2347 f = f.replace('/', os.sep)
2347 f = f.replace('/', os.sep)
2348 if fullpaths:
2348 if fullpaths:
2349 addfile(f)
2349 addfile(f)
2350 continue
2350 continue
2351 s = f.find(os.sep, speclen)
2351 s = f.find(os.sep, speclen)
2352 if s >= 0:
2352 if s >= 0:
2353 adddir(f[:s])
2353 adddir(f[:s])
2354 else:
2354 else:
2355 addfile(f)
2355 addfile(f)
2356 return files, dirs
2356 return files, dirs
2357
2357
2358 acceptable = ''
2358 acceptable = ''
2359 if opts['normal']:
2359 if opts['normal']:
2360 acceptable += 'nm'
2360 acceptable += 'nm'
2361 if opts['added']:
2361 if opts['added']:
2362 acceptable += 'a'
2362 acceptable += 'a'
2363 if opts['removed']:
2363 if opts['removed']:
2364 acceptable += 'r'
2364 acceptable += 'r'
2365 cwd = repo.getcwd()
2365 cwd = repo.getcwd()
2366 if not specs:
2366 if not specs:
2367 specs = ['.']
2367 specs = ['.']
2368
2368
2369 files, dirs = set(), set()
2369 files, dirs = set(), set()
2370 for spec in specs:
2370 for spec in specs:
2371 f, d = complete(spec, acceptable or 'nmar')
2371 f, d = complete(spec, acceptable or 'nmar')
2372 files.update(f)
2372 files.update(f)
2373 dirs.update(d)
2373 dirs.update(d)
2374 files.update(dirs)
2374 files.update(dirs)
2375 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2375 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2376 ui.write('\n')
2376 ui.write('\n')
2377
2377
2378 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2378 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2379 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2379 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2380 '''access the pushkey key/value protocol
2380 '''access the pushkey key/value protocol
2381
2381
2382 With two args, list the keys in the given namespace.
2382 With two args, list the keys in the given namespace.
2383
2383
2384 With five args, set a key to new if it currently is set to old.
2384 With five args, set a key to new if it currently is set to old.
2385 Reports success or failure.
2385 Reports success or failure.
2386 '''
2386 '''
2387
2387
2388 target = hg.peer(ui, {}, repopath)
2388 target = hg.peer(ui, {}, repopath)
2389 if keyinfo:
2389 if keyinfo:
2390 key, old, new = keyinfo
2390 key, old, new = keyinfo
2391 r = target.pushkey(namespace, key, old, new)
2391 r = target.pushkey(namespace, key, old, new)
2392 ui.status(str(r) + '\n')
2392 ui.status(str(r) + '\n')
2393 return not r
2393 return not r
2394 else:
2394 else:
2395 for k, v in sorted(target.listkeys(namespace).iteritems()):
2395 for k, v in sorted(target.listkeys(namespace).iteritems()):
2396 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2396 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2397 v.encode('string-escape')))
2397 v.encode('string-escape')))
2398
2398
2399 @command('debugpvec', [], _('A B'))
2399 @command('debugpvec', [], _('A B'))
2400 def debugpvec(ui, repo, a, b=None):
2400 def debugpvec(ui, repo, a, b=None):
2401 ca = scmutil.revsingle(repo, a)
2401 ca = scmutil.revsingle(repo, a)
2402 cb = scmutil.revsingle(repo, b)
2402 cb = scmutil.revsingle(repo, b)
2403 pa = pvec.ctxpvec(ca)
2403 pa = pvec.ctxpvec(ca)
2404 pb = pvec.ctxpvec(cb)
2404 pb = pvec.ctxpvec(cb)
2405 if pa == pb:
2405 if pa == pb:
2406 rel = "="
2406 rel = "="
2407 elif pa > pb:
2407 elif pa > pb:
2408 rel = ">"
2408 rel = ">"
2409 elif pa < pb:
2409 elif pa < pb:
2410 rel = "<"
2410 rel = "<"
2411 elif pa | pb:
2411 elif pa | pb:
2412 rel = "|"
2412 rel = "|"
2413 ui.write(_("a: %s\n") % pa)
2413 ui.write(_("a: %s\n") % pa)
2414 ui.write(_("b: %s\n") % pb)
2414 ui.write(_("b: %s\n") % pb)
2415 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2415 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2416 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2416 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2417 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2417 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2418 pa.distance(pb), rel))
2418 pa.distance(pb), rel))
2419
2419
2420 @command('debugrebuilddirstate|debugrebuildstate',
2420 @command('debugrebuilddirstate|debugrebuildstate',
2421 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2421 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2422 _('[-r REV]'))
2422 _('[-r REV]'))
2423 def debugrebuilddirstate(ui, repo, rev):
2423 def debugrebuilddirstate(ui, repo, rev):
2424 """rebuild the dirstate as it would look like for the given revision
2424 """rebuild the dirstate as it would look like for the given revision
2425
2425
2426 If no revision is specified the first current parent will be used.
2426 If no revision is specified the first current parent will be used.
2427
2427
2428 The dirstate will be set to the files of the given revision.
2428 The dirstate will be set to the files of the given revision.
2429 The actual working directory content or existing dirstate
2429 The actual working directory content or existing dirstate
2430 information such as adds or removes is not considered.
2430 information such as adds or removes is not considered.
2431
2431
2432 One use of this command is to make the next :hg:`status` invocation
2432 One use of this command is to make the next :hg:`status` invocation
2433 check the actual file content.
2433 check the actual file content.
2434 """
2434 """
2435 ctx = scmutil.revsingle(repo, rev)
2435 ctx = scmutil.revsingle(repo, rev)
2436 wlock = repo.wlock()
2436 wlock = repo.wlock()
2437 try:
2437 try:
2438 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2438 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2439 finally:
2439 finally:
2440 wlock.release()
2440 wlock.release()
2441
2441
2442 @command('debugrename',
2442 @command('debugrename',
2443 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2443 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2444 _('[-r REV] FILE'))
2444 _('[-r REV] FILE'))
2445 def debugrename(ui, repo, file1, *pats, **opts):
2445 def debugrename(ui, repo, file1, *pats, **opts):
2446 """dump rename information"""
2446 """dump rename information"""
2447
2447
2448 ctx = scmutil.revsingle(repo, opts.get('rev'))
2448 ctx = scmutil.revsingle(repo, opts.get('rev'))
2449 m = scmutil.match(ctx, (file1,) + pats, opts)
2449 m = scmutil.match(ctx, (file1,) + pats, opts)
2450 for abs in ctx.walk(m):
2450 for abs in ctx.walk(m):
2451 fctx = ctx[abs]
2451 fctx = ctx[abs]
2452 o = fctx.filelog().renamed(fctx.filenode())
2452 o = fctx.filelog().renamed(fctx.filenode())
2453 rel = m.rel(abs)
2453 rel = m.rel(abs)
2454 if o:
2454 if o:
2455 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2455 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2456 else:
2456 else:
2457 ui.write(_("%s not renamed\n") % rel)
2457 ui.write(_("%s not renamed\n") % rel)
2458
2458
2459 @command('debugrevlog',
2459 @command('debugrevlog',
2460 [('c', 'changelog', False, _('open changelog')),
2460 [('c', 'changelog', False, _('open changelog')),
2461 ('m', 'manifest', False, _('open manifest')),
2461 ('m', 'manifest', False, _('open manifest')),
2462 ('d', 'dump', False, _('dump index data'))],
2462 ('d', 'dump', False, _('dump index data'))],
2463 _('-c|-m|FILE'))
2463 _('-c|-m|FILE'))
2464 def debugrevlog(ui, repo, file_=None, **opts):
2464 def debugrevlog(ui, repo, file_=None, **opts):
2465 """show data and statistics about a revlog"""
2465 """show data and statistics about a revlog"""
2466 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2466 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2467
2467
2468 if opts.get("dump"):
2468 if opts.get("dump"):
2469 numrevs = len(r)
2469 numrevs = len(r)
2470 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2470 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2471 " rawsize totalsize compression heads\n")
2471 " rawsize totalsize compression heads\n")
2472 ts = 0
2472 ts = 0
2473 heads = set()
2473 heads = set()
2474 for rev in xrange(numrevs):
2474 for rev in xrange(numrevs):
2475 dbase = r.deltaparent(rev)
2475 dbase = r.deltaparent(rev)
2476 if dbase == -1:
2476 if dbase == -1:
2477 dbase = rev
2477 dbase = rev
2478 cbase = r.chainbase(rev)
2478 cbase = r.chainbase(rev)
2479 p1, p2 = r.parentrevs(rev)
2479 p1, p2 = r.parentrevs(rev)
2480 rs = r.rawsize(rev)
2480 rs = r.rawsize(rev)
2481 ts = ts + rs
2481 ts = ts + rs
2482 heads -= set(r.parentrevs(rev))
2482 heads -= set(r.parentrevs(rev))
2483 heads.add(rev)
2483 heads.add(rev)
2484 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2484 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2485 (rev, p1, p2, r.start(rev), r.end(rev),
2485 (rev, p1, p2, r.start(rev), r.end(rev),
2486 r.start(dbase), r.start(cbase),
2486 r.start(dbase), r.start(cbase),
2487 r.start(p1), r.start(p2),
2487 r.start(p1), r.start(p2),
2488 rs, ts, ts / r.end(rev), len(heads)))
2488 rs, ts, ts / r.end(rev), len(heads)))
2489 return 0
2489 return 0
2490
2490
2491 v = r.version
2491 v = r.version
2492 format = v & 0xFFFF
2492 format = v & 0xFFFF
2493 flags = []
2493 flags = []
2494 gdelta = False
2494 gdelta = False
2495 if v & revlog.REVLOGNGINLINEDATA:
2495 if v & revlog.REVLOGNGINLINEDATA:
2496 flags.append('inline')
2496 flags.append('inline')
2497 if v & revlog.REVLOGGENERALDELTA:
2497 if v & revlog.REVLOGGENERALDELTA:
2498 gdelta = True
2498 gdelta = True
2499 flags.append('generaldelta')
2499 flags.append('generaldelta')
2500 if not flags:
2500 if not flags:
2501 flags = ['(none)']
2501 flags = ['(none)']
2502
2502
2503 nummerges = 0
2503 nummerges = 0
2504 numfull = 0
2504 numfull = 0
2505 numprev = 0
2505 numprev = 0
2506 nump1 = 0
2506 nump1 = 0
2507 nump2 = 0
2507 nump2 = 0
2508 numother = 0
2508 numother = 0
2509 nump1prev = 0
2509 nump1prev = 0
2510 nump2prev = 0
2510 nump2prev = 0
2511 chainlengths = []
2511 chainlengths = []
2512
2512
2513 datasize = [None, 0, 0L]
2513 datasize = [None, 0, 0L]
2514 fullsize = [None, 0, 0L]
2514 fullsize = [None, 0, 0L]
2515 deltasize = [None, 0, 0L]
2515 deltasize = [None, 0, 0L]
2516
2516
2517 def addsize(size, l):
2517 def addsize(size, l):
2518 if l[0] is None or size < l[0]:
2518 if l[0] is None or size < l[0]:
2519 l[0] = size
2519 l[0] = size
2520 if size > l[1]:
2520 if size > l[1]:
2521 l[1] = size
2521 l[1] = size
2522 l[2] += size
2522 l[2] += size
2523
2523
2524 numrevs = len(r)
2524 numrevs = len(r)
2525 for rev in xrange(numrevs):
2525 for rev in xrange(numrevs):
2526 p1, p2 = r.parentrevs(rev)
2526 p1, p2 = r.parentrevs(rev)
2527 delta = r.deltaparent(rev)
2527 delta = r.deltaparent(rev)
2528 if format > 0:
2528 if format > 0:
2529 addsize(r.rawsize(rev), datasize)
2529 addsize(r.rawsize(rev), datasize)
2530 if p2 != nullrev:
2530 if p2 != nullrev:
2531 nummerges += 1
2531 nummerges += 1
2532 size = r.length(rev)
2532 size = r.length(rev)
2533 if delta == nullrev:
2533 if delta == nullrev:
2534 chainlengths.append(0)
2534 chainlengths.append(0)
2535 numfull += 1
2535 numfull += 1
2536 addsize(size, fullsize)
2536 addsize(size, fullsize)
2537 else:
2537 else:
2538 chainlengths.append(chainlengths[delta] + 1)
2538 chainlengths.append(chainlengths[delta] + 1)
2539 addsize(size, deltasize)
2539 addsize(size, deltasize)
2540 if delta == rev - 1:
2540 if delta == rev - 1:
2541 numprev += 1
2541 numprev += 1
2542 if delta == p1:
2542 if delta == p1:
2543 nump1prev += 1
2543 nump1prev += 1
2544 elif delta == p2:
2544 elif delta == p2:
2545 nump2prev += 1
2545 nump2prev += 1
2546 elif delta == p1:
2546 elif delta == p1:
2547 nump1 += 1
2547 nump1 += 1
2548 elif delta == p2:
2548 elif delta == p2:
2549 nump2 += 1
2549 nump2 += 1
2550 elif delta != nullrev:
2550 elif delta != nullrev:
2551 numother += 1
2551 numother += 1
2552
2552
2553 # Adjust size min value for empty cases
2553 # Adjust size min value for empty cases
2554 for size in (datasize, fullsize, deltasize):
2554 for size in (datasize, fullsize, deltasize):
2555 if size[0] is None:
2555 if size[0] is None:
2556 size[0] = 0
2556 size[0] = 0
2557
2557
2558 numdeltas = numrevs - numfull
2558 numdeltas = numrevs - numfull
2559 numoprev = numprev - nump1prev - nump2prev
2559 numoprev = numprev - nump1prev - nump2prev
2560 totalrawsize = datasize[2]
2560 totalrawsize = datasize[2]
2561 datasize[2] /= numrevs
2561 datasize[2] /= numrevs
2562 fulltotal = fullsize[2]
2562 fulltotal = fullsize[2]
2563 fullsize[2] /= numfull
2563 fullsize[2] /= numfull
2564 deltatotal = deltasize[2]
2564 deltatotal = deltasize[2]
2565 if numrevs - numfull > 0:
2565 if numrevs - numfull > 0:
2566 deltasize[2] /= numrevs - numfull
2566 deltasize[2] /= numrevs - numfull
2567 totalsize = fulltotal + deltatotal
2567 totalsize = fulltotal + deltatotal
2568 avgchainlen = sum(chainlengths) / numrevs
2568 avgchainlen = sum(chainlengths) / numrevs
2569 compratio = totalrawsize / totalsize
2569 compratio = totalrawsize / totalsize
2570
2570
2571 basedfmtstr = '%%%dd\n'
2571 basedfmtstr = '%%%dd\n'
2572 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2572 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2573
2573
2574 def dfmtstr(max):
2574 def dfmtstr(max):
2575 return basedfmtstr % len(str(max))
2575 return basedfmtstr % len(str(max))
2576 def pcfmtstr(max, padding=0):
2576 def pcfmtstr(max, padding=0):
2577 return basepcfmtstr % (len(str(max)), ' ' * padding)
2577 return basepcfmtstr % (len(str(max)), ' ' * padding)
2578
2578
2579 def pcfmt(value, total):
2579 def pcfmt(value, total):
2580 return (value, 100 * float(value) / total)
2580 return (value, 100 * float(value) / total)
2581
2581
2582 ui.write(('format : %d\n') % format)
2582 ui.write(('format : %d\n') % format)
2583 ui.write(('flags : %s\n') % ', '.join(flags))
2583 ui.write(('flags : %s\n') % ', '.join(flags))
2584
2584
2585 ui.write('\n')
2585 ui.write('\n')
2586 fmt = pcfmtstr(totalsize)
2586 fmt = pcfmtstr(totalsize)
2587 fmt2 = dfmtstr(totalsize)
2587 fmt2 = dfmtstr(totalsize)
2588 ui.write(('revisions : ') + fmt2 % numrevs)
2588 ui.write(('revisions : ') + fmt2 % numrevs)
2589 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2589 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2590 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2590 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2591 ui.write(('revisions : ') + fmt2 % numrevs)
2591 ui.write(('revisions : ') + fmt2 % numrevs)
2592 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2592 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2593 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2593 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2594 ui.write(('revision size : ') + fmt2 % totalsize)
2594 ui.write(('revision size : ') + fmt2 % totalsize)
2595 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2595 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2596 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2596 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2597
2597
2598 ui.write('\n')
2598 ui.write('\n')
2599 fmt = dfmtstr(max(avgchainlen, compratio))
2599 fmt = dfmtstr(max(avgchainlen, compratio))
2600 ui.write(('avg chain length : ') + fmt % avgchainlen)
2600 ui.write(('avg chain length : ') + fmt % avgchainlen)
2601 ui.write(('compression ratio : ') + fmt % compratio)
2601 ui.write(('compression ratio : ') + fmt % compratio)
2602
2602
2603 if format > 0:
2603 if format > 0:
2604 ui.write('\n')
2604 ui.write('\n')
2605 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2605 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2606 % tuple(datasize))
2606 % tuple(datasize))
2607 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2607 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2608 % tuple(fullsize))
2608 % tuple(fullsize))
2609 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2609 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2610 % tuple(deltasize))
2610 % tuple(deltasize))
2611
2611
2612 if numdeltas > 0:
2612 if numdeltas > 0:
2613 ui.write('\n')
2613 ui.write('\n')
2614 fmt = pcfmtstr(numdeltas)
2614 fmt = pcfmtstr(numdeltas)
2615 fmt2 = pcfmtstr(numdeltas, 4)
2615 fmt2 = pcfmtstr(numdeltas, 4)
2616 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2616 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2617 if numprev > 0:
2617 if numprev > 0:
2618 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2618 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2619 numprev))
2619 numprev))
2620 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2620 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2621 numprev))
2621 numprev))
2622 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2622 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2623 numprev))
2623 numprev))
2624 if gdelta:
2624 if gdelta:
2625 ui.write(('deltas against p1 : ')
2625 ui.write(('deltas against p1 : ')
2626 + fmt % pcfmt(nump1, numdeltas))
2626 + fmt % pcfmt(nump1, numdeltas))
2627 ui.write(('deltas against p2 : ')
2627 ui.write(('deltas against p2 : ')
2628 + fmt % pcfmt(nump2, numdeltas))
2628 + fmt % pcfmt(nump2, numdeltas))
2629 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2629 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2630 numdeltas))
2630 numdeltas))
2631
2631
2632 @command('debugrevspec',
2632 @command('debugrevspec',
2633 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2633 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2634 ('REVSPEC'))
2634 ('REVSPEC'))
2635 def debugrevspec(ui, repo, expr, **opts):
2635 def debugrevspec(ui, repo, expr, **opts):
2636 """parse and apply a revision specification
2636 """parse and apply a revision specification
2637
2637
2638 Use --verbose to print the parsed tree before and after aliases
2638 Use --verbose to print the parsed tree before and after aliases
2639 expansion.
2639 expansion.
2640 """
2640 """
2641 if ui.verbose:
2641 if ui.verbose:
2642 tree = revset.parse(expr)[0]
2642 tree = revset.parse(expr)[0]
2643 ui.note(revset.prettyformat(tree), "\n")
2643 ui.note(revset.prettyformat(tree), "\n")
2644 newtree = revset.findaliases(ui, tree)
2644 newtree = revset.findaliases(ui, tree)
2645 if newtree != tree:
2645 if newtree != tree:
2646 ui.note(revset.prettyformat(newtree), "\n")
2646 ui.note(revset.prettyformat(newtree), "\n")
2647 if opts["optimize"]:
2647 if opts["optimize"]:
2648 weight, optimizedtree = revset.optimize(newtree, True)
2648 weight, optimizedtree = revset.optimize(newtree, True)
2649 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2649 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2650 func = revset.match(ui, expr)
2650 func = revset.match(ui, expr)
2651 for c in func(repo, revset.spanset(repo)):
2651 for c in func(repo, revset.spanset(repo)):
2652 ui.write("%s\n" % c)
2652 ui.write("%s\n" % c)
2653
2653
2654 @command('debugsetparents', [], _('REV1 [REV2]'))
2654 @command('debugsetparents', [], _('REV1 [REV2]'))
2655 def debugsetparents(ui, repo, rev1, rev2=None):
2655 def debugsetparents(ui, repo, rev1, rev2=None):
2656 """manually set the parents of the current working directory
2656 """manually set the parents of the current working directory
2657
2657
2658 This is useful for writing repository conversion tools, but should
2658 This is useful for writing repository conversion tools, but should
2659 be used with care.
2659 be used with care.
2660
2660
2661 Returns 0 on success.
2661 Returns 0 on success.
2662 """
2662 """
2663
2663
2664 r1 = scmutil.revsingle(repo, rev1).node()
2664 r1 = scmutil.revsingle(repo, rev1).node()
2665 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2665 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2666
2666
2667 wlock = repo.wlock()
2667 wlock = repo.wlock()
2668 try:
2668 try:
2669 repo.setparents(r1, r2)
2669 repo.setparents(r1, r2)
2670 finally:
2670 finally:
2671 wlock.release()
2671 wlock.release()
2672
2672
2673 @command('debugdirstate|debugstate',
2673 @command('debugdirstate|debugstate',
2674 [('', 'nodates', None, _('do not display the saved mtime')),
2674 [('', 'nodates', None, _('do not display the saved mtime')),
2675 ('', 'datesort', None, _('sort by saved mtime'))],
2675 ('', 'datesort', None, _('sort by saved mtime'))],
2676 _('[OPTION]...'))
2676 _('[OPTION]...'))
2677 def debugstate(ui, repo, nodates=None, datesort=None):
2677 def debugstate(ui, repo, nodates=None, datesort=None):
2678 """show the contents of the current dirstate"""
2678 """show the contents of the current dirstate"""
2679 timestr = ""
2679 timestr = ""
2680 showdate = not nodates
2680 showdate = not nodates
2681 if datesort:
2681 if datesort:
2682 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2682 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2683 else:
2683 else:
2684 keyfunc = None # sort by filename
2684 keyfunc = None # sort by filename
2685 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2685 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2686 if showdate:
2686 if showdate:
2687 if ent[3] == -1:
2687 if ent[3] == -1:
2688 # Pad or slice to locale representation
2688 # Pad or slice to locale representation
2689 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2689 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2690 time.localtime(0)))
2690 time.localtime(0)))
2691 timestr = 'unset'
2691 timestr = 'unset'
2692 timestr = (timestr[:locale_len] +
2692 timestr = (timestr[:locale_len] +
2693 ' ' * (locale_len - len(timestr)))
2693 ' ' * (locale_len - len(timestr)))
2694 else:
2694 else:
2695 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2695 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2696 time.localtime(ent[3]))
2696 time.localtime(ent[3]))
2697 if ent[1] & 020000:
2697 if ent[1] & 020000:
2698 mode = 'lnk'
2698 mode = 'lnk'
2699 else:
2699 else:
2700 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2700 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2701 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2701 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2702 for f in repo.dirstate.copies():
2702 for f in repo.dirstate.copies():
2703 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2703 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2704
2704
2705 @command('debugsub',
2705 @command('debugsub',
2706 [('r', 'rev', '',
2706 [('r', 'rev', '',
2707 _('revision to check'), _('REV'))],
2707 _('revision to check'), _('REV'))],
2708 _('[-r REV] [REV]'))
2708 _('[-r REV] [REV]'))
2709 def debugsub(ui, repo, rev=None):
2709 def debugsub(ui, repo, rev=None):
2710 ctx = scmutil.revsingle(repo, rev, None)
2710 ctx = scmutil.revsingle(repo, rev, None)
2711 for k, v in sorted(ctx.substate.items()):
2711 for k, v in sorted(ctx.substate.items()):
2712 ui.write(('path %s\n') % k)
2712 ui.write(('path %s\n') % k)
2713 ui.write((' source %s\n') % v[0])
2713 ui.write((' source %s\n') % v[0])
2714 ui.write((' revision %s\n') % v[1])
2714 ui.write((' revision %s\n') % v[1])
2715
2715
2716 @command('debugsuccessorssets',
2716 @command('debugsuccessorssets',
2717 [],
2717 [],
2718 _('[REV]'))
2718 _('[REV]'))
2719 def debugsuccessorssets(ui, repo, *revs):
2719 def debugsuccessorssets(ui, repo, *revs):
2720 """show set of successors for revision
2720 """show set of successors for revision
2721
2721
2722 A successors set of changeset A is a consistent group of revisions that
2722 A successors set of changeset A is a consistent group of revisions that
2723 succeed A. It contains non-obsolete changesets only.
2723 succeed A. It contains non-obsolete changesets only.
2724
2724
2725 In most cases a changeset A has a single successors set containing a single
2725 In most cases a changeset A has a single successors set containing a single
2726 successor (changeset A replaced by A').
2726 successor (changeset A replaced by A').
2727
2727
2728 A changeset that is made obsolete with no successors are called "pruned".
2728 A changeset that is made obsolete with no successors are called "pruned".
2729 Such changesets have no successors sets at all.
2729 Such changesets have no successors sets at all.
2730
2730
2731 A changeset that has been "split" will have a successors set containing
2731 A changeset that has been "split" will have a successors set containing
2732 more than one successor.
2732 more than one successor.
2733
2733
2734 A changeset that has been rewritten in multiple different ways is called
2734 A changeset that has been rewritten in multiple different ways is called
2735 "divergent". Such changesets have multiple successor sets (each of which
2735 "divergent". Such changesets have multiple successor sets (each of which
2736 may also be split, i.e. have multiple successors).
2736 may also be split, i.e. have multiple successors).
2737
2737
2738 Results are displayed as follows::
2738 Results are displayed as follows::
2739
2739
2740 <rev1>
2740 <rev1>
2741 <successors-1A>
2741 <successors-1A>
2742 <rev2>
2742 <rev2>
2743 <successors-2A>
2743 <successors-2A>
2744 <successors-2B1> <successors-2B2> <successors-2B3>
2744 <successors-2B1> <successors-2B2> <successors-2B3>
2745
2745
2746 Here rev2 has two possible (i.e. divergent) successors sets. The first
2746 Here rev2 has two possible (i.e. divergent) successors sets. The first
2747 holds one element, whereas the second holds three (i.e. the changeset has
2747 holds one element, whereas the second holds three (i.e. the changeset has
2748 been split).
2748 been split).
2749 """
2749 """
2750 # passed to successorssets caching computation from one call to another
2750 # passed to successorssets caching computation from one call to another
2751 cache = {}
2751 cache = {}
2752 ctx2str = str
2752 ctx2str = str
2753 node2str = short
2753 node2str = short
2754 if ui.debug():
2754 if ui.debug():
2755 def ctx2str(ctx):
2755 def ctx2str(ctx):
2756 return ctx.hex()
2756 return ctx.hex()
2757 node2str = hex
2757 node2str = hex
2758 for rev in scmutil.revrange(repo, revs):
2758 for rev in scmutil.revrange(repo, revs):
2759 ctx = repo[rev]
2759 ctx = repo[rev]
2760 ui.write('%s\n'% ctx2str(ctx))
2760 ui.write('%s\n'% ctx2str(ctx))
2761 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2761 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2762 if succsset:
2762 if succsset:
2763 ui.write(' ')
2763 ui.write(' ')
2764 ui.write(node2str(succsset[0]))
2764 ui.write(node2str(succsset[0]))
2765 for node in succsset[1:]:
2765 for node in succsset[1:]:
2766 ui.write(' ')
2766 ui.write(' ')
2767 ui.write(node2str(node))
2767 ui.write(node2str(node))
2768 ui.write('\n')
2768 ui.write('\n')
2769
2769
2770 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2770 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2771 def debugwalk(ui, repo, *pats, **opts):
2771 def debugwalk(ui, repo, *pats, **opts):
2772 """show how files match on given patterns"""
2772 """show how files match on given patterns"""
2773 m = scmutil.match(repo[None], pats, opts)
2773 m = scmutil.match(repo[None], pats, opts)
2774 items = list(repo.walk(m))
2774 items = list(repo.walk(m))
2775 if not items:
2775 if not items:
2776 return
2776 return
2777 f = lambda fn: fn
2777 f = lambda fn: fn
2778 if ui.configbool('ui', 'slash') and os.sep != '/':
2778 if ui.configbool('ui', 'slash') and os.sep != '/':
2779 f = lambda fn: util.normpath(fn)
2779 f = lambda fn: util.normpath(fn)
2780 fmt = 'f %%-%ds %%-%ds %%s' % (
2780 fmt = 'f %%-%ds %%-%ds %%s' % (
2781 max([len(abs) for abs in items]),
2781 max([len(abs) for abs in items]),
2782 max([len(m.rel(abs)) for abs in items]))
2782 max([len(m.rel(abs)) for abs in items]))
2783 for abs in items:
2783 for abs in items:
2784 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2784 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2785 ui.write("%s\n" % line.rstrip())
2785 ui.write("%s\n" % line.rstrip())
2786
2786
2787 @command('debugwireargs',
2787 @command('debugwireargs',
2788 [('', 'three', '', 'three'),
2788 [('', 'three', '', 'three'),
2789 ('', 'four', '', 'four'),
2789 ('', 'four', '', 'four'),
2790 ('', 'five', '', 'five'),
2790 ('', 'five', '', 'five'),
2791 ] + remoteopts,
2791 ] + remoteopts,
2792 _('REPO [OPTIONS]... [ONE [TWO]]'))
2792 _('REPO [OPTIONS]... [ONE [TWO]]'))
2793 def debugwireargs(ui, repopath, *vals, **opts):
2793 def debugwireargs(ui, repopath, *vals, **opts):
2794 repo = hg.peer(ui, opts, repopath)
2794 repo = hg.peer(ui, opts, repopath)
2795 for opt in remoteopts:
2795 for opt in remoteopts:
2796 del opts[opt[1]]
2796 del opts[opt[1]]
2797 args = {}
2797 args = {}
2798 for k, v in opts.iteritems():
2798 for k, v in opts.iteritems():
2799 if v:
2799 if v:
2800 args[k] = v
2800 args[k] = v
2801 # run twice to check that we don't mess up the stream for the next command
2801 # run twice to check that we don't mess up the stream for the next command
2802 res1 = repo.debugwireargs(*vals, **args)
2802 res1 = repo.debugwireargs(*vals, **args)
2803 res2 = repo.debugwireargs(*vals, **args)
2803 res2 = repo.debugwireargs(*vals, **args)
2804 ui.write("%s\n" % res1)
2804 ui.write("%s\n" % res1)
2805 if res1 != res2:
2805 if res1 != res2:
2806 ui.warn("%s\n" % res2)
2806 ui.warn("%s\n" % res2)
2807
2807
2808 @command('^diff',
2808 @command('^diff',
2809 [('r', 'rev', [], _('revision'), _('REV')),
2809 [('r', 'rev', [], _('revision'), _('REV')),
2810 ('c', 'change', '', _('change made by revision'), _('REV'))
2810 ('c', 'change', '', _('change made by revision'), _('REV'))
2811 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2811 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2812 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2812 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2813 def diff(ui, repo, *pats, **opts):
2813 def diff(ui, repo, *pats, **opts):
2814 """diff repository (or selected files)
2814 """diff repository (or selected files)
2815
2815
2816 Show differences between revisions for the specified files.
2816 Show differences between revisions for the specified files.
2817
2817
2818 Differences between files are shown using the unified diff format.
2818 Differences between files are shown using the unified diff format.
2819
2819
2820 .. note::
2820 .. note::
2821
2821
2822 diff may generate unexpected results for merges, as it will
2822 diff may generate unexpected results for merges, as it will
2823 default to comparing against the working directory's first
2823 default to comparing against the working directory's first
2824 parent changeset if no revisions are specified.
2824 parent changeset if no revisions are specified.
2825
2825
2826 When two revision arguments are given, then changes are shown
2826 When two revision arguments are given, then changes are shown
2827 between those revisions. If only one revision is specified then
2827 between those revisions. If only one revision is specified then
2828 that revision is compared to the working directory, and, when no
2828 that revision is compared to the working directory, and, when no
2829 revisions are specified, the working directory files are compared
2829 revisions are specified, the working directory files are compared
2830 to its parent.
2830 to its parent.
2831
2831
2832 Alternatively you can specify -c/--change with a revision to see
2832 Alternatively you can specify -c/--change with a revision to see
2833 the changes in that changeset relative to its first parent.
2833 the changes in that changeset relative to its first parent.
2834
2834
2835 Without the -a/--text option, diff will avoid generating diffs of
2835 Without the -a/--text option, diff will avoid generating diffs of
2836 files it detects as binary. With -a, diff will generate a diff
2836 files it detects as binary. With -a, diff will generate a diff
2837 anyway, probably with undesirable results.
2837 anyway, probably with undesirable results.
2838
2838
2839 Use the -g/--git option to generate diffs in the git extended diff
2839 Use the -g/--git option to generate diffs in the git extended diff
2840 format. For more information, read :hg:`help diffs`.
2840 format. For more information, read :hg:`help diffs`.
2841
2841
2842 .. container:: verbose
2842 .. container:: verbose
2843
2843
2844 Examples:
2844 Examples:
2845
2845
2846 - compare a file in the current working directory to its parent::
2846 - compare a file in the current working directory to its parent::
2847
2847
2848 hg diff foo.c
2848 hg diff foo.c
2849
2849
2850 - compare two historical versions of a directory, with rename info::
2850 - compare two historical versions of a directory, with rename info::
2851
2851
2852 hg diff --git -r 1.0:1.2 lib/
2852 hg diff --git -r 1.0:1.2 lib/
2853
2853
2854 - get change stats relative to the last change on some date::
2854 - get change stats relative to the last change on some date::
2855
2855
2856 hg diff --stat -r "date('may 2')"
2856 hg diff --stat -r "date('may 2')"
2857
2857
2858 - diff all newly-added files that contain a keyword::
2858 - diff all newly-added files that contain a keyword::
2859
2859
2860 hg diff "set:added() and grep(GNU)"
2860 hg diff "set:added() and grep(GNU)"
2861
2861
2862 - compare a revision and its parents::
2862 - compare a revision and its parents::
2863
2863
2864 hg diff -c 9353 # compare against first parent
2864 hg diff -c 9353 # compare against first parent
2865 hg diff -r 9353^:9353 # same using revset syntax
2865 hg diff -r 9353^:9353 # same using revset syntax
2866 hg diff -r 9353^2:9353 # compare against the second parent
2866 hg diff -r 9353^2:9353 # compare against the second parent
2867
2867
2868 Returns 0 on success.
2868 Returns 0 on success.
2869 """
2869 """
2870
2870
2871 revs = opts.get('rev')
2871 revs = opts.get('rev')
2872 change = opts.get('change')
2872 change = opts.get('change')
2873 stat = opts.get('stat')
2873 stat = opts.get('stat')
2874 reverse = opts.get('reverse')
2874 reverse = opts.get('reverse')
2875
2875
2876 if revs and change:
2876 if revs and change:
2877 msg = _('cannot specify --rev and --change at the same time')
2877 msg = _('cannot specify --rev and --change at the same time')
2878 raise util.Abort(msg)
2878 raise util.Abort(msg)
2879 elif change:
2879 elif change:
2880 node2 = scmutil.revsingle(repo, change, None).node()
2880 node2 = scmutil.revsingle(repo, change, None).node()
2881 node1 = repo[node2].p1().node()
2881 node1 = repo[node2].p1().node()
2882 else:
2882 else:
2883 node1, node2 = scmutil.revpair(repo, revs)
2883 node1, node2 = scmutil.revpair(repo, revs)
2884
2884
2885 if reverse:
2885 if reverse:
2886 node1, node2 = node2, node1
2886 node1, node2 = node2, node1
2887
2887
2888 diffopts = patch.diffopts(ui, opts)
2888 diffopts = patch.diffopts(ui, opts)
2889 m = scmutil.match(repo[node2], pats, opts)
2889 m = scmutil.match(repo[node2], pats, opts)
2890 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2890 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2891 listsubrepos=opts.get('subrepos'))
2891 listsubrepos=opts.get('subrepos'))
2892
2892
2893 @command('^export',
2893 @command('^export',
2894 [('o', 'output', '',
2894 [('o', 'output', '',
2895 _('print output to file with formatted name'), _('FORMAT')),
2895 _('print output to file with formatted name'), _('FORMAT')),
2896 ('', 'switch-parent', None, _('diff against the second parent')),
2896 ('', 'switch-parent', None, _('diff against the second parent')),
2897 ('r', 'rev', [], _('revisions to export'), _('REV')),
2897 ('r', 'rev', [], _('revisions to export'), _('REV')),
2898 ] + diffopts,
2898 ] + diffopts,
2899 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2899 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2900 def export(ui, repo, *changesets, **opts):
2900 def export(ui, repo, *changesets, **opts):
2901 """dump the header and diffs for one or more changesets
2901 """dump the header and diffs for one or more changesets
2902
2902
2903 Print the changeset header and diffs for one or more revisions.
2903 Print the changeset header and diffs for one or more revisions.
2904 If no revision is given, the parent of the working directory is used.
2904 If no revision is given, the parent of the working directory is used.
2905
2905
2906 The information shown in the changeset header is: author, date,
2906 The information shown in the changeset header is: author, date,
2907 branch name (if non-default), changeset hash, parent(s) and commit
2907 branch name (if non-default), changeset hash, parent(s) and commit
2908 comment.
2908 comment.
2909
2909
2910 .. note::
2910 .. note::
2911
2911
2912 export may generate unexpected diff output for merge
2912 export may generate unexpected diff output for merge
2913 changesets, as it will compare the merge changeset against its
2913 changesets, as it will compare the merge changeset against its
2914 first parent only.
2914 first parent only.
2915
2915
2916 Output may be to a file, in which case the name of the file is
2916 Output may be to a file, in which case the name of the file is
2917 given using a format string. The formatting rules are as follows:
2917 given using a format string. The formatting rules are as follows:
2918
2918
2919 :``%%``: literal "%" character
2919 :``%%``: literal "%" character
2920 :``%H``: changeset hash (40 hexadecimal digits)
2920 :``%H``: changeset hash (40 hexadecimal digits)
2921 :``%N``: number of patches being generated
2921 :``%N``: number of patches being generated
2922 :``%R``: changeset revision number
2922 :``%R``: changeset revision number
2923 :``%b``: basename of the exporting repository
2923 :``%b``: basename of the exporting repository
2924 :``%h``: short-form changeset hash (12 hexadecimal digits)
2924 :``%h``: short-form changeset hash (12 hexadecimal digits)
2925 :``%m``: first line of the commit message (only alphanumeric characters)
2925 :``%m``: first line of the commit message (only alphanumeric characters)
2926 :``%n``: zero-padded sequence number, starting at 1
2926 :``%n``: zero-padded sequence number, starting at 1
2927 :``%r``: zero-padded changeset revision number
2927 :``%r``: zero-padded changeset revision number
2928
2928
2929 Without the -a/--text option, export will avoid generating diffs
2929 Without the -a/--text option, export will avoid generating diffs
2930 of files it detects as binary. With -a, export will generate a
2930 of files it detects as binary. With -a, export will generate a
2931 diff anyway, probably with undesirable results.
2931 diff anyway, probably with undesirable results.
2932
2932
2933 Use the -g/--git option to generate diffs in the git extended diff
2933 Use the -g/--git option to generate diffs in the git extended diff
2934 format. See :hg:`help diffs` for more information.
2934 format. See :hg:`help diffs` for more information.
2935
2935
2936 With the --switch-parent option, the diff will be against the
2936 With the --switch-parent option, the diff will be against the
2937 second parent. It can be useful to review a merge.
2937 second parent. It can be useful to review a merge.
2938
2938
2939 .. container:: verbose
2939 .. container:: verbose
2940
2940
2941 Examples:
2941 Examples:
2942
2942
2943 - use export and import to transplant a bugfix to the current
2943 - use export and import to transplant a bugfix to the current
2944 branch::
2944 branch::
2945
2945
2946 hg export -r 9353 | hg import -
2946 hg export -r 9353 | hg import -
2947
2947
2948 - export all the changesets between two revisions to a file with
2948 - export all the changesets between two revisions to a file with
2949 rename information::
2949 rename information::
2950
2950
2951 hg export --git -r 123:150 > changes.txt
2951 hg export --git -r 123:150 > changes.txt
2952
2952
2953 - split outgoing changes into a series of patches with
2953 - split outgoing changes into a series of patches with
2954 descriptive names::
2954 descriptive names::
2955
2955
2956 hg export -r "outgoing()" -o "%n-%m.patch"
2956 hg export -r "outgoing()" -o "%n-%m.patch"
2957
2957
2958 Returns 0 on success.
2958 Returns 0 on success.
2959 """
2959 """
2960 changesets += tuple(opts.get('rev', []))
2960 changesets += tuple(opts.get('rev', []))
2961 if not changesets:
2961 if not changesets:
2962 changesets = ['.']
2962 changesets = ['.']
2963 revs = scmutil.revrange(repo, changesets)
2963 revs = scmutil.revrange(repo, changesets)
2964 if not revs:
2964 if not revs:
2965 raise util.Abort(_("export requires at least one changeset"))
2965 raise util.Abort(_("export requires at least one changeset"))
2966 if len(revs) > 1:
2966 if len(revs) > 1:
2967 ui.note(_('exporting patches:\n'))
2967 ui.note(_('exporting patches:\n'))
2968 else:
2968 else:
2969 ui.note(_('exporting patch:\n'))
2969 ui.note(_('exporting patch:\n'))
2970 cmdutil.export(repo, revs, template=opts.get('output'),
2970 cmdutil.export(repo, revs, template=opts.get('output'),
2971 switch_parent=opts.get('switch_parent'),
2971 switch_parent=opts.get('switch_parent'),
2972 opts=patch.diffopts(ui, opts))
2972 opts=patch.diffopts(ui, opts))
2973
2973
2974 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2974 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2975 def forget(ui, repo, *pats, **opts):
2975 def forget(ui, repo, *pats, **opts):
2976 """forget the specified files on the next commit
2976 """forget the specified files on the next commit
2977
2977
2978 Mark the specified files so they will no longer be tracked
2978 Mark the specified files so they will no longer be tracked
2979 after the next commit.
2979 after the next commit.
2980
2980
2981 This only removes files from the current branch, not from the
2981 This only removes files from the current branch, not from the
2982 entire project history, and it does not delete them from the
2982 entire project history, and it does not delete them from the
2983 working directory.
2983 working directory.
2984
2984
2985 To undo a forget before the next commit, see :hg:`add`.
2985 To undo a forget before the next commit, see :hg:`add`.
2986
2986
2987 .. container:: verbose
2987 .. container:: verbose
2988
2988
2989 Examples:
2989 Examples:
2990
2990
2991 - forget newly-added binary files::
2991 - forget newly-added binary files::
2992
2992
2993 hg forget "set:added() and binary()"
2993 hg forget "set:added() and binary()"
2994
2994
2995 - forget files that would be excluded by .hgignore::
2995 - forget files that would be excluded by .hgignore::
2996
2996
2997 hg forget "set:hgignore()"
2997 hg forget "set:hgignore()"
2998
2998
2999 Returns 0 on success.
2999 Returns 0 on success.
3000 """
3000 """
3001
3001
3002 if not pats:
3002 if not pats:
3003 raise util.Abort(_('no files specified'))
3003 raise util.Abort(_('no files specified'))
3004
3004
3005 m = scmutil.match(repo[None], pats, opts)
3005 m = scmutil.match(repo[None], pats, opts)
3006 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3006 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3007 return rejected and 1 or 0
3007 return rejected and 1 or 0
3008
3008
3009 @command(
3009 @command(
3010 'graft',
3010 'graft',
3011 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3011 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3012 ('c', 'continue', False, _('resume interrupted graft')),
3012 ('c', 'continue', False, _('resume interrupted graft')),
3013 ('e', 'edit', False, _('invoke editor on commit messages')),
3013 ('e', 'edit', False, _('invoke editor on commit messages')),
3014 ('', 'log', None, _('append graft info to log message')),
3014 ('', 'log', None, _('append graft info to log message')),
3015 ('D', 'currentdate', False,
3015 ('D', 'currentdate', False,
3016 _('record the current date as commit date')),
3016 _('record the current date as commit date')),
3017 ('U', 'currentuser', False,
3017 ('U', 'currentuser', False,
3018 _('record the current user as committer'), _('DATE'))]
3018 _('record the current user as committer'), _('DATE'))]
3019 + commitopts2 + mergetoolopts + dryrunopts,
3019 + commitopts2 + mergetoolopts + dryrunopts,
3020 _('[OPTION]... [-r] REV...'))
3020 _('[OPTION]... [-r] REV...'))
3021 def graft(ui, repo, *revs, **opts):
3021 def graft(ui, repo, *revs, **opts):
3022 '''copy changes from other branches onto the current branch
3022 '''copy changes from other branches onto the current branch
3023
3023
3024 This command uses Mercurial's merge logic to copy individual
3024 This command uses Mercurial's merge logic to copy individual
3025 changes from other branches without merging branches in the
3025 changes from other branches without merging branches in the
3026 history graph. This is sometimes known as 'backporting' or
3026 history graph. This is sometimes known as 'backporting' or
3027 'cherry-picking'. By default, graft will copy user, date, and
3027 'cherry-picking'. By default, graft will copy user, date, and
3028 description from the source changesets.
3028 description from the source changesets.
3029
3029
3030 Changesets that are ancestors of the current revision, that have
3030 Changesets that are ancestors of the current revision, that have
3031 already been grafted, or that are merges will be skipped.
3031 already been grafted, or that are merges will be skipped.
3032
3032
3033 If --log is specified, log messages will have a comment appended
3033 If --log is specified, log messages will have a comment appended
3034 of the form::
3034 of the form::
3035
3035
3036 (grafted from CHANGESETHASH)
3036 (grafted from CHANGESETHASH)
3037
3037
3038 If a graft merge results in conflicts, the graft process is
3038 If a graft merge results in conflicts, the graft process is
3039 interrupted so that the current merge can be manually resolved.
3039 interrupted so that the current merge can be manually resolved.
3040 Once all conflicts are addressed, the graft process can be
3040 Once all conflicts are addressed, the graft process can be
3041 continued with the -c/--continue option.
3041 continued with the -c/--continue option.
3042
3042
3043 .. note::
3043 .. note::
3044
3044
3045 The -c/--continue option does not reapply earlier options.
3045 The -c/--continue option does not reapply earlier options.
3046
3046
3047 .. container:: verbose
3047 .. container:: verbose
3048
3048
3049 Examples:
3049 Examples:
3050
3050
3051 - copy a single change to the stable branch and edit its description::
3051 - copy a single change to the stable branch and edit its description::
3052
3052
3053 hg update stable
3053 hg update stable
3054 hg graft --edit 9393
3054 hg graft --edit 9393
3055
3055
3056 - graft a range of changesets with one exception, updating dates::
3056 - graft a range of changesets with one exception, updating dates::
3057
3057
3058 hg graft -D "2085::2093 and not 2091"
3058 hg graft -D "2085::2093 and not 2091"
3059
3059
3060 - continue a graft after resolving conflicts::
3060 - continue a graft after resolving conflicts::
3061
3061
3062 hg graft -c
3062 hg graft -c
3063
3063
3064 - show the source of a grafted changeset::
3064 - show the source of a grafted changeset::
3065
3065
3066 hg log --debug -r .
3066 hg log --debug -r .
3067
3067
3068 Returns 0 on successful completion.
3068 Returns 0 on successful completion.
3069 '''
3069 '''
3070
3070
3071 revs = list(revs)
3071 revs = list(revs)
3072 revs.extend(opts['rev'])
3072 revs.extend(opts['rev'])
3073
3073
3074 if not opts.get('user') and opts.get('currentuser'):
3074 if not opts.get('user') and opts.get('currentuser'):
3075 opts['user'] = ui.username()
3075 opts['user'] = ui.username()
3076 if not opts.get('date') and opts.get('currentdate'):
3076 if not opts.get('date') and opts.get('currentdate'):
3077 opts['date'] = "%d %d" % util.makedate()
3077 opts['date'] = "%d %d" % util.makedate()
3078
3078
3079 editor = None
3079 editor = None
3080 if opts.get('edit'):
3080 if opts.get('edit'):
3081 editor = cmdutil.commitforceeditor
3081 editor = cmdutil.commitforceeditor
3082
3082
3083 cont = False
3083 cont = False
3084 if opts['continue']:
3084 if opts['continue']:
3085 cont = True
3085 cont = True
3086 if revs:
3086 if revs:
3087 raise util.Abort(_("can't specify --continue and revisions"))
3087 raise util.Abort(_("can't specify --continue and revisions"))
3088 # read in unfinished revisions
3088 # read in unfinished revisions
3089 try:
3089 try:
3090 nodes = repo.opener.read('graftstate').splitlines()
3090 nodes = repo.opener.read('graftstate').splitlines()
3091 revs = [repo[node].rev() for node in nodes]
3091 revs = [repo[node].rev() for node in nodes]
3092 except IOError, inst:
3092 except IOError, inst:
3093 if inst.errno != errno.ENOENT:
3093 if inst.errno != errno.ENOENT:
3094 raise
3094 raise
3095 raise util.Abort(_("no graft state found, can't continue"))
3095 raise util.Abort(_("no graft state found, can't continue"))
3096 else:
3096 else:
3097 cmdutil.checkunfinished(repo)
3097 cmdutil.checkunfinished(repo)
3098 cmdutil.bailifchanged(repo)
3098 cmdutil.bailifchanged(repo)
3099 if not revs:
3099 if not revs:
3100 raise util.Abort(_('no revisions specified'))
3100 raise util.Abort(_('no revisions specified'))
3101 revs = scmutil.revrange(repo, revs)
3101 revs = scmutil.revrange(repo, revs)
3102
3102
3103 # check for merges
3103 # check for merges
3104 for rev in repo.revs('%ld and merge()', revs):
3104 for rev in repo.revs('%ld and merge()', revs):
3105 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3105 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3106 revs.remove(rev)
3106 revs.remove(rev)
3107 if not revs:
3107 if not revs:
3108 return -1
3108 return -1
3109
3109
3110 # check for ancestors of dest branch
3110 # check for ancestors of dest branch
3111 crev = repo['.'].rev()
3111 crev = repo['.'].rev()
3112 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3112 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3113 # don't mutate while iterating, create a copy
3113 # don't mutate while iterating, create a copy
3114 for rev in list(revs):
3114 for rev in list(revs):
3115 if rev in ancestors:
3115 if rev in ancestors:
3116 ui.warn(_('skipping ancestor revision %s\n') % rev)
3116 ui.warn(_('skipping ancestor revision %s\n') % rev)
3117 revs.remove(rev)
3117 revs.remove(rev)
3118 if not revs:
3118 if not revs:
3119 return -1
3119 return -1
3120
3120
3121 # analyze revs for earlier grafts
3121 # analyze revs for earlier grafts
3122 ids = {}
3122 ids = {}
3123 for ctx in repo.set("%ld", revs):
3123 for ctx in repo.set("%ld", revs):
3124 ids[ctx.hex()] = ctx.rev()
3124 ids[ctx.hex()] = ctx.rev()
3125 n = ctx.extra().get('source')
3125 n = ctx.extra().get('source')
3126 if n:
3126 if n:
3127 ids[n] = ctx.rev()
3127 ids[n] = ctx.rev()
3128
3128
3129 # check ancestors for earlier grafts
3129 # check ancestors for earlier grafts
3130 ui.debug('scanning for duplicate grafts\n')
3130 ui.debug('scanning for duplicate grafts\n')
3131
3131
3132 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3132 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3133 ctx = repo[rev]
3133 ctx = repo[rev]
3134 n = ctx.extra().get('source')
3134 n = ctx.extra().get('source')
3135 if n in ids:
3135 if n in ids:
3136 r = repo[n].rev()
3136 r = repo[n].rev()
3137 if r in revs:
3137 if r in revs:
3138 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3138 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3139 % (r, rev))
3139 % (r, rev))
3140 revs.remove(r)
3140 revs.remove(r)
3141 elif ids[n] in revs:
3141 elif ids[n] in revs:
3142 ui.warn(_('skipping already grafted revision %s '
3142 ui.warn(_('skipping already grafted revision %s '
3143 '(%s also has origin %d)\n') % (ids[n], rev, r))
3143 '(%s also has origin %d)\n') % (ids[n], rev, r))
3144 revs.remove(ids[n])
3144 revs.remove(ids[n])
3145 elif ctx.hex() in ids:
3145 elif ctx.hex() in ids:
3146 r = ids[ctx.hex()]
3146 r = ids[ctx.hex()]
3147 ui.warn(_('skipping already grafted revision %s '
3147 ui.warn(_('skipping already grafted revision %s '
3148 '(was grafted from %d)\n') % (r, rev))
3148 '(was grafted from %d)\n') % (r, rev))
3149 revs.remove(r)
3149 revs.remove(r)
3150 if not revs:
3150 if not revs:
3151 return -1
3151 return -1
3152
3152
3153 wlock = repo.wlock()
3153 wlock = repo.wlock()
3154 try:
3154 try:
3155 current = repo['.']
3155 current = repo['.']
3156 for pos, ctx in enumerate(repo.set("%ld", revs)):
3156 for pos, ctx in enumerate(repo.set("%ld", revs)):
3157
3157
3158 ui.status(_('grafting revision %s\n') % ctx.rev())
3158 ui.status(_('grafting revision %s\n') % ctx.rev())
3159 if opts.get('dry_run'):
3159 if opts.get('dry_run'):
3160 continue
3160 continue
3161
3161
3162 source = ctx.extra().get('source')
3162 source = ctx.extra().get('source')
3163 if not source:
3163 if not source:
3164 source = ctx.hex()
3164 source = ctx.hex()
3165 extra = {'source': source}
3165 extra = {'source': source}
3166 user = ctx.user()
3166 user = ctx.user()
3167 if opts.get('user'):
3167 if opts.get('user'):
3168 user = opts['user']
3168 user = opts['user']
3169 date = ctx.date()
3169 date = ctx.date()
3170 if opts.get('date'):
3170 if opts.get('date'):
3171 date = opts['date']
3171 date = opts['date']
3172 message = ctx.description()
3172 message = ctx.description()
3173 if opts.get('log'):
3173 if opts.get('log'):
3174 message += '\n(grafted from %s)' % ctx.hex()
3174 message += '\n(grafted from %s)' % ctx.hex()
3175
3175
3176 # we don't merge the first commit when continuing
3176 # we don't merge the first commit when continuing
3177 if not cont:
3177 if not cont:
3178 # perform the graft merge with p1(rev) as 'ancestor'
3178 # perform the graft merge with p1(rev) as 'ancestor'
3179 try:
3179 try:
3180 # ui.forcemerge is an internal variable, do not document
3180 # ui.forcemerge is an internal variable, do not document
3181 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3181 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3182 'graft')
3182 'graft')
3183 stats = mergemod.update(repo, ctx.node(), True, True, False,
3183 stats = mergemod.update(repo, ctx.node(), True, True, False,
3184 ctx.p1().node())
3184 ctx.p1().node())
3185 finally:
3185 finally:
3186 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3186 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3187 # report any conflicts
3187 # report any conflicts
3188 if stats and stats[3] > 0:
3188 if stats and stats[3] > 0:
3189 # write out state for --continue
3189 # write out state for --continue
3190 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3190 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3191 repo.opener.write('graftstate', ''.join(nodelines))
3191 repo.opener.write('graftstate', ''.join(nodelines))
3192 raise util.Abort(
3192 raise util.Abort(
3193 _("unresolved conflicts, can't continue"),
3193 _("unresolved conflicts, can't continue"),
3194 hint=_('use hg resolve and hg graft --continue'))
3194 hint=_('use hg resolve and hg graft --continue'))
3195 else:
3195 else:
3196 cont = False
3196 cont = False
3197
3197
3198 # drop the second merge parent
3198 # drop the second merge parent
3199 repo.setparents(current.node(), nullid)
3199 repo.setparents(current.node(), nullid)
3200 repo.dirstate.write()
3200 repo.dirstate.write()
3201 # fix up dirstate for copies and renames
3201 # fix up dirstate for copies and renames
3202 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3202 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3203
3203
3204 # commit
3204 # commit
3205 node = repo.commit(text=message, user=user,
3205 node = repo.commit(text=message, user=user,
3206 date=date, extra=extra, editor=editor)
3206 date=date, extra=extra, editor=editor)
3207 if node is None:
3207 if node is None:
3208 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3208 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3209 else:
3209 else:
3210 current = repo[node]
3210 current = repo[node]
3211 finally:
3211 finally:
3212 wlock.release()
3212 wlock.release()
3213
3213
3214 # remove state when we complete successfully
3214 # remove state when we complete successfully
3215 if not opts.get('dry_run'):
3215 if not opts.get('dry_run'):
3216 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3216 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3217
3217
3218 return 0
3218 return 0
3219
3219
3220 @command('grep',
3220 @command('grep',
3221 [('0', 'print0', None, _('end fields with NUL')),
3221 [('0', 'print0', None, _('end fields with NUL')),
3222 ('', 'all', None, _('print all revisions that match')),
3222 ('', 'all', None, _('print all revisions that match')),
3223 ('a', 'text', None, _('treat all files as text')),
3223 ('a', 'text', None, _('treat all files as text')),
3224 ('f', 'follow', None,
3224 ('f', 'follow', None,
3225 _('follow changeset history,'
3225 _('follow changeset history,'
3226 ' or file history across copies and renames')),
3226 ' or file history across copies and renames')),
3227 ('i', 'ignore-case', None, _('ignore case when matching')),
3227 ('i', 'ignore-case', None, _('ignore case when matching')),
3228 ('l', 'files-with-matches', None,
3228 ('l', 'files-with-matches', None,
3229 _('print only filenames and revisions that match')),
3229 _('print only filenames and revisions that match')),
3230 ('n', 'line-number', None, _('print matching line numbers')),
3230 ('n', 'line-number', None, _('print matching line numbers')),
3231 ('r', 'rev', [],
3231 ('r', 'rev', [],
3232 _('only search files changed within revision range'), _('REV')),
3232 _('only search files changed within revision range'), _('REV')),
3233 ('u', 'user', None, _('list the author (long with -v)')),
3233 ('u', 'user', None, _('list the author (long with -v)')),
3234 ('d', 'date', None, _('list the date (short with -q)')),
3234 ('d', 'date', None, _('list the date (short with -q)')),
3235 ] + walkopts,
3235 ] + walkopts,
3236 _('[OPTION]... PATTERN [FILE]...'))
3236 _('[OPTION]... PATTERN [FILE]...'))
3237 def grep(ui, repo, pattern, *pats, **opts):
3237 def grep(ui, repo, pattern, *pats, **opts):
3238 """search for a pattern in specified files and revisions
3238 """search for a pattern in specified files and revisions
3239
3239
3240 Search revisions of files for a regular expression.
3240 Search revisions of files for a regular expression.
3241
3241
3242 This command behaves differently than Unix grep. It only accepts
3242 This command behaves differently than Unix grep. It only accepts
3243 Python/Perl regexps. It searches repository history, not the
3243 Python/Perl regexps. It searches repository history, not the
3244 working directory. It always prints the revision number in which a
3244 working directory. It always prints the revision number in which a
3245 match appears.
3245 match appears.
3246
3246
3247 By default, grep only prints output for the first revision of a
3247 By default, grep only prints output for the first revision of a
3248 file in which it finds a match. To get it to print every revision
3248 file in which it finds a match. To get it to print every revision
3249 that contains a change in match status ("-" for a match that
3249 that contains a change in match status ("-" for a match that
3250 becomes a non-match, or "+" for a non-match that becomes a match),
3250 becomes a non-match, or "+" for a non-match that becomes a match),
3251 use the --all flag.
3251 use the --all flag.
3252
3252
3253 Returns 0 if a match is found, 1 otherwise.
3253 Returns 0 if a match is found, 1 otherwise.
3254 """
3254 """
3255 reflags = re.M
3255 reflags = re.M
3256 if opts.get('ignore_case'):
3256 if opts.get('ignore_case'):
3257 reflags |= re.I
3257 reflags |= re.I
3258 try:
3258 try:
3259 regexp = util.compilere(pattern, reflags)
3259 regexp = util.compilere(pattern, reflags)
3260 except re.error, inst:
3260 except re.error, inst:
3261 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3261 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3262 return 1
3262 return 1
3263 sep, eol = ':', '\n'
3263 sep, eol = ':', '\n'
3264 if opts.get('print0'):
3264 if opts.get('print0'):
3265 sep = eol = '\0'
3265 sep = eol = '\0'
3266
3266
3267 getfile = util.lrucachefunc(repo.file)
3267 getfile = util.lrucachefunc(repo.file)
3268
3268
3269 def matchlines(body):
3269 def matchlines(body):
3270 begin = 0
3270 begin = 0
3271 linenum = 0
3271 linenum = 0
3272 while begin < len(body):
3272 while begin < len(body):
3273 match = regexp.search(body, begin)
3273 match = regexp.search(body, begin)
3274 if not match:
3274 if not match:
3275 break
3275 break
3276 mstart, mend = match.span()
3276 mstart, mend = match.span()
3277 linenum += body.count('\n', begin, mstart) + 1
3277 linenum += body.count('\n', begin, mstart) + 1
3278 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3278 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3279 begin = body.find('\n', mend) + 1 or len(body) + 1
3279 begin = body.find('\n', mend) + 1 or len(body) + 1
3280 lend = begin - 1
3280 lend = begin - 1
3281 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3281 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3282
3282
3283 class linestate(object):
3283 class linestate(object):
3284 def __init__(self, line, linenum, colstart, colend):
3284 def __init__(self, line, linenum, colstart, colend):
3285 self.line = line
3285 self.line = line
3286 self.linenum = linenum
3286 self.linenum = linenum
3287 self.colstart = colstart
3287 self.colstart = colstart
3288 self.colend = colend
3288 self.colend = colend
3289
3289
3290 def __hash__(self):
3290 def __hash__(self):
3291 return hash((self.linenum, self.line))
3291 return hash((self.linenum, self.line))
3292
3292
3293 def __eq__(self, other):
3293 def __eq__(self, other):
3294 return self.line == other.line
3294 return self.line == other.line
3295
3295
3296 def __iter__(self):
3296 def __iter__(self):
3297 yield (self.line[:self.colstart], '')
3297 yield (self.line[:self.colstart], '')
3298 yield (self.line[self.colstart:self.colend], 'grep.match')
3298 yield (self.line[self.colstart:self.colend], 'grep.match')
3299 rest = self.line[self.colend:]
3299 rest = self.line[self.colend:]
3300 while rest != '':
3300 while rest != '':
3301 match = regexp.search(rest)
3301 match = regexp.search(rest)
3302 if not match:
3302 if not match:
3303 yield (rest, '')
3303 yield (rest, '')
3304 break
3304 break
3305 mstart, mend = match.span()
3305 mstart, mend = match.span()
3306 yield (rest[:mstart], '')
3306 yield (rest[:mstart], '')
3307 yield (rest[mstart:mend], 'grep.match')
3307 yield (rest[mstart:mend], 'grep.match')
3308 rest = rest[mend:]
3308 rest = rest[mend:]
3309
3309
3310 matches = {}
3310 matches = {}
3311 copies = {}
3311 copies = {}
3312 def grepbody(fn, rev, body):
3312 def grepbody(fn, rev, body):
3313 matches[rev].setdefault(fn, [])
3313 matches[rev].setdefault(fn, [])
3314 m = matches[rev][fn]
3314 m = matches[rev][fn]
3315 for lnum, cstart, cend, line in matchlines(body):
3315 for lnum, cstart, cend, line in matchlines(body):
3316 s = linestate(line, lnum, cstart, cend)
3316 s = linestate(line, lnum, cstart, cend)
3317 m.append(s)
3317 m.append(s)
3318
3318
3319 def difflinestates(a, b):
3319 def difflinestates(a, b):
3320 sm = difflib.SequenceMatcher(None, a, b)
3320 sm = difflib.SequenceMatcher(None, a, b)
3321 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3321 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3322 if tag == 'insert':
3322 if tag == 'insert':
3323 for i in xrange(blo, bhi):
3323 for i in xrange(blo, bhi):
3324 yield ('+', b[i])
3324 yield ('+', b[i])
3325 elif tag == 'delete':
3325 elif tag == 'delete':
3326 for i in xrange(alo, ahi):
3326 for i in xrange(alo, ahi):
3327 yield ('-', a[i])
3327 yield ('-', a[i])
3328 elif tag == 'replace':
3328 elif tag == 'replace':
3329 for i in xrange(alo, ahi):
3329 for i in xrange(alo, ahi):
3330 yield ('-', a[i])
3330 yield ('-', a[i])
3331 for i in xrange(blo, bhi):
3331 for i in xrange(blo, bhi):
3332 yield ('+', b[i])
3332 yield ('+', b[i])
3333
3333
3334 def display(fn, ctx, pstates, states):
3334 def display(fn, ctx, pstates, states):
3335 rev = ctx.rev()
3335 rev = ctx.rev()
3336 datefunc = ui.quiet and util.shortdate or util.datestr
3336 datefunc = ui.quiet and util.shortdate or util.datestr
3337 found = False
3337 found = False
3338 @util.cachefunc
3338 @util.cachefunc
3339 def binary():
3339 def binary():
3340 flog = getfile(fn)
3340 flog = getfile(fn)
3341 return util.binary(flog.read(ctx.filenode(fn)))
3341 return util.binary(flog.read(ctx.filenode(fn)))
3342
3342
3343 if opts.get('all'):
3343 if opts.get('all'):
3344 iter = difflinestates(pstates, states)
3344 iter = difflinestates(pstates, states)
3345 else:
3345 else:
3346 iter = [('', l) for l in states]
3346 iter = [('', l) for l in states]
3347 for change, l in iter:
3347 for change, l in iter:
3348 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3348 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3349
3349
3350 if opts.get('line_number'):
3350 if opts.get('line_number'):
3351 cols.append((str(l.linenum), 'grep.linenumber'))
3351 cols.append((str(l.linenum), 'grep.linenumber'))
3352 if opts.get('all'):
3352 if opts.get('all'):
3353 cols.append((change, 'grep.change'))
3353 cols.append((change, 'grep.change'))
3354 if opts.get('user'):
3354 if opts.get('user'):
3355 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3355 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3356 if opts.get('date'):
3356 if opts.get('date'):
3357 cols.append((datefunc(ctx.date()), 'grep.date'))
3357 cols.append((datefunc(ctx.date()), 'grep.date'))
3358 for col, label in cols[:-1]:
3358 for col, label in cols[:-1]:
3359 ui.write(col, label=label)
3359 ui.write(col, label=label)
3360 ui.write(sep, label='grep.sep')
3360 ui.write(sep, label='grep.sep')
3361 ui.write(cols[-1][0], label=cols[-1][1])
3361 ui.write(cols[-1][0], label=cols[-1][1])
3362 if not opts.get('files_with_matches'):
3362 if not opts.get('files_with_matches'):
3363 ui.write(sep, label='grep.sep')
3363 ui.write(sep, label='grep.sep')
3364 if not opts.get('text') and binary():
3364 if not opts.get('text') and binary():
3365 ui.write(" Binary file matches")
3365 ui.write(" Binary file matches")
3366 else:
3366 else:
3367 for s, label in l:
3367 for s, label in l:
3368 ui.write(s, label=label)
3368 ui.write(s, label=label)
3369 ui.write(eol)
3369 ui.write(eol)
3370 found = True
3370 found = True
3371 if opts.get('files_with_matches'):
3371 if opts.get('files_with_matches'):
3372 break
3372 break
3373 return found
3373 return found
3374
3374
3375 skip = {}
3375 skip = {}
3376 revfiles = {}
3376 revfiles = {}
3377 matchfn = scmutil.match(repo[None], pats, opts)
3377 matchfn = scmutil.match(repo[None], pats, opts)
3378 found = False
3378 found = False
3379 follow = opts.get('follow')
3379 follow = opts.get('follow')
3380
3380
3381 def prep(ctx, fns):
3381 def prep(ctx, fns):
3382 rev = ctx.rev()
3382 rev = ctx.rev()
3383 pctx = ctx.p1()
3383 pctx = ctx.p1()
3384 parent = pctx.rev()
3384 parent = pctx.rev()
3385 matches.setdefault(rev, {})
3385 matches.setdefault(rev, {})
3386 matches.setdefault(parent, {})
3386 matches.setdefault(parent, {})
3387 files = revfiles.setdefault(rev, [])
3387 files = revfiles.setdefault(rev, [])
3388 for fn in fns:
3388 for fn in fns:
3389 flog = getfile(fn)
3389 flog = getfile(fn)
3390 try:
3390 try:
3391 fnode = ctx.filenode(fn)
3391 fnode = ctx.filenode(fn)
3392 except error.LookupError:
3392 except error.LookupError:
3393 continue
3393 continue
3394
3394
3395 copied = flog.renamed(fnode)
3395 copied = flog.renamed(fnode)
3396 copy = follow and copied and copied[0]
3396 copy = follow and copied and copied[0]
3397 if copy:
3397 if copy:
3398 copies.setdefault(rev, {})[fn] = copy
3398 copies.setdefault(rev, {})[fn] = copy
3399 if fn in skip:
3399 if fn in skip:
3400 if copy:
3400 if copy:
3401 skip[copy] = True
3401 skip[copy] = True
3402 continue
3402 continue
3403 files.append(fn)
3403 files.append(fn)
3404
3404
3405 if fn not in matches[rev]:
3405 if fn not in matches[rev]:
3406 grepbody(fn, rev, flog.read(fnode))
3406 grepbody(fn, rev, flog.read(fnode))
3407
3407
3408 pfn = copy or fn
3408 pfn = copy or fn
3409 if pfn not in matches[parent]:
3409 if pfn not in matches[parent]:
3410 try:
3410 try:
3411 fnode = pctx.filenode(pfn)
3411 fnode = pctx.filenode(pfn)
3412 grepbody(pfn, parent, flog.read(fnode))
3412 grepbody(pfn, parent, flog.read(fnode))
3413 except error.LookupError:
3413 except error.LookupError:
3414 pass
3414 pass
3415
3415
3416 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3416 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3417 rev = ctx.rev()
3417 rev = ctx.rev()
3418 parent = ctx.p1().rev()
3418 parent = ctx.p1().rev()
3419 for fn in sorted(revfiles.get(rev, [])):
3419 for fn in sorted(revfiles.get(rev, [])):
3420 states = matches[rev][fn]
3420 states = matches[rev][fn]
3421 copy = copies.get(rev, {}).get(fn)
3421 copy = copies.get(rev, {}).get(fn)
3422 if fn in skip:
3422 if fn in skip:
3423 if copy:
3423 if copy:
3424 skip[copy] = True
3424 skip[copy] = True
3425 continue
3425 continue
3426 pstates = matches.get(parent, {}).get(copy or fn, [])
3426 pstates = matches.get(parent, {}).get(copy or fn, [])
3427 if pstates or states:
3427 if pstates or states:
3428 r = display(fn, ctx, pstates, states)
3428 r = display(fn, ctx, pstates, states)
3429 found = found or r
3429 found = found or r
3430 if r and not opts.get('all'):
3430 if r and not opts.get('all'):
3431 skip[fn] = True
3431 skip[fn] = True
3432 if copy:
3432 if copy:
3433 skip[copy] = True
3433 skip[copy] = True
3434 del matches[rev]
3434 del matches[rev]
3435 del revfiles[rev]
3435 del revfiles[rev]
3436
3436
3437 return not found
3437 return not found
3438
3438
3439 @command('heads',
3439 @command('heads',
3440 [('r', 'rev', '',
3440 [('r', 'rev', '',
3441 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3441 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3442 ('t', 'topo', False, _('show topological heads only')),
3442 ('t', 'topo', False, _('show topological heads only')),
3443 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3443 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3444 ('c', 'closed', False, _('show normal and closed branch heads')),
3444 ('c', 'closed', False, _('show normal and closed branch heads')),
3445 ] + templateopts,
3445 ] + templateopts,
3446 _('[-ct] [-r STARTREV] [REV]...'))
3446 _('[-ct] [-r STARTREV] [REV]...'))
3447 def heads(ui, repo, *branchrevs, **opts):
3447 def heads(ui, repo, *branchrevs, **opts):
3448 """show branch heads
3448 """show branch heads
3449
3449
3450 With no arguments, show all open branch heads in the repository.
3450 With no arguments, show all open branch heads in the repository.
3451 Branch heads are changesets that have no descendants on the
3451 Branch heads are changesets that have no descendants on the
3452 same branch. They are where development generally takes place and
3452 same branch. They are where development generally takes place and
3453 are the usual targets for update and merge operations.
3453 are the usual targets for update and merge operations.
3454
3454
3455 If one or more REVs are given, only open branch heads on the
3455 If one or more REVs are given, only open branch heads on the
3456 branches associated with the specified changesets are shown. This
3456 branches associated with the specified changesets are shown. This
3457 means that you can use :hg:`heads .` to see the heads on the
3457 means that you can use :hg:`heads .` to see the heads on the
3458 currently checked-out branch.
3458 currently checked-out branch.
3459
3459
3460 If -c/--closed is specified, also show branch heads marked closed
3460 If -c/--closed is specified, also show branch heads marked closed
3461 (see :hg:`commit --close-branch`).
3461 (see :hg:`commit --close-branch`).
3462
3462
3463 If STARTREV is specified, only those heads that are descendants of
3463 If STARTREV is specified, only those heads that are descendants of
3464 STARTREV will be displayed.
3464 STARTREV will be displayed.
3465
3465
3466 If -t/--topo is specified, named branch mechanics will be ignored and only
3466 If -t/--topo is specified, named branch mechanics will be ignored and only
3467 topological heads (changesets with no children) will be shown.
3467 topological heads (changesets with no children) will be shown.
3468
3468
3469 Returns 0 if matching heads are found, 1 if not.
3469 Returns 0 if matching heads are found, 1 if not.
3470 """
3470 """
3471
3471
3472 start = None
3472 start = None
3473 if 'rev' in opts:
3473 if 'rev' in opts:
3474 start = scmutil.revsingle(repo, opts['rev'], None).node()
3474 start = scmutil.revsingle(repo, opts['rev'], None).node()
3475
3475
3476 if opts.get('topo'):
3476 if opts.get('topo'):
3477 heads = [repo[h] for h in repo.heads(start)]
3477 heads = [repo[h] for h in repo.heads(start)]
3478 else:
3478 else:
3479 heads = []
3479 heads = []
3480 for branch in repo.branchmap():
3480 for branch in repo.branchmap():
3481 heads += repo.branchheads(branch, start, opts.get('closed'))
3481 heads += repo.branchheads(branch, start, opts.get('closed'))
3482 heads = [repo[h] for h in heads]
3482 heads = [repo[h] for h in heads]
3483
3483
3484 if branchrevs:
3484 if branchrevs:
3485 branches = set(repo[br].branch() for br in branchrevs)
3485 branches = set(repo[br].branch() for br in branchrevs)
3486 heads = [h for h in heads if h.branch() in branches]
3486 heads = [h for h in heads if h.branch() in branches]
3487
3487
3488 if opts.get('active') and branchrevs:
3488 if opts.get('active') and branchrevs:
3489 dagheads = repo.heads(start)
3489 dagheads = repo.heads(start)
3490 heads = [h for h in heads if h.node() in dagheads]
3490 heads = [h for h in heads if h.node() in dagheads]
3491
3491
3492 if branchrevs:
3492 if branchrevs:
3493 haveheads = set(h.branch() for h in heads)
3493 haveheads = set(h.branch() for h in heads)
3494 if branches - haveheads:
3494 if branches - haveheads:
3495 headless = ', '.join(b for b in branches - haveheads)
3495 headless = ', '.join(b for b in branches - haveheads)
3496 msg = _('no open branch heads found on branches %s')
3496 msg = _('no open branch heads found on branches %s')
3497 if opts.get('rev'):
3497 if opts.get('rev'):
3498 msg += _(' (started at %s)') % opts['rev']
3498 msg += _(' (started at %s)') % opts['rev']
3499 ui.warn((msg + '\n') % headless)
3499 ui.warn((msg + '\n') % headless)
3500
3500
3501 if not heads:
3501 if not heads:
3502 return 1
3502 return 1
3503
3503
3504 heads = sorted(heads, key=lambda x: -x.rev())
3504 heads = sorted(heads, key=lambda x: -x.rev())
3505 displayer = cmdutil.show_changeset(ui, repo, opts)
3505 displayer = cmdutil.show_changeset(ui, repo, opts)
3506 for ctx in heads:
3506 for ctx in heads:
3507 displayer.show(ctx)
3507 displayer.show(ctx)
3508 displayer.close()
3508 displayer.close()
3509
3509
3510 @command('help',
3510 @command('help',
3511 [('e', 'extension', None, _('show only help for extensions')),
3511 [('e', 'extension', None, _('show only help for extensions')),
3512 ('c', 'command', None, _('show only help for commands')),
3512 ('c', 'command', None, _('show only help for commands')),
3513 ('k', 'keyword', '', _('show topics matching keyword')),
3513 ('k', 'keyword', '', _('show topics matching keyword')),
3514 ],
3514 ],
3515 _('[-ec] [TOPIC]'))
3515 _('[-ec] [TOPIC]'))
3516 def help_(ui, name=None, **opts):
3516 def help_(ui, name=None, **opts):
3517 """show help for a given topic or a help overview
3517 """show help for a given topic or a help overview
3518
3518
3519 With no arguments, print a list of commands with short help messages.
3519 With no arguments, print a list of commands with short help messages.
3520
3520
3521 Given a topic, extension, or command name, print help for that
3521 Given a topic, extension, or command name, print help for that
3522 topic.
3522 topic.
3523
3523
3524 Returns 0 if successful.
3524 Returns 0 if successful.
3525 """
3525 """
3526
3526
3527 textwidth = min(ui.termwidth(), 80) - 2
3527 textwidth = min(ui.termwidth(), 80) - 2
3528
3528
3529 keep = ui.verbose and ['verbose'] or []
3529 keep = ui.verbose and ['verbose'] or []
3530 text = help.help_(ui, name, **opts)
3530 text = help.help_(ui, name, **opts)
3531
3531
3532 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3532 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3533 if 'verbose' in pruned:
3533 if 'verbose' in pruned:
3534 keep.append('omitted')
3534 keep.append('omitted')
3535 else:
3535 else:
3536 keep.append('notomitted')
3536 keep.append('notomitted')
3537 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3537 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3538 ui.write(formatted)
3538 ui.write(formatted)
3539
3539
3540
3540
3541 @command('identify|id',
3541 @command('identify|id',
3542 [('r', 'rev', '',
3542 [('r', 'rev', '',
3543 _('identify the specified revision'), _('REV')),
3543 _('identify the specified revision'), _('REV')),
3544 ('n', 'num', None, _('show local revision number')),
3544 ('n', 'num', None, _('show local revision number')),
3545 ('i', 'id', None, _('show global revision id')),
3545 ('i', 'id', None, _('show global revision id')),
3546 ('b', 'branch', None, _('show branch')),
3546 ('b', 'branch', None, _('show branch')),
3547 ('t', 'tags', None, _('show tags')),
3547 ('t', 'tags', None, _('show tags')),
3548 ('B', 'bookmarks', None, _('show bookmarks')),
3548 ('B', 'bookmarks', None, _('show bookmarks')),
3549 ] + remoteopts,
3549 ] + remoteopts,
3550 _('[-nibtB] [-r REV] [SOURCE]'))
3550 _('[-nibtB] [-r REV] [SOURCE]'))
3551 def identify(ui, repo, source=None, rev=None,
3551 def identify(ui, repo, source=None, rev=None,
3552 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3552 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3553 """identify the working copy or specified revision
3553 """identify the working copy or specified revision
3554
3554
3555 Print a summary identifying the repository state at REV using one or
3555 Print a summary identifying the repository state at REV using one or
3556 two parent hash identifiers, followed by a "+" if the working
3556 two parent hash identifiers, followed by a "+" if the working
3557 directory has uncommitted changes, the branch name (if not default),
3557 directory has uncommitted changes, the branch name (if not default),
3558 a list of tags, and a list of bookmarks.
3558 a list of tags, and a list of bookmarks.
3559
3559
3560 When REV is not given, print a summary of the current state of the
3560 When REV is not given, print a summary of the current state of the
3561 repository.
3561 repository.
3562
3562
3563 Specifying a path to a repository root or Mercurial bundle will
3563 Specifying a path to a repository root or Mercurial bundle will
3564 cause lookup to operate on that repository/bundle.
3564 cause lookup to operate on that repository/bundle.
3565
3565
3566 .. container:: verbose
3566 .. container:: verbose
3567
3567
3568 Examples:
3568 Examples:
3569
3569
3570 - generate a build identifier for the working directory::
3570 - generate a build identifier for the working directory::
3571
3571
3572 hg id --id > build-id.dat
3572 hg id --id > build-id.dat
3573
3573
3574 - find the revision corresponding to a tag::
3574 - find the revision corresponding to a tag::
3575
3575
3576 hg id -n -r 1.3
3576 hg id -n -r 1.3
3577
3577
3578 - check the most recent revision of a remote repository::
3578 - check the most recent revision of a remote repository::
3579
3579
3580 hg id -r tip http://selenic.com/hg/
3580 hg id -r tip http://selenic.com/hg/
3581
3581
3582 Returns 0 if successful.
3582 Returns 0 if successful.
3583 """
3583 """
3584
3584
3585 if not repo and not source:
3585 if not repo and not source:
3586 raise util.Abort(_("there is no Mercurial repository here "
3586 raise util.Abort(_("there is no Mercurial repository here "
3587 "(.hg not found)"))
3587 "(.hg not found)"))
3588
3588
3589 hexfunc = ui.debugflag and hex or short
3589 hexfunc = ui.debugflag and hex or short
3590 default = not (num or id or branch or tags or bookmarks)
3590 default = not (num or id or branch or tags or bookmarks)
3591 output = []
3591 output = []
3592 revs = []
3592 revs = []
3593
3593
3594 if source:
3594 if source:
3595 source, branches = hg.parseurl(ui.expandpath(source))
3595 source, branches = hg.parseurl(ui.expandpath(source))
3596 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3596 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3597 repo = peer.local()
3597 repo = peer.local()
3598 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3598 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3599
3599
3600 if not repo:
3600 if not repo:
3601 if num or branch or tags:
3601 if num or branch or tags:
3602 raise util.Abort(
3602 raise util.Abort(
3603 _("can't query remote revision number, branch, or tags"))
3603 _("can't query remote revision number, branch, or tags"))
3604 if not rev and revs:
3604 if not rev and revs:
3605 rev = revs[0]
3605 rev = revs[0]
3606 if not rev:
3606 if not rev:
3607 rev = "tip"
3607 rev = "tip"
3608
3608
3609 remoterev = peer.lookup(rev)
3609 remoterev = peer.lookup(rev)
3610 if default or id:
3610 if default or id:
3611 output = [hexfunc(remoterev)]
3611 output = [hexfunc(remoterev)]
3612
3612
3613 def getbms():
3613 def getbms():
3614 bms = []
3614 bms = []
3615
3615
3616 if 'bookmarks' in peer.listkeys('namespaces'):
3616 if 'bookmarks' in peer.listkeys('namespaces'):
3617 hexremoterev = hex(remoterev)
3617 hexremoterev = hex(remoterev)
3618 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3618 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3619 if bmr == hexremoterev]
3619 if bmr == hexremoterev]
3620
3620
3621 return sorted(bms)
3621 return sorted(bms)
3622
3622
3623 if bookmarks:
3623 if bookmarks:
3624 output.extend(getbms())
3624 output.extend(getbms())
3625 elif default and not ui.quiet:
3625 elif default and not ui.quiet:
3626 # multiple bookmarks for a single parent separated by '/'
3626 # multiple bookmarks for a single parent separated by '/'
3627 bm = '/'.join(getbms())
3627 bm = '/'.join(getbms())
3628 if bm:
3628 if bm:
3629 output.append(bm)
3629 output.append(bm)
3630 else:
3630 else:
3631 if not rev:
3631 if not rev:
3632 ctx = repo[None]
3632 ctx = repo[None]
3633 parents = ctx.parents()
3633 parents = ctx.parents()
3634 changed = ""
3634 changed = ""
3635 if default or id or num:
3635 if default or id or num:
3636 if (util.any(repo.status())
3636 if (util.any(repo.status())
3637 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3637 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3638 changed = '+'
3638 changed = '+'
3639 if default or id:
3639 if default or id:
3640 output = ["%s%s" %
3640 output = ["%s%s" %
3641 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3641 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3642 if num:
3642 if num:
3643 output.append("%s%s" %
3643 output.append("%s%s" %
3644 ('+'.join([str(p.rev()) for p in parents]), changed))
3644 ('+'.join([str(p.rev()) for p in parents]), changed))
3645 else:
3645 else:
3646 ctx = scmutil.revsingle(repo, rev)
3646 ctx = scmutil.revsingle(repo, rev)
3647 if default or id:
3647 if default or id:
3648 output = [hexfunc(ctx.node())]
3648 output = [hexfunc(ctx.node())]
3649 if num:
3649 if num:
3650 output.append(str(ctx.rev()))
3650 output.append(str(ctx.rev()))
3651
3651
3652 if default and not ui.quiet:
3652 if default and not ui.quiet:
3653 b = ctx.branch()
3653 b = ctx.branch()
3654 if b != 'default':
3654 if b != 'default':
3655 output.append("(%s)" % b)
3655 output.append("(%s)" % b)
3656
3656
3657 # multiple tags for a single parent separated by '/'
3657 # multiple tags for a single parent separated by '/'
3658 t = '/'.join(ctx.tags())
3658 t = '/'.join(ctx.tags())
3659 if t:
3659 if t:
3660 output.append(t)
3660 output.append(t)
3661
3661
3662 # multiple bookmarks for a single parent separated by '/'
3662 # multiple bookmarks for a single parent separated by '/'
3663 bm = '/'.join(ctx.bookmarks())
3663 bm = '/'.join(ctx.bookmarks())
3664 if bm:
3664 if bm:
3665 output.append(bm)
3665 output.append(bm)
3666 else:
3666 else:
3667 if branch:
3667 if branch:
3668 output.append(ctx.branch())
3668 output.append(ctx.branch())
3669
3669
3670 if tags:
3670 if tags:
3671 output.extend(ctx.tags())
3671 output.extend(ctx.tags())
3672
3672
3673 if bookmarks:
3673 if bookmarks:
3674 output.extend(ctx.bookmarks())
3674 output.extend(ctx.bookmarks())
3675
3675
3676 ui.write("%s\n" % ' '.join(output))
3676 ui.write("%s\n" % ' '.join(output))
3677
3677
3678 @command('import|patch',
3678 @command('import|patch',
3679 [('p', 'strip', 1,
3679 [('p', 'strip', 1,
3680 _('directory strip option for patch. This has the same '
3680 _('directory strip option for patch. This has the same '
3681 'meaning as the corresponding patch option'), _('NUM')),
3681 'meaning as the corresponding patch option'), _('NUM')),
3682 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3682 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3683 ('e', 'edit', False, _('invoke editor on commit messages')),
3683 ('e', 'edit', False, _('invoke editor on commit messages')),
3684 ('f', 'force', None,
3684 ('f', 'force', None,
3685 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3685 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3686 ('', 'no-commit', None,
3686 ('', 'no-commit', None,
3687 _("don't commit, just update the working directory")),
3687 _("don't commit, just update the working directory")),
3688 ('', 'bypass', None,
3688 ('', 'bypass', None,
3689 _("apply patch without touching the working directory")),
3689 _("apply patch without touching the working directory")),
3690 ('', 'exact', None,
3690 ('', 'exact', None,
3691 _('apply patch to the nodes from which it was generated')),
3691 _('apply patch to the nodes from which it was generated')),
3692 ('', 'import-branch', None,
3692 ('', 'import-branch', None,
3693 _('use any branch information in patch (implied by --exact)'))] +
3693 _('use any branch information in patch (implied by --exact)'))] +
3694 commitopts + commitopts2 + similarityopts,
3694 commitopts + commitopts2 + similarityopts,
3695 _('[OPTION]... PATCH...'))
3695 _('[OPTION]... PATCH...'))
3696 def import_(ui, repo, patch1=None, *patches, **opts):
3696 def import_(ui, repo, patch1=None, *patches, **opts):
3697 """import an ordered set of patches
3697 """import an ordered set of patches
3698
3698
3699 Import a list of patches and commit them individually (unless
3699 Import a list of patches and commit them individually (unless
3700 --no-commit is specified).
3700 --no-commit is specified).
3701
3701
3702 Because import first applies changes to the working directory,
3702 Because import first applies changes to the working directory,
3703 import will abort if there are outstanding changes.
3703 import will abort if there are outstanding changes.
3704
3704
3705 You can import a patch straight from a mail message. Even patches
3705 You can import a patch straight from a mail message. Even patches
3706 as attachments work (to use the body part, it must have type
3706 as attachments work (to use the body part, it must have type
3707 text/plain or text/x-patch). From and Subject headers of email
3707 text/plain or text/x-patch). From and Subject headers of email
3708 message are used as default committer and commit message. All
3708 message are used as default committer and commit message. All
3709 text/plain body parts before first diff are added to commit
3709 text/plain body parts before first diff are added to commit
3710 message.
3710 message.
3711
3711
3712 If the imported patch was generated by :hg:`export`, user and
3712 If the imported patch was generated by :hg:`export`, user and
3713 description from patch override values from message headers and
3713 description from patch override values from message headers and
3714 body. Values given on command line with -m/--message and -u/--user
3714 body. Values given on command line with -m/--message and -u/--user
3715 override these.
3715 override these.
3716
3716
3717 If --exact is specified, import will set the working directory to
3717 If --exact is specified, import will set the working directory to
3718 the parent of each patch before applying it, and will abort if the
3718 the parent of each patch before applying it, and will abort if the
3719 resulting changeset has a different ID than the one recorded in
3719 resulting changeset has a different ID than the one recorded in
3720 the patch. This may happen due to character set problems or other
3720 the patch. This may happen due to character set problems or other
3721 deficiencies in the text patch format.
3721 deficiencies in the text patch format.
3722
3722
3723 Use --bypass to apply and commit patches directly to the
3723 Use --bypass to apply and commit patches directly to the
3724 repository, not touching the working directory. Without --exact,
3724 repository, not touching the working directory. Without --exact,
3725 patches will be applied on top of the working directory parent
3725 patches will be applied on top of the working directory parent
3726 revision.
3726 revision.
3727
3727
3728 With -s/--similarity, hg will attempt to discover renames and
3728 With -s/--similarity, hg will attempt to discover renames and
3729 copies in the patch in the same way as :hg:`addremove`.
3729 copies in the patch in the same way as :hg:`addremove`.
3730
3730
3731 To read a patch from standard input, use "-" as the patch name. If
3731 To read a patch from standard input, use "-" as the patch name. If
3732 a URL is specified, the patch will be downloaded from it.
3732 a URL is specified, the patch will be downloaded from it.
3733 See :hg:`help dates` for a list of formats valid for -d/--date.
3733 See :hg:`help dates` for a list of formats valid for -d/--date.
3734
3734
3735 .. container:: verbose
3735 .. container:: verbose
3736
3736
3737 Examples:
3737 Examples:
3738
3738
3739 - import a traditional patch from a website and detect renames::
3739 - import a traditional patch from a website and detect renames::
3740
3740
3741 hg import -s 80 http://example.com/bugfix.patch
3741 hg import -s 80 http://example.com/bugfix.patch
3742
3742
3743 - import a changeset from an hgweb server::
3743 - import a changeset from an hgweb server::
3744
3744
3745 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3745 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3746
3746
3747 - import all the patches in an Unix-style mbox::
3747 - import all the patches in an Unix-style mbox::
3748
3748
3749 hg import incoming-patches.mbox
3749 hg import incoming-patches.mbox
3750
3750
3751 - attempt to exactly restore an exported changeset (not always
3751 - attempt to exactly restore an exported changeset (not always
3752 possible)::
3752 possible)::
3753
3753
3754 hg import --exact proposed-fix.patch
3754 hg import --exact proposed-fix.patch
3755
3755
3756 Returns 0 on success.
3756 Returns 0 on success.
3757 """
3757 """
3758
3758
3759 if not patch1:
3759 if not patch1:
3760 raise util.Abort(_('need at least one patch to import'))
3760 raise util.Abort(_('need at least one patch to import'))
3761
3761
3762 patches = (patch1,) + patches
3762 patches = (patch1,) + patches
3763
3763
3764 date = opts.get('date')
3764 date = opts.get('date')
3765 if date:
3765 if date:
3766 opts['date'] = util.parsedate(date)
3766 opts['date'] = util.parsedate(date)
3767
3767
3768 update = not opts.get('bypass')
3768 update = not opts.get('bypass')
3769 if not update and opts.get('no_commit'):
3769 if not update and opts.get('no_commit'):
3770 raise util.Abort(_('cannot use --no-commit with --bypass'))
3770 raise util.Abort(_('cannot use --no-commit with --bypass'))
3771 try:
3771 try:
3772 sim = float(opts.get('similarity') or 0)
3772 sim = float(opts.get('similarity') or 0)
3773 except ValueError:
3773 except ValueError:
3774 raise util.Abort(_('similarity must be a number'))
3774 raise util.Abort(_('similarity must be a number'))
3775 if sim < 0 or sim > 100:
3775 if sim < 0 or sim > 100:
3776 raise util.Abort(_('similarity must be between 0 and 100'))
3776 raise util.Abort(_('similarity must be between 0 and 100'))
3777 if sim and not update:
3777 if sim and not update:
3778 raise util.Abort(_('cannot use --similarity with --bypass'))
3778 raise util.Abort(_('cannot use --similarity with --bypass'))
3779
3779
3780 if update:
3780 if update:
3781 cmdutil.checkunfinished(repo)
3781 cmdutil.checkunfinished(repo)
3782 if (opts.get('exact') or not opts.get('force')) and update:
3782 if (opts.get('exact') or not opts.get('force')) and update:
3783 cmdutil.bailifchanged(repo)
3783 cmdutil.bailifchanged(repo)
3784
3784
3785 base = opts["base"]
3785 base = opts["base"]
3786 wlock = lock = tr = None
3786 wlock = lock = tr = None
3787 msgs = []
3787 msgs = []
3788
3788
3789
3789
3790 try:
3790 try:
3791 try:
3791 try:
3792 wlock = repo.wlock()
3792 wlock = repo.wlock()
3793 if not opts.get('no_commit'):
3793 if not opts.get('no_commit'):
3794 lock = repo.lock()
3794 lock = repo.lock()
3795 tr = repo.transaction('import')
3795 tr = repo.transaction('import')
3796 parents = repo.parents()
3796 parents = repo.parents()
3797 for patchurl in patches:
3797 for patchurl in patches:
3798 if patchurl == '-':
3798 if patchurl == '-':
3799 ui.status(_('applying patch from stdin\n'))
3799 ui.status(_('applying patch from stdin\n'))
3800 patchfile = ui.fin
3800 patchfile = ui.fin
3801 patchurl = 'stdin' # for error message
3801 patchurl = 'stdin' # for error message
3802 else:
3802 else:
3803 patchurl = os.path.join(base, patchurl)
3803 patchurl = os.path.join(base, patchurl)
3804 ui.status(_('applying %s\n') % patchurl)
3804 ui.status(_('applying %s\n') % patchurl)
3805 patchfile = hg.openpath(ui, patchurl)
3805 patchfile = hg.openpath(ui, patchurl)
3806
3806
3807 haspatch = False
3807 haspatch = False
3808 for hunk in patch.split(patchfile):
3808 for hunk in patch.split(patchfile):
3809 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3809 (msg, node) = cmdutil.tryimportone(ui, repo, hunk, parents,
3810 opts, msgs, hg.clean)
3810 opts, msgs, hg.clean)
3811 if msg:
3811 if msg:
3812 haspatch = True
3812 haspatch = True
3813 ui.note(msg + '\n')
3813 ui.note(msg + '\n')
3814 if update or opts.get('exact'):
3814 if update or opts.get('exact'):
3815 parents = repo.parents()
3815 parents = repo.parents()
3816 else:
3816 else:
3817 parents = [repo[node]]
3817 parents = [repo[node]]
3818
3818
3819 if not haspatch:
3819 if not haspatch:
3820 raise util.Abort(_('%s: no diffs found') % patchurl)
3820 raise util.Abort(_('%s: no diffs found') % patchurl)
3821
3821
3822 if tr:
3822 if tr:
3823 tr.close()
3823 tr.close()
3824 if msgs:
3824 if msgs:
3825 repo.savecommitmessage('\n* * *\n'.join(msgs))
3825 repo.savecommitmessage('\n* * *\n'.join(msgs))
3826 except: # re-raises
3826 except: # re-raises
3827 # wlock.release() indirectly calls dirstate.write(): since
3827 # wlock.release() indirectly calls dirstate.write(): since
3828 # we're crashing, we do not want to change the working dir
3828 # we're crashing, we do not want to change the working dir
3829 # parent after all, so make sure it writes nothing
3829 # parent after all, so make sure it writes nothing
3830 repo.dirstate.invalidate()
3830 repo.dirstate.invalidate()
3831 raise
3831 raise
3832 finally:
3832 finally:
3833 if tr:
3833 if tr:
3834 tr.release()
3834 tr.release()
3835 release(lock, wlock)
3835 release(lock, wlock)
3836
3836
3837 @command('incoming|in',
3837 @command('incoming|in',
3838 [('f', 'force', None,
3838 [('f', 'force', None,
3839 _('run even if remote repository is unrelated')),
3839 _('run even if remote repository is unrelated')),
3840 ('n', 'newest-first', None, _('show newest record first')),
3840 ('n', 'newest-first', None, _('show newest record first')),
3841 ('', 'bundle', '',
3841 ('', 'bundle', '',
3842 _('file to store the bundles into'), _('FILE')),
3842 _('file to store the bundles into'), _('FILE')),
3843 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3843 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3844 ('B', 'bookmarks', False, _("compare bookmarks")),
3844 ('B', 'bookmarks', False, _("compare bookmarks")),
3845 ('b', 'branch', [],
3845 ('b', 'branch', [],
3846 _('a specific branch you would like to pull'), _('BRANCH')),
3846 _('a specific branch you would like to pull'), _('BRANCH')),
3847 ] + logopts + remoteopts + subrepoopts,
3847 ] + logopts + remoteopts + subrepoopts,
3848 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3848 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3849 def incoming(ui, repo, source="default", **opts):
3849 def incoming(ui, repo, source="default", **opts):
3850 """show new changesets found in source
3850 """show new changesets found in source
3851
3851
3852 Show new changesets found in the specified path/URL or the default
3852 Show new changesets found in the specified path/URL or the default
3853 pull location. These are the changesets that would have been pulled
3853 pull location. These are the changesets that would have been pulled
3854 if a pull at the time you issued this command.
3854 if a pull at the time you issued this command.
3855
3855
3856 For remote repository, using --bundle avoids downloading the
3856 For remote repository, using --bundle avoids downloading the
3857 changesets twice if the incoming is followed by a pull.
3857 changesets twice if the incoming is followed by a pull.
3858
3858
3859 See pull for valid source format details.
3859 See pull for valid source format details.
3860
3860
3861 .. container:: verbose
3861 .. container:: verbose
3862
3862
3863 Examples:
3863 Examples:
3864
3864
3865 - show incoming changes with patches and full description::
3865 - show incoming changes with patches and full description::
3866
3866
3867 hg incoming -vp
3867 hg incoming -vp
3868
3868
3869 - show incoming changes excluding merges, store a bundle::
3869 - show incoming changes excluding merges, store a bundle::
3870
3870
3871 hg in -vpM --bundle incoming.hg
3871 hg in -vpM --bundle incoming.hg
3872 hg pull incoming.hg
3872 hg pull incoming.hg
3873
3873
3874 - briefly list changes inside a bundle::
3874 - briefly list changes inside a bundle::
3875
3875
3876 hg in changes.hg -T "{desc|firstline}\\n"
3876 hg in changes.hg -T "{desc|firstline}\\n"
3877
3877
3878 Returns 0 if there are incoming changes, 1 otherwise.
3878 Returns 0 if there are incoming changes, 1 otherwise.
3879 """
3879 """
3880 if opts.get('graph'):
3880 if opts.get('graph'):
3881 cmdutil.checkunsupportedgraphflags([], opts)
3881 cmdutil.checkunsupportedgraphflags([], opts)
3882 def display(other, chlist, displayer):
3882 def display(other, chlist, displayer):
3883 revdag = cmdutil.graphrevs(other, chlist, opts)
3883 revdag = cmdutil.graphrevs(other, chlist, opts)
3884 showparents = [ctx.node() for ctx in repo[None].parents()]
3884 showparents = [ctx.node() for ctx in repo[None].parents()]
3885 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3885 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3886 graphmod.asciiedges)
3886 graphmod.asciiedges)
3887
3887
3888 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3888 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3889 return 0
3889 return 0
3890
3890
3891 if opts.get('bundle') and opts.get('subrepos'):
3891 if opts.get('bundle') and opts.get('subrepos'):
3892 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3892 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3893
3893
3894 if opts.get('bookmarks'):
3894 if opts.get('bookmarks'):
3895 source, branches = hg.parseurl(ui.expandpath(source),
3895 source, branches = hg.parseurl(ui.expandpath(source),
3896 opts.get('branch'))
3896 opts.get('branch'))
3897 other = hg.peer(repo, opts, source)
3897 other = hg.peer(repo, opts, source)
3898 if 'bookmarks' not in other.listkeys('namespaces'):
3898 if 'bookmarks' not in other.listkeys('namespaces'):
3899 ui.warn(_("remote doesn't support bookmarks\n"))
3899 ui.warn(_("remote doesn't support bookmarks\n"))
3900 return 0
3900 return 0
3901 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3901 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3902 return bookmarks.diff(ui, repo, other)
3902 return bookmarks.diff(ui, repo, other)
3903
3903
3904 repo._subtoppath = ui.expandpath(source)
3904 repo._subtoppath = ui.expandpath(source)
3905 try:
3905 try:
3906 return hg.incoming(ui, repo, source, opts)
3906 return hg.incoming(ui, repo, source, opts)
3907 finally:
3907 finally:
3908 del repo._subtoppath
3908 del repo._subtoppath
3909
3909
3910
3910
3911 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3911 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3912 def init(ui, dest=".", **opts):
3912 def init(ui, dest=".", **opts):
3913 """create a new repository in the given directory
3913 """create a new repository in the given directory
3914
3914
3915 Initialize a new repository in the given directory. If the given
3915 Initialize a new repository in the given directory. If the given
3916 directory does not exist, it will be created.
3916 directory does not exist, it will be created.
3917
3917
3918 If no directory is given, the current directory is used.
3918 If no directory is given, the current directory is used.
3919
3919
3920 It is possible to specify an ``ssh://`` URL as the destination.
3920 It is possible to specify an ``ssh://`` URL as the destination.
3921 See :hg:`help urls` for more information.
3921 See :hg:`help urls` for more information.
3922
3922
3923 Returns 0 on success.
3923 Returns 0 on success.
3924 """
3924 """
3925 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3925 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3926
3926
3927 @command('locate',
3927 @command('locate',
3928 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3928 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3929 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3929 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3930 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3930 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3931 ] + walkopts,
3931 ] + walkopts,
3932 _('[OPTION]... [PATTERN]...'))
3932 _('[OPTION]... [PATTERN]...'))
3933 def locate(ui, repo, *pats, **opts):
3933 def locate(ui, repo, *pats, **opts):
3934 """locate files matching specific patterns
3934 """locate files matching specific patterns
3935
3935
3936 Print files under Mercurial control in the working directory whose
3936 Print files under Mercurial control in the working directory whose
3937 names match the given patterns.
3937 names match the given patterns.
3938
3938
3939 By default, this command searches all directories in the working
3939 By default, this command searches all directories in the working
3940 directory. To search just the current directory and its
3940 directory. To search just the current directory and its
3941 subdirectories, use "--include .".
3941 subdirectories, use "--include .".
3942
3942
3943 If no patterns are given to match, this command prints the names
3943 If no patterns are given to match, this command prints the names
3944 of all files under Mercurial control in the working directory.
3944 of all files under Mercurial control in the working directory.
3945
3945
3946 If you want to feed the output of this command into the "xargs"
3946 If you want to feed the output of this command into the "xargs"
3947 command, use the -0 option to both this command and "xargs". This
3947 command, use the -0 option to both this command and "xargs". This
3948 will avoid the problem of "xargs" treating single filenames that
3948 will avoid the problem of "xargs" treating single filenames that
3949 contain whitespace as multiple filenames.
3949 contain whitespace as multiple filenames.
3950
3950
3951 Returns 0 if a match is found, 1 otherwise.
3951 Returns 0 if a match is found, 1 otherwise.
3952 """
3952 """
3953 end = opts.get('print0') and '\0' or '\n'
3953 end = opts.get('print0') and '\0' or '\n'
3954 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3954 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3955
3955
3956 ret = 1
3956 ret = 1
3957 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3957 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3958 m.bad = lambda x, y: False
3958 m.bad = lambda x, y: False
3959 for abs in repo[rev].walk(m):
3959 for abs in repo[rev].walk(m):
3960 if not rev and abs not in repo.dirstate:
3960 if not rev and abs not in repo.dirstate:
3961 continue
3961 continue
3962 if opts.get('fullpath'):
3962 if opts.get('fullpath'):
3963 ui.write(repo.wjoin(abs), end)
3963 ui.write(repo.wjoin(abs), end)
3964 else:
3964 else:
3965 ui.write(((pats and m.rel(abs)) or abs), end)
3965 ui.write(((pats and m.rel(abs)) or abs), end)
3966 ret = 0
3966 ret = 0
3967
3967
3968 return ret
3968 return ret
3969
3969
3970 @command('^log|history',
3970 @command('^log|history',
3971 [('f', 'follow', None,
3971 [('f', 'follow', None,
3972 _('follow changeset history, or file history across copies and renames')),
3972 _('follow changeset history, or file history across copies and renames')),
3973 ('', 'follow-first', None,
3973 ('', 'follow-first', None,
3974 _('only follow the first parent of merge changesets (DEPRECATED)')),
3974 _('only follow the first parent of merge changesets (DEPRECATED)')),
3975 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3975 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3976 ('C', 'copies', None, _('show copied files')),
3976 ('C', 'copies', None, _('show copied files')),
3977 ('k', 'keyword', [],
3977 ('k', 'keyword', [],
3978 _('do case-insensitive search for a given text'), _('TEXT')),
3978 _('do case-insensitive search for a given text'), _('TEXT')),
3979 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3979 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3980 ('', 'removed', None, _('include revisions where files were removed')),
3980 ('', 'removed', None, _('include revisions where files were removed')),
3981 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3981 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3982 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3982 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3983 ('', 'only-branch', [],
3983 ('', 'only-branch', [],
3984 _('show only changesets within the given named branch (DEPRECATED)'),
3984 _('show only changesets within the given named branch (DEPRECATED)'),
3985 _('BRANCH')),
3985 _('BRANCH')),
3986 ('b', 'branch', [],
3986 ('b', 'branch', [],
3987 _('show changesets within the given named branch'), _('BRANCH')),
3987 _('show changesets within the given named branch'), _('BRANCH')),
3988 ('P', 'prune', [],
3988 ('P', 'prune', [],
3989 _('do not display revision or any of its ancestors'), _('REV')),
3989 _('do not display revision or any of its ancestors'), _('REV')),
3990 ] + logopts + walkopts,
3990 ] + logopts + walkopts,
3991 _('[OPTION]... [FILE]'))
3991 _('[OPTION]... [FILE]'))
3992 def log(ui, repo, *pats, **opts):
3992 def log(ui, repo, *pats, **opts):
3993 """show revision history of entire repository or files
3993 """show revision history of entire repository or files
3994
3994
3995 Print the revision history of the specified files or the entire
3995 Print the revision history of the specified files or the entire
3996 project.
3996 project.
3997
3997
3998 If no revision range is specified, the default is ``tip:0`` unless
3998 If no revision range is specified, the default is ``tip:0`` unless
3999 --follow is set, in which case the working directory parent is
3999 --follow is set, in which case the working directory parent is
4000 used as the starting revision.
4000 used as the starting revision.
4001
4001
4002 File history is shown without following rename or copy history of
4002 File history is shown without following rename or copy history of
4003 files. Use -f/--follow with a filename to follow history across
4003 files. Use -f/--follow with a filename to follow history across
4004 renames and copies. --follow without a filename will only show
4004 renames and copies. --follow without a filename will only show
4005 ancestors or descendants of the starting revision.
4005 ancestors or descendants of the starting revision.
4006
4006
4007 By default this command prints revision number and changeset id,
4007 By default this command prints revision number and changeset id,
4008 tags, non-trivial parents, user, date and time, and a summary for
4008 tags, non-trivial parents, user, date and time, and a summary for
4009 each commit. When the -v/--verbose switch is used, the list of
4009 each commit. When the -v/--verbose switch is used, the list of
4010 changed files and full commit message are shown.
4010 changed files and full commit message are shown.
4011
4011
4012 With --graph the revisions are shown as an ASCII art DAG with the most
4012 With --graph the revisions are shown as an ASCII art DAG with the most
4013 recent changeset at the top.
4013 recent changeset at the top.
4014 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4014 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4015 and '+' represents a fork where the changeset from the lines below is a
4015 and '+' represents a fork where the changeset from the lines below is a
4016 parent of the 'o' merge on the same same line.
4016 parent of the 'o' merge on the same same line.
4017
4017
4018 .. note::
4018 .. note::
4019
4019
4020 log -p/--patch may generate unexpected diff output for merge
4020 log -p/--patch may generate unexpected diff output for merge
4021 changesets, as it will only compare the merge changeset against
4021 changesets, as it will only compare the merge changeset against
4022 its first parent. Also, only files different from BOTH parents
4022 its first parent. Also, only files different from BOTH parents
4023 will appear in files:.
4023 will appear in files:.
4024
4024
4025 .. note::
4025 .. note::
4026
4026
4027 for performance reasons, log FILE may omit duplicate changes
4027 for performance reasons, log FILE may omit duplicate changes
4028 made on branches and will not show deletions. To see all
4028 made on branches and will not show deletions. To see all
4029 changes including duplicates and deletions, use the --removed
4029 changes including duplicates and deletions, use the --removed
4030 switch.
4030 switch.
4031
4031
4032 .. container:: verbose
4032 .. container:: verbose
4033
4033
4034 Some examples:
4034 Some examples:
4035
4035
4036 - changesets with full descriptions and file lists::
4036 - changesets with full descriptions and file lists::
4037
4037
4038 hg log -v
4038 hg log -v
4039
4039
4040 - changesets ancestral to the working directory::
4040 - changesets ancestral to the working directory::
4041
4041
4042 hg log -f
4042 hg log -f
4043
4043
4044 - last 10 commits on the current branch::
4044 - last 10 commits on the current branch::
4045
4045
4046 hg log -l 10 -b .
4046 hg log -l 10 -b .
4047
4047
4048 - changesets showing all modifications of a file, including removals::
4048 - changesets showing all modifications of a file, including removals::
4049
4049
4050 hg log --removed file.c
4050 hg log --removed file.c
4051
4051
4052 - all changesets that touch a directory, with diffs, excluding merges::
4052 - all changesets that touch a directory, with diffs, excluding merges::
4053
4053
4054 hg log -Mp lib/
4054 hg log -Mp lib/
4055
4055
4056 - all revision numbers that match a keyword::
4056 - all revision numbers that match a keyword::
4057
4057
4058 hg log -k bug --template "{rev}\\n"
4058 hg log -k bug --template "{rev}\\n"
4059
4059
4060 - check if a given changeset is included is a tagged release::
4060 - check if a given changeset is included is a tagged release::
4061
4061
4062 hg log -r "a21ccf and ancestor(1.9)"
4062 hg log -r "a21ccf and ancestor(1.9)"
4063
4063
4064 - find all changesets by some user in a date range::
4064 - find all changesets by some user in a date range::
4065
4065
4066 hg log -k alice -d "may 2008 to jul 2008"
4066 hg log -k alice -d "may 2008 to jul 2008"
4067
4067
4068 - summary of all changesets after the last tag::
4068 - summary of all changesets after the last tag::
4069
4069
4070 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4070 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4071
4071
4072 See :hg:`help dates` for a list of formats valid for -d/--date.
4072 See :hg:`help dates` for a list of formats valid for -d/--date.
4073
4073
4074 See :hg:`help revisions` and :hg:`help revsets` for more about
4074 See :hg:`help revisions` and :hg:`help revsets` for more about
4075 specifying revisions.
4075 specifying revisions.
4076
4076
4077 See :hg:`help templates` for more about pre-packaged styles and
4077 See :hg:`help templates` for more about pre-packaged styles and
4078 specifying custom templates.
4078 specifying custom templates.
4079
4079
4080 Returns 0 on success.
4080 Returns 0 on success.
4081 """
4081 """
4082 if opts.get('graph'):
4082 if opts.get('graph'):
4083 return cmdutil.graphlog(ui, repo, *pats, **opts)
4083 return cmdutil.graphlog(ui, repo, *pats, **opts)
4084
4084
4085 matchfn = scmutil.match(repo[None], pats, opts)
4085 matchfn = scmutil.match(repo[None], pats, opts)
4086 limit = cmdutil.loglimit(opts)
4086 limit = cmdutil.loglimit(opts)
4087 count = 0
4087 count = 0
4088
4088
4089 getrenamed, endrev = None, None
4089 getrenamed, endrev = None, None
4090 if opts.get('copies'):
4090 if opts.get('copies'):
4091 if opts.get('rev'):
4091 if opts.get('rev'):
4092 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4092 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4093 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4093 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4094
4094
4095 df = False
4095 df = False
4096 if opts.get("date"):
4096 if opts.get("date"):
4097 df = util.matchdate(opts["date"])
4097 df = util.matchdate(opts["date"])
4098
4098
4099 branches = opts.get('branch', []) + opts.get('only_branch', [])
4099 branches = opts.get('branch', []) + opts.get('only_branch', [])
4100 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4100 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4101
4101
4102 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4102 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4103 def prep(ctx, fns):
4103 def prep(ctx, fns):
4104 rev = ctx.rev()
4104 rev = ctx.rev()
4105 parents = [p for p in repo.changelog.parentrevs(rev)
4105 parents = [p for p in repo.changelog.parentrevs(rev)
4106 if p != nullrev]
4106 if p != nullrev]
4107 if opts.get('no_merges') and len(parents) == 2:
4107 if opts.get('no_merges') and len(parents) == 2:
4108 return
4108 return
4109 if opts.get('only_merges') and len(parents) != 2:
4109 if opts.get('only_merges') and len(parents) != 2:
4110 return
4110 return
4111 if opts.get('branch') and ctx.branch() not in opts['branch']:
4111 if opts.get('branch') and ctx.branch() not in opts['branch']:
4112 return
4112 return
4113 if df and not df(ctx.date()[0]):
4113 if df and not df(ctx.date()[0]):
4114 return
4114 return
4115
4115
4116 lower = encoding.lower
4116 lower = encoding.lower
4117 if opts.get('user'):
4117 if opts.get('user'):
4118 luser = lower(ctx.user())
4118 luser = lower(ctx.user())
4119 for k in [lower(x) for x in opts['user']]:
4119 for k in [lower(x) for x in opts['user']]:
4120 if (k in luser):
4120 if (k in luser):
4121 break
4121 break
4122 else:
4122 else:
4123 return
4123 return
4124 if opts.get('keyword'):
4124 if opts.get('keyword'):
4125 luser = lower(ctx.user())
4125 luser = lower(ctx.user())
4126 ldesc = lower(ctx.description())
4126 ldesc = lower(ctx.description())
4127 lfiles = lower(" ".join(ctx.files()))
4127 lfiles = lower(" ".join(ctx.files()))
4128 for k in [lower(x) for x in opts['keyword']]:
4128 for k in [lower(x) for x in opts['keyword']]:
4129 if (k in luser or k in ldesc or k in lfiles):
4129 if (k in luser or k in ldesc or k in lfiles):
4130 break
4130 break
4131 else:
4131 else:
4132 return
4132 return
4133
4133
4134 copies = None
4134 copies = None
4135 if getrenamed is not None and rev:
4135 if getrenamed is not None and rev:
4136 copies = []
4136 copies = []
4137 for fn in ctx.files():
4137 for fn in ctx.files():
4138 rename = getrenamed(fn, rev)
4138 rename = getrenamed(fn, rev)
4139 if rename:
4139 if rename:
4140 copies.append((fn, rename[0]))
4140 copies.append((fn, rename[0]))
4141
4141
4142 revmatchfn = None
4142 revmatchfn = None
4143 if opts.get('patch') or opts.get('stat'):
4143 if opts.get('patch') or opts.get('stat'):
4144 if opts.get('follow') or opts.get('follow_first'):
4144 if opts.get('follow') or opts.get('follow_first'):
4145 # note: this might be wrong when following through merges
4145 # note: this might be wrong when following through merges
4146 revmatchfn = scmutil.match(repo[None], fns, default='path')
4146 revmatchfn = scmutil.match(repo[None], fns, default='path')
4147 else:
4147 else:
4148 revmatchfn = matchfn
4148 revmatchfn = matchfn
4149
4149
4150 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4150 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4151
4151
4152 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4152 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4153 if displayer.flush(ctx.rev()):
4153 if displayer.flush(ctx.rev()):
4154 count += 1
4154 count += 1
4155 if count == limit:
4155 if count == limit:
4156 break
4156 break
4157 displayer.close()
4157 displayer.close()
4158
4158
4159 @command('manifest',
4159 @command('manifest',
4160 [('r', 'rev', '', _('revision to display'), _('REV')),
4160 [('r', 'rev', '', _('revision to display'), _('REV')),
4161 ('', 'all', False, _("list files from all revisions"))],
4161 ('', 'all', False, _("list files from all revisions"))],
4162 _('[-r REV]'))
4162 _('[-r REV]'))
4163 def manifest(ui, repo, node=None, rev=None, **opts):
4163 def manifest(ui, repo, node=None, rev=None, **opts):
4164 """output the current or given revision of the project manifest
4164 """output the current or given revision of the project manifest
4165
4165
4166 Print a list of version controlled files for the given revision.
4166 Print a list of version controlled files for the given revision.
4167 If no revision is given, the first parent of the working directory
4167 If no revision is given, the first parent of the working directory
4168 is used, or the null revision if no revision is checked out.
4168 is used, or the null revision if no revision is checked out.
4169
4169
4170 With -v, print file permissions, symlink and executable bits.
4170 With -v, print file permissions, symlink and executable bits.
4171 With --debug, print file revision hashes.
4171 With --debug, print file revision hashes.
4172
4172
4173 If option --all is specified, the list of all files from all revisions
4173 If option --all is specified, the list of all files from all revisions
4174 is printed. This includes deleted and renamed files.
4174 is printed. This includes deleted and renamed files.
4175
4175
4176 Returns 0 on success.
4176 Returns 0 on success.
4177 """
4177 """
4178
4178
4179 fm = ui.formatter('manifest', opts)
4179 fm = ui.formatter('manifest', opts)
4180
4180
4181 if opts.get('all'):
4181 if opts.get('all'):
4182 if rev or node:
4182 if rev or node:
4183 raise util.Abort(_("can't specify a revision with --all"))
4183 raise util.Abort(_("can't specify a revision with --all"))
4184
4184
4185 res = []
4185 res = []
4186 prefix = "data/"
4186 prefix = "data/"
4187 suffix = ".i"
4187 suffix = ".i"
4188 plen = len(prefix)
4188 plen = len(prefix)
4189 slen = len(suffix)
4189 slen = len(suffix)
4190 lock = repo.lock()
4190 lock = repo.lock()
4191 try:
4191 try:
4192 for fn, b, size in repo.store.datafiles():
4192 for fn, b, size in repo.store.datafiles():
4193 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4193 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4194 res.append(fn[plen:-slen])
4194 res.append(fn[plen:-slen])
4195 finally:
4195 finally:
4196 lock.release()
4196 lock.release()
4197 for f in res:
4197 for f in res:
4198 fm.startitem()
4198 fm.startitem()
4199 fm.write("path", '%s\n', f)
4199 fm.write("path", '%s\n', f)
4200 fm.end()
4200 fm.end()
4201 return
4201 return
4202
4202
4203 if rev and node:
4203 if rev and node:
4204 raise util.Abort(_("please specify just one revision"))
4204 raise util.Abort(_("please specify just one revision"))
4205
4205
4206 if not node:
4206 if not node:
4207 node = rev
4207 node = rev
4208
4208
4209 char = {'l': '@', 'x': '*', '': ''}
4209 char = {'l': '@', 'x': '*', '': ''}
4210 mode = {'l': '644', 'x': '755', '': '644'}
4210 mode = {'l': '644', 'x': '755', '': '644'}
4211 ctx = scmutil.revsingle(repo, node)
4211 ctx = scmutil.revsingle(repo, node)
4212 mf = ctx.manifest()
4212 mf = ctx.manifest()
4213 for f in ctx:
4213 for f in ctx:
4214 fm.startitem()
4214 fm.startitem()
4215 fl = ctx[f].flags()
4215 fl = ctx[f].flags()
4216 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4216 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4217 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4217 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4218 fm.write('path', '%s\n', f)
4218 fm.write('path', '%s\n', f)
4219 fm.end()
4219 fm.end()
4220
4220
4221 @command('^merge',
4221 @command('^merge',
4222 [('f', 'force', None,
4222 [('f', 'force', None,
4223 _('force a merge including outstanding changes (DEPRECATED)')),
4223 _('force a merge including outstanding changes (DEPRECATED)')),
4224 ('r', 'rev', '', _('revision to merge'), _('REV')),
4224 ('r', 'rev', '', _('revision to merge'), _('REV')),
4225 ('P', 'preview', None,
4225 ('P', 'preview', None,
4226 _('review revisions to merge (no merge is performed)'))
4226 _('review revisions to merge (no merge is performed)'))
4227 ] + mergetoolopts,
4227 ] + mergetoolopts,
4228 _('[-P] [-f] [[-r] REV]'))
4228 _('[-P] [-f] [[-r] REV]'))
4229 def merge(ui, repo, node=None, **opts):
4229 def merge(ui, repo, node=None, **opts):
4230 """merge working directory with another revision
4230 """merge working directory with another revision
4231
4231
4232 The current working directory is updated with all changes made in
4232 The current working directory is updated with all changes made in
4233 the requested revision since the last common predecessor revision.
4233 the requested revision since the last common predecessor revision.
4234
4234
4235 Files that changed between either parent are marked as changed for
4235 Files that changed between either parent are marked as changed for
4236 the next commit and a commit must be performed before any further
4236 the next commit and a commit must be performed before any further
4237 updates to the repository are allowed. The next commit will have
4237 updates to the repository are allowed. The next commit will have
4238 two parents.
4238 two parents.
4239
4239
4240 ``--tool`` can be used to specify the merge tool used for file
4240 ``--tool`` can be used to specify the merge tool used for file
4241 merges. It overrides the HGMERGE environment variable and your
4241 merges. It overrides the HGMERGE environment variable and your
4242 configuration files. See :hg:`help merge-tools` for options.
4242 configuration files. See :hg:`help merge-tools` for options.
4243
4243
4244 If no revision is specified, the working directory's parent is a
4244 If no revision is specified, the working directory's parent is a
4245 head revision, and the current branch contains exactly one other
4245 head revision, and the current branch contains exactly one other
4246 head, the other head is merged with by default. Otherwise, an
4246 head, the other head is merged with by default. Otherwise, an
4247 explicit revision with which to merge with must be provided.
4247 explicit revision with which to merge with must be provided.
4248
4248
4249 :hg:`resolve` must be used to resolve unresolved files.
4249 :hg:`resolve` must be used to resolve unresolved files.
4250
4250
4251 To undo an uncommitted merge, use :hg:`update --clean .` which
4251 To undo an uncommitted merge, use :hg:`update --clean .` which
4252 will check out a clean copy of the original merge parent, losing
4252 will check out a clean copy of the original merge parent, losing
4253 all changes.
4253 all changes.
4254
4254
4255 Returns 0 on success, 1 if there are unresolved files.
4255 Returns 0 on success, 1 if there are unresolved files.
4256 """
4256 """
4257
4257
4258 if opts.get('rev') and node:
4258 if opts.get('rev') and node:
4259 raise util.Abort(_("please specify just one revision"))
4259 raise util.Abort(_("please specify just one revision"))
4260 if not node:
4260 if not node:
4261 node = opts.get('rev')
4261 node = opts.get('rev')
4262
4262
4263 if node:
4263 if node:
4264 node = scmutil.revsingle(repo, node).node()
4264 node = scmutil.revsingle(repo, node).node()
4265
4265
4266 if not node and repo._bookmarkcurrent:
4266 if not node and repo._bookmarkcurrent:
4267 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4267 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4268 curhead = repo[repo._bookmarkcurrent].node()
4268 curhead = repo[repo._bookmarkcurrent].node()
4269 if len(bmheads) == 2:
4269 if len(bmheads) == 2:
4270 if curhead == bmheads[0]:
4270 if curhead == bmheads[0]:
4271 node = bmheads[1]
4271 node = bmheads[1]
4272 else:
4272 else:
4273 node = bmheads[0]
4273 node = bmheads[0]
4274 elif len(bmheads) > 2:
4274 elif len(bmheads) > 2:
4275 raise util.Abort(_("multiple matching bookmarks to merge - "
4275 raise util.Abort(_("multiple matching bookmarks to merge - "
4276 "please merge with an explicit rev or bookmark"),
4276 "please merge with an explicit rev or bookmark"),
4277 hint=_("run 'hg heads' to see all heads"))
4277 hint=_("run 'hg heads' to see all heads"))
4278 elif len(bmheads) <= 1:
4278 elif len(bmheads) <= 1:
4279 raise util.Abort(_("no matching bookmark to merge - "
4279 raise util.Abort(_("no matching bookmark to merge - "
4280 "please merge with an explicit rev or bookmark"),
4280 "please merge with an explicit rev or bookmark"),
4281 hint=_("run 'hg heads' to see all heads"))
4281 hint=_("run 'hg heads' to see all heads"))
4282
4282
4283 if not node and not repo._bookmarkcurrent:
4283 if not node and not repo._bookmarkcurrent:
4284 branch = repo[None].branch()
4284 branch = repo[None].branch()
4285 bheads = repo.branchheads(branch)
4285 bheads = repo.branchheads(branch)
4286 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4286 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4287
4287
4288 if len(nbhs) > 2:
4288 if len(nbhs) > 2:
4289 raise util.Abort(_("branch '%s' has %d heads - "
4289 raise util.Abort(_("branch '%s' has %d heads - "
4290 "please merge with an explicit rev")
4290 "please merge with an explicit rev")
4291 % (branch, len(bheads)),
4291 % (branch, len(bheads)),
4292 hint=_("run 'hg heads .' to see heads"))
4292 hint=_("run 'hg heads .' to see heads"))
4293
4293
4294 parent = repo.dirstate.p1()
4294 parent = repo.dirstate.p1()
4295 if len(nbhs) <= 1:
4295 if len(nbhs) <= 1:
4296 if len(bheads) > 1:
4296 if len(bheads) > 1:
4297 raise util.Abort(_("heads are bookmarked - "
4297 raise util.Abort(_("heads are bookmarked - "
4298 "please merge with an explicit rev"),
4298 "please merge with an explicit rev"),
4299 hint=_("run 'hg heads' to see all heads"))
4299 hint=_("run 'hg heads' to see all heads"))
4300 if len(repo.heads()) > 1:
4300 if len(repo.heads()) > 1:
4301 raise util.Abort(_("branch '%s' has one head - "
4301 raise util.Abort(_("branch '%s' has one head - "
4302 "please merge with an explicit rev")
4302 "please merge with an explicit rev")
4303 % branch,
4303 % branch,
4304 hint=_("run 'hg heads' to see all heads"))
4304 hint=_("run 'hg heads' to see all heads"))
4305 msg, hint = _('nothing to merge'), None
4305 msg, hint = _('nothing to merge'), None
4306 if parent != repo.lookup(branch):
4306 if parent != repo.lookup(branch):
4307 hint = _("use 'hg update' instead")
4307 hint = _("use 'hg update' instead")
4308 raise util.Abort(msg, hint=hint)
4308 raise util.Abort(msg, hint=hint)
4309
4309
4310 if parent not in bheads:
4310 if parent not in bheads:
4311 raise util.Abort(_('working directory not at a head revision'),
4311 raise util.Abort(_('working directory not at a head revision'),
4312 hint=_("use 'hg update' or merge with an "
4312 hint=_("use 'hg update' or merge with an "
4313 "explicit revision"))
4313 "explicit revision"))
4314 if parent == nbhs[0]:
4314 if parent == nbhs[0]:
4315 node = nbhs[-1]
4315 node = nbhs[-1]
4316 else:
4316 else:
4317 node = nbhs[0]
4317 node = nbhs[0]
4318
4318
4319 if opts.get('preview'):
4319 if opts.get('preview'):
4320 # find nodes that are ancestors of p2 but not of p1
4320 # find nodes that are ancestors of p2 but not of p1
4321 p1 = repo.lookup('.')
4321 p1 = repo.lookup('.')
4322 p2 = repo.lookup(node)
4322 p2 = repo.lookup(node)
4323 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4323 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4324
4324
4325 displayer = cmdutil.show_changeset(ui, repo, opts)
4325 displayer = cmdutil.show_changeset(ui, repo, opts)
4326 for node in nodes:
4326 for node in nodes:
4327 displayer.show(repo[node])
4327 displayer.show(repo[node])
4328 displayer.close()
4328 displayer.close()
4329 return 0
4329 return 0
4330
4330
4331 try:
4331 try:
4332 # ui.forcemerge is an internal variable, do not document
4332 # ui.forcemerge is an internal variable, do not document
4333 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4333 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4334 return hg.merge(repo, node, force=opts.get('force'))
4334 return hg.merge(repo, node, force=opts.get('force'))
4335 finally:
4335 finally:
4336 ui.setconfig('ui', 'forcemerge', '', 'merge')
4336 ui.setconfig('ui', 'forcemerge', '', 'merge')
4337
4337
4338 @command('outgoing|out',
4338 @command('outgoing|out',
4339 [('f', 'force', None, _('run even when the destination is unrelated')),
4339 [('f', 'force', None, _('run even when the destination is unrelated')),
4340 ('r', 'rev', [],
4340 ('r', 'rev', [],
4341 _('a changeset intended to be included in the destination'), _('REV')),
4341 _('a changeset intended to be included in the destination'), _('REV')),
4342 ('n', 'newest-first', None, _('show newest record first')),
4342 ('n', 'newest-first', None, _('show newest record first')),
4343 ('B', 'bookmarks', False, _('compare bookmarks')),
4343 ('B', 'bookmarks', False, _('compare bookmarks')),
4344 ('b', 'branch', [], _('a specific branch you would like to push'),
4344 ('b', 'branch', [], _('a specific branch you would like to push'),
4345 _('BRANCH')),
4345 _('BRANCH')),
4346 ] + logopts + remoteopts + subrepoopts,
4346 ] + logopts + remoteopts + subrepoopts,
4347 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4347 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4348 def outgoing(ui, repo, dest=None, **opts):
4348 def outgoing(ui, repo, dest=None, **opts):
4349 """show changesets not found in the destination
4349 """show changesets not found in the destination
4350
4350
4351 Show changesets not found in the specified destination repository
4351 Show changesets not found in the specified destination repository
4352 or the default push location. These are the changesets that would
4352 or the default push location. These are the changesets that would
4353 be pushed if a push was requested.
4353 be pushed if a push was requested.
4354
4354
4355 See pull for details of valid destination formats.
4355 See pull for details of valid destination formats.
4356
4356
4357 Returns 0 if there are outgoing changes, 1 otherwise.
4357 Returns 0 if there are outgoing changes, 1 otherwise.
4358 """
4358 """
4359 if opts.get('graph'):
4359 if opts.get('graph'):
4360 cmdutil.checkunsupportedgraphflags([], opts)
4360 cmdutil.checkunsupportedgraphflags([], opts)
4361 o, other = hg._outgoing(ui, repo, dest, opts)
4361 o, other = hg._outgoing(ui, repo, dest, opts)
4362 if not o:
4362 if not o:
4363 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4363 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4364 return
4364 return
4365
4365
4366 revdag = cmdutil.graphrevs(repo, o, opts)
4366 revdag = cmdutil.graphrevs(repo, o, opts)
4367 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4367 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4368 showparents = [ctx.node() for ctx in repo[None].parents()]
4368 showparents = [ctx.node() for ctx in repo[None].parents()]
4369 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4369 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4370 graphmod.asciiedges)
4370 graphmod.asciiedges)
4371 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4371 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4372 return 0
4372 return 0
4373
4373
4374 if opts.get('bookmarks'):
4374 if opts.get('bookmarks'):
4375 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4375 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4376 dest, branches = hg.parseurl(dest, opts.get('branch'))
4376 dest, branches = hg.parseurl(dest, opts.get('branch'))
4377 other = hg.peer(repo, opts, dest)
4377 other = hg.peer(repo, opts, dest)
4378 if 'bookmarks' not in other.listkeys('namespaces'):
4378 if 'bookmarks' not in other.listkeys('namespaces'):
4379 ui.warn(_("remote doesn't support bookmarks\n"))
4379 ui.warn(_("remote doesn't support bookmarks\n"))
4380 return 0
4380 return 0
4381 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4381 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4382 return bookmarks.diff(ui, other, repo)
4382 return bookmarks.diff(ui, other, repo)
4383
4383
4384 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4384 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4385 try:
4385 try:
4386 return hg.outgoing(ui, repo, dest, opts)
4386 return hg.outgoing(ui, repo, dest, opts)
4387 finally:
4387 finally:
4388 del repo._subtoppath
4388 del repo._subtoppath
4389
4389
4390 @command('parents',
4390 @command('parents',
4391 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4391 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4392 ] + templateopts,
4392 ] + templateopts,
4393 _('[-r REV] [FILE]'))
4393 _('[-r REV] [FILE]'))
4394 def parents(ui, repo, file_=None, **opts):
4394 def parents(ui, repo, file_=None, **opts):
4395 """show the parents of the working directory or revision
4395 """show the parents of the working directory or revision
4396
4396
4397 Print the working directory's parent revisions. If a revision is
4397 Print the working directory's parent revisions. If a revision is
4398 given via -r/--rev, the parent of that revision will be printed.
4398 given via -r/--rev, the parent of that revision will be printed.
4399 If a file argument is given, the revision in which the file was
4399 If a file argument is given, the revision in which the file was
4400 last changed (before the working directory revision or the
4400 last changed (before the working directory revision or the
4401 argument to --rev if given) is printed.
4401 argument to --rev if given) is printed.
4402
4402
4403 Returns 0 on success.
4403 Returns 0 on success.
4404 """
4404 """
4405
4405
4406 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4406 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4407
4407
4408 if file_:
4408 if file_:
4409 m = scmutil.match(ctx, (file_,), opts)
4409 m = scmutil.match(ctx, (file_,), opts)
4410 if m.anypats() or len(m.files()) != 1:
4410 if m.anypats() or len(m.files()) != 1:
4411 raise util.Abort(_('can only specify an explicit filename'))
4411 raise util.Abort(_('can only specify an explicit filename'))
4412 file_ = m.files()[0]
4412 file_ = m.files()[0]
4413 filenodes = []
4413 filenodes = []
4414 for cp in ctx.parents():
4414 for cp in ctx.parents():
4415 if not cp:
4415 if not cp:
4416 continue
4416 continue
4417 try:
4417 try:
4418 filenodes.append(cp.filenode(file_))
4418 filenodes.append(cp.filenode(file_))
4419 except error.LookupError:
4419 except error.LookupError:
4420 pass
4420 pass
4421 if not filenodes:
4421 if not filenodes:
4422 raise util.Abort(_("'%s' not found in manifest!") % file_)
4422 raise util.Abort(_("'%s' not found in manifest!") % file_)
4423 p = []
4423 p = []
4424 for fn in filenodes:
4424 for fn in filenodes:
4425 fctx = repo.filectx(file_, fileid=fn)
4425 fctx = repo.filectx(file_, fileid=fn)
4426 p.append(fctx.node())
4426 p.append(fctx.node())
4427 else:
4427 else:
4428 p = [cp.node() for cp in ctx.parents()]
4428 p = [cp.node() for cp in ctx.parents()]
4429
4429
4430 displayer = cmdutil.show_changeset(ui, repo, opts)
4430 displayer = cmdutil.show_changeset(ui, repo, opts)
4431 for n in p:
4431 for n in p:
4432 if n != nullid:
4432 if n != nullid:
4433 displayer.show(repo[n])
4433 displayer.show(repo[n])
4434 displayer.close()
4434 displayer.close()
4435
4435
4436 @command('paths', [], _('[NAME]'))
4436 @command('paths', [], _('[NAME]'))
4437 def paths(ui, repo, search=None):
4437 def paths(ui, repo, search=None):
4438 """show aliases for remote repositories
4438 """show aliases for remote repositories
4439
4439
4440 Show definition of symbolic path name NAME. If no name is given,
4440 Show definition of symbolic path name NAME. If no name is given,
4441 show definition of all available names.
4441 show definition of all available names.
4442
4442
4443 Option -q/--quiet suppresses all output when searching for NAME
4443 Option -q/--quiet suppresses all output when searching for NAME
4444 and shows only the path names when listing all definitions.
4444 and shows only the path names when listing all definitions.
4445
4445
4446 Path names are defined in the [paths] section of your
4446 Path names are defined in the [paths] section of your
4447 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4447 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4448 repository, ``.hg/hgrc`` is used, too.
4448 repository, ``.hg/hgrc`` is used, too.
4449
4449
4450 The path names ``default`` and ``default-push`` have a special
4450 The path names ``default`` and ``default-push`` have a special
4451 meaning. When performing a push or pull operation, they are used
4451 meaning. When performing a push or pull operation, they are used
4452 as fallbacks if no location is specified on the command-line.
4452 as fallbacks if no location is specified on the command-line.
4453 When ``default-push`` is set, it will be used for push and
4453 When ``default-push`` is set, it will be used for push and
4454 ``default`` will be used for pull; otherwise ``default`` is used
4454 ``default`` will be used for pull; otherwise ``default`` is used
4455 as the fallback for both. When cloning a repository, the clone
4455 as the fallback for both. When cloning a repository, the clone
4456 source is written as ``default`` in ``.hg/hgrc``. Note that
4456 source is written as ``default`` in ``.hg/hgrc``. Note that
4457 ``default`` and ``default-push`` apply to all inbound (e.g.
4457 ``default`` and ``default-push`` apply to all inbound (e.g.
4458 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4458 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4459 :hg:`bundle`) operations.
4459 :hg:`bundle`) operations.
4460
4460
4461 See :hg:`help urls` for more information.
4461 See :hg:`help urls` for more information.
4462
4462
4463 Returns 0 on success.
4463 Returns 0 on success.
4464 """
4464 """
4465 if search:
4465 if search:
4466 for name, path in ui.configitems("paths"):
4466 for name, path in ui.configitems("paths"):
4467 if name == search:
4467 if name == search:
4468 ui.status("%s\n" % util.hidepassword(path))
4468 ui.status("%s\n" % util.hidepassword(path))
4469 return
4469 return
4470 if not ui.quiet:
4470 if not ui.quiet:
4471 ui.warn(_("not found!\n"))
4471 ui.warn(_("not found!\n"))
4472 return 1
4472 return 1
4473 else:
4473 else:
4474 for name, path in ui.configitems("paths"):
4474 for name, path in ui.configitems("paths"):
4475 if ui.quiet:
4475 if ui.quiet:
4476 ui.write("%s\n" % name)
4476 ui.write("%s\n" % name)
4477 else:
4477 else:
4478 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4478 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4479
4479
4480 @command('phase',
4480 @command('phase',
4481 [('p', 'public', False, _('set changeset phase to public')),
4481 [('p', 'public', False, _('set changeset phase to public')),
4482 ('d', 'draft', False, _('set changeset phase to draft')),
4482 ('d', 'draft', False, _('set changeset phase to draft')),
4483 ('s', 'secret', False, _('set changeset phase to secret')),
4483 ('s', 'secret', False, _('set changeset phase to secret')),
4484 ('f', 'force', False, _('allow to move boundary backward')),
4484 ('f', 'force', False, _('allow to move boundary backward')),
4485 ('r', 'rev', [], _('target revision'), _('REV')),
4485 ('r', 'rev', [], _('target revision'), _('REV')),
4486 ],
4486 ],
4487 _('[-p|-d|-s] [-f] [-r] REV...'))
4487 _('[-p|-d|-s] [-f] [-r] REV...'))
4488 def phase(ui, repo, *revs, **opts):
4488 def phase(ui, repo, *revs, **opts):
4489 """set or show the current phase name
4489 """set or show the current phase name
4490
4490
4491 With no argument, show the phase name of specified revisions.
4491 With no argument, show the phase name of specified revisions.
4492
4492
4493 With one of -p/--public, -d/--draft or -s/--secret, change the
4493 With one of -p/--public, -d/--draft or -s/--secret, change the
4494 phase value of the specified revisions.
4494 phase value of the specified revisions.
4495
4495
4496 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4496 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4497 lower phase to an higher phase. Phases are ordered as follows::
4497 lower phase to an higher phase. Phases are ordered as follows::
4498
4498
4499 public < draft < secret
4499 public < draft < secret
4500
4500
4501 Returns 0 on success, 1 if no phases were changed or some could not
4501 Returns 0 on success, 1 if no phases were changed or some could not
4502 be changed.
4502 be changed.
4503 """
4503 """
4504 # search for a unique phase argument
4504 # search for a unique phase argument
4505 targetphase = None
4505 targetphase = None
4506 for idx, name in enumerate(phases.phasenames):
4506 for idx, name in enumerate(phases.phasenames):
4507 if opts[name]:
4507 if opts[name]:
4508 if targetphase is not None:
4508 if targetphase is not None:
4509 raise util.Abort(_('only one phase can be specified'))
4509 raise util.Abort(_('only one phase can be specified'))
4510 targetphase = idx
4510 targetphase = idx
4511
4511
4512 # look for specified revision
4512 # look for specified revision
4513 revs = list(revs)
4513 revs = list(revs)
4514 revs.extend(opts['rev'])
4514 revs.extend(opts['rev'])
4515 if not revs:
4515 if not revs:
4516 raise util.Abort(_('no revisions specified'))
4516 raise util.Abort(_('no revisions specified'))
4517
4517
4518 revs = scmutil.revrange(repo, revs)
4518 revs = scmutil.revrange(repo, revs)
4519
4519
4520 lock = None
4520 lock = None
4521 ret = 0
4521 ret = 0
4522 if targetphase is None:
4522 if targetphase is None:
4523 # display
4523 # display
4524 for r in revs:
4524 for r in revs:
4525 ctx = repo[r]
4525 ctx = repo[r]
4526 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4526 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4527 else:
4527 else:
4528 lock = repo.lock()
4528 lock = repo.lock()
4529 try:
4529 try:
4530 # set phase
4530 # set phase
4531 if not revs:
4531 if not revs:
4532 raise util.Abort(_('empty revision set'))
4532 raise util.Abort(_('empty revision set'))
4533 nodes = [repo[r].node() for r in revs]
4533 nodes = [repo[r].node() for r in revs]
4534 olddata = repo._phasecache.getphaserevs(repo)[:]
4534 olddata = repo._phasecache.getphaserevs(repo)[:]
4535 phases.advanceboundary(repo, targetphase, nodes)
4535 phases.advanceboundary(repo, targetphase, nodes)
4536 if opts['force']:
4536 if opts['force']:
4537 phases.retractboundary(repo, targetphase, nodes)
4537 phases.retractboundary(repo, targetphase, nodes)
4538 finally:
4538 finally:
4539 lock.release()
4539 lock.release()
4540 # moving revision from public to draft may hide them
4540 # moving revision from public to draft may hide them
4541 # We have to check result on an unfiltered repository
4541 # We have to check result on an unfiltered repository
4542 unfi = repo.unfiltered()
4542 unfi = repo.unfiltered()
4543 newdata = repo._phasecache.getphaserevs(unfi)
4543 newdata = repo._phasecache.getphaserevs(unfi)
4544 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4544 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4545 cl = unfi.changelog
4545 cl = unfi.changelog
4546 rejected = [n for n in nodes
4546 rejected = [n for n in nodes
4547 if newdata[cl.rev(n)] < targetphase]
4547 if newdata[cl.rev(n)] < targetphase]
4548 if rejected:
4548 if rejected:
4549 ui.warn(_('cannot move %i changesets to a higher '
4549 ui.warn(_('cannot move %i changesets to a higher '
4550 'phase, use --force\n') % len(rejected))
4550 'phase, use --force\n') % len(rejected))
4551 ret = 1
4551 ret = 1
4552 if changes:
4552 if changes:
4553 msg = _('phase changed for %i changesets\n') % changes
4553 msg = _('phase changed for %i changesets\n') % changes
4554 if ret:
4554 if ret:
4555 ui.status(msg)
4555 ui.status(msg)
4556 else:
4556 else:
4557 ui.note(msg)
4557 ui.note(msg)
4558 else:
4558 else:
4559 ui.warn(_('no phases changed\n'))
4559 ui.warn(_('no phases changed\n'))
4560 ret = 1
4560 ret = 1
4561 return ret
4561 return ret
4562
4562
4563 def postincoming(ui, repo, modheads, optupdate, checkout):
4563 def postincoming(ui, repo, modheads, optupdate, checkout):
4564 if modheads == 0:
4564 if modheads == 0:
4565 return
4565 return
4566 if optupdate:
4566 if optupdate:
4567 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4567 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4568 try:
4568 try:
4569 ret = hg.update(repo, checkout)
4569 ret = hg.update(repo, checkout)
4570 except util.Abort, inst:
4570 except util.Abort, inst:
4571 ui.warn(_("not updating: %s\n") % str(inst))
4571 ui.warn(_("not updating: %s\n") % str(inst))
4572 if inst.hint:
4572 if inst.hint:
4573 ui.warn(_("(%s)\n") % inst.hint)
4573 ui.warn(_("(%s)\n") % inst.hint)
4574 return 0
4574 return 0
4575 if not ret and not checkout:
4575 if not ret and not checkout:
4576 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4576 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4577 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4577 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4578 return ret
4578 return ret
4579 if modheads > 1:
4579 if modheads > 1:
4580 currentbranchheads = len(repo.branchheads())
4580 currentbranchheads = len(repo.branchheads())
4581 if currentbranchheads == modheads:
4581 if currentbranchheads == modheads:
4582 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4582 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4583 elif currentbranchheads > 1:
4583 elif currentbranchheads > 1:
4584 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4584 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4585 "merge)\n"))
4585 "merge)\n"))
4586 else:
4586 else:
4587 ui.status(_("(run 'hg heads' to see heads)\n"))
4587 ui.status(_("(run 'hg heads' to see heads)\n"))
4588 else:
4588 else:
4589 ui.status(_("(run 'hg update' to get a working copy)\n"))
4589 ui.status(_("(run 'hg update' to get a working copy)\n"))
4590
4590
4591 @command('^pull',
4591 @command('^pull',
4592 [('u', 'update', None,
4592 [('u', 'update', None,
4593 _('update to new branch head if changesets were pulled')),
4593 _('update to new branch head if changesets were pulled')),
4594 ('f', 'force', None, _('run even when remote repository is unrelated')),
4594 ('f', 'force', None, _('run even when remote repository is unrelated')),
4595 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4595 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4596 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4596 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4597 ('b', 'branch', [], _('a specific branch you would like to pull'),
4597 ('b', 'branch', [], _('a specific branch you would like to pull'),
4598 _('BRANCH')),
4598 _('BRANCH')),
4599 ] + remoteopts,
4599 ] + remoteopts,
4600 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4600 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4601 def pull(ui, repo, source="default", **opts):
4601 def pull(ui, repo, source="default", **opts):
4602 """pull changes from the specified source
4602 """pull changes from the specified source
4603
4603
4604 Pull changes from a remote repository to a local one.
4604 Pull changes from a remote repository to a local one.
4605
4605
4606 This finds all changes from the repository at the specified path
4606 This finds all changes from the repository at the specified path
4607 or URL and adds them to a local repository (the current one unless
4607 or URL and adds them to a local repository (the current one unless
4608 -R is specified). By default, this does not update the copy of the
4608 -R is specified). By default, this does not update the copy of the
4609 project in the working directory.
4609 project in the working directory.
4610
4610
4611 Use :hg:`incoming` if you want to see what would have been added
4611 Use :hg:`incoming` if you want to see what would have been added
4612 by a pull at the time you issued this command. If you then decide
4612 by a pull at the time you issued this command. If you then decide
4613 to add those changes to the repository, you should use :hg:`pull
4613 to add those changes to the repository, you should use :hg:`pull
4614 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4614 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4615
4615
4616 If SOURCE is omitted, the 'default' path will be used.
4616 If SOURCE is omitted, the 'default' path will be used.
4617 See :hg:`help urls` for more information.
4617 See :hg:`help urls` for more information.
4618
4618
4619 Returns 0 on success, 1 if an update had unresolved files.
4619 Returns 0 on success, 1 if an update had unresolved files.
4620 """
4620 """
4621 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4621 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4622 other = hg.peer(repo, opts, source)
4622 other = hg.peer(repo, opts, source)
4623 try:
4623 try:
4624 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4624 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4625 revs, checkout = hg.addbranchrevs(repo, other, branches,
4625 revs, checkout = hg.addbranchrevs(repo, other, branches,
4626 opts.get('rev'))
4626 opts.get('rev'))
4627
4627
4628 remotebookmarks = other.listkeys('bookmarks')
4628 remotebookmarks = other.listkeys('bookmarks')
4629
4629
4630 if opts.get('bookmark'):
4630 if opts.get('bookmark'):
4631 if not revs:
4631 if not revs:
4632 revs = []
4632 revs = []
4633 for b in opts['bookmark']:
4633 for b in opts['bookmark']:
4634 if b not in remotebookmarks:
4634 if b not in remotebookmarks:
4635 raise util.Abort(_('remote bookmark %s not found!') % b)
4635 raise util.Abort(_('remote bookmark %s not found!') % b)
4636 revs.append(remotebookmarks[b])
4636 revs.append(remotebookmarks[b])
4637
4637
4638 if revs:
4638 if revs:
4639 try:
4639 try:
4640 revs = [other.lookup(rev) for rev in revs]
4640 revs = [other.lookup(rev) for rev in revs]
4641 except error.CapabilityError:
4641 except error.CapabilityError:
4642 err = _("other repository doesn't support revision lookup, "
4642 err = _("other repository doesn't support revision lookup, "
4643 "so a rev cannot be specified.")
4643 "so a rev cannot be specified.")
4644 raise util.Abort(err)
4644 raise util.Abort(err)
4645
4645
4646 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4646 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4647 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4647 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4648 if checkout:
4648 if checkout:
4649 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4649 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4650 repo._subtoppath = source
4650 repo._subtoppath = source
4651 try:
4651 try:
4652 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4652 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4653
4653
4654 finally:
4654 finally:
4655 del repo._subtoppath
4655 del repo._subtoppath
4656
4656
4657 # update specified bookmarks
4657 # update specified bookmarks
4658 if opts.get('bookmark'):
4658 if opts.get('bookmark'):
4659 marks = repo._bookmarks
4659 marks = repo._bookmarks
4660 for b in opts['bookmark']:
4660 for b in opts['bookmark']:
4661 # explicit pull overrides local bookmark if any
4661 # explicit pull overrides local bookmark if any
4662 ui.status(_("importing bookmark %s\n") % b)
4662 ui.status(_("importing bookmark %s\n") % b)
4663 marks[b] = repo[remotebookmarks[b]].node()
4663 marks[b] = repo[remotebookmarks[b]].node()
4664 marks.write()
4664 marks.write()
4665 finally:
4665 finally:
4666 other.close()
4666 other.close()
4667 return ret
4667 return ret
4668
4668
4669 @command('^push',
4669 @command('^push',
4670 [('f', 'force', None, _('force push')),
4670 [('f', 'force', None, _('force push')),
4671 ('r', 'rev', [],
4671 ('r', 'rev', [],
4672 _('a changeset intended to be included in the destination'),
4672 _('a changeset intended to be included in the destination'),
4673 _('REV')),
4673 _('REV')),
4674 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4674 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4675 ('b', 'branch', [],
4675 ('b', 'branch', [],
4676 _('a specific branch you would like to push'), _('BRANCH')),
4676 _('a specific branch you would like to push'), _('BRANCH')),
4677 ('', 'new-branch', False, _('allow pushing a new branch')),
4677 ('', 'new-branch', False, _('allow pushing a new branch')),
4678 ] + remoteopts,
4678 ] + remoteopts,
4679 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4679 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4680 def push(ui, repo, dest=None, **opts):
4680 def push(ui, repo, dest=None, **opts):
4681 """push changes to the specified destination
4681 """push changes to the specified destination
4682
4682
4683 Push changesets from the local repository to the specified
4683 Push changesets from the local repository to the specified
4684 destination.
4684 destination.
4685
4685
4686 This operation is symmetrical to pull: it is identical to a pull
4686 This operation is symmetrical to pull: it is identical to a pull
4687 in the destination repository from the current one.
4687 in the destination repository from the current one.
4688
4688
4689 By default, push will not allow creation of new heads at the
4689 By default, push will not allow creation of new heads at the
4690 destination, since multiple heads would make it unclear which head
4690 destination, since multiple heads would make it unclear which head
4691 to use. In this situation, it is recommended to pull and merge
4691 to use. In this situation, it is recommended to pull and merge
4692 before pushing.
4692 before pushing.
4693
4693
4694 Use --new-branch if you want to allow push to create a new named
4694 Use --new-branch if you want to allow push to create a new named
4695 branch that is not present at the destination. This allows you to
4695 branch that is not present at the destination. This allows you to
4696 only create a new branch without forcing other changes.
4696 only create a new branch without forcing other changes.
4697
4697
4698 .. note::
4698 .. note::
4699
4699
4700 Extra care should be taken with the -f/--force option,
4700 Extra care should be taken with the -f/--force option,
4701 which will push all new heads on all branches, an action which will
4701 which will push all new heads on all branches, an action which will
4702 almost always cause confusion for collaborators.
4702 almost always cause confusion for collaborators.
4703
4703
4704 If -r/--rev is used, the specified revision and all its ancestors
4704 If -r/--rev is used, the specified revision and all its ancestors
4705 will be pushed to the remote repository.
4705 will be pushed to the remote repository.
4706
4706
4707 If -B/--bookmark is used, the specified bookmarked revision, its
4707 If -B/--bookmark is used, the specified bookmarked revision, its
4708 ancestors, and the bookmark will be pushed to the remote
4708 ancestors, and the bookmark will be pushed to the remote
4709 repository.
4709 repository.
4710
4710
4711 Please see :hg:`help urls` for important details about ``ssh://``
4711 Please see :hg:`help urls` for important details about ``ssh://``
4712 URLs. If DESTINATION is omitted, a default path will be used.
4712 URLs. If DESTINATION is omitted, a default path will be used.
4713
4713
4714 Returns 0 if push was successful, 1 if nothing to push.
4714 Returns 0 if push was successful, 1 if nothing to push.
4715 """
4715 """
4716
4716
4717 if opts.get('bookmark'):
4717 if opts.get('bookmark'):
4718 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4718 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4719 for b in opts['bookmark']:
4719 for b in opts['bookmark']:
4720 # translate -B options to -r so changesets get pushed
4720 # translate -B options to -r so changesets get pushed
4721 if b in repo._bookmarks:
4721 if b in repo._bookmarks:
4722 opts.setdefault('rev', []).append(b)
4722 opts.setdefault('rev', []).append(b)
4723 else:
4723 else:
4724 # if we try to push a deleted bookmark, translate it to null
4724 # if we try to push a deleted bookmark, translate it to null
4725 # this lets simultaneous -r, -b options continue working
4725 # this lets simultaneous -r, -b options continue working
4726 opts.setdefault('rev', []).append("null")
4726 opts.setdefault('rev', []).append("null")
4727
4727
4728 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4728 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4729 dest, branches = hg.parseurl(dest, opts.get('branch'))
4729 dest, branches = hg.parseurl(dest, opts.get('branch'))
4730 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4730 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4731 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4731 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4732 try:
4732 try:
4733 other = hg.peer(repo, opts, dest)
4733 other = hg.peer(repo, opts, dest)
4734 except error.RepoError:
4734 except error.RepoError:
4735 if dest == "default-push":
4735 if dest == "default-push":
4736 raise util.Abort(_("default repository not configured!"),
4736 raise util.Abort(_("default repository not configured!"),
4737 hint=_('see the "path" section in "hg help config"'))
4737 hint=_('see the "path" section in "hg help config"'))
4738 else:
4738 else:
4739 raise
4739 raise
4740
4740
4741 if revs:
4741 if revs:
4742 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4742 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4743
4743
4744 repo._subtoppath = dest
4744 repo._subtoppath = dest
4745 try:
4745 try:
4746 # push subrepos depth-first for coherent ordering
4746 # push subrepos depth-first for coherent ordering
4747 c = repo['']
4747 c = repo['']
4748 subs = c.substate # only repos that are committed
4748 subs = c.substate # only repos that are committed
4749 for s in sorted(subs):
4749 for s in sorted(subs):
4750 result = c.sub(s).push(opts)
4750 result = c.sub(s).push(opts)
4751 if result == 0:
4751 if result == 0:
4752 return not result
4752 return not result
4753 finally:
4753 finally:
4754 del repo._subtoppath
4754 del repo._subtoppath
4755 result = repo.push(other, opts.get('force'), revs=revs,
4755 result = repo.push(other, opts.get('force'), revs=revs,
4756 newbranch=opts.get('new_branch'))
4756 newbranch=opts.get('new_branch'))
4757
4757
4758 result = not result
4758 result = not result
4759
4759
4760 if opts.get('bookmark'):
4760 if opts.get('bookmark'):
4761 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4761 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4762 if bresult == 2:
4762 if bresult == 2:
4763 return 2
4763 return 2
4764 if not result and bresult:
4764 if not result and bresult:
4765 result = 2
4765 result = 2
4766
4766
4767 return result
4767 return result
4768
4768
4769 @command('recover', [])
4769 @command('recover', [])
4770 def recover(ui, repo):
4770 def recover(ui, repo):
4771 """roll back an interrupted transaction
4771 """roll back an interrupted transaction
4772
4772
4773 Recover from an interrupted commit or pull.
4773 Recover from an interrupted commit or pull.
4774
4774
4775 This command tries to fix the repository status after an
4775 This command tries to fix the repository status after an
4776 interrupted operation. It should only be necessary when Mercurial
4776 interrupted operation. It should only be necessary when Mercurial
4777 suggests it.
4777 suggests it.
4778
4778
4779 Returns 0 if successful, 1 if nothing to recover or verify fails.
4779 Returns 0 if successful, 1 if nothing to recover or verify fails.
4780 """
4780 """
4781 if repo.recover():
4781 if repo.recover():
4782 return hg.verify(repo)
4782 return hg.verify(repo)
4783 return 1
4783 return 1
4784
4784
4785 @command('^remove|rm',
4785 @command('^remove|rm',
4786 [('A', 'after', None, _('record delete for missing files')),
4786 [('A', 'after', None, _('record delete for missing files')),
4787 ('f', 'force', None,
4787 ('f', 'force', None,
4788 _('remove (and delete) file even if added or modified')),
4788 _('remove (and delete) file even if added or modified')),
4789 ] + walkopts,
4789 ] + walkopts,
4790 _('[OPTION]... FILE...'))
4790 _('[OPTION]... FILE...'))
4791 def remove(ui, repo, *pats, **opts):
4791 def remove(ui, repo, *pats, **opts):
4792 """remove the specified files on the next commit
4792 """remove the specified files on the next commit
4793
4793
4794 Schedule the indicated files for removal from the current branch.
4794 Schedule the indicated files for removal from the current branch.
4795
4795
4796 This command schedules the files to be removed at the next commit.
4796 This command schedules the files to be removed at the next commit.
4797 To undo a remove before that, see :hg:`revert`. To undo added
4797 To undo a remove before that, see :hg:`revert`. To undo added
4798 files, see :hg:`forget`.
4798 files, see :hg:`forget`.
4799
4799
4800 .. container:: verbose
4800 .. container:: verbose
4801
4801
4802 -A/--after can be used to remove only files that have already
4802 -A/--after can be used to remove only files that have already
4803 been deleted, -f/--force can be used to force deletion, and -Af
4803 been deleted, -f/--force can be used to force deletion, and -Af
4804 can be used to remove files from the next revision without
4804 can be used to remove files from the next revision without
4805 deleting them from the working directory.
4805 deleting them from the working directory.
4806
4806
4807 The following table details the behavior of remove for different
4807 The following table details the behavior of remove for different
4808 file states (columns) and option combinations (rows). The file
4808 file states (columns) and option combinations (rows). The file
4809 states are Added [A], Clean [C], Modified [M] and Missing [!]
4809 states are Added [A], Clean [C], Modified [M] and Missing [!]
4810 (as reported by :hg:`status`). The actions are Warn, Remove
4810 (as reported by :hg:`status`). The actions are Warn, Remove
4811 (from branch) and Delete (from disk):
4811 (from branch) and Delete (from disk):
4812
4812
4813 ========= == == == ==
4813 ========= == == == ==
4814 opt/state A C M !
4814 opt/state A C M !
4815 ========= == == == ==
4815 ========= == == == ==
4816 none W RD W R
4816 none W RD W R
4817 -f R RD RD R
4817 -f R RD RD R
4818 -A W W W R
4818 -A W W W R
4819 -Af R R R R
4819 -Af R R R R
4820 ========= == == == ==
4820 ========= == == == ==
4821
4821
4822 Note that remove never deletes files in Added [A] state from the
4822 Note that remove never deletes files in Added [A] state from the
4823 working directory, not even if option --force is specified.
4823 working directory, not even if option --force is specified.
4824
4824
4825 Returns 0 on success, 1 if any warnings encountered.
4825 Returns 0 on success, 1 if any warnings encountered.
4826 """
4826 """
4827
4827
4828 ret = 0
4828 ret = 0
4829 after, force = opts.get('after'), opts.get('force')
4829 after, force = opts.get('after'), opts.get('force')
4830 if not pats and not after:
4830 if not pats and not after:
4831 raise util.Abort(_('no files specified'))
4831 raise util.Abort(_('no files specified'))
4832
4832
4833 m = scmutil.match(repo[None], pats, opts)
4833 m = scmutil.match(repo[None], pats, opts)
4834 s = repo.status(match=m, clean=True)
4834 s = repo.status(match=m, clean=True)
4835 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4835 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4836
4836
4837 # warn about failure to delete explicit files/dirs
4837 # warn about failure to delete explicit files/dirs
4838 wctx = repo[None]
4838 wctx = repo[None]
4839 for f in m.files():
4839 for f in m.files():
4840 if f in repo.dirstate or f in wctx.dirs():
4840 if f in repo.dirstate or f in wctx.dirs():
4841 continue
4841 continue
4842 if os.path.exists(m.rel(f)):
4842 if os.path.exists(m.rel(f)):
4843 if os.path.isdir(m.rel(f)):
4843 if os.path.isdir(m.rel(f)):
4844 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4844 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4845 else:
4845 else:
4846 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4846 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4847 # missing files will generate a warning elsewhere
4847 # missing files will generate a warning elsewhere
4848 ret = 1
4848 ret = 1
4849
4849
4850 if force:
4850 if force:
4851 list = modified + deleted + clean + added
4851 list = modified + deleted + clean + added
4852 elif after:
4852 elif after:
4853 list = deleted
4853 list = deleted
4854 for f in modified + added + clean:
4854 for f in modified + added + clean:
4855 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4855 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4856 ret = 1
4856 ret = 1
4857 else:
4857 else:
4858 list = deleted + clean
4858 list = deleted + clean
4859 for f in modified:
4859 for f in modified:
4860 ui.warn(_('not removing %s: file is modified (use -f'
4860 ui.warn(_('not removing %s: file is modified (use -f'
4861 ' to force removal)\n') % m.rel(f))
4861 ' to force removal)\n') % m.rel(f))
4862 ret = 1
4862 ret = 1
4863 for f in added:
4863 for f in added:
4864 ui.warn(_('not removing %s: file has been marked for add'
4864 ui.warn(_('not removing %s: file has been marked for add'
4865 ' (use forget to undo)\n') % m.rel(f))
4865 ' (use forget to undo)\n') % m.rel(f))
4866 ret = 1
4866 ret = 1
4867
4867
4868 for f in sorted(list):
4868 for f in sorted(list):
4869 if ui.verbose or not m.exact(f):
4869 if ui.verbose or not m.exact(f):
4870 ui.status(_('removing %s\n') % m.rel(f))
4870 ui.status(_('removing %s\n') % m.rel(f))
4871
4871
4872 wlock = repo.wlock()
4872 wlock = repo.wlock()
4873 try:
4873 try:
4874 if not after:
4874 if not after:
4875 for f in list:
4875 for f in list:
4876 if f in added:
4876 if f in added:
4877 continue # we never unlink added files on remove
4877 continue # we never unlink added files on remove
4878 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4878 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4879 repo[None].forget(list)
4879 repo[None].forget(list)
4880 finally:
4880 finally:
4881 wlock.release()
4881 wlock.release()
4882
4882
4883 return ret
4883 return ret
4884
4884
4885 @command('rename|move|mv',
4885 @command('rename|move|mv',
4886 [('A', 'after', None, _('record a rename that has already occurred')),
4886 [('A', 'after', None, _('record a rename that has already occurred')),
4887 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4887 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4888 ] + walkopts + dryrunopts,
4888 ] + walkopts + dryrunopts,
4889 _('[OPTION]... SOURCE... DEST'))
4889 _('[OPTION]... SOURCE... DEST'))
4890 def rename(ui, repo, *pats, **opts):
4890 def rename(ui, repo, *pats, **opts):
4891 """rename files; equivalent of copy + remove
4891 """rename files; equivalent of copy + remove
4892
4892
4893 Mark dest as copies of sources; mark sources for deletion. If dest
4893 Mark dest as copies of sources; mark sources for deletion. If dest
4894 is a directory, copies are put in that directory. If dest is a
4894 is a directory, copies are put in that directory. If dest is a
4895 file, there can only be one source.
4895 file, there can only be one source.
4896
4896
4897 By default, this command copies the contents of files as they
4897 By default, this command copies the contents of files as they
4898 exist in the working directory. If invoked with -A/--after, the
4898 exist in the working directory. If invoked with -A/--after, the
4899 operation is recorded, but no copying is performed.
4899 operation is recorded, but no copying is performed.
4900
4900
4901 This command takes effect at the next commit. To undo a rename
4901 This command takes effect at the next commit. To undo a rename
4902 before that, see :hg:`revert`.
4902 before that, see :hg:`revert`.
4903
4903
4904 Returns 0 on success, 1 if errors are encountered.
4904 Returns 0 on success, 1 if errors are encountered.
4905 """
4905 """
4906 wlock = repo.wlock(False)
4906 wlock = repo.wlock(False)
4907 try:
4907 try:
4908 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4908 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4909 finally:
4909 finally:
4910 wlock.release()
4910 wlock.release()
4911
4911
4912 @command('resolve',
4912 @command('resolve',
4913 [('a', 'all', None, _('select all unresolved files')),
4913 [('a', 'all', None, _('select all unresolved files')),
4914 ('l', 'list', None, _('list state of files needing merge')),
4914 ('l', 'list', None, _('list state of files needing merge')),
4915 ('m', 'mark', None, _('mark files as resolved')),
4915 ('m', 'mark', None, _('mark files as resolved')),
4916 ('u', 'unmark', None, _('mark files as unresolved')),
4916 ('u', 'unmark', None, _('mark files as unresolved')),
4917 ('n', 'no-status', None, _('hide status prefix'))]
4917 ('n', 'no-status', None, _('hide status prefix'))]
4918 + mergetoolopts + walkopts,
4918 + mergetoolopts + walkopts,
4919 _('[OPTION]... [FILE]...'))
4919 _('[OPTION]... [FILE]...'))
4920 def resolve(ui, repo, *pats, **opts):
4920 def resolve(ui, repo, *pats, **opts):
4921 """redo merges or set/view the merge status of files
4921 """redo merges or set/view the merge status of files
4922
4922
4923 Merges with unresolved conflicts are often the result of
4923 Merges with unresolved conflicts are often the result of
4924 non-interactive merging using the ``internal:merge`` configuration
4924 non-interactive merging using the ``internal:merge`` configuration
4925 setting, or a command-line merge tool like ``diff3``. The resolve
4925 setting, or a command-line merge tool like ``diff3``. The resolve
4926 command is used to manage the files involved in a merge, after
4926 command is used to manage the files involved in a merge, after
4927 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4927 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4928 working directory must have two parents). See :hg:`help
4928 working directory must have two parents). See :hg:`help
4929 merge-tools` for information on configuring merge tools.
4929 merge-tools` for information on configuring merge tools.
4930
4930
4931 The resolve command can be used in the following ways:
4931 The resolve command can be used in the following ways:
4932
4932
4933 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4933 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4934 files, discarding any previous merge attempts. Re-merging is not
4934 files, discarding any previous merge attempts. Re-merging is not
4935 performed for files already marked as resolved. Use ``--all/-a``
4935 performed for files already marked as resolved. Use ``--all/-a``
4936 to select all unresolved files. ``--tool`` can be used to specify
4936 to select all unresolved files. ``--tool`` can be used to specify
4937 the merge tool used for the given files. It overrides the HGMERGE
4937 the merge tool used for the given files. It overrides the HGMERGE
4938 environment variable and your configuration files. Previous file
4938 environment variable and your configuration files. Previous file
4939 contents are saved with a ``.orig`` suffix.
4939 contents are saved with a ``.orig`` suffix.
4940
4940
4941 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4941 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4942 (e.g. after having manually fixed-up the files). The default is
4942 (e.g. after having manually fixed-up the files). The default is
4943 to mark all unresolved files.
4943 to mark all unresolved files.
4944
4944
4945 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4945 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4946 default is to mark all resolved files.
4946 default is to mark all resolved files.
4947
4947
4948 - :hg:`resolve -l`: list files which had or still have conflicts.
4948 - :hg:`resolve -l`: list files which had or still have conflicts.
4949 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4949 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4950
4950
4951 Note that Mercurial will not let you commit files with unresolved
4951 Note that Mercurial will not let you commit files with unresolved
4952 merge conflicts. You must use :hg:`resolve -m ...` before you can
4952 merge conflicts. You must use :hg:`resolve -m ...` before you can
4953 commit after a conflicting merge.
4953 commit after a conflicting merge.
4954
4954
4955 Returns 0 on success, 1 if any files fail a resolve attempt.
4955 Returns 0 on success, 1 if any files fail a resolve attempt.
4956 """
4956 """
4957
4957
4958 all, mark, unmark, show, nostatus = \
4958 all, mark, unmark, show, nostatus = \
4959 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4959 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4960
4960
4961 if (show and (mark or unmark)) or (mark and unmark):
4961 if (show and (mark or unmark)) or (mark and unmark):
4962 raise util.Abort(_("too many options specified"))
4962 raise util.Abort(_("too many options specified"))
4963 if pats and all:
4963 if pats and all:
4964 raise util.Abort(_("can't specify --all and patterns"))
4964 raise util.Abort(_("can't specify --all and patterns"))
4965 if not (all or pats or show or mark or unmark):
4965 if not (all or pats or show or mark or unmark):
4966 raise util.Abort(_('no files or directories specified; '
4966 raise util.Abort(_('no files or directories specified; '
4967 'use --all to remerge all files'))
4967 'use --all to remerge all files'))
4968
4968
4969 ms = mergemod.mergestate(repo)
4969 ms = mergemod.mergestate(repo)
4970 m = scmutil.match(repo[None], pats, opts)
4970 m = scmutil.match(repo[None], pats, opts)
4971 ret = 0
4971 ret = 0
4972
4972
4973 for f in ms:
4973 for f in ms:
4974 if m(f):
4974 if m(f):
4975 if show:
4975 if show:
4976 if nostatus:
4976 if nostatus:
4977 ui.write("%s\n" % f)
4977 ui.write("%s\n" % f)
4978 else:
4978 else:
4979 ui.write("%s %s\n" % (ms[f].upper(), f),
4979 ui.write("%s %s\n" % (ms[f].upper(), f),
4980 label='resolve.' +
4980 label='resolve.' +
4981 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4981 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4982 elif mark:
4982 elif mark:
4983 ms.mark(f, "r")
4983 ms.mark(f, "r")
4984 elif unmark:
4984 elif unmark:
4985 ms.mark(f, "u")
4985 ms.mark(f, "u")
4986 else:
4986 else:
4987 wctx = repo[None]
4987 wctx = repo[None]
4988
4988
4989 # backup pre-resolve (merge uses .orig for its own purposes)
4989 # backup pre-resolve (merge uses .orig for its own purposes)
4990 a = repo.wjoin(f)
4990 a = repo.wjoin(f)
4991 util.copyfile(a, a + ".resolve")
4991 util.copyfile(a, a + ".resolve")
4992
4992
4993 try:
4993 try:
4994 # resolve file
4994 # resolve file
4995 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4995 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4996 'resolve')
4996 'resolve')
4997 if ms.resolve(f, wctx):
4997 if ms.resolve(f, wctx):
4998 ret = 1
4998 ret = 1
4999 finally:
4999 finally:
5000 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5000 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5001 ms.commit()
5001 ms.commit()
5002
5002
5003 # replace filemerge's .orig file with our resolve file
5003 # replace filemerge's .orig file with our resolve file
5004 util.rename(a + ".resolve", a + ".orig")
5004 util.rename(a + ".resolve", a + ".orig")
5005
5005
5006 ms.commit()
5006 ms.commit()
5007 return ret
5007 return ret
5008
5008
5009 @command('revert',
5009 @command('revert',
5010 [('a', 'all', None, _('revert all changes when no arguments given')),
5010 [('a', 'all', None, _('revert all changes when no arguments given')),
5011 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5011 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5012 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5012 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5013 ('C', 'no-backup', None, _('do not save backup copies of files')),
5013 ('C', 'no-backup', None, _('do not save backup copies of files')),
5014 ] + walkopts + dryrunopts,
5014 ] + walkopts + dryrunopts,
5015 _('[OPTION]... [-r REV] [NAME]...'))
5015 _('[OPTION]... [-r REV] [NAME]...'))
5016 def revert(ui, repo, *pats, **opts):
5016 def revert(ui, repo, *pats, **opts):
5017 """restore files to their checkout state
5017 """restore files to their checkout state
5018
5018
5019 .. note::
5019 .. note::
5020
5020
5021 To check out earlier revisions, you should use :hg:`update REV`.
5021 To check out earlier revisions, you should use :hg:`update REV`.
5022 To cancel an uncommitted merge (and lose your changes),
5022 To cancel an uncommitted merge (and lose your changes),
5023 use :hg:`update --clean .`.
5023 use :hg:`update --clean .`.
5024
5024
5025 With no revision specified, revert the specified files or directories
5025 With no revision specified, revert the specified files or directories
5026 to the contents they had in the parent of the working directory.
5026 to the contents they had in the parent of the working directory.
5027 This restores the contents of files to an unmodified
5027 This restores the contents of files to an unmodified
5028 state and unschedules adds, removes, copies, and renames. If the
5028 state and unschedules adds, removes, copies, and renames. If the
5029 working directory has two parents, you must explicitly specify a
5029 working directory has two parents, you must explicitly specify a
5030 revision.
5030 revision.
5031
5031
5032 Using the -r/--rev or -d/--date options, revert the given files or
5032 Using the -r/--rev or -d/--date options, revert the given files or
5033 directories to their states as of a specific revision. Because
5033 directories to their states as of a specific revision. Because
5034 revert does not change the working directory parents, this will
5034 revert does not change the working directory parents, this will
5035 cause these files to appear modified. This can be helpful to "back
5035 cause these files to appear modified. This can be helpful to "back
5036 out" some or all of an earlier change. See :hg:`backout` for a
5036 out" some or all of an earlier change. See :hg:`backout` for a
5037 related method.
5037 related method.
5038
5038
5039 Modified files are saved with a .orig suffix before reverting.
5039 Modified files are saved with a .orig suffix before reverting.
5040 To disable these backups, use --no-backup.
5040 To disable these backups, use --no-backup.
5041
5041
5042 See :hg:`help dates` for a list of formats valid for -d/--date.
5042 See :hg:`help dates` for a list of formats valid for -d/--date.
5043
5043
5044 Returns 0 on success.
5044 Returns 0 on success.
5045 """
5045 """
5046
5046
5047 if opts.get("date"):
5047 if opts.get("date"):
5048 if opts.get("rev"):
5048 if opts.get("rev"):
5049 raise util.Abort(_("you can't specify a revision and a date"))
5049 raise util.Abort(_("you can't specify a revision and a date"))
5050 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5050 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5051
5051
5052 parent, p2 = repo.dirstate.parents()
5052 parent, p2 = repo.dirstate.parents()
5053 if not opts.get('rev') and p2 != nullid:
5053 if not opts.get('rev') and p2 != nullid:
5054 # revert after merge is a trap for new users (issue2915)
5054 # revert after merge is a trap for new users (issue2915)
5055 raise util.Abort(_('uncommitted merge with no revision specified'),
5055 raise util.Abort(_('uncommitted merge with no revision specified'),
5056 hint=_('use "hg update" or see "hg help revert"'))
5056 hint=_('use "hg update" or see "hg help revert"'))
5057
5057
5058 ctx = scmutil.revsingle(repo, opts.get('rev'))
5058 ctx = scmutil.revsingle(repo, opts.get('rev'))
5059
5059
5060 if not pats and not opts.get('all'):
5060 if not pats and not opts.get('all'):
5061 msg = _("no files or directories specified")
5061 msg = _("no files or directories specified")
5062 if p2 != nullid:
5062 if p2 != nullid:
5063 hint = _("uncommitted merge, use --all to discard all changes,"
5063 hint = _("uncommitted merge, use --all to discard all changes,"
5064 " or 'hg update -C .' to abort the merge")
5064 " or 'hg update -C .' to abort the merge")
5065 raise util.Abort(msg, hint=hint)
5065 raise util.Abort(msg, hint=hint)
5066 dirty = util.any(repo.status())
5066 dirty = util.any(repo.status())
5067 node = ctx.node()
5067 node = ctx.node()
5068 if node != parent:
5068 if node != parent:
5069 if dirty:
5069 if dirty:
5070 hint = _("uncommitted changes, use --all to discard all"
5070 hint = _("uncommitted changes, use --all to discard all"
5071 " changes, or 'hg update %s' to update") % ctx.rev()
5071 " changes, or 'hg update %s' to update") % ctx.rev()
5072 else:
5072 else:
5073 hint = _("use --all to revert all files,"
5073 hint = _("use --all to revert all files,"
5074 " or 'hg update %s' to update") % ctx.rev()
5074 " or 'hg update %s' to update") % ctx.rev()
5075 elif dirty:
5075 elif dirty:
5076 hint = _("uncommitted changes, use --all to discard all changes")
5076 hint = _("uncommitted changes, use --all to discard all changes")
5077 else:
5077 else:
5078 hint = _("use --all to revert all files")
5078 hint = _("use --all to revert all files")
5079 raise util.Abort(msg, hint=hint)
5079 raise util.Abort(msg, hint=hint)
5080
5080
5081 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5081 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5082
5082
5083 @command('rollback', dryrunopts +
5083 @command('rollback', dryrunopts +
5084 [('f', 'force', False, _('ignore safety measures'))])
5084 [('f', 'force', False, _('ignore safety measures'))])
5085 def rollback(ui, repo, **opts):
5085 def rollback(ui, repo, **opts):
5086 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5086 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5087
5087
5088 Please use :hg:`commit --amend` instead of rollback to correct
5088 Please use :hg:`commit --amend` instead of rollback to correct
5089 mistakes in the last commit.
5089 mistakes in the last commit.
5090
5090
5091 This command should be used with care. There is only one level of
5091 This command should be used with care. There is only one level of
5092 rollback, and there is no way to undo a rollback. It will also
5092 rollback, and there is no way to undo a rollback. It will also
5093 restore the dirstate at the time of the last transaction, losing
5093 restore the dirstate at the time of the last transaction, losing
5094 any dirstate changes since that time. This command does not alter
5094 any dirstate changes since that time. This command does not alter
5095 the working directory.
5095 the working directory.
5096
5096
5097 Transactions are used to encapsulate the effects of all commands
5097 Transactions are used to encapsulate the effects of all commands
5098 that create new changesets or propagate existing changesets into a
5098 that create new changesets or propagate existing changesets into a
5099 repository.
5099 repository.
5100
5100
5101 .. container:: verbose
5101 .. container:: verbose
5102
5102
5103 For example, the following commands are transactional, and their
5103 For example, the following commands are transactional, and their
5104 effects can be rolled back:
5104 effects can be rolled back:
5105
5105
5106 - commit
5106 - commit
5107 - import
5107 - import
5108 - pull
5108 - pull
5109 - push (with this repository as the destination)
5109 - push (with this repository as the destination)
5110 - unbundle
5110 - unbundle
5111
5111
5112 To avoid permanent data loss, rollback will refuse to rollback a
5112 To avoid permanent data loss, rollback will refuse to rollback a
5113 commit transaction if it isn't checked out. Use --force to
5113 commit transaction if it isn't checked out. Use --force to
5114 override this protection.
5114 override this protection.
5115
5115
5116 This command is not intended for use on public repositories. Once
5116 This command is not intended for use on public repositories. Once
5117 changes are visible for pull by other users, rolling a transaction
5117 changes are visible for pull by other users, rolling a transaction
5118 back locally is ineffective (someone else may already have pulled
5118 back locally is ineffective (someone else may already have pulled
5119 the changes). Furthermore, a race is possible with readers of the
5119 the changes). Furthermore, a race is possible with readers of the
5120 repository; for example an in-progress pull from the repository
5120 repository; for example an in-progress pull from the repository
5121 may fail if a rollback is performed.
5121 may fail if a rollback is performed.
5122
5122
5123 Returns 0 on success, 1 if no rollback data is available.
5123 Returns 0 on success, 1 if no rollback data is available.
5124 """
5124 """
5125 return repo.rollback(dryrun=opts.get('dry_run'),
5125 return repo.rollback(dryrun=opts.get('dry_run'),
5126 force=opts.get('force'))
5126 force=opts.get('force'))
5127
5127
5128 @command('root', [])
5128 @command('root', [])
5129 def root(ui, repo):
5129 def root(ui, repo):
5130 """print the root (top) of the current working directory
5130 """print the root (top) of the current working directory
5131
5131
5132 Print the root directory of the current repository.
5132 Print the root directory of the current repository.
5133
5133
5134 Returns 0 on success.
5134 Returns 0 on success.
5135 """
5135 """
5136 ui.write(repo.root + "\n")
5136 ui.write(repo.root + "\n")
5137
5137
5138 @command('^serve',
5138 @command('^serve',
5139 [('A', 'accesslog', '', _('name of access log file to write to'),
5139 [('A', 'accesslog', '', _('name of access log file to write to'),
5140 _('FILE')),
5140 _('FILE')),
5141 ('d', 'daemon', None, _('run server in background')),
5141 ('d', 'daemon', None, _('run server in background')),
5142 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5142 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5143 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5143 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5144 # use string type, then we can check if something was passed
5144 # use string type, then we can check if something was passed
5145 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5145 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5146 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5146 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5147 _('ADDR')),
5147 _('ADDR')),
5148 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5148 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5149 _('PREFIX')),
5149 _('PREFIX')),
5150 ('n', 'name', '',
5150 ('n', 'name', '',
5151 _('name to show in web pages (default: working directory)'), _('NAME')),
5151 _('name to show in web pages (default: working directory)'), _('NAME')),
5152 ('', 'web-conf', '',
5152 ('', 'web-conf', '',
5153 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5153 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5154 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5154 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5155 _('FILE')),
5155 _('FILE')),
5156 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5156 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5157 ('', 'stdio', None, _('for remote clients')),
5157 ('', 'stdio', None, _('for remote clients')),
5158 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5158 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5159 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5159 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5160 ('', 'style', '', _('template style to use'), _('STYLE')),
5160 ('', 'style', '', _('template style to use'), _('STYLE')),
5161 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5161 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5162 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5162 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5163 _('[OPTION]...'))
5163 _('[OPTION]...'))
5164 def serve(ui, repo, **opts):
5164 def serve(ui, repo, **opts):
5165 """start stand-alone webserver
5165 """start stand-alone webserver
5166
5166
5167 Start a local HTTP repository browser and pull server. You can use
5167 Start a local HTTP repository browser and pull server. You can use
5168 this for ad-hoc sharing and browsing of repositories. It is
5168 this for ad-hoc sharing and browsing of repositories. It is
5169 recommended to use a real web server to serve a repository for
5169 recommended to use a real web server to serve a repository for
5170 longer periods of time.
5170 longer periods of time.
5171
5171
5172 Please note that the server does not implement access control.
5172 Please note that the server does not implement access control.
5173 This means that, by default, anybody can read from the server and
5173 This means that, by default, anybody can read from the server and
5174 nobody can write to it by default. Set the ``web.allow_push``
5174 nobody can write to it by default. Set the ``web.allow_push``
5175 option to ``*`` to allow everybody to push to the server. You
5175 option to ``*`` to allow everybody to push to the server. You
5176 should use a real web server if you need to authenticate users.
5176 should use a real web server if you need to authenticate users.
5177
5177
5178 By default, the server logs accesses to stdout and errors to
5178 By default, the server logs accesses to stdout and errors to
5179 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5179 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5180 files.
5180 files.
5181
5181
5182 To have the server choose a free port number to listen on, specify
5182 To have the server choose a free port number to listen on, specify
5183 a port number of 0; in this case, the server will print the port
5183 a port number of 0; in this case, the server will print the port
5184 number it uses.
5184 number it uses.
5185
5185
5186 Returns 0 on success.
5186 Returns 0 on success.
5187 """
5187 """
5188
5188
5189 if opts["stdio"] and opts["cmdserver"]:
5189 if opts["stdio"] and opts["cmdserver"]:
5190 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5190 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5191
5191
5192 def checkrepo():
5192 def checkrepo():
5193 if repo is None:
5193 if repo is None:
5194 raise error.RepoError(_("there is no Mercurial repository here"
5194 raise error.RepoError(_("there is no Mercurial repository here"
5195 " (.hg not found)"))
5195 " (.hg not found)"))
5196
5196
5197 if opts["stdio"]:
5197 if opts["stdio"]:
5198 checkrepo()
5198 checkrepo()
5199 s = sshserver.sshserver(ui, repo)
5199 s = sshserver.sshserver(ui, repo)
5200 s.serve_forever()
5200 s.serve_forever()
5201
5201
5202 if opts["cmdserver"]:
5202 if opts["cmdserver"]:
5203 s = commandserver.server(ui, repo, opts["cmdserver"])
5203 s = commandserver.server(ui, repo, opts["cmdserver"])
5204 return s.serve()
5204 return s.serve()
5205
5205
5206 # this way we can check if something was given in the command-line
5206 # this way we can check if something was given in the command-line
5207 if opts.get('port'):
5207 if opts.get('port'):
5208 opts['port'] = util.getport(opts.get('port'))
5208 opts['port'] = util.getport(opts.get('port'))
5209
5209
5210 baseui = repo and repo.baseui or ui
5210 baseui = repo and repo.baseui or ui
5211 optlist = ("name templates style address port prefix ipv6"
5211 optlist = ("name templates style address port prefix ipv6"
5212 " accesslog errorlog certificate encoding")
5212 " accesslog errorlog certificate encoding")
5213 for o in optlist.split():
5213 for o in optlist.split():
5214 val = opts.get(o, '')
5214 val = opts.get(o, '')
5215 if val in (None, ''): # should check against default options instead
5215 if val in (None, ''): # should check against default options instead
5216 continue
5216 continue
5217 baseui.setconfig("web", o, val, 'serve')
5217 baseui.setconfig("web", o, val, 'serve')
5218 if repo and repo.ui != baseui:
5218 if repo and repo.ui != baseui:
5219 repo.ui.setconfig("web", o, val, 'serve')
5219 repo.ui.setconfig("web", o, val, 'serve')
5220
5220
5221 o = opts.get('web_conf') or opts.get('webdir_conf')
5221 o = opts.get('web_conf') or opts.get('webdir_conf')
5222 if not o:
5222 if not o:
5223 if not repo:
5223 if not repo:
5224 raise error.RepoError(_("there is no Mercurial repository"
5224 raise error.RepoError(_("there is no Mercurial repository"
5225 " here (.hg not found)"))
5225 " here (.hg not found)"))
5226 o = repo
5226 o = repo
5227
5227
5228 app = hgweb.hgweb(o, baseui=baseui)
5228 app = hgweb.hgweb(o, baseui=baseui)
5229 service = httpservice(ui, app, opts)
5229 service = httpservice(ui, app, opts)
5230 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5230 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5231
5231
5232 class httpservice(object):
5232 class httpservice(object):
5233 def __init__(self, ui, app, opts):
5233 def __init__(self, ui, app, opts):
5234 self.ui = ui
5234 self.ui = ui
5235 self.app = app
5235 self.app = app
5236 self.opts = opts
5236 self.opts = opts
5237
5237
5238 def init(self):
5238 def init(self):
5239 util.setsignalhandler()
5239 util.setsignalhandler()
5240 self.httpd = hgweb_server.create_server(self.ui, self.app)
5240 self.httpd = hgweb_server.create_server(self.ui, self.app)
5241
5241
5242 if self.opts['port'] and not self.ui.verbose:
5242 if self.opts['port'] and not self.ui.verbose:
5243 return
5243 return
5244
5244
5245 if self.httpd.prefix:
5245 if self.httpd.prefix:
5246 prefix = self.httpd.prefix.strip('/') + '/'
5246 prefix = self.httpd.prefix.strip('/') + '/'
5247 else:
5247 else:
5248 prefix = ''
5248 prefix = ''
5249
5249
5250 port = ':%d' % self.httpd.port
5250 port = ':%d' % self.httpd.port
5251 if port == ':80':
5251 if port == ':80':
5252 port = ''
5252 port = ''
5253
5253
5254 bindaddr = self.httpd.addr
5254 bindaddr = self.httpd.addr
5255 if bindaddr == '0.0.0.0':
5255 if bindaddr == '0.0.0.0':
5256 bindaddr = '*'
5256 bindaddr = '*'
5257 elif ':' in bindaddr: # IPv6
5257 elif ':' in bindaddr: # IPv6
5258 bindaddr = '[%s]' % bindaddr
5258 bindaddr = '[%s]' % bindaddr
5259
5259
5260 fqaddr = self.httpd.fqaddr
5260 fqaddr = self.httpd.fqaddr
5261 if ':' in fqaddr:
5261 if ':' in fqaddr:
5262 fqaddr = '[%s]' % fqaddr
5262 fqaddr = '[%s]' % fqaddr
5263 if self.opts['port']:
5263 if self.opts['port']:
5264 write = self.ui.status
5264 write = self.ui.status
5265 else:
5265 else:
5266 write = self.ui.write
5266 write = self.ui.write
5267 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5267 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5268 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5268 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5269
5269
5270 def run(self):
5270 def run(self):
5271 self.httpd.serve_forever()
5271 self.httpd.serve_forever()
5272
5272
5273
5273
5274 @command('^status|st',
5274 @command('^status|st',
5275 [('A', 'all', None, _('show status of all files')),
5275 [('A', 'all', None, _('show status of all files')),
5276 ('m', 'modified', None, _('show only modified files')),
5276 ('m', 'modified', None, _('show only modified files')),
5277 ('a', 'added', None, _('show only added files')),
5277 ('a', 'added', None, _('show only added files')),
5278 ('r', 'removed', None, _('show only removed files')),
5278 ('r', 'removed', None, _('show only removed files')),
5279 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5279 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5280 ('c', 'clean', None, _('show only files without changes')),
5280 ('c', 'clean', None, _('show only files without changes')),
5281 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5281 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5282 ('i', 'ignored', None, _('show only ignored files')),
5282 ('i', 'ignored', None, _('show only ignored files')),
5283 ('n', 'no-status', None, _('hide status prefix')),
5283 ('n', 'no-status', None, _('hide status prefix')),
5284 ('C', 'copies', None, _('show source of copied files')),
5284 ('C', 'copies', None, _('show source of copied files')),
5285 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5285 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5286 ('', 'rev', [], _('show difference from revision'), _('REV')),
5286 ('', 'rev', [], _('show difference from revision'), _('REV')),
5287 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5287 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5288 ] + walkopts + subrepoopts,
5288 ] + walkopts + subrepoopts,
5289 _('[OPTION]... [FILE]...'))
5289 _('[OPTION]... [FILE]...'))
5290 def status(ui, repo, *pats, **opts):
5290 def status(ui, repo, *pats, **opts):
5291 """show changed files in the working directory
5291 """show changed files in the working directory
5292
5292
5293 Show status of files in the repository. If names are given, only
5293 Show status of files in the repository. If names are given, only
5294 files that match are shown. Files that are clean or ignored or
5294 files that match are shown. Files that are clean or ignored or
5295 the source of a copy/move operation, are not listed unless
5295 the source of a copy/move operation, are not listed unless
5296 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5296 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5297 Unless options described with "show only ..." are given, the
5297 Unless options described with "show only ..." are given, the
5298 options -mardu are used.
5298 options -mardu are used.
5299
5299
5300 Option -q/--quiet hides untracked (unknown and ignored) files
5300 Option -q/--quiet hides untracked (unknown and ignored) files
5301 unless explicitly requested with -u/--unknown or -i/--ignored.
5301 unless explicitly requested with -u/--unknown or -i/--ignored.
5302
5302
5303 .. note::
5303 .. note::
5304
5304
5305 status may appear to disagree with diff if permissions have
5305 status may appear to disagree with diff if permissions have
5306 changed or a merge has occurred. The standard diff format does
5306 changed or a merge has occurred. The standard diff format does
5307 not report permission changes and diff only reports changes
5307 not report permission changes and diff only reports changes
5308 relative to one merge parent.
5308 relative to one merge parent.
5309
5309
5310 If one revision is given, it is used as the base revision.
5310 If one revision is given, it is used as the base revision.
5311 If two revisions are given, the differences between them are
5311 If two revisions are given, the differences between them are
5312 shown. The --change option can also be used as a shortcut to list
5312 shown. The --change option can also be used as a shortcut to list
5313 the changed files of a revision from its first parent.
5313 the changed files of a revision from its first parent.
5314
5314
5315 The codes used to show the status of files are::
5315 The codes used to show the status of files are::
5316
5316
5317 M = modified
5317 M = modified
5318 A = added
5318 A = added
5319 R = removed
5319 R = removed
5320 C = clean
5320 C = clean
5321 ! = missing (deleted by non-hg command, but still tracked)
5321 ! = missing (deleted by non-hg command, but still tracked)
5322 ? = not tracked
5322 ? = not tracked
5323 I = ignored
5323 I = ignored
5324 = origin of the previous file (with --copies)
5324 = origin of the previous file (with --copies)
5325
5325
5326 .. container:: verbose
5326 .. container:: verbose
5327
5327
5328 Examples:
5328 Examples:
5329
5329
5330 - show changes in the working directory relative to a
5330 - show changes in the working directory relative to a
5331 changeset::
5331 changeset::
5332
5332
5333 hg status --rev 9353
5333 hg status --rev 9353
5334
5334
5335 - show all changes including copies in an existing changeset::
5335 - show all changes including copies in an existing changeset::
5336
5336
5337 hg status --copies --change 9353
5337 hg status --copies --change 9353
5338
5338
5339 - get a NUL separated list of added files, suitable for xargs::
5339 - get a NUL separated list of added files, suitable for xargs::
5340
5340
5341 hg status -an0
5341 hg status -an0
5342
5342
5343 Returns 0 on success.
5343 Returns 0 on success.
5344 """
5344 """
5345
5345
5346 revs = opts.get('rev')
5346 revs = opts.get('rev')
5347 change = opts.get('change')
5347 change = opts.get('change')
5348
5348
5349 if revs and change:
5349 if revs and change:
5350 msg = _('cannot specify --rev and --change at the same time')
5350 msg = _('cannot specify --rev and --change at the same time')
5351 raise util.Abort(msg)
5351 raise util.Abort(msg)
5352 elif change:
5352 elif change:
5353 node2 = scmutil.revsingle(repo, change, None).node()
5353 node2 = scmutil.revsingle(repo, change, None).node()
5354 node1 = repo[node2].p1().node()
5354 node1 = repo[node2].p1().node()
5355 else:
5355 else:
5356 node1, node2 = scmutil.revpair(repo, revs)
5356 node1, node2 = scmutil.revpair(repo, revs)
5357
5357
5358 cwd = (pats and repo.getcwd()) or ''
5358 cwd = (pats and repo.getcwd()) or ''
5359 end = opts.get('print0') and '\0' or '\n'
5359 end = opts.get('print0') and '\0' or '\n'
5360 copy = {}
5360 copy = {}
5361 states = 'modified added removed deleted unknown ignored clean'.split()
5361 states = 'modified added removed deleted unknown ignored clean'.split()
5362 show = [k for k in states if opts.get(k)]
5362 show = [k for k in states if opts.get(k)]
5363 if opts.get('all'):
5363 if opts.get('all'):
5364 show += ui.quiet and (states[:4] + ['clean']) or states
5364 show += ui.quiet and (states[:4] + ['clean']) or states
5365 if not show:
5365 if not show:
5366 show = ui.quiet and states[:4] or states[:5]
5366 show = ui.quiet and states[:4] or states[:5]
5367
5367
5368 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5368 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5369 'ignored' in show, 'clean' in show, 'unknown' in show,
5369 'ignored' in show, 'clean' in show, 'unknown' in show,
5370 opts.get('subrepos'))
5370 opts.get('subrepos'))
5371 changestates = zip(states, 'MAR!?IC', stat)
5371 changestates = zip(states, 'MAR!?IC', stat)
5372
5372
5373 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5373 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5374 copy = copies.pathcopies(repo[node1], repo[node2])
5374 copy = copies.pathcopies(repo[node1], repo[node2])
5375
5375
5376 fm = ui.formatter('status', opts)
5376 fm = ui.formatter('status', opts)
5377 fmt = '%s' + end
5377 fmt = '%s' + end
5378 showchar = not opts.get('no_status')
5378 showchar = not opts.get('no_status')
5379
5379
5380 for state, char, files in changestates:
5380 for state, char, files in changestates:
5381 if state in show:
5381 if state in show:
5382 label = 'status.' + state
5382 label = 'status.' + state
5383 for f in files:
5383 for f in files:
5384 fm.startitem()
5384 fm.startitem()
5385 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5385 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5386 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5386 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5387 if f in copy:
5387 if f in copy:
5388 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5388 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5389 label='status.copied')
5389 label='status.copied')
5390 fm.end()
5390 fm.end()
5391
5391
5392 @command('^summary|sum',
5392 @command('^summary|sum',
5393 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5393 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5394 def summary(ui, repo, **opts):
5394 def summary(ui, repo, **opts):
5395 """summarize working directory state
5395 """summarize working directory state
5396
5396
5397 This generates a brief summary of the working directory state,
5397 This generates a brief summary of the working directory state,
5398 including parents, branch, commit status, and available updates.
5398 including parents, branch, commit status, and available updates.
5399
5399
5400 With the --remote option, this will check the default paths for
5400 With the --remote option, this will check the default paths for
5401 incoming and outgoing changes. This can be time-consuming.
5401 incoming and outgoing changes. This can be time-consuming.
5402
5402
5403 Returns 0 on success.
5403 Returns 0 on success.
5404 """
5404 """
5405
5405
5406 ctx = repo[None]
5406 ctx = repo[None]
5407 parents = ctx.parents()
5407 parents = ctx.parents()
5408 pnode = parents[0].node()
5408 pnode = parents[0].node()
5409 marks = []
5409 marks = []
5410
5410
5411 for p in parents:
5411 for p in parents:
5412 # label with log.changeset (instead of log.parent) since this
5412 # label with log.changeset (instead of log.parent) since this
5413 # shows a working directory parent *changeset*:
5413 # shows a working directory parent *changeset*:
5414 # i18n: column positioning for "hg summary"
5414 # i18n: column positioning for "hg summary"
5415 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5415 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5416 label='log.changeset changeset.%s' % p.phasestr())
5416 label='log.changeset changeset.%s' % p.phasestr())
5417 ui.write(' '.join(p.tags()), label='log.tag')
5417 ui.write(' '.join(p.tags()), label='log.tag')
5418 if p.bookmarks():
5418 if p.bookmarks():
5419 marks.extend(p.bookmarks())
5419 marks.extend(p.bookmarks())
5420 if p.rev() == -1:
5420 if p.rev() == -1:
5421 if not len(repo):
5421 if not len(repo):
5422 ui.write(_(' (empty repository)'))
5422 ui.write(_(' (empty repository)'))
5423 else:
5423 else:
5424 ui.write(_(' (no revision checked out)'))
5424 ui.write(_(' (no revision checked out)'))
5425 ui.write('\n')
5425 ui.write('\n')
5426 if p.description():
5426 if p.description():
5427 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5427 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5428 label='log.summary')
5428 label='log.summary')
5429
5429
5430 branch = ctx.branch()
5430 branch = ctx.branch()
5431 bheads = repo.branchheads(branch)
5431 bheads = repo.branchheads(branch)
5432 # i18n: column positioning for "hg summary"
5432 # i18n: column positioning for "hg summary"
5433 m = _('branch: %s\n') % branch
5433 m = _('branch: %s\n') % branch
5434 if branch != 'default':
5434 if branch != 'default':
5435 ui.write(m, label='log.branch')
5435 ui.write(m, label='log.branch')
5436 else:
5436 else:
5437 ui.status(m, label='log.branch')
5437 ui.status(m, label='log.branch')
5438
5438
5439 if marks:
5439 if marks:
5440 current = repo._bookmarkcurrent
5440 current = repo._bookmarkcurrent
5441 # i18n: column positioning for "hg summary"
5441 # i18n: column positioning for "hg summary"
5442 ui.write(_('bookmarks:'), label='log.bookmark')
5442 ui.write(_('bookmarks:'), label='log.bookmark')
5443 if current is not None:
5443 if current is not None:
5444 if current in marks:
5444 if current in marks:
5445 ui.write(' *' + current, label='bookmarks.current')
5445 ui.write(' *' + current, label='bookmarks.current')
5446 marks.remove(current)
5446 marks.remove(current)
5447 else:
5447 else:
5448 ui.write(' [%s]' % current, label='bookmarks.current')
5448 ui.write(' [%s]' % current, label='bookmarks.current')
5449 for m in marks:
5449 for m in marks:
5450 ui.write(' ' + m, label='log.bookmark')
5450 ui.write(' ' + m, label='log.bookmark')
5451 ui.write('\n', label='log.bookmark')
5451 ui.write('\n', label='log.bookmark')
5452
5452
5453 st = list(repo.status(unknown=True))[:6]
5453 st = list(repo.status(unknown=True))[:6]
5454
5454
5455 c = repo.dirstate.copies()
5455 c = repo.dirstate.copies()
5456 copied, renamed = [], []
5456 copied, renamed = [], []
5457 for d, s in c.iteritems():
5457 for d, s in c.iteritems():
5458 if s in st[2]:
5458 if s in st[2]:
5459 st[2].remove(s)
5459 st[2].remove(s)
5460 renamed.append(d)
5460 renamed.append(d)
5461 else:
5461 else:
5462 copied.append(d)
5462 copied.append(d)
5463 if d in st[1]:
5463 if d in st[1]:
5464 st[1].remove(d)
5464 st[1].remove(d)
5465 st.insert(3, renamed)
5465 st.insert(3, renamed)
5466 st.insert(4, copied)
5466 st.insert(4, copied)
5467
5467
5468 ms = mergemod.mergestate(repo)
5468 ms = mergemod.mergestate(repo)
5469 st.append([f for f in ms if ms[f] == 'u'])
5469 st.append([f for f in ms if ms[f] == 'u'])
5470
5470
5471 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5471 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5472 st.append(subs)
5472 st.append(subs)
5473
5473
5474 labels = [ui.label(_('%d modified'), 'status.modified'),
5474 labels = [ui.label(_('%d modified'), 'status.modified'),
5475 ui.label(_('%d added'), 'status.added'),
5475 ui.label(_('%d added'), 'status.added'),
5476 ui.label(_('%d removed'), 'status.removed'),
5476 ui.label(_('%d removed'), 'status.removed'),
5477 ui.label(_('%d renamed'), 'status.copied'),
5477 ui.label(_('%d renamed'), 'status.copied'),
5478 ui.label(_('%d copied'), 'status.copied'),
5478 ui.label(_('%d copied'), 'status.copied'),
5479 ui.label(_('%d deleted'), 'status.deleted'),
5479 ui.label(_('%d deleted'), 'status.deleted'),
5480 ui.label(_('%d unknown'), 'status.unknown'),
5480 ui.label(_('%d unknown'), 'status.unknown'),
5481 ui.label(_('%d ignored'), 'status.ignored'),
5481 ui.label(_('%d ignored'), 'status.ignored'),
5482 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5482 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5483 ui.label(_('%d subrepos'), 'status.modified')]
5483 ui.label(_('%d subrepos'), 'status.modified')]
5484 t = []
5484 t = []
5485 for s, l in zip(st, labels):
5485 for s, l in zip(st, labels):
5486 if s:
5486 if s:
5487 t.append(l % len(s))
5487 t.append(l % len(s))
5488
5488
5489 t = ', '.join(t)
5489 t = ', '.join(t)
5490 cleanworkdir = False
5490 cleanworkdir = False
5491
5491
5492 if repo.vfs.exists('updatestate'):
5492 if repo.vfs.exists('updatestate'):
5493 t += _(' (interrupted update)')
5493 t += _(' (interrupted update)')
5494 elif len(parents) > 1:
5494 elif len(parents) > 1:
5495 t += _(' (merge)')
5495 t += _(' (merge)')
5496 elif branch != parents[0].branch():
5496 elif branch != parents[0].branch():
5497 t += _(' (new branch)')
5497 t += _(' (new branch)')
5498 elif (parents[0].closesbranch() and
5498 elif (parents[0].closesbranch() and
5499 pnode in repo.branchheads(branch, closed=True)):
5499 pnode in repo.branchheads(branch, closed=True)):
5500 t += _(' (head closed)')
5500 t += _(' (head closed)')
5501 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5501 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5502 t += _(' (clean)')
5502 t += _(' (clean)')
5503 cleanworkdir = True
5503 cleanworkdir = True
5504 elif pnode not in bheads:
5504 elif pnode not in bheads:
5505 t += _(' (new branch head)')
5505 t += _(' (new branch head)')
5506
5506
5507 if cleanworkdir:
5507 if cleanworkdir:
5508 # i18n: column positioning for "hg summary"
5508 # i18n: column positioning for "hg summary"
5509 ui.status(_('commit: %s\n') % t.strip())
5509 ui.status(_('commit: %s\n') % t.strip())
5510 else:
5510 else:
5511 # i18n: column positioning for "hg summary"
5511 # i18n: column positioning for "hg summary"
5512 ui.write(_('commit: %s\n') % t.strip())
5512 ui.write(_('commit: %s\n') % t.strip())
5513
5513
5514 # all ancestors of branch heads - all ancestors of parent = new csets
5514 # all ancestors of branch heads - all ancestors of parent = new csets
5515 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5515 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5516 bheads))
5516 bheads))
5517
5517
5518 if new == 0:
5518 if new == 0:
5519 # i18n: column positioning for "hg summary"
5519 # i18n: column positioning for "hg summary"
5520 ui.status(_('update: (current)\n'))
5520 ui.status(_('update: (current)\n'))
5521 elif pnode not in bheads:
5521 elif pnode not in bheads:
5522 # i18n: column positioning for "hg summary"
5522 # i18n: column positioning for "hg summary"
5523 ui.write(_('update: %d new changesets (update)\n') % new)
5523 ui.write(_('update: %d new changesets (update)\n') % new)
5524 else:
5524 else:
5525 # i18n: column positioning for "hg summary"
5525 # i18n: column positioning for "hg summary"
5526 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5526 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5527 (new, len(bheads)))
5527 (new, len(bheads)))
5528
5528
5529 cmdutil.summaryhooks(ui, repo)
5529 cmdutil.summaryhooks(ui, repo)
5530
5530
5531 if opts.get('remote'):
5531 if opts.get('remote'):
5532 needsincoming, needsoutgoing = True, True
5532 needsincoming, needsoutgoing = True, True
5533 else:
5533 else:
5534 needsincoming, needsoutgoing = False, False
5534 needsincoming, needsoutgoing = False, False
5535 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5535 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5536 if i:
5536 if i:
5537 needsincoming = True
5537 needsincoming = True
5538 if o:
5538 if o:
5539 needsoutgoing = True
5539 needsoutgoing = True
5540 if not needsincoming and not needsoutgoing:
5540 if not needsincoming and not needsoutgoing:
5541 return
5541 return
5542
5542
5543 def getincoming():
5543 def getincoming():
5544 source, branches = hg.parseurl(ui.expandpath('default'))
5544 source, branches = hg.parseurl(ui.expandpath('default'))
5545 sbranch = branches[0]
5545 sbranch = branches[0]
5546 try:
5546 try:
5547 other = hg.peer(repo, {}, source)
5547 other = hg.peer(repo, {}, source)
5548 except error.RepoError:
5548 except error.RepoError:
5549 if opts.get('remote'):
5549 if opts.get('remote'):
5550 raise
5550 raise
5551 return source, sbranch, None, None, None
5551 return source, sbranch, None, None, None
5552 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5552 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5553 if revs:
5553 if revs:
5554 revs = [other.lookup(rev) for rev in revs]
5554 revs = [other.lookup(rev) for rev in revs]
5555 ui.debug('comparing with %s\n' % util.hidepassword(source))
5555 ui.debug('comparing with %s\n' % util.hidepassword(source))
5556 repo.ui.pushbuffer()
5556 repo.ui.pushbuffer()
5557 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5557 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5558 repo.ui.popbuffer()
5558 repo.ui.popbuffer()
5559 return source, sbranch, other, commoninc, commoninc[1]
5559 return source, sbranch, other, commoninc, commoninc[1]
5560
5560
5561 if needsincoming:
5561 if needsincoming:
5562 source, sbranch, sother, commoninc, incoming = getincoming()
5562 source, sbranch, sother, commoninc, incoming = getincoming()
5563 else:
5563 else:
5564 source = sbranch = sother = commoninc = incoming = None
5564 source = sbranch = sother = commoninc = incoming = None
5565
5565
5566 def getoutgoing():
5566 def getoutgoing():
5567 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5567 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5568 dbranch = branches[0]
5568 dbranch = branches[0]
5569 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5569 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5570 if source != dest:
5570 if source != dest:
5571 try:
5571 try:
5572 dother = hg.peer(repo, {}, dest)
5572 dother = hg.peer(repo, {}, dest)
5573 except error.RepoError:
5573 except error.RepoError:
5574 if opts.get('remote'):
5574 if opts.get('remote'):
5575 raise
5575 raise
5576 return dest, dbranch, None, None
5576 return dest, dbranch, None, None
5577 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5577 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5578 elif sother is None:
5578 elif sother is None:
5579 # there is no explicit destination peer, but source one is invalid
5579 # there is no explicit destination peer, but source one is invalid
5580 return dest, dbranch, None, None
5580 return dest, dbranch, None, None
5581 else:
5581 else:
5582 dother = sother
5582 dother = sother
5583 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5583 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5584 common = None
5584 common = None
5585 else:
5585 else:
5586 common = commoninc
5586 common = commoninc
5587 if revs:
5587 if revs:
5588 revs = [repo.lookup(rev) for rev in revs]
5588 revs = [repo.lookup(rev) for rev in revs]
5589 repo.ui.pushbuffer()
5589 repo.ui.pushbuffer()
5590 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5590 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5591 commoninc=common)
5591 commoninc=common)
5592 repo.ui.popbuffer()
5592 repo.ui.popbuffer()
5593 return dest, dbranch, dother, outgoing
5593 return dest, dbranch, dother, outgoing
5594
5594
5595 if needsoutgoing:
5595 if needsoutgoing:
5596 dest, dbranch, dother, outgoing = getoutgoing()
5596 dest, dbranch, dother, outgoing = getoutgoing()
5597 else:
5597 else:
5598 dest = dbranch = dother = outgoing = None
5598 dest = dbranch = dother = outgoing = None
5599
5599
5600 if opts.get('remote'):
5600 if opts.get('remote'):
5601 t = []
5601 t = []
5602 if incoming:
5602 if incoming:
5603 t.append(_('1 or more incoming'))
5603 t.append(_('1 or more incoming'))
5604 o = outgoing.missing
5604 o = outgoing.missing
5605 if o:
5605 if o:
5606 t.append(_('%d outgoing') % len(o))
5606 t.append(_('%d outgoing') % len(o))
5607 other = dother or sother
5607 other = dother or sother
5608 if 'bookmarks' in other.listkeys('namespaces'):
5608 if 'bookmarks' in other.listkeys('namespaces'):
5609 lmarks = repo.listkeys('bookmarks')
5609 lmarks = repo.listkeys('bookmarks')
5610 rmarks = other.listkeys('bookmarks')
5610 rmarks = other.listkeys('bookmarks')
5611 diff = set(rmarks) - set(lmarks)
5611 diff = set(rmarks) - set(lmarks)
5612 if len(diff) > 0:
5612 if len(diff) > 0:
5613 t.append(_('%d incoming bookmarks') % len(diff))
5613 t.append(_('%d incoming bookmarks') % len(diff))
5614 diff = set(lmarks) - set(rmarks)
5614 diff = set(lmarks) - set(rmarks)
5615 if len(diff) > 0:
5615 if len(diff) > 0:
5616 t.append(_('%d outgoing bookmarks') % len(diff))
5616 t.append(_('%d outgoing bookmarks') % len(diff))
5617
5617
5618 if t:
5618 if t:
5619 # i18n: column positioning for "hg summary"
5619 # i18n: column positioning for "hg summary"
5620 ui.write(_('remote: %s\n') % (', '.join(t)))
5620 ui.write(_('remote: %s\n') % (', '.join(t)))
5621 else:
5621 else:
5622 # i18n: column positioning for "hg summary"
5622 # i18n: column positioning for "hg summary"
5623 ui.status(_('remote: (synced)\n'))
5623 ui.status(_('remote: (synced)\n'))
5624
5624
5625 cmdutil.summaryremotehooks(ui, repo, opts,
5625 cmdutil.summaryremotehooks(ui, repo, opts,
5626 ((source, sbranch, sother, commoninc),
5626 ((source, sbranch, sother, commoninc),
5627 (dest, dbranch, dother, outgoing)))
5627 (dest, dbranch, dother, outgoing)))
5628
5628
5629 @command('tag',
5629 @command('tag',
5630 [('f', 'force', None, _('force tag')),
5630 [('f', 'force', None, _('force tag')),
5631 ('l', 'local', None, _('make the tag local')),
5631 ('l', 'local', None, _('make the tag local')),
5632 ('r', 'rev', '', _('revision to tag'), _('REV')),
5632 ('r', 'rev', '', _('revision to tag'), _('REV')),
5633 ('', 'remove', None, _('remove a tag')),
5633 ('', 'remove', None, _('remove a tag')),
5634 # -l/--local is already there, commitopts cannot be used
5634 # -l/--local is already there, commitopts cannot be used
5635 ('e', 'edit', None, _('edit commit message')),
5635 ('e', 'edit', None, _('edit commit message')),
5636 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5636 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5637 ] + commitopts2,
5637 ] + commitopts2,
5638 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5638 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5639 def tag(ui, repo, name1, *names, **opts):
5639 def tag(ui, repo, name1, *names, **opts):
5640 """add one or more tags for the current or given revision
5640 """add one or more tags for the current or given revision
5641
5641
5642 Name a particular revision using <name>.
5642 Name a particular revision using <name>.
5643
5643
5644 Tags are used to name particular revisions of the repository and are
5644 Tags are used to name particular revisions of the repository and are
5645 very useful to compare different revisions, to go back to significant
5645 very useful to compare different revisions, to go back to significant
5646 earlier versions or to mark branch points as releases, etc. Changing
5646 earlier versions or to mark branch points as releases, etc. Changing
5647 an existing tag is normally disallowed; use -f/--force to override.
5647 an existing tag is normally disallowed; use -f/--force to override.
5648
5648
5649 If no revision is given, the parent of the working directory is
5649 If no revision is given, the parent of the working directory is
5650 used.
5650 used.
5651
5651
5652 To facilitate version control, distribution, and merging of tags,
5652 To facilitate version control, distribution, and merging of tags,
5653 they are stored as a file named ".hgtags" which is managed similarly
5653 they are stored as a file named ".hgtags" which is managed similarly
5654 to other project files and can be hand-edited if necessary. This
5654 to other project files and can be hand-edited if necessary. This
5655 also means that tagging creates a new commit. The file
5655 also means that tagging creates a new commit. The file
5656 ".hg/localtags" is used for local tags (not shared among
5656 ".hg/localtags" is used for local tags (not shared among
5657 repositories).
5657 repositories).
5658
5658
5659 Tag commits are usually made at the head of a branch. If the parent
5659 Tag commits are usually made at the head of a branch. If the parent
5660 of the working directory is not a branch head, :hg:`tag` aborts; use
5660 of the working directory is not a branch head, :hg:`tag` aborts; use
5661 -f/--force to force the tag commit to be based on a non-head
5661 -f/--force to force the tag commit to be based on a non-head
5662 changeset.
5662 changeset.
5663
5663
5664 See :hg:`help dates` for a list of formats valid for -d/--date.
5664 See :hg:`help dates` for a list of formats valid for -d/--date.
5665
5665
5666 Since tag names have priority over branch names during revision
5666 Since tag names have priority over branch names during revision
5667 lookup, using an existing branch name as a tag name is discouraged.
5667 lookup, using an existing branch name as a tag name is discouraged.
5668
5668
5669 Returns 0 on success.
5669 Returns 0 on success.
5670 """
5670 """
5671 wlock = lock = None
5671 wlock = lock = None
5672 try:
5672 try:
5673 wlock = repo.wlock()
5673 wlock = repo.wlock()
5674 lock = repo.lock()
5674 lock = repo.lock()
5675 rev_ = "."
5675 rev_ = "."
5676 names = [t.strip() for t in (name1,) + names]
5676 names = [t.strip() for t in (name1,) + names]
5677 if len(names) != len(set(names)):
5677 if len(names) != len(set(names)):
5678 raise util.Abort(_('tag names must be unique'))
5678 raise util.Abort(_('tag names must be unique'))
5679 for n in names:
5679 for n in names:
5680 scmutil.checknewlabel(repo, n, 'tag')
5680 scmutil.checknewlabel(repo, n, 'tag')
5681 if not n:
5681 if not n:
5682 raise util.Abort(_('tag names cannot consist entirely of '
5682 raise util.Abort(_('tag names cannot consist entirely of '
5683 'whitespace'))
5683 'whitespace'))
5684 if opts.get('rev') and opts.get('remove'):
5684 if opts.get('rev') and opts.get('remove'):
5685 raise util.Abort(_("--rev and --remove are incompatible"))
5685 raise util.Abort(_("--rev and --remove are incompatible"))
5686 if opts.get('rev'):
5686 if opts.get('rev'):
5687 rev_ = opts['rev']
5687 rev_ = opts['rev']
5688 message = opts.get('message')
5688 message = opts.get('message')
5689 if opts.get('remove'):
5689 if opts.get('remove'):
5690 expectedtype = opts.get('local') and 'local' or 'global'
5690 expectedtype = opts.get('local') and 'local' or 'global'
5691 for n in names:
5691 for n in names:
5692 if not repo.tagtype(n):
5692 if not repo.tagtype(n):
5693 raise util.Abort(_("tag '%s' does not exist") % n)
5693 raise util.Abort(_("tag '%s' does not exist") % n)
5694 if repo.tagtype(n) != expectedtype:
5694 if repo.tagtype(n) != expectedtype:
5695 if expectedtype == 'global':
5695 if expectedtype == 'global':
5696 raise util.Abort(_("tag '%s' is not a global tag") % n)
5696 raise util.Abort(_("tag '%s' is not a global tag") % n)
5697 else:
5697 else:
5698 raise util.Abort(_("tag '%s' is not a local tag") % n)
5698 raise util.Abort(_("tag '%s' is not a local tag") % n)
5699 rev_ = nullid
5699 rev_ = nullid
5700 if not message:
5700 if not message:
5701 # we don't translate commit messages
5701 # we don't translate commit messages
5702 message = 'Removed tag %s' % ', '.join(names)
5702 message = 'Removed tag %s' % ', '.join(names)
5703 elif not opts.get('force'):
5703 elif not opts.get('force'):
5704 for n in names:
5704 for n in names:
5705 if n in repo.tags():
5705 if n in repo.tags():
5706 raise util.Abort(_("tag '%s' already exists "
5706 raise util.Abort(_("tag '%s' already exists "
5707 "(use -f to force)") % n)
5707 "(use -f to force)") % n)
5708 if not opts.get('local'):
5708 if not opts.get('local'):
5709 p1, p2 = repo.dirstate.parents()
5709 p1, p2 = repo.dirstate.parents()
5710 if p2 != nullid:
5710 if p2 != nullid:
5711 raise util.Abort(_('uncommitted merge'))
5711 raise util.Abort(_('uncommitted merge'))
5712 bheads = repo.branchheads()
5712 bheads = repo.branchheads()
5713 if not opts.get('force') and bheads and p1 not in bheads:
5713 if not opts.get('force') and bheads and p1 not in bheads:
5714 raise util.Abort(_('not at a branch head (use -f to force)'))
5714 raise util.Abort(_('not at a branch head (use -f to force)'))
5715 r = scmutil.revsingle(repo, rev_).node()
5715 r = scmutil.revsingle(repo, rev_).node()
5716
5716
5717 if not message:
5717 if not message:
5718 # we don't translate commit messages
5718 # we don't translate commit messages
5719 message = ('Added tag %s for changeset %s' %
5719 message = ('Added tag %s for changeset %s' %
5720 (', '.join(names), short(r)))
5720 (', '.join(names), short(r)))
5721
5721
5722 date = opts.get('date')
5722 date = opts.get('date')
5723 if date:
5723 if date:
5724 date = util.parsedate(date)
5724 date = util.parsedate(date)
5725
5725
5726 if opts.get('edit'):
5726 if opts.get('edit'):
5727 message = ui.edit(message, ui.username())
5727 message = ui.edit(message, ui.username())
5728 repo.savecommitmessage(message)
5728 repo.savecommitmessage(message)
5729
5729
5730 # don't allow tagging the null rev
5730 # don't allow tagging the null rev
5731 if (not opts.get('remove') and
5731 if (not opts.get('remove') and
5732 scmutil.revsingle(repo, rev_).rev() == nullrev):
5732 scmutil.revsingle(repo, rev_).rev() == nullrev):
5733 raise util.Abort(_("cannot tag null revision"))
5733 raise util.Abort(_("cannot tag null revision"))
5734
5734
5735 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5735 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5736 finally:
5736 finally:
5737 release(lock, wlock)
5737 release(lock, wlock)
5738
5738
5739 @command('tags', [], '')
5739 @command('tags', [], '')
5740 def tags(ui, repo, **opts):
5740 def tags(ui, repo, **opts):
5741 """list repository tags
5741 """list repository tags
5742
5742
5743 This lists both regular and local tags. When the -v/--verbose
5743 This lists both regular and local tags. When the -v/--verbose
5744 switch is used, a third column "local" is printed for local tags.
5744 switch is used, a third column "local" is printed for local tags.
5745
5745
5746 Returns 0 on success.
5746 Returns 0 on success.
5747 """
5747 """
5748
5748
5749 fm = ui.formatter('tags', opts)
5749 fm = ui.formatter('tags', opts)
5750 hexfunc = ui.debugflag and hex or short
5750 hexfunc = ui.debugflag and hex or short
5751 tagtype = ""
5751 tagtype = ""
5752
5752
5753 for t, n in reversed(repo.tagslist()):
5753 for t, n in reversed(repo.tagslist()):
5754 hn = hexfunc(n)
5754 hn = hexfunc(n)
5755 label = 'tags.normal'
5755 label = 'tags.normal'
5756 tagtype = ''
5756 tagtype = ''
5757 if repo.tagtype(t) == 'local':
5757 if repo.tagtype(t) == 'local':
5758 label = 'tags.local'
5758 label = 'tags.local'
5759 tagtype = 'local'
5759 tagtype = 'local'
5760
5760
5761 fm.startitem()
5761 fm.startitem()
5762 fm.write('tag', '%s', t, label=label)
5762 fm.write('tag', '%s', t, label=label)
5763 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5763 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5764 fm.condwrite(not ui.quiet, 'rev id', fmt,
5764 fm.condwrite(not ui.quiet, 'rev id', fmt,
5765 repo.changelog.rev(n), hn, label=label)
5765 repo.changelog.rev(n), hn, label=label)
5766 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5766 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5767 tagtype, label=label)
5767 tagtype, label=label)
5768 fm.plain('\n')
5768 fm.plain('\n')
5769 fm.end()
5769 fm.end()
5770
5770
5771 @command('tip',
5771 @command('tip',
5772 [('p', 'patch', None, _('show patch')),
5772 [('p', 'patch', None, _('show patch')),
5773 ('g', 'git', None, _('use git extended diff format')),
5773 ('g', 'git', None, _('use git extended diff format')),
5774 ] + templateopts,
5774 ] + templateopts,
5775 _('[-p] [-g]'))
5775 _('[-p] [-g]'))
5776 def tip(ui, repo, **opts):
5776 def tip(ui, repo, **opts):
5777 """show the tip revision (DEPRECATED)
5777 """show the tip revision (DEPRECATED)
5778
5778
5779 The tip revision (usually just called the tip) is the changeset
5779 The tip revision (usually just called the tip) is the changeset
5780 most recently added to the repository (and therefore the most
5780 most recently added to the repository (and therefore the most
5781 recently changed head).
5781 recently changed head).
5782
5782
5783 If you have just made a commit, that commit will be the tip. If
5783 If you have just made a commit, that commit will be the tip. If
5784 you have just pulled changes from another repository, the tip of
5784 you have just pulled changes from another repository, the tip of
5785 that repository becomes the current tip. The "tip" tag is special
5785 that repository becomes the current tip. The "tip" tag is special
5786 and cannot be renamed or assigned to a different changeset.
5786 and cannot be renamed or assigned to a different changeset.
5787
5787
5788 This command is deprecated, please use :hg:`heads` instead.
5788 This command is deprecated, please use :hg:`heads` instead.
5789
5789
5790 Returns 0 on success.
5790 Returns 0 on success.
5791 """
5791 """
5792 displayer = cmdutil.show_changeset(ui, repo, opts)
5792 displayer = cmdutil.show_changeset(ui, repo, opts)
5793 displayer.show(repo['tip'])
5793 displayer.show(repo['tip'])
5794 displayer.close()
5794 displayer.close()
5795
5795
5796 @command('unbundle',
5796 @command('unbundle',
5797 [('u', 'update', None,
5797 [('u', 'update', None,
5798 _('update to new branch head if changesets were unbundled'))],
5798 _('update to new branch head if changesets were unbundled'))],
5799 _('[-u] FILE...'))
5799 _('[-u] FILE...'))
5800 def unbundle(ui, repo, fname1, *fnames, **opts):
5800 def unbundle(ui, repo, fname1, *fnames, **opts):
5801 """apply one or more changegroup files
5801 """apply one or more changegroup files
5802
5802
5803 Apply one or more compressed changegroup files generated by the
5803 Apply one or more compressed changegroup files generated by the
5804 bundle command.
5804 bundle command.
5805
5805
5806 Returns 0 on success, 1 if an update has unresolved files.
5806 Returns 0 on success, 1 if an update has unresolved files.
5807 """
5807 """
5808 fnames = (fname1,) + fnames
5808 fnames = (fname1,) + fnames
5809
5809
5810 lock = repo.lock()
5810 lock = repo.lock()
5811 wc = repo['.']
5811 wc = repo['.']
5812 try:
5812 try:
5813 for fname in fnames:
5813 for fname in fnames:
5814 f = hg.openpath(ui, fname)
5814 f = hg.openpath(ui, fname)
5815 gen = exchange.readbundle(ui, f, fname)
5815 gen = exchange.readbundle(ui, f, fname)
5816 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5816 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5817 'bundle:' + fname)
5817 'bundle:' + fname)
5818 finally:
5818 finally:
5819 lock.release()
5819 lock.release()
5820 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5820 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5821 return postincoming(ui, repo, modheads, opts.get('update'), None)
5821 return postincoming(ui, repo, modheads, opts.get('update'), None)
5822
5822
5823 @command('^update|up|checkout|co',
5823 @command('^update|up|checkout|co',
5824 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5824 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5825 ('c', 'check', None,
5825 ('c', 'check', None,
5826 _('update across branches if no uncommitted changes')),
5826 _('update across branches if no uncommitted changes')),
5827 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5827 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5828 ('r', 'rev', '', _('revision'), _('REV'))],
5828 ('r', 'rev', '', _('revision'), _('REV'))],
5829 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5829 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5830 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5830 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5831 """update working directory (or switch revisions)
5831 """update working directory (or switch revisions)
5832
5832
5833 Update the repository's working directory to the specified
5833 Update the repository's working directory to the specified
5834 changeset. If no changeset is specified, update to the tip of the
5834 changeset. If no changeset is specified, update to the tip of the
5835 current named branch and move the current bookmark (see :hg:`help
5835 current named branch and move the current bookmark (see :hg:`help
5836 bookmarks`).
5836 bookmarks`).
5837
5837
5838 Update sets the working directory's parent revision to the specified
5838 Update sets the working directory's parent revision to the specified
5839 changeset (see :hg:`help parents`).
5839 changeset (see :hg:`help parents`).
5840
5840
5841 If the changeset is not a descendant or ancestor of the working
5841 If the changeset is not a descendant or ancestor of the working
5842 directory's parent, the update is aborted. With the -c/--check
5842 directory's parent, the update is aborted. With the -c/--check
5843 option, the working directory is checked for uncommitted changes; if
5843 option, the working directory is checked for uncommitted changes; if
5844 none are found, the working directory is updated to the specified
5844 none are found, the working directory is updated to the specified
5845 changeset.
5845 changeset.
5846
5846
5847 .. container:: verbose
5847 .. container:: verbose
5848
5848
5849 The following rules apply when the working directory contains
5849 The following rules apply when the working directory contains
5850 uncommitted changes:
5850 uncommitted changes:
5851
5851
5852 1. If neither -c/--check nor -C/--clean is specified, and if
5852 1. If neither -c/--check nor -C/--clean is specified, and if
5853 the requested changeset is an ancestor or descendant of
5853 the requested changeset is an ancestor or descendant of
5854 the working directory's parent, the uncommitted changes
5854 the working directory's parent, the uncommitted changes
5855 are merged into the requested changeset and the merged
5855 are merged into the requested changeset and the merged
5856 result is left uncommitted. If the requested changeset is
5856 result is left uncommitted. If the requested changeset is
5857 not an ancestor or descendant (that is, it is on another
5857 not an ancestor or descendant (that is, it is on another
5858 branch), the update is aborted and the uncommitted changes
5858 branch), the update is aborted and the uncommitted changes
5859 are preserved.
5859 are preserved.
5860
5860
5861 2. With the -c/--check option, the update is aborted and the
5861 2. With the -c/--check option, the update is aborted and the
5862 uncommitted changes are preserved.
5862 uncommitted changes are preserved.
5863
5863
5864 3. With the -C/--clean option, uncommitted changes are discarded and
5864 3. With the -C/--clean option, uncommitted changes are discarded and
5865 the working directory is updated to the requested changeset.
5865 the working directory is updated to the requested changeset.
5866
5866
5867 To cancel an uncommitted merge (and lose your changes), use
5867 To cancel an uncommitted merge (and lose your changes), use
5868 :hg:`update --clean .`.
5868 :hg:`update --clean .`.
5869
5869
5870 Use null as the changeset to remove the working directory (like
5870 Use null as the changeset to remove the working directory (like
5871 :hg:`clone -U`).
5871 :hg:`clone -U`).
5872
5872
5873 If you want to revert just one file to an older revision, use
5873 If you want to revert just one file to an older revision, use
5874 :hg:`revert [-r REV] NAME`.
5874 :hg:`revert [-r REV] NAME`.
5875
5875
5876 See :hg:`help dates` for a list of formats valid for -d/--date.
5876 See :hg:`help dates` for a list of formats valid for -d/--date.
5877
5877
5878 Returns 0 on success, 1 if there are unresolved files.
5878 Returns 0 on success, 1 if there are unresolved files.
5879 """
5879 """
5880 if rev and node:
5880 if rev and node:
5881 raise util.Abort(_("please specify just one revision"))
5881 raise util.Abort(_("please specify just one revision"))
5882
5882
5883 if rev is None or rev == '':
5883 if rev is None or rev == '':
5884 rev = node
5884 rev = node
5885
5885
5886 cmdutil.clearunfinished(repo)
5886 cmdutil.clearunfinished(repo)
5887
5887
5888 # with no argument, we also move the current bookmark, if any
5888 # with no argument, we also move the current bookmark, if any
5889 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5889 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5890
5890
5891 # if we defined a bookmark, we have to remember the original bookmark name
5891 # if we defined a bookmark, we have to remember the original bookmark name
5892 brev = rev
5892 brev = rev
5893 rev = scmutil.revsingle(repo, rev, rev).rev()
5893 rev = scmutil.revsingle(repo, rev, rev).rev()
5894
5894
5895 if check and clean:
5895 if check and clean:
5896 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5896 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5897
5897
5898 if date:
5898 if date:
5899 if rev is not None:
5899 if rev is not None:
5900 raise util.Abort(_("you can't specify a revision and a date"))
5900 raise util.Abort(_("you can't specify a revision and a date"))
5901 rev = cmdutil.finddate(ui, repo, date)
5901 rev = cmdutil.finddate(ui, repo, date)
5902
5902
5903 if check:
5903 if check:
5904 c = repo[None]
5904 c = repo[None]
5905 if c.dirty(merge=False, branch=False, missing=True):
5905 if c.dirty(merge=False, branch=False, missing=True):
5906 raise util.Abort(_("uncommitted changes"))
5906 raise util.Abort(_("uncommitted changes"))
5907 if rev is None:
5907 if rev is None:
5908 rev = repo[repo[None].branch()].rev()
5908 rev = repo[repo[None].branch()].rev()
5909 mergemod._checkunknown(repo, repo[None], repo[rev])
5909 mergemod._checkunknown(repo, repo[None], repo[rev])
5910
5910
5911 if clean:
5911 if clean:
5912 ret = hg.clean(repo, rev)
5912 ret = hg.clean(repo, rev)
5913 else:
5913 else:
5914 ret = hg.update(repo, rev)
5914 ret = hg.update(repo, rev)
5915
5915
5916 if not ret and movemarkfrom:
5916 if not ret and movemarkfrom:
5917 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5917 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5918 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5918 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5919 elif brev in repo._bookmarks:
5919 elif brev in repo._bookmarks:
5920 bookmarks.setcurrent(repo, brev)
5920 bookmarks.setcurrent(repo, brev)
5921 elif brev:
5921 elif brev:
5922 bookmarks.unsetcurrent(repo)
5922 bookmarks.unsetcurrent(repo)
5923
5923
5924 return ret
5924 return ret
5925
5925
5926 @command('verify', [])
5926 @command('verify', [])
5927 def verify(ui, repo):
5927 def verify(ui, repo):
5928 """verify the integrity of the repository
5928 """verify the integrity of the repository
5929
5929
5930 Verify the integrity of the current repository.
5930 Verify the integrity of the current repository.
5931
5931
5932 This will perform an extensive check of the repository's
5932 This will perform an extensive check of the repository's
5933 integrity, validating the hashes and checksums of each entry in
5933 integrity, validating the hashes and checksums of each entry in
5934 the changelog, manifest, and tracked files, as well as the
5934 the changelog, manifest, and tracked files, as well as the
5935 integrity of their crosslinks and indices.
5935 integrity of their crosslinks and indices.
5936
5936
5937 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5937 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5938 for more information about recovery from corruption of the
5938 for more information about recovery from corruption of the
5939 repository.
5939 repository.
5940
5940
5941 Returns 0 on success, 1 if errors are encountered.
5941 Returns 0 on success, 1 if errors are encountered.
5942 """
5942 """
5943 return hg.verify(repo)
5943 return hg.verify(repo)
5944
5944
5945 @command('version', [])
5945 @command('version', [])
5946 def version_(ui):
5946 def version_(ui):
5947 """output version and copyright information"""
5947 """output version and copyright information"""
5948 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5948 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5949 % util.version())
5949 % util.version())
5950 ui.status(_(
5950 ui.status(_(
5951 "(see http://mercurial.selenic.com for more information)\n"
5951 "(see http://mercurial.selenic.com for more information)\n"
5952 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5952 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5953 "This is free software; see the source for copying conditions. "
5953 "This is free software; see the source for copying conditions. "
5954 "There is NO\nwarranty; "
5954 "There is NO\nwarranty; "
5955 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5955 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5956 ))
5956 ))
5957
5957
5958 norepo = ("clone init version help debugcommands debugcomplete"
5958 norepo = ("clone init version help debugcommands debugcomplete"
5959 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5959 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5960 " debugknown debuggetbundle debugbundle")
5960 " debugknown debuggetbundle debugbundle")
5961 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5961 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
5962 " debugdata debugindex debugindexdot debugrevlog")
5962 " debugdata debugindex debugindexdot debugrevlog")
5963 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5963 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5964 " remove resolve status debugwalk")
5964 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now