##// END OF EJS Templates
commands: define norepo in command decorator
Gregory Szorc -
r21768:16aeb28c default
parent child Browse files
Show More
@@ -1,5986 +1,5996 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 norepo = ("clone init version help debugcommands debugcomplete"
29 # Space delimited list of commands that don't require local repositories.
30 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
30 # This should be populated by passing norepo=True into the @command decorator.
31 " debugknown debuggetbundle debugbundle")
31 norepo = ''
32 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
32 optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
33 " debugdata debugindex debugindexdot debugrevlog")
33 " debugdata debugindex debugindexdot debugrevlog")
34 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
34 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
35 " remove resolve status debugwalk")
35 " remove resolve status debugwalk")
36 # common command options
36 # common command options
37
37
38 globalopts = [
38 globalopts = [
39 ('R', 'repository', '',
39 ('R', 'repository', '',
40 _('repository root directory or name of overlay bundle file'),
40 _('repository root directory or name of overlay bundle file'),
41 _('REPO')),
41 _('REPO')),
42 ('', 'cwd', '',
42 ('', 'cwd', '',
43 _('change working directory'), _('DIR')),
43 _('change working directory'), _('DIR')),
44 ('y', 'noninteractive', None,
44 ('y', 'noninteractive', None,
45 _('do not prompt, automatically pick the first choice for all prompts')),
45 _('do not prompt, automatically pick the first choice for all prompts')),
46 ('q', 'quiet', None, _('suppress output')),
46 ('q', 'quiet', None, _('suppress output')),
47 ('v', 'verbose', None, _('enable additional output')),
47 ('v', 'verbose', None, _('enable additional output')),
48 ('', 'config', [],
48 ('', 'config', [],
49 _('set/override config option (use \'section.name=value\')'),
49 _('set/override config option (use \'section.name=value\')'),
50 _('CONFIG')),
50 _('CONFIG')),
51 ('', 'debug', None, _('enable debugging output')),
51 ('', 'debug', None, _('enable debugging output')),
52 ('', 'debugger', None, _('start debugger')),
52 ('', 'debugger', None, _('start debugger')),
53 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
53 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
54 _('ENCODE')),
54 _('ENCODE')),
55 ('', 'encodingmode', encoding.encodingmode,
55 ('', 'encodingmode', encoding.encodingmode,
56 _('set the charset encoding mode'), _('MODE')),
56 _('set the charset encoding mode'), _('MODE')),
57 ('', 'traceback', None, _('always print a traceback on exception')),
57 ('', 'traceback', None, _('always print a traceback on exception')),
58 ('', 'time', None, _('time how long the command takes')),
58 ('', 'time', None, _('time how long the command takes')),
59 ('', 'profile', None, _('print command execution profile')),
59 ('', 'profile', None, _('print command execution profile')),
60 ('', 'version', None, _('output version information and exit')),
60 ('', 'version', None, _('output version information and exit')),
61 ('h', 'help', None, _('display help and exit')),
61 ('h', 'help', None, _('display help and exit')),
62 ('', 'hidden', False, _('consider hidden changesets')),
62 ('', 'hidden', False, _('consider hidden changesets')),
63 ]
63 ]
64
64
65 dryrunopts = [('n', 'dry-run', None,
65 dryrunopts = [('n', 'dry-run', None,
66 _('do not perform actions, just print output'))]
66 _('do not perform actions, just print output'))]
67
67
68 remoteopts = [
68 remoteopts = [
69 ('e', 'ssh', '',
69 ('e', 'ssh', '',
70 _('specify ssh command to use'), _('CMD')),
70 _('specify ssh command to use'), _('CMD')),
71 ('', 'remotecmd', '',
71 ('', 'remotecmd', '',
72 _('specify hg command to run on the remote side'), _('CMD')),
72 _('specify hg command to run on the remote side'), _('CMD')),
73 ('', 'insecure', None,
73 ('', 'insecure', None,
74 _('do not verify server certificate (ignoring web.cacerts config)')),
74 _('do not verify server certificate (ignoring web.cacerts config)')),
75 ]
75 ]
76
76
77 walkopts = [
77 walkopts = [
78 ('I', 'include', [],
78 ('I', 'include', [],
79 _('include names matching the given patterns'), _('PATTERN')),
79 _('include names matching the given patterns'), _('PATTERN')),
80 ('X', 'exclude', [],
80 ('X', 'exclude', [],
81 _('exclude names matching the given patterns'), _('PATTERN')),
81 _('exclude names matching the given patterns'), _('PATTERN')),
82 ]
82 ]
83
83
84 commitopts = [
84 commitopts = [
85 ('m', 'message', '',
85 ('m', 'message', '',
86 _('use text as commit message'), _('TEXT')),
86 _('use text as commit message'), _('TEXT')),
87 ('l', 'logfile', '',
87 ('l', 'logfile', '',
88 _('read commit message from file'), _('FILE')),
88 _('read commit message from file'), _('FILE')),
89 ]
89 ]
90
90
91 commitopts2 = [
91 commitopts2 = [
92 ('d', 'date', '',
92 ('d', 'date', '',
93 _('record the specified date as commit date'), _('DATE')),
93 _('record the specified date as commit date'), _('DATE')),
94 ('u', 'user', '',
94 ('u', 'user', '',
95 _('record the specified user as committer'), _('USER')),
95 _('record the specified user as committer'), _('USER')),
96 ]
96 ]
97
97
98 templateopts = [
98 templateopts = [
99 ('', 'style', '',
99 ('', 'style', '',
100 _('display using template map file (DEPRECATED)'), _('STYLE')),
100 _('display using template map file (DEPRECATED)'), _('STYLE')),
101 ('T', 'template', '',
101 ('T', 'template', '',
102 _('display with template'), _('TEMPLATE')),
102 _('display with template'), _('TEMPLATE')),
103 ]
103 ]
104
104
105 logopts = [
105 logopts = [
106 ('p', 'patch', None, _('show patch')),
106 ('p', 'patch', None, _('show patch')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('l', 'limit', '',
108 ('l', 'limit', '',
109 _('limit number of changes displayed'), _('NUM')),
109 _('limit number of changes displayed'), _('NUM')),
110 ('M', 'no-merges', None, _('do not show merges')),
110 ('M', 'no-merges', None, _('do not show merges')),
111 ('', 'stat', None, _('output diffstat-style summary of changes')),
111 ('', 'stat', None, _('output diffstat-style summary of changes')),
112 ('G', 'graph', None, _("show the revision DAG")),
112 ('G', 'graph', None, _("show the revision DAG")),
113 ] + templateopts
113 ] + templateopts
114
114
115 diffopts = [
115 diffopts = [
116 ('a', 'text', None, _('treat all files as text')),
116 ('a', 'text', None, _('treat all files as text')),
117 ('g', 'git', None, _('use git extended diff format')),
117 ('g', 'git', None, _('use git extended diff format')),
118 ('', 'nodates', None, _('omit dates from diff headers'))
118 ('', 'nodates', None, _('omit dates from diff headers'))
119 ]
119 ]
120
120
121 diffwsopts = [
121 diffwsopts = [
122 ('w', 'ignore-all-space', None,
122 ('w', 'ignore-all-space', None,
123 _('ignore white space when comparing lines')),
123 _('ignore white space when comparing lines')),
124 ('b', 'ignore-space-change', None,
124 ('b', 'ignore-space-change', None,
125 _('ignore changes in the amount of white space')),
125 _('ignore changes in the amount of white space')),
126 ('B', 'ignore-blank-lines', None,
126 ('B', 'ignore-blank-lines', None,
127 _('ignore changes whose lines are all blank')),
127 _('ignore changes whose lines are all blank')),
128 ]
128 ]
129
129
130 diffopts2 = [
130 diffopts2 = [
131 ('p', 'show-function', None, _('show which function each change is in')),
131 ('p', 'show-function', None, _('show which function each change is in')),
132 ('', 'reverse', None, _('produce a diff that undoes the changes')),
132 ('', 'reverse', None, _('produce a diff that undoes the changes')),
133 ] + diffwsopts + [
133 ] + diffwsopts + [
134 ('U', 'unified', '',
134 ('U', 'unified', '',
135 _('number of lines of context to show'), _('NUM')),
135 _('number of lines of context to show'), _('NUM')),
136 ('', 'stat', None, _('output diffstat-style summary of changes')),
136 ('', 'stat', None, _('output diffstat-style summary of changes')),
137 ]
137 ]
138
138
139 mergetoolopts = [
139 mergetoolopts = [
140 ('t', 'tool', '', _('specify merge tool')),
140 ('t', 'tool', '', _('specify merge tool')),
141 ]
141 ]
142
142
143 similarityopts = [
143 similarityopts = [
144 ('s', 'similarity', '',
144 ('s', 'similarity', '',
145 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
145 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
146 ]
146 ]
147
147
148 subrepoopts = [
148 subrepoopts = [
149 ('S', 'subrepos', None,
149 ('S', 'subrepos', None,
150 _('recurse into subrepositories'))
150 _('recurse into subrepositories'))
151 ]
151 ]
152
152
153 # Commands start here, listed alphabetically
153 # Commands start here, listed alphabetically
154
154
155 @command('^add',
155 @command('^add',
156 walkopts + subrepoopts + dryrunopts,
156 walkopts + subrepoopts + dryrunopts,
157 _('[OPTION]... [FILE]...'))
157 _('[OPTION]... [FILE]...'))
158 def add(ui, repo, *pats, **opts):
158 def add(ui, repo, *pats, **opts):
159 """add the specified files on the next commit
159 """add the specified files on the next commit
160
160
161 Schedule files to be version controlled and added to the
161 Schedule files to be version controlled and added to the
162 repository.
162 repository.
163
163
164 The files will be added to the repository at the next commit. To
164 The files will be added to the repository at the next commit. To
165 undo an add before that, see :hg:`forget`.
165 undo an add before that, see :hg:`forget`.
166
166
167 If no names are given, add all files to the repository.
167 If no names are given, add all files to the repository.
168
168
169 .. container:: verbose
169 .. container:: verbose
170
170
171 An example showing how new (unknown) files are added
171 An example showing how new (unknown) files are added
172 automatically by :hg:`add`::
172 automatically by :hg:`add`::
173
173
174 $ ls
174 $ ls
175 foo.c
175 foo.c
176 $ hg status
176 $ hg status
177 ? foo.c
177 ? foo.c
178 $ hg add
178 $ hg add
179 adding foo.c
179 adding foo.c
180 $ hg status
180 $ hg status
181 A foo.c
181 A foo.c
182
182
183 Returns 0 if all files are successfully added.
183 Returns 0 if all files are successfully added.
184 """
184 """
185
185
186 m = scmutil.match(repo[None], pats, opts)
186 m = scmutil.match(repo[None], pats, opts)
187 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
187 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
188 opts.get('subrepos'), prefix="", explicitonly=False)
188 opts.get('subrepos'), prefix="", explicitonly=False)
189 return rejected and 1 or 0
189 return rejected and 1 or 0
190
190
191 @command('addremove',
191 @command('addremove',
192 similarityopts + walkopts + dryrunopts,
192 similarityopts + walkopts + dryrunopts,
193 _('[OPTION]... [FILE]...'))
193 _('[OPTION]... [FILE]...'))
194 def addremove(ui, repo, *pats, **opts):
194 def addremove(ui, repo, *pats, **opts):
195 """add all new files, delete all missing files
195 """add all new files, delete all missing files
196
196
197 Add all new files and remove all missing files from the
197 Add all new files and remove all missing files from the
198 repository.
198 repository.
199
199
200 New files are ignored if they match any of the patterns in
200 New files are ignored if they match any of the patterns in
201 ``.hgignore``. As with add, these changes take effect at the next
201 ``.hgignore``. As with add, these changes take effect at the next
202 commit.
202 commit.
203
203
204 Use the -s/--similarity option to detect renamed files. This
204 Use the -s/--similarity option to detect renamed files. This
205 option takes a percentage between 0 (disabled) and 100 (files must
205 option takes a percentage between 0 (disabled) and 100 (files must
206 be identical) as its parameter. With a parameter greater than 0,
206 be identical) as its parameter. With a parameter greater than 0,
207 this compares every removed file with every added file and records
207 this compares every removed file with every added file and records
208 those similar enough as renames. Detecting renamed files this way
208 those similar enough as renames. Detecting renamed files this way
209 can be expensive. After using this option, :hg:`status -C` can be
209 can be expensive. After using this option, :hg:`status -C` can be
210 used to check which files were identified as moved or renamed. If
210 used to check which files were identified as moved or renamed. If
211 not specified, -s/--similarity defaults to 100 and only renames of
211 not specified, -s/--similarity defaults to 100 and only renames of
212 identical files are detected.
212 identical files are detected.
213
213
214 Returns 0 if all files are successfully added.
214 Returns 0 if all files are successfully added.
215 """
215 """
216 try:
216 try:
217 sim = float(opts.get('similarity') or 100)
217 sim = float(opts.get('similarity') or 100)
218 except ValueError:
218 except ValueError:
219 raise util.Abort(_('similarity must be a number'))
219 raise util.Abort(_('similarity must be a number'))
220 if sim < 0 or sim > 100:
220 if sim < 0 or sim > 100:
221 raise util.Abort(_('similarity must be between 0 and 100'))
221 raise util.Abort(_('similarity must be between 0 and 100'))
222 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
222 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
223
223
224 @command('^annotate|blame',
224 @command('^annotate|blame',
225 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
225 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
226 ('', 'follow', None,
226 ('', 'follow', None,
227 _('follow copies/renames and list the filename (DEPRECATED)')),
227 _('follow copies/renames and list the filename (DEPRECATED)')),
228 ('', 'no-follow', None, _("don't follow copies and renames")),
228 ('', 'no-follow', None, _("don't follow copies and renames")),
229 ('a', 'text', None, _('treat all files as text')),
229 ('a', 'text', None, _('treat all files as text')),
230 ('u', 'user', None, _('list the author (long with -v)')),
230 ('u', 'user', None, _('list the author (long with -v)')),
231 ('f', 'file', None, _('list the filename')),
231 ('f', 'file', None, _('list the filename')),
232 ('d', 'date', None, _('list the date (short with -q)')),
232 ('d', 'date', None, _('list the date (short with -q)')),
233 ('n', 'number', None, _('list the revision number (default)')),
233 ('n', 'number', None, _('list the revision number (default)')),
234 ('c', 'changeset', None, _('list the changeset')),
234 ('c', 'changeset', None, _('list the changeset')),
235 ('l', 'line-number', None, _('show line number at the first appearance'))
235 ('l', 'line-number', None, _('show line number at the first appearance'))
236 ] + diffwsopts + walkopts,
236 ] + diffwsopts + walkopts,
237 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
237 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
238 def annotate(ui, repo, *pats, **opts):
238 def annotate(ui, repo, *pats, **opts):
239 """show changeset information by line for each file
239 """show changeset information by line for each file
240
240
241 List changes in files, showing the revision id responsible for
241 List changes in files, showing the revision id responsible for
242 each line
242 each line
243
243
244 This command is useful for discovering when a change was made and
244 This command is useful for discovering when a change was made and
245 by whom.
245 by whom.
246
246
247 Without the -a/--text option, annotate will avoid processing files
247 Without the -a/--text option, annotate will avoid processing files
248 it detects as binary. With -a, annotate will annotate the file
248 it detects as binary. With -a, annotate will annotate the file
249 anyway, although the results will probably be neither useful
249 anyway, although the results will probably be neither useful
250 nor desirable.
250 nor desirable.
251
251
252 Returns 0 on success.
252 Returns 0 on success.
253 """
253 """
254 if opts.get('follow'):
254 if opts.get('follow'):
255 # --follow is deprecated and now just an alias for -f/--file
255 # --follow is deprecated and now just an alias for -f/--file
256 # to mimic the behavior of Mercurial before version 1.5
256 # to mimic the behavior of Mercurial before version 1.5
257 opts['file'] = True
257 opts['file'] = True
258
258
259 datefunc = ui.quiet and util.shortdate or util.datestr
259 datefunc = ui.quiet and util.shortdate or util.datestr
260 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
260 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
261
261
262 if not pats:
262 if not pats:
263 raise util.Abort(_('at least one filename or pattern is required'))
263 raise util.Abort(_('at least one filename or pattern is required'))
264
264
265 hexfn = ui.debugflag and hex or short
265 hexfn = ui.debugflag and hex or short
266
266
267 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
267 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
268 ('number', ' ', lambda x: str(x[0].rev())),
268 ('number', ' ', lambda x: str(x[0].rev())),
269 ('changeset', ' ', lambda x: hexfn(x[0].node())),
269 ('changeset', ' ', lambda x: hexfn(x[0].node())),
270 ('date', ' ', getdate),
270 ('date', ' ', getdate),
271 ('file', ' ', lambda x: x[0].path()),
271 ('file', ' ', lambda x: x[0].path()),
272 ('line_number', ':', lambda x: str(x[1])),
272 ('line_number', ':', lambda x: str(x[1])),
273 ]
273 ]
274
274
275 if (not opts.get('user') and not opts.get('changeset')
275 if (not opts.get('user') and not opts.get('changeset')
276 and not opts.get('date') and not opts.get('file')):
276 and not opts.get('date') and not opts.get('file')):
277 opts['number'] = True
277 opts['number'] = True
278
278
279 linenumber = opts.get('line_number') is not None
279 linenumber = opts.get('line_number') is not None
280 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
280 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
281 raise util.Abort(_('at least one of -n/-c is required for -l'))
281 raise util.Abort(_('at least one of -n/-c is required for -l'))
282
282
283 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
283 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
284 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
284 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
285
285
286 def bad(x, y):
286 def bad(x, y):
287 raise util.Abort("%s: %s" % (x, y))
287 raise util.Abort("%s: %s" % (x, y))
288
288
289 ctx = scmutil.revsingle(repo, opts.get('rev'))
289 ctx = scmutil.revsingle(repo, opts.get('rev'))
290 m = scmutil.match(ctx, pats, opts)
290 m = scmutil.match(ctx, pats, opts)
291 m.bad = bad
291 m.bad = bad
292 follow = not opts.get('no_follow')
292 follow = not opts.get('no_follow')
293 diffopts = patch.diffopts(ui, opts, section='annotate')
293 diffopts = patch.diffopts(ui, opts, section='annotate')
294 for abs in ctx.walk(m):
294 for abs in ctx.walk(m):
295 fctx = ctx[abs]
295 fctx = ctx[abs]
296 if not opts.get('text') and util.binary(fctx.data()):
296 if not opts.get('text') and util.binary(fctx.data()):
297 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
297 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
298 continue
298 continue
299
299
300 lines = fctx.annotate(follow=follow, linenumber=linenumber,
300 lines = fctx.annotate(follow=follow, linenumber=linenumber,
301 diffopts=diffopts)
301 diffopts=diffopts)
302 pieces = []
302 pieces = []
303
303
304 for f, sep in funcmap:
304 for f, sep in funcmap:
305 l = [f(n) for n, dummy in lines]
305 l = [f(n) for n, dummy in lines]
306 if l:
306 if l:
307 sized = [(x, encoding.colwidth(x)) for x in l]
307 sized = [(x, encoding.colwidth(x)) for x in l]
308 ml = max([w for x, w in sized])
308 ml = max([w for x, w in sized])
309 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
309 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
310 for x, w in sized])
310 for x, w in sized])
311
311
312 if pieces:
312 if pieces:
313 for p, l in zip(zip(*pieces), lines):
313 for p, l in zip(zip(*pieces), lines):
314 ui.write("%s: %s" % ("".join(p), l[1]))
314 ui.write("%s: %s" % ("".join(p), l[1]))
315
315
316 if lines and not lines[-1][1].endswith('\n'):
316 if lines and not lines[-1][1].endswith('\n'):
317 ui.write('\n')
317 ui.write('\n')
318
318
319 @command('archive',
319 @command('archive',
320 [('', 'no-decode', None, _('do not pass files through decoders')),
320 [('', 'no-decode', None, _('do not pass files through decoders')),
321 ('p', 'prefix', '', _('directory prefix for files in archive'),
321 ('p', 'prefix', '', _('directory prefix for files in archive'),
322 _('PREFIX')),
322 _('PREFIX')),
323 ('r', 'rev', '', _('revision to distribute'), _('REV')),
323 ('r', 'rev', '', _('revision to distribute'), _('REV')),
324 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
324 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
325 ] + subrepoopts + walkopts,
325 ] + subrepoopts + walkopts,
326 _('[OPTION]... DEST'))
326 _('[OPTION]... DEST'))
327 def archive(ui, repo, dest, **opts):
327 def archive(ui, repo, dest, **opts):
328 '''create an unversioned archive of a repository revision
328 '''create an unversioned archive of a repository revision
329
329
330 By default, the revision used is the parent of the working
330 By default, the revision used is the parent of the working
331 directory; use -r/--rev to specify a different revision.
331 directory; use -r/--rev to specify a different revision.
332
332
333 The archive type is automatically detected based on file
333 The archive type is automatically detected based on file
334 extension (or override using -t/--type).
334 extension (or override using -t/--type).
335
335
336 .. container:: verbose
336 .. container:: verbose
337
337
338 Examples:
338 Examples:
339
339
340 - create a zip file containing the 1.0 release::
340 - create a zip file containing the 1.0 release::
341
341
342 hg archive -r 1.0 project-1.0.zip
342 hg archive -r 1.0 project-1.0.zip
343
343
344 - create a tarball excluding .hg files::
344 - create a tarball excluding .hg files::
345
345
346 hg archive project.tar.gz -X ".hg*"
346 hg archive project.tar.gz -X ".hg*"
347
347
348 Valid types are:
348 Valid types are:
349
349
350 :``files``: a directory full of files (default)
350 :``files``: a directory full of files (default)
351 :``tar``: tar archive, uncompressed
351 :``tar``: tar archive, uncompressed
352 :``tbz2``: tar archive, compressed using bzip2
352 :``tbz2``: tar archive, compressed using bzip2
353 :``tgz``: tar archive, compressed using gzip
353 :``tgz``: tar archive, compressed using gzip
354 :``uzip``: zip archive, uncompressed
354 :``uzip``: zip archive, uncompressed
355 :``zip``: zip archive, compressed using deflate
355 :``zip``: zip archive, compressed using deflate
356
356
357 The exact name of the destination archive or directory is given
357 The exact name of the destination archive or directory is given
358 using a format string; see :hg:`help export` for details.
358 using a format string; see :hg:`help export` for details.
359
359
360 Each member added to an archive file has a directory prefix
360 Each member added to an archive file has a directory prefix
361 prepended. Use -p/--prefix to specify a format string for the
361 prepended. Use -p/--prefix to specify a format string for the
362 prefix. The default is the basename of the archive, with suffixes
362 prefix. The default is the basename of the archive, with suffixes
363 removed.
363 removed.
364
364
365 Returns 0 on success.
365 Returns 0 on success.
366 '''
366 '''
367
367
368 ctx = scmutil.revsingle(repo, opts.get('rev'))
368 ctx = scmutil.revsingle(repo, opts.get('rev'))
369 if not ctx:
369 if not ctx:
370 raise util.Abort(_('no working directory: please specify a revision'))
370 raise util.Abort(_('no working directory: please specify a revision'))
371 node = ctx.node()
371 node = ctx.node()
372 dest = cmdutil.makefilename(repo, dest, node)
372 dest = cmdutil.makefilename(repo, dest, node)
373 if os.path.realpath(dest) == repo.root:
373 if os.path.realpath(dest) == repo.root:
374 raise util.Abort(_('repository root cannot be destination'))
374 raise util.Abort(_('repository root cannot be destination'))
375
375
376 kind = opts.get('type') or archival.guesskind(dest) or 'files'
376 kind = opts.get('type') or archival.guesskind(dest) or 'files'
377 prefix = opts.get('prefix')
377 prefix = opts.get('prefix')
378
378
379 if dest == '-':
379 if dest == '-':
380 if kind == 'files':
380 if kind == 'files':
381 raise util.Abort(_('cannot archive plain files to stdout'))
381 raise util.Abort(_('cannot archive plain files to stdout'))
382 dest = cmdutil.makefileobj(repo, dest)
382 dest = cmdutil.makefileobj(repo, dest)
383 if not prefix:
383 if not prefix:
384 prefix = os.path.basename(repo.root) + '-%h'
384 prefix = os.path.basename(repo.root) + '-%h'
385
385
386 prefix = cmdutil.makefilename(repo, prefix, node)
386 prefix = cmdutil.makefilename(repo, prefix, node)
387 matchfn = scmutil.match(ctx, [], opts)
387 matchfn = scmutil.match(ctx, [], opts)
388 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
388 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
389 matchfn, prefix, subrepos=opts.get('subrepos'))
389 matchfn, prefix, subrepos=opts.get('subrepos'))
390
390
391 @command('backout',
391 @command('backout',
392 [('', 'merge', None, _('merge with old dirstate parent after backout')),
392 [('', 'merge', None, _('merge with old dirstate parent after backout')),
393 ('', 'parent', '',
393 ('', 'parent', '',
394 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
394 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
395 ('r', 'rev', '', _('revision to backout'), _('REV')),
395 ('r', 'rev', '', _('revision to backout'), _('REV')),
396 ('e', 'edit', False, _('invoke editor on commit messages')),
396 ('e', 'edit', False, _('invoke editor on commit messages')),
397 ] + mergetoolopts + walkopts + commitopts + commitopts2,
397 ] + mergetoolopts + walkopts + commitopts + commitopts2,
398 _('[OPTION]... [-r] REV'))
398 _('[OPTION]... [-r] REV'))
399 def backout(ui, repo, node=None, rev=None, **opts):
399 def backout(ui, repo, node=None, rev=None, **opts):
400 '''reverse effect of earlier changeset
400 '''reverse effect of earlier changeset
401
401
402 Prepare a new changeset with the effect of REV undone in the
402 Prepare a new changeset with the effect of REV undone in the
403 current working directory.
403 current working directory.
404
404
405 If REV is the parent of the working directory, then this new changeset
405 If REV is the parent of the working directory, then this new changeset
406 is committed automatically. Otherwise, hg needs to merge the
406 is committed automatically. Otherwise, hg needs to merge the
407 changes and the merged result is left uncommitted.
407 changes and the merged result is left uncommitted.
408
408
409 .. note::
409 .. note::
410
410
411 backout cannot be used to fix either an unwanted or
411 backout cannot be used to fix either an unwanted or
412 incorrect merge.
412 incorrect merge.
413
413
414 .. container:: verbose
414 .. container:: verbose
415
415
416 By default, the pending changeset will have one parent,
416 By default, the pending changeset will have one parent,
417 maintaining a linear history. With --merge, the pending
417 maintaining a linear history. With --merge, the pending
418 changeset will instead have two parents: the old parent of the
418 changeset will instead have two parents: the old parent of the
419 working directory and a new child of REV that simply undoes REV.
419 working directory and a new child of REV that simply undoes REV.
420
420
421 Before version 1.7, the behavior without --merge was equivalent
421 Before version 1.7, the behavior without --merge was equivalent
422 to specifying --merge followed by :hg:`update --clean .` to
422 to specifying --merge followed by :hg:`update --clean .` to
423 cancel the merge and leave the child of REV as a head to be
423 cancel the merge and leave the child of REV as a head to be
424 merged separately.
424 merged separately.
425
425
426 See :hg:`help dates` for a list of formats valid for -d/--date.
426 See :hg:`help dates` for a list of formats valid for -d/--date.
427
427
428 Returns 0 on success, 1 if nothing to backout or there are unresolved
428 Returns 0 on success, 1 if nothing to backout or there are unresolved
429 files.
429 files.
430 '''
430 '''
431 if rev and node:
431 if rev and node:
432 raise util.Abort(_("please specify just one revision"))
432 raise util.Abort(_("please specify just one revision"))
433
433
434 if not rev:
434 if not rev:
435 rev = node
435 rev = node
436
436
437 if not rev:
437 if not rev:
438 raise util.Abort(_("please specify a revision to backout"))
438 raise util.Abort(_("please specify a revision to backout"))
439
439
440 date = opts.get('date')
440 date = opts.get('date')
441 if date:
441 if date:
442 opts['date'] = util.parsedate(date)
442 opts['date'] = util.parsedate(date)
443
443
444 cmdutil.checkunfinished(repo)
444 cmdutil.checkunfinished(repo)
445 cmdutil.bailifchanged(repo)
445 cmdutil.bailifchanged(repo)
446 node = scmutil.revsingle(repo, rev).node()
446 node = scmutil.revsingle(repo, rev).node()
447
447
448 op1, op2 = repo.dirstate.parents()
448 op1, op2 = repo.dirstate.parents()
449 if node not in repo.changelog.commonancestorsheads(op1, node):
449 if node not in repo.changelog.commonancestorsheads(op1, node):
450 raise util.Abort(_('cannot backout change that is not an ancestor'))
450 raise util.Abort(_('cannot backout change that is not an ancestor'))
451
451
452 p1, p2 = repo.changelog.parents(node)
452 p1, p2 = repo.changelog.parents(node)
453 if p1 == nullid:
453 if p1 == nullid:
454 raise util.Abort(_('cannot backout a change with no parents'))
454 raise util.Abort(_('cannot backout a change with no parents'))
455 if p2 != nullid:
455 if p2 != nullid:
456 if not opts.get('parent'):
456 if not opts.get('parent'):
457 raise util.Abort(_('cannot backout a merge changeset'))
457 raise util.Abort(_('cannot backout a merge changeset'))
458 p = repo.lookup(opts['parent'])
458 p = repo.lookup(opts['parent'])
459 if p not in (p1, p2):
459 if p not in (p1, p2):
460 raise util.Abort(_('%s is not a parent of %s') %
460 raise util.Abort(_('%s is not a parent of %s') %
461 (short(p), short(node)))
461 (short(p), short(node)))
462 parent = p
462 parent = p
463 else:
463 else:
464 if opts.get('parent'):
464 if opts.get('parent'):
465 raise util.Abort(_('cannot use --parent on non-merge changeset'))
465 raise util.Abort(_('cannot use --parent on non-merge changeset'))
466 parent = p1
466 parent = p1
467
467
468 # the backout should appear on the same branch
468 # the backout should appear on the same branch
469 wlock = repo.wlock()
469 wlock = repo.wlock()
470 try:
470 try:
471 branch = repo.dirstate.branch()
471 branch = repo.dirstate.branch()
472 bheads = repo.branchheads(branch)
472 bheads = repo.branchheads(branch)
473 rctx = scmutil.revsingle(repo, hex(parent))
473 rctx = scmutil.revsingle(repo, hex(parent))
474 if not opts.get('merge') and op1 != node:
474 if not opts.get('merge') and op1 != node:
475 try:
475 try:
476 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
476 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
477 'backout')
477 'backout')
478 stats = mergemod.update(repo, parent, True, True, False,
478 stats = mergemod.update(repo, parent, True, True, False,
479 node, False)
479 node, False)
480 repo.setparents(op1, op2)
480 repo.setparents(op1, op2)
481 hg._showstats(repo, stats)
481 hg._showstats(repo, stats)
482 if stats[3]:
482 if stats[3]:
483 repo.ui.status(_("use 'hg resolve' to retry unresolved "
483 repo.ui.status(_("use 'hg resolve' to retry unresolved "
484 "file merges\n"))
484 "file merges\n"))
485 else:
485 else:
486 msg = _("changeset %s backed out, "
486 msg = _("changeset %s backed out, "
487 "don't forget to commit.\n")
487 "don't forget to commit.\n")
488 ui.status(msg % short(node))
488 ui.status(msg % short(node))
489 return stats[3] > 0
489 return stats[3] > 0
490 finally:
490 finally:
491 ui.setconfig('ui', 'forcemerge', '', '')
491 ui.setconfig('ui', 'forcemerge', '', '')
492 else:
492 else:
493 hg.clean(repo, node, show_stats=False)
493 hg.clean(repo, node, show_stats=False)
494 repo.dirstate.setbranch(branch)
494 repo.dirstate.setbranch(branch)
495 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
495 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
496
496
497
497
498 def commitfunc(ui, repo, message, match, opts):
498 def commitfunc(ui, repo, message, match, opts):
499 e = cmdutil.getcommiteditor(**opts)
499 e = cmdutil.getcommiteditor(**opts)
500 if not message:
500 if not message:
501 # we don't translate commit messages
501 # we don't translate commit messages
502 message = "Backed out changeset %s" % short(node)
502 message = "Backed out changeset %s" % short(node)
503 e = cmdutil.getcommiteditor(edit=True)
503 e = cmdutil.getcommiteditor(edit=True)
504 return repo.commit(message, opts.get('user'), opts.get('date'),
504 return repo.commit(message, opts.get('user'), opts.get('date'),
505 match, editor=e)
505 match, editor=e)
506 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
506 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
507 if not newnode:
507 if not newnode:
508 ui.status(_("nothing changed\n"))
508 ui.status(_("nothing changed\n"))
509 return 1
509 return 1
510 cmdutil.commitstatus(repo, newnode, branch, bheads)
510 cmdutil.commitstatus(repo, newnode, branch, bheads)
511
511
512 def nice(node):
512 def nice(node):
513 return '%d:%s' % (repo.changelog.rev(node), short(node))
513 return '%d:%s' % (repo.changelog.rev(node), short(node))
514 ui.status(_('changeset %s backs out changeset %s\n') %
514 ui.status(_('changeset %s backs out changeset %s\n') %
515 (nice(repo.changelog.tip()), nice(node)))
515 (nice(repo.changelog.tip()), nice(node)))
516 if opts.get('merge') and op1 != node:
516 if opts.get('merge') and op1 != node:
517 hg.clean(repo, op1, show_stats=False)
517 hg.clean(repo, op1, show_stats=False)
518 ui.status(_('merging with changeset %s\n')
518 ui.status(_('merging with changeset %s\n')
519 % nice(repo.changelog.tip()))
519 % nice(repo.changelog.tip()))
520 try:
520 try:
521 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
521 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
522 'backout')
522 'backout')
523 return hg.merge(repo, hex(repo.changelog.tip()))
523 return hg.merge(repo, hex(repo.changelog.tip()))
524 finally:
524 finally:
525 ui.setconfig('ui', 'forcemerge', '', '')
525 ui.setconfig('ui', 'forcemerge', '', '')
526 finally:
526 finally:
527 wlock.release()
527 wlock.release()
528 return 0
528 return 0
529
529
530 @command('bisect',
530 @command('bisect',
531 [('r', 'reset', False, _('reset bisect state')),
531 [('r', 'reset', False, _('reset bisect state')),
532 ('g', 'good', False, _('mark changeset good')),
532 ('g', 'good', False, _('mark changeset good')),
533 ('b', 'bad', False, _('mark changeset bad')),
533 ('b', 'bad', False, _('mark changeset bad')),
534 ('s', 'skip', False, _('skip testing changeset')),
534 ('s', 'skip', False, _('skip testing changeset')),
535 ('e', 'extend', False, _('extend the bisect range')),
535 ('e', 'extend', False, _('extend the bisect range')),
536 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
536 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
537 ('U', 'noupdate', False, _('do not update to target'))],
537 ('U', 'noupdate', False, _('do not update to target'))],
538 _("[-gbsr] [-U] [-c CMD] [REV]"))
538 _("[-gbsr] [-U] [-c CMD] [REV]"))
539 def bisect(ui, repo, rev=None, extra=None, command=None,
539 def bisect(ui, repo, rev=None, extra=None, command=None,
540 reset=None, good=None, bad=None, skip=None, extend=None,
540 reset=None, good=None, bad=None, skip=None, extend=None,
541 noupdate=None):
541 noupdate=None):
542 """subdivision search of changesets
542 """subdivision search of changesets
543
543
544 This command helps to find changesets which introduce problems. To
544 This command helps to find changesets which introduce problems. To
545 use, mark the earliest changeset you know exhibits the problem as
545 use, mark the earliest changeset you know exhibits the problem as
546 bad, then mark the latest changeset which is free from the problem
546 bad, then mark the latest changeset which is free from the problem
547 as good. Bisect will update your working directory to a revision
547 as good. Bisect will update your working directory to a revision
548 for testing (unless the -U/--noupdate option is specified). Once
548 for testing (unless the -U/--noupdate option is specified). Once
549 you have performed tests, mark the working directory as good or
549 you have performed tests, mark the working directory as good or
550 bad, and bisect will either update to another candidate changeset
550 bad, and bisect will either update to another candidate changeset
551 or announce that it has found the bad revision.
551 or announce that it has found the bad revision.
552
552
553 As a shortcut, you can also use the revision argument to mark a
553 As a shortcut, you can also use the revision argument to mark a
554 revision as good or bad without checking it out first.
554 revision as good or bad without checking it out first.
555
555
556 If you supply a command, it will be used for automatic bisection.
556 If you supply a command, it will be used for automatic bisection.
557 The environment variable HG_NODE will contain the ID of the
557 The environment variable HG_NODE will contain the ID of the
558 changeset being tested. The exit status of the command will be
558 changeset being tested. The exit status of the command will be
559 used to mark revisions as good or bad: status 0 means good, 125
559 used to mark revisions as good or bad: status 0 means good, 125
560 means to skip the revision, 127 (command not found) will abort the
560 means to skip the revision, 127 (command not found) will abort the
561 bisection, and any other non-zero exit status means the revision
561 bisection, and any other non-zero exit status means the revision
562 is bad.
562 is bad.
563
563
564 .. container:: verbose
564 .. container:: verbose
565
565
566 Some examples:
566 Some examples:
567
567
568 - start a bisection with known bad revision 34, and good revision 12::
568 - start a bisection with known bad revision 34, and good revision 12::
569
569
570 hg bisect --bad 34
570 hg bisect --bad 34
571 hg bisect --good 12
571 hg bisect --good 12
572
572
573 - advance the current bisection by marking current revision as good or
573 - advance the current bisection by marking current revision as good or
574 bad::
574 bad::
575
575
576 hg bisect --good
576 hg bisect --good
577 hg bisect --bad
577 hg bisect --bad
578
578
579 - mark the current revision, or a known revision, to be skipped (e.g. if
579 - mark the current revision, or a known revision, to be skipped (e.g. if
580 that revision is not usable because of another issue)::
580 that revision is not usable because of another issue)::
581
581
582 hg bisect --skip
582 hg bisect --skip
583 hg bisect --skip 23
583 hg bisect --skip 23
584
584
585 - skip all revisions that do not touch directories ``foo`` or ``bar``::
585 - skip all revisions that do not touch directories ``foo`` or ``bar``::
586
586
587 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
587 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
588
588
589 - forget the current bisection::
589 - forget the current bisection::
590
590
591 hg bisect --reset
591 hg bisect --reset
592
592
593 - use 'make && make tests' to automatically find the first broken
593 - use 'make && make tests' to automatically find the first broken
594 revision::
594 revision::
595
595
596 hg bisect --reset
596 hg bisect --reset
597 hg bisect --bad 34
597 hg bisect --bad 34
598 hg bisect --good 12
598 hg bisect --good 12
599 hg bisect --command "make && make tests"
599 hg bisect --command "make && make tests"
600
600
601 - see all changesets whose states are already known in the current
601 - see all changesets whose states are already known in the current
602 bisection::
602 bisection::
603
603
604 hg log -r "bisect(pruned)"
604 hg log -r "bisect(pruned)"
605
605
606 - see the changeset currently being bisected (especially useful
606 - see the changeset currently being bisected (especially useful
607 if running with -U/--noupdate)::
607 if running with -U/--noupdate)::
608
608
609 hg log -r "bisect(current)"
609 hg log -r "bisect(current)"
610
610
611 - see all changesets that took part in the current bisection::
611 - see all changesets that took part in the current bisection::
612
612
613 hg log -r "bisect(range)"
613 hg log -r "bisect(range)"
614
614
615 - you can even get a nice graph::
615 - you can even get a nice graph::
616
616
617 hg log --graph -r "bisect(range)"
617 hg log --graph -r "bisect(range)"
618
618
619 See :hg:`help revsets` for more about the `bisect()` keyword.
619 See :hg:`help revsets` for more about the `bisect()` keyword.
620
620
621 Returns 0 on success.
621 Returns 0 on success.
622 """
622 """
623 def extendbisectrange(nodes, good):
623 def extendbisectrange(nodes, good):
624 # bisect is incomplete when it ends on a merge node and
624 # bisect is incomplete when it ends on a merge node and
625 # one of the parent was not checked.
625 # one of the parent was not checked.
626 parents = repo[nodes[0]].parents()
626 parents = repo[nodes[0]].parents()
627 if len(parents) > 1:
627 if len(parents) > 1:
628 side = good and state['bad'] or state['good']
628 side = good and state['bad'] or state['good']
629 num = len(set(i.node() for i in parents) & set(side))
629 num = len(set(i.node() for i in parents) & set(side))
630 if num == 1:
630 if num == 1:
631 return parents[0].ancestor(parents[1])
631 return parents[0].ancestor(parents[1])
632 return None
632 return None
633
633
634 def print_result(nodes, good):
634 def print_result(nodes, good):
635 displayer = cmdutil.show_changeset(ui, repo, {})
635 displayer = cmdutil.show_changeset(ui, repo, {})
636 if len(nodes) == 1:
636 if len(nodes) == 1:
637 # narrowed it down to a single revision
637 # narrowed it down to a single revision
638 if good:
638 if good:
639 ui.write(_("The first good revision is:\n"))
639 ui.write(_("The first good revision is:\n"))
640 else:
640 else:
641 ui.write(_("The first bad revision is:\n"))
641 ui.write(_("The first bad revision is:\n"))
642 displayer.show(repo[nodes[0]])
642 displayer.show(repo[nodes[0]])
643 extendnode = extendbisectrange(nodes, good)
643 extendnode = extendbisectrange(nodes, good)
644 if extendnode is not None:
644 if extendnode is not None:
645 ui.write(_('Not all ancestors of this changeset have been'
645 ui.write(_('Not all ancestors of this changeset have been'
646 ' checked.\nUse bisect --extend to continue the '
646 ' checked.\nUse bisect --extend to continue the '
647 'bisection from\nthe common ancestor, %s.\n')
647 'bisection from\nthe common ancestor, %s.\n')
648 % extendnode)
648 % extendnode)
649 else:
649 else:
650 # multiple possible revisions
650 # multiple possible revisions
651 if good:
651 if good:
652 ui.write(_("Due to skipped revisions, the first "
652 ui.write(_("Due to skipped revisions, the first "
653 "good revision could be any of:\n"))
653 "good revision could be any of:\n"))
654 else:
654 else:
655 ui.write(_("Due to skipped revisions, the first "
655 ui.write(_("Due to skipped revisions, the first "
656 "bad revision could be any of:\n"))
656 "bad revision could be any of:\n"))
657 for n in nodes:
657 for n in nodes:
658 displayer.show(repo[n])
658 displayer.show(repo[n])
659 displayer.close()
659 displayer.close()
660
660
661 def check_state(state, interactive=True):
661 def check_state(state, interactive=True):
662 if not state['good'] or not state['bad']:
662 if not state['good'] or not state['bad']:
663 if (good or bad or skip or reset) and interactive:
663 if (good or bad or skip or reset) and interactive:
664 return
664 return
665 if not state['good']:
665 if not state['good']:
666 raise util.Abort(_('cannot bisect (no known good revisions)'))
666 raise util.Abort(_('cannot bisect (no known good revisions)'))
667 else:
667 else:
668 raise util.Abort(_('cannot bisect (no known bad revisions)'))
668 raise util.Abort(_('cannot bisect (no known bad revisions)'))
669 return True
669 return True
670
670
671 # backward compatibility
671 # backward compatibility
672 if rev in "good bad reset init".split():
672 if rev in "good bad reset init".split():
673 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
673 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
674 cmd, rev, extra = rev, extra, None
674 cmd, rev, extra = rev, extra, None
675 if cmd == "good":
675 if cmd == "good":
676 good = True
676 good = True
677 elif cmd == "bad":
677 elif cmd == "bad":
678 bad = True
678 bad = True
679 else:
679 else:
680 reset = True
680 reset = True
681 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
681 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
682 raise util.Abort(_('incompatible arguments'))
682 raise util.Abort(_('incompatible arguments'))
683
683
684 cmdutil.checkunfinished(repo)
684 cmdutil.checkunfinished(repo)
685
685
686 if reset:
686 if reset:
687 p = repo.join("bisect.state")
687 p = repo.join("bisect.state")
688 if os.path.exists(p):
688 if os.path.exists(p):
689 os.unlink(p)
689 os.unlink(p)
690 return
690 return
691
691
692 state = hbisect.load_state(repo)
692 state = hbisect.load_state(repo)
693
693
694 if command:
694 if command:
695 changesets = 1
695 changesets = 1
696 if noupdate:
696 if noupdate:
697 try:
697 try:
698 node = state['current'][0]
698 node = state['current'][0]
699 except LookupError:
699 except LookupError:
700 raise util.Abort(_('current bisect revision is unknown - '
700 raise util.Abort(_('current bisect revision is unknown - '
701 'start a new bisect to fix'))
701 'start a new bisect to fix'))
702 else:
702 else:
703 node, p2 = repo.dirstate.parents()
703 node, p2 = repo.dirstate.parents()
704 if p2 != nullid:
704 if p2 != nullid:
705 raise util.Abort(_('current bisect revision is a merge'))
705 raise util.Abort(_('current bisect revision is a merge'))
706 try:
706 try:
707 while changesets:
707 while changesets:
708 # update state
708 # update state
709 state['current'] = [node]
709 state['current'] = [node]
710 hbisect.save_state(repo, state)
710 hbisect.save_state(repo, state)
711 status = util.system(command,
711 status = util.system(command,
712 environ={'HG_NODE': hex(node)},
712 environ={'HG_NODE': hex(node)},
713 out=ui.fout)
713 out=ui.fout)
714 if status == 125:
714 if status == 125:
715 transition = "skip"
715 transition = "skip"
716 elif status == 0:
716 elif status == 0:
717 transition = "good"
717 transition = "good"
718 # status < 0 means process was killed
718 # status < 0 means process was killed
719 elif status == 127:
719 elif status == 127:
720 raise util.Abort(_("failed to execute %s") % command)
720 raise util.Abort(_("failed to execute %s") % command)
721 elif status < 0:
721 elif status < 0:
722 raise util.Abort(_("%s killed") % command)
722 raise util.Abort(_("%s killed") % command)
723 else:
723 else:
724 transition = "bad"
724 transition = "bad"
725 ctx = scmutil.revsingle(repo, rev, node)
725 ctx = scmutil.revsingle(repo, rev, node)
726 rev = None # clear for future iterations
726 rev = None # clear for future iterations
727 state[transition].append(ctx.node())
727 state[transition].append(ctx.node())
728 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
728 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
729 check_state(state, interactive=False)
729 check_state(state, interactive=False)
730 # bisect
730 # bisect
731 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
731 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
732 # update to next check
732 # update to next check
733 node = nodes[0]
733 node = nodes[0]
734 if not noupdate:
734 if not noupdate:
735 cmdutil.bailifchanged(repo)
735 cmdutil.bailifchanged(repo)
736 hg.clean(repo, node, show_stats=False)
736 hg.clean(repo, node, show_stats=False)
737 finally:
737 finally:
738 state['current'] = [node]
738 state['current'] = [node]
739 hbisect.save_state(repo, state)
739 hbisect.save_state(repo, state)
740 print_result(nodes, bgood)
740 print_result(nodes, bgood)
741 return
741 return
742
742
743 # update state
743 # update state
744
744
745 if rev:
745 if rev:
746 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
746 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
747 else:
747 else:
748 nodes = [repo.lookup('.')]
748 nodes = [repo.lookup('.')]
749
749
750 if good or bad or skip:
750 if good or bad or skip:
751 if good:
751 if good:
752 state['good'] += nodes
752 state['good'] += nodes
753 elif bad:
753 elif bad:
754 state['bad'] += nodes
754 state['bad'] += nodes
755 elif skip:
755 elif skip:
756 state['skip'] += nodes
756 state['skip'] += nodes
757 hbisect.save_state(repo, state)
757 hbisect.save_state(repo, state)
758
758
759 if not check_state(state):
759 if not check_state(state):
760 return
760 return
761
761
762 # actually bisect
762 # actually bisect
763 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
763 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
764 if extend:
764 if extend:
765 if not changesets:
765 if not changesets:
766 extendnode = extendbisectrange(nodes, good)
766 extendnode = extendbisectrange(nodes, good)
767 if extendnode is not None:
767 if extendnode is not None:
768 ui.write(_("Extending search to changeset %d:%s\n")
768 ui.write(_("Extending search to changeset %d:%s\n")
769 % (extendnode.rev(), extendnode))
769 % (extendnode.rev(), extendnode))
770 state['current'] = [extendnode.node()]
770 state['current'] = [extendnode.node()]
771 hbisect.save_state(repo, state)
771 hbisect.save_state(repo, state)
772 if noupdate:
772 if noupdate:
773 return
773 return
774 cmdutil.bailifchanged(repo)
774 cmdutil.bailifchanged(repo)
775 return hg.clean(repo, extendnode.node())
775 return hg.clean(repo, extendnode.node())
776 raise util.Abort(_("nothing to extend"))
776 raise util.Abort(_("nothing to extend"))
777
777
778 if changesets == 0:
778 if changesets == 0:
779 print_result(nodes, good)
779 print_result(nodes, good)
780 else:
780 else:
781 assert len(nodes) == 1 # only a single node can be tested next
781 assert len(nodes) == 1 # only a single node can be tested next
782 node = nodes[0]
782 node = nodes[0]
783 # compute the approximate number of remaining tests
783 # compute the approximate number of remaining tests
784 tests, size = 0, 2
784 tests, size = 0, 2
785 while size <= changesets:
785 while size <= changesets:
786 tests, size = tests + 1, size * 2
786 tests, size = tests + 1, size * 2
787 rev = repo.changelog.rev(node)
787 rev = repo.changelog.rev(node)
788 ui.write(_("Testing changeset %d:%s "
788 ui.write(_("Testing changeset %d:%s "
789 "(%d changesets remaining, ~%d tests)\n")
789 "(%d changesets remaining, ~%d tests)\n")
790 % (rev, short(node), changesets, tests))
790 % (rev, short(node), changesets, tests))
791 state['current'] = [node]
791 state['current'] = [node]
792 hbisect.save_state(repo, state)
792 hbisect.save_state(repo, state)
793 if not noupdate:
793 if not noupdate:
794 cmdutil.bailifchanged(repo)
794 cmdutil.bailifchanged(repo)
795 return hg.clean(repo, node)
795 return hg.clean(repo, node)
796
796
797 @command('bookmarks|bookmark',
797 @command('bookmarks|bookmark',
798 [('f', 'force', False, _('force')),
798 [('f', 'force', False, _('force')),
799 ('r', 'rev', '', _('revision'), _('REV')),
799 ('r', 'rev', '', _('revision'), _('REV')),
800 ('d', 'delete', False, _('delete a given bookmark')),
800 ('d', 'delete', False, _('delete a given bookmark')),
801 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
801 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
802 ('i', 'inactive', False, _('mark a bookmark inactive'))],
802 ('i', 'inactive', False, _('mark a bookmark inactive'))],
803 _('hg bookmarks [OPTIONS]... [NAME]...'))
803 _('hg bookmarks [OPTIONS]... [NAME]...'))
804 def bookmark(ui, repo, *names, **opts):
804 def bookmark(ui, repo, *names, **opts):
805 '''create a new bookmark or list existing bookmarks
805 '''create a new bookmark or list existing bookmarks
806
806
807 Bookmarks are labels on changesets to help track lines of development.
807 Bookmarks are labels on changesets to help track lines of development.
808 Bookmarks are unversioned and can be moved, renamed and deleted.
808 Bookmarks are unversioned and can be moved, renamed and deleted.
809 Deleting or moving a bookmark has no effect on the associated changesets.
809 Deleting or moving a bookmark has no effect on the associated changesets.
810
810
811 Creating or updating to a bookmark causes it to be marked as 'active'.
811 Creating or updating to a bookmark causes it to be marked as 'active'.
812 Active bookmarks are indicated with a '*'.
812 Active bookmarks are indicated with a '*'.
813 When a commit is made, an active bookmark will advance to the new commit.
813 When a commit is made, an active bookmark will advance to the new commit.
814 A plain :hg:`update` will also advance an active bookmark, if possible.
814 A plain :hg:`update` will also advance an active bookmark, if possible.
815 Updating away from a bookmark will cause it to be deactivated.
815 Updating away from a bookmark will cause it to be deactivated.
816
816
817 Bookmarks can be pushed and pulled between repositories (see
817 Bookmarks can be pushed and pulled between repositories (see
818 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
818 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
819 diverged, a new 'divergent bookmark' of the form 'name@path' will
819 diverged, a new 'divergent bookmark' of the form 'name@path' will
820 be created. Using :hg:'merge' will resolve the divergence.
820 be created. Using :hg:'merge' will resolve the divergence.
821
821
822 A bookmark named '@' has the special property that :hg:`clone` will
822 A bookmark named '@' has the special property that :hg:`clone` will
823 check it out by default if it exists.
823 check it out by default if it exists.
824
824
825 .. container:: verbose
825 .. container:: verbose
826
826
827 Examples:
827 Examples:
828
828
829 - create an active bookmark for a new line of development::
829 - create an active bookmark for a new line of development::
830
830
831 hg book new-feature
831 hg book new-feature
832
832
833 - create an inactive bookmark as a place marker::
833 - create an inactive bookmark as a place marker::
834
834
835 hg book -i reviewed
835 hg book -i reviewed
836
836
837 - create an inactive bookmark on another changeset::
837 - create an inactive bookmark on another changeset::
838
838
839 hg book -r .^ tested
839 hg book -r .^ tested
840
840
841 - move the '@' bookmark from another branch::
841 - move the '@' bookmark from another branch::
842
842
843 hg book -f @
843 hg book -f @
844 '''
844 '''
845 force = opts.get('force')
845 force = opts.get('force')
846 rev = opts.get('rev')
846 rev = opts.get('rev')
847 delete = opts.get('delete')
847 delete = opts.get('delete')
848 rename = opts.get('rename')
848 rename = opts.get('rename')
849 inactive = opts.get('inactive')
849 inactive = opts.get('inactive')
850
850
851 def checkformat(mark):
851 def checkformat(mark):
852 mark = mark.strip()
852 mark = mark.strip()
853 if not mark:
853 if not mark:
854 raise util.Abort(_("bookmark names cannot consist entirely of "
854 raise util.Abort(_("bookmark names cannot consist entirely of "
855 "whitespace"))
855 "whitespace"))
856 scmutil.checknewlabel(repo, mark, 'bookmark')
856 scmutil.checknewlabel(repo, mark, 'bookmark')
857 return mark
857 return mark
858
858
859 def checkconflict(repo, mark, cur, force=False, target=None):
859 def checkconflict(repo, mark, cur, force=False, target=None):
860 if mark in marks and not force:
860 if mark in marks and not force:
861 if target:
861 if target:
862 if marks[mark] == target and target == cur:
862 if marks[mark] == target and target == cur:
863 # re-activating a bookmark
863 # re-activating a bookmark
864 return
864 return
865 anc = repo.changelog.ancestors([repo[target].rev()])
865 anc = repo.changelog.ancestors([repo[target].rev()])
866 bmctx = repo[marks[mark]]
866 bmctx = repo[marks[mark]]
867 divs = [repo[b].node() for b in marks
867 divs = [repo[b].node() for b in marks
868 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
868 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
869
869
870 # allow resolving a single divergent bookmark even if moving
870 # allow resolving a single divergent bookmark even if moving
871 # the bookmark across branches when a revision is specified
871 # the bookmark across branches when a revision is specified
872 # that contains a divergent bookmark
872 # that contains a divergent bookmark
873 if bmctx.rev() not in anc and target in divs:
873 if bmctx.rev() not in anc and target in divs:
874 bookmarks.deletedivergent(repo, [target], mark)
874 bookmarks.deletedivergent(repo, [target], mark)
875 return
875 return
876
876
877 deletefrom = [b for b in divs
877 deletefrom = [b for b in divs
878 if repo[b].rev() in anc or b == target]
878 if repo[b].rev() in anc or b == target]
879 bookmarks.deletedivergent(repo, deletefrom, mark)
879 bookmarks.deletedivergent(repo, deletefrom, mark)
880 if bookmarks.validdest(repo, bmctx, repo[target]):
880 if bookmarks.validdest(repo, bmctx, repo[target]):
881 ui.status(_("moving bookmark '%s' forward from %s\n") %
881 ui.status(_("moving bookmark '%s' forward from %s\n") %
882 (mark, short(bmctx.node())))
882 (mark, short(bmctx.node())))
883 return
883 return
884 raise util.Abort(_("bookmark '%s' already exists "
884 raise util.Abort(_("bookmark '%s' already exists "
885 "(use -f to force)") % mark)
885 "(use -f to force)") % mark)
886 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
886 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
887 and not force):
887 and not force):
888 raise util.Abort(
888 raise util.Abort(
889 _("a bookmark cannot have the name of an existing branch"))
889 _("a bookmark cannot have the name of an existing branch"))
890
890
891 if delete and rename:
891 if delete and rename:
892 raise util.Abort(_("--delete and --rename are incompatible"))
892 raise util.Abort(_("--delete and --rename are incompatible"))
893 if delete and rev:
893 if delete and rev:
894 raise util.Abort(_("--rev is incompatible with --delete"))
894 raise util.Abort(_("--rev is incompatible with --delete"))
895 if rename and rev:
895 if rename and rev:
896 raise util.Abort(_("--rev is incompatible with --rename"))
896 raise util.Abort(_("--rev is incompatible with --rename"))
897 if not names and (delete or rev):
897 if not names and (delete or rev):
898 raise util.Abort(_("bookmark name required"))
898 raise util.Abort(_("bookmark name required"))
899
899
900 if delete or rename or names or inactive:
900 if delete or rename or names or inactive:
901 wlock = repo.wlock()
901 wlock = repo.wlock()
902 try:
902 try:
903 cur = repo.changectx('.').node()
903 cur = repo.changectx('.').node()
904 marks = repo._bookmarks
904 marks = repo._bookmarks
905 if delete:
905 if delete:
906 for mark in names:
906 for mark in names:
907 if mark not in marks:
907 if mark not in marks:
908 raise util.Abort(_("bookmark '%s' does not exist") %
908 raise util.Abort(_("bookmark '%s' does not exist") %
909 mark)
909 mark)
910 if mark == repo._bookmarkcurrent:
910 if mark == repo._bookmarkcurrent:
911 bookmarks.unsetcurrent(repo)
911 bookmarks.unsetcurrent(repo)
912 del marks[mark]
912 del marks[mark]
913 marks.write()
913 marks.write()
914
914
915 elif rename:
915 elif rename:
916 if not names:
916 if not names:
917 raise util.Abort(_("new bookmark name required"))
917 raise util.Abort(_("new bookmark name required"))
918 elif len(names) > 1:
918 elif len(names) > 1:
919 raise util.Abort(_("only one new bookmark name allowed"))
919 raise util.Abort(_("only one new bookmark name allowed"))
920 mark = checkformat(names[0])
920 mark = checkformat(names[0])
921 if rename not in marks:
921 if rename not in marks:
922 raise util.Abort(_("bookmark '%s' does not exist") % rename)
922 raise util.Abort(_("bookmark '%s' does not exist") % rename)
923 checkconflict(repo, mark, cur, force)
923 checkconflict(repo, mark, cur, force)
924 marks[mark] = marks[rename]
924 marks[mark] = marks[rename]
925 if repo._bookmarkcurrent == rename and not inactive:
925 if repo._bookmarkcurrent == rename and not inactive:
926 bookmarks.setcurrent(repo, mark)
926 bookmarks.setcurrent(repo, mark)
927 del marks[rename]
927 del marks[rename]
928 marks.write()
928 marks.write()
929
929
930 elif names:
930 elif names:
931 newact = None
931 newact = None
932 for mark in names:
932 for mark in names:
933 mark = checkformat(mark)
933 mark = checkformat(mark)
934 if newact is None:
934 if newact is None:
935 newact = mark
935 newact = mark
936 if inactive and mark == repo._bookmarkcurrent:
936 if inactive and mark == repo._bookmarkcurrent:
937 bookmarks.unsetcurrent(repo)
937 bookmarks.unsetcurrent(repo)
938 return
938 return
939 tgt = cur
939 tgt = cur
940 if rev:
940 if rev:
941 tgt = scmutil.revsingle(repo, rev).node()
941 tgt = scmutil.revsingle(repo, rev).node()
942 checkconflict(repo, mark, cur, force, tgt)
942 checkconflict(repo, mark, cur, force, tgt)
943 marks[mark] = tgt
943 marks[mark] = tgt
944 if not inactive and cur == marks[newact] and not rev:
944 if not inactive and cur == marks[newact] and not rev:
945 bookmarks.setcurrent(repo, newact)
945 bookmarks.setcurrent(repo, newact)
946 elif cur != tgt and newact == repo._bookmarkcurrent:
946 elif cur != tgt and newact == repo._bookmarkcurrent:
947 bookmarks.unsetcurrent(repo)
947 bookmarks.unsetcurrent(repo)
948 marks.write()
948 marks.write()
949
949
950 elif inactive:
950 elif inactive:
951 if len(marks) == 0:
951 if len(marks) == 0:
952 ui.status(_("no bookmarks set\n"))
952 ui.status(_("no bookmarks set\n"))
953 elif not repo._bookmarkcurrent:
953 elif not repo._bookmarkcurrent:
954 ui.status(_("no active bookmark\n"))
954 ui.status(_("no active bookmark\n"))
955 else:
955 else:
956 bookmarks.unsetcurrent(repo)
956 bookmarks.unsetcurrent(repo)
957 finally:
957 finally:
958 wlock.release()
958 wlock.release()
959 else: # show bookmarks
959 else: # show bookmarks
960 hexfn = ui.debugflag and hex or short
960 hexfn = ui.debugflag and hex or short
961 marks = repo._bookmarks
961 marks = repo._bookmarks
962 if len(marks) == 0:
962 if len(marks) == 0:
963 ui.status(_("no bookmarks set\n"))
963 ui.status(_("no bookmarks set\n"))
964 else:
964 else:
965 for bmark, n in sorted(marks.iteritems()):
965 for bmark, n in sorted(marks.iteritems()):
966 current = repo._bookmarkcurrent
966 current = repo._bookmarkcurrent
967 if bmark == current:
967 if bmark == current:
968 prefix, label = '*', 'bookmarks.current'
968 prefix, label = '*', 'bookmarks.current'
969 else:
969 else:
970 prefix, label = ' ', ''
970 prefix, label = ' ', ''
971
971
972 if ui.quiet:
972 if ui.quiet:
973 ui.write("%s\n" % bmark, label=label)
973 ui.write("%s\n" % bmark, label=label)
974 else:
974 else:
975 pad = " " * (25 - encoding.colwidth(bmark))
975 pad = " " * (25 - encoding.colwidth(bmark))
976 ui.write(" %s %s%s %d:%s\n" % (
976 ui.write(" %s %s%s %d:%s\n" % (
977 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
977 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
978 label=label)
978 label=label)
979
979
980 @command('branch',
980 @command('branch',
981 [('f', 'force', None,
981 [('f', 'force', None,
982 _('set branch name even if it shadows an existing branch')),
982 _('set branch name even if it shadows an existing branch')),
983 ('C', 'clean', None, _('reset branch name to parent branch name'))],
983 ('C', 'clean', None, _('reset branch name to parent branch name'))],
984 _('[-fC] [NAME]'))
984 _('[-fC] [NAME]'))
985 def branch(ui, repo, label=None, **opts):
985 def branch(ui, repo, label=None, **opts):
986 """set or show the current branch name
986 """set or show the current branch name
987
987
988 .. note::
988 .. note::
989
989
990 Branch names are permanent and global. Use :hg:`bookmark` to create a
990 Branch names are permanent and global. Use :hg:`bookmark` to create a
991 light-weight bookmark instead. See :hg:`help glossary` for more
991 light-weight bookmark instead. See :hg:`help glossary` for more
992 information about named branches and bookmarks.
992 information about named branches and bookmarks.
993
993
994 With no argument, show the current branch name. With one argument,
994 With no argument, show the current branch name. With one argument,
995 set the working directory branch name (the branch will not exist
995 set the working directory branch name (the branch will not exist
996 in the repository until the next commit). Standard practice
996 in the repository until the next commit). Standard practice
997 recommends that primary development take place on the 'default'
997 recommends that primary development take place on the 'default'
998 branch.
998 branch.
999
999
1000 Unless -f/--force is specified, branch will not let you set a
1000 Unless -f/--force is specified, branch will not let you set a
1001 branch name that already exists, even if it's inactive.
1001 branch name that already exists, even if it's inactive.
1002
1002
1003 Use -C/--clean to reset the working directory branch to that of
1003 Use -C/--clean to reset the working directory branch to that of
1004 the parent of the working directory, negating a previous branch
1004 the parent of the working directory, negating a previous branch
1005 change.
1005 change.
1006
1006
1007 Use the command :hg:`update` to switch to an existing branch. Use
1007 Use the command :hg:`update` to switch to an existing branch. Use
1008 :hg:`commit --close-branch` to mark this branch as closed.
1008 :hg:`commit --close-branch` to mark this branch as closed.
1009
1009
1010 Returns 0 on success.
1010 Returns 0 on success.
1011 """
1011 """
1012 if label:
1012 if label:
1013 label = label.strip()
1013 label = label.strip()
1014
1014
1015 if not opts.get('clean') and not label:
1015 if not opts.get('clean') and not label:
1016 ui.write("%s\n" % repo.dirstate.branch())
1016 ui.write("%s\n" % repo.dirstate.branch())
1017 return
1017 return
1018
1018
1019 wlock = repo.wlock()
1019 wlock = repo.wlock()
1020 try:
1020 try:
1021 if opts.get('clean'):
1021 if opts.get('clean'):
1022 label = repo[None].p1().branch()
1022 label = repo[None].p1().branch()
1023 repo.dirstate.setbranch(label)
1023 repo.dirstate.setbranch(label)
1024 ui.status(_('reset working directory to branch %s\n') % label)
1024 ui.status(_('reset working directory to branch %s\n') % label)
1025 elif label:
1025 elif label:
1026 if not opts.get('force') and label in repo.branchmap():
1026 if not opts.get('force') and label in repo.branchmap():
1027 if label not in [p.branch() for p in repo.parents()]:
1027 if label not in [p.branch() for p in repo.parents()]:
1028 raise util.Abort(_('a branch of the same name already'
1028 raise util.Abort(_('a branch of the same name already'
1029 ' exists'),
1029 ' exists'),
1030 # i18n: "it" refers to an existing branch
1030 # i18n: "it" refers to an existing branch
1031 hint=_("use 'hg update' to switch to it"))
1031 hint=_("use 'hg update' to switch to it"))
1032 scmutil.checknewlabel(repo, label, 'branch')
1032 scmutil.checknewlabel(repo, label, 'branch')
1033 repo.dirstate.setbranch(label)
1033 repo.dirstate.setbranch(label)
1034 ui.status(_('marked working directory as branch %s\n') % label)
1034 ui.status(_('marked working directory as branch %s\n') % label)
1035 ui.status(_('(branches are permanent and global, '
1035 ui.status(_('(branches are permanent and global, '
1036 'did you want a bookmark?)\n'))
1036 'did you want a bookmark?)\n'))
1037 finally:
1037 finally:
1038 wlock.release()
1038 wlock.release()
1039
1039
1040 @command('branches',
1040 @command('branches',
1041 [('a', 'active', False, _('show only branches that have unmerged heads')),
1041 [('a', 'active', False, _('show only branches that have unmerged heads')),
1042 ('c', 'closed', False, _('show normal and closed branches'))],
1042 ('c', 'closed', False, _('show normal and closed branches'))],
1043 _('[-ac]'))
1043 _('[-ac]'))
1044 def branches(ui, repo, active=False, closed=False):
1044 def branches(ui, repo, active=False, closed=False):
1045 """list repository named branches
1045 """list repository named branches
1046
1046
1047 List the repository's named branches, indicating which ones are
1047 List the repository's named branches, indicating which ones are
1048 inactive. If -c/--closed is specified, also list branches which have
1048 inactive. If -c/--closed is specified, also list branches which have
1049 been marked closed (see :hg:`commit --close-branch`).
1049 been marked closed (see :hg:`commit --close-branch`).
1050
1050
1051 If -a/--active is specified, only show active branches. A branch
1051 If -a/--active is specified, only show active branches. A branch
1052 is considered active if it contains repository heads.
1052 is considered active if it contains repository heads.
1053
1053
1054 Use the command :hg:`update` to switch to an existing branch.
1054 Use the command :hg:`update` to switch to an existing branch.
1055
1055
1056 Returns 0.
1056 Returns 0.
1057 """
1057 """
1058
1058
1059 hexfunc = ui.debugflag and hex or short
1059 hexfunc = ui.debugflag and hex or short
1060
1060
1061 allheads = set(repo.heads())
1061 allheads = set(repo.heads())
1062 branches = []
1062 branches = []
1063 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1063 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1064 isactive = not isclosed and bool(set(heads) & allheads)
1064 isactive = not isclosed and bool(set(heads) & allheads)
1065 branches.append((tag, repo[tip], isactive, not isclosed))
1065 branches.append((tag, repo[tip], isactive, not isclosed))
1066 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1066 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1067 reverse=True)
1067 reverse=True)
1068
1068
1069 for tag, ctx, isactive, isopen in branches:
1069 for tag, ctx, isactive, isopen in branches:
1070 if (not active) or isactive:
1070 if (not active) or isactive:
1071 if isactive:
1071 if isactive:
1072 label = 'branches.active'
1072 label = 'branches.active'
1073 notice = ''
1073 notice = ''
1074 elif not isopen:
1074 elif not isopen:
1075 if not closed:
1075 if not closed:
1076 continue
1076 continue
1077 label = 'branches.closed'
1077 label = 'branches.closed'
1078 notice = _(' (closed)')
1078 notice = _(' (closed)')
1079 else:
1079 else:
1080 label = 'branches.inactive'
1080 label = 'branches.inactive'
1081 notice = _(' (inactive)')
1081 notice = _(' (inactive)')
1082 if tag == repo.dirstate.branch():
1082 if tag == repo.dirstate.branch():
1083 label = 'branches.current'
1083 label = 'branches.current'
1084 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1084 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1085 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1085 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1086 'log.changeset changeset.%s' % ctx.phasestr())
1086 'log.changeset changeset.%s' % ctx.phasestr())
1087 labeledtag = ui.label(tag, label)
1087 labeledtag = ui.label(tag, label)
1088 if ui.quiet:
1088 if ui.quiet:
1089 ui.write("%s\n" % labeledtag)
1089 ui.write("%s\n" % labeledtag)
1090 else:
1090 else:
1091 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1091 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1092
1092
1093 @command('bundle',
1093 @command('bundle',
1094 [('f', 'force', None, _('run even when the destination is unrelated')),
1094 [('f', 'force', None, _('run even when the destination is unrelated')),
1095 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1095 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1096 _('REV')),
1096 _('REV')),
1097 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1097 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1098 _('BRANCH')),
1098 _('BRANCH')),
1099 ('', 'base', [],
1099 ('', 'base', [],
1100 _('a base changeset assumed to be available at the destination'),
1100 _('a base changeset assumed to be available at the destination'),
1101 _('REV')),
1101 _('REV')),
1102 ('a', 'all', None, _('bundle all changesets in the repository')),
1102 ('a', 'all', None, _('bundle all changesets in the repository')),
1103 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1103 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1104 ] + remoteopts,
1104 ] + remoteopts,
1105 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1105 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1106 def bundle(ui, repo, fname, dest=None, **opts):
1106 def bundle(ui, repo, fname, dest=None, **opts):
1107 """create a changegroup file
1107 """create a changegroup file
1108
1108
1109 Generate a compressed changegroup file collecting changesets not
1109 Generate a compressed changegroup file collecting changesets not
1110 known to be in another repository.
1110 known to be in another repository.
1111
1111
1112 If you omit the destination repository, then hg assumes the
1112 If you omit the destination repository, then hg assumes the
1113 destination will have all the nodes you specify with --base
1113 destination will have all the nodes you specify with --base
1114 parameters. To create a bundle containing all changesets, use
1114 parameters. To create a bundle containing all changesets, use
1115 -a/--all (or --base null).
1115 -a/--all (or --base null).
1116
1116
1117 You can change compression method with the -t/--type option.
1117 You can change compression method with the -t/--type option.
1118 The available compression methods are: none, bzip2, and
1118 The available compression methods are: none, bzip2, and
1119 gzip (by default, bundles are compressed using bzip2).
1119 gzip (by default, bundles are compressed using bzip2).
1120
1120
1121 The bundle file can then be transferred using conventional means
1121 The bundle file can then be transferred using conventional means
1122 and applied to another repository with the unbundle or pull
1122 and applied to another repository with the unbundle or pull
1123 command. This is useful when direct push and pull are not
1123 command. This is useful when direct push and pull are not
1124 available or when exporting an entire repository is undesirable.
1124 available or when exporting an entire repository is undesirable.
1125
1125
1126 Applying bundles preserves all changeset contents including
1126 Applying bundles preserves all changeset contents including
1127 permissions, copy/rename information, and revision history.
1127 permissions, copy/rename information, and revision history.
1128
1128
1129 Returns 0 on success, 1 if no changes found.
1129 Returns 0 on success, 1 if no changes found.
1130 """
1130 """
1131 revs = None
1131 revs = None
1132 if 'rev' in opts:
1132 if 'rev' in opts:
1133 revs = scmutil.revrange(repo, opts['rev'])
1133 revs = scmutil.revrange(repo, opts['rev'])
1134
1134
1135 bundletype = opts.get('type', 'bzip2').lower()
1135 bundletype = opts.get('type', 'bzip2').lower()
1136 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1136 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1137 bundletype = btypes.get(bundletype)
1137 bundletype = btypes.get(bundletype)
1138 if bundletype not in changegroup.bundletypes:
1138 if bundletype not in changegroup.bundletypes:
1139 raise util.Abort(_('unknown bundle type specified with --type'))
1139 raise util.Abort(_('unknown bundle type specified with --type'))
1140
1140
1141 if opts.get('all'):
1141 if opts.get('all'):
1142 base = ['null']
1142 base = ['null']
1143 else:
1143 else:
1144 base = scmutil.revrange(repo, opts.get('base'))
1144 base = scmutil.revrange(repo, opts.get('base'))
1145 # TODO: get desired bundlecaps from command line.
1145 # TODO: get desired bundlecaps from command line.
1146 bundlecaps = None
1146 bundlecaps = None
1147 if base:
1147 if base:
1148 if dest:
1148 if dest:
1149 raise util.Abort(_("--base is incompatible with specifying "
1149 raise util.Abort(_("--base is incompatible with specifying "
1150 "a destination"))
1150 "a destination"))
1151 common = [repo.lookup(rev) for rev in base]
1151 common = [repo.lookup(rev) for rev in base]
1152 heads = revs and map(repo.lookup, revs) or revs
1152 heads = revs and map(repo.lookup, revs) or revs
1153 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1153 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1154 bundlecaps=bundlecaps)
1154 bundlecaps=bundlecaps)
1155 outgoing = None
1155 outgoing = None
1156 else:
1156 else:
1157 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1157 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1158 dest, branches = hg.parseurl(dest, opts.get('branch'))
1158 dest, branches = hg.parseurl(dest, opts.get('branch'))
1159 other = hg.peer(repo, opts, dest)
1159 other = hg.peer(repo, opts, dest)
1160 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1160 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1161 heads = revs and map(repo.lookup, revs) or revs
1161 heads = revs and map(repo.lookup, revs) or revs
1162 outgoing = discovery.findcommonoutgoing(repo, other,
1162 outgoing = discovery.findcommonoutgoing(repo, other,
1163 onlyheads=heads,
1163 onlyheads=heads,
1164 force=opts.get('force'),
1164 force=opts.get('force'),
1165 portable=True)
1165 portable=True)
1166 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1166 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1167 if not cg:
1167 if not cg:
1168 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1168 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1169 return 1
1169 return 1
1170
1170
1171 changegroup.writebundle(cg, fname, bundletype)
1171 changegroup.writebundle(cg, fname, bundletype)
1172
1172
1173 @command('cat',
1173 @command('cat',
1174 [('o', 'output', '',
1174 [('o', 'output', '',
1175 _('print output to file with formatted name'), _('FORMAT')),
1175 _('print output to file with formatted name'), _('FORMAT')),
1176 ('r', 'rev', '', _('print the given revision'), _('REV')),
1176 ('r', 'rev', '', _('print the given revision'), _('REV')),
1177 ('', 'decode', None, _('apply any matching decode filter')),
1177 ('', 'decode', None, _('apply any matching decode filter')),
1178 ] + walkopts,
1178 ] + walkopts,
1179 _('[OPTION]... FILE...'))
1179 _('[OPTION]... FILE...'))
1180 def cat(ui, repo, file1, *pats, **opts):
1180 def cat(ui, repo, file1, *pats, **opts):
1181 """output the current or given revision of files
1181 """output the current or given revision of files
1182
1182
1183 Print the specified files as they were at the given revision. If
1183 Print the specified files as they were at the given revision. If
1184 no revision is given, the parent of the working directory is used.
1184 no revision is given, the parent of the working directory is used.
1185
1185
1186 Output may be to a file, in which case the name of the file is
1186 Output may be to a file, in which case the name of the file is
1187 given using a format string. The formatting rules as follows:
1187 given using a format string. The formatting rules as follows:
1188
1188
1189 :``%%``: literal "%" character
1189 :``%%``: literal "%" character
1190 :``%s``: basename of file being printed
1190 :``%s``: basename of file being printed
1191 :``%d``: dirname of file being printed, or '.' if in repository root
1191 :``%d``: dirname of file being printed, or '.' if in repository root
1192 :``%p``: root-relative path name of file being printed
1192 :``%p``: root-relative path name of file being printed
1193 :``%H``: changeset hash (40 hexadecimal digits)
1193 :``%H``: changeset hash (40 hexadecimal digits)
1194 :``%R``: changeset revision number
1194 :``%R``: changeset revision number
1195 :``%h``: short-form changeset hash (12 hexadecimal digits)
1195 :``%h``: short-form changeset hash (12 hexadecimal digits)
1196 :``%r``: zero-padded changeset revision number
1196 :``%r``: zero-padded changeset revision number
1197 :``%b``: basename of the exporting repository
1197 :``%b``: basename of the exporting repository
1198
1198
1199 Returns 0 on success.
1199 Returns 0 on success.
1200 """
1200 """
1201 ctx = scmutil.revsingle(repo, opts.get('rev'))
1201 ctx = scmutil.revsingle(repo, opts.get('rev'))
1202 m = scmutil.match(ctx, (file1,) + pats, opts)
1202 m = scmutil.match(ctx, (file1,) + pats, opts)
1203
1203
1204 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1204 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1205
1205
1206 @command('^clone',
1206 @command('^clone',
1207 [('U', 'noupdate', None,
1207 [('U', 'noupdate', None,
1208 _('the clone will include an empty working copy (only a repository)')),
1208 _('the clone will include an empty working copy (only a repository)')),
1209 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1209 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1210 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1210 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1211 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1211 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1212 ('', 'pull', None, _('use pull protocol to copy metadata')),
1212 ('', 'pull', None, _('use pull protocol to copy metadata')),
1213 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1213 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1214 ] + remoteopts,
1214 ] + remoteopts,
1215 _('[OPTION]... SOURCE [DEST]'))
1215 _('[OPTION]... SOURCE [DEST]'),
1216 norepo=True)
1216 def clone(ui, source, dest=None, **opts):
1217 def clone(ui, source, dest=None, **opts):
1217 """make a copy of an existing repository
1218 """make a copy of an existing repository
1218
1219
1219 Create a copy of an existing repository in a new directory.
1220 Create a copy of an existing repository in a new directory.
1220
1221
1221 If no destination directory name is specified, it defaults to the
1222 If no destination directory name is specified, it defaults to the
1222 basename of the source.
1223 basename of the source.
1223
1224
1224 The location of the source is added to the new repository's
1225 The location of the source is added to the new repository's
1225 ``.hg/hgrc`` file, as the default to be used for future pulls.
1226 ``.hg/hgrc`` file, as the default to be used for future pulls.
1226
1227
1227 Only local paths and ``ssh://`` URLs are supported as
1228 Only local paths and ``ssh://`` URLs are supported as
1228 destinations. For ``ssh://`` destinations, no working directory or
1229 destinations. For ``ssh://`` destinations, no working directory or
1229 ``.hg/hgrc`` will be created on the remote side.
1230 ``.hg/hgrc`` will be created on the remote side.
1230
1231
1231 To pull only a subset of changesets, specify one or more revisions
1232 To pull only a subset of changesets, specify one or more revisions
1232 identifiers with -r/--rev or branches with -b/--branch. The
1233 identifiers with -r/--rev or branches with -b/--branch. The
1233 resulting clone will contain only the specified changesets and
1234 resulting clone will contain only the specified changesets and
1234 their ancestors. These options (or 'clone src#rev dest') imply
1235 their ancestors. These options (or 'clone src#rev dest') imply
1235 --pull, even for local source repositories. Note that specifying a
1236 --pull, even for local source repositories. Note that specifying a
1236 tag will include the tagged changeset but not the changeset
1237 tag will include the tagged changeset but not the changeset
1237 containing the tag.
1238 containing the tag.
1238
1239
1239 If the source repository has a bookmark called '@' set, that
1240 If the source repository has a bookmark called '@' set, that
1240 revision will be checked out in the new repository by default.
1241 revision will be checked out in the new repository by default.
1241
1242
1242 To check out a particular version, use -u/--update, or
1243 To check out a particular version, use -u/--update, or
1243 -U/--noupdate to create a clone with no working directory.
1244 -U/--noupdate to create a clone with no working directory.
1244
1245
1245 .. container:: verbose
1246 .. container:: verbose
1246
1247
1247 For efficiency, hardlinks are used for cloning whenever the
1248 For efficiency, hardlinks are used for cloning whenever the
1248 source and destination are on the same filesystem (note this
1249 source and destination are on the same filesystem (note this
1249 applies only to the repository data, not to the working
1250 applies only to the repository data, not to the working
1250 directory). Some filesystems, such as AFS, implement hardlinking
1251 directory). Some filesystems, such as AFS, implement hardlinking
1251 incorrectly, but do not report errors. In these cases, use the
1252 incorrectly, but do not report errors. In these cases, use the
1252 --pull option to avoid hardlinking.
1253 --pull option to avoid hardlinking.
1253
1254
1254 In some cases, you can clone repositories and the working
1255 In some cases, you can clone repositories and the working
1255 directory using full hardlinks with ::
1256 directory using full hardlinks with ::
1256
1257
1257 $ cp -al REPO REPOCLONE
1258 $ cp -al REPO REPOCLONE
1258
1259
1259 This is the fastest way to clone, but it is not always safe. The
1260 This is the fastest way to clone, but it is not always safe. The
1260 operation is not atomic (making sure REPO is not modified during
1261 operation is not atomic (making sure REPO is not modified during
1261 the operation is up to you) and you have to make sure your
1262 the operation is up to you) and you have to make sure your
1262 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1263 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1263 so). Also, this is not compatible with certain extensions that
1264 so). Also, this is not compatible with certain extensions that
1264 place their metadata under the .hg directory, such as mq.
1265 place their metadata under the .hg directory, such as mq.
1265
1266
1266 Mercurial will update the working directory to the first applicable
1267 Mercurial will update the working directory to the first applicable
1267 revision from this list:
1268 revision from this list:
1268
1269
1269 a) null if -U or the source repository has no changesets
1270 a) null if -U or the source repository has no changesets
1270 b) if -u . and the source repository is local, the first parent of
1271 b) if -u . and the source repository is local, the first parent of
1271 the source repository's working directory
1272 the source repository's working directory
1272 c) the changeset specified with -u (if a branch name, this means the
1273 c) the changeset specified with -u (if a branch name, this means the
1273 latest head of that branch)
1274 latest head of that branch)
1274 d) the changeset specified with -r
1275 d) the changeset specified with -r
1275 e) the tipmost head specified with -b
1276 e) the tipmost head specified with -b
1276 f) the tipmost head specified with the url#branch source syntax
1277 f) the tipmost head specified with the url#branch source syntax
1277 g) the revision marked with the '@' bookmark, if present
1278 g) the revision marked with the '@' bookmark, if present
1278 h) the tipmost head of the default branch
1279 h) the tipmost head of the default branch
1279 i) tip
1280 i) tip
1280
1281
1281 Examples:
1282 Examples:
1282
1283
1283 - clone a remote repository to a new directory named hg/::
1284 - clone a remote repository to a new directory named hg/::
1284
1285
1285 hg clone http://selenic.com/hg
1286 hg clone http://selenic.com/hg
1286
1287
1287 - create a lightweight local clone::
1288 - create a lightweight local clone::
1288
1289
1289 hg clone project/ project-feature/
1290 hg clone project/ project-feature/
1290
1291
1291 - clone from an absolute path on an ssh server (note double-slash)::
1292 - clone from an absolute path on an ssh server (note double-slash)::
1292
1293
1293 hg clone ssh://user@server//home/projects/alpha/
1294 hg clone ssh://user@server//home/projects/alpha/
1294
1295
1295 - do a high-speed clone over a LAN while checking out a
1296 - do a high-speed clone over a LAN while checking out a
1296 specified version::
1297 specified version::
1297
1298
1298 hg clone --uncompressed http://server/repo -u 1.5
1299 hg clone --uncompressed http://server/repo -u 1.5
1299
1300
1300 - create a repository without changesets after a particular revision::
1301 - create a repository without changesets after a particular revision::
1301
1302
1302 hg clone -r 04e544 experimental/ good/
1303 hg clone -r 04e544 experimental/ good/
1303
1304
1304 - clone (and track) a particular named branch::
1305 - clone (and track) a particular named branch::
1305
1306
1306 hg clone http://selenic.com/hg#stable
1307 hg clone http://selenic.com/hg#stable
1307
1308
1308 See :hg:`help urls` for details on specifying URLs.
1309 See :hg:`help urls` for details on specifying URLs.
1309
1310
1310 Returns 0 on success.
1311 Returns 0 on success.
1311 """
1312 """
1312 if opts.get('noupdate') and opts.get('updaterev'):
1313 if opts.get('noupdate') and opts.get('updaterev'):
1313 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1314 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1314
1315
1315 r = hg.clone(ui, opts, source, dest,
1316 r = hg.clone(ui, opts, source, dest,
1316 pull=opts.get('pull'),
1317 pull=opts.get('pull'),
1317 stream=opts.get('uncompressed'),
1318 stream=opts.get('uncompressed'),
1318 rev=opts.get('rev'),
1319 rev=opts.get('rev'),
1319 update=opts.get('updaterev') or not opts.get('noupdate'),
1320 update=opts.get('updaterev') or not opts.get('noupdate'),
1320 branch=opts.get('branch'))
1321 branch=opts.get('branch'))
1321
1322
1322 return r is None
1323 return r is None
1323
1324
1324 @command('^commit|ci',
1325 @command('^commit|ci',
1325 [('A', 'addremove', None,
1326 [('A', 'addremove', None,
1326 _('mark new/missing files as added/removed before committing')),
1327 _('mark new/missing files as added/removed before committing')),
1327 ('', 'close-branch', None,
1328 ('', 'close-branch', None,
1328 _('mark a branch as closed, hiding it from the branch list')),
1329 _('mark a branch as closed, hiding it from the branch list')),
1329 ('', 'amend', None, _('amend the parent of the working dir')),
1330 ('', 'amend', None, _('amend the parent of the working dir')),
1330 ('s', 'secret', None, _('use the secret phase for committing')),
1331 ('s', 'secret', None, _('use the secret phase for committing')),
1331 ('e', 'edit', None,
1332 ('e', 'edit', None,
1332 _('further edit commit message already specified')),
1333 _('further edit commit message already specified')),
1333 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1334 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1334 _('[OPTION]... [FILE]...'))
1335 _('[OPTION]... [FILE]...'))
1335 def commit(ui, repo, *pats, **opts):
1336 def commit(ui, repo, *pats, **opts):
1336 """commit the specified files or all outstanding changes
1337 """commit the specified files or all outstanding changes
1337
1338
1338 Commit changes to the given files into the repository. Unlike a
1339 Commit changes to the given files into the repository. Unlike a
1339 centralized SCM, this operation is a local operation. See
1340 centralized SCM, this operation is a local operation. See
1340 :hg:`push` for a way to actively distribute your changes.
1341 :hg:`push` for a way to actively distribute your changes.
1341
1342
1342 If a list of files is omitted, all changes reported by :hg:`status`
1343 If a list of files is omitted, all changes reported by :hg:`status`
1343 will be committed.
1344 will be committed.
1344
1345
1345 If you are committing the result of a merge, do not provide any
1346 If you are committing the result of a merge, do not provide any
1346 filenames or -I/-X filters.
1347 filenames or -I/-X filters.
1347
1348
1348 If no commit message is specified, Mercurial starts your
1349 If no commit message is specified, Mercurial starts your
1349 configured editor where you can enter a message. In case your
1350 configured editor where you can enter a message. In case your
1350 commit fails, you will find a backup of your message in
1351 commit fails, you will find a backup of your message in
1351 ``.hg/last-message.txt``.
1352 ``.hg/last-message.txt``.
1352
1353
1353 The --amend flag can be used to amend the parent of the
1354 The --amend flag can be used to amend the parent of the
1354 working directory with a new commit that contains the changes
1355 working directory with a new commit that contains the changes
1355 in the parent in addition to those currently reported by :hg:`status`,
1356 in the parent in addition to those currently reported by :hg:`status`,
1356 if there are any. The old commit is stored in a backup bundle in
1357 if there are any. The old commit is stored in a backup bundle in
1357 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1358 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1358 on how to restore it).
1359 on how to restore it).
1359
1360
1360 Message, user and date are taken from the amended commit unless
1361 Message, user and date are taken from the amended commit unless
1361 specified. When a message isn't specified on the command line,
1362 specified. When a message isn't specified on the command line,
1362 the editor will open with the message of the amended commit.
1363 the editor will open with the message of the amended commit.
1363
1364
1364 It is not possible to amend public changesets (see :hg:`help phases`)
1365 It is not possible to amend public changesets (see :hg:`help phases`)
1365 or changesets that have children.
1366 or changesets that have children.
1366
1367
1367 See :hg:`help dates` for a list of formats valid for -d/--date.
1368 See :hg:`help dates` for a list of formats valid for -d/--date.
1368
1369
1369 Returns 0 on success, 1 if nothing changed.
1370 Returns 0 on success, 1 if nothing changed.
1370 """
1371 """
1371 if opts.get('subrepos'):
1372 if opts.get('subrepos'):
1372 if opts.get('amend'):
1373 if opts.get('amend'):
1373 raise util.Abort(_('cannot amend with --subrepos'))
1374 raise util.Abort(_('cannot amend with --subrepos'))
1374 # Let --subrepos on the command line override config setting.
1375 # Let --subrepos on the command line override config setting.
1375 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1376 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1376
1377
1377 # Save this for restoring it later
1378 # Save this for restoring it later
1378 oldcommitphase = ui.config('phases', 'new-commit')
1379 oldcommitphase = ui.config('phases', 'new-commit')
1379
1380
1380 cmdutil.checkunfinished(repo, commit=True)
1381 cmdutil.checkunfinished(repo, commit=True)
1381
1382
1382 branch = repo[None].branch()
1383 branch = repo[None].branch()
1383 bheads = repo.branchheads(branch)
1384 bheads = repo.branchheads(branch)
1384
1385
1385 extra = {}
1386 extra = {}
1386 if opts.get('close_branch'):
1387 if opts.get('close_branch'):
1387 extra['close'] = 1
1388 extra['close'] = 1
1388
1389
1389 if not bheads:
1390 if not bheads:
1390 raise util.Abort(_('can only close branch heads'))
1391 raise util.Abort(_('can only close branch heads'))
1391 elif opts.get('amend'):
1392 elif opts.get('amend'):
1392 if repo.parents()[0].p1().branch() != branch and \
1393 if repo.parents()[0].p1().branch() != branch and \
1393 repo.parents()[0].p2().branch() != branch:
1394 repo.parents()[0].p2().branch() != branch:
1394 raise util.Abort(_('can only close branch heads'))
1395 raise util.Abort(_('can only close branch heads'))
1395
1396
1396 if opts.get('amend'):
1397 if opts.get('amend'):
1397 if ui.configbool('ui', 'commitsubrepos'):
1398 if ui.configbool('ui', 'commitsubrepos'):
1398 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1399 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1399
1400
1400 old = repo['.']
1401 old = repo['.']
1401 if old.phase() == phases.public:
1402 if old.phase() == phases.public:
1402 raise util.Abort(_('cannot amend public changesets'))
1403 raise util.Abort(_('cannot amend public changesets'))
1403 if len(repo[None].parents()) > 1:
1404 if len(repo[None].parents()) > 1:
1404 raise util.Abort(_('cannot amend while merging'))
1405 raise util.Abort(_('cannot amend while merging'))
1405 if (not obsolete._enabled) and old.children():
1406 if (not obsolete._enabled) and old.children():
1406 raise util.Abort(_('cannot amend changeset with children'))
1407 raise util.Abort(_('cannot amend changeset with children'))
1407
1408
1408 # commitfunc is used only for temporary amend commit by cmdutil.amend
1409 # commitfunc is used only for temporary amend commit by cmdutil.amend
1409 def commitfunc(ui, repo, message, match, opts):
1410 def commitfunc(ui, repo, message, match, opts):
1410 return repo.commit(message,
1411 return repo.commit(message,
1411 opts.get('user') or old.user(),
1412 opts.get('user') or old.user(),
1412 opts.get('date') or old.date(),
1413 opts.get('date') or old.date(),
1413 match,
1414 match,
1414 extra=extra)
1415 extra=extra)
1415
1416
1416 current = repo._bookmarkcurrent
1417 current = repo._bookmarkcurrent
1417 marks = old.bookmarks()
1418 marks = old.bookmarks()
1418 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1419 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1419 if node == old.node():
1420 if node == old.node():
1420 ui.status(_("nothing changed\n"))
1421 ui.status(_("nothing changed\n"))
1421 return 1
1422 return 1
1422 elif marks:
1423 elif marks:
1423 ui.debug('moving bookmarks %r from %s to %s\n' %
1424 ui.debug('moving bookmarks %r from %s to %s\n' %
1424 (marks, old.hex(), hex(node)))
1425 (marks, old.hex(), hex(node)))
1425 newmarks = repo._bookmarks
1426 newmarks = repo._bookmarks
1426 for bm in marks:
1427 for bm in marks:
1427 newmarks[bm] = node
1428 newmarks[bm] = node
1428 if bm == current:
1429 if bm == current:
1429 bookmarks.setcurrent(repo, bm)
1430 bookmarks.setcurrent(repo, bm)
1430 newmarks.write()
1431 newmarks.write()
1431 else:
1432 else:
1432 def commitfunc(ui, repo, message, match, opts):
1433 def commitfunc(ui, repo, message, match, opts):
1433 try:
1434 try:
1434 if opts.get('secret'):
1435 if opts.get('secret'):
1435 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1436 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1436 # Propagate to subrepos
1437 # Propagate to subrepos
1437 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1438 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1438 'commit')
1439 'commit')
1439
1440
1440 return repo.commit(message, opts.get('user'), opts.get('date'),
1441 return repo.commit(message, opts.get('user'), opts.get('date'),
1441 match,
1442 match,
1442 editor=cmdutil.getcommiteditor(**opts),
1443 editor=cmdutil.getcommiteditor(**opts),
1443 extra=extra)
1444 extra=extra)
1444 finally:
1445 finally:
1445 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1446 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1446 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1447 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1447 'commit')
1448 'commit')
1448
1449
1449
1450
1450 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1451 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1451
1452
1452 if not node:
1453 if not node:
1453 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1454 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1454 if stat[3]:
1455 if stat[3]:
1455 ui.status(_("nothing changed (%d missing files, see "
1456 ui.status(_("nothing changed (%d missing files, see "
1456 "'hg status')\n") % len(stat[3]))
1457 "'hg status')\n") % len(stat[3]))
1457 else:
1458 else:
1458 ui.status(_("nothing changed\n"))
1459 ui.status(_("nothing changed\n"))
1459 return 1
1460 return 1
1460
1461
1461 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1462 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1462
1463
1463 @command('config|showconfig|debugconfig',
1464 @command('config|showconfig|debugconfig',
1464 [('u', 'untrusted', None, _('show untrusted configuration options')),
1465 [('u', 'untrusted', None, _('show untrusted configuration options')),
1465 ('e', 'edit', None, _('edit user config')),
1466 ('e', 'edit', None, _('edit user config')),
1466 ('l', 'local', None, _('edit repository config')),
1467 ('l', 'local', None, _('edit repository config')),
1467 ('g', 'global', None, _('edit global config'))],
1468 ('g', 'global', None, _('edit global config'))],
1468 _('[-u] [NAME]...'))
1469 _('[-u] [NAME]...'))
1469 def config(ui, repo, *values, **opts):
1470 def config(ui, repo, *values, **opts):
1470 """show combined config settings from all hgrc files
1471 """show combined config settings from all hgrc files
1471
1472
1472 With no arguments, print names and values of all config items.
1473 With no arguments, print names and values of all config items.
1473
1474
1474 With one argument of the form section.name, print just the value
1475 With one argument of the form section.name, print just the value
1475 of that config item.
1476 of that config item.
1476
1477
1477 With multiple arguments, print names and values of all config
1478 With multiple arguments, print names and values of all config
1478 items with matching section names.
1479 items with matching section names.
1479
1480
1480 With --edit, start an editor on the user-level config file. With
1481 With --edit, start an editor on the user-level config file. With
1481 --global, edit the system-wide config file. With --local, edit the
1482 --global, edit the system-wide config file. With --local, edit the
1482 repository-level config file.
1483 repository-level config file.
1483
1484
1484 With --debug, the source (filename and line number) is printed
1485 With --debug, the source (filename and line number) is printed
1485 for each config item.
1486 for each config item.
1486
1487
1487 See :hg:`help config` for more information about config files.
1488 See :hg:`help config` for more information about config files.
1488
1489
1489 Returns 0 on success.
1490 Returns 0 on success.
1490
1491
1491 """
1492 """
1492
1493
1493 if opts.get('edit') or opts.get('local') or opts.get('global'):
1494 if opts.get('edit') or opts.get('local') or opts.get('global'):
1494 if opts.get('local') and opts.get('global'):
1495 if opts.get('local') and opts.get('global'):
1495 raise util.Abort(_("can't use --local and --global together"))
1496 raise util.Abort(_("can't use --local and --global together"))
1496
1497
1497 if opts.get('local'):
1498 if opts.get('local'):
1498 if not repo:
1499 if not repo:
1499 raise util.Abort(_("can't use --local outside a repository"))
1500 raise util.Abort(_("can't use --local outside a repository"))
1500 paths = [repo.join('hgrc')]
1501 paths = [repo.join('hgrc')]
1501 elif opts.get('global'):
1502 elif opts.get('global'):
1502 paths = scmutil.systemrcpath()
1503 paths = scmutil.systemrcpath()
1503 else:
1504 else:
1504 paths = scmutil.userrcpath()
1505 paths = scmutil.userrcpath()
1505
1506
1506 for f in paths:
1507 for f in paths:
1507 if os.path.exists(f):
1508 if os.path.exists(f):
1508 break
1509 break
1509 else:
1510 else:
1510 f = paths[0]
1511 f = paths[0]
1511 fp = open(f, "w")
1512 fp = open(f, "w")
1512 fp.write(
1513 fp.write(
1513 '# example config (see "hg help config" for more info)\n'
1514 '# example config (see "hg help config" for more info)\n'
1514 '\n'
1515 '\n'
1515 '[ui]\n'
1516 '[ui]\n'
1516 '# name and email, e.g.\n'
1517 '# name and email, e.g.\n'
1517 '# username = Jane Doe <jdoe@example.com>\n'
1518 '# username = Jane Doe <jdoe@example.com>\n'
1518 'username =\n'
1519 'username =\n'
1519 '\n'
1520 '\n'
1520 '[extensions]\n'
1521 '[extensions]\n'
1521 '# uncomment these lines to enable some popular extensions\n'
1522 '# uncomment these lines to enable some popular extensions\n'
1522 '# (see "hg help extensions" for more info)\n'
1523 '# (see "hg help extensions" for more info)\n'
1523 '# pager =\n'
1524 '# pager =\n'
1524 '# progress =\n'
1525 '# progress =\n'
1525 '# color =\n')
1526 '# color =\n')
1526 fp.close()
1527 fp.close()
1527
1528
1528 editor = ui.geteditor()
1529 editor = ui.geteditor()
1529 util.system("%s \"%s\"" % (editor, f),
1530 util.system("%s \"%s\"" % (editor, f),
1530 onerr=util.Abort, errprefix=_("edit failed"),
1531 onerr=util.Abort, errprefix=_("edit failed"),
1531 out=ui.fout)
1532 out=ui.fout)
1532 return
1533 return
1533
1534
1534 for f in scmutil.rcpath():
1535 for f in scmutil.rcpath():
1535 ui.debug('read config from: %s\n' % f)
1536 ui.debug('read config from: %s\n' % f)
1536 untrusted = bool(opts.get('untrusted'))
1537 untrusted = bool(opts.get('untrusted'))
1537 if values:
1538 if values:
1538 sections = [v for v in values if '.' not in v]
1539 sections = [v for v in values if '.' not in v]
1539 items = [v for v in values if '.' in v]
1540 items = [v for v in values if '.' in v]
1540 if len(items) > 1 or items and sections:
1541 if len(items) > 1 or items and sections:
1541 raise util.Abort(_('only one config item permitted'))
1542 raise util.Abort(_('only one config item permitted'))
1542 for section, name, value in ui.walkconfig(untrusted=untrusted):
1543 for section, name, value in ui.walkconfig(untrusted=untrusted):
1543 value = str(value).replace('\n', '\\n')
1544 value = str(value).replace('\n', '\\n')
1544 sectname = section + '.' + name
1545 sectname = section + '.' + name
1545 if values:
1546 if values:
1546 for v in values:
1547 for v in values:
1547 if v == section:
1548 if v == section:
1548 ui.debug('%s: ' %
1549 ui.debug('%s: ' %
1549 ui.configsource(section, name, untrusted))
1550 ui.configsource(section, name, untrusted))
1550 ui.write('%s=%s\n' % (sectname, value))
1551 ui.write('%s=%s\n' % (sectname, value))
1551 elif v == sectname:
1552 elif v == sectname:
1552 ui.debug('%s: ' %
1553 ui.debug('%s: ' %
1553 ui.configsource(section, name, untrusted))
1554 ui.configsource(section, name, untrusted))
1554 ui.write(value, '\n')
1555 ui.write(value, '\n')
1555 else:
1556 else:
1556 ui.debug('%s: ' %
1557 ui.debug('%s: ' %
1557 ui.configsource(section, name, untrusted))
1558 ui.configsource(section, name, untrusted))
1558 ui.write('%s=%s\n' % (sectname, value))
1559 ui.write('%s=%s\n' % (sectname, value))
1559
1560
1560 @command('copy|cp',
1561 @command('copy|cp',
1561 [('A', 'after', None, _('record a copy that has already occurred')),
1562 [('A', 'after', None, _('record a copy that has already occurred')),
1562 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1563 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1563 ] + walkopts + dryrunopts,
1564 ] + walkopts + dryrunopts,
1564 _('[OPTION]... [SOURCE]... DEST'))
1565 _('[OPTION]... [SOURCE]... DEST'))
1565 def copy(ui, repo, *pats, **opts):
1566 def copy(ui, repo, *pats, **opts):
1566 """mark files as copied for the next commit
1567 """mark files as copied for the next commit
1567
1568
1568 Mark dest as having copies of source files. If dest is a
1569 Mark dest as having copies of source files. If dest is a
1569 directory, copies are put in that directory. If dest is a file,
1570 directory, copies are put in that directory. If dest is a file,
1570 the source must be a single file.
1571 the source must be a single file.
1571
1572
1572 By default, this command copies the contents of files as they
1573 By default, this command copies the contents of files as they
1573 exist in the working directory. If invoked with -A/--after, the
1574 exist in the working directory. If invoked with -A/--after, the
1574 operation is recorded, but no copying is performed.
1575 operation is recorded, but no copying is performed.
1575
1576
1576 This command takes effect with the next commit. To undo a copy
1577 This command takes effect with the next commit. To undo a copy
1577 before that, see :hg:`revert`.
1578 before that, see :hg:`revert`.
1578
1579
1579 Returns 0 on success, 1 if errors are encountered.
1580 Returns 0 on success, 1 if errors are encountered.
1580 """
1581 """
1581 wlock = repo.wlock(False)
1582 wlock = repo.wlock(False)
1582 try:
1583 try:
1583 return cmdutil.copy(ui, repo, pats, opts)
1584 return cmdutil.copy(ui, repo, pats, opts)
1584 finally:
1585 finally:
1585 wlock.release()
1586 wlock.release()
1586
1587
1587 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1588 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1588 def debugancestor(ui, repo, *args):
1589 def debugancestor(ui, repo, *args):
1589 """find the ancestor revision of two revisions in a given index"""
1590 """find the ancestor revision of two revisions in a given index"""
1590 if len(args) == 3:
1591 if len(args) == 3:
1591 index, rev1, rev2 = args
1592 index, rev1, rev2 = args
1592 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1593 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1593 lookup = r.lookup
1594 lookup = r.lookup
1594 elif len(args) == 2:
1595 elif len(args) == 2:
1595 if not repo:
1596 if not repo:
1596 raise util.Abort(_("there is no Mercurial repository here "
1597 raise util.Abort(_("there is no Mercurial repository here "
1597 "(.hg not found)"))
1598 "(.hg not found)"))
1598 rev1, rev2 = args
1599 rev1, rev2 = args
1599 r = repo.changelog
1600 r = repo.changelog
1600 lookup = repo.lookup
1601 lookup = repo.lookup
1601 else:
1602 else:
1602 raise util.Abort(_('either two or three arguments required'))
1603 raise util.Abort(_('either two or three arguments required'))
1603 a = r.ancestor(lookup(rev1), lookup(rev2))
1604 a = r.ancestor(lookup(rev1), lookup(rev2))
1604 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1605 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1605
1606
1606 @command('debugbuilddag',
1607 @command('debugbuilddag',
1607 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1608 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1608 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1609 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1609 ('n', 'new-file', None, _('add new file at each rev'))],
1610 ('n', 'new-file', None, _('add new file at each rev'))],
1610 _('[OPTION]... [TEXT]'))
1611 _('[OPTION]... [TEXT]'))
1611 def debugbuilddag(ui, repo, text=None,
1612 def debugbuilddag(ui, repo, text=None,
1612 mergeable_file=False,
1613 mergeable_file=False,
1613 overwritten_file=False,
1614 overwritten_file=False,
1614 new_file=False):
1615 new_file=False):
1615 """builds a repo with a given DAG from scratch in the current empty repo
1616 """builds a repo with a given DAG from scratch in the current empty repo
1616
1617
1617 The description of the DAG is read from stdin if not given on the
1618 The description of the DAG is read from stdin if not given on the
1618 command line.
1619 command line.
1619
1620
1620 Elements:
1621 Elements:
1621
1622
1622 - "+n" is a linear run of n nodes based on the current default parent
1623 - "+n" is a linear run of n nodes based on the current default parent
1623 - "." is a single node based on the current default parent
1624 - "." is a single node based on the current default parent
1624 - "$" resets the default parent to null (implied at the start);
1625 - "$" resets the default parent to null (implied at the start);
1625 otherwise the default parent is always the last node created
1626 otherwise the default parent is always the last node created
1626 - "<p" sets the default parent to the backref p
1627 - "<p" sets the default parent to the backref p
1627 - "*p" is a fork at parent p, which is a backref
1628 - "*p" is a fork at parent p, which is a backref
1628 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1629 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1629 - "/p2" is a merge of the preceding node and p2
1630 - "/p2" is a merge of the preceding node and p2
1630 - ":tag" defines a local tag for the preceding node
1631 - ":tag" defines a local tag for the preceding node
1631 - "@branch" sets the named branch for subsequent nodes
1632 - "@branch" sets the named branch for subsequent nodes
1632 - "#...\\n" is a comment up to the end of the line
1633 - "#...\\n" is a comment up to the end of the line
1633
1634
1634 Whitespace between the above elements is ignored.
1635 Whitespace between the above elements is ignored.
1635
1636
1636 A backref is either
1637 A backref is either
1637
1638
1638 - a number n, which references the node curr-n, where curr is the current
1639 - a number n, which references the node curr-n, where curr is the current
1639 node, or
1640 node, or
1640 - the name of a local tag you placed earlier using ":tag", or
1641 - the name of a local tag you placed earlier using ":tag", or
1641 - empty to denote the default parent.
1642 - empty to denote the default parent.
1642
1643
1643 All string valued-elements are either strictly alphanumeric, or must
1644 All string valued-elements are either strictly alphanumeric, or must
1644 be enclosed in double quotes ("..."), with "\\" as escape character.
1645 be enclosed in double quotes ("..."), with "\\" as escape character.
1645 """
1646 """
1646
1647
1647 if text is None:
1648 if text is None:
1648 ui.status(_("reading DAG from stdin\n"))
1649 ui.status(_("reading DAG from stdin\n"))
1649 text = ui.fin.read()
1650 text = ui.fin.read()
1650
1651
1651 cl = repo.changelog
1652 cl = repo.changelog
1652 if len(cl) > 0:
1653 if len(cl) > 0:
1653 raise util.Abort(_('repository is not empty'))
1654 raise util.Abort(_('repository is not empty'))
1654
1655
1655 # determine number of revs in DAG
1656 # determine number of revs in DAG
1656 total = 0
1657 total = 0
1657 for type, data in dagparser.parsedag(text):
1658 for type, data in dagparser.parsedag(text):
1658 if type == 'n':
1659 if type == 'n':
1659 total += 1
1660 total += 1
1660
1661
1661 if mergeable_file:
1662 if mergeable_file:
1662 linesperrev = 2
1663 linesperrev = 2
1663 # make a file with k lines per rev
1664 # make a file with k lines per rev
1664 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1665 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1665 initialmergedlines.append("")
1666 initialmergedlines.append("")
1666
1667
1667 tags = []
1668 tags = []
1668
1669
1669 lock = tr = None
1670 lock = tr = None
1670 try:
1671 try:
1671 lock = repo.lock()
1672 lock = repo.lock()
1672 tr = repo.transaction("builddag")
1673 tr = repo.transaction("builddag")
1673
1674
1674 at = -1
1675 at = -1
1675 atbranch = 'default'
1676 atbranch = 'default'
1676 nodeids = []
1677 nodeids = []
1677 id = 0
1678 id = 0
1678 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1679 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1679 for type, data in dagparser.parsedag(text):
1680 for type, data in dagparser.parsedag(text):
1680 if type == 'n':
1681 if type == 'n':
1681 ui.note(('node %s\n' % str(data)))
1682 ui.note(('node %s\n' % str(data)))
1682 id, ps = data
1683 id, ps = data
1683
1684
1684 files = []
1685 files = []
1685 fctxs = {}
1686 fctxs = {}
1686
1687
1687 p2 = None
1688 p2 = None
1688 if mergeable_file:
1689 if mergeable_file:
1689 fn = "mf"
1690 fn = "mf"
1690 p1 = repo[ps[0]]
1691 p1 = repo[ps[0]]
1691 if len(ps) > 1:
1692 if len(ps) > 1:
1692 p2 = repo[ps[1]]
1693 p2 = repo[ps[1]]
1693 pa = p1.ancestor(p2)
1694 pa = p1.ancestor(p2)
1694 base, local, other = [x[fn].data() for x in (pa, p1,
1695 base, local, other = [x[fn].data() for x in (pa, p1,
1695 p2)]
1696 p2)]
1696 m3 = simplemerge.Merge3Text(base, local, other)
1697 m3 = simplemerge.Merge3Text(base, local, other)
1697 ml = [l.strip() for l in m3.merge_lines()]
1698 ml = [l.strip() for l in m3.merge_lines()]
1698 ml.append("")
1699 ml.append("")
1699 elif at > 0:
1700 elif at > 0:
1700 ml = p1[fn].data().split("\n")
1701 ml = p1[fn].data().split("\n")
1701 else:
1702 else:
1702 ml = initialmergedlines
1703 ml = initialmergedlines
1703 ml[id * linesperrev] += " r%i" % id
1704 ml[id * linesperrev] += " r%i" % id
1704 mergedtext = "\n".join(ml)
1705 mergedtext = "\n".join(ml)
1705 files.append(fn)
1706 files.append(fn)
1706 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1707 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1707
1708
1708 if overwritten_file:
1709 if overwritten_file:
1709 fn = "of"
1710 fn = "of"
1710 files.append(fn)
1711 files.append(fn)
1711 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1712 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1712
1713
1713 if new_file:
1714 if new_file:
1714 fn = "nf%i" % id
1715 fn = "nf%i" % id
1715 files.append(fn)
1716 files.append(fn)
1716 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1717 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1717 if len(ps) > 1:
1718 if len(ps) > 1:
1718 if not p2:
1719 if not p2:
1719 p2 = repo[ps[1]]
1720 p2 = repo[ps[1]]
1720 for fn in p2:
1721 for fn in p2:
1721 if fn.startswith("nf"):
1722 if fn.startswith("nf"):
1722 files.append(fn)
1723 files.append(fn)
1723 fctxs[fn] = p2[fn]
1724 fctxs[fn] = p2[fn]
1724
1725
1725 def fctxfn(repo, cx, path):
1726 def fctxfn(repo, cx, path):
1726 return fctxs.get(path)
1727 return fctxs.get(path)
1727
1728
1728 if len(ps) == 0 or ps[0] < 0:
1729 if len(ps) == 0 or ps[0] < 0:
1729 pars = [None, None]
1730 pars = [None, None]
1730 elif len(ps) == 1:
1731 elif len(ps) == 1:
1731 pars = [nodeids[ps[0]], None]
1732 pars = [nodeids[ps[0]], None]
1732 else:
1733 else:
1733 pars = [nodeids[p] for p in ps]
1734 pars = [nodeids[p] for p in ps]
1734 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1735 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1735 date=(id, 0),
1736 date=(id, 0),
1736 user="debugbuilddag",
1737 user="debugbuilddag",
1737 extra={'branch': atbranch})
1738 extra={'branch': atbranch})
1738 nodeid = repo.commitctx(cx)
1739 nodeid = repo.commitctx(cx)
1739 nodeids.append(nodeid)
1740 nodeids.append(nodeid)
1740 at = id
1741 at = id
1741 elif type == 'l':
1742 elif type == 'l':
1742 id, name = data
1743 id, name = data
1743 ui.note(('tag %s\n' % name))
1744 ui.note(('tag %s\n' % name))
1744 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1745 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1745 elif type == 'a':
1746 elif type == 'a':
1746 ui.note(('branch %s\n' % data))
1747 ui.note(('branch %s\n' % data))
1747 atbranch = data
1748 atbranch = data
1748 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1749 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1749 tr.close()
1750 tr.close()
1750
1751
1751 if tags:
1752 if tags:
1752 repo.opener.write("localtags", "".join(tags))
1753 repo.opener.write("localtags", "".join(tags))
1753 finally:
1754 finally:
1754 ui.progress(_('building'), None)
1755 ui.progress(_('building'), None)
1755 release(tr, lock)
1756 release(tr, lock)
1756
1757
1757 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1758 @command('debugbundle',
1759 [('a', 'all', None, _('show all details'))],
1760 _('FILE'),
1761 norepo=True)
1758 def debugbundle(ui, bundlepath, all=None, **opts):
1762 def debugbundle(ui, bundlepath, all=None, **opts):
1759 """lists the contents of a bundle"""
1763 """lists the contents of a bundle"""
1760 f = hg.openpath(ui, bundlepath)
1764 f = hg.openpath(ui, bundlepath)
1761 try:
1765 try:
1762 gen = exchange.readbundle(ui, f, bundlepath)
1766 gen = exchange.readbundle(ui, f, bundlepath)
1763 if all:
1767 if all:
1764 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1768 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1765
1769
1766 def showchunks(named):
1770 def showchunks(named):
1767 ui.write("\n%s\n" % named)
1771 ui.write("\n%s\n" % named)
1768 chain = None
1772 chain = None
1769 while True:
1773 while True:
1770 chunkdata = gen.deltachunk(chain)
1774 chunkdata = gen.deltachunk(chain)
1771 if not chunkdata:
1775 if not chunkdata:
1772 break
1776 break
1773 node = chunkdata['node']
1777 node = chunkdata['node']
1774 p1 = chunkdata['p1']
1778 p1 = chunkdata['p1']
1775 p2 = chunkdata['p2']
1779 p2 = chunkdata['p2']
1776 cs = chunkdata['cs']
1780 cs = chunkdata['cs']
1777 deltabase = chunkdata['deltabase']
1781 deltabase = chunkdata['deltabase']
1778 delta = chunkdata['delta']
1782 delta = chunkdata['delta']
1779 ui.write("%s %s %s %s %s %s\n" %
1783 ui.write("%s %s %s %s %s %s\n" %
1780 (hex(node), hex(p1), hex(p2),
1784 (hex(node), hex(p1), hex(p2),
1781 hex(cs), hex(deltabase), len(delta)))
1785 hex(cs), hex(deltabase), len(delta)))
1782 chain = node
1786 chain = node
1783
1787
1784 chunkdata = gen.changelogheader()
1788 chunkdata = gen.changelogheader()
1785 showchunks("changelog")
1789 showchunks("changelog")
1786 chunkdata = gen.manifestheader()
1790 chunkdata = gen.manifestheader()
1787 showchunks("manifest")
1791 showchunks("manifest")
1788 while True:
1792 while True:
1789 chunkdata = gen.filelogheader()
1793 chunkdata = gen.filelogheader()
1790 if not chunkdata:
1794 if not chunkdata:
1791 break
1795 break
1792 fname = chunkdata['filename']
1796 fname = chunkdata['filename']
1793 showchunks(fname)
1797 showchunks(fname)
1794 else:
1798 else:
1795 chunkdata = gen.changelogheader()
1799 chunkdata = gen.changelogheader()
1796 chain = None
1800 chain = None
1797 while True:
1801 while True:
1798 chunkdata = gen.deltachunk(chain)
1802 chunkdata = gen.deltachunk(chain)
1799 if not chunkdata:
1803 if not chunkdata:
1800 break
1804 break
1801 node = chunkdata['node']
1805 node = chunkdata['node']
1802 ui.write("%s\n" % hex(node))
1806 ui.write("%s\n" % hex(node))
1803 chain = node
1807 chain = node
1804 finally:
1808 finally:
1805 f.close()
1809 f.close()
1806
1810
1807 @command('debugcheckstate', [], '')
1811 @command('debugcheckstate', [], '')
1808 def debugcheckstate(ui, repo):
1812 def debugcheckstate(ui, repo):
1809 """validate the correctness of the current dirstate"""
1813 """validate the correctness of the current dirstate"""
1810 parent1, parent2 = repo.dirstate.parents()
1814 parent1, parent2 = repo.dirstate.parents()
1811 m1 = repo[parent1].manifest()
1815 m1 = repo[parent1].manifest()
1812 m2 = repo[parent2].manifest()
1816 m2 = repo[parent2].manifest()
1813 errors = 0
1817 errors = 0
1814 for f in repo.dirstate:
1818 for f in repo.dirstate:
1815 state = repo.dirstate[f]
1819 state = repo.dirstate[f]
1816 if state in "nr" and f not in m1:
1820 if state in "nr" and f not in m1:
1817 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1821 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1818 errors += 1
1822 errors += 1
1819 if state in "a" and f in m1:
1823 if state in "a" and f in m1:
1820 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1824 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1821 errors += 1
1825 errors += 1
1822 if state in "m" and f not in m1 and f not in m2:
1826 if state in "m" and f not in m1 and f not in m2:
1823 ui.warn(_("%s in state %s, but not in either manifest\n") %
1827 ui.warn(_("%s in state %s, but not in either manifest\n") %
1824 (f, state))
1828 (f, state))
1825 errors += 1
1829 errors += 1
1826 for f in m1:
1830 for f in m1:
1827 state = repo.dirstate[f]
1831 state = repo.dirstate[f]
1828 if state not in "nrm":
1832 if state not in "nrm":
1829 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1833 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1830 errors += 1
1834 errors += 1
1831 if errors:
1835 if errors:
1832 error = _(".hg/dirstate inconsistent with current parent's manifest")
1836 error = _(".hg/dirstate inconsistent with current parent's manifest")
1833 raise util.Abort(error)
1837 raise util.Abort(error)
1834
1838
1835 @command('debugcommands', [], _('[COMMAND]'))
1839 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1836 def debugcommands(ui, cmd='', *args):
1840 def debugcommands(ui, cmd='', *args):
1837 """list all available commands and options"""
1841 """list all available commands and options"""
1838 for cmd, vals in sorted(table.iteritems()):
1842 for cmd, vals in sorted(table.iteritems()):
1839 cmd = cmd.split('|')[0].strip('^')
1843 cmd = cmd.split('|')[0].strip('^')
1840 opts = ', '.join([i[1] for i in vals[1]])
1844 opts = ', '.join([i[1] for i in vals[1]])
1841 ui.write('%s: %s\n' % (cmd, opts))
1845 ui.write('%s: %s\n' % (cmd, opts))
1842
1846
1843 @command('debugcomplete',
1847 @command('debugcomplete',
1844 [('o', 'options', None, _('show the command options'))],
1848 [('o', 'options', None, _('show the command options'))],
1845 _('[-o] CMD'))
1849 _('[-o] CMD'),
1850 norepo=True)
1846 def debugcomplete(ui, cmd='', **opts):
1851 def debugcomplete(ui, cmd='', **opts):
1847 """returns the completion list associated with the given command"""
1852 """returns the completion list associated with the given command"""
1848
1853
1849 if opts.get('options'):
1854 if opts.get('options'):
1850 options = []
1855 options = []
1851 otables = [globalopts]
1856 otables = [globalopts]
1852 if cmd:
1857 if cmd:
1853 aliases, entry = cmdutil.findcmd(cmd, table, False)
1858 aliases, entry = cmdutil.findcmd(cmd, table, False)
1854 otables.append(entry[1])
1859 otables.append(entry[1])
1855 for t in otables:
1860 for t in otables:
1856 for o in t:
1861 for o in t:
1857 if "(DEPRECATED)" in o[3]:
1862 if "(DEPRECATED)" in o[3]:
1858 continue
1863 continue
1859 if o[0]:
1864 if o[0]:
1860 options.append('-%s' % o[0])
1865 options.append('-%s' % o[0])
1861 options.append('--%s' % o[1])
1866 options.append('--%s' % o[1])
1862 ui.write("%s\n" % "\n".join(options))
1867 ui.write("%s\n" % "\n".join(options))
1863 return
1868 return
1864
1869
1865 cmdlist = cmdutil.findpossible(cmd, table)
1870 cmdlist = cmdutil.findpossible(cmd, table)
1866 if ui.verbose:
1871 if ui.verbose:
1867 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1872 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1868 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1873 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1869
1874
1870 @command('debugdag',
1875 @command('debugdag',
1871 [('t', 'tags', None, _('use tags as labels')),
1876 [('t', 'tags', None, _('use tags as labels')),
1872 ('b', 'branches', None, _('annotate with branch names')),
1877 ('b', 'branches', None, _('annotate with branch names')),
1873 ('', 'dots', None, _('use dots for runs')),
1878 ('', 'dots', None, _('use dots for runs')),
1874 ('s', 'spaces', None, _('separate elements by spaces'))],
1879 ('s', 'spaces', None, _('separate elements by spaces'))],
1875 _('[OPTION]... [FILE [REV]...]'))
1880 _('[OPTION]... [FILE [REV]...]'))
1876 def debugdag(ui, repo, file_=None, *revs, **opts):
1881 def debugdag(ui, repo, file_=None, *revs, **opts):
1877 """format the changelog or an index DAG as a concise textual description
1882 """format the changelog or an index DAG as a concise textual description
1878
1883
1879 If you pass a revlog index, the revlog's DAG is emitted. If you list
1884 If you pass a revlog index, the revlog's DAG is emitted. If you list
1880 revision numbers, they get labeled in the output as rN.
1885 revision numbers, they get labeled in the output as rN.
1881
1886
1882 Otherwise, the changelog DAG of the current repo is emitted.
1887 Otherwise, the changelog DAG of the current repo is emitted.
1883 """
1888 """
1884 spaces = opts.get('spaces')
1889 spaces = opts.get('spaces')
1885 dots = opts.get('dots')
1890 dots = opts.get('dots')
1886 if file_:
1891 if file_:
1887 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1892 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1888 revs = set((int(r) for r in revs))
1893 revs = set((int(r) for r in revs))
1889 def events():
1894 def events():
1890 for r in rlog:
1895 for r in rlog:
1891 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1896 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1892 if p != -1)))
1897 if p != -1)))
1893 if r in revs:
1898 if r in revs:
1894 yield 'l', (r, "r%i" % r)
1899 yield 'l', (r, "r%i" % r)
1895 elif repo:
1900 elif repo:
1896 cl = repo.changelog
1901 cl = repo.changelog
1897 tags = opts.get('tags')
1902 tags = opts.get('tags')
1898 branches = opts.get('branches')
1903 branches = opts.get('branches')
1899 if tags:
1904 if tags:
1900 labels = {}
1905 labels = {}
1901 for l, n in repo.tags().items():
1906 for l, n in repo.tags().items():
1902 labels.setdefault(cl.rev(n), []).append(l)
1907 labels.setdefault(cl.rev(n), []).append(l)
1903 def events():
1908 def events():
1904 b = "default"
1909 b = "default"
1905 for r in cl:
1910 for r in cl:
1906 if branches:
1911 if branches:
1907 newb = cl.read(cl.node(r))[5]['branch']
1912 newb = cl.read(cl.node(r))[5]['branch']
1908 if newb != b:
1913 if newb != b:
1909 yield 'a', newb
1914 yield 'a', newb
1910 b = newb
1915 b = newb
1911 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1916 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1912 if p != -1)))
1917 if p != -1)))
1913 if tags:
1918 if tags:
1914 ls = labels.get(r)
1919 ls = labels.get(r)
1915 if ls:
1920 if ls:
1916 for l in ls:
1921 for l in ls:
1917 yield 'l', (r, l)
1922 yield 'l', (r, l)
1918 else:
1923 else:
1919 raise util.Abort(_('need repo for changelog dag'))
1924 raise util.Abort(_('need repo for changelog dag'))
1920
1925
1921 for line in dagparser.dagtextlines(events(),
1926 for line in dagparser.dagtextlines(events(),
1922 addspaces=spaces,
1927 addspaces=spaces,
1923 wraplabels=True,
1928 wraplabels=True,
1924 wrapannotations=True,
1929 wrapannotations=True,
1925 wrapnonlinear=dots,
1930 wrapnonlinear=dots,
1926 usedots=dots,
1931 usedots=dots,
1927 maxlinewidth=70):
1932 maxlinewidth=70):
1928 ui.write(line)
1933 ui.write(line)
1929 ui.write("\n")
1934 ui.write("\n")
1930
1935
1931 @command('debugdata',
1936 @command('debugdata',
1932 [('c', 'changelog', False, _('open changelog')),
1937 [('c', 'changelog', False, _('open changelog')),
1933 ('m', 'manifest', False, _('open manifest'))],
1938 ('m', 'manifest', False, _('open manifest'))],
1934 _('-c|-m|FILE REV'))
1939 _('-c|-m|FILE REV'))
1935 def debugdata(ui, repo, file_, rev=None, **opts):
1940 def debugdata(ui, repo, file_, rev=None, **opts):
1936 """dump the contents of a data file revision"""
1941 """dump the contents of a data file revision"""
1937 if opts.get('changelog') or opts.get('manifest'):
1942 if opts.get('changelog') or opts.get('manifest'):
1938 file_, rev = None, file_
1943 file_, rev = None, file_
1939 elif rev is None:
1944 elif rev is None:
1940 raise error.CommandError('debugdata', _('invalid arguments'))
1945 raise error.CommandError('debugdata', _('invalid arguments'))
1941 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1946 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1942 try:
1947 try:
1943 ui.write(r.revision(r.lookup(rev)))
1948 ui.write(r.revision(r.lookup(rev)))
1944 except KeyError:
1949 except KeyError:
1945 raise util.Abort(_('invalid revision identifier %s') % rev)
1950 raise util.Abort(_('invalid revision identifier %s') % rev)
1946
1951
1947 @command('debugdate',
1952 @command('debugdate',
1948 [('e', 'extended', None, _('try extended date formats'))],
1953 [('e', 'extended', None, _('try extended date formats'))],
1949 _('[-e] DATE [RANGE]'))
1954 _('[-e] DATE [RANGE]'),
1955 norepo=True)
1950 def debugdate(ui, date, range=None, **opts):
1956 def debugdate(ui, date, range=None, **opts):
1951 """parse and display a date"""
1957 """parse and display a date"""
1952 if opts["extended"]:
1958 if opts["extended"]:
1953 d = util.parsedate(date, util.extendeddateformats)
1959 d = util.parsedate(date, util.extendeddateformats)
1954 else:
1960 else:
1955 d = util.parsedate(date)
1961 d = util.parsedate(date)
1956 ui.write(("internal: %s %s\n") % d)
1962 ui.write(("internal: %s %s\n") % d)
1957 ui.write(("standard: %s\n") % util.datestr(d))
1963 ui.write(("standard: %s\n") % util.datestr(d))
1958 if range:
1964 if range:
1959 m = util.matchdate(range)
1965 m = util.matchdate(range)
1960 ui.write(("match: %s\n") % m(d[0]))
1966 ui.write(("match: %s\n") % m(d[0]))
1961
1967
1962 @command('debugdiscovery',
1968 @command('debugdiscovery',
1963 [('', 'old', None, _('use old-style discovery')),
1969 [('', 'old', None, _('use old-style discovery')),
1964 ('', 'nonheads', None,
1970 ('', 'nonheads', None,
1965 _('use old-style discovery with non-heads included')),
1971 _('use old-style discovery with non-heads included')),
1966 ] + remoteopts,
1972 ] + remoteopts,
1967 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1973 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1968 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1974 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1969 """runs the changeset discovery protocol in isolation"""
1975 """runs the changeset discovery protocol in isolation"""
1970 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1976 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1971 opts.get('branch'))
1977 opts.get('branch'))
1972 remote = hg.peer(repo, opts, remoteurl)
1978 remote = hg.peer(repo, opts, remoteurl)
1973 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1979 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1974
1980
1975 # make sure tests are repeatable
1981 # make sure tests are repeatable
1976 random.seed(12323)
1982 random.seed(12323)
1977
1983
1978 def doit(localheads, remoteheads, remote=remote):
1984 def doit(localheads, remoteheads, remote=remote):
1979 if opts.get('old'):
1985 if opts.get('old'):
1980 if localheads:
1986 if localheads:
1981 raise util.Abort('cannot use localheads with old style '
1987 raise util.Abort('cannot use localheads with old style '
1982 'discovery')
1988 'discovery')
1983 if not util.safehasattr(remote, 'branches'):
1989 if not util.safehasattr(remote, 'branches'):
1984 # enable in-client legacy support
1990 # enable in-client legacy support
1985 remote = localrepo.locallegacypeer(remote.local())
1991 remote = localrepo.locallegacypeer(remote.local())
1986 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1992 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1987 force=True)
1993 force=True)
1988 common = set(common)
1994 common = set(common)
1989 if not opts.get('nonheads'):
1995 if not opts.get('nonheads'):
1990 ui.write(("unpruned common: %s\n") %
1996 ui.write(("unpruned common: %s\n") %
1991 " ".join(sorted(short(n) for n in common)))
1997 " ".join(sorted(short(n) for n in common)))
1992 dag = dagutil.revlogdag(repo.changelog)
1998 dag = dagutil.revlogdag(repo.changelog)
1993 all = dag.ancestorset(dag.internalizeall(common))
1999 all = dag.ancestorset(dag.internalizeall(common))
1994 common = dag.externalizeall(dag.headsetofconnecteds(all))
2000 common = dag.externalizeall(dag.headsetofconnecteds(all))
1995 else:
2001 else:
1996 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2002 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1997 common = set(common)
2003 common = set(common)
1998 rheads = set(hds)
2004 rheads = set(hds)
1999 lheads = set(repo.heads())
2005 lheads = set(repo.heads())
2000 ui.write(("common heads: %s\n") %
2006 ui.write(("common heads: %s\n") %
2001 " ".join(sorted(short(n) for n in common)))
2007 " ".join(sorted(short(n) for n in common)))
2002 if lheads <= common:
2008 if lheads <= common:
2003 ui.write(("local is subset\n"))
2009 ui.write(("local is subset\n"))
2004 elif rheads <= common:
2010 elif rheads <= common:
2005 ui.write(("remote is subset\n"))
2011 ui.write(("remote is subset\n"))
2006
2012
2007 serverlogs = opts.get('serverlog')
2013 serverlogs = opts.get('serverlog')
2008 if serverlogs:
2014 if serverlogs:
2009 for filename in serverlogs:
2015 for filename in serverlogs:
2010 logfile = open(filename, 'r')
2016 logfile = open(filename, 'r')
2011 try:
2017 try:
2012 line = logfile.readline()
2018 line = logfile.readline()
2013 while line:
2019 while line:
2014 parts = line.strip().split(';')
2020 parts = line.strip().split(';')
2015 op = parts[1]
2021 op = parts[1]
2016 if op == 'cg':
2022 if op == 'cg':
2017 pass
2023 pass
2018 elif op == 'cgss':
2024 elif op == 'cgss':
2019 doit(parts[2].split(' '), parts[3].split(' '))
2025 doit(parts[2].split(' '), parts[3].split(' '))
2020 elif op == 'unb':
2026 elif op == 'unb':
2021 doit(parts[3].split(' '), parts[2].split(' '))
2027 doit(parts[3].split(' '), parts[2].split(' '))
2022 line = logfile.readline()
2028 line = logfile.readline()
2023 finally:
2029 finally:
2024 logfile.close()
2030 logfile.close()
2025
2031
2026 else:
2032 else:
2027 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2033 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2028 opts.get('remote_head'))
2034 opts.get('remote_head'))
2029 localrevs = opts.get('local_head')
2035 localrevs = opts.get('local_head')
2030 doit(localrevs, remoterevs)
2036 doit(localrevs, remoterevs)
2031
2037
2032 @command('debugfileset',
2038 @command('debugfileset',
2033 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2039 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2034 _('[-r REV] FILESPEC'))
2040 _('[-r REV] FILESPEC'))
2035 def debugfileset(ui, repo, expr, **opts):
2041 def debugfileset(ui, repo, expr, **opts):
2036 '''parse and apply a fileset specification'''
2042 '''parse and apply a fileset specification'''
2037 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2043 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2038 if ui.verbose:
2044 if ui.verbose:
2039 tree = fileset.parse(expr)[0]
2045 tree = fileset.parse(expr)[0]
2040 ui.note(tree, "\n")
2046 ui.note(tree, "\n")
2041
2047
2042 for f in ctx.getfileset(expr):
2048 for f in ctx.getfileset(expr):
2043 ui.write("%s\n" % f)
2049 ui.write("%s\n" % f)
2044
2050
2045 @command('debugfsinfo', [], _('[PATH]'))
2051 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2046 def debugfsinfo(ui, path="."):
2052 def debugfsinfo(ui, path="."):
2047 """show information detected about current filesystem"""
2053 """show information detected about current filesystem"""
2048 util.writefile('.debugfsinfo', '')
2054 util.writefile('.debugfsinfo', '')
2049 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2055 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2050 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2056 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2051 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2057 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2052 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2058 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2053 and 'yes' or 'no'))
2059 and 'yes' or 'no'))
2054 os.unlink('.debugfsinfo')
2060 os.unlink('.debugfsinfo')
2055
2061
2056 @command('debuggetbundle',
2062 @command('debuggetbundle',
2057 [('H', 'head', [], _('id of head node'), _('ID')),
2063 [('H', 'head', [], _('id of head node'), _('ID')),
2058 ('C', 'common', [], _('id of common node'), _('ID')),
2064 ('C', 'common', [], _('id of common node'), _('ID')),
2059 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2065 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2060 _('REPO FILE [-H|-C ID]...'))
2066 _('REPO FILE [-H|-C ID]...'),
2067 norepo=True)
2061 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2068 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2062 """retrieves a bundle from a repo
2069 """retrieves a bundle from a repo
2063
2070
2064 Every ID must be a full-length hex node id string. Saves the bundle to the
2071 Every ID must be a full-length hex node id string. Saves the bundle to the
2065 given file.
2072 given file.
2066 """
2073 """
2067 repo = hg.peer(ui, opts, repopath)
2074 repo = hg.peer(ui, opts, repopath)
2068 if not repo.capable('getbundle'):
2075 if not repo.capable('getbundle'):
2069 raise util.Abort("getbundle() not supported by target repository")
2076 raise util.Abort("getbundle() not supported by target repository")
2070 args = {}
2077 args = {}
2071 if common:
2078 if common:
2072 args['common'] = [bin(s) for s in common]
2079 args['common'] = [bin(s) for s in common]
2073 if head:
2080 if head:
2074 args['heads'] = [bin(s) for s in head]
2081 args['heads'] = [bin(s) for s in head]
2075 # TODO: get desired bundlecaps from command line.
2082 # TODO: get desired bundlecaps from command line.
2076 args['bundlecaps'] = None
2083 args['bundlecaps'] = None
2077 bundle = repo.getbundle('debug', **args)
2084 bundle = repo.getbundle('debug', **args)
2078
2085
2079 bundletype = opts.get('type', 'bzip2').lower()
2086 bundletype = opts.get('type', 'bzip2').lower()
2080 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2087 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2081 bundletype = btypes.get(bundletype)
2088 bundletype = btypes.get(bundletype)
2082 if bundletype not in changegroup.bundletypes:
2089 if bundletype not in changegroup.bundletypes:
2083 raise util.Abort(_('unknown bundle type specified with --type'))
2090 raise util.Abort(_('unknown bundle type specified with --type'))
2084 changegroup.writebundle(bundle, bundlepath, bundletype)
2091 changegroup.writebundle(bundle, bundlepath, bundletype)
2085
2092
2086 @command('debugignore', [], '')
2093 @command('debugignore', [], '')
2087 def debugignore(ui, repo, *values, **opts):
2094 def debugignore(ui, repo, *values, **opts):
2088 """display the combined ignore pattern"""
2095 """display the combined ignore pattern"""
2089 ignore = repo.dirstate._ignore
2096 ignore = repo.dirstate._ignore
2090 includepat = getattr(ignore, 'includepat', None)
2097 includepat = getattr(ignore, 'includepat', None)
2091 if includepat is not None:
2098 if includepat is not None:
2092 ui.write("%s\n" % includepat)
2099 ui.write("%s\n" % includepat)
2093 else:
2100 else:
2094 raise util.Abort(_("no ignore patterns found"))
2101 raise util.Abort(_("no ignore patterns found"))
2095
2102
2096 @command('debugindex',
2103 @command('debugindex',
2097 [('c', 'changelog', False, _('open changelog')),
2104 [('c', 'changelog', False, _('open changelog')),
2098 ('m', 'manifest', False, _('open manifest')),
2105 ('m', 'manifest', False, _('open manifest')),
2099 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2106 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2100 _('[-f FORMAT] -c|-m|FILE'))
2107 _('[-f FORMAT] -c|-m|FILE'))
2101 def debugindex(ui, repo, file_=None, **opts):
2108 def debugindex(ui, repo, file_=None, **opts):
2102 """dump the contents of an index file"""
2109 """dump the contents of an index file"""
2103 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2110 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2104 format = opts.get('format', 0)
2111 format = opts.get('format', 0)
2105 if format not in (0, 1):
2112 if format not in (0, 1):
2106 raise util.Abort(_("unknown format %d") % format)
2113 raise util.Abort(_("unknown format %d") % format)
2107
2114
2108 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2115 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2109 if generaldelta:
2116 if generaldelta:
2110 basehdr = ' delta'
2117 basehdr = ' delta'
2111 else:
2118 else:
2112 basehdr = ' base'
2119 basehdr = ' base'
2113
2120
2114 if format == 0:
2121 if format == 0:
2115 ui.write(" rev offset length " + basehdr + " linkrev"
2122 ui.write(" rev offset length " + basehdr + " linkrev"
2116 " nodeid p1 p2\n")
2123 " nodeid p1 p2\n")
2117 elif format == 1:
2124 elif format == 1:
2118 ui.write(" rev flag offset length"
2125 ui.write(" rev flag offset length"
2119 " size " + basehdr + " link p1 p2"
2126 " size " + basehdr + " link p1 p2"
2120 " nodeid\n")
2127 " nodeid\n")
2121
2128
2122 for i in r:
2129 for i in r:
2123 node = r.node(i)
2130 node = r.node(i)
2124 if generaldelta:
2131 if generaldelta:
2125 base = r.deltaparent(i)
2132 base = r.deltaparent(i)
2126 else:
2133 else:
2127 base = r.chainbase(i)
2134 base = r.chainbase(i)
2128 if format == 0:
2135 if format == 0:
2129 try:
2136 try:
2130 pp = r.parents(node)
2137 pp = r.parents(node)
2131 except Exception:
2138 except Exception:
2132 pp = [nullid, nullid]
2139 pp = [nullid, nullid]
2133 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2140 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2134 i, r.start(i), r.length(i), base, r.linkrev(i),
2141 i, r.start(i), r.length(i), base, r.linkrev(i),
2135 short(node), short(pp[0]), short(pp[1])))
2142 short(node), short(pp[0]), short(pp[1])))
2136 elif format == 1:
2143 elif format == 1:
2137 pr = r.parentrevs(i)
2144 pr = r.parentrevs(i)
2138 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2145 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2139 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2146 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2140 base, r.linkrev(i), pr[0], pr[1], short(node)))
2147 base, r.linkrev(i), pr[0], pr[1], short(node)))
2141
2148
2142 @command('debugindexdot', [], _('FILE'))
2149 @command('debugindexdot', [], _('FILE'))
2143 def debugindexdot(ui, repo, file_):
2150 def debugindexdot(ui, repo, file_):
2144 """dump an index DAG as a graphviz dot file"""
2151 """dump an index DAG as a graphviz dot file"""
2145 r = None
2152 r = None
2146 if repo:
2153 if repo:
2147 filelog = repo.file(file_)
2154 filelog = repo.file(file_)
2148 if len(filelog):
2155 if len(filelog):
2149 r = filelog
2156 r = filelog
2150 if not r:
2157 if not r:
2151 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2158 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2152 ui.write(("digraph G {\n"))
2159 ui.write(("digraph G {\n"))
2153 for i in r:
2160 for i in r:
2154 node = r.node(i)
2161 node = r.node(i)
2155 pp = r.parents(node)
2162 pp = r.parents(node)
2156 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2163 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2157 if pp[1] != nullid:
2164 if pp[1] != nullid:
2158 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2165 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2159 ui.write("}\n")
2166 ui.write("}\n")
2160
2167
2161 @command('debuginstall', [], '')
2168 @command('debuginstall', [], '', norepo=True)
2162 def debuginstall(ui):
2169 def debuginstall(ui):
2163 '''test Mercurial installation
2170 '''test Mercurial installation
2164
2171
2165 Returns 0 on success.
2172 Returns 0 on success.
2166 '''
2173 '''
2167
2174
2168 def writetemp(contents):
2175 def writetemp(contents):
2169 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2176 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2170 f = os.fdopen(fd, "wb")
2177 f = os.fdopen(fd, "wb")
2171 f.write(contents)
2178 f.write(contents)
2172 f.close()
2179 f.close()
2173 return name
2180 return name
2174
2181
2175 problems = 0
2182 problems = 0
2176
2183
2177 # encoding
2184 # encoding
2178 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2185 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2179 try:
2186 try:
2180 encoding.fromlocal("test")
2187 encoding.fromlocal("test")
2181 except util.Abort, inst:
2188 except util.Abort, inst:
2182 ui.write(" %s\n" % inst)
2189 ui.write(" %s\n" % inst)
2183 ui.write(_(" (check that your locale is properly set)\n"))
2190 ui.write(_(" (check that your locale is properly set)\n"))
2184 problems += 1
2191 problems += 1
2185
2192
2186 # Python
2193 # Python
2187 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2194 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2188 ui.status(_("checking Python version (%s)\n")
2195 ui.status(_("checking Python version (%s)\n")
2189 % ("%s.%s.%s" % sys.version_info[:3]))
2196 % ("%s.%s.%s" % sys.version_info[:3]))
2190 ui.status(_("checking Python lib (%s)...\n")
2197 ui.status(_("checking Python lib (%s)...\n")
2191 % os.path.dirname(os.__file__))
2198 % os.path.dirname(os.__file__))
2192
2199
2193 # compiled modules
2200 # compiled modules
2194 ui.status(_("checking installed modules (%s)...\n")
2201 ui.status(_("checking installed modules (%s)...\n")
2195 % os.path.dirname(__file__))
2202 % os.path.dirname(__file__))
2196 try:
2203 try:
2197 import bdiff, mpatch, base85, osutil
2204 import bdiff, mpatch, base85, osutil
2198 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2205 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2199 except Exception, inst:
2206 except Exception, inst:
2200 ui.write(" %s\n" % inst)
2207 ui.write(" %s\n" % inst)
2201 ui.write(_(" One or more extensions could not be found"))
2208 ui.write(_(" One or more extensions could not be found"))
2202 ui.write(_(" (check that you compiled the extensions)\n"))
2209 ui.write(_(" (check that you compiled the extensions)\n"))
2203 problems += 1
2210 problems += 1
2204
2211
2205 # templates
2212 # templates
2206 import templater
2213 import templater
2207 p = templater.templatepath()
2214 p = templater.templatepath()
2208 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2215 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2209 if p:
2216 if p:
2210 m = templater.templatepath("map-cmdline.default")
2217 m = templater.templatepath("map-cmdline.default")
2211 if m:
2218 if m:
2212 # template found, check if it is working
2219 # template found, check if it is working
2213 try:
2220 try:
2214 templater.templater(m)
2221 templater.templater(m)
2215 except Exception, inst:
2222 except Exception, inst:
2216 ui.write(" %s\n" % inst)
2223 ui.write(" %s\n" % inst)
2217 p = None
2224 p = None
2218 else:
2225 else:
2219 ui.write(_(" template 'default' not found\n"))
2226 ui.write(_(" template 'default' not found\n"))
2220 p = None
2227 p = None
2221 else:
2228 else:
2222 ui.write(_(" no template directories found\n"))
2229 ui.write(_(" no template directories found\n"))
2223 if not p:
2230 if not p:
2224 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2231 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2225 problems += 1
2232 problems += 1
2226
2233
2227 # editor
2234 # editor
2228 ui.status(_("checking commit editor...\n"))
2235 ui.status(_("checking commit editor...\n"))
2229 editor = ui.geteditor()
2236 editor = ui.geteditor()
2230 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2237 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2231 if not cmdpath:
2238 if not cmdpath:
2232 if editor == 'vi':
2239 if editor == 'vi':
2233 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2240 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2234 ui.write(_(" (specify a commit editor in your configuration"
2241 ui.write(_(" (specify a commit editor in your configuration"
2235 " file)\n"))
2242 " file)\n"))
2236 else:
2243 else:
2237 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2244 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2238 ui.write(_(" (specify a commit editor in your configuration"
2245 ui.write(_(" (specify a commit editor in your configuration"
2239 " file)\n"))
2246 " file)\n"))
2240 problems += 1
2247 problems += 1
2241
2248
2242 # check username
2249 # check username
2243 ui.status(_("checking username...\n"))
2250 ui.status(_("checking username...\n"))
2244 try:
2251 try:
2245 ui.username()
2252 ui.username()
2246 except util.Abort, e:
2253 except util.Abort, e:
2247 ui.write(" %s\n" % e)
2254 ui.write(" %s\n" % e)
2248 ui.write(_(" (specify a username in your configuration file)\n"))
2255 ui.write(_(" (specify a username in your configuration file)\n"))
2249 problems += 1
2256 problems += 1
2250
2257
2251 if not problems:
2258 if not problems:
2252 ui.status(_("no problems detected\n"))
2259 ui.status(_("no problems detected\n"))
2253 else:
2260 else:
2254 ui.write(_("%s problems detected,"
2261 ui.write(_("%s problems detected,"
2255 " please check your install!\n") % problems)
2262 " please check your install!\n") % problems)
2256
2263
2257 return problems
2264 return problems
2258
2265
2259 @command('debugknown', [], _('REPO ID...'))
2266 @command('debugknown', [], _('REPO ID...'), norepo=True)
2260 def debugknown(ui, repopath, *ids, **opts):
2267 def debugknown(ui, repopath, *ids, **opts):
2261 """test whether node ids are known to a repo
2268 """test whether node ids are known to a repo
2262
2269
2263 Every ID must be a full-length hex node id string. Returns a list of 0s
2270 Every ID must be a full-length hex node id string. Returns a list of 0s
2264 and 1s indicating unknown/known.
2271 and 1s indicating unknown/known.
2265 """
2272 """
2266 repo = hg.peer(ui, opts, repopath)
2273 repo = hg.peer(ui, opts, repopath)
2267 if not repo.capable('known'):
2274 if not repo.capable('known'):
2268 raise util.Abort("known() not supported by target repository")
2275 raise util.Abort("known() not supported by target repository")
2269 flags = repo.known([bin(s) for s in ids])
2276 flags = repo.known([bin(s) for s in ids])
2270 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2277 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2271
2278
2272 @command('debuglabelcomplete', [], _('LABEL...'))
2279 @command('debuglabelcomplete', [], _('LABEL...'))
2273 def debuglabelcomplete(ui, repo, *args):
2280 def debuglabelcomplete(ui, repo, *args):
2274 '''complete "labels" - tags, open branch names, bookmark names'''
2281 '''complete "labels" - tags, open branch names, bookmark names'''
2275
2282
2276 labels = set()
2283 labels = set()
2277 labels.update(t[0] for t in repo.tagslist())
2284 labels.update(t[0] for t in repo.tagslist())
2278 labels.update(repo._bookmarks.keys())
2285 labels.update(repo._bookmarks.keys())
2279 labels.update(tag for (tag, heads, tip, closed)
2286 labels.update(tag for (tag, heads, tip, closed)
2280 in repo.branchmap().iterbranches() if not closed)
2287 in repo.branchmap().iterbranches() if not closed)
2281 completions = set()
2288 completions = set()
2282 if not args:
2289 if not args:
2283 args = ['']
2290 args = ['']
2284 for a in args:
2291 for a in args:
2285 completions.update(l for l in labels if l.startswith(a))
2292 completions.update(l for l in labels if l.startswith(a))
2286 ui.write('\n'.join(sorted(completions)))
2293 ui.write('\n'.join(sorted(completions)))
2287 ui.write('\n')
2294 ui.write('\n')
2288
2295
2289 @command('debugobsolete',
2296 @command('debugobsolete',
2290 [('', 'flags', 0, _('markers flag')),
2297 [('', 'flags', 0, _('markers flag')),
2291 ] + commitopts2,
2298 ] + commitopts2,
2292 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2299 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2293 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2300 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2294 """create arbitrary obsolete marker
2301 """create arbitrary obsolete marker
2295
2302
2296 With no arguments, displays the list of obsolescence markers."""
2303 With no arguments, displays the list of obsolescence markers."""
2297 def parsenodeid(s):
2304 def parsenodeid(s):
2298 try:
2305 try:
2299 # We do not use revsingle/revrange functions here to accept
2306 # We do not use revsingle/revrange functions here to accept
2300 # arbitrary node identifiers, possibly not present in the
2307 # arbitrary node identifiers, possibly not present in the
2301 # local repository.
2308 # local repository.
2302 n = bin(s)
2309 n = bin(s)
2303 if len(n) != len(nullid):
2310 if len(n) != len(nullid):
2304 raise TypeError()
2311 raise TypeError()
2305 return n
2312 return n
2306 except TypeError:
2313 except TypeError:
2307 raise util.Abort('changeset references must be full hexadecimal '
2314 raise util.Abort('changeset references must be full hexadecimal '
2308 'node identifiers')
2315 'node identifiers')
2309
2316
2310 if precursor is not None:
2317 if precursor is not None:
2311 metadata = {}
2318 metadata = {}
2312 if 'date' in opts:
2319 if 'date' in opts:
2313 metadata['date'] = opts['date']
2320 metadata['date'] = opts['date']
2314 metadata['user'] = opts['user'] or ui.username()
2321 metadata['user'] = opts['user'] or ui.username()
2315 succs = tuple(parsenodeid(succ) for succ in successors)
2322 succs = tuple(parsenodeid(succ) for succ in successors)
2316 l = repo.lock()
2323 l = repo.lock()
2317 try:
2324 try:
2318 tr = repo.transaction('debugobsolete')
2325 tr = repo.transaction('debugobsolete')
2319 try:
2326 try:
2320 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2327 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2321 opts['flags'], metadata)
2328 opts['flags'], metadata)
2322 tr.close()
2329 tr.close()
2323 finally:
2330 finally:
2324 tr.release()
2331 tr.release()
2325 finally:
2332 finally:
2326 l.release()
2333 l.release()
2327 else:
2334 else:
2328 for m in obsolete.allmarkers(repo):
2335 for m in obsolete.allmarkers(repo):
2329 cmdutil.showmarker(ui, m)
2336 cmdutil.showmarker(ui, m)
2330
2337
2331 @command('debugpathcomplete',
2338 @command('debugpathcomplete',
2332 [('f', 'full', None, _('complete an entire path')),
2339 [('f', 'full', None, _('complete an entire path')),
2333 ('n', 'normal', None, _('show only normal files')),
2340 ('n', 'normal', None, _('show only normal files')),
2334 ('a', 'added', None, _('show only added files')),
2341 ('a', 'added', None, _('show only added files')),
2335 ('r', 'removed', None, _('show only removed files'))],
2342 ('r', 'removed', None, _('show only removed files'))],
2336 _('FILESPEC...'))
2343 _('FILESPEC...'))
2337 def debugpathcomplete(ui, repo, *specs, **opts):
2344 def debugpathcomplete(ui, repo, *specs, **opts):
2338 '''complete part or all of a tracked path
2345 '''complete part or all of a tracked path
2339
2346
2340 This command supports shells that offer path name completion. It
2347 This command supports shells that offer path name completion. It
2341 currently completes only files already known to the dirstate.
2348 currently completes only files already known to the dirstate.
2342
2349
2343 Completion extends only to the next path segment unless
2350 Completion extends only to the next path segment unless
2344 --full is specified, in which case entire paths are used.'''
2351 --full is specified, in which case entire paths are used.'''
2345
2352
2346 def complete(path, acceptable):
2353 def complete(path, acceptable):
2347 dirstate = repo.dirstate
2354 dirstate = repo.dirstate
2348 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2355 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2349 rootdir = repo.root + os.sep
2356 rootdir = repo.root + os.sep
2350 if spec != repo.root and not spec.startswith(rootdir):
2357 if spec != repo.root and not spec.startswith(rootdir):
2351 return [], []
2358 return [], []
2352 if os.path.isdir(spec):
2359 if os.path.isdir(spec):
2353 spec += '/'
2360 spec += '/'
2354 spec = spec[len(rootdir):]
2361 spec = spec[len(rootdir):]
2355 fixpaths = os.sep != '/'
2362 fixpaths = os.sep != '/'
2356 if fixpaths:
2363 if fixpaths:
2357 spec = spec.replace(os.sep, '/')
2364 spec = spec.replace(os.sep, '/')
2358 speclen = len(spec)
2365 speclen = len(spec)
2359 fullpaths = opts['full']
2366 fullpaths = opts['full']
2360 files, dirs = set(), set()
2367 files, dirs = set(), set()
2361 adddir, addfile = dirs.add, files.add
2368 adddir, addfile = dirs.add, files.add
2362 for f, st in dirstate.iteritems():
2369 for f, st in dirstate.iteritems():
2363 if f.startswith(spec) and st[0] in acceptable:
2370 if f.startswith(spec) and st[0] in acceptable:
2364 if fixpaths:
2371 if fixpaths:
2365 f = f.replace('/', os.sep)
2372 f = f.replace('/', os.sep)
2366 if fullpaths:
2373 if fullpaths:
2367 addfile(f)
2374 addfile(f)
2368 continue
2375 continue
2369 s = f.find(os.sep, speclen)
2376 s = f.find(os.sep, speclen)
2370 if s >= 0:
2377 if s >= 0:
2371 adddir(f[:s])
2378 adddir(f[:s])
2372 else:
2379 else:
2373 addfile(f)
2380 addfile(f)
2374 return files, dirs
2381 return files, dirs
2375
2382
2376 acceptable = ''
2383 acceptable = ''
2377 if opts['normal']:
2384 if opts['normal']:
2378 acceptable += 'nm'
2385 acceptable += 'nm'
2379 if opts['added']:
2386 if opts['added']:
2380 acceptable += 'a'
2387 acceptable += 'a'
2381 if opts['removed']:
2388 if opts['removed']:
2382 acceptable += 'r'
2389 acceptable += 'r'
2383 cwd = repo.getcwd()
2390 cwd = repo.getcwd()
2384 if not specs:
2391 if not specs:
2385 specs = ['.']
2392 specs = ['.']
2386
2393
2387 files, dirs = set(), set()
2394 files, dirs = set(), set()
2388 for spec in specs:
2395 for spec in specs:
2389 f, d = complete(spec, acceptable or 'nmar')
2396 f, d = complete(spec, acceptable or 'nmar')
2390 files.update(f)
2397 files.update(f)
2391 dirs.update(d)
2398 dirs.update(d)
2392 files.update(dirs)
2399 files.update(dirs)
2393 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2400 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2394 ui.write('\n')
2401 ui.write('\n')
2395
2402
2396 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2403 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2397 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2404 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2398 '''access the pushkey key/value protocol
2405 '''access the pushkey key/value protocol
2399
2406
2400 With two args, list the keys in the given namespace.
2407 With two args, list the keys in the given namespace.
2401
2408
2402 With five args, set a key to new if it currently is set to old.
2409 With five args, set a key to new if it currently is set to old.
2403 Reports success or failure.
2410 Reports success or failure.
2404 '''
2411 '''
2405
2412
2406 target = hg.peer(ui, {}, repopath)
2413 target = hg.peer(ui, {}, repopath)
2407 if keyinfo:
2414 if keyinfo:
2408 key, old, new = keyinfo
2415 key, old, new = keyinfo
2409 r = target.pushkey(namespace, key, old, new)
2416 r = target.pushkey(namespace, key, old, new)
2410 ui.status(str(r) + '\n')
2417 ui.status(str(r) + '\n')
2411 return not r
2418 return not r
2412 else:
2419 else:
2413 for k, v in sorted(target.listkeys(namespace).iteritems()):
2420 for k, v in sorted(target.listkeys(namespace).iteritems()):
2414 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2421 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2415 v.encode('string-escape')))
2422 v.encode('string-escape')))
2416
2423
2417 @command('debugpvec', [], _('A B'))
2424 @command('debugpvec', [], _('A B'))
2418 def debugpvec(ui, repo, a, b=None):
2425 def debugpvec(ui, repo, a, b=None):
2419 ca = scmutil.revsingle(repo, a)
2426 ca = scmutil.revsingle(repo, a)
2420 cb = scmutil.revsingle(repo, b)
2427 cb = scmutil.revsingle(repo, b)
2421 pa = pvec.ctxpvec(ca)
2428 pa = pvec.ctxpvec(ca)
2422 pb = pvec.ctxpvec(cb)
2429 pb = pvec.ctxpvec(cb)
2423 if pa == pb:
2430 if pa == pb:
2424 rel = "="
2431 rel = "="
2425 elif pa > pb:
2432 elif pa > pb:
2426 rel = ">"
2433 rel = ">"
2427 elif pa < pb:
2434 elif pa < pb:
2428 rel = "<"
2435 rel = "<"
2429 elif pa | pb:
2436 elif pa | pb:
2430 rel = "|"
2437 rel = "|"
2431 ui.write(_("a: %s\n") % pa)
2438 ui.write(_("a: %s\n") % pa)
2432 ui.write(_("b: %s\n") % pb)
2439 ui.write(_("b: %s\n") % pb)
2433 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2440 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2434 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2441 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2435 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2442 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2436 pa.distance(pb), rel))
2443 pa.distance(pb), rel))
2437
2444
2438 @command('debugrebuilddirstate|debugrebuildstate',
2445 @command('debugrebuilddirstate|debugrebuildstate',
2439 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2446 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2440 _('[-r REV]'))
2447 _('[-r REV]'))
2441 def debugrebuilddirstate(ui, repo, rev):
2448 def debugrebuilddirstate(ui, repo, rev):
2442 """rebuild the dirstate as it would look like for the given revision
2449 """rebuild the dirstate as it would look like for the given revision
2443
2450
2444 If no revision is specified the first current parent will be used.
2451 If no revision is specified the first current parent will be used.
2445
2452
2446 The dirstate will be set to the files of the given revision.
2453 The dirstate will be set to the files of the given revision.
2447 The actual working directory content or existing dirstate
2454 The actual working directory content or existing dirstate
2448 information such as adds or removes is not considered.
2455 information such as adds or removes is not considered.
2449
2456
2450 One use of this command is to make the next :hg:`status` invocation
2457 One use of this command is to make the next :hg:`status` invocation
2451 check the actual file content.
2458 check the actual file content.
2452 """
2459 """
2453 ctx = scmutil.revsingle(repo, rev)
2460 ctx = scmutil.revsingle(repo, rev)
2454 wlock = repo.wlock()
2461 wlock = repo.wlock()
2455 try:
2462 try:
2456 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2463 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2457 finally:
2464 finally:
2458 wlock.release()
2465 wlock.release()
2459
2466
2460 @command('debugrename',
2467 @command('debugrename',
2461 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2468 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2462 _('[-r REV] FILE'))
2469 _('[-r REV] FILE'))
2463 def debugrename(ui, repo, file1, *pats, **opts):
2470 def debugrename(ui, repo, file1, *pats, **opts):
2464 """dump rename information"""
2471 """dump rename information"""
2465
2472
2466 ctx = scmutil.revsingle(repo, opts.get('rev'))
2473 ctx = scmutil.revsingle(repo, opts.get('rev'))
2467 m = scmutil.match(ctx, (file1,) + pats, opts)
2474 m = scmutil.match(ctx, (file1,) + pats, opts)
2468 for abs in ctx.walk(m):
2475 for abs in ctx.walk(m):
2469 fctx = ctx[abs]
2476 fctx = ctx[abs]
2470 o = fctx.filelog().renamed(fctx.filenode())
2477 o = fctx.filelog().renamed(fctx.filenode())
2471 rel = m.rel(abs)
2478 rel = m.rel(abs)
2472 if o:
2479 if o:
2473 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2480 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2474 else:
2481 else:
2475 ui.write(_("%s not renamed\n") % rel)
2482 ui.write(_("%s not renamed\n") % rel)
2476
2483
2477 @command('debugrevlog',
2484 @command('debugrevlog',
2478 [('c', 'changelog', False, _('open changelog')),
2485 [('c', 'changelog', False, _('open changelog')),
2479 ('m', 'manifest', False, _('open manifest')),
2486 ('m', 'manifest', False, _('open manifest')),
2480 ('d', 'dump', False, _('dump index data'))],
2487 ('d', 'dump', False, _('dump index data'))],
2481 _('-c|-m|FILE'))
2488 _('-c|-m|FILE'))
2482 def debugrevlog(ui, repo, file_=None, **opts):
2489 def debugrevlog(ui, repo, file_=None, **opts):
2483 """show data and statistics about a revlog"""
2490 """show data and statistics about a revlog"""
2484 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2491 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2485
2492
2486 if opts.get("dump"):
2493 if opts.get("dump"):
2487 numrevs = len(r)
2494 numrevs = len(r)
2488 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2495 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2489 " rawsize totalsize compression heads\n")
2496 " rawsize totalsize compression heads\n")
2490 ts = 0
2497 ts = 0
2491 heads = set()
2498 heads = set()
2492 for rev in xrange(numrevs):
2499 for rev in xrange(numrevs):
2493 dbase = r.deltaparent(rev)
2500 dbase = r.deltaparent(rev)
2494 if dbase == -1:
2501 if dbase == -1:
2495 dbase = rev
2502 dbase = rev
2496 cbase = r.chainbase(rev)
2503 cbase = r.chainbase(rev)
2497 p1, p2 = r.parentrevs(rev)
2504 p1, p2 = r.parentrevs(rev)
2498 rs = r.rawsize(rev)
2505 rs = r.rawsize(rev)
2499 ts = ts + rs
2506 ts = ts + rs
2500 heads -= set(r.parentrevs(rev))
2507 heads -= set(r.parentrevs(rev))
2501 heads.add(rev)
2508 heads.add(rev)
2502 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2509 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2503 (rev, p1, p2, r.start(rev), r.end(rev),
2510 (rev, p1, p2, r.start(rev), r.end(rev),
2504 r.start(dbase), r.start(cbase),
2511 r.start(dbase), r.start(cbase),
2505 r.start(p1), r.start(p2),
2512 r.start(p1), r.start(p2),
2506 rs, ts, ts / r.end(rev), len(heads)))
2513 rs, ts, ts / r.end(rev), len(heads)))
2507 return 0
2514 return 0
2508
2515
2509 v = r.version
2516 v = r.version
2510 format = v & 0xFFFF
2517 format = v & 0xFFFF
2511 flags = []
2518 flags = []
2512 gdelta = False
2519 gdelta = False
2513 if v & revlog.REVLOGNGINLINEDATA:
2520 if v & revlog.REVLOGNGINLINEDATA:
2514 flags.append('inline')
2521 flags.append('inline')
2515 if v & revlog.REVLOGGENERALDELTA:
2522 if v & revlog.REVLOGGENERALDELTA:
2516 gdelta = True
2523 gdelta = True
2517 flags.append('generaldelta')
2524 flags.append('generaldelta')
2518 if not flags:
2525 if not flags:
2519 flags = ['(none)']
2526 flags = ['(none)']
2520
2527
2521 nummerges = 0
2528 nummerges = 0
2522 numfull = 0
2529 numfull = 0
2523 numprev = 0
2530 numprev = 0
2524 nump1 = 0
2531 nump1 = 0
2525 nump2 = 0
2532 nump2 = 0
2526 numother = 0
2533 numother = 0
2527 nump1prev = 0
2534 nump1prev = 0
2528 nump2prev = 0
2535 nump2prev = 0
2529 chainlengths = []
2536 chainlengths = []
2530
2537
2531 datasize = [None, 0, 0L]
2538 datasize = [None, 0, 0L]
2532 fullsize = [None, 0, 0L]
2539 fullsize = [None, 0, 0L]
2533 deltasize = [None, 0, 0L]
2540 deltasize = [None, 0, 0L]
2534
2541
2535 def addsize(size, l):
2542 def addsize(size, l):
2536 if l[0] is None or size < l[0]:
2543 if l[0] is None or size < l[0]:
2537 l[0] = size
2544 l[0] = size
2538 if size > l[1]:
2545 if size > l[1]:
2539 l[1] = size
2546 l[1] = size
2540 l[2] += size
2547 l[2] += size
2541
2548
2542 numrevs = len(r)
2549 numrevs = len(r)
2543 for rev in xrange(numrevs):
2550 for rev in xrange(numrevs):
2544 p1, p2 = r.parentrevs(rev)
2551 p1, p2 = r.parentrevs(rev)
2545 delta = r.deltaparent(rev)
2552 delta = r.deltaparent(rev)
2546 if format > 0:
2553 if format > 0:
2547 addsize(r.rawsize(rev), datasize)
2554 addsize(r.rawsize(rev), datasize)
2548 if p2 != nullrev:
2555 if p2 != nullrev:
2549 nummerges += 1
2556 nummerges += 1
2550 size = r.length(rev)
2557 size = r.length(rev)
2551 if delta == nullrev:
2558 if delta == nullrev:
2552 chainlengths.append(0)
2559 chainlengths.append(0)
2553 numfull += 1
2560 numfull += 1
2554 addsize(size, fullsize)
2561 addsize(size, fullsize)
2555 else:
2562 else:
2556 chainlengths.append(chainlengths[delta] + 1)
2563 chainlengths.append(chainlengths[delta] + 1)
2557 addsize(size, deltasize)
2564 addsize(size, deltasize)
2558 if delta == rev - 1:
2565 if delta == rev - 1:
2559 numprev += 1
2566 numprev += 1
2560 if delta == p1:
2567 if delta == p1:
2561 nump1prev += 1
2568 nump1prev += 1
2562 elif delta == p2:
2569 elif delta == p2:
2563 nump2prev += 1
2570 nump2prev += 1
2564 elif delta == p1:
2571 elif delta == p1:
2565 nump1 += 1
2572 nump1 += 1
2566 elif delta == p2:
2573 elif delta == p2:
2567 nump2 += 1
2574 nump2 += 1
2568 elif delta != nullrev:
2575 elif delta != nullrev:
2569 numother += 1
2576 numother += 1
2570
2577
2571 # Adjust size min value for empty cases
2578 # Adjust size min value for empty cases
2572 for size in (datasize, fullsize, deltasize):
2579 for size in (datasize, fullsize, deltasize):
2573 if size[0] is None:
2580 if size[0] is None:
2574 size[0] = 0
2581 size[0] = 0
2575
2582
2576 numdeltas = numrevs - numfull
2583 numdeltas = numrevs - numfull
2577 numoprev = numprev - nump1prev - nump2prev
2584 numoprev = numprev - nump1prev - nump2prev
2578 totalrawsize = datasize[2]
2585 totalrawsize = datasize[2]
2579 datasize[2] /= numrevs
2586 datasize[2] /= numrevs
2580 fulltotal = fullsize[2]
2587 fulltotal = fullsize[2]
2581 fullsize[2] /= numfull
2588 fullsize[2] /= numfull
2582 deltatotal = deltasize[2]
2589 deltatotal = deltasize[2]
2583 if numrevs - numfull > 0:
2590 if numrevs - numfull > 0:
2584 deltasize[2] /= numrevs - numfull
2591 deltasize[2] /= numrevs - numfull
2585 totalsize = fulltotal + deltatotal
2592 totalsize = fulltotal + deltatotal
2586 avgchainlen = sum(chainlengths) / numrevs
2593 avgchainlen = sum(chainlengths) / numrevs
2587 compratio = totalrawsize / totalsize
2594 compratio = totalrawsize / totalsize
2588
2595
2589 basedfmtstr = '%%%dd\n'
2596 basedfmtstr = '%%%dd\n'
2590 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2597 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2591
2598
2592 def dfmtstr(max):
2599 def dfmtstr(max):
2593 return basedfmtstr % len(str(max))
2600 return basedfmtstr % len(str(max))
2594 def pcfmtstr(max, padding=0):
2601 def pcfmtstr(max, padding=0):
2595 return basepcfmtstr % (len(str(max)), ' ' * padding)
2602 return basepcfmtstr % (len(str(max)), ' ' * padding)
2596
2603
2597 def pcfmt(value, total):
2604 def pcfmt(value, total):
2598 return (value, 100 * float(value) / total)
2605 return (value, 100 * float(value) / total)
2599
2606
2600 ui.write(('format : %d\n') % format)
2607 ui.write(('format : %d\n') % format)
2601 ui.write(('flags : %s\n') % ', '.join(flags))
2608 ui.write(('flags : %s\n') % ', '.join(flags))
2602
2609
2603 ui.write('\n')
2610 ui.write('\n')
2604 fmt = pcfmtstr(totalsize)
2611 fmt = pcfmtstr(totalsize)
2605 fmt2 = dfmtstr(totalsize)
2612 fmt2 = dfmtstr(totalsize)
2606 ui.write(('revisions : ') + fmt2 % numrevs)
2613 ui.write(('revisions : ') + fmt2 % numrevs)
2607 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2614 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2608 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2615 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2609 ui.write(('revisions : ') + fmt2 % numrevs)
2616 ui.write(('revisions : ') + fmt2 % numrevs)
2610 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2617 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2611 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2618 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2612 ui.write(('revision size : ') + fmt2 % totalsize)
2619 ui.write(('revision size : ') + fmt2 % totalsize)
2613 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2620 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2614 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2621 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2615
2622
2616 ui.write('\n')
2623 ui.write('\n')
2617 fmt = dfmtstr(max(avgchainlen, compratio))
2624 fmt = dfmtstr(max(avgchainlen, compratio))
2618 ui.write(('avg chain length : ') + fmt % avgchainlen)
2625 ui.write(('avg chain length : ') + fmt % avgchainlen)
2619 ui.write(('compression ratio : ') + fmt % compratio)
2626 ui.write(('compression ratio : ') + fmt % compratio)
2620
2627
2621 if format > 0:
2628 if format > 0:
2622 ui.write('\n')
2629 ui.write('\n')
2623 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2630 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2624 % tuple(datasize))
2631 % tuple(datasize))
2625 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2632 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2626 % tuple(fullsize))
2633 % tuple(fullsize))
2627 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2634 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2628 % tuple(deltasize))
2635 % tuple(deltasize))
2629
2636
2630 if numdeltas > 0:
2637 if numdeltas > 0:
2631 ui.write('\n')
2638 ui.write('\n')
2632 fmt = pcfmtstr(numdeltas)
2639 fmt = pcfmtstr(numdeltas)
2633 fmt2 = pcfmtstr(numdeltas, 4)
2640 fmt2 = pcfmtstr(numdeltas, 4)
2634 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2641 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2635 if numprev > 0:
2642 if numprev > 0:
2636 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2643 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2637 numprev))
2644 numprev))
2638 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2645 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2639 numprev))
2646 numprev))
2640 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2647 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2641 numprev))
2648 numprev))
2642 if gdelta:
2649 if gdelta:
2643 ui.write(('deltas against p1 : ')
2650 ui.write(('deltas against p1 : ')
2644 + fmt % pcfmt(nump1, numdeltas))
2651 + fmt % pcfmt(nump1, numdeltas))
2645 ui.write(('deltas against p2 : ')
2652 ui.write(('deltas against p2 : ')
2646 + fmt % pcfmt(nump2, numdeltas))
2653 + fmt % pcfmt(nump2, numdeltas))
2647 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2654 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2648 numdeltas))
2655 numdeltas))
2649
2656
2650 @command('debugrevspec',
2657 @command('debugrevspec',
2651 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2658 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2652 ('REVSPEC'))
2659 ('REVSPEC'))
2653 def debugrevspec(ui, repo, expr, **opts):
2660 def debugrevspec(ui, repo, expr, **opts):
2654 """parse and apply a revision specification
2661 """parse and apply a revision specification
2655
2662
2656 Use --verbose to print the parsed tree before and after aliases
2663 Use --verbose to print the parsed tree before and after aliases
2657 expansion.
2664 expansion.
2658 """
2665 """
2659 if ui.verbose:
2666 if ui.verbose:
2660 tree = revset.parse(expr)[0]
2667 tree = revset.parse(expr)[0]
2661 ui.note(revset.prettyformat(tree), "\n")
2668 ui.note(revset.prettyformat(tree), "\n")
2662 newtree = revset.findaliases(ui, tree)
2669 newtree = revset.findaliases(ui, tree)
2663 if newtree != tree:
2670 if newtree != tree:
2664 ui.note(revset.prettyformat(newtree), "\n")
2671 ui.note(revset.prettyformat(newtree), "\n")
2665 if opts["optimize"]:
2672 if opts["optimize"]:
2666 weight, optimizedtree = revset.optimize(newtree, True)
2673 weight, optimizedtree = revset.optimize(newtree, True)
2667 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2674 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2668 func = revset.match(ui, expr)
2675 func = revset.match(ui, expr)
2669 for c in func(repo, revset.spanset(repo)):
2676 for c in func(repo, revset.spanset(repo)):
2670 ui.write("%s\n" % c)
2677 ui.write("%s\n" % c)
2671
2678
2672 @command('debugsetparents', [], _('REV1 [REV2]'))
2679 @command('debugsetparents', [], _('REV1 [REV2]'))
2673 def debugsetparents(ui, repo, rev1, rev2=None):
2680 def debugsetparents(ui, repo, rev1, rev2=None):
2674 """manually set the parents of the current working directory
2681 """manually set the parents of the current working directory
2675
2682
2676 This is useful for writing repository conversion tools, but should
2683 This is useful for writing repository conversion tools, but should
2677 be used with care.
2684 be used with care.
2678
2685
2679 Returns 0 on success.
2686 Returns 0 on success.
2680 """
2687 """
2681
2688
2682 r1 = scmutil.revsingle(repo, rev1).node()
2689 r1 = scmutil.revsingle(repo, rev1).node()
2683 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2690 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2684
2691
2685 wlock = repo.wlock()
2692 wlock = repo.wlock()
2686 try:
2693 try:
2687 repo.setparents(r1, r2)
2694 repo.setparents(r1, r2)
2688 finally:
2695 finally:
2689 wlock.release()
2696 wlock.release()
2690
2697
2691 @command('debugdirstate|debugstate',
2698 @command('debugdirstate|debugstate',
2692 [('', 'nodates', None, _('do not display the saved mtime')),
2699 [('', 'nodates', None, _('do not display the saved mtime')),
2693 ('', 'datesort', None, _('sort by saved mtime'))],
2700 ('', 'datesort', None, _('sort by saved mtime'))],
2694 _('[OPTION]...'))
2701 _('[OPTION]...'))
2695 def debugstate(ui, repo, nodates=None, datesort=None):
2702 def debugstate(ui, repo, nodates=None, datesort=None):
2696 """show the contents of the current dirstate"""
2703 """show the contents of the current dirstate"""
2697 timestr = ""
2704 timestr = ""
2698 showdate = not nodates
2705 showdate = not nodates
2699 if datesort:
2706 if datesort:
2700 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2707 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2701 else:
2708 else:
2702 keyfunc = None # sort by filename
2709 keyfunc = None # sort by filename
2703 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2710 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2704 if showdate:
2711 if showdate:
2705 if ent[3] == -1:
2712 if ent[3] == -1:
2706 # Pad or slice to locale representation
2713 # Pad or slice to locale representation
2707 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2714 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2708 time.localtime(0)))
2715 time.localtime(0)))
2709 timestr = 'unset'
2716 timestr = 'unset'
2710 timestr = (timestr[:locale_len] +
2717 timestr = (timestr[:locale_len] +
2711 ' ' * (locale_len - len(timestr)))
2718 ' ' * (locale_len - len(timestr)))
2712 else:
2719 else:
2713 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2720 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2714 time.localtime(ent[3]))
2721 time.localtime(ent[3]))
2715 if ent[1] & 020000:
2722 if ent[1] & 020000:
2716 mode = 'lnk'
2723 mode = 'lnk'
2717 else:
2724 else:
2718 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2725 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2719 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2726 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2720 for f in repo.dirstate.copies():
2727 for f in repo.dirstate.copies():
2721 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2728 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2722
2729
2723 @command('debugsub',
2730 @command('debugsub',
2724 [('r', 'rev', '',
2731 [('r', 'rev', '',
2725 _('revision to check'), _('REV'))],
2732 _('revision to check'), _('REV'))],
2726 _('[-r REV] [REV]'))
2733 _('[-r REV] [REV]'))
2727 def debugsub(ui, repo, rev=None):
2734 def debugsub(ui, repo, rev=None):
2728 ctx = scmutil.revsingle(repo, rev, None)
2735 ctx = scmutil.revsingle(repo, rev, None)
2729 for k, v in sorted(ctx.substate.items()):
2736 for k, v in sorted(ctx.substate.items()):
2730 ui.write(('path %s\n') % k)
2737 ui.write(('path %s\n') % k)
2731 ui.write((' source %s\n') % v[0])
2738 ui.write((' source %s\n') % v[0])
2732 ui.write((' revision %s\n') % v[1])
2739 ui.write((' revision %s\n') % v[1])
2733
2740
2734 @command('debugsuccessorssets',
2741 @command('debugsuccessorssets',
2735 [],
2742 [],
2736 _('[REV]'))
2743 _('[REV]'))
2737 def debugsuccessorssets(ui, repo, *revs):
2744 def debugsuccessorssets(ui, repo, *revs):
2738 """show set of successors for revision
2745 """show set of successors for revision
2739
2746
2740 A successors set of changeset A is a consistent group of revisions that
2747 A successors set of changeset A is a consistent group of revisions that
2741 succeed A. It contains non-obsolete changesets only.
2748 succeed A. It contains non-obsolete changesets only.
2742
2749
2743 In most cases a changeset A has a single successors set containing a single
2750 In most cases a changeset A has a single successors set containing a single
2744 successor (changeset A replaced by A').
2751 successor (changeset A replaced by A').
2745
2752
2746 A changeset that is made obsolete with no successors are called "pruned".
2753 A changeset that is made obsolete with no successors are called "pruned".
2747 Such changesets have no successors sets at all.
2754 Such changesets have no successors sets at all.
2748
2755
2749 A changeset that has been "split" will have a successors set containing
2756 A changeset that has been "split" will have a successors set containing
2750 more than one successor.
2757 more than one successor.
2751
2758
2752 A changeset that has been rewritten in multiple different ways is called
2759 A changeset that has been rewritten in multiple different ways is called
2753 "divergent". Such changesets have multiple successor sets (each of which
2760 "divergent". Such changesets have multiple successor sets (each of which
2754 may also be split, i.e. have multiple successors).
2761 may also be split, i.e. have multiple successors).
2755
2762
2756 Results are displayed as follows::
2763 Results are displayed as follows::
2757
2764
2758 <rev1>
2765 <rev1>
2759 <successors-1A>
2766 <successors-1A>
2760 <rev2>
2767 <rev2>
2761 <successors-2A>
2768 <successors-2A>
2762 <successors-2B1> <successors-2B2> <successors-2B3>
2769 <successors-2B1> <successors-2B2> <successors-2B3>
2763
2770
2764 Here rev2 has two possible (i.e. divergent) successors sets. The first
2771 Here rev2 has two possible (i.e. divergent) successors sets. The first
2765 holds one element, whereas the second holds three (i.e. the changeset has
2772 holds one element, whereas the second holds three (i.e. the changeset has
2766 been split).
2773 been split).
2767 """
2774 """
2768 # passed to successorssets caching computation from one call to another
2775 # passed to successorssets caching computation from one call to another
2769 cache = {}
2776 cache = {}
2770 ctx2str = str
2777 ctx2str = str
2771 node2str = short
2778 node2str = short
2772 if ui.debug():
2779 if ui.debug():
2773 def ctx2str(ctx):
2780 def ctx2str(ctx):
2774 return ctx.hex()
2781 return ctx.hex()
2775 node2str = hex
2782 node2str = hex
2776 for rev in scmutil.revrange(repo, revs):
2783 for rev in scmutil.revrange(repo, revs):
2777 ctx = repo[rev]
2784 ctx = repo[rev]
2778 ui.write('%s\n'% ctx2str(ctx))
2785 ui.write('%s\n'% ctx2str(ctx))
2779 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2786 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2780 if succsset:
2787 if succsset:
2781 ui.write(' ')
2788 ui.write(' ')
2782 ui.write(node2str(succsset[0]))
2789 ui.write(node2str(succsset[0]))
2783 for node in succsset[1:]:
2790 for node in succsset[1:]:
2784 ui.write(' ')
2791 ui.write(' ')
2785 ui.write(node2str(node))
2792 ui.write(node2str(node))
2786 ui.write('\n')
2793 ui.write('\n')
2787
2794
2788 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2795 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2789 def debugwalk(ui, repo, *pats, **opts):
2796 def debugwalk(ui, repo, *pats, **opts):
2790 """show how files match on given patterns"""
2797 """show how files match on given patterns"""
2791 m = scmutil.match(repo[None], pats, opts)
2798 m = scmutil.match(repo[None], pats, opts)
2792 items = list(repo.walk(m))
2799 items = list(repo.walk(m))
2793 if not items:
2800 if not items:
2794 return
2801 return
2795 f = lambda fn: fn
2802 f = lambda fn: fn
2796 if ui.configbool('ui', 'slash') and os.sep != '/':
2803 if ui.configbool('ui', 'slash') and os.sep != '/':
2797 f = lambda fn: util.normpath(fn)
2804 f = lambda fn: util.normpath(fn)
2798 fmt = 'f %%-%ds %%-%ds %%s' % (
2805 fmt = 'f %%-%ds %%-%ds %%s' % (
2799 max([len(abs) for abs in items]),
2806 max([len(abs) for abs in items]),
2800 max([len(m.rel(abs)) for abs in items]))
2807 max([len(m.rel(abs)) for abs in items]))
2801 for abs in items:
2808 for abs in items:
2802 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2809 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2803 ui.write("%s\n" % line.rstrip())
2810 ui.write("%s\n" % line.rstrip())
2804
2811
2805 @command('debugwireargs',
2812 @command('debugwireargs',
2806 [('', 'three', '', 'three'),
2813 [('', 'three', '', 'three'),
2807 ('', 'four', '', 'four'),
2814 ('', 'four', '', 'four'),
2808 ('', 'five', '', 'five'),
2815 ('', 'five', '', 'five'),
2809 ] + remoteopts,
2816 ] + remoteopts,
2810 _('REPO [OPTIONS]... [ONE [TWO]]'))
2817 _('REPO [OPTIONS]... [ONE [TWO]]'),
2818 norepo=True)
2811 def debugwireargs(ui, repopath, *vals, **opts):
2819 def debugwireargs(ui, repopath, *vals, **opts):
2812 repo = hg.peer(ui, opts, repopath)
2820 repo = hg.peer(ui, opts, repopath)
2813 for opt in remoteopts:
2821 for opt in remoteopts:
2814 del opts[opt[1]]
2822 del opts[opt[1]]
2815 args = {}
2823 args = {}
2816 for k, v in opts.iteritems():
2824 for k, v in opts.iteritems():
2817 if v:
2825 if v:
2818 args[k] = v
2826 args[k] = v
2819 # run twice to check that we don't mess up the stream for the next command
2827 # run twice to check that we don't mess up the stream for the next command
2820 res1 = repo.debugwireargs(*vals, **args)
2828 res1 = repo.debugwireargs(*vals, **args)
2821 res2 = repo.debugwireargs(*vals, **args)
2829 res2 = repo.debugwireargs(*vals, **args)
2822 ui.write("%s\n" % res1)
2830 ui.write("%s\n" % res1)
2823 if res1 != res2:
2831 if res1 != res2:
2824 ui.warn("%s\n" % res2)
2832 ui.warn("%s\n" % res2)
2825
2833
2826 @command('^diff',
2834 @command('^diff',
2827 [('r', 'rev', [], _('revision'), _('REV')),
2835 [('r', 'rev', [], _('revision'), _('REV')),
2828 ('c', 'change', '', _('change made by revision'), _('REV'))
2836 ('c', 'change', '', _('change made by revision'), _('REV'))
2829 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2837 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2830 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2838 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2831 def diff(ui, repo, *pats, **opts):
2839 def diff(ui, repo, *pats, **opts):
2832 """diff repository (or selected files)
2840 """diff repository (or selected files)
2833
2841
2834 Show differences between revisions for the specified files.
2842 Show differences between revisions for the specified files.
2835
2843
2836 Differences between files are shown using the unified diff format.
2844 Differences between files are shown using the unified diff format.
2837
2845
2838 .. note::
2846 .. note::
2839
2847
2840 diff may generate unexpected results for merges, as it will
2848 diff may generate unexpected results for merges, as it will
2841 default to comparing against the working directory's first
2849 default to comparing against the working directory's first
2842 parent changeset if no revisions are specified.
2850 parent changeset if no revisions are specified.
2843
2851
2844 When two revision arguments are given, then changes are shown
2852 When two revision arguments are given, then changes are shown
2845 between those revisions. If only one revision is specified then
2853 between those revisions. If only one revision is specified then
2846 that revision is compared to the working directory, and, when no
2854 that revision is compared to the working directory, and, when no
2847 revisions are specified, the working directory files are compared
2855 revisions are specified, the working directory files are compared
2848 to its parent.
2856 to its parent.
2849
2857
2850 Alternatively you can specify -c/--change with a revision to see
2858 Alternatively you can specify -c/--change with a revision to see
2851 the changes in that changeset relative to its first parent.
2859 the changes in that changeset relative to its first parent.
2852
2860
2853 Without the -a/--text option, diff will avoid generating diffs of
2861 Without the -a/--text option, diff will avoid generating diffs of
2854 files it detects as binary. With -a, diff will generate a diff
2862 files it detects as binary. With -a, diff will generate a diff
2855 anyway, probably with undesirable results.
2863 anyway, probably with undesirable results.
2856
2864
2857 Use the -g/--git option to generate diffs in the git extended diff
2865 Use the -g/--git option to generate diffs in the git extended diff
2858 format. For more information, read :hg:`help diffs`.
2866 format. For more information, read :hg:`help diffs`.
2859
2867
2860 .. container:: verbose
2868 .. container:: verbose
2861
2869
2862 Examples:
2870 Examples:
2863
2871
2864 - compare a file in the current working directory to its parent::
2872 - compare a file in the current working directory to its parent::
2865
2873
2866 hg diff foo.c
2874 hg diff foo.c
2867
2875
2868 - compare two historical versions of a directory, with rename info::
2876 - compare two historical versions of a directory, with rename info::
2869
2877
2870 hg diff --git -r 1.0:1.2 lib/
2878 hg diff --git -r 1.0:1.2 lib/
2871
2879
2872 - get change stats relative to the last change on some date::
2880 - get change stats relative to the last change on some date::
2873
2881
2874 hg diff --stat -r "date('may 2')"
2882 hg diff --stat -r "date('may 2')"
2875
2883
2876 - diff all newly-added files that contain a keyword::
2884 - diff all newly-added files that contain a keyword::
2877
2885
2878 hg diff "set:added() and grep(GNU)"
2886 hg diff "set:added() and grep(GNU)"
2879
2887
2880 - compare a revision and its parents::
2888 - compare a revision and its parents::
2881
2889
2882 hg diff -c 9353 # compare against first parent
2890 hg diff -c 9353 # compare against first parent
2883 hg diff -r 9353^:9353 # same using revset syntax
2891 hg diff -r 9353^:9353 # same using revset syntax
2884 hg diff -r 9353^2:9353 # compare against the second parent
2892 hg diff -r 9353^2:9353 # compare against the second parent
2885
2893
2886 Returns 0 on success.
2894 Returns 0 on success.
2887 """
2895 """
2888
2896
2889 revs = opts.get('rev')
2897 revs = opts.get('rev')
2890 change = opts.get('change')
2898 change = opts.get('change')
2891 stat = opts.get('stat')
2899 stat = opts.get('stat')
2892 reverse = opts.get('reverse')
2900 reverse = opts.get('reverse')
2893
2901
2894 if revs and change:
2902 if revs and change:
2895 msg = _('cannot specify --rev and --change at the same time')
2903 msg = _('cannot specify --rev and --change at the same time')
2896 raise util.Abort(msg)
2904 raise util.Abort(msg)
2897 elif change:
2905 elif change:
2898 node2 = scmutil.revsingle(repo, change, None).node()
2906 node2 = scmutil.revsingle(repo, change, None).node()
2899 node1 = repo[node2].p1().node()
2907 node1 = repo[node2].p1().node()
2900 else:
2908 else:
2901 node1, node2 = scmutil.revpair(repo, revs)
2909 node1, node2 = scmutil.revpair(repo, revs)
2902
2910
2903 if reverse:
2911 if reverse:
2904 node1, node2 = node2, node1
2912 node1, node2 = node2, node1
2905
2913
2906 diffopts = patch.diffopts(ui, opts)
2914 diffopts = patch.diffopts(ui, opts)
2907 m = scmutil.match(repo[node2], pats, opts)
2915 m = scmutil.match(repo[node2], pats, opts)
2908 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2916 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2909 listsubrepos=opts.get('subrepos'))
2917 listsubrepos=opts.get('subrepos'))
2910
2918
2911 @command('^export',
2919 @command('^export',
2912 [('o', 'output', '',
2920 [('o', 'output', '',
2913 _('print output to file with formatted name'), _('FORMAT')),
2921 _('print output to file with formatted name'), _('FORMAT')),
2914 ('', 'switch-parent', None, _('diff against the second parent')),
2922 ('', 'switch-parent', None, _('diff against the second parent')),
2915 ('r', 'rev', [], _('revisions to export'), _('REV')),
2923 ('r', 'rev', [], _('revisions to export'), _('REV')),
2916 ] + diffopts,
2924 ] + diffopts,
2917 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2925 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2918 def export(ui, repo, *changesets, **opts):
2926 def export(ui, repo, *changesets, **opts):
2919 """dump the header and diffs for one or more changesets
2927 """dump the header and diffs for one or more changesets
2920
2928
2921 Print the changeset header and diffs for one or more revisions.
2929 Print the changeset header and diffs for one or more revisions.
2922 If no revision is given, the parent of the working directory is used.
2930 If no revision is given, the parent of the working directory is used.
2923
2931
2924 The information shown in the changeset header is: author, date,
2932 The information shown in the changeset header is: author, date,
2925 branch name (if non-default), changeset hash, parent(s) and commit
2933 branch name (if non-default), changeset hash, parent(s) and commit
2926 comment.
2934 comment.
2927
2935
2928 .. note::
2936 .. note::
2929
2937
2930 export may generate unexpected diff output for merge
2938 export may generate unexpected diff output for merge
2931 changesets, as it will compare the merge changeset against its
2939 changesets, as it will compare the merge changeset against its
2932 first parent only.
2940 first parent only.
2933
2941
2934 Output may be to a file, in which case the name of the file is
2942 Output may be to a file, in which case the name of the file is
2935 given using a format string. The formatting rules are as follows:
2943 given using a format string. The formatting rules are as follows:
2936
2944
2937 :``%%``: literal "%" character
2945 :``%%``: literal "%" character
2938 :``%H``: changeset hash (40 hexadecimal digits)
2946 :``%H``: changeset hash (40 hexadecimal digits)
2939 :``%N``: number of patches being generated
2947 :``%N``: number of patches being generated
2940 :``%R``: changeset revision number
2948 :``%R``: changeset revision number
2941 :``%b``: basename of the exporting repository
2949 :``%b``: basename of the exporting repository
2942 :``%h``: short-form changeset hash (12 hexadecimal digits)
2950 :``%h``: short-form changeset hash (12 hexadecimal digits)
2943 :``%m``: first line of the commit message (only alphanumeric characters)
2951 :``%m``: first line of the commit message (only alphanumeric characters)
2944 :``%n``: zero-padded sequence number, starting at 1
2952 :``%n``: zero-padded sequence number, starting at 1
2945 :``%r``: zero-padded changeset revision number
2953 :``%r``: zero-padded changeset revision number
2946
2954
2947 Without the -a/--text option, export will avoid generating diffs
2955 Without the -a/--text option, export will avoid generating diffs
2948 of files it detects as binary. With -a, export will generate a
2956 of files it detects as binary. With -a, export will generate a
2949 diff anyway, probably with undesirable results.
2957 diff anyway, probably with undesirable results.
2950
2958
2951 Use the -g/--git option to generate diffs in the git extended diff
2959 Use the -g/--git option to generate diffs in the git extended diff
2952 format. See :hg:`help diffs` for more information.
2960 format. See :hg:`help diffs` for more information.
2953
2961
2954 With the --switch-parent option, the diff will be against the
2962 With the --switch-parent option, the diff will be against the
2955 second parent. It can be useful to review a merge.
2963 second parent. It can be useful to review a merge.
2956
2964
2957 .. container:: verbose
2965 .. container:: verbose
2958
2966
2959 Examples:
2967 Examples:
2960
2968
2961 - use export and import to transplant a bugfix to the current
2969 - use export and import to transplant a bugfix to the current
2962 branch::
2970 branch::
2963
2971
2964 hg export -r 9353 | hg import -
2972 hg export -r 9353 | hg import -
2965
2973
2966 - export all the changesets between two revisions to a file with
2974 - export all the changesets between two revisions to a file with
2967 rename information::
2975 rename information::
2968
2976
2969 hg export --git -r 123:150 > changes.txt
2977 hg export --git -r 123:150 > changes.txt
2970
2978
2971 - split outgoing changes into a series of patches with
2979 - split outgoing changes into a series of patches with
2972 descriptive names::
2980 descriptive names::
2973
2981
2974 hg export -r "outgoing()" -o "%n-%m.patch"
2982 hg export -r "outgoing()" -o "%n-%m.patch"
2975
2983
2976 Returns 0 on success.
2984 Returns 0 on success.
2977 """
2985 """
2978 changesets += tuple(opts.get('rev', []))
2986 changesets += tuple(opts.get('rev', []))
2979 if not changesets:
2987 if not changesets:
2980 changesets = ['.']
2988 changesets = ['.']
2981 revs = scmutil.revrange(repo, changesets)
2989 revs = scmutil.revrange(repo, changesets)
2982 if not revs:
2990 if not revs:
2983 raise util.Abort(_("export requires at least one changeset"))
2991 raise util.Abort(_("export requires at least one changeset"))
2984 if len(revs) > 1:
2992 if len(revs) > 1:
2985 ui.note(_('exporting patches:\n'))
2993 ui.note(_('exporting patches:\n'))
2986 else:
2994 else:
2987 ui.note(_('exporting patch:\n'))
2995 ui.note(_('exporting patch:\n'))
2988 cmdutil.export(repo, revs, template=opts.get('output'),
2996 cmdutil.export(repo, revs, template=opts.get('output'),
2989 switch_parent=opts.get('switch_parent'),
2997 switch_parent=opts.get('switch_parent'),
2990 opts=patch.diffopts(ui, opts))
2998 opts=patch.diffopts(ui, opts))
2991
2999
2992 @command('^forget', walkopts, _('[OPTION]... FILE...'))
3000 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2993 def forget(ui, repo, *pats, **opts):
3001 def forget(ui, repo, *pats, **opts):
2994 """forget the specified files on the next commit
3002 """forget the specified files on the next commit
2995
3003
2996 Mark the specified files so they will no longer be tracked
3004 Mark the specified files so they will no longer be tracked
2997 after the next commit.
3005 after the next commit.
2998
3006
2999 This only removes files from the current branch, not from the
3007 This only removes files from the current branch, not from the
3000 entire project history, and it does not delete them from the
3008 entire project history, and it does not delete them from the
3001 working directory.
3009 working directory.
3002
3010
3003 To undo a forget before the next commit, see :hg:`add`.
3011 To undo a forget before the next commit, see :hg:`add`.
3004
3012
3005 .. container:: verbose
3013 .. container:: verbose
3006
3014
3007 Examples:
3015 Examples:
3008
3016
3009 - forget newly-added binary files::
3017 - forget newly-added binary files::
3010
3018
3011 hg forget "set:added() and binary()"
3019 hg forget "set:added() and binary()"
3012
3020
3013 - forget files that would be excluded by .hgignore::
3021 - forget files that would be excluded by .hgignore::
3014
3022
3015 hg forget "set:hgignore()"
3023 hg forget "set:hgignore()"
3016
3024
3017 Returns 0 on success.
3025 Returns 0 on success.
3018 """
3026 """
3019
3027
3020 if not pats:
3028 if not pats:
3021 raise util.Abort(_('no files specified'))
3029 raise util.Abort(_('no files specified'))
3022
3030
3023 m = scmutil.match(repo[None], pats, opts)
3031 m = scmutil.match(repo[None], pats, opts)
3024 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3032 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3025 return rejected and 1 or 0
3033 return rejected and 1 or 0
3026
3034
3027 @command(
3035 @command(
3028 'graft',
3036 'graft',
3029 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3037 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3030 ('c', 'continue', False, _('resume interrupted graft')),
3038 ('c', 'continue', False, _('resume interrupted graft')),
3031 ('e', 'edit', False, _('invoke editor on commit messages')),
3039 ('e', 'edit', False, _('invoke editor on commit messages')),
3032 ('', 'log', None, _('append graft info to log message')),
3040 ('', 'log', None, _('append graft info to log message')),
3033 ('D', 'currentdate', False,
3041 ('D', 'currentdate', False,
3034 _('record the current date as commit date')),
3042 _('record the current date as commit date')),
3035 ('U', 'currentuser', False,
3043 ('U', 'currentuser', False,
3036 _('record the current user as committer'), _('DATE'))]
3044 _('record the current user as committer'), _('DATE'))]
3037 + commitopts2 + mergetoolopts + dryrunopts,
3045 + commitopts2 + mergetoolopts + dryrunopts,
3038 _('[OPTION]... [-r] REV...'))
3046 _('[OPTION]... [-r] REV...'))
3039 def graft(ui, repo, *revs, **opts):
3047 def graft(ui, repo, *revs, **opts):
3040 '''copy changes from other branches onto the current branch
3048 '''copy changes from other branches onto the current branch
3041
3049
3042 This command uses Mercurial's merge logic to copy individual
3050 This command uses Mercurial's merge logic to copy individual
3043 changes from other branches without merging branches in the
3051 changes from other branches without merging branches in the
3044 history graph. This is sometimes known as 'backporting' or
3052 history graph. This is sometimes known as 'backporting' or
3045 'cherry-picking'. By default, graft will copy user, date, and
3053 'cherry-picking'. By default, graft will copy user, date, and
3046 description from the source changesets.
3054 description from the source changesets.
3047
3055
3048 Changesets that are ancestors of the current revision, that have
3056 Changesets that are ancestors of the current revision, that have
3049 already been grafted, or that are merges will be skipped.
3057 already been grafted, or that are merges will be skipped.
3050
3058
3051 If --log is specified, log messages will have a comment appended
3059 If --log is specified, log messages will have a comment appended
3052 of the form::
3060 of the form::
3053
3061
3054 (grafted from CHANGESETHASH)
3062 (grafted from CHANGESETHASH)
3055
3063
3056 If a graft merge results in conflicts, the graft process is
3064 If a graft merge results in conflicts, the graft process is
3057 interrupted so that the current merge can be manually resolved.
3065 interrupted so that the current merge can be manually resolved.
3058 Once all conflicts are addressed, the graft process can be
3066 Once all conflicts are addressed, the graft process can be
3059 continued with the -c/--continue option.
3067 continued with the -c/--continue option.
3060
3068
3061 .. note::
3069 .. note::
3062
3070
3063 The -c/--continue option does not reapply earlier options.
3071 The -c/--continue option does not reapply earlier options.
3064
3072
3065 .. container:: verbose
3073 .. container:: verbose
3066
3074
3067 Examples:
3075 Examples:
3068
3076
3069 - copy a single change to the stable branch and edit its description::
3077 - copy a single change to the stable branch and edit its description::
3070
3078
3071 hg update stable
3079 hg update stable
3072 hg graft --edit 9393
3080 hg graft --edit 9393
3073
3081
3074 - graft a range of changesets with one exception, updating dates::
3082 - graft a range of changesets with one exception, updating dates::
3075
3083
3076 hg graft -D "2085::2093 and not 2091"
3084 hg graft -D "2085::2093 and not 2091"
3077
3085
3078 - continue a graft after resolving conflicts::
3086 - continue a graft after resolving conflicts::
3079
3087
3080 hg graft -c
3088 hg graft -c
3081
3089
3082 - show the source of a grafted changeset::
3090 - show the source of a grafted changeset::
3083
3091
3084 hg log --debug -r .
3092 hg log --debug -r .
3085
3093
3086 Returns 0 on successful completion.
3094 Returns 0 on successful completion.
3087 '''
3095 '''
3088
3096
3089 revs = list(revs)
3097 revs = list(revs)
3090 revs.extend(opts['rev'])
3098 revs.extend(opts['rev'])
3091
3099
3092 if not opts.get('user') and opts.get('currentuser'):
3100 if not opts.get('user') and opts.get('currentuser'):
3093 opts['user'] = ui.username()
3101 opts['user'] = ui.username()
3094 if not opts.get('date') and opts.get('currentdate'):
3102 if not opts.get('date') and opts.get('currentdate'):
3095 opts['date'] = "%d %d" % util.makedate()
3103 opts['date'] = "%d %d" % util.makedate()
3096
3104
3097 editor = cmdutil.getcommiteditor(**opts)
3105 editor = cmdutil.getcommiteditor(**opts)
3098
3106
3099 cont = False
3107 cont = False
3100 if opts['continue']:
3108 if opts['continue']:
3101 cont = True
3109 cont = True
3102 if revs:
3110 if revs:
3103 raise util.Abort(_("can't specify --continue and revisions"))
3111 raise util.Abort(_("can't specify --continue and revisions"))
3104 # read in unfinished revisions
3112 # read in unfinished revisions
3105 try:
3113 try:
3106 nodes = repo.opener.read('graftstate').splitlines()
3114 nodes = repo.opener.read('graftstate').splitlines()
3107 revs = [repo[node].rev() for node in nodes]
3115 revs = [repo[node].rev() for node in nodes]
3108 except IOError, inst:
3116 except IOError, inst:
3109 if inst.errno != errno.ENOENT:
3117 if inst.errno != errno.ENOENT:
3110 raise
3118 raise
3111 raise util.Abort(_("no graft state found, can't continue"))
3119 raise util.Abort(_("no graft state found, can't continue"))
3112 else:
3120 else:
3113 cmdutil.checkunfinished(repo)
3121 cmdutil.checkunfinished(repo)
3114 cmdutil.bailifchanged(repo)
3122 cmdutil.bailifchanged(repo)
3115 if not revs:
3123 if not revs:
3116 raise util.Abort(_('no revisions specified'))
3124 raise util.Abort(_('no revisions specified'))
3117 revs = scmutil.revrange(repo, revs)
3125 revs = scmutil.revrange(repo, revs)
3118
3126
3119 # check for merges
3127 # check for merges
3120 for rev in repo.revs('%ld and merge()', revs):
3128 for rev in repo.revs('%ld and merge()', revs):
3121 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3129 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3122 revs.remove(rev)
3130 revs.remove(rev)
3123 if not revs:
3131 if not revs:
3124 return -1
3132 return -1
3125
3133
3126 # check for ancestors of dest branch
3134 # check for ancestors of dest branch
3127 crev = repo['.'].rev()
3135 crev = repo['.'].rev()
3128 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3136 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3129 # Cannot use x.remove(y) on smart set, this has to be a list.
3137 # Cannot use x.remove(y) on smart set, this has to be a list.
3130 # XXX make this lazy in the future
3138 # XXX make this lazy in the future
3131 revs = list(revs)
3139 revs = list(revs)
3132 # don't mutate while iterating, create a copy
3140 # don't mutate while iterating, create a copy
3133 for rev in list(revs):
3141 for rev in list(revs):
3134 if rev in ancestors:
3142 if rev in ancestors:
3135 ui.warn(_('skipping ancestor revision %s\n') % rev)
3143 ui.warn(_('skipping ancestor revision %s\n') % rev)
3136 # XXX remove on list is slow
3144 # XXX remove on list is slow
3137 revs.remove(rev)
3145 revs.remove(rev)
3138 if not revs:
3146 if not revs:
3139 return -1
3147 return -1
3140
3148
3141 # analyze revs for earlier grafts
3149 # analyze revs for earlier grafts
3142 ids = {}
3150 ids = {}
3143 for ctx in repo.set("%ld", revs):
3151 for ctx in repo.set("%ld", revs):
3144 ids[ctx.hex()] = ctx.rev()
3152 ids[ctx.hex()] = ctx.rev()
3145 n = ctx.extra().get('source')
3153 n = ctx.extra().get('source')
3146 if n:
3154 if n:
3147 ids[n] = ctx.rev()
3155 ids[n] = ctx.rev()
3148
3156
3149 # check ancestors for earlier grafts
3157 # check ancestors for earlier grafts
3150 ui.debug('scanning for duplicate grafts\n')
3158 ui.debug('scanning for duplicate grafts\n')
3151
3159
3152 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3160 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3153 ctx = repo[rev]
3161 ctx = repo[rev]
3154 n = ctx.extra().get('source')
3162 n = ctx.extra().get('source')
3155 if n in ids:
3163 if n in ids:
3156 r = repo[n].rev()
3164 r = repo[n].rev()
3157 if r in revs:
3165 if r in revs:
3158 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3166 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3159 % (r, rev))
3167 % (r, rev))
3160 revs.remove(r)
3168 revs.remove(r)
3161 elif ids[n] in revs:
3169 elif ids[n] in revs:
3162 ui.warn(_('skipping already grafted revision %s '
3170 ui.warn(_('skipping already grafted revision %s '
3163 '(%s also has origin %d)\n') % (ids[n], rev, r))
3171 '(%s also has origin %d)\n') % (ids[n], rev, r))
3164 revs.remove(ids[n])
3172 revs.remove(ids[n])
3165 elif ctx.hex() in ids:
3173 elif ctx.hex() in ids:
3166 r = ids[ctx.hex()]
3174 r = ids[ctx.hex()]
3167 ui.warn(_('skipping already grafted revision %s '
3175 ui.warn(_('skipping already grafted revision %s '
3168 '(was grafted from %d)\n') % (r, rev))
3176 '(was grafted from %d)\n') % (r, rev))
3169 revs.remove(r)
3177 revs.remove(r)
3170 if not revs:
3178 if not revs:
3171 return -1
3179 return -1
3172
3180
3173 wlock = repo.wlock()
3181 wlock = repo.wlock()
3174 try:
3182 try:
3175 current = repo['.']
3183 current = repo['.']
3176 for pos, ctx in enumerate(repo.set("%ld", revs)):
3184 for pos, ctx in enumerate(repo.set("%ld", revs)):
3177
3185
3178 ui.status(_('grafting revision %s\n') % ctx.rev())
3186 ui.status(_('grafting revision %s\n') % ctx.rev())
3179 if opts.get('dry_run'):
3187 if opts.get('dry_run'):
3180 continue
3188 continue
3181
3189
3182 source = ctx.extra().get('source')
3190 source = ctx.extra().get('source')
3183 if not source:
3191 if not source:
3184 source = ctx.hex()
3192 source = ctx.hex()
3185 extra = {'source': source}
3193 extra = {'source': source}
3186 user = ctx.user()
3194 user = ctx.user()
3187 if opts.get('user'):
3195 if opts.get('user'):
3188 user = opts['user']
3196 user = opts['user']
3189 date = ctx.date()
3197 date = ctx.date()
3190 if opts.get('date'):
3198 if opts.get('date'):
3191 date = opts['date']
3199 date = opts['date']
3192 message = ctx.description()
3200 message = ctx.description()
3193 if opts.get('log'):
3201 if opts.get('log'):
3194 message += '\n(grafted from %s)' % ctx.hex()
3202 message += '\n(grafted from %s)' % ctx.hex()
3195
3203
3196 # we don't merge the first commit when continuing
3204 # we don't merge the first commit when continuing
3197 if not cont:
3205 if not cont:
3198 # perform the graft merge with p1(rev) as 'ancestor'
3206 # perform the graft merge with p1(rev) as 'ancestor'
3199 try:
3207 try:
3200 # ui.forcemerge is an internal variable, do not document
3208 # ui.forcemerge is an internal variable, do not document
3201 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3209 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3202 'graft')
3210 'graft')
3203 stats = mergemod.update(repo, ctx.node(), True, True, False,
3211 stats = mergemod.update(repo, ctx.node(), True, True, False,
3204 ctx.p1().node(),
3212 ctx.p1().node(),
3205 labels=['local', 'graft'])
3213 labels=['local', 'graft'])
3206 finally:
3214 finally:
3207 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3215 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3208 # report any conflicts
3216 # report any conflicts
3209 if stats and stats[3] > 0:
3217 if stats and stats[3] > 0:
3210 # write out state for --continue
3218 # write out state for --continue
3211 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3219 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3212 repo.opener.write('graftstate', ''.join(nodelines))
3220 repo.opener.write('graftstate', ''.join(nodelines))
3213 raise util.Abort(
3221 raise util.Abort(
3214 _("unresolved conflicts, can't continue"),
3222 _("unresolved conflicts, can't continue"),
3215 hint=_('use hg resolve and hg graft --continue'))
3223 hint=_('use hg resolve and hg graft --continue'))
3216 else:
3224 else:
3217 cont = False
3225 cont = False
3218
3226
3219 # drop the second merge parent
3227 # drop the second merge parent
3220 repo.setparents(current.node(), nullid)
3228 repo.setparents(current.node(), nullid)
3221 repo.dirstate.write()
3229 repo.dirstate.write()
3222 # fix up dirstate for copies and renames
3230 # fix up dirstate for copies and renames
3223 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3231 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3224
3232
3225 # commit
3233 # commit
3226 node = repo.commit(text=message, user=user,
3234 node = repo.commit(text=message, user=user,
3227 date=date, extra=extra, editor=editor)
3235 date=date, extra=extra, editor=editor)
3228 if node is None:
3236 if node is None:
3229 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3237 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3230 else:
3238 else:
3231 current = repo[node]
3239 current = repo[node]
3232 finally:
3240 finally:
3233 wlock.release()
3241 wlock.release()
3234
3242
3235 # remove state when we complete successfully
3243 # remove state when we complete successfully
3236 if not opts.get('dry_run'):
3244 if not opts.get('dry_run'):
3237 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3245 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3238
3246
3239 return 0
3247 return 0
3240
3248
3241 @command('grep',
3249 @command('grep',
3242 [('0', 'print0', None, _('end fields with NUL')),
3250 [('0', 'print0', None, _('end fields with NUL')),
3243 ('', 'all', None, _('print all revisions that match')),
3251 ('', 'all', None, _('print all revisions that match')),
3244 ('a', 'text', None, _('treat all files as text')),
3252 ('a', 'text', None, _('treat all files as text')),
3245 ('f', 'follow', None,
3253 ('f', 'follow', None,
3246 _('follow changeset history,'
3254 _('follow changeset history,'
3247 ' or file history across copies and renames')),
3255 ' or file history across copies and renames')),
3248 ('i', 'ignore-case', None, _('ignore case when matching')),
3256 ('i', 'ignore-case', None, _('ignore case when matching')),
3249 ('l', 'files-with-matches', None,
3257 ('l', 'files-with-matches', None,
3250 _('print only filenames and revisions that match')),
3258 _('print only filenames and revisions that match')),
3251 ('n', 'line-number', None, _('print matching line numbers')),
3259 ('n', 'line-number', None, _('print matching line numbers')),
3252 ('r', 'rev', [],
3260 ('r', 'rev', [],
3253 _('only search files changed within revision range'), _('REV')),
3261 _('only search files changed within revision range'), _('REV')),
3254 ('u', 'user', None, _('list the author (long with -v)')),
3262 ('u', 'user', None, _('list the author (long with -v)')),
3255 ('d', 'date', None, _('list the date (short with -q)')),
3263 ('d', 'date', None, _('list the date (short with -q)')),
3256 ] + walkopts,
3264 ] + walkopts,
3257 _('[OPTION]... PATTERN [FILE]...'))
3265 _('[OPTION]... PATTERN [FILE]...'))
3258 def grep(ui, repo, pattern, *pats, **opts):
3266 def grep(ui, repo, pattern, *pats, **opts):
3259 """search for a pattern in specified files and revisions
3267 """search for a pattern in specified files and revisions
3260
3268
3261 Search revisions of files for a regular expression.
3269 Search revisions of files for a regular expression.
3262
3270
3263 This command behaves differently than Unix grep. It only accepts
3271 This command behaves differently than Unix grep. It only accepts
3264 Python/Perl regexps. It searches repository history, not the
3272 Python/Perl regexps. It searches repository history, not the
3265 working directory. It always prints the revision number in which a
3273 working directory. It always prints the revision number in which a
3266 match appears.
3274 match appears.
3267
3275
3268 By default, grep only prints output for the first revision of a
3276 By default, grep only prints output for the first revision of a
3269 file in which it finds a match. To get it to print every revision
3277 file in which it finds a match. To get it to print every revision
3270 that contains a change in match status ("-" for a match that
3278 that contains a change in match status ("-" for a match that
3271 becomes a non-match, or "+" for a non-match that becomes a match),
3279 becomes a non-match, or "+" for a non-match that becomes a match),
3272 use the --all flag.
3280 use the --all flag.
3273
3281
3274 Returns 0 if a match is found, 1 otherwise.
3282 Returns 0 if a match is found, 1 otherwise.
3275 """
3283 """
3276 reflags = re.M
3284 reflags = re.M
3277 if opts.get('ignore_case'):
3285 if opts.get('ignore_case'):
3278 reflags |= re.I
3286 reflags |= re.I
3279 try:
3287 try:
3280 regexp = util.compilere(pattern, reflags)
3288 regexp = util.compilere(pattern, reflags)
3281 except re.error, inst:
3289 except re.error, inst:
3282 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3290 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3283 return 1
3291 return 1
3284 sep, eol = ':', '\n'
3292 sep, eol = ':', '\n'
3285 if opts.get('print0'):
3293 if opts.get('print0'):
3286 sep = eol = '\0'
3294 sep = eol = '\0'
3287
3295
3288 getfile = util.lrucachefunc(repo.file)
3296 getfile = util.lrucachefunc(repo.file)
3289
3297
3290 def matchlines(body):
3298 def matchlines(body):
3291 begin = 0
3299 begin = 0
3292 linenum = 0
3300 linenum = 0
3293 while begin < len(body):
3301 while begin < len(body):
3294 match = regexp.search(body, begin)
3302 match = regexp.search(body, begin)
3295 if not match:
3303 if not match:
3296 break
3304 break
3297 mstart, mend = match.span()
3305 mstart, mend = match.span()
3298 linenum += body.count('\n', begin, mstart) + 1
3306 linenum += body.count('\n', begin, mstart) + 1
3299 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3307 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3300 begin = body.find('\n', mend) + 1 or len(body) + 1
3308 begin = body.find('\n', mend) + 1 or len(body) + 1
3301 lend = begin - 1
3309 lend = begin - 1
3302 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3310 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3303
3311
3304 class linestate(object):
3312 class linestate(object):
3305 def __init__(self, line, linenum, colstart, colend):
3313 def __init__(self, line, linenum, colstart, colend):
3306 self.line = line
3314 self.line = line
3307 self.linenum = linenum
3315 self.linenum = linenum
3308 self.colstart = colstart
3316 self.colstart = colstart
3309 self.colend = colend
3317 self.colend = colend
3310
3318
3311 def __hash__(self):
3319 def __hash__(self):
3312 return hash((self.linenum, self.line))
3320 return hash((self.linenum, self.line))
3313
3321
3314 def __eq__(self, other):
3322 def __eq__(self, other):
3315 return self.line == other.line
3323 return self.line == other.line
3316
3324
3317 def __iter__(self):
3325 def __iter__(self):
3318 yield (self.line[:self.colstart], '')
3326 yield (self.line[:self.colstart], '')
3319 yield (self.line[self.colstart:self.colend], 'grep.match')
3327 yield (self.line[self.colstart:self.colend], 'grep.match')
3320 rest = self.line[self.colend:]
3328 rest = self.line[self.colend:]
3321 while rest != '':
3329 while rest != '':
3322 match = regexp.search(rest)
3330 match = regexp.search(rest)
3323 if not match:
3331 if not match:
3324 yield (rest, '')
3332 yield (rest, '')
3325 break
3333 break
3326 mstart, mend = match.span()
3334 mstart, mend = match.span()
3327 yield (rest[:mstart], '')
3335 yield (rest[:mstart], '')
3328 yield (rest[mstart:mend], 'grep.match')
3336 yield (rest[mstart:mend], 'grep.match')
3329 rest = rest[mend:]
3337 rest = rest[mend:]
3330
3338
3331 matches = {}
3339 matches = {}
3332 copies = {}
3340 copies = {}
3333 def grepbody(fn, rev, body):
3341 def grepbody(fn, rev, body):
3334 matches[rev].setdefault(fn, [])
3342 matches[rev].setdefault(fn, [])
3335 m = matches[rev][fn]
3343 m = matches[rev][fn]
3336 for lnum, cstart, cend, line in matchlines(body):
3344 for lnum, cstart, cend, line in matchlines(body):
3337 s = linestate(line, lnum, cstart, cend)
3345 s = linestate(line, lnum, cstart, cend)
3338 m.append(s)
3346 m.append(s)
3339
3347
3340 def difflinestates(a, b):
3348 def difflinestates(a, b):
3341 sm = difflib.SequenceMatcher(None, a, b)
3349 sm = difflib.SequenceMatcher(None, a, b)
3342 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3350 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3343 if tag == 'insert':
3351 if tag == 'insert':
3344 for i in xrange(blo, bhi):
3352 for i in xrange(blo, bhi):
3345 yield ('+', b[i])
3353 yield ('+', b[i])
3346 elif tag == 'delete':
3354 elif tag == 'delete':
3347 for i in xrange(alo, ahi):
3355 for i in xrange(alo, ahi):
3348 yield ('-', a[i])
3356 yield ('-', a[i])
3349 elif tag == 'replace':
3357 elif tag == 'replace':
3350 for i in xrange(alo, ahi):
3358 for i in xrange(alo, ahi):
3351 yield ('-', a[i])
3359 yield ('-', a[i])
3352 for i in xrange(blo, bhi):
3360 for i in xrange(blo, bhi):
3353 yield ('+', b[i])
3361 yield ('+', b[i])
3354
3362
3355 def display(fn, ctx, pstates, states):
3363 def display(fn, ctx, pstates, states):
3356 rev = ctx.rev()
3364 rev = ctx.rev()
3357 datefunc = ui.quiet and util.shortdate or util.datestr
3365 datefunc = ui.quiet and util.shortdate or util.datestr
3358 found = False
3366 found = False
3359 @util.cachefunc
3367 @util.cachefunc
3360 def binary():
3368 def binary():
3361 flog = getfile(fn)
3369 flog = getfile(fn)
3362 return util.binary(flog.read(ctx.filenode(fn)))
3370 return util.binary(flog.read(ctx.filenode(fn)))
3363
3371
3364 if opts.get('all'):
3372 if opts.get('all'):
3365 iter = difflinestates(pstates, states)
3373 iter = difflinestates(pstates, states)
3366 else:
3374 else:
3367 iter = [('', l) for l in states]
3375 iter = [('', l) for l in states]
3368 for change, l in iter:
3376 for change, l in iter:
3369 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3377 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3370
3378
3371 if opts.get('line_number'):
3379 if opts.get('line_number'):
3372 cols.append((str(l.linenum), 'grep.linenumber'))
3380 cols.append((str(l.linenum), 'grep.linenumber'))
3373 if opts.get('all'):
3381 if opts.get('all'):
3374 cols.append((change, 'grep.change'))
3382 cols.append((change, 'grep.change'))
3375 if opts.get('user'):
3383 if opts.get('user'):
3376 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3384 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3377 if opts.get('date'):
3385 if opts.get('date'):
3378 cols.append((datefunc(ctx.date()), 'grep.date'))
3386 cols.append((datefunc(ctx.date()), 'grep.date'))
3379 for col, label in cols[:-1]:
3387 for col, label in cols[:-1]:
3380 ui.write(col, label=label)
3388 ui.write(col, label=label)
3381 ui.write(sep, label='grep.sep')
3389 ui.write(sep, label='grep.sep')
3382 ui.write(cols[-1][0], label=cols[-1][1])
3390 ui.write(cols[-1][0], label=cols[-1][1])
3383 if not opts.get('files_with_matches'):
3391 if not opts.get('files_with_matches'):
3384 ui.write(sep, label='grep.sep')
3392 ui.write(sep, label='grep.sep')
3385 if not opts.get('text') and binary():
3393 if not opts.get('text') and binary():
3386 ui.write(" Binary file matches")
3394 ui.write(" Binary file matches")
3387 else:
3395 else:
3388 for s, label in l:
3396 for s, label in l:
3389 ui.write(s, label=label)
3397 ui.write(s, label=label)
3390 ui.write(eol)
3398 ui.write(eol)
3391 found = True
3399 found = True
3392 if opts.get('files_with_matches'):
3400 if opts.get('files_with_matches'):
3393 break
3401 break
3394 return found
3402 return found
3395
3403
3396 skip = {}
3404 skip = {}
3397 revfiles = {}
3405 revfiles = {}
3398 matchfn = scmutil.match(repo[None], pats, opts)
3406 matchfn = scmutil.match(repo[None], pats, opts)
3399 found = False
3407 found = False
3400 follow = opts.get('follow')
3408 follow = opts.get('follow')
3401
3409
3402 def prep(ctx, fns):
3410 def prep(ctx, fns):
3403 rev = ctx.rev()
3411 rev = ctx.rev()
3404 pctx = ctx.p1()
3412 pctx = ctx.p1()
3405 parent = pctx.rev()
3413 parent = pctx.rev()
3406 matches.setdefault(rev, {})
3414 matches.setdefault(rev, {})
3407 matches.setdefault(parent, {})
3415 matches.setdefault(parent, {})
3408 files = revfiles.setdefault(rev, [])
3416 files = revfiles.setdefault(rev, [])
3409 for fn in fns:
3417 for fn in fns:
3410 flog = getfile(fn)
3418 flog = getfile(fn)
3411 try:
3419 try:
3412 fnode = ctx.filenode(fn)
3420 fnode = ctx.filenode(fn)
3413 except error.LookupError:
3421 except error.LookupError:
3414 continue
3422 continue
3415
3423
3416 copied = flog.renamed(fnode)
3424 copied = flog.renamed(fnode)
3417 copy = follow and copied and copied[0]
3425 copy = follow and copied and copied[0]
3418 if copy:
3426 if copy:
3419 copies.setdefault(rev, {})[fn] = copy
3427 copies.setdefault(rev, {})[fn] = copy
3420 if fn in skip:
3428 if fn in skip:
3421 if copy:
3429 if copy:
3422 skip[copy] = True
3430 skip[copy] = True
3423 continue
3431 continue
3424 files.append(fn)
3432 files.append(fn)
3425
3433
3426 if fn not in matches[rev]:
3434 if fn not in matches[rev]:
3427 grepbody(fn, rev, flog.read(fnode))
3435 grepbody(fn, rev, flog.read(fnode))
3428
3436
3429 pfn = copy or fn
3437 pfn = copy or fn
3430 if pfn not in matches[parent]:
3438 if pfn not in matches[parent]:
3431 try:
3439 try:
3432 fnode = pctx.filenode(pfn)
3440 fnode = pctx.filenode(pfn)
3433 grepbody(pfn, parent, flog.read(fnode))
3441 grepbody(pfn, parent, flog.read(fnode))
3434 except error.LookupError:
3442 except error.LookupError:
3435 pass
3443 pass
3436
3444
3437 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3445 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3438 rev = ctx.rev()
3446 rev = ctx.rev()
3439 parent = ctx.p1().rev()
3447 parent = ctx.p1().rev()
3440 for fn in sorted(revfiles.get(rev, [])):
3448 for fn in sorted(revfiles.get(rev, [])):
3441 states = matches[rev][fn]
3449 states = matches[rev][fn]
3442 copy = copies.get(rev, {}).get(fn)
3450 copy = copies.get(rev, {}).get(fn)
3443 if fn in skip:
3451 if fn in skip:
3444 if copy:
3452 if copy:
3445 skip[copy] = True
3453 skip[copy] = True
3446 continue
3454 continue
3447 pstates = matches.get(parent, {}).get(copy or fn, [])
3455 pstates = matches.get(parent, {}).get(copy or fn, [])
3448 if pstates or states:
3456 if pstates or states:
3449 r = display(fn, ctx, pstates, states)
3457 r = display(fn, ctx, pstates, states)
3450 found = found or r
3458 found = found or r
3451 if r and not opts.get('all'):
3459 if r and not opts.get('all'):
3452 skip[fn] = True
3460 skip[fn] = True
3453 if copy:
3461 if copy:
3454 skip[copy] = True
3462 skip[copy] = True
3455 del matches[rev]
3463 del matches[rev]
3456 del revfiles[rev]
3464 del revfiles[rev]
3457
3465
3458 return not found
3466 return not found
3459
3467
3460 @command('heads',
3468 @command('heads',
3461 [('r', 'rev', '',
3469 [('r', 'rev', '',
3462 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3470 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3463 ('t', 'topo', False, _('show topological heads only')),
3471 ('t', 'topo', False, _('show topological heads only')),
3464 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3472 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3465 ('c', 'closed', False, _('show normal and closed branch heads')),
3473 ('c', 'closed', False, _('show normal and closed branch heads')),
3466 ] + templateopts,
3474 ] + templateopts,
3467 _('[-ct] [-r STARTREV] [REV]...'))
3475 _('[-ct] [-r STARTREV] [REV]...'))
3468 def heads(ui, repo, *branchrevs, **opts):
3476 def heads(ui, repo, *branchrevs, **opts):
3469 """show branch heads
3477 """show branch heads
3470
3478
3471 With no arguments, show all open branch heads in the repository.
3479 With no arguments, show all open branch heads in the repository.
3472 Branch heads are changesets that have no descendants on the
3480 Branch heads are changesets that have no descendants on the
3473 same branch. They are where development generally takes place and
3481 same branch. They are where development generally takes place and
3474 are the usual targets for update and merge operations.
3482 are the usual targets for update and merge operations.
3475
3483
3476 If one or more REVs are given, only open branch heads on the
3484 If one or more REVs are given, only open branch heads on the
3477 branches associated with the specified changesets are shown. This
3485 branches associated with the specified changesets are shown. This
3478 means that you can use :hg:`heads .` to see the heads on the
3486 means that you can use :hg:`heads .` to see the heads on the
3479 currently checked-out branch.
3487 currently checked-out branch.
3480
3488
3481 If -c/--closed is specified, also show branch heads marked closed
3489 If -c/--closed is specified, also show branch heads marked closed
3482 (see :hg:`commit --close-branch`).
3490 (see :hg:`commit --close-branch`).
3483
3491
3484 If STARTREV is specified, only those heads that are descendants of
3492 If STARTREV is specified, only those heads that are descendants of
3485 STARTREV will be displayed.
3493 STARTREV will be displayed.
3486
3494
3487 If -t/--topo is specified, named branch mechanics will be ignored and only
3495 If -t/--topo is specified, named branch mechanics will be ignored and only
3488 topological heads (changesets with no children) will be shown.
3496 topological heads (changesets with no children) will be shown.
3489
3497
3490 Returns 0 if matching heads are found, 1 if not.
3498 Returns 0 if matching heads are found, 1 if not.
3491 """
3499 """
3492
3500
3493 start = None
3501 start = None
3494 if 'rev' in opts:
3502 if 'rev' in opts:
3495 start = scmutil.revsingle(repo, opts['rev'], None).node()
3503 start = scmutil.revsingle(repo, opts['rev'], None).node()
3496
3504
3497 if opts.get('topo'):
3505 if opts.get('topo'):
3498 heads = [repo[h] for h in repo.heads(start)]
3506 heads = [repo[h] for h in repo.heads(start)]
3499 else:
3507 else:
3500 heads = []
3508 heads = []
3501 for branch in repo.branchmap():
3509 for branch in repo.branchmap():
3502 heads += repo.branchheads(branch, start, opts.get('closed'))
3510 heads += repo.branchheads(branch, start, opts.get('closed'))
3503 heads = [repo[h] for h in heads]
3511 heads = [repo[h] for h in heads]
3504
3512
3505 if branchrevs:
3513 if branchrevs:
3506 branches = set(repo[br].branch() for br in branchrevs)
3514 branches = set(repo[br].branch() for br in branchrevs)
3507 heads = [h for h in heads if h.branch() in branches]
3515 heads = [h for h in heads if h.branch() in branches]
3508
3516
3509 if opts.get('active') and branchrevs:
3517 if opts.get('active') and branchrevs:
3510 dagheads = repo.heads(start)
3518 dagheads = repo.heads(start)
3511 heads = [h for h in heads if h.node() in dagheads]
3519 heads = [h for h in heads if h.node() in dagheads]
3512
3520
3513 if branchrevs:
3521 if branchrevs:
3514 haveheads = set(h.branch() for h in heads)
3522 haveheads = set(h.branch() for h in heads)
3515 if branches - haveheads:
3523 if branches - haveheads:
3516 headless = ', '.join(b for b in branches - haveheads)
3524 headless = ', '.join(b for b in branches - haveheads)
3517 msg = _('no open branch heads found on branches %s')
3525 msg = _('no open branch heads found on branches %s')
3518 if opts.get('rev'):
3526 if opts.get('rev'):
3519 msg += _(' (started at %s)') % opts['rev']
3527 msg += _(' (started at %s)') % opts['rev']
3520 ui.warn((msg + '\n') % headless)
3528 ui.warn((msg + '\n') % headless)
3521
3529
3522 if not heads:
3530 if not heads:
3523 return 1
3531 return 1
3524
3532
3525 heads = sorted(heads, key=lambda x: -x.rev())
3533 heads = sorted(heads, key=lambda x: -x.rev())
3526 displayer = cmdutil.show_changeset(ui, repo, opts)
3534 displayer = cmdutil.show_changeset(ui, repo, opts)
3527 for ctx in heads:
3535 for ctx in heads:
3528 displayer.show(ctx)
3536 displayer.show(ctx)
3529 displayer.close()
3537 displayer.close()
3530
3538
3531 @command('help',
3539 @command('help',
3532 [('e', 'extension', None, _('show only help for extensions')),
3540 [('e', 'extension', None, _('show only help for extensions')),
3533 ('c', 'command', None, _('show only help for commands')),
3541 ('c', 'command', None, _('show only help for commands')),
3534 ('k', 'keyword', '', _('show topics matching keyword')),
3542 ('k', 'keyword', '', _('show topics matching keyword')),
3535 ],
3543 ],
3536 _('[-ec] [TOPIC]'))
3544 _('[-ec] [TOPIC]'),
3545 norepo=True)
3537 def help_(ui, name=None, **opts):
3546 def help_(ui, name=None, **opts):
3538 """show help for a given topic or a help overview
3547 """show help for a given topic or a help overview
3539
3548
3540 With no arguments, print a list of commands with short help messages.
3549 With no arguments, print a list of commands with short help messages.
3541
3550
3542 Given a topic, extension, or command name, print help for that
3551 Given a topic, extension, or command name, print help for that
3543 topic.
3552 topic.
3544
3553
3545 Returns 0 if successful.
3554 Returns 0 if successful.
3546 """
3555 """
3547
3556
3548 textwidth = min(ui.termwidth(), 80) - 2
3557 textwidth = min(ui.termwidth(), 80) - 2
3549
3558
3550 keep = ui.verbose and ['verbose'] or []
3559 keep = ui.verbose and ['verbose'] or []
3551 text = help.help_(ui, name, **opts)
3560 text = help.help_(ui, name, **opts)
3552
3561
3553 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3562 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3554 if 'verbose' in pruned:
3563 if 'verbose' in pruned:
3555 keep.append('omitted')
3564 keep.append('omitted')
3556 else:
3565 else:
3557 keep.append('notomitted')
3566 keep.append('notomitted')
3558 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3567 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3559 ui.write(formatted)
3568 ui.write(formatted)
3560
3569
3561
3570
3562 @command('identify|id',
3571 @command('identify|id',
3563 [('r', 'rev', '',
3572 [('r', 'rev', '',
3564 _('identify the specified revision'), _('REV')),
3573 _('identify the specified revision'), _('REV')),
3565 ('n', 'num', None, _('show local revision number')),
3574 ('n', 'num', None, _('show local revision number')),
3566 ('i', 'id', None, _('show global revision id')),
3575 ('i', 'id', None, _('show global revision id')),
3567 ('b', 'branch', None, _('show branch')),
3576 ('b', 'branch', None, _('show branch')),
3568 ('t', 'tags', None, _('show tags')),
3577 ('t', 'tags', None, _('show tags')),
3569 ('B', 'bookmarks', None, _('show bookmarks')),
3578 ('B', 'bookmarks', None, _('show bookmarks')),
3570 ] + remoteopts,
3579 ] + remoteopts,
3571 _('[-nibtB] [-r REV] [SOURCE]'))
3580 _('[-nibtB] [-r REV] [SOURCE]'))
3572 def identify(ui, repo, source=None, rev=None,
3581 def identify(ui, repo, source=None, rev=None,
3573 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3582 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3574 """identify the working copy or specified revision
3583 """identify the working copy or specified revision
3575
3584
3576 Print a summary identifying the repository state at REV using one or
3585 Print a summary identifying the repository state at REV using one or
3577 two parent hash identifiers, followed by a "+" if the working
3586 two parent hash identifiers, followed by a "+" if the working
3578 directory has uncommitted changes, the branch name (if not default),
3587 directory has uncommitted changes, the branch name (if not default),
3579 a list of tags, and a list of bookmarks.
3588 a list of tags, and a list of bookmarks.
3580
3589
3581 When REV is not given, print a summary of the current state of the
3590 When REV is not given, print a summary of the current state of the
3582 repository.
3591 repository.
3583
3592
3584 Specifying a path to a repository root or Mercurial bundle will
3593 Specifying a path to a repository root or Mercurial bundle will
3585 cause lookup to operate on that repository/bundle.
3594 cause lookup to operate on that repository/bundle.
3586
3595
3587 .. container:: verbose
3596 .. container:: verbose
3588
3597
3589 Examples:
3598 Examples:
3590
3599
3591 - generate a build identifier for the working directory::
3600 - generate a build identifier for the working directory::
3592
3601
3593 hg id --id > build-id.dat
3602 hg id --id > build-id.dat
3594
3603
3595 - find the revision corresponding to a tag::
3604 - find the revision corresponding to a tag::
3596
3605
3597 hg id -n -r 1.3
3606 hg id -n -r 1.3
3598
3607
3599 - check the most recent revision of a remote repository::
3608 - check the most recent revision of a remote repository::
3600
3609
3601 hg id -r tip http://selenic.com/hg/
3610 hg id -r tip http://selenic.com/hg/
3602
3611
3603 Returns 0 if successful.
3612 Returns 0 if successful.
3604 """
3613 """
3605
3614
3606 if not repo and not source:
3615 if not repo and not source:
3607 raise util.Abort(_("there is no Mercurial repository here "
3616 raise util.Abort(_("there is no Mercurial repository here "
3608 "(.hg not found)"))
3617 "(.hg not found)"))
3609
3618
3610 hexfunc = ui.debugflag and hex or short
3619 hexfunc = ui.debugflag and hex or short
3611 default = not (num or id or branch or tags or bookmarks)
3620 default = not (num or id or branch or tags or bookmarks)
3612 output = []
3621 output = []
3613 revs = []
3622 revs = []
3614
3623
3615 if source:
3624 if source:
3616 source, branches = hg.parseurl(ui.expandpath(source))
3625 source, branches = hg.parseurl(ui.expandpath(source))
3617 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3626 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3618 repo = peer.local()
3627 repo = peer.local()
3619 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3628 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3620
3629
3621 if not repo:
3630 if not repo:
3622 if num or branch or tags:
3631 if num or branch or tags:
3623 raise util.Abort(
3632 raise util.Abort(
3624 _("can't query remote revision number, branch, or tags"))
3633 _("can't query remote revision number, branch, or tags"))
3625 if not rev and revs:
3634 if not rev and revs:
3626 rev = revs[0]
3635 rev = revs[0]
3627 if not rev:
3636 if not rev:
3628 rev = "tip"
3637 rev = "tip"
3629
3638
3630 remoterev = peer.lookup(rev)
3639 remoterev = peer.lookup(rev)
3631 if default or id:
3640 if default or id:
3632 output = [hexfunc(remoterev)]
3641 output = [hexfunc(remoterev)]
3633
3642
3634 def getbms():
3643 def getbms():
3635 bms = []
3644 bms = []
3636
3645
3637 if 'bookmarks' in peer.listkeys('namespaces'):
3646 if 'bookmarks' in peer.listkeys('namespaces'):
3638 hexremoterev = hex(remoterev)
3647 hexremoterev = hex(remoterev)
3639 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3648 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3640 if bmr == hexremoterev]
3649 if bmr == hexremoterev]
3641
3650
3642 return sorted(bms)
3651 return sorted(bms)
3643
3652
3644 if bookmarks:
3653 if bookmarks:
3645 output.extend(getbms())
3654 output.extend(getbms())
3646 elif default and not ui.quiet:
3655 elif default and not ui.quiet:
3647 # multiple bookmarks for a single parent separated by '/'
3656 # multiple bookmarks for a single parent separated by '/'
3648 bm = '/'.join(getbms())
3657 bm = '/'.join(getbms())
3649 if bm:
3658 if bm:
3650 output.append(bm)
3659 output.append(bm)
3651 else:
3660 else:
3652 if not rev:
3661 if not rev:
3653 ctx = repo[None]
3662 ctx = repo[None]
3654 parents = ctx.parents()
3663 parents = ctx.parents()
3655 changed = ""
3664 changed = ""
3656 if default or id or num:
3665 if default or id or num:
3657 if (util.any(repo.status())
3666 if (util.any(repo.status())
3658 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3667 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3659 changed = '+'
3668 changed = '+'
3660 if default or id:
3669 if default or id:
3661 output = ["%s%s" %
3670 output = ["%s%s" %
3662 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3671 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3663 if num:
3672 if num:
3664 output.append("%s%s" %
3673 output.append("%s%s" %
3665 ('+'.join([str(p.rev()) for p in parents]), changed))
3674 ('+'.join([str(p.rev()) for p in parents]), changed))
3666 else:
3675 else:
3667 ctx = scmutil.revsingle(repo, rev)
3676 ctx = scmutil.revsingle(repo, rev)
3668 if default or id:
3677 if default or id:
3669 output = [hexfunc(ctx.node())]
3678 output = [hexfunc(ctx.node())]
3670 if num:
3679 if num:
3671 output.append(str(ctx.rev()))
3680 output.append(str(ctx.rev()))
3672
3681
3673 if default and not ui.quiet:
3682 if default and not ui.quiet:
3674 b = ctx.branch()
3683 b = ctx.branch()
3675 if b != 'default':
3684 if b != 'default':
3676 output.append("(%s)" % b)
3685 output.append("(%s)" % b)
3677
3686
3678 # multiple tags for a single parent separated by '/'
3687 # multiple tags for a single parent separated by '/'
3679 t = '/'.join(ctx.tags())
3688 t = '/'.join(ctx.tags())
3680 if t:
3689 if t:
3681 output.append(t)
3690 output.append(t)
3682
3691
3683 # multiple bookmarks for a single parent separated by '/'
3692 # multiple bookmarks for a single parent separated by '/'
3684 bm = '/'.join(ctx.bookmarks())
3693 bm = '/'.join(ctx.bookmarks())
3685 if bm:
3694 if bm:
3686 output.append(bm)
3695 output.append(bm)
3687 else:
3696 else:
3688 if branch:
3697 if branch:
3689 output.append(ctx.branch())
3698 output.append(ctx.branch())
3690
3699
3691 if tags:
3700 if tags:
3692 output.extend(ctx.tags())
3701 output.extend(ctx.tags())
3693
3702
3694 if bookmarks:
3703 if bookmarks:
3695 output.extend(ctx.bookmarks())
3704 output.extend(ctx.bookmarks())
3696
3705
3697 ui.write("%s\n" % ' '.join(output))
3706 ui.write("%s\n" % ' '.join(output))
3698
3707
3699 @command('import|patch',
3708 @command('import|patch',
3700 [('p', 'strip', 1,
3709 [('p', 'strip', 1,
3701 _('directory strip option for patch. This has the same '
3710 _('directory strip option for patch. This has the same '
3702 'meaning as the corresponding patch option'), _('NUM')),
3711 'meaning as the corresponding patch option'), _('NUM')),
3703 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3712 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3704 ('e', 'edit', False, _('invoke editor on commit messages')),
3713 ('e', 'edit', False, _('invoke editor on commit messages')),
3705 ('f', 'force', None,
3714 ('f', 'force', None,
3706 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3715 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3707 ('', 'no-commit', None,
3716 ('', 'no-commit', None,
3708 _("don't commit, just update the working directory")),
3717 _("don't commit, just update the working directory")),
3709 ('', 'bypass', None,
3718 ('', 'bypass', None,
3710 _("apply patch without touching the working directory")),
3719 _("apply patch without touching the working directory")),
3711 ('', 'partial', None,
3720 ('', 'partial', None,
3712 _('commit even if some hunks fail')),
3721 _('commit even if some hunks fail')),
3713 ('', 'exact', None,
3722 ('', 'exact', None,
3714 _('apply patch to the nodes from which it was generated')),
3723 _('apply patch to the nodes from which it was generated')),
3715 ('', 'import-branch', None,
3724 ('', 'import-branch', None,
3716 _('use any branch information in patch (implied by --exact)'))] +
3725 _('use any branch information in patch (implied by --exact)'))] +
3717 commitopts + commitopts2 + similarityopts,
3726 commitopts + commitopts2 + similarityopts,
3718 _('[OPTION]... PATCH...'))
3727 _('[OPTION]... PATCH...'))
3719 def import_(ui, repo, patch1=None, *patches, **opts):
3728 def import_(ui, repo, patch1=None, *patches, **opts):
3720 """import an ordered set of patches
3729 """import an ordered set of patches
3721
3730
3722 Import a list of patches and commit them individually (unless
3731 Import a list of patches and commit them individually (unless
3723 --no-commit is specified).
3732 --no-commit is specified).
3724
3733
3725 Because import first applies changes to the working directory,
3734 Because import first applies changes to the working directory,
3726 import will abort if there are outstanding changes.
3735 import will abort if there are outstanding changes.
3727
3736
3728 You can import a patch straight from a mail message. Even patches
3737 You can import a patch straight from a mail message. Even patches
3729 as attachments work (to use the body part, it must have type
3738 as attachments work (to use the body part, it must have type
3730 text/plain or text/x-patch). From and Subject headers of email
3739 text/plain or text/x-patch). From and Subject headers of email
3731 message are used as default committer and commit message. All
3740 message are used as default committer and commit message. All
3732 text/plain body parts before first diff are added to commit
3741 text/plain body parts before first diff are added to commit
3733 message.
3742 message.
3734
3743
3735 If the imported patch was generated by :hg:`export`, user and
3744 If the imported patch was generated by :hg:`export`, user and
3736 description from patch override values from message headers and
3745 description from patch override values from message headers and
3737 body. Values given on command line with -m/--message and -u/--user
3746 body. Values given on command line with -m/--message and -u/--user
3738 override these.
3747 override these.
3739
3748
3740 If --exact is specified, import will set the working directory to
3749 If --exact is specified, import will set the working directory to
3741 the parent of each patch before applying it, and will abort if the
3750 the parent of each patch before applying it, and will abort if the
3742 resulting changeset has a different ID than the one recorded in
3751 resulting changeset has a different ID than the one recorded in
3743 the patch. This may happen due to character set problems or other
3752 the patch. This may happen due to character set problems or other
3744 deficiencies in the text patch format.
3753 deficiencies in the text patch format.
3745
3754
3746 Use --bypass to apply and commit patches directly to the
3755 Use --bypass to apply and commit patches directly to the
3747 repository, not touching the working directory. Without --exact,
3756 repository, not touching the working directory. Without --exact,
3748 patches will be applied on top of the working directory parent
3757 patches will be applied on top of the working directory parent
3749 revision.
3758 revision.
3750
3759
3751 With -s/--similarity, hg will attempt to discover renames and
3760 With -s/--similarity, hg will attempt to discover renames and
3752 copies in the patch in the same way as :hg:`addremove`.
3761 copies in the patch in the same way as :hg:`addremove`.
3753
3762
3754 Use --partial to ensure a changeset will be created from the patch
3763 Use --partial to ensure a changeset will be created from the patch
3755 even if some hunks fail to apply. Hunks that fail to apply will be
3764 even if some hunks fail to apply. Hunks that fail to apply will be
3756 written to a <target-file>.rej file. Conflicts can then be resolved
3765 written to a <target-file>.rej file. Conflicts can then be resolved
3757 by hand before :hg:`commit --amend` is run to update the created
3766 by hand before :hg:`commit --amend` is run to update the created
3758 changeset. This flag exists to let people import patches that
3767 changeset. This flag exists to let people import patches that
3759 partially apply without losing the associated metadata (author,
3768 partially apply without losing the associated metadata (author,
3760 date, description, ...), Note that when none of the hunk applies
3769 date, description, ...), Note that when none of the hunk applies
3761 cleanly, :hg:`import --partial` will create an empty changeset,
3770 cleanly, :hg:`import --partial` will create an empty changeset,
3762 importing only the patch metadata.
3771 importing only the patch metadata.
3763
3772
3764 To read a patch from standard input, use "-" as the patch name. If
3773 To read a patch from standard input, use "-" as the patch name. If
3765 a URL is specified, the patch will be downloaded from it.
3774 a URL is specified, the patch will be downloaded from it.
3766 See :hg:`help dates` for a list of formats valid for -d/--date.
3775 See :hg:`help dates` for a list of formats valid for -d/--date.
3767
3776
3768 .. container:: verbose
3777 .. container:: verbose
3769
3778
3770 Examples:
3779 Examples:
3771
3780
3772 - import a traditional patch from a website and detect renames::
3781 - import a traditional patch from a website and detect renames::
3773
3782
3774 hg import -s 80 http://example.com/bugfix.patch
3783 hg import -s 80 http://example.com/bugfix.patch
3775
3784
3776 - import a changeset from an hgweb server::
3785 - import a changeset from an hgweb server::
3777
3786
3778 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3787 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3779
3788
3780 - import all the patches in an Unix-style mbox::
3789 - import all the patches in an Unix-style mbox::
3781
3790
3782 hg import incoming-patches.mbox
3791 hg import incoming-patches.mbox
3783
3792
3784 - attempt to exactly restore an exported changeset (not always
3793 - attempt to exactly restore an exported changeset (not always
3785 possible)::
3794 possible)::
3786
3795
3787 hg import --exact proposed-fix.patch
3796 hg import --exact proposed-fix.patch
3788
3797
3789 Returns 0 on success, 1 on partial success (see --partial).
3798 Returns 0 on success, 1 on partial success (see --partial).
3790 """
3799 """
3791
3800
3792 if not patch1:
3801 if not patch1:
3793 raise util.Abort(_('need at least one patch to import'))
3802 raise util.Abort(_('need at least one patch to import'))
3794
3803
3795 patches = (patch1,) + patches
3804 patches = (patch1,) + patches
3796
3805
3797 date = opts.get('date')
3806 date = opts.get('date')
3798 if date:
3807 if date:
3799 opts['date'] = util.parsedate(date)
3808 opts['date'] = util.parsedate(date)
3800
3809
3801 update = not opts.get('bypass')
3810 update = not opts.get('bypass')
3802 if not update and opts.get('no_commit'):
3811 if not update and opts.get('no_commit'):
3803 raise util.Abort(_('cannot use --no-commit with --bypass'))
3812 raise util.Abort(_('cannot use --no-commit with --bypass'))
3804 try:
3813 try:
3805 sim = float(opts.get('similarity') or 0)
3814 sim = float(opts.get('similarity') or 0)
3806 except ValueError:
3815 except ValueError:
3807 raise util.Abort(_('similarity must be a number'))
3816 raise util.Abort(_('similarity must be a number'))
3808 if sim < 0 or sim > 100:
3817 if sim < 0 or sim > 100:
3809 raise util.Abort(_('similarity must be between 0 and 100'))
3818 raise util.Abort(_('similarity must be between 0 and 100'))
3810 if sim and not update:
3819 if sim and not update:
3811 raise util.Abort(_('cannot use --similarity with --bypass'))
3820 raise util.Abort(_('cannot use --similarity with --bypass'))
3812
3821
3813 if update:
3822 if update:
3814 cmdutil.checkunfinished(repo)
3823 cmdutil.checkunfinished(repo)
3815 if (opts.get('exact') or not opts.get('force')) and update:
3824 if (opts.get('exact') or not opts.get('force')) and update:
3816 cmdutil.bailifchanged(repo)
3825 cmdutil.bailifchanged(repo)
3817
3826
3818 base = opts["base"]
3827 base = opts["base"]
3819 wlock = lock = tr = None
3828 wlock = lock = tr = None
3820 msgs = []
3829 msgs = []
3821 ret = 0
3830 ret = 0
3822
3831
3823
3832
3824 try:
3833 try:
3825 try:
3834 try:
3826 wlock = repo.wlock()
3835 wlock = repo.wlock()
3827 if not opts.get('no_commit'):
3836 if not opts.get('no_commit'):
3828 lock = repo.lock()
3837 lock = repo.lock()
3829 tr = repo.transaction('import')
3838 tr = repo.transaction('import')
3830 parents = repo.parents()
3839 parents = repo.parents()
3831 for patchurl in patches:
3840 for patchurl in patches:
3832 if patchurl == '-':
3841 if patchurl == '-':
3833 ui.status(_('applying patch from stdin\n'))
3842 ui.status(_('applying patch from stdin\n'))
3834 patchfile = ui.fin
3843 patchfile = ui.fin
3835 patchurl = 'stdin' # for error message
3844 patchurl = 'stdin' # for error message
3836 else:
3845 else:
3837 patchurl = os.path.join(base, patchurl)
3846 patchurl = os.path.join(base, patchurl)
3838 ui.status(_('applying %s\n') % patchurl)
3847 ui.status(_('applying %s\n') % patchurl)
3839 patchfile = hg.openpath(ui, patchurl)
3848 patchfile = hg.openpath(ui, patchurl)
3840
3849
3841 haspatch = False
3850 haspatch = False
3842 for hunk in patch.split(patchfile):
3851 for hunk in patch.split(patchfile):
3843 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3852 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3844 parents, opts,
3853 parents, opts,
3845 msgs, hg.clean)
3854 msgs, hg.clean)
3846 if msg:
3855 if msg:
3847 haspatch = True
3856 haspatch = True
3848 ui.note(msg + '\n')
3857 ui.note(msg + '\n')
3849 if update or opts.get('exact'):
3858 if update or opts.get('exact'):
3850 parents = repo.parents()
3859 parents = repo.parents()
3851 else:
3860 else:
3852 parents = [repo[node]]
3861 parents = [repo[node]]
3853 if rej:
3862 if rej:
3854 ui.write_err(_("patch applied partially\n"))
3863 ui.write_err(_("patch applied partially\n"))
3855 ui.write_err(("(fix the .rej files and run "
3864 ui.write_err(("(fix the .rej files and run "
3856 "`hg commit --amend`)\n"))
3865 "`hg commit --amend`)\n"))
3857 ret = 1
3866 ret = 1
3858 break
3867 break
3859
3868
3860 if not haspatch:
3869 if not haspatch:
3861 raise util.Abort(_('%s: no diffs found') % patchurl)
3870 raise util.Abort(_('%s: no diffs found') % patchurl)
3862
3871
3863 if tr:
3872 if tr:
3864 tr.close()
3873 tr.close()
3865 if msgs:
3874 if msgs:
3866 repo.savecommitmessage('\n* * *\n'.join(msgs))
3875 repo.savecommitmessage('\n* * *\n'.join(msgs))
3867 return ret
3876 return ret
3868 except: # re-raises
3877 except: # re-raises
3869 # wlock.release() indirectly calls dirstate.write(): since
3878 # wlock.release() indirectly calls dirstate.write(): since
3870 # we're crashing, we do not want to change the working dir
3879 # we're crashing, we do not want to change the working dir
3871 # parent after all, so make sure it writes nothing
3880 # parent after all, so make sure it writes nothing
3872 repo.dirstate.invalidate()
3881 repo.dirstate.invalidate()
3873 raise
3882 raise
3874 finally:
3883 finally:
3875 if tr:
3884 if tr:
3876 tr.release()
3885 tr.release()
3877 release(lock, wlock)
3886 release(lock, wlock)
3878
3887
3879 @command('incoming|in',
3888 @command('incoming|in',
3880 [('f', 'force', None,
3889 [('f', 'force', None,
3881 _('run even if remote repository is unrelated')),
3890 _('run even if remote repository is unrelated')),
3882 ('n', 'newest-first', None, _('show newest record first')),
3891 ('n', 'newest-first', None, _('show newest record first')),
3883 ('', 'bundle', '',
3892 ('', 'bundle', '',
3884 _('file to store the bundles into'), _('FILE')),
3893 _('file to store the bundles into'), _('FILE')),
3885 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3894 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3886 ('B', 'bookmarks', False, _("compare bookmarks")),
3895 ('B', 'bookmarks', False, _("compare bookmarks")),
3887 ('b', 'branch', [],
3896 ('b', 'branch', [],
3888 _('a specific branch you would like to pull'), _('BRANCH')),
3897 _('a specific branch you would like to pull'), _('BRANCH')),
3889 ] + logopts + remoteopts + subrepoopts,
3898 ] + logopts + remoteopts + subrepoopts,
3890 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3899 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3891 def incoming(ui, repo, source="default", **opts):
3900 def incoming(ui, repo, source="default", **opts):
3892 """show new changesets found in source
3901 """show new changesets found in source
3893
3902
3894 Show new changesets found in the specified path/URL or the default
3903 Show new changesets found in the specified path/URL or the default
3895 pull location. These are the changesets that would have been pulled
3904 pull location. These are the changesets that would have been pulled
3896 if a pull at the time you issued this command.
3905 if a pull at the time you issued this command.
3897
3906
3898 For remote repository, using --bundle avoids downloading the
3907 For remote repository, using --bundle avoids downloading the
3899 changesets twice if the incoming is followed by a pull.
3908 changesets twice if the incoming is followed by a pull.
3900
3909
3901 See pull for valid source format details.
3910 See pull for valid source format details.
3902
3911
3903 .. container:: verbose
3912 .. container:: verbose
3904
3913
3905 Examples:
3914 Examples:
3906
3915
3907 - show incoming changes with patches and full description::
3916 - show incoming changes with patches and full description::
3908
3917
3909 hg incoming -vp
3918 hg incoming -vp
3910
3919
3911 - show incoming changes excluding merges, store a bundle::
3920 - show incoming changes excluding merges, store a bundle::
3912
3921
3913 hg in -vpM --bundle incoming.hg
3922 hg in -vpM --bundle incoming.hg
3914 hg pull incoming.hg
3923 hg pull incoming.hg
3915
3924
3916 - briefly list changes inside a bundle::
3925 - briefly list changes inside a bundle::
3917
3926
3918 hg in changes.hg -T "{desc|firstline}\\n"
3927 hg in changes.hg -T "{desc|firstline}\\n"
3919
3928
3920 Returns 0 if there are incoming changes, 1 otherwise.
3929 Returns 0 if there are incoming changes, 1 otherwise.
3921 """
3930 """
3922 if opts.get('graph'):
3931 if opts.get('graph'):
3923 cmdutil.checkunsupportedgraphflags([], opts)
3932 cmdutil.checkunsupportedgraphflags([], opts)
3924 def display(other, chlist, displayer):
3933 def display(other, chlist, displayer):
3925 revdag = cmdutil.graphrevs(other, chlist, opts)
3934 revdag = cmdutil.graphrevs(other, chlist, opts)
3926 showparents = [ctx.node() for ctx in repo[None].parents()]
3935 showparents = [ctx.node() for ctx in repo[None].parents()]
3927 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3936 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3928 graphmod.asciiedges)
3937 graphmod.asciiedges)
3929
3938
3930 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3939 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3931 return 0
3940 return 0
3932
3941
3933 if opts.get('bundle') and opts.get('subrepos'):
3942 if opts.get('bundle') and opts.get('subrepos'):
3934 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3943 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3935
3944
3936 if opts.get('bookmarks'):
3945 if opts.get('bookmarks'):
3937 source, branches = hg.parseurl(ui.expandpath(source),
3946 source, branches = hg.parseurl(ui.expandpath(source),
3938 opts.get('branch'))
3947 opts.get('branch'))
3939 other = hg.peer(repo, opts, source)
3948 other = hg.peer(repo, opts, source)
3940 if 'bookmarks' not in other.listkeys('namespaces'):
3949 if 'bookmarks' not in other.listkeys('namespaces'):
3941 ui.warn(_("remote doesn't support bookmarks\n"))
3950 ui.warn(_("remote doesn't support bookmarks\n"))
3942 return 0
3951 return 0
3943 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3952 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3944 return bookmarks.diff(ui, repo, other)
3953 return bookmarks.diff(ui, repo, other)
3945
3954
3946 repo._subtoppath = ui.expandpath(source)
3955 repo._subtoppath = ui.expandpath(source)
3947 try:
3956 try:
3948 return hg.incoming(ui, repo, source, opts)
3957 return hg.incoming(ui, repo, source, opts)
3949 finally:
3958 finally:
3950 del repo._subtoppath
3959 del repo._subtoppath
3951
3960
3952
3961
3953 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3962 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3963 norepo=True)
3954 def init(ui, dest=".", **opts):
3964 def init(ui, dest=".", **opts):
3955 """create a new repository in the given directory
3965 """create a new repository in the given directory
3956
3966
3957 Initialize a new repository in the given directory. If the given
3967 Initialize a new repository in the given directory. If the given
3958 directory does not exist, it will be created.
3968 directory does not exist, it will be created.
3959
3969
3960 If no directory is given, the current directory is used.
3970 If no directory is given, the current directory is used.
3961
3971
3962 It is possible to specify an ``ssh://`` URL as the destination.
3972 It is possible to specify an ``ssh://`` URL as the destination.
3963 See :hg:`help urls` for more information.
3973 See :hg:`help urls` for more information.
3964
3974
3965 Returns 0 on success.
3975 Returns 0 on success.
3966 """
3976 """
3967 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3977 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3968
3978
3969 @command('locate',
3979 @command('locate',
3970 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3980 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3971 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3981 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3972 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3982 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3973 ] + walkopts,
3983 ] + walkopts,
3974 _('[OPTION]... [PATTERN]...'))
3984 _('[OPTION]... [PATTERN]...'))
3975 def locate(ui, repo, *pats, **opts):
3985 def locate(ui, repo, *pats, **opts):
3976 """locate files matching specific patterns
3986 """locate files matching specific patterns
3977
3987
3978 Print files under Mercurial control in the working directory whose
3988 Print files under Mercurial control in the working directory whose
3979 names match the given patterns.
3989 names match the given patterns.
3980
3990
3981 By default, this command searches all directories in the working
3991 By default, this command searches all directories in the working
3982 directory. To search just the current directory and its
3992 directory. To search just the current directory and its
3983 subdirectories, use "--include .".
3993 subdirectories, use "--include .".
3984
3994
3985 If no patterns are given to match, this command prints the names
3995 If no patterns are given to match, this command prints the names
3986 of all files under Mercurial control in the working directory.
3996 of all files under Mercurial control in the working directory.
3987
3997
3988 If you want to feed the output of this command into the "xargs"
3998 If you want to feed the output of this command into the "xargs"
3989 command, use the -0 option to both this command and "xargs". This
3999 command, use the -0 option to both this command and "xargs". This
3990 will avoid the problem of "xargs" treating single filenames that
4000 will avoid the problem of "xargs" treating single filenames that
3991 contain whitespace as multiple filenames.
4001 contain whitespace as multiple filenames.
3992
4002
3993 Returns 0 if a match is found, 1 otherwise.
4003 Returns 0 if a match is found, 1 otherwise.
3994 """
4004 """
3995 end = opts.get('print0') and '\0' or '\n'
4005 end = opts.get('print0') and '\0' or '\n'
3996 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4006 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3997
4007
3998 ret = 1
4008 ret = 1
3999 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4009 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4000 m.bad = lambda x, y: False
4010 m.bad = lambda x, y: False
4001 for abs in repo[rev].walk(m):
4011 for abs in repo[rev].walk(m):
4002 if not rev and abs not in repo.dirstate:
4012 if not rev and abs not in repo.dirstate:
4003 continue
4013 continue
4004 if opts.get('fullpath'):
4014 if opts.get('fullpath'):
4005 ui.write(repo.wjoin(abs), end)
4015 ui.write(repo.wjoin(abs), end)
4006 else:
4016 else:
4007 ui.write(((pats and m.rel(abs)) or abs), end)
4017 ui.write(((pats and m.rel(abs)) or abs), end)
4008 ret = 0
4018 ret = 0
4009
4019
4010 return ret
4020 return ret
4011
4021
4012 @command('^log|history',
4022 @command('^log|history',
4013 [('f', 'follow', None,
4023 [('f', 'follow', None,
4014 _('follow changeset history, or file history across copies and renames')),
4024 _('follow changeset history, or file history across copies and renames')),
4015 ('', 'follow-first', None,
4025 ('', 'follow-first', None,
4016 _('only follow the first parent of merge changesets (DEPRECATED)')),
4026 _('only follow the first parent of merge changesets (DEPRECATED)')),
4017 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4027 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4018 ('C', 'copies', None, _('show copied files')),
4028 ('C', 'copies', None, _('show copied files')),
4019 ('k', 'keyword', [],
4029 ('k', 'keyword', [],
4020 _('do case-insensitive search for a given text'), _('TEXT')),
4030 _('do case-insensitive search for a given text'), _('TEXT')),
4021 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4031 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4022 ('', 'removed', None, _('include revisions where files were removed')),
4032 ('', 'removed', None, _('include revisions where files were removed')),
4023 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4033 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4024 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4034 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4025 ('', 'only-branch', [],
4035 ('', 'only-branch', [],
4026 _('show only changesets within the given named branch (DEPRECATED)'),
4036 _('show only changesets within the given named branch (DEPRECATED)'),
4027 _('BRANCH')),
4037 _('BRANCH')),
4028 ('b', 'branch', [],
4038 ('b', 'branch', [],
4029 _('show changesets within the given named branch'), _('BRANCH')),
4039 _('show changesets within the given named branch'), _('BRANCH')),
4030 ('P', 'prune', [],
4040 ('P', 'prune', [],
4031 _('do not display revision or any of its ancestors'), _('REV')),
4041 _('do not display revision or any of its ancestors'), _('REV')),
4032 ] + logopts + walkopts,
4042 ] + logopts + walkopts,
4033 _('[OPTION]... [FILE]'))
4043 _('[OPTION]... [FILE]'))
4034 def log(ui, repo, *pats, **opts):
4044 def log(ui, repo, *pats, **opts):
4035 """show revision history of entire repository or files
4045 """show revision history of entire repository or files
4036
4046
4037 Print the revision history of the specified files or the entire
4047 Print the revision history of the specified files or the entire
4038 project.
4048 project.
4039
4049
4040 If no revision range is specified, the default is ``tip:0`` unless
4050 If no revision range is specified, the default is ``tip:0`` unless
4041 --follow is set, in which case the working directory parent is
4051 --follow is set, in which case the working directory parent is
4042 used as the starting revision.
4052 used as the starting revision.
4043
4053
4044 File history is shown without following rename or copy history of
4054 File history is shown without following rename or copy history of
4045 files. Use -f/--follow with a filename to follow history across
4055 files. Use -f/--follow with a filename to follow history across
4046 renames and copies. --follow without a filename will only show
4056 renames and copies. --follow without a filename will only show
4047 ancestors or descendants of the starting revision.
4057 ancestors or descendants of the starting revision.
4048
4058
4049 By default this command prints revision number and changeset id,
4059 By default this command prints revision number and changeset id,
4050 tags, non-trivial parents, user, date and time, and a summary for
4060 tags, non-trivial parents, user, date and time, and a summary for
4051 each commit. When the -v/--verbose switch is used, the list of
4061 each commit. When the -v/--verbose switch is used, the list of
4052 changed files and full commit message are shown.
4062 changed files and full commit message are shown.
4053
4063
4054 With --graph the revisions are shown as an ASCII art DAG with the most
4064 With --graph the revisions are shown as an ASCII art DAG with the most
4055 recent changeset at the top.
4065 recent changeset at the top.
4056 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4066 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4057 and '+' represents a fork where the changeset from the lines below is a
4067 and '+' represents a fork where the changeset from the lines below is a
4058 parent of the 'o' merge on the same line.
4068 parent of the 'o' merge on the same line.
4059
4069
4060 .. note::
4070 .. note::
4061
4071
4062 log -p/--patch may generate unexpected diff output for merge
4072 log -p/--patch may generate unexpected diff output for merge
4063 changesets, as it will only compare the merge changeset against
4073 changesets, as it will only compare the merge changeset against
4064 its first parent. Also, only files different from BOTH parents
4074 its first parent. Also, only files different from BOTH parents
4065 will appear in files:.
4075 will appear in files:.
4066
4076
4067 .. note::
4077 .. note::
4068
4078
4069 for performance reasons, log FILE may omit duplicate changes
4079 for performance reasons, log FILE may omit duplicate changes
4070 made on branches and will not show deletions. To see all
4080 made on branches and will not show deletions. To see all
4071 changes including duplicates and deletions, use the --removed
4081 changes including duplicates and deletions, use the --removed
4072 switch.
4082 switch.
4073
4083
4074 .. container:: verbose
4084 .. container:: verbose
4075
4085
4076 Some examples:
4086 Some examples:
4077
4087
4078 - changesets with full descriptions and file lists::
4088 - changesets with full descriptions and file lists::
4079
4089
4080 hg log -v
4090 hg log -v
4081
4091
4082 - changesets ancestral to the working directory::
4092 - changesets ancestral to the working directory::
4083
4093
4084 hg log -f
4094 hg log -f
4085
4095
4086 - last 10 commits on the current branch::
4096 - last 10 commits on the current branch::
4087
4097
4088 hg log -l 10 -b .
4098 hg log -l 10 -b .
4089
4099
4090 - changesets showing all modifications of a file, including removals::
4100 - changesets showing all modifications of a file, including removals::
4091
4101
4092 hg log --removed file.c
4102 hg log --removed file.c
4093
4103
4094 - all changesets that touch a directory, with diffs, excluding merges::
4104 - all changesets that touch a directory, with diffs, excluding merges::
4095
4105
4096 hg log -Mp lib/
4106 hg log -Mp lib/
4097
4107
4098 - all revision numbers that match a keyword::
4108 - all revision numbers that match a keyword::
4099
4109
4100 hg log -k bug --template "{rev}\\n"
4110 hg log -k bug --template "{rev}\\n"
4101
4111
4102 - check if a given changeset is included is a tagged release::
4112 - check if a given changeset is included is a tagged release::
4103
4113
4104 hg log -r "a21ccf and ancestor(1.9)"
4114 hg log -r "a21ccf and ancestor(1.9)"
4105
4115
4106 - find all changesets by some user in a date range::
4116 - find all changesets by some user in a date range::
4107
4117
4108 hg log -k alice -d "may 2008 to jul 2008"
4118 hg log -k alice -d "may 2008 to jul 2008"
4109
4119
4110 - summary of all changesets after the last tag::
4120 - summary of all changesets after the last tag::
4111
4121
4112 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4122 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4113
4123
4114 See :hg:`help dates` for a list of formats valid for -d/--date.
4124 See :hg:`help dates` for a list of formats valid for -d/--date.
4115
4125
4116 See :hg:`help revisions` and :hg:`help revsets` for more about
4126 See :hg:`help revisions` and :hg:`help revsets` for more about
4117 specifying revisions.
4127 specifying revisions.
4118
4128
4119 See :hg:`help templates` for more about pre-packaged styles and
4129 See :hg:`help templates` for more about pre-packaged styles and
4120 specifying custom templates.
4130 specifying custom templates.
4121
4131
4122 Returns 0 on success.
4132 Returns 0 on success.
4123 """
4133 """
4124 if opts.get('graph'):
4134 if opts.get('graph'):
4125 return cmdutil.graphlog(ui, repo, *pats, **opts)
4135 return cmdutil.graphlog(ui, repo, *pats, **opts)
4126
4136
4127 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4137 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4128 limit = cmdutil.loglimit(opts)
4138 limit = cmdutil.loglimit(opts)
4129 count = 0
4139 count = 0
4130
4140
4131 getrenamed = None
4141 getrenamed = None
4132 if opts.get('copies'):
4142 if opts.get('copies'):
4133 endrev = None
4143 endrev = None
4134 if opts.get('rev'):
4144 if opts.get('rev'):
4135 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4145 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4136 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4146 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4137
4147
4138 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4148 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4139 for rev in revs:
4149 for rev in revs:
4140 if count == limit:
4150 if count == limit:
4141 break
4151 break
4142 ctx = repo[rev]
4152 ctx = repo[rev]
4143 copies = None
4153 copies = None
4144 if getrenamed is not None and rev:
4154 if getrenamed is not None and rev:
4145 copies = []
4155 copies = []
4146 for fn in ctx.files():
4156 for fn in ctx.files():
4147 rename = getrenamed(fn, rev)
4157 rename = getrenamed(fn, rev)
4148 if rename:
4158 if rename:
4149 copies.append((fn, rename[0]))
4159 copies.append((fn, rename[0]))
4150 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4160 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4151 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4161 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4152 if displayer.flush(rev):
4162 if displayer.flush(rev):
4153 count += 1
4163 count += 1
4154
4164
4155 displayer.close()
4165 displayer.close()
4156
4166
4157 @command('manifest',
4167 @command('manifest',
4158 [('r', 'rev', '', _('revision to display'), _('REV')),
4168 [('r', 'rev', '', _('revision to display'), _('REV')),
4159 ('', 'all', False, _("list files from all revisions"))],
4169 ('', 'all', False, _("list files from all revisions"))],
4160 _('[-r REV]'))
4170 _('[-r REV]'))
4161 def manifest(ui, repo, node=None, rev=None, **opts):
4171 def manifest(ui, repo, node=None, rev=None, **opts):
4162 """output the current or given revision of the project manifest
4172 """output the current or given revision of the project manifest
4163
4173
4164 Print a list of version controlled files for the given revision.
4174 Print a list of version controlled files for the given revision.
4165 If no revision is given, the first parent of the working directory
4175 If no revision is given, the first parent of the working directory
4166 is used, or the null revision if no revision is checked out.
4176 is used, or the null revision if no revision is checked out.
4167
4177
4168 With -v, print file permissions, symlink and executable bits.
4178 With -v, print file permissions, symlink and executable bits.
4169 With --debug, print file revision hashes.
4179 With --debug, print file revision hashes.
4170
4180
4171 If option --all is specified, the list of all files from all revisions
4181 If option --all is specified, the list of all files from all revisions
4172 is printed. This includes deleted and renamed files.
4182 is printed. This includes deleted and renamed files.
4173
4183
4174 Returns 0 on success.
4184 Returns 0 on success.
4175 """
4185 """
4176
4186
4177 fm = ui.formatter('manifest', opts)
4187 fm = ui.formatter('manifest', opts)
4178
4188
4179 if opts.get('all'):
4189 if opts.get('all'):
4180 if rev or node:
4190 if rev or node:
4181 raise util.Abort(_("can't specify a revision with --all"))
4191 raise util.Abort(_("can't specify a revision with --all"))
4182
4192
4183 res = []
4193 res = []
4184 prefix = "data/"
4194 prefix = "data/"
4185 suffix = ".i"
4195 suffix = ".i"
4186 plen = len(prefix)
4196 plen = len(prefix)
4187 slen = len(suffix)
4197 slen = len(suffix)
4188 lock = repo.lock()
4198 lock = repo.lock()
4189 try:
4199 try:
4190 for fn, b, size in repo.store.datafiles():
4200 for fn, b, size in repo.store.datafiles():
4191 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4201 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4192 res.append(fn[plen:-slen])
4202 res.append(fn[plen:-slen])
4193 finally:
4203 finally:
4194 lock.release()
4204 lock.release()
4195 for f in res:
4205 for f in res:
4196 fm.startitem()
4206 fm.startitem()
4197 fm.write("path", '%s\n', f)
4207 fm.write("path", '%s\n', f)
4198 fm.end()
4208 fm.end()
4199 return
4209 return
4200
4210
4201 if rev and node:
4211 if rev and node:
4202 raise util.Abort(_("please specify just one revision"))
4212 raise util.Abort(_("please specify just one revision"))
4203
4213
4204 if not node:
4214 if not node:
4205 node = rev
4215 node = rev
4206
4216
4207 char = {'l': '@', 'x': '*', '': ''}
4217 char = {'l': '@', 'x': '*', '': ''}
4208 mode = {'l': '644', 'x': '755', '': '644'}
4218 mode = {'l': '644', 'x': '755', '': '644'}
4209 ctx = scmutil.revsingle(repo, node)
4219 ctx = scmutil.revsingle(repo, node)
4210 mf = ctx.manifest()
4220 mf = ctx.manifest()
4211 for f in ctx:
4221 for f in ctx:
4212 fm.startitem()
4222 fm.startitem()
4213 fl = ctx[f].flags()
4223 fl = ctx[f].flags()
4214 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4224 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4215 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4225 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4216 fm.write('path', '%s\n', f)
4226 fm.write('path', '%s\n', f)
4217 fm.end()
4227 fm.end()
4218
4228
4219 @command('^merge',
4229 @command('^merge',
4220 [('f', 'force', None,
4230 [('f', 'force', None,
4221 _('force a merge including outstanding changes (DEPRECATED)')),
4231 _('force a merge including outstanding changes (DEPRECATED)')),
4222 ('r', 'rev', '', _('revision to merge'), _('REV')),
4232 ('r', 'rev', '', _('revision to merge'), _('REV')),
4223 ('P', 'preview', None,
4233 ('P', 'preview', None,
4224 _('review revisions to merge (no merge is performed)'))
4234 _('review revisions to merge (no merge is performed)'))
4225 ] + mergetoolopts,
4235 ] + mergetoolopts,
4226 _('[-P] [-f] [[-r] REV]'))
4236 _('[-P] [-f] [[-r] REV]'))
4227 def merge(ui, repo, node=None, **opts):
4237 def merge(ui, repo, node=None, **opts):
4228 """merge working directory with another revision
4238 """merge working directory with another revision
4229
4239
4230 The current working directory is updated with all changes made in
4240 The current working directory is updated with all changes made in
4231 the requested revision since the last common predecessor revision.
4241 the requested revision since the last common predecessor revision.
4232
4242
4233 Files that changed between either parent are marked as changed for
4243 Files that changed between either parent are marked as changed for
4234 the next commit and a commit must be performed before any further
4244 the next commit and a commit must be performed before any further
4235 updates to the repository are allowed. The next commit will have
4245 updates to the repository are allowed. The next commit will have
4236 two parents.
4246 two parents.
4237
4247
4238 ``--tool`` can be used to specify the merge tool used for file
4248 ``--tool`` can be used to specify the merge tool used for file
4239 merges. It overrides the HGMERGE environment variable and your
4249 merges. It overrides the HGMERGE environment variable and your
4240 configuration files. See :hg:`help merge-tools` for options.
4250 configuration files. See :hg:`help merge-tools` for options.
4241
4251
4242 If no revision is specified, the working directory's parent is a
4252 If no revision is specified, the working directory's parent is a
4243 head revision, and the current branch contains exactly one other
4253 head revision, and the current branch contains exactly one other
4244 head, the other head is merged with by default. Otherwise, an
4254 head, the other head is merged with by default. Otherwise, an
4245 explicit revision with which to merge with must be provided.
4255 explicit revision with which to merge with must be provided.
4246
4256
4247 :hg:`resolve` must be used to resolve unresolved files.
4257 :hg:`resolve` must be used to resolve unresolved files.
4248
4258
4249 To undo an uncommitted merge, use :hg:`update --clean .` which
4259 To undo an uncommitted merge, use :hg:`update --clean .` which
4250 will check out a clean copy of the original merge parent, losing
4260 will check out a clean copy of the original merge parent, losing
4251 all changes.
4261 all changes.
4252
4262
4253 Returns 0 on success, 1 if there are unresolved files.
4263 Returns 0 on success, 1 if there are unresolved files.
4254 """
4264 """
4255
4265
4256 if opts.get('rev') and node:
4266 if opts.get('rev') and node:
4257 raise util.Abort(_("please specify just one revision"))
4267 raise util.Abort(_("please specify just one revision"))
4258 if not node:
4268 if not node:
4259 node = opts.get('rev')
4269 node = opts.get('rev')
4260
4270
4261 if node:
4271 if node:
4262 node = scmutil.revsingle(repo, node).node()
4272 node = scmutil.revsingle(repo, node).node()
4263
4273
4264 if not node and repo._bookmarkcurrent:
4274 if not node and repo._bookmarkcurrent:
4265 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4275 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4266 curhead = repo[repo._bookmarkcurrent].node()
4276 curhead = repo[repo._bookmarkcurrent].node()
4267 if len(bmheads) == 2:
4277 if len(bmheads) == 2:
4268 if curhead == bmheads[0]:
4278 if curhead == bmheads[0]:
4269 node = bmheads[1]
4279 node = bmheads[1]
4270 else:
4280 else:
4271 node = bmheads[0]
4281 node = bmheads[0]
4272 elif len(bmheads) > 2:
4282 elif len(bmheads) > 2:
4273 raise util.Abort(_("multiple matching bookmarks to merge - "
4283 raise util.Abort(_("multiple matching bookmarks to merge - "
4274 "please merge with an explicit rev or bookmark"),
4284 "please merge with an explicit rev or bookmark"),
4275 hint=_("run 'hg heads' to see all heads"))
4285 hint=_("run 'hg heads' to see all heads"))
4276 elif len(bmheads) <= 1:
4286 elif len(bmheads) <= 1:
4277 raise util.Abort(_("no matching bookmark to merge - "
4287 raise util.Abort(_("no matching bookmark to merge - "
4278 "please merge with an explicit rev or bookmark"),
4288 "please merge with an explicit rev or bookmark"),
4279 hint=_("run 'hg heads' to see all heads"))
4289 hint=_("run 'hg heads' to see all heads"))
4280
4290
4281 if not node and not repo._bookmarkcurrent:
4291 if not node and not repo._bookmarkcurrent:
4282 branch = repo[None].branch()
4292 branch = repo[None].branch()
4283 bheads = repo.branchheads(branch)
4293 bheads = repo.branchheads(branch)
4284 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4294 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4285
4295
4286 if len(nbhs) > 2:
4296 if len(nbhs) > 2:
4287 raise util.Abort(_("branch '%s' has %d heads - "
4297 raise util.Abort(_("branch '%s' has %d heads - "
4288 "please merge with an explicit rev")
4298 "please merge with an explicit rev")
4289 % (branch, len(bheads)),
4299 % (branch, len(bheads)),
4290 hint=_("run 'hg heads .' to see heads"))
4300 hint=_("run 'hg heads .' to see heads"))
4291
4301
4292 parent = repo.dirstate.p1()
4302 parent = repo.dirstate.p1()
4293 if len(nbhs) <= 1:
4303 if len(nbhs) <= 1:
4294 if len(bheads) > 1:
4304 if len(bheads) > 1:
4295 raise util.Abort(_("heads are bookmarked - "
4305 raise util.Abort(_("heads are bookmarked - "
4296 "please merge with an explicit rev"),
4306 "please merge with an explicit rev"),
4297 hint=_("run 'hg heads' to see all heads"))
4307 hint=_("run 'hg heads' to see all heads"))
4298 if len(repo.heads()) > 1:
4308 if len(repo.heads()) > 1:
4299 raise util.Abort(_("branch '%s' has one head - "
4309 raise util.Abort(_("branch '%s' has one head - "
4300 "please merge with an explicit rev")
4310 "please merge with an explicit rev")
4301 % branch,
4311 % branch,
4302 hint=_("run 'hg heads' to see all heads"))
4312 hint=_("run 'hg heads' to see all heads"))
4303 msg, hint = _('nothing to merge'), None
4313 msg, hint = _('nothing to merge'), None
4304 if parent != repo.lookup(branch):
4314 if parent != repo.lookup(branch):
4305 hint = _("use 'hg update' instead")
4315 hint = _("use 'hg update' instead")
4306 raise util.Abort(msg, hint=hint)
4316 raise util.Abort(msg, hint=hint)
4307
4317
4308 if parent not in bheads:
4318 if parent not in bheads:
4309 raise util.Abort(_('working directory not at a head revision'),
4319 raise util.Abort(_('working directory not at a head revision'),
4310 hint=_("use 'hg update' or merge with an "
4320 hint=_("use 'hg update' or merge with an "
4311 "explicit revision"))
4321 "explicit revision"))
4312 if parent == nbhs[0]:
4322 if parent == nbhs[0]:
4313 node = nbhs[-1]
4323 node = nbhs[-1]
4314 else:
4324 else:
4315 node = nbhs[0]
4325 node = nbhs[0]
4316
4326
4317 if opts.get('preview'):
4327 if opts.get('preview'):
4318 # find nodes that are ancestors of p2 but not of p1
4328 # find nodes that are ancestors of p2 but not of p1
4319 p1 = repo.lookup('.')
4329 p1 = repo.lookup('.')
4320 p2 = repo.lookup(node)
4330 p2 = repo.lookup(node)
4321 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4331 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4322
4332
4323 displayer = cmdutil.show_changeset(ui, repo, opts)
4333 displayer = cmdutil.show_changeset(ui, repo, opts)
4324 for node in nodes:
4334 for node in nodes:
4325 displayer.show(repo[node])
4335 displayer.show(repo[node])
4326 displayer.close()
4336 displayer.close()
4327 return 0
4337 return 0
4328
4338
4329 try:
4339 try:
4330 # ui.forcemerge is an internal variable, do not document
4340 # ui.forcemerge is an internal variable, do not document
4331 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4341 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4332 return hg.merge(repo, node, force=opts.get('force'))
4342 return hg.merge(repo, node, force=opts.get('force'))
4333 finally:
4343 finally:
4334 ui.setconfig('ui', 'forcemerge', '', 'merge')
4344 ui.setconfig('ui', 'forcemerge', '', 'merge')
4335
4345
4336 @command('outgoing|out',
4346 @command('outgoing|out',
4337 [('f', 'force', None, _('run even when the destination is unrelated')),
4347 [('f', 'force', None, _('run even when the destination is unrelated')),
4338 ('r', 'rev', [],
4348 ('r', 'rev', [],
4339 _('a changeset intended to be included in the destination'), _('REV')),
4349 _('a changeset intended to be included in the destination'), _('REV')),
4340 ('n', 'newest-first', None, _('show newest record first')),
4350 ('n', 'newest-first', None, _('show newest record first')),
4341 ('B', 'bookmarks', False, _('compare bookmarks')),
4351 ('B', 'bookmarks', False, _('compare bookmarks')),
4342 ('b', 'branch', [], _('a specific branch you would like to push'),
4352 ('b', 'branch', [], _('a specific branch you would like to push'),
4343 _('BRANCH')),
4353 _('BRANCH')),
4344 ] + logopts + remoteopts + subrepoopts,
4354 ] + logopts + remoteopts + subrepoopts,
4345 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4355 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4346 def outgoing(ui, repo, dest=None, **opts):
4356 def outgoing(ui, repo, dest=None, **opts):
4347 """show changesets not found in the destination
4357 """show changesets not found in the destination
4348
4358
4349 Show changesets not found in the specified destination repository
4359 Show changesets not found in the specified destination repository
4350 or the default push location. These are the changesets that would
4360 or the default push location. These are the changesets that would
4351 be pushed if a push was requested.
4361 be pushed if a push was requested.
4352
4362
4353 See pull for details of valid destination formats.
4363 See pull for details of valid destination formats.
4354
4364
4355 Returns 0 if there are outgoing changes, 1 otherwise.
4365 Returns 0 if there are outgoing changes, 1 otherwise.
4356 """
4366 """
4357 if opts.get('graph'):
4367 if opts.get('graph'):
4358 cmdutil.checkunsupportedgraphflags([], opts)
4368 cmdutil.checkunsupportedgraphflags([], opts)
4359 o, other = hg._outgoing(ui, repo, dest, opts)
4369 o, other = hg._outgoing(ui, repo, dest, opts)
4360 if not o:
4370 if not o:
4361 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4371 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4362 return
4372 return
4363
4373
4364 revdag = cmdutil.graphrevs(repo, o, opts)
4374 revdag = cmdutil.graphrevs(repo, o, opts)
4365 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4375 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4366 showparents = [ctx.node() for ctx in repo[None].parents()]
4376 showparents = [ctx.node() for ctx in repo[None].parents()]
4367 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4377 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4368 graphmod.asciiedges)
4378 graphmod.asciiedges)
4369 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4379 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4370 return 0
4380 return 0
4371
4381
4372 if opts.get('bookmarks'):
4382 if opts.get('bookmarks'):
4373 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4383 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4374 dest, branches = hg.parseurl(dest, opts.get('branch'))
4384 dest, branches = hg.parseurl(dest, opts.get('branch'))
4375 other = hg.peer(repo, opts, dest)
4385 other = hg.peer(repo, opts, dest)
4376 if 'bookmarks' not in other.listkeys('namespaces'):
4386 if 'bookmarks' not in other.listkeys('namespaces'):
4377 ui.warn(_("remote doesn't support bookmarks\n"))
4387 ui.warn(_("remote doesn't support bookmarks\n"))
4378 return 0
4388 return 0
4379 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4389 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4380 return bookmarks.diff(ui, other, repo)
4390 return bookmarks.diff(ui, other, repo)
4381
4391
4382 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4392 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4383 try:
4393 try:
4384 return hg.outgoing(ui, repo, dest, opts)
4394 return hg.outgoing(ui, repo, dest, opts)
4385 finally:
4395 finally:
4386 del repo._subtoppath
4396 del repo._subtoppath
4387
4397
4388 @command('parents',
4398 @command('parents',
4389 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4399 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4390 ] + templateopts,
4400 ] + templateopts,
4391 _('[-r REV] [FILE]'))
4401 _('[-r REV] [FILE]'))
4392 def parents(ui, repo, file_=None, **opts):
4402 def parents(ui, repo, file_=None, **opts):
4393 """show the parents of the working directory or revision
4403 """show the parents of the working directory or revision
4394
4404
4395 Print the working directory's parent revisions. If a revision is
4405 Print the working directory's parent revisions. If a revision is
4396 given via -r/--rev, the parent of that revision will be printed.
4406 given via -r/--rev, the parent of that revision will be printed.
4397 If a file argument is given, the revision in which the file was
4407 If a file argument is given, the revision in which the file was
4398 last changed (before the working directory revision or the
4408 last changed (before the working directory revision or the
4399 argument to --rev if given) is printed.
4409 argument to --rev if given) is printed.
4400
4410
4401 Returns 0 on success.
4411 Returns 0 on success.
4402 """
4412 """
4403
4413
4404 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4414 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4405
4415
4406 if file_:
4416 if file_:
4407 m = scmutil.match(ctx, (file_,), opts)
4417 m = scmutil.match(ctx, (file_,), opts)
4408 if m.anypats() or len(m.files()) != 1:
4418 if m.anypats() or len(m.files()) != 1:
4409 raise util.Abort(_('can only specify an explicit filename'))
4419 raise util.Abort(_('can only specify an explicit filename'))
4410 file_ = m.files()[0]
4420 file_ = m.files()[0]
4411 filenodes = []
4421 filenodes = []
4412 for cp in ctx.parents():
4422 for cp in ctx.parents():
4413 if not cp:
4423 if not cp:
4414 continue
4424 continue
4415 try:
4425 try:
4416 filenodes.append(cp.filenode(file_))
4426 filenodes.append(cp.filenode(file_))
4417 except error.LookupError:
4427 except error.LookupError:
4418 pass
4428 pass
4419 if not filenodes:
4429 if not filenodes:
4420 raise util.Abort(_("'%s' not found in manifest!") % file_)
4430 raise util.Abort(_("'%s' not found in manifest!") % file_)
4421 p = []
4431 p = []
4422 for fn in filenodes:
4432 for fn in filenodes:
4423 fctx = repo.filectx(file_, fileid=fn)
4433 fctx = repo.filectx(file_, fileid=fn)
4424 p.append(fctx.node())
4434 p.append(fctx.node())
4425 else:
4435 else:
4426 p = [cp.node() for cp in ctx.parents()]
4436 p = [cp.node() for cp in ctx.parents()]
4427
4437
4428 displayer = cmdutil.show_changeset(ui, repo, opts)
4438 displayer = cmdutil.show_changeset(ui, repo, opts)
4429 for n in p:
4439 for n in p:
4430 if n != nullid:
4440 if n != nullid:
4431 displayer.show(repo[n])
4441 displayer.show(repo[n])
4432 displayer.close()
4442 displayer.close()
4433
4443
4434 @command('paths', [], _('[NAME]'))
4444 @command('paths', [], _('[NAME]'))
4435 def paths(ui, repo, search=None):
4445 def paths(ui, repo, search=None):
4436 """show aliases for remote repositories
4446 """show aliases for remote repositories
4437
4447
4438 Show definition of symbolic path name NAME. If no name is given,
4448 Show definition of symbolic path name NAME. If no name is given,
4439 show definition of all available names.
4449 show definition of all available names.
4440
4450
4441 Option -q/--quiet suppresses all output when searching for NAME
4451 Option -q/--quiet suppresses all output when searching for NAME
4442 and shows only the path names when listing all definitions.
4452 and shows only the path names when listing all definitions.
4443
4453
4444 Path names are defined in the [paths] section of your
4454 Path names are defined in the [paths] section of your
4445 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4455 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4446 repository, ``.hg/hgrc`` is used, too.
4456 repository, ``.hg/hgrc`` is used, too.
4447
4457
4448 The path names ``default`` and ``default-push`` have a special
4458 The path names ``default`` and ``default-push`` have a special
4449 meaning. When performing a push or pull operation, they are used
4459 meaning. When performing a push or pull operation, they are used
4450 as fallbacks if no location is specified on the command-line.
4460 as fallbacks if no location is specified on the command-line.
4451 When ``default-push`` is set, it will be used for push and
4461 When ``default-push`` is set, it will be used for push and
4452 ``default`` will be used for pull; otherwise ``default`` is used
4462 ``default`` will be used for pull; otherwise ``default`` is used
4453 as the fallback for both. When cloning a repository, the clone
4463 as the fallback for both. When cloning a repository, the clone
4454 source is written as ``default`` in ``.hg/hgrc``. Note that
4464 source is written as ``default`` in ``.hg/hgrc``. Note that
4455 ``default`` and ``default-push`` apply to all inbound (e.g.
4465 ``default`` and ``default-push`` apply to all inbound (e.g.
4456 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4466 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4457 :hg:`bundle`) operations.
4467 :hg:`bundle`) operations.
4458
4468
4459 See :hg:`help urls` for more information.
4469 See :hg:`help urls` for more information.
4460
4470
4461 Returns 0 on success.
4471 Returns 0 on success.
4462 """
4472 """
4463 if search:
4473 if search:
4464 for name, path in ui.configitems("paths"):
4474 for name, path in ui.configitems("paths"):
4465 if name == search:
4475 if name == search:
4466 ui.status("%s\n" % util.hidepassword(path))
4476 ui.status("%s\n" % util.hidepassword(path))
4467 return
4477 return
4468 if not ui.quiet:
4478 if not ui.quiet:
4469 ui.warn(_("not found!\n"))
4479 ui.warn(_("not found!\n"))
4470 return 1
4480 return 1
4471 else:
4481 else:
4472 for name, path in ui.configitems("paths"):
4482 for name, path in ui.configitems("paths"):
4473 if ui.quiet:
4483 if ui.quiet:
4474 ui.write("%s\n" % name)
4484 ui.write("%s\n" % name)
4475 else:
4485 else:
4476 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4486 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4477
4487
4478 @command('phase',
4488 @command('phase',
4479 [('p', 'public', False, _('set changeset phase to public')),
4489 [('p', 'public', False, _('set changeset phase to public')),
4480 ('d', 'draft', False, _('set changeset phase to draft')),
4490 ('d', 'draft', False, _('set changeset phase to draft')),
4481 ('s', 'secret', False, _('set changeset phase to secret')),
4491 ('s', 'secret', False, _('set changeset phase to secret')),
4482 ('f', 'force', False, _('allow to move boundary backward')),
4492 ('f', 'force', False, _('allow to move boundary backward')),
4483 ('r', 'rev', [], _('target revision'), _('REV')),
4493 ('r', 'rev', [], _('target revision'), _('REV')),
4484 ],
4494 ],
4485 _('[-p|-d|-s] [-f] [-r] REV...'))
4495 _('[-p|-d|-s] [-f] [-r] REV...'))
4486 def phase(ui, repo, *revs, **opts):
4496 def phase(ui, repo, *revs, **opts):
4487 """set or show the current phase name
4497 """set or show the current phase name
4488
4498
4489 With no argument, show the phase name of specified revisions.
4499 With no argument, show the phase name of specified revisions.
4490
4500
4491 With one of -p/--public, -d/--draft or -s/--secret, change the
4501 With one of -p/--public, -d/--draft or -s/--secret, change the
4492 phase value of the specified revisions.
4502 phase value of the specified revisions.
4493
4503
4494 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4504 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4495 lower phase to an higher phase. Phases are ordered as follows::
4505 lower phase to an higher phase. Phases are ordered as follows::
4496
4506
4497 public < draft < secret
4507 public < draft < secret
4498
4508
4499 Returns 0 on success, 1 if no phases were changed or some could not
4509 Returns 0 on success, 1 if no phases were changed or some could not
4500 be changed.
4510 be changed.
4501 """
4511 """
4502 # search for a unique phase argument
4512 # search for a unique phase argument
4503 targetphase = None
4513 targetphase = None
4504 for idx, name in enumerate(phases.phasenames):
4514 for idx, name in enumerate(phases.phasenames):
4505 if opts[name]:
4515 if opts[name]:
4506 if targetphase is not None:
4516 if targetphase is not None:
4507 raise util.Abort(_('only one phase can be specified'))
4517 raise util.Abort(_('only one phase can be specified'))
4508 targetphase = idx
4518 targetphase = idx
4509
4519
4510 # look for specified revision
4520 # look for specified revision
4511 revs = list(revs)
4521 revs = list(revs)
4512 revs.extend(opts['rev'])
4522 revs.extend(opts['rev'])
4513 if not revs:
4523 if not revs:
4514 raise util.Abort(_('no revisions specified'))
4524 raise util.Abort(_('no revisions specified'))
4515
4525
4516 revs = scmutil.revrange(repo, revs)
4526 revs = scmutil.revrange(repo, revs)
4517
4527
4518 lock = None
4528 lock = None
4519 ret = 0
4529 ret = 0
4520 if targetphase is None:
4530 if targetphase is None:
4521 # display
4531 # display
4522 for r in revs:
4532 for r in revs:
4523 ctx = repo[r]
4533 ctx = repo[r]
4524 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4534 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4525 else:
4535 else:
4526 lock = repo.lock()
4536 lock = repo.lock()
4527 try:
4537 try:
4528 # set phase
4538 # set phase
4529 if not revs:
4539 if not revs:
4530 raise util.Abort(_('empty revision set'))
4540 raise util.Abort(_('empty revision set'))
4531 nodes = [repo[r].node() for r in revs]
4541 nodes = [repo[r].node() for r in revs]
4532 olddata = repo._phasecache.getphaserevs(repo)[:]
4542 olddata = repo._phasecache.getphaserevs(repo)[:]
4533 phases.advanceboundary(repo, targetphase, nodes)
4543 phases.advanceboundary(repo, targetphase, nodes)
4534 if opts['force']:
4544 if opts['force']:
4535 phases.retractboundary(repo, targetphase, nodes)
4545 phases.retractboundary(repo, targetphase, nodes)
4536 finally:
4546 finally:
4537 lock.release()
4547 lock.release()
4538 # moving revision from public to draft may hide them
4548 # moving revision from public to draft may hide them
4539 # We have to check result on an unfiltered repository
4549 # We have to check result on an unfiltered repository
4540 unfi = repo.unfiltered()
4550 unfi = repo.unfiltered()
4541 newdata = repo._phasecache.getphaserevs(unfi)
4551 newdata = repo._phasecache.getphaserevs(unfi)
4542 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4552 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4543 cl = unfi.changelog
4553 cl = unfi.changelog
4544 rejected = [n for n in nodes
4554 rejected = [n for n in nodes
4545 if newdata[cl.rev(n)] < targetphase]
4555 if newdata[cl.rev(n)] < targetphase]
4546 if rejected:
4556 if rejected:
4547 ui.warn(_('cannot move %i changesets to a higher '
4557 ui.warn(_('cannot move %i changesets to a higher '
4548 'phase, use --force\n') % len(rejected))
4558 'phase, use --force\n') % len(rejected))
4549 ret = 1
4559 ret = 1
4550 if changes:
4560 if changes:
4551 msg = _('phase changed for %i changesets\n') % changes
4561 msg = _('phase changed for %i changesets\n') % changes
4552 if ret:
4562 if ret:
4553 ui.status(msg)
4563 ui.status(msg)
4554 else:
4564 else:
4555 ui.note(msg)
4565 ui.note(msg)
4556 else:
4566 else:
4557 ui.warn(_('no phases changed\n'))
4567 ui.warn(_('no phases changed\n'))
4558 ret = 1
4568 ret = 1
4559 return ret
4569 return ret
4560
4570
4561 def postincoming(ui, repo, modheads, optupdate, checkout):
4571 def postincoming(ui, repo, modheads, optupdate, checkout):
4562 if modheads == 0:
4572 if modheads == 0:
4563 return
4573 return
4564 if optupdate:
4574 if optupdate:
4565 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4575 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4566 try:
4576 try:
4567 ret = hg.update(repo, checkout)
4577 ret = hg.update(repo, checkout)
4568 except util.Abort, inst:
4578 except util.Abort, inst:
4569 ui.warn(_("not updating: %s\n") % str(inst))
4579 ui.warn(_("not updating: %s\n") % str(inst))
4570 if inst.hint:
4580 if inst.hint:
4571 ui.warn(_("(%s)\n") % inst.hint)
4581 ui.warn(_("(%s)\n") % inst.hint)
4572 return 0
4582 return 0
4573 if not ret and not checkout:
4583 if not ret and not checkout:
4574 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4584 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4575 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4585 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4576 return ret
4586 return ret
4577 if modheads > 1:
4587 if modheads > 1:
4578 currentbranchheads = len(repo.branchheads())
4588 currentbranchheads = len(repo.branchheads())
4579 if currentbranchheads == modheads:
4589 if currentbranchheads == modheads:
4580 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4590 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4581 elif currentbranchheads > 1:
4591 elif currentbranchheads > 1:
4582 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4592 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4583 "merge)\n"))
4593 "merge)\n"))
4584 else:
4594 else:
4585 ui.status(_("(run 'hg heads' to see heads)\n"))
4595 ui.status(_("(run 'hg heads' to see heads)\n"))
4586 else:
4596 else:
4587 ui.status(_("(run 'hg update' to get a working copy)\n"))
4597 ui.status(_("(run 'hg update' to get a working copy)\n"))
4588
4598
4589 @command('^pull',
4599 @command('^pull',
4590 [('u', 'update', None,
4600 [('u', 'update', None,
4591 _('update to new branch head if changesets were pulled')),
4601 _('update to new branch head if changesets were pulled')),
4592 ('f', 'force', None, _('run even when remote repository is unrelated')),
4602 ('f', 'force', None, _('run even when remote repository is unrelated')),
4593 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4603 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4594 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4604 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4595 ('b', 'branch', [], _('a specific branch you would like to pull'),
4605 ('b', 'branch', [], _('a specific branch you would like to pull'),
4596 _('BRANCH')),
4606 _('BRANCH')),
4597 ] + remoteopts,
4607 ] + remoteopts,
4598 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4608 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4599 def pull(ui, repo, source="default", **opts):
4609 def pull(ui, repo, source="default", **opts):
4600 """pull changes from the specified source
4610 """pull changes from the specified source
4601
4611
4602 Pull changes from a remote repository to a local one.
4612 Pull changes from a remote repository to a local one.
4603
4613
4604 This finds all changes from the repository at the specified path
4614 This finds all changes from the repository at the specified path
4605 or URL and adds them to a local repository (the current one unless
4615 or URL and adds them to a local repository (the current one unless
4606 -R is specified). By default, this does not update the copy of the
4616 -R is specified). By default, this does not update the copy of the
4607 project in the working directory.
4617 project in the working directory.
4608
4618
4609 Use :hg:`incoming` if you want to see what would have been added
4619 Use :hg:`incoming` if you want to see what would have been added
4610 by a pull at the time you issued this command. If you then decide
4620 by a pull at the time you issued this command. If you then decide
4611 to add those changes to the repository, you should use :hg:`pull
4621 to add those changes to the repository, you should use :hg:`pull
4612 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4622 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4613
4623
4614 If SOURCE is omitted, the 'default' path will be used.
4624 If SOURCE is omitted, the 'default' path will be used.
4615 See :hg:`help urls` for more information.
4625 See :hg:`help urls` for more information.
4616
4626
4617 Returns 0 on success, 1 if an update had unresolved files.
4627 Returns 0 on success, 1 if an update had unresolved files.
4618 """
4628 """
4619 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4629 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4620 other = hg.peer(repo, opts, source)
4630 other = hg.peer(repo, opts, source)
4621 try:
4631 try:
4622 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4632 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4623 revs, checkout = hg.addbranchrevs(repo, other, branches,
4633 revs, checkout = hg.addbranchrevs(repo, other, branches,
4624 opts.get('rev'))
4634 opts.get('rev'))
4625
4635
4626 remotebookmarks = other.listkeys('bookmarks')
4636 remotebookmarks = other.listkeys('bookmarks')
4627
4637
4628 if opts.get('bookmark'):
4638 if opts.get('bookmark'):
4629 if not revs:
4639 if not revs:
4630 revs = []
4640 revs = []
4631 for b in opts['bookmark']:
4641 for b in opts['bookmark']:
4632 if b not in remotebookmarks:
4642 if b not in remotebookmarks:
4633 raise util.Abort(_('remote bookmark %s not found!') % b)
4643 raise util.Abort(_('remote bookmark %s not found!') % b)
4634 revs.append(remotebookmarks[b])
4644 revs.append(remotebookmarks[b])
4635
4645
4636 if revs:
4646 if revs:
4637 try:
4647 try:
4638 revs = [other.lookup(rev) for rev in revs]
4648 revs = [other.lookup(rev) for rev in revs]
4639 except error.CapabilityError:
4649 except error.CapabilityError:
4640 err = _("other repository doesn't support revision lookup, "
4650 err = _("other repository doesn't support revision lookup, "
4641 "so a rev cannot be specified.")
4651 "so a rev cannot be specified.")
4642 raise util.Abort(err)
4652 raise util.Abort(err)
4643
4653
4644 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4654 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4645 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4655 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4646 if checkout:
4656 if checkout:
4647 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4657 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4648 repo._subtoppath = source
4658 repo._subtoppath = source
4649 try:
4659 try:
4650 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4660 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4651
4661
4652 finally:
4662 finally:
4653 del repo._subtoppath
4663 del repo._subtoppath
4654
4664
4655 # update specified bookmarks
4665 # update specified bookmarks
4656 if opts.get('bookmark'):
4666 if opts.get('bookmark'):
4657 marks = repo._bookmarks
4667 marks = repo._bookmarks
4658 for b in opts['bookmark']:
4668 for b in opts['bookmark']:
4659 # explicit pull overrides local bookmark if any
4669 # explicit pull overrides local bookmark if any
4660 ui.status(_("importing bookmark %s\n") % b)
4670 ui.status(_("importing bookmark %s\n") % b)
4661 marks[b] = repo[remotebookmarks[b]].node()
4671 marks[b] = repo[remotebookmarks[b]].node()
4662 marks.write()
4672 marks.write()
4663 finally:
4673 finally:
4664 other.close()
4674 other.close()
4665 return ret
4675 return ret
4666
4676
4667 @command('^push',
4677 @command('^push',
4668 [('f', 'force', None, _('force push')),
4678 [('f', 'force', None, _('force push')),
4669 ('r', 'rev', [],
4679 ('r', 'rev', [],
4670 _('a changeset intended to be included in the destination'),
4680 _('a changeset intended to be included in the destination'),
4671 _('REV')),
4681 _('REV')),
4672 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4682 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4673 ('b', 'branch', [],
4683 ('b', 'branch', [],
4674 _('a specific branch you would like to push'), _('BRANCH')),
4684 _('a specific branch you would like to push'), _('BRANCH')),
4675 ('', 'new-branch', False, _('allow pushing a new branch')),
4685 ('', 'new-branch', False, _('allow pushing a new branch')),
4676 ] + remoteopts,
4686 ] + remoteopts,
4677 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4687 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4678 def push(ui, repo, dest=None, **opts):
4688 def push(ui, repo, dest=None, **opts):
4679 """push changes to the specified destination
4689 """push changes to the specified destination
4680
4690
4681 Push changesets from the local repository to the specified
4691 Push changesets from the local repository to the specified
4682 destination.
4692 destination.
4683
4693
4684 This operation is symmetrical to pull: it is identical to a pull
4694 This operation is symmetrical to pull: it is identical to a pull
4685 in the destination repository from the current one.
4695 in the destination repository from the current one.
4686
4696
4687 By default, push will not allow creation of new heads at the
4697 By default, push will not allow creation of new heads at the
4688 destination, since multiple heads would make it unclear which head
4698 destination, since multiple heads would make it unclear which head
4689 to use. In this situation, it is recommended to pull and merge
4699 to use. In this situation, it is recommended to pull and merge
4690 before pushing.
4700 before pushing.
4691
4701
4692 Use --new-branch if you want to allow push to create a new named
4702 Use --new-branch if you want to allow push to create a new named
4693 branch that is not present at the destination. This allows you to
4703 branch that is not present at the destination. This allows you to
4694 only create a new branch without forcing other changes.
4704 only create a new branch without forcing other changes.
4695
4705
4696 .. note::
4706 .. note::
4697
4707
4698 Extra care should be taken with the -f/--force option,
4708 Extra care should be taken with the -f/--force option,
4699 which will push all new heads on all branches, an action which will
4709 which will push all new heads on all branches, an action which will
4700 almost always cause confusion for collaborators.
4710 almost always cause confusion for collaborators.
4701
4711
4702 If -r/--rev is used, the specified revision and all its ancestors
4712 If -r/--rev is used, the specified revision and all its ancestors
4703 will be pushed to the remote repository.
4713 will be pushed to the remote repository.
4704
4714
4705 If -B/--bookmark is used, the specified bookmarked revision, its
4715 If -B/--bookmark is used, the specified bookmarked revision, its
4706 ancestors, and the bookmark will be pushed to the remote
4716 ancestors, and the bookmark will be pushed to the remote
4707 repository.
4717 repository.
4708
4718
4709 Please see :hg:`help urls` for important details about ``ssh://``
4719 Please see :hg:`help urls` for important details about ``ssh://``
4710 URLs. If DESTINATION is omitted, a default path will be used.
4720 URLs. If DESTINATION is omitted, a default path will be used.
4711
4721
4712 Returns 0 if push was successful, 1 if nothing to push.
4722 Returns 0 if push was successful, 1 if nothing to push.
4713 """
4723 """
4714
4724
4715 if opts.get('bookmark'):
4725 if opts.get('bookmark'):
4716 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4726 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4717 for b in opts['bookmark']:
4727 for b in opts['bookmark']:
4718 # translate -B options to -r so changesets get pushed
4728 # translate -B options to -r so changesets get pushed
4719 if b in repo._bookmarks:
4729 if b in repo._bookmarks:
4720 opts.setdefault('rev', []).append(b)
4730 opts.setdefault('rev', []).append(b)
4721 else:
4731 else:
4722 # if we try to push a deleted bookmark, translate it to null
4732 # if we try to push a deleted bookmark, translate it to null
4723 # this lets simultaneous -r, -b options continue working
4733 # this lets simultaneous -r, -b options continue working
4724 opts.setdefault('rev', []).append("null")
4734 opts.setdefault('rev', []).append("null")
4725
4735
4726 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4736 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4727 dest, branches = hg.parseurl(dest, opts.get('branch'))
4737 dest, branches = hg.parseurl(dest, opts.get('branch'))
4728 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4738 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4729 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4739 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4730 try:
4740 try:
4731 other = hg.peer(repo, opts, dest)
4741 other = hg.peer(repo, opts, dest)
4732 except error.RepoError:
4742 except error.RepoError:
4733 if dest == "default-push":
4743 if dest == "default-push":
4734 raise util.Abort(_("default repository not configured!"),
4744 raise util.Abort(_("default repository not configured!"),
4735 hint=_('see the "path" section in "hg help config"'))
4745 hint=_('see the "path" section in "hg help config"'))
4736 else:
4746 else:
4737 raise
4747 raise
4738
4748
4739 if revs:
4749 if revs:
4740 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4750 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4741
4751
4742 repo._subtoppath = dest
4752 repo._subtoppath = dest
4743 try:
4753 try:
4744 # push subrepos depth-first for coherent ordering
4754 # push subrepos depth-first for coherent ordering
4745 c = repo['']
4755 c = repo['']
4746 subs = c.substate # only repos that are committed
4756 subs = c.substate # only repos that are committed
4747 for s in sorted(subs):
4757 for s in sorted(subs):
4748 result = c.sub(s).push(opts)
4758 result = c.sub(s).push(opts)
4749 if result == 0:
4759 if result == 0:
4750 return not result
4760 return not result
4751 finally:
4761 finally:
4752 del repo._subtoppath
4762 del repo._subtoppath
4753 result = repo.push(other, opts.get('force'), revs=revs,
4763 result = repo.push(other, opts.get('force'), revs=revs,
4754 newbranch=opts.get('new_branch'))
4764 newbranch=opts.get('new_branch'))
4755
4765
4756 result = not result
4766 result = not result
4757
4767
4758 if opts.get('bookmark'):
4768 if opts.get('bookmark'):
4759 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4769 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4760 if bresult == 2:
4770 if bresult == 2:
4761 return 2
4771 return 2
4762 if not result and bresult:
4772 if not result and bresult:
4763 result = 2
4773 result = 2
4764
4774
4765 return result
4775 return result
4766
4776
4767 @command('recover', [])
4777 @command('recover', [])
4768 def recover(ui, repo):
4778 def recover(ui, repo):
4769 """roll back an interrupted transaction
4779 """roll back an interrupted transaction
4770
4780
4771 Recover from an interrupted commit or pull.
4781 Recover from an interrupted commit or pull.
4772
4782
4773 This command tries to fix the repository status after an
4783 This command tries to fix the repository status after an
4774 interrupted operation. It should only be necessary when Mercurial
4784 interrupted operation. It should only be necessary when Mercurial
4775 suggests it.
4785 suggests it.
4776
4786
4777 Returns 0 if successful, 1 if nothing to recover or verify fails.
4787 Returns 0 if successful, 1 if nothing to recover or verify fails.
4778 """
4788 """
4779 if repo.recover():
4789 if repo.recover():
4780 return hg.verify(repo)
4790 return hg.verify(repo)
4781 return 1
4791 return 1
4782
4792
4783 @command('^remove|rm',
4793 @command('^remove|rm',
4784 [('A', 'after', None, _('record delete for missing files')),
4794 [('A', 'after', None, _('record delete for missing files')),
4785 ('f', 'force', None,
4795 ('f', 'force', None,
4786 _('remove (and delete) file even if added or modified')),
4796 _('remove (and delete) file even if added or modified')),
4787 ] + walkopts,
4797 ] + walkopts,
4788 _('[OPTION]... FILE...'))
4798 _('[OPTION]... FILE...'))
4789 def remove(ui, repo, *pats, **opts):
4799 def remove(ui, repo, *pats, **opts):
4790 """remove the specified files on the next commit
4800 """remove the specified files on the next commit
4791
4801
4792 Schedule the indicated files for removal from the current branch.
4802 Schedule the indicated files for removal from the current branch.
4793
4803
4794 This command schedules the files to be removed at the next commit.
4804 This command schedules the files to be removed at the next commit.
4795 To undo a remove before that, see :hg:`revert`. To undo added
4805 To undo a remove before that, see :hg:`revert`. To undo added
4796 files, see :hg:`forget`.
4806 files, see :hg:`forget`.
4797
4807
4798 .. container:: verbose
4808 .. container:: verbose
4799
4809
4800 -A/--after can be used to remove only files that have already
4810 -A/--after can be used to remove only files that have already
4801 been deleted, -f/--force can be used to force deletion, and -Af
4811 been deleted, -f/--force can be used to force deletion, and -Af
4802 can be used to remove files from the next revision without
4812 can be used to remove files from the next revision without
4803 deleting them from the working directory.
4813 deleting them from the working directory.
4804
4814
4805 The following table details the behavior of remove for different
4815 The following table details the behavior of remove for different
4806 file states (columns) and option combinations (rows). The file
4816 file states (columns) and option combinations (rows). The file
4807 states are Added [A], Clean [C], Modified [M] and Missing [!]
4817 states are Added [A], Clean [C], Modified [M] and Missing [!]
4808 (as reported by :hg:`status`). The actions are Warn, Remove
4818 (as reported by :hg:`status`). The actions are Warn, Remove
4809 (from branch) and Delete (from disk):
4819 (from branch) and Delete (from disk):
4810
4820
4811 ========= == == == ==
4821 ========= == == == ==
4812 opt/state A C M !
4822 opt/state A C M !
4813 ========= == == == ==
4823 ========= == == == ==
4814 none W RD W R
4824 none W RD W R
4815 -f R RD RD R
4825 -f R RD RD R
4816 -A W W W R
4826 -A W W W R
4817 -Af R R R R
4827 -Af R R R R
4818 ========= == == == ==
4828 ========= == == == ==
4819
4829
4820 Note that remove never deletes files in Added [A] state from the
4830 Note that remove never deletes files in Added [A] state from the
4821 working directory, not even if option --force is specified.
4831 working directory, not even if option --force is specified.
4822
4832
4823 Returns 0 on success, 1 if any warnings encountered.
4833 Returns 0 on success, 1 if any warnings encountered.
4824 """
4834 """
4825
4835
4826 ret = 0
4836 ret = 0
4827 after, force = opts.get('after'), opts.get('force')
4837 after, force = opts.get('after'), opts.get('force')
4828 if not pats and not after:
4838 if not pats and not after:
4829 raise util.Abort(_('no files specified'))
4839 raise util.Abort(_('no files specified'))
4830
4840
4831 m = scmutil.match(repo[None], pats, opts)
4841 m = scmutil.match(repo[None], pats, opts)
4832 s = repo.status(match=m, clean=True)
4842 s = repo.status(match=m, clean=True)
4833 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4843 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4834
4844
4835 # warn about failure to delete explicit files/dirs
4845 # warn about failure to delete explicit files/dirs
4836 wctx = repo[None]
4846 wctx = repo[None]
4837 for f in m.files():
4847 for f in m.files():
4838 if f in repo.dirstate or f in wctx.dirs():
4848 if f in repo.dirstate or f in wctx.dirs():
4839 continue
4849 continue
4840 if os.path.exists(m.rel(f)):
4850 if os.path.exists(m.rel(f)):
4841 if os.path.isdir(m.rel(f)):
4851 if os.path.isdir(m.rel(f)):
4842 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4852 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4843 else:
4853 else:
4844 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4854 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4845 # missing files will generate a warning elsewhere
4855 # missing files will generate a warning elsewhere
4846 ret = 1
4856 ret = 1
4847
4857
4848 if force:
4858 if force:
4849 list = modified + deleted + clean + added
4859 list = modified + deleted + clean + added
4850 elif after:
4860 elif after:
4851 list = deleted
4861 list = deleted
4852 for f in modified + added + clean:
4862 for f in modified + added + clean:
4853 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4863 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4854 ret = 1
4864 ret = 1
4855 else:
4865 else:
4856 list = deleted + clean
4866 list = deleted + clean
4857 for f in modified:
4867 for f in modified:
4858 ui.warn(_('not removing %s: file is modified (use -f'
4868 ui.warn(_('not removing %s: file is modified (use -f'
4859 ' to force removal)\n') % m.rel(f))
4869 ' to force removal)\n') % m.rel(f))
4860 ret = 1
4870 ret = 1
4861 for f in added:
4871 for f in added:
4862 ui.warn(_('not removing %s: file has been marked for add'
4872 ui.warn(_('not removing %s: file has been marked for add'
4863 ' (use forget to undo)\n') % m.rel(f))
4873 ' (use forget to undo)\n') % m.rel(f))
4864 ret = 1
4874 ret = 1
4865
4875
4866 for f in sorted(list):
4876 for f in sorted(list):
4867 if ui.verbose or not m.exact(f):
4877 if ui.verbose or not m.exact(f):
4868 ui.status(_('removing %s\n') % m.rel(f))
4878 ui.status(_('removing %s\n') % m.rel(f))
4869
4879
4870 wlock = repo.wlock()
4880 wlock = repo.wlock()
4871 try:
4881 try:
4872 if not after:
4882 if not after:
4873 for f in list:
4883 for f in list:
4874 if f in added:
4884 if f in added:
4875 continue # we never unlink added files on remove
4885 continue # we never unlink added files on remove
4876 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4886 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4877 repo[None].forget(list)
4887 repo[None].forget(list)
4878 finally:
4888 finally:
4879 wlock.release()
4889 wlock.release()
4880
4890
4881 return ret
4891 return ret
4882
4892
4883 @command('rename|move|mv',
4893 @command('rename|move|mv',
4884 [('A', 'after', None, _('record a rename that has already occurred')),
4894 [('A', 'after', None, _('record a rename that has already occurred')),
4885 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4895 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4886 ] + walkopts + dryrunopts,
4896 ] + walkopts + dryrunopts,
4887 _('[OPTION]... SOURCE... DEST'))
4897 _('[OPTION]... SOURCE... DEST'))
4888 def rename(ui, repo, *pats, **opts):
4898 def rename(ui, repo, *pats, **opts):
4889 """rename files; equivalent of copy + remove
4899 """rename files; equivalent of copy + remove
4890
4900
4891 Mark dest as copies of sources; mark sources for deletion. If dest
4901 Mark dest as copies of sources; mark sources for deletion. If dest
4892 is a directory, copies are put in that directory. If dest is a
4902 is a directory, copies are put in that directory. If dest is a
4893 file, there can only be one source.
4903 file, there can only be one source.
4894
4904
4895 By default, this command copies the contents of files as they
4905 By default, this command copies the contents of files as they
4896 exist in the working directory. If invoked with -A/--after, the
4906 exist in the working directory. If invoked with -A/--after, the
4897 operation is recorded, but no copying is performed.
4907 operation is recorded, but no copying is performed.
4898
4908
4899 This command takes effect at the next commit. To undo a rename
4909 This command takes effect at the next commit. To undo a rename
4900 before that, see :hg:`revert`.
4910 before that, see :hg:`revert`.
4901
4911
4902 Returns 0 on success, 1 if errors are encountered.
4912 Returns 0 on success, 1 if errors are encountered.
4903 """
4913 """
4904 wlock = repo.wlock(False)
4914 wlock = repo.wlock(False)
4905 try:
4915 try:
4906 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4916 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4907 finally:
4917 finally:
4908 wlock.release()
4918 wlock.release()
4909
4919
4910 @command('resolve',
4920 @command('resolve',
4911 [('a', 'all', None, _('select all unresolved files')),
4921 [('a', 'all', None, _('select all unresolved files')),
4912 ('l', 'list', None, _('list state of files needing merge')),
4922 ('l', 'list', None, _('list state of files needing merge')),
4913 ('m', 'mark', None, _('mark files as resolved')),
4923 ('m', 'mark', None, _('mark files as resolved')),
4914 ('u', 'unmark', None, _('mark files as unresolved')),
4924 ('u', 'unmark', None, _('mark files as unresolved')),
4915 ('n', 'no-status', None, _('hide status prefix'))]
4925 ('n', 'no-status', None, _('hide status prefix'))]
4916 + mergetoolopts + walkopts,
4926 + mergetoolopts + walkopts,
4917 _('[OPTION]... [FILE]...'))
4927 _('[OPTION]... [FILE]...'))
4918 def resolve(ui, repo, *pats, **opts):
4928 def resolve(ui, repo, *pats, **opts):
4919 """redo merges or set/view the merge status of files
4929 """redo merges or set/view the merge status of files
4920
4930
4921 Merges with unresolved conflicts are often the result of
4931 Merges with unresolved conflicts are often the result of
4922 non-interactive merging using the ``internal:merge`` configuration
4932 non-interactive merging using the ``internal:merge`` configuration
4923 setting, or a command-line merge tool like ``diff3``. The resolve
4933 setting, or a command-line merge tool like ``diff3``. The resolve
4924 command is used to manage the files involved in a merge, after
4934 command is used to manage the files involved in a merge, after
4925 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4935 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4926 working directory must have two parents). See :hg:`help
4936 working directory must have two parents). See :hg:`help
4927 merge-tools` for information on configuring merge tools.
4937 merge-tools` for information on configuring merge tools.
4928
4938
4929 The resolve command can be used in the following ways:
4939 The resolve command can be used in the following ways:
4930
4940
4931 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4941 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4932 files, discarding any previous merge attempts. Re-merging is not
4942 files, discarding any previous merge attempts. Re-merging is not
4933 performed for files already marked as resolved. Use ``--all/-a``
4943 performed for files already marked as resolved. Use ``--all/-a``
4934 to select all unresolved files. ``--tool`` can be used to specify
4944 to select all unresolved files. ``--tool`` can be used to specify
4935 the merge tool used for the given files. It overrides the HGMERGE
4945 the merge tool used for the given files. It overrides the HGMERGE
4936 environment variable and your configuration files. Previous file
4946 environment variable and your configuration files. Previous file
4937 contents are saved with a ``.orig`` suffix.
4947 contents are saved with a ``.orig`` suffix.
4938
4948
4939 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4949 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4940 (e.g. after having manually fixed-up the files). The default is
4950 (e.g. after having manually fixed-up the files). The default is
4941 to mark all unresolved files.
4951 to mark all unresolved files.
4942
4952
4943 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4953 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4944 default is to mark all resolved files.
4954 default is to mark all resolved files.
4945
4955
4946 - :hg:`resolve -l`: list files which had or still have conflicts.
4956 - :hg:`resolve -l`: list files which had or still have conflicts.
4947 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4957 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4948
4958
4949 Note that Mercurial will not let you commit files with unresolved
4959 Note that Mercurial will not let you commit files with unresolved
4950 merge conflicts. You must use :hg:`resolve -m ...` before you can
4960 merge conflicts. You must use :hg:`resolve -m ...` before you can
4951 commit after a conflicting merge.
4961 commit after a conflicting merge.
4952
4962
4953 Returns 0 on success, 1 if any files fail a resolve attempt.
4963 Returns 0 on success, 1 if any files fail a resolve attempt.
4954 """
4964 """
4955
4965
4956 all, mark, unmark, show, nostatus = \
4966 all, mark, unmark, show, nostatus = \
4957 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4967 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4958
4968
4959 if (show and (mark or unmark)) or (mark and unmark):
4969 if (show and (mark or unmark)) or (mark and unmark):
4960 raise util.Abort(_("too many options specified"))
4970 raise util.Abort(_("too many options specified"))
4961 if pats and all:
4971 if pats and all:
4962 raise util.Abort(_("can't specify --all and patterns"))
4972 raise util.Abort(_("can't specify --all and patterns"))
4963 if not (all or pats or show or mark or unmark):
4973 if not (all or pats or show or mark or unmark):
4964 raise util.Abort(_('no files or directories specified; '
4974 raise util.Abort(_('no files or directories specified; '
4965 'use --all to remerge all files'))
4975 'use --all to remerge all files'))
4966
4976
4967 wlock = repo.wlock()
4977 wlock = repo.wlock()
4968 try:
4978 try:
4969 ms = mergemod.mergestate(repo)
4979 ms = mergemod.mergestate(repo)
4970
4980
4971 if not ms.active() and not show:
4981 if not ms.active() and not show:
4972 raise util.Abort(
4982 raise util.Abort(
4973 _('resolve command not applicable when not merging'))
4983 _('resolve command not applicable when not merging'))
4974
4984
4975 m = scmutil.match(repo[None], pats, opts)
4985 m = scmutil.match(repo[None], pats, opts)
4976 ret = 0
4986 ret = 0
4977 didwork = False
4987 didwork = False
4978
4988
4979 for f in ms:
4989 for f in ms:
4980 if not m(f):
4990 if not m(f):
4981 continue
4991 continue
4982
4992
4983 didwork = True
4993 didwork = True
4984
4994
4985 if show:
4995 if show:
4986 if nostatus:
4996 if nostatus:
4987 ui.write("%s\n" % f)
4997 ui.write("%s\n" % f)
4988 else:
4998 else:
4989 ui.write("%s %s\n" % (ms[f].upper(), f),
4999 ui.write("%s %s\n" % (ms[f].upper(), f),
4990 label='resolve.' +
5000 label='resolve.' +
4991 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5001 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4992 elif mark:
5002 elif mark:
4993 ms.mark(f, "r")
5003 ms.mark(f, "r")
4994 elif unmark:
5004 elif unmark:
4995 ms.mark(f, "u")
5005 ms.mark(f, "u")
4996 else:
5006 else:
4997 wctx = repo[None]
5007 wctx = repo[None]
4998
5008
4999 # backup pre-resolve (merge uses .orig for its own purposes)
5009 # backup pre-resolve (merge uses .orig for its own purposes)
5000 a = repo.wjoin(f)
5010 a = repo.wjoin(f)
5001 util.copyfile(a, a + ".resolve")
5011 util.copyfile(a, a + ".resolve")
5002
5012
5003 try:
5013 try:
5004 # resolve file
5014 # resolve file
5005 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5015 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5006 'resolve')
5016 'resolve')
5007 if ms.resolve(f, wctx):
5017 if ms.resolve(f, wctx):
5008 ret = 1
5018 ret = 1
5009 finally:
5019 finally:
5010 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5020 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5011 ms.commit()
5021 ms.commit()
5012
5022
5013 # replace filemerge's .orig file with our resolve file
5023 # replace filemerge's .orig file with our resolve file
5014 util.rename(a + ".resolve", a + ".orig")
5024 util.rename(a + ".resolve", a + ".orig")
5015
5025
5016 ms.commit()
5026 ms.commit()
5017
5027
5018 if not didwork and pats:
5028 if not didwork and pats:
5019 ui.warn(_("arguments do not match paths that need resolving\n"))
5029 ui.warn(_("arguments do not match paths that need resolving\n"))
5020
5030
5021 finally:
5031 finally:
5022 wlock.release()
5032 wlock.release()
5023
5033
5024 # Nudge users into finishing an unfinished operation. We don't print
5034 # Nudge users into finishing an unfinished operation. We don't print
5025 # this with the list/show operation because we want list/show to remain
5035 # this with the list/show operation because we want list/show to remain
5026 # machine readable.
5036 # machine readable.
5027 if not list(ms.unresolved()) and not show:
5037 if not list(ms.unresolved()) and not show:
5028 ui.status(_('no more unresolved files\n'))
5038 ui.status(_('no more unresolved files\n'))
5029
5039
5030 return ret
5040 return ret
5031
5041
5032 @command('revert',
5042 @command('revert',
5033 [('a', 'all', None, _('revert all changes when no arguments given')),
5043 [('a', 'all', None, _('revert all changes when no arguments given')),
5034 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5044 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5035 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5045 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5036 ('C', 'no-backup', None, _('do not save backup copies of files')),
5046 ('C', 'no-backup', None, _('do not save backup copies of files')),
5037 ] + walkopts + dryrunopts,
5047 ] + walkopts + dryrunopts,
5038 _('[OPTION]... [-r REV] [NAME]...'))
5048 _('[OPTION]... [-r REV] [NAME]...'))
5039 def revert(ui, repo, *pats, **opts):
5049 def revert(ui, repo, *pats, **opts):
5040 """restore files to their checkout state
5050 """restore files to their checkout state
5041
5051
5042 .. note::
5052 .. note::
5043
5053
5044 To check out earlier revisions, you should use :hg:`update REV`.
5054 To check out earlier revisions, you should use :hg:`update REV`.
5045 To cancel an uncommitted merge (and lose your changes),
5055 To cancel an uncommitted merge (and lose your changes),
5046 use :hg:`update --clean .`.
5056 use :hg:`update --clean .`.
5047
5057
5048 With no revision specified, revert the specified files or directories
5058 With no revision specified, revert the specified files or directories
5049 to the contents they had in the parent of the working directory.
5059 to the contents they had in the parent of the working directory.
5050 This restores the contents of files to an unmodified
5060 This restores the contents of files to an unmodified
5051 state and unschedules adds, removes, copies, and renames. If the
5061 state and unschedules adds, removes, copies, and renames. If the
5052 working directory has two parents, you must explicitly specify a
5062 working directory has two parents, you must explicitly specify a
5053 revision.
5063 revision.
5054
5064
5055 Using the -r/--rev or -d/--date options, revert the given files or
5065 Using the -r/--rev or -d/--date options, revert the given files or
5056 directories to their states as of a specific revision. Because
5066 directories to their states as of a specific revision. Because
5057 revert does not change the working directory parents, this will
5067 revert does not change the working directory parents, this will
5058 cause these files to appear modified. This can be helpful to "back
5068 cause these files to appear modified. This can be helpful to "back
5059 out" some or all of an earlier change. See :hg:`backout` for a
5069 out" some or all of an earlier change. See :hg:`backout` for a
5060 related method.
5070 related method.
5061
5071
5062 Modified files are saved with a .orig suffix before reverting.
5072 Modified files are saved with a .orig suffix before reverting.
5063 To disable these backups, use --no-backup.
5073 To disable these backups, use --no-backup.
5064
5074
5065 See :hg:`help dates` for a list of formats valid for -d/--date.
5075 See :hg:`help dates` for a list of formats valid for -d/--date.
5066
5076
5067 Returns 0 on success.
5077 Returns 0 on success.
5068 """
5078 """
5069
5079
5070 if opts.get("date"):
5080 if opts.get("date"):
5071 if opts.get("rev"):
5081 if opts.get("rev"):
5072 raise util.Abort(_("you can't specify a revision and a date"))
5082 raise util.Abort(_("you can't specify a revision and a date"))
5073 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5083 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5074
5084
5075 parent, p2 = repo.dirstate.parents()
5085 parent, p2 = repo.dirstate.parents()
5076 if not opts.get('rev') and p2 != nullid:
5086 if not opts.get('rev') and p2 != nullid:
5077 # revert after merge is a trap for new users (issue2915)
5087 # revert after merge is a trap for new users (issue2915)
5078 raise util.Abort(_('uncommitted merge with no revision specified'),
5088 raise util.Abort(_('uncommitted merge with no revision specified'),
5079 hint=_('use "hg update" or see "hg help revert"'))
5089 hint=_('use "hg update" or see "hg help revert"'))
5080
5090
5081 ctx = scmutil.revsingle(repo, opts.get('rev'))
5091 ctx = scmutil.revsingle(repo, opts.get('rev'))
5082
5092
5083 if not pats and not opts.get('all'):
5093 if not pats and not opts.get('all'):
5084 msg = _("no files or directories specified")
5094 msg = _("no files or directories specified")
5085 if p2 != nullid:
5095 if p2 != nullid:
5086 hint = _("uncommitted merge, use --all to discard all changes,"
5096 hint = _("uncommitted merge, use --all to discard all changes,"
5087 " or 'hg update -C .' to abort the merge")
5097 " or 'hg update -C .' to abort the merge")
5088 raise util.Abort(msg, hint=hint)
5098 raise util.Abort(msg, hint=hint)
5089 dirty = util.any(repo.status())
5099 dirty = util.any(repo.status())
5090 node = ctx.node()
5100 node = ctx.node()
5091 if node != parent:
5101 if node != parent:
5092 if dirty:
5102 if dirty:
5093 hint = _("uncommitted changes, use --all to discard all"
5103 hint = _("uncommitted changes, use --all to discard all"
5094 " changes, or 'hg update %s' to update") % ctx.rev()
5104 " changes, or 'hg update %s' to update") % ctx.rev()
5095 else:
5105 else:
5096 hint = _("use --all to revert all files,"
5106 hint = _("use --all to revert all files,"
5097 " or 'hg update %s' to update") % ctx.rev()
5107 " or 'hg update %s' to update") % ctx.rev()
5098 elif dirty:
5108 elif dirty:
5099 hint = _("uncommitted changes, use --all to discard all changes")
5109 hint = _("uncommitted changes, use --all to discard all changes")
5100 else:
5110 else:
5101 hint = _("use --all to revert all files")
5111 hint = _("use --all to revert all files")
5102 raise util.Abort(msg, hint=hint)
5112 raise util.Abort(msg, hint=hint)
5103
5113
5104 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5114 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5105
5115
5106 @command('rollback', dryrunopts +
5116 @command('rollback', dryrunopts +
5107 [('f', 'force', False, _('ignore safety measures'))])
5117 [('f', 'force', False, _('ignore safety measures'))])
5108 def rollback(ui, repo, **opts):
5118 def rollback(ui, repo, **opts):
5109 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5119 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5110
5120
5111 Please use :hg:`commit --amend` instead of rollback to correct
5121 Please use :hg:`commit --amend` instead of rollback to correct
5112 mistakes in the last commit.
5122 mistakes in the last commit.
5113
5123
5114 This command should be used with care. There is only one level of
5124 This command should be used with care. There is only one level of
5115 rollback, and there is no way to undo a rollback. It will also
5125 rollback, and there is no way to undo a rollback. It will also
5116 restore the dirstate at the time of the last transaction, losing
5126 restore the dirstate at the time of the last transaction, losing
5117 any dirstate changes since that time. This command does not alter
5127 any dirstate changes since that time. This command does not alter
5118 the working directory.
5128 the working directory.
5119
5129
5120 Transactions are used to encapsulate the effects of all commands
5130 Transactions are used to encapsulate the effects of all commands
5121 that create new changesets or propagate existing changesets into a
5131 that create new changesets or propagate existing changesets into a
5122 repository.
5132 repository.
5123
5133
5124 .. container:: verbose
5134 .. container:: verbose
5125
5135
5126 For example, the following commands are transactional, and their
5136 For example, the following commands are transactional, and their
5127 effects can be rolled back:
5137 effects can be rolled back:
5128
5138
5129 - commit
5139 - commit
5130 - import
5140 - import
5131 - pull
5141 - pull
5132 - push (with this repository as the destination)
5142 - push (with this repository as the destination)
5133 - unbundle
5143 - unbundle
5134
5144
5135 To avoid permanent data loss, rollback will refuse to rollback a
5145 To avoid permanent data loss, rollback will refuse to rollback a
5136 commit transaction if it isn't checked out. Use --force to
5146 commit transaction if it isn't checked out. Use --force to
5137 override this protection.
5147 override this protection.
5138
5148
5139 This command is not intended for use on public repositories. Once
5149 This command is not intended for use on public repositories. Once
5140 changes are visible for pull by other users, rolling a transaction
5150 changes are visible for pull by other users, rolling a transaction
5141 back locally is ineffective (someone else may already have pulled
5151 back locally is ineffective (someone else may already have pulled
5142 the changes). Furthermore, a race is possible with readers of the
5152 the changes). Furthermore, a race is possible with readers of the
5143 repository; for example an in-progress pull from the repository
5153 repository; for example an in-progress pull from the repository
5144 may fail if a rollback is performed.
5154 may fail if a rollback is performed.
5145
5155
5146 Returns 0 on success, 1 if no rollback data is available.
5156 Returns 0 on success, 1 if no rollback data is available.
5147 """
5157 """
5148 return repo.rollback(dryrun=opts.get('dry_run'),
5158 return repo.rollback(dryrun=opts.get('dry_run'),
5149 force=opts.get('force'))
5159 force=opts.get('force'))
5150
5160
5151 @command('root', [])
5161 @command('root', [])
5152 def root(ui, repo):
5162 def root(ui, repo):
5153 """print the root (top) of the current working directory
5163 """print the root (top) of the current working directory
5154
5164
5155 Print the root directory of the current repository.
5165 Print the root directory of the current repository.
5156
5166
5157 Returns 0 on success.
5167 Returns 0 on success.
5158 """
5168 """
5159 ui.write(repo.root + "\n")
5169 ui.write(repo.root + "\n")
5160
5170
5161 @command('^serve',
5171 @command('^serve',
5162 [('A', 'accesslog', '', _('name of access log file to write to'),
5172 [('A', 'accesslog', '', _('name of access log file to write to'),
5163 _('FILE')),
5173 _('FILE')),
5164 ('d', 'daemon', None, _('run server in background')),
5174 ('d', 'daemon', None, _('run server in background')),
5165 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5175 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5166 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5176 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5167 # use string type, then we can check if something was passed
5177 # use string type, then we can check if something was passed
5168 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5178 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5169 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5179 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5170 _('ADDR')),
5180 _('ADDR')),
5171 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5181 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5172 _('PREFIX')),
5182 _('PREFIX')),
5173 ('n', 'name', '',
5183 ('n', 'name', '',
5174 _('name to show in web pages (default: working directory)'), _('NAME')),
5184 _('name to show in web pages (default: working directory)'), _('NAME')),
5175 ('', 'web-conf', '',
5185 ('', 'web-conf', '',
5176 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5186 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5177 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5187 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5178 _('FILE')),
5188 _('FILE')),
5179 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5189 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5180 ('', 'stdio', None, _('for remote clients')),
5190 ('', 'stdio', None, _('for remote clients')),
5181 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5191 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5182 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5192 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5183 ('', 'style', '', _('template style to use'), _('STYLE')),
5193 ('', 'style', '', _('template style to use'), _('STYLE')),
5184 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5194 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5185 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5195 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5186 _('[OPTION]...'))
5196 _('[OPTION]...'))
5187 def serve(ui, repo, **opts):
5197 def serve(ui, repo, **opts):
5188 """start stand-alone webserver
5198 """start stand-alone webserver
5189
5199
5190 Start a local HTTP repository browser and pull server. You can use
5200 Start a local HTTP repository browser and pull server. You can use
5191 this for ad-hoc sharing and browsing of repositories. It is
5201 this for ad-hoc sharing and browsing of repositories. It is
5192 recommended to use a real web server to serve a repository for
5202 recommended to use a real web server to serve a repository for
5193 longer periods of time.
5203 longer periods of time.
5194
5204
5195 Please note that the server does not implement access control.
5205 Please note that the server does not implement access control.
5196 This means that, by default, anybody can read from the server and
5206 This means that, by default, anybody can read from the server and
5197 nobody can write to it by default. Set the ``web.allow_push``
5207 nobody can write to it by default. Set the ``web.allow_push``
5198 option to ``*`` to allow everybody to push to the server. You
5208 option to ``*`` to allow everybody to push to the server. You
5199 should use a real web server if you need to authenticate users.
5209 should use a real web server if you need to authenticate users.
5200
5210
5201 By default, the server logs accesses to stdout and errors to
5211 By default, the server logs accesses to stdout and errors to
5202 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5212 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5203 files.
5213 files.
5204
5214
5205 To have the server choose a free port number to listen on, specify
5215 To have the server choose a free port number to listen on, specify
5206 a port number of 0; in this case, the server will print the port
5216 a port number of 0; in this case, the server will print the port
5207 number it uses.
5217 number it uses.
5208
5218
5209 Returns 0 on success.
5219 Returns 0 on success.
5210 """
5220 """
5211
5221
5212 if opts["stdio"] and opts["cmdserver"]:
5222 if opts["stdio"] and opts["cmdserver"]:
5213 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5223 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5214
5224
5215 def checkrepo():
5225 def checkrepo():
5216 if repo is None:
5226 if repo is None:
5217 raise error.RepoError(_("there is no Mercurial repository here"
5227 raise error.RepoError(_("there is no Mercurial repository here"
5218 " (.hg not found)"))
5228 " (.hg not found)"))
5219
5229
5220 if opts["stdio"]:
5230 if opts["stdio"]:
5221 checkrepo()
5231 checkrepo()
5222 s = sshserver.sshserver(ui, repo)
5232 s = sshserver.sshserver(ui, repo)
5223 s.serve_forever()
5233 s.serve_forever()
5224
5234
5225 if opts["cmdserver"]:
5235 if opts["cmdserver"]:
5226 s = commandserver.server(ui, repo, opts["cmdserver"])
5236 s = commandserver.server(ui, repo, opts["cmdserver"])
5227 return s.serve()
5237 return s.serve()
5228
5238
5229 # this way we can check if something was given in the command-line
5239 # this way we can check if something was given in the command-line
5230 if opts.get('port'):
5240 if opts.get('port'):
5231 opts['port'] = util.getport(opts.get('port'))
5241 opts['port'] = util.getport(opts.get('port'))
5232
5242
5233 baseui = repo and repo.baseui or ui
5243 baseui = repo and repo.baseui or ui
5234 optlist = ("name templates style address port prefix ipv6"
5244 optlist = ("name templates style address port prefix ipv6"
5235 " accesslog errorlog certificate encoding")
5245 " accesslog errorlog certificate encoding")
5236 for o in optlist.split():
5246 for o in optlist.split():
5237 val = opts.get(o, '')
5247 val = opts.get(o, '')
5238 if val in (None, ''): # should check against default options instead
5248 if val in (None, ''): # should check against default options instead
5239 continue
5249 continue
5240 baseui.setconfig("web", o, val, 'serve')
5250 baseui.setconfig("web", o, val, 'serve')
5241 if repo and repo.ui != baseui:
5251 if repo and repo.ui != baseui:
5242 repo.ui.setconfig("web", o, val, 'serve')
5252 repo.ui.setconfig("web", o, val, 'serve')
5243
5253
5244 o = opts.get('web_conf') or opts.get('webdir_conf')
5254 o = opts.get('web_conf') or opts.get('webdir_conf')
5245 if not o:
5255 if not o:
5246 if not repo:
5256 if not repo:
5247 raise error.RepoError(_("there is no Mercurial repository"
5257 raise error.RepoError(_("there is no Mercurial repository"
5248 " here (.hg not found)"))
5258 " here (.hg not found)"))
5249 o = repo
5259 o = repo
5250
5260
5251 app = hgweb.hgweb(o, baseui=baseui)
5261 app = hgweb.hgweb(o, baseui=baseui)
5252 service = httpservice(ui, app, opts)
5262 service = httpservice(ui, app, opts)
5253 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5263 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5254
5264
5255 class httpservice(object):
5265 class httpservice(object):
5256 def __init__(self, ui, app, opts):
5266 def __init__(self, ui, app, opts):
5257 self.ui = ui
5267 self.ui = ui
5258 self.app = app
5268 self.app = app
5259 self.opts = opts
5269 self.opts = opts
5260
5270
5261 def init(self):
5271 def init(self):
5262 util.setsignalhandler()
5272 util.setsignalhandler()
5263 self.httpd = hgweb_server.create_server(self.ui, self.app)
5273 self.httpd = hgweb_server.create_server(self.ui, self.app)
5264
5274
5265 if self.opts['port'] and not self.ui.verbose:
5275 if self.opts['port'] and not self.ui.verbose:
5266 return
5276 return
5267
5277
5268 if self.httpd.prefix:
5278 if self.httpd.prefix:
5269 prefix = self.httpd.prefix.strip('/') + '/'
5279 prefix = self.httpd.prefix.strip('/') + '/'
5270 else:
5280 else:
5271 prefix = ''
5281 prefix = ''
5272
5282
5273 port = ':%d' % self.httpd.port
5283 port = ':%d' % self.httpd.port
5274 if port == ':80':
5284 if port == ':80':
5275 port = ''
5285 port = ''
5276
5286
5277 bindaddr = self.httpd.addr
5287 bindaddr = self.httpd.addr
5278 if bindaddr == '0.0.0.0':
5288 if bindaddr == '0.0.0.0':
5279 bindaddr = '*'
5289 bindaddr = '*'
5280 elif ':' in bindaddr: # IPv6
5290 elif ':' in bindaddr: # IPv6
5281 bindaddr = '[%s]' % bindaddr
5291 bindaddr = '[%s]' % bindaddr
5282
5292
5283 fqaddr = self.httpd.fqaddr
5293 fqaddr = self.httpd.fqaddr
5284 if ':' in fqaddr:
5294 if ':' in fqaddr:
5285 fqaddr = '[%s]' % fqaddr
5295 fqaddr = '[%s]' % fqaddr
5286 if self.opts['port']:
5296 if self.opts['port']:
5287 write = self.ui.status
5297 write = self.ui.status
5288 else:
5298 else:
5289 write = self.ui.write
5299 write = self.ui.write
5290 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5300 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5291 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5301 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5292
5302
5293 def run(self):
5303 def run(self):
5294 self.httpd.serve_forever()
5304 self.httpd.serve_forever()
5295
5305
5296
5306
5297 @command('^status|st',
5307 @command('^status|st',
5298 [('A', 'all', None, _('show status of all files')),
5308 [('A', 'all', None, _('show status of all files')),
5299 ('m', 'modified', None, _('show only modified files')),
5309 ('m', 'modified', None, _('show only modified files')),
5300 ('a', 'added', None, _('show only added files')),
5310 ('a', 'added', None, _('show only added files')),
5301 ('r', 'removed', None, _('show only removed files')),
5311 ('r', 'removed', None, _('show only removed files')),
5302 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5312 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5303 ('c', 'clean', None, _('show only files without changes')),
5313 ('c', 'clean', None, _('show only files without changes')),
5304 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5314 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5305 ('i', 'ignored', None, _('show only ignored files')),
5315 ('i', 'ignored', None, _('show only ignored files')),
5306 ('n', 'no-status', None, _('hide status prefix')),
5316 ('n', 'no-status', None, _('hide status prefix')),
5307 ('C', 'copies', None, _('show source of copied files')),
5317 ('C', 'copies', None, _('show source of copied files')),
5308 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5318 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5309 ('', 'rev', [], _('show difference from revision'), _('REV')),
5319 ('', 'rev', [], _('show difference from revision'), _('REV')),
5310 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5320 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5311 ] + walkopts + subrepoopts,
5321 ] + walkopts + subrepoopts,
5312 _('[OPTION]... [FILE]...'))
5322 _('[OPTION]... [FILE]...'))
5313 def status(ui, repo, *pats, **opts):
5323 def status(ui, repo, *pats, **opts):
5314 """show changed files in the working directory
5324 """show changed files in the working directory
5315
5325
5316 Show status of files in the repository. If names are given, only
5326 Show status of files in the repository. If names are given, only
5317 files that match are shown. Files that are clean or ignored or
5327 files that match are shown. Files that are clean or ignored or
5318 the source of a copy/move operation, are not listed unless
5328 the source of a copy/move operation, are not listed unless
5319 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5329 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5320 Unless options described with "show only ..." are given, the
5330 Unless options described with "show only ..." are given, the
5321 options -mardu are used.
5331 options -mardu are used.
5322
5332
5323 Option -q/--quiet hides untracked (unknown and ignored) files
5333 Option -q/--quiet hides untracked (unknown and ignored) files
5324 unless explicitly requested with -u/--unknown or -i/--ignored.
5334 unless explicitly requested with -u/--unknown or -i/--ignored.
5325
5335
5326 .. note::
5336 .. note::
5327
5337
5328 status may appear to disagree with diff if permissions have
5338 status may appear to disagree with diff if permissions have
5329 changed or a merge has occurred. The standard diff format does
5339 changed or a merge has occurred. The standard diff format does
5330 not report permission changes and diff only reports changes
5340 not report permission changes and diff only reports changes
5331 relative to one merge parent.
5341 relative to one merge parent.
5332
5342
5333 If one revision is given, it is used as the base revision.
5343 If one revision is given, it is used as the base revision.
5334 If two revisions are given, the differences between them are
5344 If two revisions are given, the differences between them are
5335 shown. The --change option can also be used as a shortcut to list
5345 shown. The --change option can also be used as a shortcut to list
5336 the changed files of a revision from its first parent.
5346 the changed files of a revision from its first parent.
5337
5347
5338 The codes used to show the status of files are::
5348 The codes used to show the status of files are::
5339
5349
5340 M = modified
5350 M = modified
5341 A = added
5351 A = added
5342 R = removed
5352 R = removed
5343 C = clean
5353 C = clean
5344 ! = missing (deleted by non-hg command, but still tracked)
5354 ! = missing (deleted by non-hg command, but still tracked)
5345 ? = not tracked
5355 ? = not tracked
5346 I = ignored
5356 I = ignored
5347 = origin of the previous file (with --copies)
5357 = origin of the previous file (with --copies)
5348
5358
5349 .. container:: verbose
5359 .. container:: verbose
5350
5360
5351 Examples:
5361 Examples:
5352
5362
5353 - show changes in the working directory relative to a
5363 - show changes in the working directory relative to a
5354 changeset::
5364 changeset::
5355
5365
5356 hg status --rev 9353
5366 hg status --rev 9353
5357
5367
5358 - show all changes including copies in an existing changeset::
5368 - show all changes including copies in an existing changeset::
5359
5369
5360 hg status --copies --change 9353
5370 hg status --copies --change 9353
5361
5371
5362 - get a NUL separated list of added files, suitable for xargs::
5372 - get a NUL separated list of added files, suitable for xargs::
5363
5373
5364 hg status -an0
5374 hg status -an0
5365
5375
5366 Returns 0 on success.
5376 Returns 0 on success.
5367 """
5377 """
5368
5378
5369 revs = opts.get('rev')
5379 revs = opts.get('rev')
5370 change = opts.get('change')
5380 change = opts.get('change')
5371
5381
5372 if revs and change:
5382 if revs and change:
5373 msg = _('cannot specify --rev and --change at the same time')
5383 msg = _('cannot specify --rev and --change at the same time')
5374 raise util.Abort(msg)
5384 raise util.Abort(msg)
5375 elif change:
5385 elif change:
5376 node2 = scmutil.revsingle(repo, change, None).node()
5386 node2 = scmutil.revsingle(repo, change, None).node()
5377 node1 = repo[node2].p1().node()
5387 node1 = repo[node2].p1().node()
5378 else:
5388 else:
5379 node1, node2 = scmutil.revpair(repo, revs)
5389 node1, node2 = scmutil.revpair(repo, revs)
5380
5390
5381 cwd = (pats and repo.getcwd()) or ''
5391 cwd = (pats and repo.getcwd()) or ''
5382 end = opts.get('print0') and '\0' or '\n'
5392 end = opts.get('print0') and '\0' or '\n'
5383 copy = {}
5393 copy = {}
5384 states = 'modified added removed deleted unknown ignored clean'.split()
5394 states = 'modified added removed deleted unknown ignored clean'.split()
5385 show = [k for k in states if opts.get(k)]
5395 show = [k for k in states if opts.get(k)]
5386 if opts.get('all'):
5396 if opts.get('all'):
5387 show += ui.quiet and (states[:4] + ['clean']) or states
5397 show += ui.quiet and (states[:4] + ['clean']) or states
5388 if not show:
5398 if not show:
5389 show = ui.quiet and states[:4] or states[:5]
5399 show = ui.quiet and states[:4] or states[:5]
5390
5400
5391 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5401 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5392 'ignored' in show, 'clean' in show, 'unknown' in show,
5402 'ignored' in show, 'clean' in show, 'unknown' in show,
5393 opts.get('subrepos'))
5403 opts.get('subrepos'))
5394 changestates = zip(states, 'MAR!?IC', stat)
5404 changestates = zip(states, 'MAR!?IC', stat)
5395
5405
5396 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5406 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5397 copy = copies.pathcopies(repo[node1], repo[node2])
5407 copy = copies.pathcopies(repo[node1], repo[node2])
5398
5408
5399 fm = ui.formatter('status', opts)
5409 fm = ui.formatter('status', opts)
5400 fmt = '%s' + end
5410 fmt = '%s' + end
5401 showchar = not opts.get('no_status')
5411 showchar = not opts.get('no_status')
5402
5412
5403 for state, char, files in changestates:
5413 for state, char, files in changestates:
5404 if state in show:
5414 if state in show:
5405 label = 'status.' + state
5415 label = 'status.' + state
5406 for f in files:
5416 for f in files:
5407 fm.startitem()
5417 fm.startitem()
5408 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5418 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5409 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5419 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5410 if f in copy:
5420 if f in copy:
5411 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5421 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5412 label='status.copied')
5422 label='status.copied')
5413 fm.end()
5423 fm.end()
5414
5424
5415 @command('^summary|sum',
5425 @command('^summary|sum',
5416 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5426 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5417 def summary(ui, repo, **opts):
5427 def summary(ui, repo, **opts):
5418 """summarize working directory state
5428 """summarize working directory state
5419
5429
5420 This generates a brief summary of the working directory state,
5430 This generates a brief summary of the working directory state,
5421 including parents, branch, commit status, and available updates.
5431 including parents, branch, commit status, and available updates.
5422
5432
5423 With the --remote option, this will check the default paths for
5433 With the --remote option, this will check the default paths for
5424 incoming and outgoing changes. This can be time-consuming.
5434 incoming and outgoing changes. This can be time-consuming.
5425
5435
5426 Returns 0 on success.
5436 Returns 0 on success.
5427 """
5437 """
5428
5438
5429 ctx = repo[None]
5439 ctx = repo[None]
5430 parents = ctx.parents()
5440 parents = ctx.parents()
5431 pnode = parents[0].node()
5441 pnode = parents[0].node()
5432 marks = []
5442 marks = []
5433
5443
5434 for p in parents:
5444 for p in parents:
5435 # label with log.changeset (instead of log.parent) since this
5445 # label with log.changeset (instead of log.parent) since this
5436 # shows a working directory parent *changeset*:
5446 # shows a working directory parent *changeset*:
5437 # i18n: column positioning for "hg summary"
5447 # i18n: column positioning for "hg summary"
5438 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5448 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5439 label='log.changeset changeset.%s' % p.phasestr())
5449 label='log.changeset changeset.%s' % p.phasestr())
5440 ui.write(' '.join(p.tags()), label='log.tag')
5450 ui.write(' '.join(p.tags()), label='log.tag')
5441 if p.bookmarks():
5451 if p.bookmarks():
5442 marks.extend(p.bookmarks())
5452 marks.extend(p.bookmarks())
5443 if p.rev() == -1:
5453 if p.rev() == -1:
5444 if not len(repo):
5454 if not len(repo):
5445 ui.write(_(' (empty repository)'))
5455 ui.write(_(' (empty repository)'))
5446 else:
5456 else:
5447 ui.write(_(' (no revision checked out)'))
5457 ui.write(_(' (no revision checked out)'))
5448 ui.write('\n')
5458 ui.write('\n')
5449 if p.description():
5459 if p.description():
5450 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5460 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5451 label='log.summary')
5461 label='log.summary')
5452
5462
5453 branch = ctx.branch()
5463 branch = ctx.branch()
5454 bheads = repo.branchheads(branch)
5464 bheads = repo.branchheads(branch)
5455 # i18n: column positioning for "hg summary"
5465 # i18n: column positioning for "hg summary"
5456 m = _('branch: %s\n') % branch
5466 m = _('branch: %s\n') % branch
5457 if branch != 'default':
5467 if branch != 'default':
5458 ui.write(m, label='log.branch')
5468 ui.write(m, label='log.branch')
5459 else:
5469 else:
5460 ui.status(m, label='log.branch')
5470 ui.status(m, label='log.branch')
5461
5471
5462 if marks:
5472 if marks:
5463 current = repo._bookmarkcurrent
5473 current = repo._bookmarkcurrent
5464 # i18n: column positioning for "hg summary"
5474 # i18n: column positioning for "hg summary"
5465 ui.write(_('bookmarks:'), label='log.bookmark')
5475 ui.write(_('bookmarks:'), label='log.bookmark')
5466 if current is not None:
5476 if current is not None:
5467 if current in marks:
5477 if current in marks:
5468 ui.write(' *' + current, label='bookmarks.current')
5478 ui.write(' *' + current, label='bookmarks.current')
5469 marks.remove(current)
5479 marks.remove(current)
5470 else:
5480 else:
5471 ui.write(' [%s]' % current, label='bookmarks.current')
5481 ui.write(' [%s]' % current, label='bookmarks.current')
5472 for m in marks:
5482 for m in marks:
5473 ui.write(' ' + m, label='log.bookmark')
5483 ui.write(' ' + m, label='log.bookmark')
5474 ui.write('\n', label='log.bookmark')
5484 ui.write('\n', label='log.bookmark')
5475
5485
5476 st = list(repo.status(unknown=True))[:6]
5486 st = list(repo.status(unknown=True))[:6]
5477
5487
5478 c = repo.dirstate.copies()
5488 c = repo.dirstate.copies()
5479 copied, renamed = [], []
5489 copied, renamed = [], []
5480 for d, s in c.iteritems():
5490 for d, s in c.iteritems():
5481 if s in st[2]:
5491 if s in st[2]:
5482 st[2].remove(s)
5492 st[2].remove(s)
5483 renamed.append(d)
5493 renamed.append(d)
5484 else:
5494 else:
5485 copied.append(d)
5495 copied.append(d)
5486 if d in st[1]:
5496 if d in st[1]:
5487 st[1].remove(d)
5497 st[1].remove(d)
5488 st.insert(3, renamed)
5498 st.insert(3, renamed)
5489 st.insert(4, copied)
5499 st.insert(4, copied)
5490
5500
5491 ms = mergemod.mergestate(repo)
5501 ms = mergemod.mergestate(repo)
5492 st.append([f for f in ms if ms[f] == 'u'])
5502 st.append([f for f in ms if ms[f] == 'u'])
5493
5503
5494 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5504 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5495 st.append(subs)
5505 st.append(subs)
5496
5506
5497 labels = [ui.label(_('%d modified'), 'status.modified'),
5507 labels = [ui.label(_('%d modified'), 'status.modified'),
5498 ui.label(_('%d added'), 'status.added'),
5508 ui.label(_('%d added'), 'status.added'),
5499 ui.label(_('%d removed'), 'status.removed'),
5509 ui.label(_('%d removed'), 'status.removed'),
5500 ui.label(_('%d renamed'), 'status.copied'),
5510 ui.label(_('%d renamed'), 'status.copied'),
5501 ui.label(_('%d copied'), 'status.copied'),
5511 ui.label(_('%d copied'), 'status.copied'),
5502 ui.label(_('%d deleted'), 'status.deleted'),
5512 ui.label(_('%d deleted'), 'status.deleted'),
5503 ui.label(_('%d unknown'), 'status.unknown'),
5513 ui.label(_('%d unknown'), 'status.unknown'),
5504 ui.label(_('%d ignored'), 'status.ignored'),
5514 ui.label(_('%d ignored'), 'status.ignored'),
5505 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5515 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5506 ui.label(_('%d subrepos'), 'status.modified')]
5516 ui.label(_('%d subrepos'), 'status.modified')]
5507 t = []
5517 t = []
5508 for s, l in zip(st, labels):
5518 for s, l in zip(st, labels):
5509 if s:
5519 if s:
5510 t.append(l % len(s))
5520 t.append(l % len(s))
5511
5521
5512 t = ', '.join(t)
5522 t = ', '.join(t)
5513 cleanworkdir = False
5523 cleanworkdir = False
5514
5524
5515 if repo.vfs.exists('updatestate'):
5525 if repo.vfs.exists('updatestate'):
5516 t += _(' (interrupted update)')
5526 t += _(' (interrupted update)')
5517 elif len(parents) > 1:
5527 elif len(parents) > 1:
5518 t += _(' (merge)')
5528 t += _(' (merge)')
5519 elif branch != parents[0].branch():
5529 elif branch != parents[0].branch():
5520 t += _(' (new branch)')
5530 t += _(' (new branch)')
5521 elif (parents[0].closesbranch() and
5531 elif (parents[0].closesbranch() and
5522 pnode in repo.branchheads(branch, closed=True)):
5532 pnode in repo.branchheads(branch, closed=True)):
5523 t += _(' (head closed)')
5533 t += _(' (head closed)')
5524 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5534 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5525 t += _(' (clean)')
5535 t += _(' (clean)')
5526 cleanworkdir = True
5536 cleanworkdir = True
5527 elif pnode not in bheads:
5537 elif pnode not in bheads:
5528 t += _(' (new branch head)')
5538 t += _(' (new branch head)')
5529
5539
5530 if cleanworkdir:
5540 if cleanworkdir:
5531 # i18n: column positioning for "hg summary"
5541 # i18n: column positioning for "hg summary"
5532 ui.status(_('commit: %s\n') % t.strip())
5542 ui.status(_('commit: %s\n') % t.strip())
5533 else:
5543 else:
5534 # i18n: column positioning for "hg summary"
5544 # i18n: column positioning for "hg summary"
5535 ui.write(_('commit: %s\n') % t.strip())
5545 ui.write(_('commit: %s\n') % t.strip())
5536
5546
5537 # all ancestors of branch heads - all ancestors of parent = new csets
5547 # all ancestors of branch heads - all ancestors of parent = new csets
5538 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5548 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5539 bheads))
5549 bheads))
5540
5550
5541 if new == 0:
5551 if new == 0:
5542 # i18n: column positioning for "hg summary"
5552 # i18n: column positioning for "hg summary"
5543 ui.status(_('update: (current)\n'))
5553 ui.status(_('update: (current)\n'))
5544 elif pnode not in bheads:
5554 elif pnode not in bheads:
5545 # i18n: column positioning for "hg summary"
5555 # i18n: column positioning for "hg summary"
5546 ui.write(_('update: %d new changesets (update)\n') % new)
5556 ui.write(_('update: %d new changesets (update)\n') % new)
5547 else:
5557 else:
5548 # i18n: column positioning for "hg summary"
5558 # i18n: column positioning for "hg summary"
5549 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5559 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5550 (new, len(bheads)))
5560 (new, len(bheads)))
5551
5561
5552 cmdutil.summaryhooks(ui, repo)
5562 cmdutil.summaryhooks(ui, repo)
5553
5563
5554 if opts.get('remote'):
5564 if opts.get('remote'):
5555 needsincoming, needsoutgoing = True, True
5565 needsincoming, needsoutgoing = True, True
5556 else:
5566 else:
5557 needsincoming, needsoutgoing = False, False
5567 needsincoming, needsoutgoing = False, False
5558 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5568 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5559 if i:
5569 if i:
5560 needsincoming = True
5570 needsincoming = True
5561 if o:
5571 if o:
5562 needsoutgoing = True
5572 needsoutgoing = True
5563 if not needsincoming and not needsoutgoing:
5573 if not needsincoming and not needsoutgoing:
5564 return
5574 return
5565
5575
5566 def getincoming():
5576 def getincoming():
5567 source, branches = hg.parseurl(ui.expandpath('default'))
5577 source, branches = hg.parseurl(ui.expandpath('default'))
5568 sbranch = branches[0]
5578 sbranch = branches[0]
5569 try:
5579 try:
5570 other = hg.peer(repo, {}, source)
5580 other = hg.peer(repo, {}, source)
5571 except error.RepoError:
5581 except error.RepoError:
5572 if opts.get('remote'):
5582 if opts.get('remote'):
5573 raise
5583 raise
5574 return source, sbranch, None, None, None
5584 return source, sbranch, None, None, None
5575 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5585 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5576 if revs:
5586 if revs:
5577 revs = [other.lookup(rev) for rev in revs]
5587 revs = [other.lookup(rev) for rev in revs]
5578 ui.debug('comparing with %s\n' % util.hidepassword(source))
5588 ui.debug('comparing with %s\n' % util.hidepassword(source))
5579 repo.ui.pushbuffer()
5589 repo.ui.pushbuffer()
5580 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5590 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5581 repo.ui.popbuffer()
5591 repo.ui.popbuffer()
5582 return source, sbranch, other, commoninc, commoninc[1]
5592 return source, sbranch, other, commoninc, commoninc[1]
5583
5593
5584 if needsincoming:
5594 if needsincoming:
5585 source, sbranch, sother, commoninc, incoming = getincoming()
5595 source, sbranch, sother, commoninc, incoming = getincoming()
5586 else:
5596 else:
5587 source = sbranch = sother = commoninc = incoming = None
5597 source = sbranch = sother = commoninc = incoming = None
5588
5598
5589 def getoutgoing():
5599 def getoutgoing():
5590 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5600 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5591 dbranch = branches[0]
5601 dbranch = branches[0]
5592 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5602 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5593 if source != dest:
5603 if source != dest:
5594 try:
5604 try:
5595 dother = hg.peer(repo, {}, dest)
5605 dother = hg.peer(repo, {}, dest)
5596 except error.RepoError:
5606 except error.RepoError:
5597 if opts.get('remote'):
5607 if opts.get('remote'):
5598 raise
5608 raise
5599 return dest, dbranch, None, None
5609 return dest, dbranch, None, None
5600 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5610 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5601 elif sother is None:
5611 elif sother is None:
5602 # there is no explicit destination peer, but source one is invalid
5612 # there is no explicit destination peer, but source one is invalid
5603 return dest, dbranch, None, None
5613 return dest, dbranch, None, None
5604 else:
5614 else:
5605 dother = sother
5615 dother = sother
5606 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5616 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5607 common = None
5617 common = None
5608 else:
5618 else:
5609 common = commoninc
5619 common = commoninc
5610 if revs:
5620 if revs:
5611 revs = [repo.lookup(rev) for rev in revs]
5621 revs = [repo.lookup(rev) for rev in revs]
5612 repo.ui.pushbuffer()
5622 repo.ui.pushbuffer()
5613 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5623 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5614 commoninc=common)
5624 commoninc=common)
5615 repo.ui.popbuffer()
5625 repo.ui.popbuffer()
5616 return dest, dbranch, dother, outgoing
5626 return dest, dbranch, dother, outgoing
5617
5627
5618 if needsoutgoing:
5628 if needsoutgoing:
5619 dest, dbranch, dother, outgoing = getoutgoing()
5629 dest, dbranch, dother, outgoing = getoutgoing()
5620 else:
5630 else:
5621 dest = dbranch = dother = outgoing = None
5631 dest = dbranch = dother = outgoing = None
5622
5632
5623 if opts.get('remote'):
5633 if opts.get('remote'):
5624 t = []
5634 t = []
5625 if incoming:
5635 if incoming:
5626 t.append(_('1 or more incoming'))
5636 t.append(_('1 or more incoming'))
5627 o = outgoing.missing
5637 o = outgoing.missing
5628 if o:
5638 if o:
5629 t.append(_('%d outgoing') % len(o))
5639 t.append(_('%d outgoing') % len(o))
5630 other = dother or sother
5640 other = dother or sother
5631 if 'bookmarks' in other.listkeys('namespaces'):
5641 if 'bookmarks' in other.listkeys('namespaces'):
5632 lmarks = repo.listkeys('bookmarks')
5642 lmarks = repo.listkeys('bookmarks')
5633 rmarks = other.listkeys('bookmarks')
5643 rmarks = other.listkeys('bookmarks')
5634 diff = set(rmarks) - set(lmarks)
5644 diff = set(rmarks) - set(lmarks)
5635 if len(diff) > 0:
5645 if len(diff) > 0:
5636 t.append(_('%d incoming bookmarks') % len(diff))
5646 t.append(_('%d incoming bookmarks') % len(diff))
5637 diff = set(lmarks) - set(rmarks)
5647 diff = set(lmarks) - set(rmarks)
5638 if len(diff) > 0:
5648 if len(diff) > 0:
5639 t.append(_('%d outgoing bookmarks') % len(diff))
5649 t.append(_('%d outgoing bookmarks') % len(diff))
5640
5650
5641 if t:
5651 if t:
5642 # i18n: column positioning for "hg summary"
5652 # i18n: column positioning for "hg summary"
5643 ui.write(_('remote: %s\n') % (', '.join(t)))
5653 ui.write(_('remote: %s\n') % (', '.join(t)))
5644 else:
5654 else:
5645 # i18n: column positioning for "hg summary"
5655 # i18n: column positioning for "hg summary"
5646 ui.status(_('remote: (synced)\n'))
5656 ui.status(_('remote: (synced)\n'))
5647
5657
5648 cmdutil.summaryremotehooks(ui, repo, opts,
5658 cmdutil.summaryremotehooks(ui, repo, opts,
5649 ((source, sbranch, sother, commoninc),
5659 ((source, sbranch, sother, commoninc),
5650 (dest, dbranch, dother, outgoing)))
5660 (dest, dbranch, dother, outgoing)))
5651
5661
5652 @command('tag',
5662 @command('tag',
5653 [('f', 'force', None, _('force tag')),
5663 [('f', 'force', None, _('force tag')),
5654 ('l', 'local', None, _('make the tag local')),
5664 ('l', 'local', None, _('make the tag local')),
5655 ('r', 'rev', '', _('revision to tag'), _('REV')),
5665 ('r', 'rev', '', _('revision to tag'), _('REV')),
5656 ('', 'remove', None, _('remove a tag')),
5666 ('', 'remove', None, _('remove a tag')),
5657 # -l/--local is already there, commitopts cannot be used
5667 # -l/--local is already there, commitopts cannot be used
5658 ('e', 'edit', None, _('edit commit message')),
5668 ('e', 'edit', None, _('edit commit message')),
5659 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5669 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5660 ] + commitopts2,
5670 ] + commitopts2,
5661 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5671 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5662 def tag(ui, repo, name1, *names, **opts):
5672 def tag(ui, repo, name1, *names, **opts):
5663 """add one or more tags for the current or given revision
5673 """add one or more tags for the current or given revision
5664
5674
5665 Name a particular revision using <name>.
5675 Name a particular revision using <name>.
5666
5676
5667 Tags are used to name particular revisions of the repository and are
5677 Tags are used to name particular revisions of the repository and are
5668 very useful to compare different revisions, to go back to significant
5678 very useful to compare different revisions, to go back to significant
5669 earlier versions or to mark branch points as releases, etc. Changing
5679 earlier versions or to mark branch points as releases, etc. Changing
5670 an existing tag is normally disallowed; use -f/--force to override.
5680 an existing tag is normally disallowed; use -f/--force to override.
5671
5681
5672 If no revision is given, the parent of the working directory is
5682 If no revision is given, the parent of the working directory is
5673 used.
5683 used.
5674
5684
5675 To facilitate version control, distribution, and merging of tags,
5685 To facilitate version control, distribution, and merging of tags,
5676 they are stored as a file named ".hgtags" which is managed similarly
5686 they are stored as a file named ".hgtags" which is managed similarly
5677 to other project files and can be hand-edited if necessary. This
5687 to other project files and can be hand-edited if necessary. This
5678 also means that tagging creates a new commit. The file
5688 also means that tagging creates a new commit. The file
5679 ".hg/localtags" is used for local tags (not shared among
5689 ".hg/localtags" is used for local tags (not shared among
5680 repositories).
5690 repositories).
5681
5691
5682 Tag commits are usually made at the head of a branch. If the parent
5692 Tag commits are usually made at the head of a branch. If the parent
5683 of the working directory is not a branch head, :hg:`tag` aborts; use
5693 of the working directory is not a branch head, :hg:`tag` aborts; use
5684 -f/--force to force the tag commit to be based on a non-head
5694 -f/--force to force the tag commit to be based on a non-head
5685 changeset.
5695 changeset.
5686
5696
5687 See :hg:`help dates` for a list of formats valid for -d/--date.
5697 See :hg:`help dates` for a list of formats valid for -d/--date.
5688
5698
5689 Since tag names have priority over branch names during revision
5699 Since tag names have priority over branch names during revision
5690 lookup, using an existing branch name as a tag name is discouraged.
5700 lookup, using an existing branch name as a tag name is discouraged.
5691
5701
5692 Returns 0 on success.
5702 Returns 0 on success.
5693 """
5703 """
5694 wlock = lock = None
5704 wlock = lock = None
5695 try:
5705 try:
5696 wlock = repo.wlock()
5706 wlock = repo.wlock()
5697 lock = repo.lock()
5707 lock = repo.lock()
5698 rev_ = "."
5708 rev_ = "."
5699 names = [t.strip() for t in (name1,) + names]
5709 names = [t.strip() for t in (name1,) + names]
5700 if len(names) != len(set(names)):
5710 if len(names) != len(set(names)):
5701 raise util.Abort(_('tag names must be unique'))
5711 raise util.Abort(_('tag names must be unique'))
5702 for n in names:
5712 for n in names:
5703 scmutil.checknewlabel(repo, n, 'tag')
5713 scmutil.checknewlabel(repo, n, 'tag')
5704 if not n:
5714 if not n:
5705 raise util.Abort(_('tag names cannot consist entirely of '
5715 raise util.Abort(_('tag names cannot consist entirely of '
5706 'whitespace'))
5716 'whitespace'))
5707 if opts.get('rev') and opts.get('remove'):
5717 if opts.get('rev') and opts.get('remove'):
5708 raise util.Abort(_("--rev and --remove are incompatible"))
5718 raise util.Abort(_("--rev and --remove are incompatible"))
5709 if opts.get('rev'):
5719 if opts.get('rev'):
5710 rev_ = opts['rev']
5720 rev_ = opts['rev']
5711 message = opts.get('message')
5721 message = opts.get('message')
5712 if opts.get('remove'):
5722 if opts.get('remove'):
5713 expectedtype = opts.get('local') and 'local' or 'global'
5723 expectedtype = opts.get('local') and 'local' or 'global'
5714 for n in names:
5724 for n in names:
5715 if not repo.tagtype(n):
5725 if not repo.tagtype(n):
5716 raise util.Abort(_("tag '%s' does not exist") % n)
5726 raise util.Abort(_("tag '%s' does not exist") % n)
5717 if repo.tagtype(n) != expectedtype:
5727 if repo.tagtype(n) != expectedtype:
5718 if expectedtype == 'global':
5728 if expectedtype == 'global':
5719 raise util.Abort(_("tag '%s' is not a global tag") % n)
5729 raise util.Abort(_("tag '%s' is not a global tag") % n)
5720 else:
5730 else:
5721 raise util.Abort(_("tag '%s' is not a local tag") % n)
5731 raise util.Abort(_("tag '%s' is not a local tag") % n)
5722 rev_ = nullid
5732 rev_ = nullid
5723 if not message:
5733 if not message:
5724 # we don't translate commit messages
5734 # we don't translate commit messages
5725 message = 'Removed tag %s' % ', '.join(names)
5735 message = 'Removed tag %s' % ', '.join(names)
5726 elif not opts.get('force'):
5736 elif not opts.get('force'):
5727 for n in names:
5737 for n in names:
5728 if n in repo.tags():
5738 if n in repo.tags():
5729 raise util.Abort(_("tag '%s' already exists "
5739 raise util.Abort(_("tag '%s' already exists "
5730 "(use -f to force)") % n)
5740 "(use -f to force)") % n)
5731 if not opts.get('local'):
5741 if not opts.get('local'):
5732 p1, p2 = repo.dirstate.parents()
5742 p1, p2 = repo.dirstate.parents()
5733 if p2 != nullid:
5743 if p2 != nullid:
5734 raise util.Abort(_('uncommitted merge'))
5744 raise util.Abort(_('uncommitted merge'))
5735 bheads = repo.branchheads()
5745 bheads = repo.branchheads()
5736 if not opts.get('force') and bheads and p1 not in bheads:
5746 if not opts.get('force') and bheads and p1 not in bheads:
5737 raise util.Abort(_('not at a branch head (use -f to force)'))
5747 raise util.Abort(_('not at a branch head (use -f to force)'))
5738 r = scmutil.revsingle(repo, rev_).node()
5748 r = scmutil.revsingle(repo, rev_).node()
5739
5749
5740 if not message:
5750 if not message:
5741 # we don't translate commit messages
5751 # we don't translate commit messages
5742 message = ('Added tag %s for changeset %s' %
5752 message = ('Added tag %s for changeset %s' %
5743 (', '.join(names), short(r)))
5753 (', '.join(names), short(r)))
5744
5754
5745 date = opts.get('date')
5755 date = opts.get('date')
5746 if date:
5756 if date:
5747 date = util.parsedate(date)
5757 date = util.parsedate(date)
5748
5758
5749 editor = cmdutil.getcommiteditor(**opts)
5759 editor = cmdutil.getcommiteditor(**opts)
5750
5760
5751 # don't allow tagging the null rev
5761 # don't allow tagging the null rev
5752 if (not opts.get('remove') and
5762 if (not opts.get('remove') and
5753 scmutil.revsingle(repo, rev_).rev() == nullrev):
5763 scmutil.revsingle(repo, rev_).rev() == nullrev):
5754 raise util.Abort(_("cannot tag null revision"))
5764 raise util.Abort(_("cannot tag null revision"))
5755
5765
5756 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5766 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5757 editor=editor)
5767 editor=editor)
5758 finally:
5768 finally:
5759 release(lock, wlock)
5769 release(lock, wlock)
5760
5770
5761 @command('tags', [], '')
5771 @command('tags', [], '')
5762 def tags(ui, repo, **opts):
5772 def tags(ui, repo, **opts):
5763 """list repository tags
5773 """list repository tags
5764
5774
5765 This lists both regular and local tags. When the -v/--verbose
5775 This lists both regular and local tags. When the -v/--verbose
5766 switch is used, a third column "local" is printed for local tags.
5776 switch is used, a third column "local" is printed for local tags.
5767
5777
5768 Returns 0 on success.
5778 Returns 0 on success.
5769 """
5779 """
5770
5780
5771 fm = ui.formatter('tags', opts)
5781 fm = ui.formatter('tags', opts)
5772 hexfunc = ui.debugflag and hex or short
5782 hexfunc = ui.debugflag and hex or short
5773 tagtype = ""
5783 tagtype = ""
5774
5784
5775 for t, n in reversed(repo.tagslist()):
5785 for t, n in reversed(repo.tagslist()):
5776 hn = hexfunc(n)
5786 hn = hexfunc(n)
5777 label = 'tags.normal'
5787 label = 'tags.normal'
5778 tagtype = ''
5788 tagtype = ''
5779 if repo.tagtype(t) == 'local':
5789 if repo.tagtype(t) == 'local':
5780 label = 'tags.local'
5790 label = 'tags.local'
5781 tagtype = 'local'
5791 tagtype = 'local'
5782
5792
5783 fm.startitem()
5793 fm.startitem()
5784 fm.write('tag', '%s', t, label=label)
5794 fm.write('tag', '%s', t, label=label)
5785 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5795 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5786 fm.condwrite(not ui.quiet, 'rev id', fmt,
5796 fm.condwrite(not ui.quiet, 'rev id', fmt,
5787 repo.changelog.rev(n), hn, label=label)
5797 repo.changelog.rev(n), hn, label=label)
5788 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5798 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5789 tagtype, label=label)
5799 tagtype, label=label)
5790 fm.plain('\n')
5800 fm.plain('\n')
5791 fm.end()
5801 fm.end()
5792
5802
5793 @command('tip',
5803 @command('tip',
5794 [('p', 'patch', None, _('show patch')),
5804 [('p', 'patch', None, _('show patch')),
5795 ('g', 'git', None, _('use git extended diff format')),
5805 ('g', 'git', None, _('use git extended diff format')),
5796 ] + templateopts,
5806 ] + templateopts,
5797 _('[-p] [-g]'))
5807 _('[-p] [-g]'))
5798 def tip(ui, repo, **opts):
5808 def tip(ui, repo, **opts):
5799 """show the tip revision (DEPRECATED)
5809 """show the tip revision (DEPRECATED)
5800
5810
5801 The tip revision (usually just called the tip) is the changeset
5811 The tip revision (usually just called the tip) is the changeset
5802 most recently added to the repository (and therefore the most
5812 most recently added to the repository (and therefore the most
5803 recently changed head).
5813 recently changed head).
5804
5814
5805 If you have just made a commit, that commit will be the tip. If
5815 If you have just made a commit, that commit will be the tip. If
5806 you have just pulled changes from another repository, the tip of
5816 you have just pulled changes from another repository, the tip of
5807 that repository becomes the current tip. The "tip" tag is special
5817 that repository becomes the current tip. The "tip" tag is special
5808 and cannot be renamed or assigned to a different changeset.
5818 and cannot be renamed or assigned to a different changeset.
5809
5819
5810 This command is deprecated, please use :hg:`heads` instead.
5820 This command is deprecated, please use :hg:`heads` instead.
5811
5821
5812 Returns 0 on success.
5822 Returns 0 on success.
5813 """
5823 """
5814 displayer = cmdutil.show_changeset(ui, repo, opts)
5824 displayer = cmdutil.show_changeset(ui, repo, opts)
5815 displayer.show(repo['tip'])
5825 displayer.show(repo['tip'])
5816 displayer.close()
5826 displayer.close()
5817
5827
5818 @command('unbundle',
5828 @command('unbundle',
5819 [('u', 'update', None,
5829 [('u', 'update', None,
5820 _('update to new branch head if changesets were unbundled'))],
5830 _('update to new branch head if changesets were unbundled'))],
5821 _('[-u] FILE...'))
5831 _('[-u] FILE...'))
5822 def unbundle(ui, repo, fname1, *fnames, **opts):
5832 def unbundle(ui, repo, fname1, *fnames, **opts):
5823 """apply one or more changegroup files
5833 """apply one or more changegroup files
5824
5834
5825 Apply one or more compressed changegroup files generated by the
5835 Apply one or more compressed changegroup files generated by the
5826 bundle command.
5836 bundle command.
5827
5837
5828 Returns 0 on success, 1 if an update has unresolved files.
5838 Returns 0 on success, 1 if an update has unresolved files.
5829 """
5839 """
5830 fnames = (fname1,) + fnames
5840 fnames = (fname1,) + fnames
5831
5841
5832 lock = repo.lock()
5842 lock = repo.lock()
5833 wc = repo['.']
5843 wc = repo['.']
5834 try:
5844 try:
5835 for fname in fnames:
5845 for fname in fnames:
5836 f = hg.openpath(ui, fname)
5846 f = hg.openpath(ui, fname)
5837 gen = exchange.readbundle(ui, f, fname)
5847 gen = exchange.readbundle(ui, f, fname)
5838 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5848 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5839 'bundle:' + fname)
5849 'bundle:' + fname)
5840 finally:
5850 finally:
5841 lock.release()
5851 lock.release()
5842 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5852 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5843 return postincoming(ui, repo, modheads, opts.get('update'), None)
5853 return postincoming(ui, repo, modheads, opts.get('update'), None)
5844
5854
5845 @command('^update|up|checkout|co',
5855 @command('^update|up|checkout|co',
5846 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5856 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5847 ('c', 'check', None,
5857 ('c', 'check', None,
5848 _('update across branches if no uncommitted changes')),
5858 _('update across branches if no uncommitted changes')),
5849 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5859 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5850 ('r', 'rev', '', _('revision'), _('REV'))
5860 ('r', 'rev', '', _('revision'), _('REV'))
5851 ] + mergetoolopts,
5861 ] + mergetoolopts,
5852 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5862 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5853 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5863 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5854 tool=None):
5864 tool=None):
5855 """update working directory (or switch revisions)
5865 """update working directory (or switch revisions)
5856
5866
5857 Update the repository's working directory to the specified
5867 Update the repository's working directory to the specified
5858 changeset. If no changeset is specified, update to the tip of the
5868 changeset. If no changeset is specified, update to the tip of the
5859 current named branch and move the current bookmark (see :hg:`help
5869 current named branch and move the current bookmark (see :hg:`help
5860 bookmarks`).
5870 bookmarks`).
5861
5871
5862 Update sets the working directory's parent revision to the specified
5872 Update sets the working directory's parent revision to the specified
5863 changeset (see :hg:`help parents`).
5873 changeset (see :hg:`help parents`).
5864
5874
5865 If the changeset is not a descendant or ancestor of the working
5875 If the changeset is not a descendant or ancestor of the working
5866 directory's parent, the update is aborted. With the -c/--check
5876 directory's parent, the update is aborted. With the -c/--check
5867 option, the working directory is checked for uncommitted changes; if
5877 option, the working directory is checked for uncommitted changes; if
5868 none are found, the working directory is updated to the specified
5878 none are found, the working directory is updated to the specified
5869 changeset.
5879 changeset.
5870
5880
5871 .. container:: verbose
5881 .. container:: verbose
5872
5882
5873 The following rules apply when the working directory contains
5883 The following rules apply when the working directory contains
5874 uncommitted changes:
5884 uncommitted changes:
5875
5885
5876 1. If neither -c/--check nor -C/--clean is specified, and if
5886 1. If neither -c/--check nor -C/--clean is specified, and if
5877 the requested changeset is an ancestor or descendant of
5887 the requested changeset is an ancestor or descendant of
5878 the working directory's parent, the uncommitted changes
5888 the working directory's parent, the uncommitted changes
5879 are merged into the requested changeset and the merged
5889 are merged into the requested changeset and the merged
5880 result is left uncommitted. If the requested changeset is
5890 result is left uncommitted. If the requested changeset is
5881 not an ancestor or descendant (that is, it is on another
5891 not an ancestor or descendant (that is, it is on another
5882 branch), the update is aborted and the uncommitted changes
5892 branch), the update is aborted and the uncommitted changes
5883 are preserved.
5893 are preserved.
5884
5894
5885 2. With the -c/--check option, the update is aborted and the
5895 2. With the -c/--check option, the update is aborted and the
5886 uncommitted changes are preserved.
5896 uncommitted changes are preserved.
5887
5897
5888 3. With the -C/--clean option, uncommitted changes are discarded and
5898 3. With the -C/--clean option, uncommitted changes are discarded and
5889 the working directory is updated to the requested changeset.
5899 the working directory is updated to the requested changeset.
5890
5900
5891 To cancel an uncommitted merge (and lose your changes), use
5901 To cancel an uncommitted merge (and lose your changes), use
5892 :hg:`update --clean .`.
5902 :hg:`update --clean .`.
5893
5903
5894 Use null as the changeset to remove the working directory (like
5904 Use null as the changeset to remove the working directory (like
5895 :hg:`clone -U`).
5905 :hg:`clone -U`).
5896
5906
5897 If you want to revert just one file to an older revision, use
5907 If you want to revert just one file to an older revision, use
5898 :hg:`revert [-r REV] NAME`.
5908 :hg:`revert [-r REV] NAME`.
5899
5909
5900 See :hg:`help dates` for a list of formats valid for -d/--date.
5910 See :hg:`help dates` for a list of formats valid for -d/--date.
5901
5911
5902 Returns 0 on success, 1 if there are unresolved files.
5912 Returns 0 on success, 1 if there are unresolved files.
5903 """
5913 """
5904 if rev and node:
5914 if rev and node:
5905 raise util.Abort(_("please specify just one revision"))
5915 raise util.Abort(_("please specify just one revision"))
5906
5916
5907 if rev is None or rev == '':
5917 if rev is None or rev == '':
5908 rev = node
5918 rev = node
5909
5919
5910 cmdutil.clearunfinished(repo)
5920 cmdutil.clearunfinished(repo)
5911
5921
5912 # with no argument, we also move the current bookmark, if any
5922 # with no argument, we also move the current bookmark, if any
5913 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5923 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5914
5924
5915 # if we defined a bookmark, we have to remember the original bookmark name
5925 # if we defined a bookmark, we have to remember the original bookmark name
5916 brev = rev
5926 brev = rev
5917 rev = scmutil.revsingle(repo, rev, rev).rev()
5927 rev = scmutil.revsingle(repo, rev, rev).rev()
5918
5928
5919 if check and clean:
5929 if check and clean:
5920 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5930 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5921
5931
5922 if date:
5932 if date:
5923 if rev is not None:
5933 if rev is not None:
5924 raise util.Abort(_("you can't specify a revision and a date"))
5934 raise util.Abort(_("you can't specify a revision and a date"))
5925 rev = cmdutil.finddate(ui, repo, date)
5935 rev = cmdutil.finddate(ui, repo, date)
5926
5936
5927 if check:
5937 if check:
5928 c = repo[None]
5938 c = repo[None]
5929 if c.dirty(merge=False, branch=False, missing=True):
5939 if c.dirty(merge=False, branch=False, missing=True):
5930 raise util.Abort(_("uncommitted changes"))
5940 raise util.Abort(_("uncommitted changes"))
5931 if rev is None:
5941 if rev is None:
5932 rev = repo[repo[None].branch()].rev()
5942 rev = repo[repo[None].branch()].rev()
5933 mergemod._checkunknown(repo, repo[None], repo[rev])
5943 mergemod._checkunknown(repo, repo[None], repo[rev])
5934
5944
5935 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5945 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5936
5946
5937 if clean:
5947 if clean:
5938 ret = hg.clean(repo, rev)
5948 ret = hg.clean(repo, rev)
5939 else:
5949 else:
5940 ret = hg.update(repo, rev)
5950 ret = hg.update(repo, rev)
5941
5951
5942 if not ret and movemarkfrom:
5952 if not ret and movemarkfrom:
5943 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5953 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5944 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5954 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5945 elif brev in repo._bookmarks:
5955 elif brev in repo._bookmarks:
5946 bookmarks.setcurrent(repo, brev)
5956 bookmarks.setcurrent(repo, brev)
5947 ui.status(_("(activating bookmark %s)\n") % brev)
5957 ui.status(_("(activating bookmark %s)\n") % brev)
5948 elif brev:
5958 elif brev:
5949 if repo._bookmarkcurrent:
5959 if repo._bookmarkcurrent:
5950 ui.status(_("(leaving bookmark %s)\n") %
5960 ui.status(_("(leaving bookmark %s)\n") %
5951 repo._bookmarkcurrent)
5961 repo._bookmarkcurrent)
5952 bookmarks.unsetcurrent(repo)
5962 bookmarks.unsetcurrent(repo)
5953
5963
5954 return ret
5964 return ret
5955
5965
5956 @command('verify', [])
5966 @command('verify', [])
5957 def verify(ui, repo):
5967 def verify(ui, repo):
5958 """verify the integrity of the repository
5968 """verify the integrity of the repository
5959
5969
5960 Verify the integrity of the current repository.
5970 Verify the integrity of the current repository.
5961
5971
5962 This will perform an extensive check of the repository's
5972 This will perform an extensive check of the repository's
5963 integrity, validating the hashes and checksums of each entry in
5973 integrity, validating the hashes and checksums of each entry in
5964 the changelog, manifest, and tracked files, as well as the
5974 the changelog, manifest, and tracked files, as well as the
5965 integrity of their crosslinks and indices.
5975 integrity of their crosslinks and indices.
5966
5976
5967 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5977 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5968 for more information about recovery from corruption of the
5978 for more information about recovery from corruption of the
5969 repository.
5979 repository.
5970
5980
5971 Returns 0 on success, 1 if errors are encountered.
5981 Returns 0 on success, 1 if errors are encountered.
5972 """
5982 """
5973 return hg.verify(repo)
5983 return hg.verify(repo)
5974
5984
5975 @command('version', [])
5985 @command('version', [], norepo=True)
5976 def version_(ui):
5986 def version_(ui):
5977 """output version and copyright information"""
5987 """output version and copyright information"""
5978 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5988 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5979 % util.version())
5989 % util.version())
5980 ui.status(_(
5990 ui.status(_(
5981 "(see http://mercurial.selenic.com for more information)\n"
5991 "(see http://mercurial.selenic.com for more information)\n"
5982 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5992 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5983 "This is free software; see the source for copying conditions. "
5993 "This is free software; see the source for copying conditions. "
5984 "There is NO\nwarranty; "
5994 "There is NO\nwarranty; "
5985 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5995 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5986 ))
5996 ))
General Comments 0
You need to be logged in to leave comments. Login now