##// END OF EJS Templates
serve: tidy up indent level of repository not found message
Yuya Nishihara -
r21819:816754e7 default
parent child Browse files
Show More
@@ -1,6018 +1,6018 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 # Space delimited list of commands that don't require local repositories.
29 # Space delimited list of commands that don't require local repositories.
30 # This should be populated by passing norepo=True into the @command decorator.
30 # This should be populated by passing norepo=True into the @command decorator.
31 norepo = ''
31 norepo = ''
32 # Space delimited list of commands that optionally require local repositories.
32 # Space delimited list of commands that optionally require local repositories.
33 # This should be populated by passing optionalrepo=True into the @command
33 # This should be populated by passing optionalrepo=True into the @command
34 # decorator.
34 # decorator.
35 optionalrepo = ''
35 optionalrepo = ''
36 # Space delimited list of commands that will examine arguments looking for
36 # Space delimited list of commands that will examine arguments looking for
37 # a repository. This should be populated by passing inferrepo=True into the
37 # a repository. This should be populated by passing inferrepo=True into the
38 # @command decorator.
38 # @command decorator.
39 inferrepo = ''
39 inferrepo = ''
40
40
41 # common command options
41 # common command options
42
42
43 globalopts = [
43 globalopts = [
44 ('R', 'repository', '',
44 ('R', 'repository', '',
45 _('repository root directory or name of overlay bundle file'),
45 _('repository root directory or name of overlay bundle file'),
46 _('REPO')),
46 _('REPO')),
47 ('', 'cwd', '',
47 ('', 'cwd', '',
48 _('change working directory'), _('DIR')),
48 _('change working directory'), _('DIR')),
49 ('y', 'noninteractive', None,
49 ('y', 'noninteractive', None,
50 _('do not prompt, automatically pick the first choice for all prompts')),
50 _('do not prompt, automatically pick the first choice for all prompts')),
51 ('q', 'quiet', None, _('suppress output')),
51 ('q', 'quiet', None, _('suppress output')),
52 ('v', 'verbose', None, _('enable additional output')),
52 ('v', 'verbose', None, _('enable additional output')),
53 ('', 'config', [],
53 ('', 'config', [],
54 _('set/override config option (use \'section.name=value\')'),
54 _('set/override config option (use \'section.name=value\')'),
55 _('CONFIG')),
55 _('CONFIG')),
56 ('', 'debug', None, _('enable debugging output')),
56 ('', 'debug', None, _('enable debugging output')),
57 ('', 'debugger', None, _('start debugger')),
57 ('', 'debugger', None, _('start debugger')),
58 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
58 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
59 _('ENCODE')),
59 _('ENCODE')),
60 ('', 'encodingmode', encoding.encodingmode,
60 ('', 'encodingmode', encoding.encodingmode,
61 _('set the charset encoding mode'), _('MODE')),
61 _('set the charset encoding mode'), _('MODE')),
62 ('', 'traceback', None, _('always print a traceback on exception')),
62 ('', 'traceback', None, _('always print a traceback on exception')),
63 ('', 'time', None, _('time how long the command takes')),
63 ('', 'time', None, _('time how long the command takes')),
64 ('', 'profile', None, _('print command execution profile')),
64 ('', 'profile', None, _('print command execution profile')),
65 ('', 'version', None, _('output version information and exit')),
65 ('', 'version', None, _('output version information and exit')),
66 ('h', 'help', None, _('display help and exit')),
66 ('h', 'help', None, _('display help and exit')),
67 ('', 'hidden', False, _('consider hidden changesets')),
67 ('', 'hidden', False, _('consider hidden changesets')),
68 ]
68 ]
69
69
70 dryrunopts = [('n', 'dry-run', None,
70 dryrunopts = [('n', 'dry-run', None,
71 _('do not perform actions, just print output'))]
71 _('do not perform actions, just print output'))]
72
72
73 remoteopts = [
73 remoteopts = [
74 ('e', 'ssh', '',
74 ('e', 'ssh', '',
75 _('specify ssh command to use'), _('CMD')),
75 _('specify ssh command to use'), _('CMD')),
76 ('', 'remotecmd', '',
76 ('', 'remotecmd', '',
77 _('specify hg command to run on the remote side'), _('CMD')),
77 _('specify hg command to run on the remote side'), _('CMD')),
78 ('', 'insecure', None,
78 ('', 'insecure', None,
79 _('do not verify server certificate (ignoring web.cacerts config)')),
79 _('do not verify server certificate (ignoring web.cacerts config)')),
80 ]
80 ]
81
81
82 walkopts = [
82 walkopts = [
83 ('I', 'include', [],
83 ('I', 'include', [],
84 _('include names matching the given patterns'), _('PATTERN')),
84 _('include names matching the given patterns'), _('PATTERN')),
85 ('X', 'exclude', [],
85 ('X', 'exclude', [],
86 _('exclude names matching the given patterns'), _('PATTERN')),
86 _('exclude names matching the given patterns'), _('PATTERN')),
87 ]
87 ]
88
88
89 commitopts = [
89 commitopts = [
90 ('m', 'message', '',
90 ('m', 'message', '',
91 _('use text as commit message'), _('TEXT')),
91 _('use text as commit message'), _('TEXT')),
92 ('l', 'logfile', '',
92 ('l', 'logfile', '',
93 _('read commit message from file'), _('FILE')),
93 _('read commit message from file'), _('FILE')),
94 ]
94 ]
95
95
96 commitopts2 = [
96 commitopts2 = [
97 ('d', 'date', '',
97 ('d', 'date', '',
98 _('record the specified date as commit date'), _('DATE')),
98 _('record the specified date as commit date'), _('DATE')),
99 ('u', 'user', '',
99 ('u', 'user', '',
100 _('record the specified user as committer'), _('USER')),
100 _('record the specified user as committer'), _('USER')),
101 ]
101 ]
102
102
103 templateopts = [
103 templateopts = [
104 ('', 'style', '',
104 ('', 'style', '',
105 _('display using template map file (DEPRECATED)'), _('STYLE')),
105 _('display using template map file (DEPRECATED)'), _('STYLE')),
106 ('T', 'template', '',
106 ('T', 'template', '',
107 _('display with template'), _('TEMPLATE')),
107 _('display with template'), _('TEMPLATE')),
108 ]
108 ]
109
109
110 logopts = [
110 logopts = [
111 ('p', 'patch', None, _('show patch')),
111 ('p', 'patch', None, _('show patch')),
112 ('g', 'git', None, _('use git extended diff format')),
112 ('g', 'git', None, _('use git extended diff format')),
113 ('l', 'limit', '',
113 ('l', 'limit', '',
114 _('limit number of changes displayed'), _('NUM')),
114 _('limit number of changes displayed'), _('NUM')),
115 ('M', 'no-merges', None, _('do not show merges')),
115 ('M', 'no-merges', None, _('do not show merges')),
116 ('', 'stat', None, _('output diffstat-style summary of changes')),
116 ('', 'stat', None, _('output diffstat-style summary of changes')),
117 ('G', 'graph', None, _("show the revision DAG")),
117 ('G', 'graph', None, _("show the revision DAG")),
118 ] + templateopts
118 ] + templateopts
119
119
120 diffopts = [
120 diffopts = [
121 ('a', 'text', None, _('treat all files as text')),
121 ('a', 'text', None, _('treat all files as text')),
122 ('g', 'git', None, _('use git extended diff format')),
122 ('g', 'git', None, _('use git extended diff format')),
123 ('', 'nodates', None, _('omit dates from diff headers'))
123 ('', 'nodates', None, _('omit dates from diff headers'))
124 ]
124 ]
125
125
126 diffwsopts = [
126 diffwsopts = [
127 ('w', 'ignore-all-space', None,
127 ('w', 'ignore-all-space', None,
128 _('ignore white space when comparing lines')),
128 _('ignore white space when comparing lines')),
129 ('b', 'ignore-space-change', None,
129 ('b', 'ignore-space-change', None,
130 _('ignore changes in the amount of white space')),
130 _('ignore changes in the amount of white space')),
131 ('B', 'ignore-blank-lines', None,
131 ('B', 'ignore-blank-lines', None,
132 _('ignore changes whose lines are all blank')),
132 _('ignore changes whose lines are all blank')),
133 ]
133 ]
134
134
135 diffopts2 = [
135 diffopts2 = [
136 ('p', 'show-function', None, _('show which function each change is in')),
136 ('p', 'show-function', None, _('show which function each change is in')),
137 ('', 'reverse', None, _('produce a diff that undoes the changes')),
137 ('', 'reverse', None, _('produce a diff that undoes the changes')),
138 ] + diffwsopts + [
138 ] + diffwsopts + [
139 ('U', 'unified', '',
139 ('U', 'unified', '',
140 _('number of lines of context to show'), _('NUM')),
140 _('number of lines of context to show'), _('NUM')),
141 ('', 'stat', None, _('output diffstat-style summary of changes')),
141 ('', 'stat', None, _('output diffstat-style summary of changes')),
142 ]
142 ]
143
143
144 mergetoolopts = [
144 mergetoolopts = [
145 ('t', 'tool', '', _('specify merge tool')),
145 ('t', 'tool', '', _('specify merge tool')),
146 ]
146 ]
147
147
148 similarityopts = [
148 similarityopts = [
149 ('s', 'similarity', '',
149 ('s', 'similarity', '',
150 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
150 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
151 ]
151 ]
152
152
153 subrepoopts = [
153 subrepoopts = [
154 ('S', 'subrepos', None,
154 ('S', 'subrepos', None,
155 _('recurse into subrepositories'))
155 _('recurse into subrepositories'))
156 ]
156 ]
157
157
158 # Commands start here, listed alphabetically
158 # Commands start here, listed alphabetically
159
159
160 @command('^add',
160 @command('^add',
161 walkopts + subrepoopts + dryrunopts,
161 walkopts + subrepoopts + dryrunopts,
162 _('[OPTION]... [FILE]...'),
162 _('[OPTION]... [FILE]...'),
163 inferrepo=True)
163 inferrepo=True)
164 def add(ui, repo, *pats, **opts):
164 def add(ui, repo, *pats, **opts):
165 """add the specified files on the next commit
165 """add the specified files on the next commit
166
166
167 Schedule files to be version controlled and added to the
167 Schedule files to be version controlled and added to the
168 repository.
168 repository.
169
169
170 The files will be added to the repository at the next commit. To
170 The files will be added to the repository at the next commit. To
171 undo an add before that, see :hg:`forget`.
171 undo an add before that, see :hg:`forget`.
172
172
173 If no names are given, add all files to the repository.
173 If no names are given, add all files to the repository.
174
174
175 .. container:: verbose
175 .. container:: verbose
176
176
177 An example showing how new (unknown) files are added
177 An example showing how new (unknown) files are added
178 automatically by :hg:`add`::
178 automatically by :hg:`add`::
179
179
180 $ ls
180 $ ls
181 foo.c
181 foo.c
182 $ hg status
182 $ hg status
183 ? foo.c
183 ? foo.c
184 $ hg add
184 $ hg add
185 adding foo.c
185 adding foo.c
186 $ hg status
186 $ hg status
187 A foo.c
187 A foo.c
188
188
189 Returns 0 if all files are successfully added.
189 Returns 0 if all files are successfully added.
190 """
190 """
191
191
192 m = scmutil.match(repo[None], pats, opts)
192 m = scmutil.match(repo[None], pats, opts)
193 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
193 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
194 opts.get('subrepos'), prefix="", explicitonly=False)
194 opts.get('subrepos'), prefix="", explicitonly=False)
195 return rejected and 1 or 0
195 return rejected and 1 or 0
196
196
197 @command('addremove',
197 @command('addremove',
198 similarityopts + walkopts + dryrunopts,
198 similarityopts + walkopts + dryrunopts,
199 _('[OPTION]... [FILE]...'),
199 _('[OPTION]... [FILE]...'),
200 inferrepo=True)
200 inferrepo=True)
201 def addremove(ui, repo, *pats, **opts):
201 def addremove(ui, repo, *pats, **opts):
202 """add all new files, delete all missing files
202 """add all new files, delete all missing files
203
203
204 Add all new files and remove all missing files from the
204 Add all new files and remove all missing files from the
205 repository.
205 repository.
206
206
207 New files are ignored if they match any of the patterns in
207 New files are ignored if they match any of the patterns in
208 ``.hgignore``. As with add, these changes take effect at the next
208 ``.hgignore``. As with add, these changes take effect at the next
209 commit.
209 commit.
210
210
211 Use the -s/--similarity option to detect renamed files. This
211 Use the -s/--similarity option to detect renamed files. This
212 option takes a percentage between 0 (disabled) and 100 (files must
212 option takes a percentage between 0 (disabled) and 100 (files must
213 be identical) as its parameter. With a parameter greater than 0,
213 be identical) as its parameter. With a parameter greater than 0,
214 this compares every removed file with every added file and records
214 this compares every removed file with every added file and records
215 those similar enough as renames. Detecting renamed files this way
215 those similar enough as renames. Detecting renamed files this way
216 can be expensive. After using this option, :hg:`status -C` can be
216 can be expensive. After using this option, :hg:`status -C` can be
217 used to check which files were identified as moved or renamed. If
217 used to check which files were identified as moved or renamed. If
218 not specified, -s/--similarity defaults to 100 and only renames of
218 not specified, -s/--similarity defaults to 100 and only renames of
219 identical files are detected.
219 identical files are detected.
220
220
221 Returns 0 if all files are successfully added.
221 Returns 0 if all files are successfully added.
222 """
222 """
223 try:
223 try:
224 sim = float(opts.get('similarity') or 100)
224 sim = float(opts.get('similarity') or 100)
225 except ValueError:
225 except ValueError:
226 raise util.Abort(_('similarity must be a number'))
226 raise util.Abort(_('similarity must be a number'))
227 if sim < 0 or sim > 100:
227 if sim < 0 or sim > 100:
228 raise util.Abort(_('similarity must be between 0 and 100'))
228 raise util.Abort(_('similarity must be between 0 and 100'))
229 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
229 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
230
230
231 @command('^annotate|blame',
231 @command('^annotate|blame',
232 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
232 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
233 ('', 'follow', None,
233 ('', 'follow', None,
234 _('follow copies/renames and list the filename (DEPRECATED)')),
234 _('follow copies/renames and list the filename (DEPRECATED)')),
235 ('', 'no-follow', None, _("don't follow copies and renames")),
235 ('', 'no-follow', None, _("don't follow copies and renames")),
236 ('a', 'text', None, _('treat all files as text')),
236 ('a', 'text', None, _('treat all files as text')),
237 ('u', 'user', None, _('list the author (long with -v)')),
237 ('u', 'user', None, _('list the author (long with -v)')),
238 ('f', 'file', None, _('list the filename')),
238 ('f', 'file', None, _('list the filename')),
239 ('d', 'date', None, _('list the date (short with -q)')),
239 ('d', 'date', None, _('list the date (short with -q)')),
240 ('n', 'number', None, _('list the revision number (default)')),
240 ('n', 'number', None, _('list the revision number (default)')),
241 ('c', 'changeset', None, _('list the changeset')),
241 ('c', 'changeset', None, _('list the changeset')),
242 ('l', 'line-number', None, _('show line number at the first appearance'))
242 ('l', 'line-number', None, _('show line number at the first appearance'))
243 ] + diffwsopts + walkopts,
243 ] + diffwsopts + walkopts,
244 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
244 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
245 inferrepo=True)
245 inferrepo=True)
246 def annotate(ui, repo, *pats, **opts):
246 def annotate(ui, repo, *pats, **opts):
247 """show changeset information by line for each file
247 """show changeset information by line for each file
248
248
249 List changes in files, showing the revision id responsible for
249 List changes in files, showing the revision id responsible for
250 each line
250 each line
251
251
252 This command is useful for discovering when a change was made and
252 This command is useful for discovering when a change was made and
253 by whom.
253 by whom.
254
254
255 Without the -a/--text option, annotate will avoid processing files
255 Without the -a/--text option, annotate will avoid processing files
256 it detects as binary. With -a, annotate will annotate the file
256 it detects as binary. With -a, annotate will annotate the file
257 anyway, although the results will probably be neither useful
257 anyway, although the results will probably be neither useful
258 nor desirable.
258 nor desirable.
259
259
260 Returns 0 on success.
260 Returns 0 on success.
261 """
261 """
262 if opts.get('follow'):
262 if opts.get('follow'):
263 # --follow is deprecated and now just an alias for -f/--file
263 # --follow is deprecated and now just an alias for -f/--file
264 # to mimic the behavior of Mercurial before version 1.5
264 # to mimic the behavior of Mercurial before version 1.5
265 opts['file'] = True
265 opts['file'] = True
266
266
267 datefunc = ui.quiet and util.shortdate or util.datestr
267 datefunc = ui.quiet and util.shortdate or util.datestr
268 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
268 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
269
269
270 if not pats:
270 if not pats:
271 raise util.Abort(_('at least one filename or pattern is required'))
271 raise util.Abort(_('at least one filename or pattern is required'))
272
272
273 hexfn = ui.debugflag and hex or short
273 hexfn = ui.debugflag and hex or short
274
274
275 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
275 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
276 ('number', ' ', lambda x: str(x[0].rev())),
276 ('number', ' ', lambda x: str(x[0].rev())),
277 ('changeset', ' ', lambda x: hexfn(x[0].node())),
277 ('changeset', ' ', lambda x: hexfn(x[0].node())),
278 ('date', ' ', getdate),
278 ('date', ' ', getdate),
279 ('file', ' ', lambda x: x[0].path()),
279 ('file', ' ', lambda x: x[0].path()),
280 ('line_number', ':', lambda x: str(x[1])),
280 ('line_number', ':', lambda x: str(x[1])),
281 ]
281 ]
282
282
283 if (not opts.get('user') and not opts.get('changeset')
283 if (not opts.get('user') and not opts.get('changeset')
284 and not opts.get('date') and not opts.get('file')):
284 and not opts.get('date') and not opts.get('file')):
285 opts['number'] = True
285 opts['number'] = True
286
286
287 linenumber = opts.get('line_number') is not None
287 linenumber = opts.get('line_number') is not None
288 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
288 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
289 raise util.Abort(_('at least one of -n/-c is required for -l'))
289 raise util.Abort(_('at least one of -n/-c is required for -l'))
290
290
291 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
291 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
292 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
292 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
293
293
294 def bad(x, y):
294 def bad(x, y):
295 raise util.Abort("%s: %s" % (x, y))
295 raise util.Abort("%s: %s" % (x, y))
296
296
297 ctx = scmutil.revsingle(repo, opts.get('rev'))
297 ctx = scmutil.revsingle(repo, opts.get('rev'))
298 m = scmutil.match(ctx, pats, opts)
298 m = scmutil.match(ctx, pats, opts)
299 m.bad = bad
299 m.bad = bad
300 follow = not opts.get('no_follow')
300 follow = not opts.get('no_follow')
301 diffopts = patch.diffopts(ui, opts, section='annotate')
301 diffopts = patch.diffopts(ui, opts, section='annotate')
302 for abs in ctx.walk(m):
302 for abs in ctx.walk(m):
303 fctx = ctx[abs]
303 fctx = ctx[abs]
304 if not opts.get('text') and util.binary(fctx.data()):
304 if not opts.get('text') and util.binary(fctx.data()):
305 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
305 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
306 continue
306 continue
307
307
308 lines = fctx.annotate(follow=follow, linenumber=linenumber,
308 lines = fctx.annotate(follow=follow, linenumber=linenumber,
309 diffopts=diffopts)
309 diffopts=diffopts)
310 pieces = []
310 pieces = []
311
311
312 for f, sep in funcmap:
312 for f, sep in funcmap:
313 l = [f(n) for n, dummy in lines]
313 l = [f(n) for n, dummy in lines]
314 if l:
314 if l:
315 sized = [(x, encoding.colwidth(x)) for x in l]
315 sized = [(x, encoding.colwidth(x)) for x in l]
316 ml = max([w for x, w in sized])
316 ml = max([w for x, w in sized])
317 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
317 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
318 for x, w in sized])
318 for x, w in sized])
319
319
320 if pieces:
320 if pieces:
321 for p, l in zip(zip(*pieces), lines):
321 for p, l in zip(zip(*pieces), lines):
322 ui.write("%s: %s" % ("".join(p), l[1]))
322 ui.write("%s: %s" % ("".join(p), l[1]))
323
323
324 if lines and not lines[-1][1].endswith('\n'):
324 if lines and not lines[-1][1].endswith('\n'):
325 ui.write('\n')
325 ui.write('\n')
326
326
327 @command('archive',
327 @command('archive',
328 [('', 'no-decode', None, _('do not pass files through decoders')),
328 [('', 'no-decode', None, _('do not pass files through decoders')),
329 ('p', 'prefix', '', _('directory prefix for files in archive'),
329 ('p', 'prefix', '', _('directory prefix for files in archive'),
330 _('PREFIX')),
330 _('PREFIX')),
331 ('r', 'rev', '', _('revision to distribute'), _('REV')),
331 ('r', 'rev', '', _('revision to distribute'), _('REV')),
332 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
332 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
333 ] + subrepoopts + walkopts,
333 ] + subrepoopts + walkopts,
334 _('[OPTION]... DEST'))
334 _('[OPTION]... DEST'))
335 def archive(ui, repo, dest, **opts):
335 def archive(ui, repo, dest, **opts):
336 '''create an unversioned archive of a repository revision
336 '''create an unversioned archive of a repository revision
337
337
338 By default, the revision used is the parent of the working
338 By default, the revision used is the parent of the working
339 directory; use -r/--rev to specify a different revision.
339 directory; use -r/--rev to specify a different revision.
340
340
341 The archive type is automatically detected based on file
341 The archive type is automatically detected based on file
342 extension (or override using -t/--type).
342 extension (or override using -t/--type).
343
343
344 .. container:: verbose
344 .. container:: verbose
345
345
346 Examples:
346 Examples:
347
347
348 - create a zip file containing the 1.0 release::
348 - create a zip file containing the 1.0 release::
349
349
350 hg archive -r 1.0 project-1.0.zip
350 hg archive -r 1.0 project-1.0.zip
351
351
352 - create a tarball excluding .hg files::
352 - create a tarball excluding .hg files::
353
353
354 hg archive project.tar.gz -X ".hg*"
354 hg archive project.tar.gz -X ".hg*"
355
355
356 Valid types are:
356 Valid types are:
357
357
358 :``files``: a directory full of files (default)
358 :``files``: a directory full of files (default)
359 :``tar``: tar archive, uncompressed
359 :``tar``: tar archive, uncompressed
360 :``tbz2``: tar archive, compressed using bzip2
360 :``tbz2``: tar archive, compressed using bzip2
361 :``tgz``: tar archive, compressed using gzip
361 :``tgz``: tar archive, compressed using gzip
362 :``uzip``: zip archive, uncompressed
362 :``uzip``: zip archive, uncompressed
363 :``zip``: zip archive, compressed using deflate
363 :``zip``: zip archive, compressed using deflate
364
364
365 The exact name of the destination archive or directory is given
365 The exact name of the destination archive or directory is given
366 using a format string; see :hg:`help export` for details.
366 using a format string; see :hg:`help export` for details.
367
367
368 Each member added to an archive file has a directory prefix
368 Each member added to an archive file has a directory prefix
369 prepended. Use -p/--prefix to specify a format string for the
369 prepended. Use -p/--prefix to specify a format string for the
370 prefix. The default is the basename of the archive, with suffixes
370 prefix. The default is the basename of the archive, with suffixes
371 removed.
371 removed.
372
372
373 Returns 0 on success.
373 Returns 0 on success.
374 '''
374 '''
375
375
376 ctx = scmutil.revsingle(repo, opts.get('rev'))
376 ctx = scmutil.revsingle(repo, opts.get('rev'))
377 if not ctx:
377 if not ctx:
378 raise util.Abort(_('no working directory: please specify a revision'))
378 raise util.Abort(_('no working directory: please specify a revision'))
379 node = ctx.node()
379 node = ctx.node()
380 dest = cmdutil.makefilename(repo, dest, node)
380 dest = cmdutil.makefilename(repo, dest, node)
381 if os.path.realpath(dest) == repo.root:
381 if os.path.realpath(dest) == repo.root:
382 raise util.Abort(_('repository root cannot be destination'))
382 raise util.Abort(_('repository root cannot be destination'))
383
383
384 kind = opts.get('type') or archival.guesskind(dest) or 'files'
384 kind = opts.get('type') or archival.guesskind(dest) or 'files'
385 prefix = opts.get('prefix')
385 prefix = opts.get('prefix')
386
386
387 if dest == '-':
387 if dest == '-':
388 if kind == 'files':
388 if kind == 'files':
389 raise util.Abort(_('cannot archive plain files to stdout'))
389 raise util.Abort(_('cannot archive plain files to stdout'))
390 dest = cmdutil.makefileobj(repo, dest)
390 dest = cmdutil.makefileobj(repo, dest)
391 if not prefix:
391 if not prefix:
392 prefix = os.path.basename(repo.root) + '-%h'
392 prefix = os.path.basename(repo.root) + '-%h'
393
393
394 prefix = cmdutil.makefilename(repo, prefix, node)
394 prefix = cmdutil.makefilename(repo, prefix, node)
395 matchfn = scmutil.match(ctx, [], opts)
395 matchfn = scmutil.match(ctx, [], opts)
396 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
396 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
397 matchfn, prefix, subrepos=opts.get('subrepos'))
397 matchfn, prefix, subrepos=opts.get('subrepos'))
398
398
399 @command('backout',
399 @command('backout',
400 [('', 'merge', None, _('merge with old dirstate parent after backout')),
400 [('', 'merge', None, _('merge with old dirstate parent after backout')),
401 ('', 'parent', '',
401 ('', 'parent', '',
402 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
402 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
403 ('r', 'rev', '', _('revision to backout'), _('REV')),
403 ('r', 'rev', '', _('revision to backout'), _('REV')),
404 ('e', 'edit', False, _('invoke editor on commit messages')),
404 ('e', 'edit', False, _('invoke editor on commit messages')),
405 ] + mergetoolopts + walkopts + commitopts + commitopts2,
405 ] + mergetoolopts + walkopts + commitopts + commitopts2,
406 _('[OPTION]... [-r] REV'))
406 _('[OPTION]... [-r] REV'))
407 def backout(ui, repo, node=None, rev=None, **opts):
407 def backout(ui, repo, node=None, rev=None, **opts):
408 '''reverse effect of earlier changeset
408 '''reverse effect of earlier changeset
409
409
410 Prepare a new changeset with the effect of REV undone in the
410 Prepare a new changeset with the effect of REV undone in the
411 current working directory.
411 current working directory.
412
412
413 If REV is the parent of the working directory, then this new changeset
413 If REV is the parent of the working directory, then this new changeset
414 is committed automatically. Otherwise, hg needs to merge the
414 is committed automatically. Otherwise, hg needs to merge the
415 changes and the merged result is left uncommitted.
415 changes and the merged result is left uncommitted.
416
416
417 .. note::
417 .. note::
418
418
419 backout cannot be used to fix either an unwanted or
419 backout cannot be used to fix either an unwanted or
420 incorrect merge.
420 incorrect merge.
421
421
422 .. container:: verbose
422 .. container:: verbose
423
423
424 By default, the pending changeset will have one parent,
424 By default, the pending changeset will have one parent,
425 maintaining a linear history. With --merge, the pending
425 maintaining a linear history. With --merge, the pending
426 changeset will instead have two parents: the old parent of the
426 changeset will instead have two parents: the old parent of the
427 working directory and a new child of REV that simply undoes REV.
427 working directory and a new child of REV that simply undoes REV.
428
428
429 Before version 1.7, the behavior without --merge was equivalent
429 Before version 1.7, the behavior without --merge was equivalent
430 to specifying --merge followed by :hg:`update --clean .` to
430 to specifying --merge followed by :hg:`update --clean .` to
431 cancel the merge and leave the child of REV as a head to be
431 cancel the merge and leave the child of REV as a head to be
432 merged separately.
432 merged separately.
433
433
434 See :hg:`help dates` for a list of formats valid for -d/--date.
434 See :hg:`help dates` for a list of formats valid for -d/--date.
435
435
436 Returns 0 on success, 1 if nothing to backout or there are unresolved
436 Returns 0 on success, 1 if nothing to backout or there are unresolved
437 files.
437 files.
438 '''
438 '''
439 if rev and node:
439 if rev and node:
440 raise util.Abort(_("please specify just one revision"))
440 raise util.Abort(_("please specify just one revision"))
441
441
442 if not rev:
442 if not rev:
443 rev = node
443 rev = node
444
444
445 if not rev:
445 if not rev:
446 raise util.Abort(_("please specify a revision to backout"))
446 raise util.Abort(_("please specify a revision to backout"))
447
447
448 date = opts.get('date')
448 date = opts.get('date')
449 if date:
449 if date:
450 opts['date'] = util.parsedate(date)
450 opts['date'] = util.parsedate(date)
451
451
452 cmdutil.checkunfinished(repo)
452 cmdutil.checkunfinished(repo)
453 cmdutil.bailifchanged(repo)
453 cmdutil.bailifchanged(repo)
454 node = scmutil.revsingle(repo, rev).node()
454 node = scmutil.revsingle(repo, rev).node()
455
455
456 op1, op2 = repo.dirstate.parents()
456 op1, op2 = repo.dirstate.parents()
457 if node not in repo.changelog.commonancestorsheads(op1, node):
457 if node not in repo.changelog.commonancestorsheads(op1, node):
458 raise util.Abort(_('cannot backout change that is not an ancestor'))
458 raise util.Abort(_('cannot backout change that is not an ancestor'))
459
459
460 p1, p2 = repo.changelog.parents(node)
460 p1, p2 = repo.changelog.parents(node)
461 if p1 == nullid:
461 if p1 == nullid:
462 raise util.Abort(_('cannot backout a change with no parents'))
462 raise util.Abort(_('cannot backout a change with no parents'))
463 if p2 != nullid:
463 if p2 != nullid:
464 if not opts.get('parent'):
464 if not opts.get('parent'):
465 raise util.Abort(_('cannot backout a merge changeset'))
465 raise util.Abort(_('cannot backout a merge changeset'))
466 p = repo.lookup(opts['parent'])
466 p = repo.lookup(opts['parent'])
467 if p not in (p1, p2):
467 if p not in (p1, p2):
468 raise util.Abort(_('%s is not a parent of %s') %
468 raise util.Abort(_('%s is not a parent of %s') %
469 (short(p), short(node)))
469 (short(p), short(node)))
470 parent = p
470 parent = p
471 else:
471 else:
472 if opts.get('parent'):
472 if opts.get('parent'):
473 raise util.Abort(_('cannot use --parent on non-merge changeset'))
473 raise util.Abort(_('cannot use --parent on non-merge changeset'))
474 parent = p1
474 parent = p1
475
475
476 # the backout should appear on the same branch
476 # the backout should appear on the same branch
477 wlock = repo.wlock()
477 wlock = repo.wlock()
478 try:
478 try:
479 branch = repo.dirstate.branch()
479 branch = repo.dirstate.branch()
480 bheads = repo.branchheads(branch)
480 bheads = repo.branchheads(branch)
481 rctx = scmutil.revsingle(repo, hex(parent))
481 rctx = scmutil.revsingle(repo, hex(parent))
482 if not opts.get('merge') and op1 != node:
482 if not opts.get('merge') and op1 != node:
483 try:
483 try:
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
485 'backout')
485 'backout')
486 stats = mergemod.update(repo, parent, True, True, False,
486 stats = mergemod.update(repo, parent, True, True, False,
487 node, False)
487 node, False)
488 repo.setparents(op1, op2)
488 repo.setparents(op1, op2)
489 hg._showstats(repo, stats)
489 hg._showstats(repo, stats)
490 if stats[3]:
490 if stats[3]:
491 repo.ui.status(_("use 'hg resolve' to retry unresolved "
491 repo.ui.status(_("use 'hg resolve' to retry unresolved "
492 "file merges\n"))
492 "file merges\n"))
493 else:
493 else:
494 msg = _("changeset %s backed out, "
494 msg = _("changeset %s backed out, "
495 "don't forget to commit.\n")
495 "don't forget to commit.\n")
496 ui.status(msg % short(node))
496 ui.status(msg % short(node))
497 return stats[3] > 0
497 return stats[3] > 0
498 finally:
498 finally:
499 ui.setconfig('ui', 'forcemerge', '', '')
499 ui.setconfig('ui', 'forcemerge', '', '')
500 else:
500 else:
501 hg.clean(repo, node, show_stats=False)
501 hg.clean(repo, node, show_stats=False)
502 repo.dirstate.setbranch(branch)
502 repo.dirstate.setbranch(branch)
503 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
503 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
504
504
505
505
506 def commitfunc(ui, repo, message, match, opts):
506 def commitfunc(ui, repo, message, match, opts):
507 e = cmdutil.getcommiteditor(**opts)
507 e = cmdutil.getcommiteditor(**opts)
508 if not message:
508 if not message:
509 # we don't translate commit messages
509 # we don't translate commit messages
510 message = "Backed out changeset %s" % short(node)
510 message = "Backed out changeset %s" % short(node)
511 e = cmdutil.getcommiteditor(edit=True)
511 e = cmdutil.getcommiteditor(edit=True)
512 return repo.commit(message, opts.get('user'), opts.get('date'),
512 return repo.commit(message, opts.get('user'), opts.get('date'),
513 match, editor=e)
513 match, editor=e)
514 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
514 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
515 if not newnode:
515 if not newnode:
516 ui.status(_("nothing changed\n"))
516 ui.status(_("nothing changed\n"))
517 return 1
517 return 1
518 cmdutil.commitstatus(repo, newnode, branch, bheads)
518 cmdutil.commitstatus(repo, newnode, branch, bheads)
519
519
520 def nice(node):
520 def nice(node):
521 return '%d:%s' % (repo.changelog.rev(node), short(node))
521 return '%d:%s' % (repo.changelog.rev(node), short(node))
522 ui.status(_('changeset %s backs out changeset %s\n') %
522 ui.status(_('changeset %s backs out changeset %s\n') %
523 (nice(repo.changelog.tip()), nice(node)))
523 (nice(repo.changelog.tip()), nice(node)))
524 if opts.get('merge') and op1 != node:
524 if opts.get('merge') and op1 != node:
525 hg.clean(repo, op1, show_stats=False)
525 hg.clean(repo, op1, show_stats=False)
526 ui.status(_('merging with changeset %s\n')
526 ui.status(_('merging with changeset %s\n')
527 % nice(repo.changelog.tip()))
527 % nice(repo.changelog.tip()))
528 try:
528 try:
529 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
529 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
530 'backout')
530 'backout')
531 return hg.merge(repo, hex(repo.changelog.tip()))
531 return hg.merge(repo, hex(repo.changelog.tip()))
532 finally:
532 finally:
533 ui.setconfig('ui', 'forcemerge', '', '')
533 ui.setconfig('ui', 'forcemerge', '', '')
534 finally:
534 finally:
535 wlock.release()
535 wlock.release()
536 return 0
536 return 0
537
537
538 @command('bisect',
538 @command('bisect',
539 [('r', 'reset', False, _('reset bisect state')),
539 [('r', 'reset', False, _('reset bisect state')),
540 ('g', 'good', False, _('mark changeset good')),
540 ('g', 'good', False, _('mark changeset good')),
541 ('b', 'bad', False, _('mark changeset bad')),
541 ('b', 'bad', False, _('mark changeset bad')),
542 ('s', 'skip', False, _('skip testing changeset')),
542 ('s', 'skip', False, _('skip testing changeset')),
543 ('e', 'extend', False, _('extend the bisect range')),
543 ('e', 'extend', False, _('extend the bisect range')),
544 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
544 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
545 ('U', 'noupdate', False, _('do not update to target'))],
545 ('U', 'noupdate', False, _('do not update to target'))],
546 _("[-gbsr] [-U] [-c CMD] [REV]"))
546 _("[-gbsr] [-U] [-c CMD] [REV]"))
547 def bisect(ui, repo, rev=None, extra=None, command=None,
547 def bisect(ui, repo, rev=None, extra=None, command=None,
548 reset=None, good=None, bad=None, skip=None, extend=None,
548 reset=None, good=None, bad=None, skip=None, extend=None,
549 noupdate=None):
549 noupdate=None):
550 """subdivision search of changesets
550 """subdivision search of changesets
551
551
552 This command helps to find changesets which introduce problems. To
552 This command helps to find changesets which introduce problems. To
553 use, mark the earliest changeset you know exhibits the problem as
553 use, mark the earliest changeset you know exhibits the problem as
554 bad, then mark the latest changeset which is free from the problem
554 bad, then mark the latest changeset which is free from the problem
555 as good. Bisect will update your working directory to a revision
555 as good. Bisect will update your working directory to a revision
556 for testing (unless the -U/--noupdate option is specified). Once
556 for testing (unless the -U/--noupdate option is specified). Once
557 you have performed tests, mark the working directory as good or
557 you have performed tests, mark the working directory as good or
558 bad, and bisect will either update to another candidate changeset
558 bad, and bisect will either update to another candidate changeset
559 or announce that it has found the bad revision.
559 or announce that it has found the bad revision.
560
560
561 As a shortcut, you can also use the revision argument to mark a
561 As a shortcut, you can also use the revision argument to mark a
562 revision as good or bad without checking it out first.
562 revision as good or bad without checking it out first.
563
563
564 If you supply a command, it will be used for automatic bisection.
564 If you supply a command, it will be used for automatic bisection.
565 The environment variable HG_NODE will contain the ID of the
565 The environment variable HG_NODE will contain the ID of the
566 changeset being tested. The exit status of the command will be
566 changeset being tested. The exit status of the command will be
567 used to mark revisions as good or bad: status 0 means good, 125
567 used to mark revisions as good or bad: status 0 means good, 125
568 means to skip the revision, 127 (command not found) will abort the
568 means to skip the revision, 127 (command not found) will abort the
569 bisection, and any other non-zero exit status means the revision
569 bisection, and any other non-zero exit status means the revision
570 is bad.
570 is bad.
571
571
572 .. container:: verbose
572 .. container:: verbose
573
573
574 Some examples:
574 Some examples:
575
575
576 - start a bisection with known bad revision 34, and good revision 12::
576 - start a bisection with known bad revision 34, and good revision 12::
577
577
578 hg bisect --bad 34
578 hg bisect --bad 34
579 hg bisect --good 12
579 hg bisect --good 12
580
580
581 - advance the current bisection by marking current revision as good or
581 - advance the current bisection by marking current revision as good or
582 bad::
582 bad::
583
583
584 hg bisect --good
584 hg bisect --good
585 hg bisect --bad
585 hg bisect --bad
586
586
587 - mark the current revision, or a known revision, to be skipped (e.g. if
587 - mark the current revision, or a known revision, to be skipped (e.g. if
588 that revision is not usable because of another issue)::
588 that revision is not usable because of another issue)::
589
589
590 hg bisect --skip
590 hg bisect --skip
591 hg bisect --skip 23
591 hg bisect --skip 23
592
592
593 - skip all revisions that do not touch directories ``foo`` or ``bar``::
593 - skip all revisions that do not touch directories ``foo`` or ``bar``::
594
594
595 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
595 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
596
596
597 - forget the current bisection::
597 - forget the current bisection::
598
598
599 hg bisect --reset
599 hg bisect --reset
600
600
601 - use 'make && make tests' to automatically find the first broken
601 - use 'make && make tests' to automatically find the first broken
602 revision::
602 revision::
603
603
604 hg bisect --reset
604 hg bisect --reset
605 hg bisect --bad 34
605 hg bisect --bad 34
606 hg bisect --good 12
606 hg bisect --good 12
607 hg bisect --command "make && make tests"
607 hg bisect --command "make && make tests"
608
608
609 - see all changesets whose states are already known in the current
609 - see all changesets whose states are already known in the current
610 bisection::
610 bisection::
611
611
612 hg log -r "bisect(pruned)"
612 hg log -r "bisect(pruned)"
613
613
614 - see the changeset currently being bisected (especially useful
614 - see the changeset currently being bisected (especially useful
615 if running with -U/--noupdate)::
615 if running with -U/--noupdate)::
616
616
617 hg log -r "bisect(current)"
617 hg log -r "bisect(current)"
618
618
619 - see all changesets that took part in the current bisection::
619 - see all changesets that took part in the current bisection::
620
620
621 hg log -r "bisect(range)"
621 hg log -r "bisect(range)"
622
622
623 - you can even get a nice graph::
623 - you can even get a nice graph::
624
624
625 hg log --graph -r "bisect(range)"
625 hg log --graph -r "bisect(range)"
626
626
627 See :hg:`help revsets` for more about the `bisect()` keyword.
627 See :hg:`help revsets` for more about the `bisect()` keyword.
628
628
629 Returns 0 on success.
629 Returns 0 on success.
630 """
630 """
631 def extendbisectrange(nodes, good):
631 def extendbisectrange(nodes, good):
632 # bisect is incomplete when it ends on a merge node and
632 # bisect is incomplete when it ends on a merge node and
633 # one of the parent was not checked.
633 # one of the parent was not checked.
634 parents = repo[nodes[0]].parents()
634 parents = repo[nodes[0]].parents()
635 if len(parents) > 1:
635 if len(parents) > 1:
636 side = good and state['bad'] or state['good']
636 side = good and state['bad'] or state['good']
637 num = len(set(i.node() for i in parents) & set(side))
637 num = len(set(i.node() for i in parents) & set(side))
638 if num == 1:
638 if num == 1:
639 return parents[0].ancestor(parents[1])
639 return parents[0].ancestor(parents[1])
640 return None
640 return None
641
641
642 def print_result(nodes, good):
642 def print_result(nodes, good):
643 displayer = cmdutil.show_changeset(ui, repo, {})
643 displayer = cmdutil.show_changeset(ui, repo, {})
644 if len(nodes) == 1:
644 if len(nodes) == 1:
645 # narrowed it down to a single revision
645 # narrowed it down to a single revision
646 if good:
646 if good:
647 ui.write(_("The first good revision is:\n"))
647 ui.write(_("The first good revision is:\n"))
648 else:
648 else:
649 ui.write(_("The first bad revision is:\n"))
649 ui.write(_("The first bad revision is:\n"))
650 displayer.show(repo[nodes[0]])
650 displayer.show(repo[nodes[0]])
651 extendnode = extendbisectrange(nodes, good)
651 extendnode = extendbisectrange(nodes, good)
652 if extendnode is not None:
652 if extendnode is not None:
653 ui.write(_('Not all ancestors of this changeset have been'
653 ui.write(_('Not all ancestors of this changeset have been'
654 ' checked.\nUse bisect --extend to continue the '
654 ' checked.\nUse bisect --extend to continue the '
655 'bisection from\nthe common ancestor, %s.\n')
655 'bisection from\nthe common ancestor, %s.\n')
656 % extendnode)
656 % extendnode)
657 else:
657 else:
658 # multiple possible revisions
658 # multiple possible revisions
659 if good:
659 if good:
660 ui.write(_("Due to skipped revisions, the first "
660 ui.write(_("Due to skipped revisions, the first "
661 "good revision could be any of:\n"))
661 "good revision could be any of:\n"))
662 else:
662 else:
663 ui.write(_("Due to skipped revisions, the first "
663 ui.write(_("Due to skipped revisions, the first "
664 "bad revision could be any of:\n"))
664 "bad revision could be any of:\n"))
665 for n in nodes:
665 for n in nodes:
666 displayer.show(repo[n])
666 displayer.show(repo[n])
667 displayer.close()
667 displayer.close()
668
668
669 def check_state(state, interactive=True):
669 def check_state(state, interactive=True):
670 if not state['good'] or not state['bad']:
670 if not state['good'] or not state['bad']:
671 if (good or bad or skip or reset) and interactive:
671 if (good or bad or skip or reset) and interactive:
672 return
672 return
673 if not state['good']:
673 if not state['good']:
674 raise util.Abort(_('cannot bisect (no known good revisions)'))
674 raise util.Abort(_('cannot bisect (no known good revisions)'))
675 else:
675 else:
676 raise util.Abort(_('cannot bisect (no known bad revisions)'))
676 raise util.Abort(_('cannot bisect (no known bad revisions)'))
677 return True
677 return True
678
678
679 # backward compatibility
679 # backward compatibility
680 if rev in "good bad reset init".split():
680 if rev in "good bad reset init".split():
681 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
681 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
682 cmd, rev, extra = rev, extra, None
682 cmd, rev, extra = rev, extra, None
683 if cmd == "good":
683 if cmd == "good":
684 good = True
684 good = True
685 elif cmd == "bad":
685 elif cmd == "bad":
686 bad = True
686 bad = True
687 else:
687 else:
688 reset = True
688 reset = True
689 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
689 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
690 raise util.Abort(_('incompatible arguments'))
690 raise util.Abort(_('incompatible arguments'))
691
691
692 cmdutil.checkunfinished(repo)
692 cmdutil.checkunfinished(repo)
693
693
694 if reset:
694 if reset:
695 p = repo.join("bisect.state")
695 p = repo.join("bisect.state")
696 if os.path.exists(p):
696 if os.path.exists(p):
697 os.unlink(p)
697 os.unlink(p)
698 return
698 return
699
699
700 state = hbisect.load_state(repo)
700 state = hbisect.load_state(repo)
701
701
702 if command:
702 if command:
703 changesets = 1
703 changesets = 1
704 if noupdate:
704 if noupdate:
705 try:
705 try:
706 node = state['current'][0]
706 node = state['current'][0]
707 except LookupError:
707 except LookupError:
708 raise util.Abort(_('current bisect revision is unknown - '
708 raise util.Abort(_('current bisect revision is unknown - '
709 'start a new bisect to fix'))
709 'start a new bisect to fix'))
710 else:
710 else:
711 node, p2 = repo.dirstate.parents()
711 node, p2 = repo.dirstate.parents()
712 if p2 != nullid:
712 if p2 != nullid:
713 raise util.Abort(_('current bisect revision is a merge'))
713 raise util.Abort(_('current bisect revision is a merge'))
714 try:
714 try:
715 while changesets:
715 while changesets:
716 # update state
716 # update state
717 state['current'] = [node]
717 state['current'] = [node]
718 hbisect.save_state(repo, state)
718 hbisect.save_state(repo, state)
719 status = util.system(command,
719 status = util.system(command,
720 environ={'HG_NODE': hex(node)},
720 environ={'HG_NODE': hex(node)},
721 out=ui.fout)
721 out=ui.fout)
722 if status == 125:
722 if status == 125:
723 transition = "skip"
723 transition = "skip"
724 elif status == 0:
724 elif status == 0:
725 transition = "good"
725 transition = "good"
726 # status < 0 means process was killed
726 # status < 0 means process was killed
727 elif status == 127:
727 elif status == 127:
728 raise util.Abort(_("failed to execute %s") % command)
728 raise util.Abort(_("failed to execute %s") % command)
729 elif status < 0:
729 elif status < 0:
730 raise util.Abort(_("%s killed") % command)
730 raise util.Abort(_("%s killed") % command)
731 else:
731 else:
732 transition = "bad"
732 transition = "bad"
733 ctx = scmutil.revsingle(repo, rev, node)
733 ctx = scmutil.revsingle(repo, rev, node)
734 rev = None # clear for future iterations
734 rev = None # clear for future iterations
735 state[transition].append(ctx.node())
735 state[transition].append(ctx.node())
736 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
736 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
737 check_state(state, interactive=False)
737 check_state(state, interactive=False)
738 # bisect
738 # bisect
739 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
739 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
740 # update to next check
740 # update to next check
741 node = nodes[0]
741 node = nodes[0]
742 if not noupdate:
742 if not noupdate:
743 cmdutil.bailifchanged(repo)
743 cmdutil.bailifchanged(repo)
744 hg.clean(repo, node, show_stats=False)
744 hg.clean(repo, node, show_stats=False)
745 finally:
745 finally:
746 state['current'] = [node]
746 state['current'] = [node]
747 hbisect.save_state(repo, state)
747 hbisect.save_state(repo, state)
748 print_result(nodes, bgood)
748 print_result(nodes, bgood)
749 return
749 return
750
750
751 # update state
751 # update state
752
752
753 if rev:
753 if rev:
754 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
754 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
755 else:
755 else:
756 nodes = [repo.lookup('.')]
756 nodes = [repo.lookup('.')]
757
757
758 if good or bad or skip:
758 if good or bad or skip:
759 if good:
759 if good:
760 state['good'] += nodes
760 state['good'] += nodes
761 elif bad:
761 elif bad:
762 state['bad'] += nodes
762 state['bad'] += nodes
763 elif skip:
763 elif skip:
764 state['skip'] += nodes
764 state['skip'] += nodes
765 hbisect.save_state(repo, state)
765 hbisect.save_state(repo, state)
766
766
767 if not check_state(state):
767 if not check_state(state):
768 return
768 return
769
769
770 # actually bisect
770 # actually bisect
771 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
771 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
772 if extend:
772 if extend:
773 if not changesets:
773 if not changesets:
774 extendnode = extendbisectrange(nodes, good)
774 extendnode = extendbisectrange(nodes, good)
775 if extendnode is not None:
775 if extendnode is not None:
776 ui.write(_("Extending search to changeset %d:%s\n")
776 ui.write(_("Extending search to changeset %d:%s\n")
777 % (extendnode.rev(), extendnode))
777 % (extendnode.rev(), extendnode))
778 state['current'] = [extendnode.node()]
778 state['current'] = [extendnode.node()]
779 hbisect.save_state(repo, state)
779 hbisect.save_state(repo, state)
780 if noupdate:
780 if noupdate:
781 return
781 return
782 cmdutil.bailifchanged(repo)
782 cmdutil.bailifchanged(repo)
783 return hg.clean(repo, extendnode.node())
783 return hg.clean(repo, extendnode.node())
784 raise util.Abort(_("nothing to extend"))
784 raise util.Abort(_("nothing to extend"))
785
785
786 if changesets == 0:
786 if changesets == 0:
787 print_result(nodes, good)
787 print_result(nodes, good)
788 else:
788 else:
789 assert len(nodes) == 1 # only a single node can be tested next
789 assert len(nodes) == 1 # only a single node can be tested next
790 node = nodes[0]
790 node = nodes[0]
791 # compute the approximate number of remaining tests
791 # compute the approximate number of remaining tests
792 tests, size = 0, 2
792 tests, size = 0, 2
793 while size <= changesets:
793 while size <= changesets:
794 tests, size = tests + 1, size * 2
794 tests, size = tests + 1, size * 2
795 rev = repo.changelog.rev(node)
795 rev = repo.changelog.rev(node)
796 ui.write(_("Testing changeset %d:%s "
796 ui.write(_("Testing changeset %d:%s "
797 "(%d changesets remaining, ~%d tests)\n")
797 "(%d changesets remaining, ~%d tests)\n")
798 % (rev, short(node), changesets, tests))
798 % (rev, short(node), changesets, tests))
799 state['current'] = [node]
799 state['current'] = [node]
800 hbisect.save_state(repo, state)
800 hbisect.save_state(repo, state)
801 if not noupdate:
801 if not noupdate:
802 cmdutil.bailifchanged(repo)
802 cmdutil.bailifchanged(repo)
803 return hg.clean(repo, node)
803 return hg.clean(repo, node)
804
804
805 @command('bookmarks|bookmark',
805 @command('bookmarks|bookmark',
806 [('f', 'force', False, _('force')),
806 [('f', 'force', False, _('force')),
807 ('r', 'rev', '', _('revision'), _('REV')),
807 ('r', 'rev', '', _('revision'), _('REV')),
808 ('d', 'delete', False, _('delete a given bookmark')),
808 ('d', 'delete', False, _('delete a given bookmark')),
809 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
809 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
810 ('i', 'inactive', False, _('mark a bookmark inactive'))],
810 ('i', 'inactive', False, _('mark a bookmark inactive'))],
811 _('hg bookmarks [OPTIONS]... [NAME]...'))
811 _('hg bookmarks [OPTIONS]... [NAME]...'))
812 def bookmark(ui, repo, *names, **opts):
812 def bookmark(ui, repo, *names, **opts):
813 '''create a new bookmark or list existing bookmarks
813 '''create a new bookmark or list existing bookmarks
814
814
815 Bookmarks are labels on changesets to help track lines of development.
815 Bookmarks are labels on changesets to help track lines of development.
816 Bookmarks are unversioned and can be moved, renamed and deleted.
816 Bookmarks are unversioned and can be moved, renamed and deleted.
817 Deleting or moving a bookmark has no effect on the associated changesets.
817 Deleting or moving a bookmark has no effect on the associated changesets.
818
818
819 Creating or updating to a bookmark causes it to be marked as 'active'.
819 Creating or updating to a bookmark causes it to be marked as 'active'.
820 Active bookmarks are indicated with a '*'.
820 Active bookmarks are indicated with a '*'.
821 When a commit is made, an active bookmark will advance to the new commit.
821 When a commit is made, an active bookmark will advance to the new commit.
822 A plain :hg:`update` will also advance an active bookmark, if possible.
822 A plain :hg:`update` will also advance an active bookmark, if possible.
823 Updating away from a bookmark will cause it to be deactivated.
823 Updating away from a bookmark will cause it to be deactivated.
824
824
825 Bookmarks can be pushed and pulled between repositories (see
825 Bookmarks can be pushed and pulled between repositories (see
826 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
826 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
827 diverged, a new 'divergent bookmark' of the form 'name@path' will
827 diverged, a new 'divergent bookmark' of the form 'name@path' will
828 be created. Using :hg:'merge' will resolve the divergence.
828 be created. Using :hg:'merge' will resolve the divergence.
829
829
830 A bookmark named '@' has the special property that :hg:`clone` will
830 A bookmark named '@' has the special property that :hg:`clone` will
831 check it out by default if it exists.
831 check it out by default if it exists.
832
832
833 .. container:: verbose
833 .. container:: verbose
834
834
835 Examples:
835 Examples:
836
836
837 - create an active bookmark for a new line of development::
837 - create an active bookmark for a new line of development::
838
838
839 hg book new-feature
839 hg book new-feature
840
840
841 - create an inactive bookmark as a place marker::
841 - create an inactive bookmark as a place marker::
842
842
843 hg book -i reviewed
843 hg book -i reviewed
844
844
845 - create an inactive bookmark on another changeset::
845 - create an inactive bookmark on another changeset::
846
846
847 hg book -r .^ tested
847 hg book -r .^ tested
848
848
849 - move the '@' bookmark from another branch::
849 - move the '@' bookmark from another branch::
850
850
851 hg book -f @
851 hg book -f @
852 '''
852 '''
853 force = opts.get('force')
853 force = opts.get('force')
854 rev = opts.get('rev')
854 rev = opts.get('rev')
855 delete = opts.get('delete')
855 delete = opts.get('delete')
856 rename = opts.get('rename')
856 rename = opts.get('rename')
857 inactive = opts.get('inactive')
857 inactive = opts.get('inactive')
858
858
859 def checkformat(mark):
859 def checkformat(mark):
860 mark = mark.strip()
860 mark = mark.strip()
861 if not mark:
861 if not mark:
862 raise util.Abort(_("bookmark names cannot consist entirely of "
862 raise util.Abort(_("bookmark names cannot consist entirely of "
863 "whitespace"))
863 "whitespace"))
864 scmutil.checknewlabel(repo, mark, 'bookmark')
864 scmutil.checknewlabel(repo, mark, 'bookmark')
865 return mark
865 return mark
866
866
867 def checkconflict(repo, mark, cur, force=False, target=None):
867 def checkconflict(repo, mark, cur, force=False, target=None):
868 if mark in marks and not force:
868 if mark in marks and not force:
869 if target:
869 if target:
870 if marks[mark] == target and target == cur:
870 if marks[mark] == target and target == cur:
871 # re-activating a bookmark
871 # re-activating a bookmark
872 return
872 return
873 anc = repo.changelog.ancestors([repo[target].rev()])
873 anc = repo.changelog.ancestors([repo[target].rev()])
874 bmctx = repo[marks[mark]]
874 bmctx = repo[marks[mark]]
875 divs = [repo[b].node() for b in marks
875 divs = [repo[b].node() for b in marks
876 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
876 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
877
877
878 # allow resolving a single divergent bookmark even if moving
878 # allow resolving a single divergent bookmark even if moving
879 # the bookmark across branches when a revision is specified
879 # the bookmark across branches when a revision is specified
880 # that contains a divergent bookmark
880 # that contains a divergent bookmark
881 if bmctx.rev() not in anc and target in divs:
881 if bmctx.rev() not in anc and target in divs:
882 bookmarks.deletedivergent(repo, [target], mark)
882 bookmarks.deletedivergent(repo, [target], mark)
883 return
883 return
884
884
885 deletefrom = [b for b in divs
885 deletefrom = [b for b in divs
886 if repo[b].rev() in anc or b == target]
886 if repo[b].rev() in anc or b == target]
887 bookmarks.deletedivergent(repo, deletefrom, mark)
887 bookmarks.deletedivergent(repo, deletefrom, mark)
888 if bookmarks.validdest(repo, bmctx, repo[target]):
888 if bookmarks.validdest(repo, bmctx, repo[target]):
889 ui.status(_("moving bookmark '%s' forward from %s\n") %
889 ui.status(_("moving bookmark '%s' forward from %s\n") %
890 (mark, short(bmctx.node())))
890 (mark, short(bmctx.node())))
891 return
891 return
892 raise util.Abort(_("bookmark '%s' already exists "
892 raise util.Abort(_("bookmark '%s' already exists "
893 "(use -f to force)") % mark)
893 "(use -f to force)") % mark)
894 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
894 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
895 and not force):
895 and not force):
896 raise util.Abort(
896 raise util.Abort(
897 _("a bookmark cannot have the name of an existing branch"))
897 _("a bookmark cannot have the name of an existing branch"))
898
898
899 if delete and rename:
899 if delete and rename:
900 raise util.Abort(_("--delete and --rename are incompatible"))
900 raise util.Abort(_("--delete and --rename are incompatible"))
901 if delete and rev:
901 if delete and rev:
902 raise util.Abort(_("--rev is incompatible with --delete"))
902 raise util.Abort(_("--rev is incompatible with --delete"))
903 if rename and rev:
903 if rename and rev:
904 raise util.Abort(_("--rev is incompatible with --rename"))
904 raise util.Abort(_("--rev is incompatible with --rename"))
905 if not names and (delete or rev):
905 if not names and (delete or rev):
906 raise util.Abort(_("bookmark name required"))
906 raise util.Abort(_("bookmark name required"))
907
907
908 if delete or rename or names or inactive:
908 if delete or rename or names or inactive:
909 wlock = repo.wlock()
909 wlock = repo.wlock()
910 try:
910 try:
911 cur = repo.changectx('.').node()
911 cur = repo.changectx('.').node()
912 marks = repo._bookmarks
912 marks = repo._bookmarks
913 if delete:
913 if delete:
914 for mark in names:
914 for mark in names:
915 if mark not in marks:
915 if mark not in marks:
916 raise util.Abort(_("bookmark '%s' does not exist") %
916 raise util.Abort(_("bookmark '%s' does not exist") %
917 mark)
917 mark)
918 if mark == repo._bookmarkcurrent:
918 if mark == repo._bookmarkcurrent:
919 bookmarks.unsetcurrent(repo)
919 bookmarks.unsetcurrent(repo)
920 del marks[mark]
920 del marks[mark]
921 marks.write()
921 marks.write()
922
922
923 elif rename:
923 elif rename:
924 if not names:
924 if not names:
925 raise util.Abort(_("new bookmark name required"))
925 raise util.Abort(_("new bookmark name required"))
926 elif len(names) > 1:
926 elif len(names) > 1:
927 raise util.Abort(_("only one new bookmark name allowed"))
927 raise util.Abort(_("only one new bookmark name allowed"))
928 mark = checkformat(names[0])
928 mark = checkformat(names[0])
929 if rename not in marks:
929 if rename not in marks:
930 raise util.Abort(_("bookmark '%s' does not exist") % rename)
930 raise util.Abort(_("bookmark '%s' does not exist") % rename)
931 checkconflict(repo, mark, cur, force)
931 checkconflict(repo, mark, cur, force)
932 marks[mark] = marks[rename]
932 marks[mark] = marks[rename]
933 if repo._bookmarkcurrent == rename and not inactive:
933 if repo._bookmarkcurrent == rename and not inactive:
934 bookmarks.setcurrent(repo, mark)
934 bookmarks.setcurrent(repo, mark)
935 del marks[rename]
935 del marks[rename]
936 marks.write()
936 marks.write()
937
937
938 elif names:
938 elif names:
939 newact = None
939 newact = None
940 for mark in names:
940 for mark in names:
941 mark = checkformat(mark)
941 mark = checkformat(mark)
942 if newact is None:
942 if newact is None:
943 newact = mark
943 newact = mark
944 if inactive and mark == repo._bookmarkcurrent:
944 if inactive and mark == repo._bookmarkcurrent:
945 bookmarks.unsetcurrent(repo)
945 bookmarks.unsetcurrent(repo)
946 return
946 return
947 tgt = cur
947 tgt = cur
948 if rev:
948 if rev:
949 tgt = scmutil.revsingle(repo, rev).node()
949 tgt = scmutil.revsingle(repo, rev).node()
950 checkconflict(repo, mark, cur, force, tgt)
950 checkconflict(repo, mark, cur, force, tgt)
951 marks[mark] = tgt
951 marks[mark] = tgt
952 if not inactive and cur == marks[newact] and not rev:
952 if not inactive and cur == marks[newact] and not rev:
953 bookmarks.setcurrent(repo, newact)
953 bookmarks.setcurrent(repo, newact)
954 elif cur != tgt and newact == repo._bookmarkcurrent:
954 elif cur != tgt and newact == repo._bookmarkcurrent:
955 bookmarks.unsetcurrent(repo)
955 bookmarks.unsetcurrent(repo)
956 marks.write()
956 marks.write()
957
957
958 elif inactive:
958 elif inactive:
959 if len(marks) == 0:
959 if len(marks) == 0:
960 ui.status(_("no bookmarks set\n"))
960 ui.status(_("no bookmarks set\n"))
961 elif not repo._bookmarkcurrent:
961 elif not repo._bookmarkcurrent:
962 ui.status(_("no active bookmark\n"))
962 ui.status(_("no active bookmark\n"))
963 else:
963 else:
964 bookmarks.unsetcurrent(repo)
964 bookmarks.unsetcurrent(repo)
965 finally:
965 finally:
966 wlock.release()
966 wlock.release()
967 else: # show bookmarks
967 else: # show bookmarks
968 hexfn = ui.debugflag and hex or short
968 hexfn = ui.debugflag and hex or short
969 marks = repo._bookmarks
969 marks = repo._bookmarks
970 if len(marks) == 0:
970 if len(marks) == 0:
971 ui.status(_("no bookmarks set\n"))
971 ui.status(_("no bookmarks set\n"))
972 else:
972 else:
973 for bmark, n in sorted(marks.iteritems()):
973 for bmark, n in sorted(marks.iteritems()):
974 current = repo._bookmarkcurrent
974 current = repo._bookmarkcurrent
975 if bmark == current:
975 if bmark == current:
976 prefix, label = '*', 'bookmarks.current'
976 prefix, label = '*', 'bookmarks.current'
977 else:
977 else:
978 prefix, label = ' ', ''
978 prefix, label = ' ', ''
979
979
980 if ui.quiet:
980 if ui.quiet:
981 ui.write("%s\n" % bmark, label=label)
981 ui.write("%s\n" % bmark, label=label)
982 else:
982 else:
983 pad = " " * (25 - encoding.colwidth(bmark))
983 pad = " " * (25 - encoding.colwidth(bmark))
984 ui.write(" %s %s%s %d:%s\n" % (
984 ui.write(" %s %s%s %d:%s\n" % (
985 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
985 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
986 label=label)
986 label=label)
987
987
988 @command('branch',
988 @command('branch',
989 [('f', 'force', None,
989 [('f', 'force', None,
990 _('set branch name even if it shadows an existing branch')),
990 _('set branch name even if it shadows an existing branch')),
991 ('C', 'clean', None, _('reset branch name to parent branch name'))],
991 ('C', 'clean', None, _('reset branch name to parent branch name'))],
992 _('[-fC] [NAME]'))
992 _('[-fC] [NAME]'))
993 def branch(ui, repo, label=None, **opts):
993 def branch(ui, repo, label=None, **opts):
994 """set or show the current branch name
994 """set or show the current branch name
995
995
996 .. note::
996 .. note::
997
997
998 Branch names are permanent and global. Use :hg:`bookmark` to create a
998 Branch names are permanent and global. Use :hg:`bookmark` to create a
999 light-weight bookmark instead. See :hg:`help glossary` for more
999 light-weight bookmark instead. See :hg:`help glossary` for more
1000 information about named branches and bookmarks.
1000 information about named branches and bookmarks.
1001
1001
1002 With no argument, show the current branch name. With one argument,
1002 With no argument, show the current branch name. With one argument,
1003 set the working directory branch name (the branch will not exist
1003 set the working directory branch name (the branch will not exist
1004 in the repository until the next commit). Standard practice
1004 in the repository until the next commit). Standard practice
1005 recommends that primary development take place on the 'default'
1005 recommends that primary development take place on the 'default'
1006 branch.
1006 branch.
1007
1007
1008 Unless -f/--force is specified, branch will not let you set a
1008 Unless -f/--force is specified, branch will not let you set a
1009 branch name that already exists, even if it's inactive.
1009 branch name that already exists, even if it's inactive.
1010
1010
1011 Use -C/--clean to reset the working directory branch to that of
1011 Use -C/--clean to reset the working directory branch to that of
1012 the parent of the working directory, negating a previous branch
1012 the parent of the working directory, negating a previous branch
1013 change.
1013 change.
1014
1014
1015 Use the command :hg:`update` to switch to an existing branch. Use
1015 Use the command :hg:`update` to switch to an existing branch. Use
1016 :hg:`commit --close-branch` to mark this branch as closed.
1016 :hg:`commit --close-branch` to mark this branch as closed.
1017
1017
1018 Returns 0 on success.
1018 Returns 0 on success.
1019 """
1019 """
1020 if label:
1020 if label:
1021 label = label.strip()
1021 label = label.strip()
1022
1022
1023 if not opts.get('clean') and not label:
1023 if not opts.get('clean') and not label:
1024 ui.write("%s\n" % repo.dirstate.branch())
1024 ui.write("%s\n" % repo.dirstate.branch())
1025 return
1025 return
1026
1026
1027 wlock = repo.wlock()
1027 wlock = repo.wlock()
1028 try:
1028 try:
1029 if opts.get('clean'):
1029 if opts.get('clean'):
1030 label = repo[None].p1().branch()
1030 label = repo[None].p1().branch()
1031 repo.dirstate.setbranch(label)
1031 repo.dirstate.setbranch(label)
1032 ui.status(_('reset working directory to branch %s\n') % label)
1032 ui.status(_('reset working directory to branch %s\n') % label)
1033 elif label:
1033 elif label:
1034 if not opts.get('force') and label in repo.branchmap():
1034 if not opts.get('force') and label in repo.branchmap():
1035 if label not in [p.branch() for p in repo.parents()]:
1035 if label not in [p.branch() for p in repo.parents()]:
1036 raise util.Abort(_('a branch of the same name already'
1036 raise util.Abort(_('a branch of the same name already'
1037 ' exists'),
1037 ' exists'),
1038 # i18n: "it" refers to an existing branch
1038 # i18n: "it" refers to an existing branch
1039 hint=_("use 'hg update' to switch to it"))
1039 hint=_("use 'hg update' to switch to it"))
1040 scmutil.checknewlabel(repo, label, 'branch')
1040 scmutil.checknewlabel(repo, label, 'branch')
1041 repo.dirstate.setbranch(label)
1041 repo.dirstate.setbranch(label)
1042 ui.status(_('marked working directory as branch %s\n') % label)
1042 ui.status(_('marked working directory as branch %s\n') % label)
1043 ui.status(_('(branches are permanent and global, '
1043 ui.status(_('(branches are permanent and global, '
1044 'did you want a bookmark?)\n'))
1044 'did you want a bookmark?)\n'))
1045 finally:
1045 finally:
1046 wlock.release()
1046 wlock.release()
1047
1047
1048 @command('branches',
1048 @command('branches',
1049 [('a', 'active', False, _('show only branches that have unmerged heads')),
1049 [('a', 'active', False, _('show only branches that have unmerged heads')),
1050 ('c', 'closed', False, _('show normal and closed branches'))],
1050 ('c', 'closed', False, _('show normal and closed branches'))],
1051 _('[-ac]'))
1051 _('[-ac]'))
1052 def branches(ui, repo, active=False, closed=False):
1052 def branches(ui, repo, active=False, closed=False):
1053 """list repository named branches
1053 """list repository named branches
1054
1054
1055 List the repository's named branches, indicating which ones are
1055 List the repository's named branches, indicating which ones are
1056 inactive. If -c/--closed is specified, also list branches which have
1056 inactive. If -c/--closed is specified, also list branches which have
1057 been marked closed (see :hg:`commit --close-branch`).
1057 been marked closed (see :hg:`commit --close-branch`).
1058
1058
1059 If -a/--active is specified, only show active branches. A branch
1059 If -a/--active is specified, only show active branches. A branch
1060 is considered active if it contains repository heads.
1060 is considered active if it contains repository heads.
1061
1061
1062 Use the command :hg:`update` to switch to an existing branch.
1062 Use the command :hg:`update` to switch to an existing branch.
1063
1063
1064 Returns 0.
1064 Returns 0.
1065 """
1065 """
1066
1066
1067 hexfunc = ui.debugflag and hex or short
1067 hexfunc = ui.debugflag and hex or short
1068
1068
1069 allheads = set(repo.heads())
1069 allheads = set(repo.heads())
1070 branches = []
1070 branches = []
1071 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1071 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1072 isactive = not isclosed and bool(set(heads) & allheads)
1072 isactive = not isclosed and bool(set(heads) & allheads)
1073 branches.append((tag, repo[tip], isactive, not isclosed))
1073 branches.append((tag, repo[tip], isactive, not isclosed))
1074 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1074 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1075 reverse=True)
1075 reverse=True)
1076
1076
1077 for tag, ctx, isactive, isopen in branches:
1077 for tag, ctx, isactive, isopen in branches:
1078 if (not active) or isactive:
1078 if (not active) or isactive:
1079 if isactive:
1079 if isactive:
1080 label = 'branches.active'
1080 label = 'branches.active'
1081 notice = ''
1081 notice = ''
1082 elif not isopen:
1082 elif not isopen:
1083 if not closed:
1083 if not closed:
1084 continue
1084 continue
1085 label = 'branches.closed'
1085 label = 'branches.closed'
1086 notice = _(' (closed)')
1086 notice = _(' (closed)')
1087 else:
1087 else:
1088 label = 'branches.inactive'
1088 label = 'branches.inactive'
1089 notice = _(' (inactive)')
1089 notice = _(' (inactive)')
1090 if tag == repo.dirstate.branch():
1090 if tag == repo.dirstate.branch():
1091 label = 'branches.current'
1091 label = 'branches.current'
1092 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1092 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1093 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1093 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1094 'log.changeset changeset.%s' % ctx.phasestr())
1094 'log.changeset changeset.%s' % ctx.phasestr())
1095 labeledtag = ui.label(tag, label)
1095 labeledtag = ui.label(tag, label)
1096 if ui.quiet:
1096 if ui.quiet:
1097 ui.write("%s\n" % labeledtag)
1097 ui.write("%s\n" % labeledtag)
1098 else:
1098 else:
1099 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1099 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1100
1100
1101 @command('bundle',
1101 @command('bundle',
1102 [('f', 'force', None, _('run even when the destination is unrelated')),
1102 [('f', 'force', None, _('run even when the destination is unrelated')),
1103 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1103 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1104 _('REV')),
1104 _('REV')),
1105 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1105 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1106 _('BRANCH')),
1106 _('BRANCH')),
1107 ('', 'base', [],
1107 ('', 'base', [],
1108 _('a base changeset assumed to be available at the destination'),
1108 _('a base changeset assumed to be available at the destination'),
1109 _('REV')),
1109 _('REV')),
1110 ('a', 'all', None, _('bundle all changesets in the repository')),
1110 ('a', 'all', None, _('bundle all changesets in the repository')),
1111 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1111 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1112 ] + remoteopts,
1112 ] + remoteopts,
1113 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1113 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1114 def bundle(ui, repo, fname, dest=None, **opts):
1114 def bundle(ui, repo, fname, dest=None, **opts):
1115 """create a changegroup file
1115 """create a changegroup file
1116
1116
1117 Generate a compressed changegroup file collecting changesets not
1117 Generate a compressed changegroup file collecting changesets not
1118 known to be in another repository.
1118 known to be in another repository.
1119
1119
1120 If you omit the destination repository, then hg assumes the
1120 If you omit the destination repository, then hg assumes the
1121 destination will have all the nodes you specify with --base
1121 destination will have all the nodes you specify with --base
1122 parameters. To create a bundle containing all changesets, use
1122 parameters. To create a bundle containing all changesets, use
1123 -a/--all (or --base null).
1123 -a/--all (or --base null).
1124
1124
1125 You can change compression method with the -t/--type option.
1125 You can change compression method with the -t/--type option.
1126 The available compression methods are: none, bzip2, and
1126 The available compression methods are: none, bzip2, and
1127 gzip (by default, bundles are compressed using bzip2).
1127 gzip (by default, bundles are compressed using bzip2).
1128
1128
1129 The bundle file can then be transferred using conventional means
1129 The bundle file can then be transferred using conventional means
1130 and applied to another repository with the unbundle or pull
1130 and applied to another repository with the unbundle or pull
1131 command. This is useful when direct push and pull are not
1131 command. This is useful when direct push and pull are not
1132 available or when exporting an entire repository is undesirable.
1132 available or when exporting an entire repository is undesirable.
1133
1133
1134 Applying bundles preserves all changeset contents including
1134 Applying bundles preserves all changeset contents including
1135 permissions, copy/rename information, and revision history.
1135 permissions, copy/rename information, and revision history.
1136
1136
1137 Returns 0 on success, 1 if no changes found.
1137 Returns 0 on success, 1 if no changes found.
1138 """
1138 """
1139 revs = None
1139 revs = None
1140 if 'rev' in opts:
1140 if 'rev' in opts:
1141 revs = scmutil.revrange(repo, opts['rev'])
1141 revs = scmutil.revrange(repo, opts['rev'])
1142
1142
1143 bundletype = opts.get('type', 'bzip2').lower()
1143 bundletype = opts.get('type', 'bzip2').lower()
1144 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1144 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1145 bundletype = btypes.get(bundletype)
1145 bundletype = btypes.get(bundletype)
1146 if bundletype not in changegroup.bundletypes:
1146 if bundletype not in changegroup.bundletypes:
1147 raise util.Abort(_('unknown bundle type specified with --type'))
1147 raise util.Abort(_('unknown bundle type specified with --type'))
1148
1148
1149 if opts.get('all'):
1149 if opts.get('all'):
1150 base = ['null']
1150 base = ['null']
1151 else:
1151 else:
1152 base = scmutil.revrange(repo, opts.get('base'))
1152 base = scmutil.revrange(repo, opts.get('base'))
1153 # TODO: get desired bundlecaps from command line.
1153 # TODO: get desired bundlecaps from command line.
1154 bundlecaps = None
1154 bundlecaps = None
1155 if base:
1155 if base:
1156 if dest:
1156 if dest:
1157 raise util.Abort(_("--base is incompatible with specifying "
1157 raise util.Abort(_("--base is incompatible with specifying "
1158 "a destination"))
1158 "a destination"))
1159 common = [repo.lookup(rev) for rev in base]
1159 common = [repo.lookup(rev) for rev in base]
1160 heads = revs and map(repo.lookup, revs) or revs
1160 heads = revs and map(repo.lookup, revs) or revs
1161 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1161 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1162 bundlecaps=bundlecaps)
1162 bundlecaps=bundlecaps)
1163 outgoing = None
1163 outgoing = None
1164 else:
1164 else:
1165 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1165 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1166 dest, branches = hg.parseurl(dest, opts.get('branch'))
1166 dest, branches = hg.parseurl(dest, opts.get('branch'))
1167 other = hg.peer(repo, opts, dest)
1167 other = hg.peer(repo, opts, dest)
1168 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1168 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1169 heads = revs and map(repo.lookup, revs) or revs
1169 heads = revs and map(repo.lookup, revs) or revs
1170 outgoing = discovery.findcommonoutgoing(repo, other,
1170 outgoing = discovery.findcommonoutgoing(repo, other,
1171 onlyheads=heads,
1171 onlyheads=heads,
1172 force=opts.get('force'),
1172 force=opts.get('force'),
1173 portable=True)
1173 portable=True)
1174 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1174 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1175 if not cg:
1175 if not cg:
1176 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1176 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1177 return 1
1177 return 1
1178
1178
1179 changegroup.writebundle(cg, fname, bundletype)
1179 changegroup.writebundle(cg, fname, bundletype)
1180
1180
1181 @command('cat',
1181 @command('cat',
1182 [('o', 'output', '',
1182 [('o', 'output', '',
1183 _('print output to file with formatted name'), _('FORMAT')),
1183 _('print output to file with formatted name'), _('FORMAT')),
1184 ('r', 'rev', '', _('print the given revision'), _('REV')),
1184 ('r', 'rev', '', _('print the given revision'), _('REV')),
1185 ('', 'decode', None, _('apply any matching decode filter')),
1185 ('', 'decode', None, _('apply any matching decode filter')),
1186 ] + walkopts,
1186 ] + walkopts,
1187 _('[OPTION]... FILE...'),
1187 _('[OPTION]... FILE...'),
1188 inferrepo=True)
1188 inferrepo=True)
1189 def cat(ui, repo, file1, *pats, **opts):
1189 def cat(ui, repo, file1, *pats, **opts):
1190 """output the current or given revision of files
1190 """output the current or given revision of files
1191
1191
1192 Print the specified files as they were at the given revision. If
1192 Print the specified files as they were at the given revision. If
1193 no revision is given, the parent of the working directory is used.
1193 no revision is given, the parent of the working directory is used.
1194
1194
1195 Output may be to a file, in which case the name of the file is
1195 Output may be to a file, in which case the name of the file is
1196 given using a format string. The formatting rules as follows:
1196 given using a format string. The formatting rules as follows:
1197
1197
1198 :``%%``: literal "%" character
1198 :``%%``: literal "%" character
1199 :``%s``: basename of file being printed
1199 :``%s``: basename of file being printed
1200 :``%d``: dirname of file being printed, or '.' if in repository root
1200 :``%d``: dirname of file being printed, or '.' if in repository root
1201 :``%p``: root-relative path name of file being printed
1201 :``%p``: root-relative path name of file being printed
1202 :``%H``: changeset hash (40 hexadecimal digits)
1202 :``%H``: changeset hash (40 hexadecimal digits)
1203 :``%R``: changeset revision number
1203 :``%R``: changeset revision number
1204 :``%h``: short-form changeset hash (12 hexadecimal digits)
1204 :``%h``: short-form changeset hash (12 hexadecimal digits)
1205 :``%r``: zero-padded changeset revision number
1205 :``%r``: zero-padded changeset revision number
1206 :``%b``: basename of the exporting repository
1206 :``%b``: basename of the exporting repository
1207
1207
1208 Returns 0 on success.
1208 Returns 0 on success.
1209 """
1209 """
1210 ctx = scmutil.revsingle(repo, opts.get('rev'))
1210 ctx = scmutil.revsingle(repo, opts.get('rev'))
1211 m = scmutil.match(ctx, (file1,) + pats, opts)
1211 m = scmutil.match(ctx, (file1,) + pats, opts)
1212
1212
1213 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1213 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1214
1214
1215 @command('^clone',
1215 @command('^clone',
1216 [('U', 'noupdate', None,
1216 [('U', 'noupdate', None,
1217 _('the clone will include an empty working copy (only a repository)')),
1217 _('the clone will include an empty working copy (only a repository)')),
1218 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1218 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1219 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1219 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1220 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1220 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1221 ('', 'pull', None, _('use pull protocol to copy metadata')),
1221 ('', 'pull', None, _('use pull protocol to copy metadata')),
1222 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1222 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1223 ] + remoteopts,
1223 ] + remoteopts,
1224 _('[OPTION]... SOURCE [DEST]'),
1224 _('[OPTION]... SOURCE [DEST]'),
1225 norepo=True)
1225 norepo=True)
1226 def clone(ui, source, dest=None, **opts):
1226 def clone(ui, source, dest=None, **opts):
1227 """make a copy of an existing repository
1227 """make a copy of an existing repository
1228
1228
1229 Create a copy of an existing repository in a new directory.
1229 Create a copy of an existing repository in a new directory.
1230
1230
1231 If no destination directory name is specified, it defaults to the
1231 If no destination directory name is specified, it defaults to the
1232 basename of the source.
1232 basename of the source.
1233
1233
1234 The location of the source is added to the new repository's
1234 The location of the source is added to the new repository's
1235 ``.hg/hgrc`` file, as the default to be used for future pulls.
1235 ``.hg/hgrc`` file, as the default to be used for future pulls.
1236
1236
1237 Only local paths and ``ssh://`` URLs are supported as
1237 Only local paths and ``ssh://`` URLs are supported as
1238 destinations. For ``ssh://`` destinations, no working directory or
1238 destinations. For ``ssh://`` destinations, no working directory or
1239 ``.hg/hgrc`` will be created on the remote side.
1239 ``.hg/hgrc`` will be created on the remote side.
1240
1240
1241 To pull only a subset of changesets, specify one or more revisions
1241 To pull only a subset of changesets, specify one or more revisions
1242 identifiers with -r/--rev or branches with -b/--branch. The
1242 identifiers with -r/--rev or branches with -b/--branch. The
1243 resulting clone will contain only the specified changesets and
1243 resulting clone will contain only the specified changesets and
1244 their ancestors. These options (or 'clone src#rev dest') imply
1244 their ancestors. These options (or 'clone src#rev dest') imply
1245 --pull, even for local source repositories. Note that specifying a
1245 --pull, even for local source repositories. Note that specifying a
1246 tag will include the tagged changeset but not the changeset
1246 tag will include the tagged changeset but not the changeset
1247 containing the tag.
1247 containing the tag.
1248
1248
1249 If the source repository has a bookmark called '@' set, that
1249 If the source repository has a bookmark called '@' set, that
1250 revision will be checked out in the new repository by default.
1250 revision will be checked out in the new repository by default.
1251
1251
1252 To check out a particular version, use -u/--update, or
1252 To check out a particular version, use -u/--update, or
1253 -U/--noupdate to create a clone with no working directory.
1253 -U/--noupdate to create a clone with no working directory.
1254
1254
1255 .. container:: verbose
1255 .. container:: verbose
1256
1256
1257 For efficiency, hardlinks are used for cloning whenever the
1257 For efficiency, hardlinks are used for cloning whenever the
1258 source and destination are on the same filesystem (note this
1258 source and destination are on the same filesystem (note this
1259 applies only to the repository data, not to the working
1259 applies only to the repository data, not to the working
1260 directory). Some filesystems, such as AFS, implement hardlinking
1260 directory). Some filesystems, such as AFS, implement hardlinking
1261 incorrectly, but do not report errors. In these cases, use the
1261 incorrectly, but do not report errors. In these cases, use the
1262 --pull option to avoid hardlinking.
1262 --pull option to avoid hardlinking.
1263
1263
1264 In some cases, you can clone repositories and the working
1264 In some cases, you can clone repositories and the working
1265 directory using full hardlinks with ::
1265 directory using full hardlinks with ::
1266
1266
1267 $ cp -al REPO REPOCLONE
1267 $ cp -al REPO REPOCLONE
1268
1268
1269 This is the fastest way to clone, but it is not always safe. The
1269 This is the fastest way to clone, but it is not always safe. The
1270 operation is not atomic (making sure REPO is not modified during
1270 operation is not atomic (making sure REPO is not modified during
1271 the operation is up to you) and you have to make sure your
1271 the operation is up to you) and you have to make sure your
1272 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1272 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1273 so). Also, this is not compatible with certain extensions that
1273 so). Also, this is not compatible with certain extensions that
1274 place their metadata under the .hg directory, such as mq.
1274 place their metadata under the .hg directory, such as mq.
1275
1275
1276 Mercurial will update the working directory to the first applicable
1276 Mercurial will update the working directory to the first applicable
1277 revision from this list:
1277 revision from this list:
1278
1278
1279 a) null if -U or the source repository has no changesets
1279 a) null if -U or the source repository has no changesets
1280 b) if -u . and the source repository is local, the first parent of
1280 b) if -u . and the source repository is local, the first parent of
1281 the source repository's working directory
1281 the source repository's working directory
1282 c) the changeset specified with -u (if a branch name, this means the
1282 c) the changeset specified with -u (if a branch name, this means the
1283 latest head of that branch)
1283 latest head of that branch)
1284 d) the changeset specified with -r
1284 d) the changeset specified with -r
1285 e) the tipmost head specified with -b
1285 e) the tipmost head specified with -b
1286 f) the tipmost head specified with the url#branch source syntax
1286 f) the tipmost head specified with the url#branch source syntax
1287 g) the revision marked with the '@' bookmark, if present
1287 g) the revision marked with the '@' bookmark, if present
1288 h) the tipmost head of the default branch
1288 h) the tipmost head of the default branch
1289 i) tip
1289 i) tip
1290
1290
1291 Examples:
1291 Examples:
1292
1292
1293 - clone a remote repository to a new directory named hg/::
1293 - clone a remote repository to a new directory named hg/::
1294
1294
1295 hg clone http://selenic.com/hg
1295 hg clone http://selenic.com/hg
1296
1296
1297 - create a lightweight local clone::
1297 - create a lightweight local clone::
1298
1298
1299 hg clone project/ project-feature/
1299 hg clone project/ project-feature/
1300
1300
1301 - clone from an absolute path on an ssh server (note double-slash)::
1301 - clone from an absolute path on an ssh server (note double-slash)::
1302
1302
1303 hg clone ssh://user@server//home/projects/alpha/
1303 hg clone ssh://user@server//home/projects/alpha/
1304
1304
1305 - do a high-speed clone over a LAN while checking out a
1305 - do a high-speed clone over a LAN while checking out a
1306 specified version::
1306 specified version::
1307
1307
1308 hg clone --uncompressed http://server/repo -u 1.5
1308 hg clone --uncompressed http://server/repo -u 1.5
1309
1309
1310 - create a repository without changesets after a particular revision::
1310 - create a repository without changesets after a particular revision::
1311
1311
1312 hg clone -r 04e544 experimental/ good/
1312 hg clone -r 04e544 experimental/ good/
1313
1313
1314 - clone (and track) a particular named branch::
1314 - clone (and track) a particular named branch::
1315
1315
1316 hg clone http://selenic.com/hg#stable
1316 hg clone http://selenic.com/hg#stable
1317
1317
1318 See :hg:`help urls` for details on specifying URLs.
1318 See :hg:`help urls` for details on specifying URLs.
1319
1319
1320 Returns 0 on success.
1320 Returns 0 on success.
1321 """
1321 """
1322 if opts.get('noupdate') and opts.get('updaterev'):
1322 if opts.get('noupdate') and opts.get('updaterev'):
1323 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1323 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1324
1324
1325 r = hg.clone(ui, opts, source, dest,
1325 r = hg.clone(ui, opts, source, dest,
1326 pull=opts.get('pull'),
1326 pull=opts.get('pull'),
1327 stream=opts.get('uncompressed'),
1327 stream=opts.get('uncompressed'),
1328 rev=opts.get('rev'),
1328 rev=opts.get('rev'),
1329 update=opts.get('updaterev') or not opts.get('noupdate'),
1329 update=opts.get('updaterev') or not opts.get('noupdate'),
1330 branch=opts.get('branch'))
1330 branch=opts.get('branch'))
1331
1331
1332 return r is None
1332 return r is None
1333
1333
1334 @command('^commit|ci',
1334 @command('^commit|ci',
1335 [('A', 'addremove', None,
1335 [('A', 'addremove', None,
1336 _('mark new/missing files as added/removed before committing')),
1336 _('mark new/missing files as added/removed before committing')),
1337 ('', 'close-branch', None,
1337 ('', 'close-branch', None,
1338 _('mark a branch as closed, hiding it from the branch list')),
1338 _('mark a branch as closed, hiding it from the branch list')),
1339 ('', 'amend', None, _('amend the parent of the working dir')),
1339 ('', 'amend', None, _('amend the parent of the working dir')),
1340 ('s', 'secret', None, _('use the secret phase for committing')),
1340 ('s', 'secret', None, _('use the secret phase for committing')),
1341 ('e', 'edit', None,
1341 ('e', 'edit', None,
1342 _('further edit commit message already specified')),
1342 _('further edit commit message already specified')),
1343 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1343 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1344 _('[OPTION]... [FILE]...'),
1344 _('[OPTION]... [FILE]...'),
1345 inferrepo=True)
1345 inferrepo=True)
1346 def commit(ui, repo, *pats, **opts):
1346 def commit(ui, repo, *pats, **opts):
1347 """commit the specified files or all outstanding changes
1347 """commit the specified files or all outstanding changes
1348
1348
1349 Commit changes to the given files into the repository. Unlike a
1349 Commit changes to the given files into the repository. Unlike a
1350 centralized SCM, this operation is a local operation. See
1350 centralized SCM, this operation is a local operation. See
1351 :hg:`push` for a way to actively distribute your changes.
1351 :hg:`push` for a way to actively distribute your changes.
1352
1352
1353 If a list of files is omitted, all changes reported by :hg:`status`
1353 If a list of files is omitted, all changes reported by :hg:`status`
1354 will be committed.
1354 will be committed.
1355
1355
1356 If you are committing the result of a merge, do not provide any
1356 If you are committing the result of a merge, do not provide any
1357 filenames or -I/-X filters.
1357 filenames or -I/-X filters.
1358
1358
1359 If no commit message is specified, Mercurial starts your
1359 If no commit message is specified, Mercurial starts your
1360 configured editor where you can enter a message. In case your
1360 configured editor where you can enter a message. In case your
1361 commit fails, you will find a backup of your message in
1361 commit fails, you will find a backup of your message in
1362 ``.hg/last-message.txt``.
1362 ``.hg/last-message.txt``.
1363
1363
1364 The --amend flag can be used to amend the parent of the
1364 The --amend flag can be used to amend the parent of the
1365 working directory with a new commit that contains the changes
1365 working directory with a new commit that contains the changes
1366 in the parent in addition to those currently reported by :hg:`status`,
1366 in the parent in addition to those currently reported by :hg:`status`,
1367 if there are any. The old commit is stored in a backup bundle in
1367 if there are any. The old commit is stored in a backup bundle in
1368 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1368 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1369 on how to restore it).
1369 on how to restore it).
1370
1370
1371 Message, user and date are taken from the amended commit unless
1371 Message, user and date are taken from the amended commit unless
1372 specified. When a message isn't specified on the command line,
1372 specified. When a message isn't specified on the command line,
1373 the editor will open with the message of the amended commit.
1373 the editor will open with the message of the amended commit.
1374
1374
1375 It is not possible to amend public changesets (see :hg:`help phases`)
1375 It is not possible to amend public changesets (see :hg:`help phases`)
1376 or changesets that have children.
1376 or changesets that have children.
1377
1377
1378 See :hg:`help dates` for a list of formats valid for -d/--date.
1378 See :hg:`help dates` for a list of formats valid for -d/--date.
1379
1379
1380 Returns 0 on success, 1 if nothing changed.
1380 Returns 0 on success, 1 if nothing changed.
1381 """
1381 """
1382 if opts.get('subrepos'):
1382 if opts.get('subrepos'):
1383 if opts.get('amend'):
1383 if opts.get('amend'):
1384 raise util.Abort(_('cannot amend with --subrepos'))
1384 raise util.Abort(_('cannot amend with --subrepos'))
1385 # Let --subrepos on the command line override config setting.
1385 # Let --subrepos on the command line override config setting.
1386 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1386 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1387
1387
1388 # Save this for restoring it later
1388 # Save this for restoring it later
1389 oldcommitphase = ui.config('phases', 'new-commit')
1389 oldcommitphase = ui.config('phases', 'new-commit')
1390
1390
1391 cmdutil.checkunfinished(repo, commit=True)
1391 cmdutil.checkunfinished(repo, commit=True)
1392
1392
1393 branch = repo[None].branch()
1393 branch = repo[None].branch()
1394 bheads = repo.branchheads(branch)
1394 bheads = repo.branchheads(branch)
1395
1395
1396 extra = {}
1396 extra = {}
1397 if opts.get('close_branch'):
1397 if opts.get('close_branch'):
1398 extra['close'] = 1
1398 extra['close'] = 1
1399
1399
1400 if not bheads:
1400 if not bheads:
1401 raise util.Abort(_('can only close branch heads'))
1401 raise util.Abort(_('can only close branch heads'))
1402 elif opts.get('amend'):
1402 elif opts.get('amend'):
1403 if repo.parents()[0].p1().branch() != branch and \
1403 if repo.parents()[0].p1().branch() != branch and \
1404 repo.parents()[0].p2().branch() != branch:
1404 repo.parents()[0].p2().branch() != branch:
1405 raise util.Abort(_('can only close branch heads'))
1405 raise util.Abort(_('can only close branch heads'))
1406
1406
1407 if opts.get('amend'):
1407 if opts.get('amend'):
1408 if ui.configbool('ui', 'commitsubrepos'):
1408 if ui.configbool('ui', 'commitsubrepos'):
1409 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1409 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1410
1410
1411 old = repo['.']
1411 old = repo['.']
1412 if old.phase() == phases.public:
1412 if old.phase() == phases.public:
1413 raise util.Abort(_('cannot amend public changesets'))
1413 raise util.Abort(_('cannot amend public changesets'))
1414 if len(repo[None].parents()) > 1:
1414 if len(repo[None].parents()) > 1:
1415 raise util.Abort(_('cannot amend while merging'))
1415 raise util.Abort(_('cannot amend while merging'))
1416 if (not obsolete._enabled) and old.children():
1416 if (not obsolete._enabled) and old.children():
1417 raise util.Abort(_('cannot amend changeset with children'))
1417 raise util.Abort(_('cannot amend changeset with children'))
1418
1418
1419 # commitfunc is used only for temporary amend commit by cmdutil.amend
1419 # commitfunc is used only for temporary amend commit by cmdutil.amend
1420 def commitfunc(ui, repo, message, match, opts):
1420 def commitfunc(ui, repo, message, match, opts):
1421 return repo.commit(message,
1421 return repo.commit(message,
1422 opts.get('user') or old.user(),
1422 opts.get('user') or old.user(),
1423 opts.get('date') or old.date(),
1423 opts.get('date') or old.date(),
1424 match,
1424 match,
1425 extra=extra)
1425 extra=extra)
1426
1426
1427 current = repo._bookmarkcurrent
1427 current = repo._bookmarkcurrent
1428 marks = old.bookmarks()
1428 marks = old.bookmarks()
1429 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1429 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1430 if node == old.node():
1430 if node == old.node():
1431 ui.status(_("nothing changed\n"))
1431 ui.status(_("nothing changed\n"))
1432 return 1
1432 return 1
1433 elif marks:
1433 elif marks:
1434 ui.debug('moving bookmarks %r from %s to %s\n' %
1434 ui.debug('moving bookmarks %r from %s to %s\n' %
1435 (marks, old.hex(), hex(node)))
1435 (marks, old.hex(), hex(node)))
1436 newmarks = repo._bookmarks
1436 newmarks = repo._bookmarks
1437 for bm in marks:
1437 for bm in marks:
1438 newmarks[bm] = node
1438 newmarks[bm] = node
1439 if bm == current:
1439 if bm == current:
1440 bookmarks.setcurrent(repo, bm)
1440 bookmarks.setcurrent(repo, bm)
1441 newmarks.write()
1441 newmarks.write()
1442 else:
1442 else:
1443 def commitfunc(ui, repo, message, match, opts):
1443 def commitfunc(ui, repo, message, match, opts):
1444 try:
1444 try:
1445 if opts.get('secret'):
1445 if opts.get('secret'):
1446 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1446 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1447 # Propagate to subrepos
1447 # Propagate to subrepos
1448 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1448 repo.baseui.setconfig('phases', 'new-commit', 'secret',
1449 'commit')
1449 'commit')
1450
1450
1451 return repo.commit(message, opts.get('user'), opts.get('date'),
1451 return repo.commit(message, opts.get('user'), opts.get('date'),
1452 match,
1452 match,
1453 editor=cmdutil.getcommiteditor(**opts),
1453 editor=cmdutil.getcommiteditor(**opts),
1454 extra=extra)
1454 extra=extra)
1455 finally:
1455 finally:
1456 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1456 ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
1457 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1457 repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
1458 'commit')
1458 'commit')
1459
1459
1460
1460
1461 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1461 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1462
1462
1463 if not node:
1463 if not node:
1464 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1464 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1465 if stat[3]:
1465 if stat[3]:
1466 ui.status(_("nothing changed (%d missing files, see "
1466 ui.status(_("nothing changed (%d missing files, see "
1467 "'hg status')\n") % len(stat[3]))
1467 "'hg status')\n") % len(stat[3]))
1468 else:
1468 else:
1469 ui.status(_("nothing changed\n"))
1469 ui.status(_("nothing changed\n"))
1470 return 1
1470 return 1
1471
1471
1472 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1472 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1473
1473
1474 @command('config|showconfig|debugconfig',
1474 @command('config|showconfig|debugconfig',
1475 [('u', 'untrusted', None, _('show untrusted configuration options')),
1475 [('u', 'untrusted', None, _('show untrusted configuration options')),
1476 ('e', 'edit', None, _('edit user config')),
1476 ('e', 'edit', None, _('edit user config')),
1477 ('l', 'local', None, _('edit repository config')),
1477 ('l', 'local', None, _('edit repository config')),
1478 ('g', 'global', None, _('edit global config'))],
1478 ('g', 'global', None, _('edit global config'))],
1479 _('[-u] [NAME]...'),
1479 _('[-u] [NAME]...'),
1480 optionalrepo=True)
1480 optionalrepo=True)
1481 def config(ui, repo, *values, **opts):
1481 def config(ui, repo, *values, **opts):
1482 """show combined config settings from all hgrc files
1482 """show combined config settings from all hgrc files
1483
1483
1484 With no arguments, print names and values of all config items.
1484 With no arguments, print names and values of all config items.
1485
1485
1486 With one argument of the form section.name, print just the value
1486 With one argument of the form section.name, print just the value
1487 of that config item.
1487 of that config item.
1488
1488
1489 With multiple arguments, print names and values of all config
1489 With multiple arguments, print names and values of all config
1490 items with matching section names.
1490 items with matching section names.
1491
1491
1492 With --edit, start an editor on the user-level config file. With
1492 With --edit, start an editor on the user-level config file. With
1493 --global, edit the system-wide config file. With --local, edit the
1493 --global, edit the system-wide config file. With --local, edit the
1494 repository-level config file.
1494 repository-level config file.
1495
1495
1496 With --debug, the source (filename and line number) is printed
1496 With --debug, the source (filename and line number) is printed
1497 for each config item.
1497 for each config item.
1498
1498
1499 See :hg:`help config` for more information about config files.
1499 See :hg:`help config` for more information about config files.
1500
1500
1501 Returns 0 on success.
1501 Returns 0 on success.
1502
1502
1503 """
1503 """
1504
1504
1505 if opts.get('edit') or opts.get('local') or opts.get('global'):
1505 if opts.get('edit') or opts.get('local') or opts.get('global'):
1506 if opts.get('local') and opts.get('global'):
1506 if opts.get('local') and opts.get('global'):
1507 raise util.Abort(_("can't use --local and --global together"))
1507 raise util.Abort(_("can't use --local and --global together"))
1508
1508
1509 if opts.get('local'):
1509 if opts.get('local'):
1510 if not repo:
1510 if not repo:
1511 raise util.Abort(_("can't use --local outside a repository"))
1511 raise util.Abort(_("can't use --local outside a repository"))
1512 paths = [repo.join('hgrc')]
1512 paths = [repo.join('hgrc')]
1513 elif opts.get('global'):
1513 elif opts.get('global'):
1514 paths = scmutil.systemrcpath()
1514 paths = scmutil.systemrcpath()
1515 else:
1515 else:
1516 paths = scmutil.userrcpath()
1516 paths = scmutil.userrcpath()
1517
1517
1518 for f in paths:
1518 for f in paths:
1519 if os.path.exists(f):
1519 if os.path.exists(f):
1520 break
1520 break
1521 else:
1521 else:
1522 f = paths[0]
1522 f = paths[0]
1523 fp = open(f, "w")
1523 fp = open(f, "w")
1524 fp.write(
1524 fp.write(
1525 '# example config (see "hg help config" for more info)\n'
1525 '# example config (see "hg help config" for more info)\n'
1526 '\n'
1526 '\n'
1527 '[ui]\n'
1527 '[ui]\n'
1528 '# name and email, e.g.\n'
1528 '# name and email, e.g.\n'
1529 '# username = Jane Doe <jdoe@example.com>\n'
1529 '# username = Jane Doe <jdoe@example.com>\n'
1530 'username =\n'
1530 'username =\n'
1531 '\n'
1531 '\n'
1532 '[extensions]\n'
1532 '[extensions]\n'
1533 '# uncomment these lines to enable some popular extensions\n'
1533 '# uncomment these lines to enable some popular extensions\n'
1534 '# (see "hg help extensions" for more info)\n'
1534 '# (see "hg help extensions" for more info)\n'
1535 '# pager =\n'
1535 '# pager =\n'
1536 '# progress =\n'
1536 '# progress =\n'
1537 '# color =\n')
1537 '# color =\n')
1538 fp.close()
1538 fp.close()
1539
1539
1540 editor = ui.geteditor()
1540 editor = ui.geteditor()
1541 util.system("%s \"%s\"" % (editor, f),
1541 util.system("%s \"%s\"" % (editor, f),
1542 onerr=util.Abort, errprefix=_("edit failed"),
1542 onerr=util.Abort, errprefix=_("edit failed"),
1543 out=ui.fout)
1543 out=ui.fout)
1544 return
1544 return
1545
1545
1546 for f in scmutil.rcpath():
1546 for f in scmutil.rcpath():
1547 ui.debug('read config from: %s\n' % f)
1547 ui.debug('read config from: %s\n' % f)
1548 untrusted = bool(opts.get('untrusted'))
1548 untrusted = bool(opts.get('untrusted'))
1549 if values:
1549 if values:
1550 sections = [v for v in values if '.' not in v]
1550 sections = [v for v in values if '.' not in v]
1551 items = [v for v in values if '.' in v]
1551 items = [v for v in values if '.' in v]
1552 if len(items) > 1 or items and sections:
1552 if len(items) > 1 or items and sections:
1553 raise util.Abort(_('only one config item permitted'))
1553 raise util.Abort(_('only one config item permitted'))
1554 for section, name, value in ui.walkconfig(untrusted=untrusted):
1554 for section, name, value in ui.walkconfig(untrusted=untrusted):
1555 value = str(value).replace('\n', '\\n')
1555 value = str(value).replace('\n', '\\n')
1556 sectname = section + '.' + name
1556 sectname = section + '.' + name
1557 if values:
1557 if values:
1558 for v in values:
1558 for v in values:
1559 if v == section:
1559 if v == section:
1560 ui.debug('%s: ' %
1560 ui.debug('%s: ' %
1561 ui.configsource(section, name, untrusted))
1561 ui.configsource(section, name, untrusted))
1562 ui.write('%s=%s\n' % (sectname, value))
1562 ui.write('%s=%s\n' % (sectname, value))
1563 elif v == sectname:
1563 elif v == sectname:
1564 ui.debug('%s: ' %
1564 ui.debug('%s: ' %
1565 ui.configsource(section, name, untrusted))
1565 ui.configsource(section, name, untrusted))
1566 ui.write(value, '\n')
1566 ui.write(value, '\n')
1567 else:
1567 else:
1568 ui.debug('%s: ' %
1568 ui.debug('%s: ' %
1569 ui.configsource(section, name, untrusted))
1569 ui.configsource(section, name, untrusted))
1570 ui.write('%s=%s\n' % (sectname, value))
1570 ui.write('%s=%s\n' % (sectname, value))
1571
1571
1572 @command('copy|cp',
1572 @command('copy|cp',
1573 [('A', 'after', None, _('record a copy that has already occurred')),
1573 [('A', 'after', None, _('record a copy that has already occurred')),
1574 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1574 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1575 ] + walkopts + dryrunopts,
1575 ] + walkopts + dryrunopts,
1576 _('[OPTION]... [SOURCE]... DEST'))
1576 _('[OPTION]... [SOURCE]... DEST'))
1577 def copy(ui, repo, *pats, **opts):
1577 def copy(ui, repo, *pats, **opts):
1578 """mark files as copied for the next commit
1578 """mark files as copied for the next commit
1579
1579
1580 Mark dest as having copies of source files. If dest is a
1580 Mark dest as having copies of source files. If dest is a
1581 directory, copies are put in that directory. If dest is a file,
1581 directory, copies are put in that directory. If dest is a file,
1582 the source must be a single file.
1582 the source must be a single file.
1583
1583
1584 By default, this command copies the contents of files as they
1584 By default, this command copies the contents of files as they
1585 exist in the working directory. If invoked with -A/--after, the
1585 exist in the working directory. If invoked with -A/--after, the
1586 operation is recorded, but no copying is performed.
1586 operation is recorded, but no copying is performed.
1587
1587
1588 This command takes effect with the next commit. To undo a copy
1588 This command takes effect with the next commit. To undo a copy
1589 before that, see :hg:`revert`.
1589 before that, see :hg:`revert`.
1590
1590
1591 Returns 0 on success, 1 if errors are encountered.
1591 Returns 0 on success, 1 if errors are encountered.
1592 """
1592 """
1593 wlock = repo.wlock(False)
1593 wlock = repo.wlock(False)
1594 try:
1594 try:
1595 return cmdutil.copy(ui, repo, pats, opts)
1595 return cmdutil.copy(ui, repo, pats, opts)
1596 finally:
1596 finally:
1597 wlock.release()
1597 wlock.release()
1598
1598
1599 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1599 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1600 def debugancestor(ui, repo, *args):
1600 def debugancestor(ui, repo, *args):
1601 """find the ancestor revision of two revisions in a given index"""
1601 """find the ancestor revision of two revisions in a given index"""
1602 if len(args) == 3:
1602 if len(args) == 3:
1603 index, rev1, rev2 = args
1603 index, rev1, rev2 = args
1604 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1604 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1605 lookup = r.lookup
1605 lookup = r.lookup
1606 elif len(args) == 2:
1606 elif len(args) == 2:
1607 if not repo:
1607 if not repo:
1608 raise util.Abort(_("there is no Mercurial repository here "
1608 raise util.Abort(_("there is no Mercurial repository here "
1609 "(.hg not found)"))
1609 "(.hg not found)"))
1610 rev1, rev2 = args
1610 rev1, rev2 = args
1611 r = repo.changelog
1611 r = repo.changelog
1612 lookup = repo.lookup
1612 lookup = repo.lookup
1613 else:
1613 else:
1614 raise util.Abort(_('either two or three arguments required'))
1614 raise util.Abort(_('either two or three arguments required'))
1615 a = r.ancestor(lookup(rev1), lookup(rev2))
1615 a = r.ancestor(lookup(rev1), lookup(rev2))
1616 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1616 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1617
1617
1618 @command('debugbuilddag',
1618 @command('debugbuilddag',
1619 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1619 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1620 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1620 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1621 ('n', 'new-file', None, _('add new file at each rev'))],
1621 ('n', 'new-file', None, _('add new file at each rev'))],
1622 _('[OPTION]... [TEXT]'))
1622 _('[OPTION]... [TEXT]'))
1623 def debugbuilddag(ui, repo, text=None,
1623 def debugbuilddag(ui, repo, text=None,
1624 mergeable_file=False,
1624 mergeable_file=False,
1625 overwritten_file=False,
1625 overwritten_file=False,
1626 new_file=False):
1626 new_file=False):
1627 """builds a repo with a given DAG from scratch in the current empty repo
1627 """builds a repo with a given DAG from scratch in the current empty repo
1628
1628
1629 The description of the DAG is read from stdin if not given on the
1629 The description of the DAG is read from stdin if not given on the
1630 command line.
1630 command line.
1631
1631
1632 Elements:
1632 Elements:
1633
1633
1634 - "+n" is a linear run of n nodes based on the current default parent
1634 - "+n" is a linear run of n nodes based on the current default parent
1635 - "." is a single node based on the current default parent
1635 - "." is a single node based on the current default parent
1636 - "$" resets the default parent to null (implied at the start);
1636 - "$" resets the default parent to null (implied at the start);
1637 otherwise the default parent is always the last node created
1637 otherwise the default parent is always the last node created
1638 - "<p" sets the default parent to the backref p
1638 - "<p" sets the default parent to the backref p
1639 - "*p" is a fork at parent p, which is a backref
1639 - "*p" is a fork at parent p, which is a backref
1640 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1640 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1641 - "/p2" is a merge of the preceding node and p2
1641 - "/p2" is a merge of the preceding node and p2
1642 - ":tag" defines a local tag for the preceding node
1642 - ":tag" defines a local tag for the preceding node
1643 - "@branch" sets the named branch for subsequent nodes
1643 - "@branch" sets the named branch for subsequent nodes
1644 - "#...\\n" is a comment up to the end of the line
1644 - "#...\\n" is a comment up to the end of the line
1645
1645
1646 Whitespace between the above elements is ignored.
1646 Whitespace between the above elements is ignored.
1647
1647
1648 A backref is either
1648 A backref is either
1649
1649
1650 - a number n, which references the node curr-n, where curr is the current
1650 - a number n, which references the node curr-n, where curr is the current
1651 node, or
1651 node, or
1652 - the name of a local tag you placed earlier using ":tag", or
1652 - the name of a local tag you placed earlier using ":tag", or
1653 - empty to denote the default parent.
1653 - empty to denote the default parent.
1654
1654
1655 All string valued-elements are either strictly alphanumeric, or must
1655 All string valued-elements are either strictly alphanumeric, or must
1656 be enclosed in double quotes ("..."), with "\\" as escape character.
1656 be enclosed in double quotes ("..."), with "\\" as escape character.
1657 """
1657 """
1658
1658
1659 if text is None:
1659 if text is None:
1660 ui.status(_("reading DAG from stdin\n"))
1660 ui.status(_("reading DAG from stdin\n"))
1661 text = ui.fin.read()
1661 text = ui.fin.read()
1662
1662
1663 cl = repo.changelog
1663 cl = repo.changelog
1664 if len(cl) > 0:
1664 if len(cl) > 0:
1665 raise util.Abort(_('repository is not empty'))
1665 raise util.Abort(_('repository is not empty'))
1666
1666
1667 # determine number of revs in DAG
1667 # determine number of revs in DAG
1668 total = 0
1668 total = 0
1669 for type, data in dagparser.parsedag(text):
1669 for type, data in dagparser.parsedag(text):
1670 if type == 'n':
1670 if type == 'n':
1671 total += 1
1671 total += 1
1672
1672
1673 if mergeable_file:
1673 if mergeable_file:
1674 linesperrev = 2
1674 linesperrev = 2
1675 # make a file with k lines per rev
1675 # make a file with k lines per rev
1676 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1676 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1677 initialmergedlines.append("")
1677 initialmergedlines.append("")
1678
1678
1679 tags = []
1679 tags = []
1680
1680
1681 lock = tr = None
1681 lock = tr = None
1682 try:
1682 try:
1683 lock = repo.lock()
1683 lock = repo.lock()
1684 tr = repo.transaction("builddag")
1684 tr = repo.transaction("builddag")
1685
1685
1686 at = -1
1686 at = -1
1687 atbranch = 'default'
1687 atbranch = 'default'
1688 nodeids = []
1688 nodeids = []
1689 id = 0
1689 id = 0
1690 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1690 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1691 for type, data in dagparser.parsedag(text):
1691 for type, data in dagparser.parsedag(text):
1692 if type == 'n':
1692 if type == 'n':
1693 ui.note(('node %s\n' % str(data)))
1693 ui.note(('node %s\n' % str(data)))
1694 id, ps = data
1694 id, ps = data
1695
1695
1696 files = []
1696 files = []
1697 fctxs = {}
1697 fctxs = {}
1698
1698
1699 p2 = None
1699 p2 = None
1700 if mergeable_file:
1700 if mergeable_file:
1701 fn = "mf"
1701 fn = "mf"
1702 p1 = repo[ps[0]]
1702 p1 = repo[ps[0]]
1703 if len(ps) > 1:
1703 if len(ps) > 1:
1704 p2 = repo[ps[1]]
1704 p2 = repo[ps[1]]
1705 pa = p1.ancestor(p2)
1705 pa = p1.ancestor(p2)
1706 base, local, other = [x[fn].data() for x in (pa, p1,
1706 base, local, other = [x[fn].data() for x in (pa, p1,
1707 p2)]
1707 p2)]
1708 m3 = simplemerge.Merge3Text(base, local, other)
1708 m3 = simplemerge.Merge3Text(base, local, other)
1709 ml = [l.strip() for l in m3.merge_lines()]
1709 ml = [l.strip() for l in m3.merge_lines()]
1710 ml.append("")
1710 ml.append("")
1711 elif at > 0:
1711 elif at > 0:
1712 ml = p1[fn].data().split("\n")
1712 ml = p1[fn].data().split("\n")
1713 else:
1713 else:
1714 ml = initialmergedlines
1714 ml = initialmergedlines
1715 ml[id * linesperrev] += " r%i" % id
1715 ml[id * linesperrev] += " r%i" % id
1716 mergedtext = "\n".join(ml)
1716 mergedtext = "\n".join(ml)
1717 files.append(fn)
1717 files.append(fn)
1718 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1718 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1719
1719
1720 if overwritten_file:
1720 if overwritten_file:
1721 fn = "of"
1721 fn = "of"
1722 files.append(fn)
1722 files.append(fn)
1723 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1723 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1724
1724
1725 if new_file:
1725 if new_file:
1726 fn = "nf%i" % id
1726 fn = "nf%i" % id
1727 files.append(fn)
1727 files.append(fn)
1728 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1728 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1729 if len(ps) > 1:
1729 if len(ps) > 1:
1730 if not p2:
1730 if not p2:
1731 p2 = repo[ps[1]]
1731 p2 = repo[ps[1]]
1732 for fn in p2:
1732 for fn in p2:
1733 if fn.startswith("nf"):
1733 if fn.startswith("nf"):
1734 files.append(fn)
1734 files.append(fn)
1735 fctxs[fn] = p2[fn]
1735 fctxs[fn] = p2[fn]
1736
1736
1737 def fctxfn(repo, cx, path):
1737 def fctxfn(repo, cx, path):
1738 return fctxs.get(path)
1738 return fctxs.get(path)
1739
1739
1740 if len(ps) == 0 or ps[0] < 0:
1740 if len(ps) == 0 or ps[0] < 0:
1741 pars = [None, None]
1741 pars = [None, None]
1742 elif len(ps) == 1:
1742 elif len(ps) == 1:
1743 pars = [nodeids[ps[0]], None]
1743 pars = [nodeids[ps[0]], None]
1744 else:
1744 else:
1745 pars = [nodeids[p] for p in ps]
1745 pars = [nodeids[p] for p in ps]
1746 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1746 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1747 date=(id, 0),
1747 date=(id, 0),
1748 user="debugbuilddag",
1748 user="debugbuilddag",
1749 extra={'branch': atbranch})
1749 extra={'branch': atbranch})
1750 nodeid = repo.commitctx(cx)
1750 nodeid = repo.commitctx(cx)
1751 nodeids.append(nodeid)
1751 nodeids.append(nodeid)
1752 at = id
1752 at = id
1753 elif type == 'l':
1753 elif type == 'l':
1754 id, name = data
1754 id, name = data
1755 ui.note(('tag %s\n' % name))
1755 ui.note(('tag %s\n' % name))
1756 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1756 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1757 elif type == 'a':
1757 elif type == 'a':
1758 ui.note(('branch %s\n' % data))
1758 ui.note(('branch %s\n' % data))
1759 atbranch = data
1759 atbranch = data
1760 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1760 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1761 tr.close()
1761 tr.close()
1762
1762
1763 if tags:
1763 if tags:
1764 repo.opener.write("localtags", "".join(tags))
1764 repo.opener.write("localtags", "".join(tags))
1765 finally:
1765 finally:
1766 ui.progress(_('building'), None)
1766 ui.progress(_('building'), None)
1767 release(tr, lock)
1767 release(tr, lock)
1768
1768
1769 @command('debugbundle',
1769 @command('debugbundle',
1770 [('a', 'all', None, _('show all details'))],
1770 [('a', 'all', None, _('show all details'))],
1771 _('FILE'),
1771 _('FILE'),
1772 norepo=True)
1772 norepo=True)
1773 def debugbundle(ui, bundlepath, all=None, **opts):
1773 def debugbundle(ui, bundlepath, all=None, **opts):
1774 """lists the contents of a bundle"""
1774 """lists the contents of a bundle"""
1775 f = hg.openpath(ui, bundlepath)
1775 f = hg.openpath(ui, bundlepath)
1776 try:
1776 try:
1777 gen = exchange.readbundle(ui, f, bundlepath)
1777 gen = exchange.readbundle(ui, f, bundlepath)
1778 if all:
1778 if all:
1779 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1779 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1780
1780
1781 def showchunks(named):
1781 def showchunks(named):
1782 ui.write("\n%s\n" % named)
1782 ui.write("\n%s\n" % named)
1783 chain = None
1783 chain = None
1784 while True:
1784 while True:
1785 chunkdata = gen.deltachunk(chain)
1785 chunkdata = gen.deltachunk(chain)
1786 if not chunkdata:
1786 if not chunkdata:
1787 break
1787 break
1788 node = chunkdata['node']
1788 node = chunkdata['node']
1789 p1 = chunkdata['p1']
1789 p1 = chunkdata['p1']
1790 p2 = chunkdata['p2']
1790 p2 = chunkdata['p2']
1791 cs = chunkdata['cs']
1791 cs = chunkdata['cs']
1792 deltabase = chunkdata['deltabase']
1792 deltabase = chunkdata['deltabase']
1793 delta = chunkdata['delta']
1793 delta = chunkdata['delta']
1794 ui.write("%s %s %s %s %s %s\n" %
1794 ui.write("%s %s %s %s %s %s\n" %
1795 (hex(node), hex(p1), hex(p2),
1795 (hex(node), hex(p1), hex(p2),
1796 hex(cs), hex(deltabase), len(delta)))
1796 hex(cs), hex(deltabase), len(delta)))
1797 chain = node
1797 chain = node
1798
1798
1799 chunkdata = gen.changelogheader()
1799 chunkdata = gen.changelogheader()
1800 showchunks("changelog")
1800 showchunks("changelog")
1801 chunkdata = gen.manifestheader()
1801 chunkdata = gen.manifestheader()
1802 showchunks("manifest")
1802 showchunks("manifest")
1803 while True:
1803 while True:
1804 chunkdata = gen.filelogheader()
1804 chunkdata = gen.filelogheader()
1805 if not chunkdata:
1805 if not chunkdata:
1806 break
1806 break
1807 fname = chunkdata['filename']
1807 fname = chunkdata['filename']
1808 showchunks(fname)
1808 showchunks(fname)
1809 else:
1809 else:
1810 chunkdata = gen.changelogheader()
1810 chunkdata = gen.changelogheader()
1811 chain = None
1811 chain = None
1812 while True:
1812 while True:
1813 chunkdata = gen.deltachunk(chain)
1813 chunkdata = gen.deltachunk(chain)
1814 if not chunkdata:
1814 if not chunkdata:
1815 break
1815 break
1816 node = chunkdata['node']
1816 node = chunkdata['node']
1817 ui.write("%s\n" % hex(node))
1817 ui.write("%s\n" % hex(node))
1818 chain = node
1818 chain = node
1819 finally:
1819 finally:
1820 f.close()
1820 f.close()
1821
1821
1822 @command('debugcheckstate', [], '')
1822 @command('debugcheckstate', [], '')
1823 def debugcheckstate(ui, repo):
1823 def debugcheckstate(ui, repo):
1824 """validate the correctness of the current dirstate"""
1824 """validate the correctness of the current dirstate"""
1825 parent1, parent2 = repo.dirstate.parents()
1825 parent1, parent2 = repo.dirstate.parents()
1826 m1 = repo[parent1].manifest()
1826 m1 = repo[parent1].manifest()
1827 m2 = repo[parent2].manifest()
1827 m2 = repo[parent2].manifest()
1828 errors = 0
1828 errors = 0
1829 for f in repo.dirstate:
1829 for f in repo.dirstate:
1830 state = repo.dirstate[f]
1830 state = repo.dirstate[f]
1831 if state in "nr" and f not in m1:
1831 if state in "nr" and f not in m1:
1832 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1832 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1833 errors += 1
1833 errors += 1
1834 if state in "a" and f in m1:
1834 if state in "a" and f in m1:
1835 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1835 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1836 errors += 1
1836 errors += 1
1837 if state in "m" and f not in m1 and f not in m2:
1837 if state in "m" and f not in m1 and f not in m2:
1838 ui.warn(_("%s in state %s, but not in either manifest\n") %
1838 ui.warn(_("%s in state %s, but not in either manifest\n") %
1839 (f, state))
1839 (f, state))
1840 errors += 1
1840 errors += 1
1841 for f in m1:
1841 for f in m1:
1842 state = repo.dirstate[f]
1842 state = repo.dirstate[f]
1843 if state not in "nrm":
1843 if state not in "nrm":
1844 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1844 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1845 errors += 1
1845 errors += 1
1846 if errors:
1846 if errors:
1847 error = _(".hg/dirstate inconsistent with current parent's manifest")
1847 error = _(".hg/dirstate inconsistent with current parent's manifest")
1848 raise util.Abort(error)
1848 raise util.Abort(error)
1849
1849
1850 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1850 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1851 def debugcommands(ui, cmd='', *args):
1851 def debugcommands(ui, cmd='', *args):
1852 """list all available commands and options"""
1852 """list all available commands and options"""
1853 for cmd, vals in sorted(table.iteritems()):
1853 for cmd, vals in sorted(table.iteritems()):
1854 cmd = cmd.split('|')[0].strip('^')
1854 cmd = cmd.split('|')[0].strip('^')
1855 opts = ', '.join([i[1] for i in vals[1]])
1855 opts = ', '.join([i[1] for i in vals[1]])
1856 ui.write('%s: %s\n' % (cmd, opts))
1856 ui.write('%s: %s\n' % (cmd, opts))
1857
1857
1858 @command('debugcomplete',
1858 @command('debugcomplete',
1859 [('o', 'options', None, _('show the command options'))],
1859 [('o', 'options', None, _('show the command options'))],
1860 _('[-o] CMD'),
1860 _('[-o] CMD'),
1861 norepo=True)
1861 norepo=True)
1862 def debugcomplete(ui, cmd='', **opts):
1862 def debugcomplete(ui, cmd='', **opts):
1863 """returns the completion list associated with the given command"""
1863 """returns the completion list associated with the given command"""
1864
1864
1865 if opts.get('options'):
1865 if opts.get('options'):
1866 options = []
1866 options = []
1867 otables = [globalopts]
1867 otables = [globalopts]
1868 if cmd:
1868 if cmd:
1869 aliases, entry = cmdutil.findcmd(cmd, table, False)
1869 aliases, entry = cmdutil.findcmd(cmd, table, False)
1870 otables.append(entry[1])
1870 otables.append(entry[1])
1871 for t in otables:
1871 for t in otables:
1872 for o in t:
1872 for o in t:
1873 if "(DEPRECATED)" in o[3]:
1873 if "(DEPRECATED)" in o[3]:
1874 continue
1874 continue
1875 if o[0]:
1875 if o[0]:
1876 options.append('-%s' % o[0])
1876 options.append('-%s' % o[0])
1877 options.append('--%s' % o[1])
1877 options.append('--%s' % o[1])
1878 ui.write("%s\n" % "\n".join(options))
1878 ui.write("%s\n" % "\n".join(options))
1879 return
1879 return
1880
1880
1881 cmdlist = cmdutil.findpossible(cmd, table)
1881 cmdlist = cmdutil.findpossible(cmd, table)
1882 if ui.verbose:
1882 if ui.verbose:
1883 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1883 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1884 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1884 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1885
1885
1886 @command('debugdag',
1886 @command('debugdag',
1887 [('t', 'tags', None, _('use tags as labels')),
1887 [('t', 'tags', None, _('use tags as labels')),
1888 ('b', 'branches', None, _('annotate with branch names')),
1888 ('b', 'branches', None, _('annotate with branch names')),
1889 ('', 'dots', None, _('use dots for runs')),
1889 ('', 'dots', None, _('use dots for runs')),
1890 ('s', 'spaces', None, _('separate elements by spaces'))],
1890 ('s', 'spaces', None, _('separate elements by spaces'))],
1891 _('[OPTION]... [FILE [REV]...]'),
1891 _('[OPTION]... [FILE [REV]...]'),
1892 optionalrepo=True)
1892 optionalrepo=True)
1893 def debugdag(ui, repo, file_=None, *revs, **opts):
1893 def debugdag(ui, repo, file_=None, *revs, **opts):
1894 """format the changelog or an index DAG as a concise textual description
1894 """format the changelog or an index DAG as a concise textual description
1895
1895
1896 If you pass a revlog index, the revlog's DAG is emitted. If you list
1896 If you pass a revlog index, the revlog's DAG is emitted. If you list
1897 revision numbers, they get labeled in the output as rN.
1897 revision numbers, they get labeled in the output as rN.
1898
1898
1899 Otherwise, the changelog DAG of the current repo is emitted.
1899 Otherwise, the changelog DAG of the current repo is emitted.
1900 """
1900 """
1901 spaces = opts.get('spaces')
1901 spaces = opts.get('spaces')
1902 dots = opts.get('dots')
1902 dots = opts.get('dots')
1903 if file_:
1903 if file_:
1904 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1904 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1905 revs = set((int(r) for r in revs))
1905 revs = set((int(r) for r in revs))
1906 def events():
1906 def events():
1907 for r in rlog:
1907 for r in rlog:
1908 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1908 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1909 if p != -1)))
1909 if p != -1)))
1910 if r in revs:
1910 if r in revs:
1911 yield 'l', (r, "r%i" % r)
1911 yield 'l', (r, "r%i" % r)
1912 elif repo:
1912 elif repo:
1913 cl = repo.changelog
1913 cl = repo.changelog
1914 tags = opts.get('tags')
1914 tags = opts.get('tags')
1915 branches = opts.get('branches')
1915 branches = opts.get('branches')
1916 if tags:
1916 if tags:
1917 labels = {}
1917 labels = {}
1918 for l, n in repo.tags().items():
1918 for l, n in repo.tags().items():
1919 labels.setdefault(cl.rev(n), []).append(l)
1919 labels.setdefault(cl.rev(n), []).append(l)
1920 def events():
1920 def events():
1921 b = "default"
1921 b = "default"
1922 for r in cl:
1922 for r in cl:
1923 if branches:
1923 if branches:
1924 newb = cl.read(cl.node(r))[5]['branch']
1924 newb = cl.read(cl.node(r))[5]['branch']
1925 if newb != b:
1925 if newb != b:
1926 yield 'a', newb
1926 yield 'a', newb
1927 b = newb
1927 b = newb
1928 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1928 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1929 if p != -1)))
1929 if p != -1)))
1930 if tags:
1930 if tags:
1931 ls = labels.get(r)
1931 ls = labels.get(r)
1932 if ls:
1932 if ls:
1933 for l in ls:
1933 for l in ls:
1934 yield 'l', (r, l)
1934 yield 'l', (r, l)
1935 else:
1935 else:
1936 raise util.Abort(_('need repo for changelog dag'))
1936 raise util.Abort(_('need repo for changelog dag'))
1937
1937
1938 for line in dagparser.dagtextlines(events(),
1938 for line in dagparser.dagtextlines(events(),
1939 addspaces=spaces,
1939 addspaces=spaces,
1940 wraplabels=True,
1940 wraplabels=True,
1941 wrapannotations=True,
1941 wrapannotations=True,
1942 wrapnonlinear=dots,
1942 wrapnonlinear=dots,
1943 usedots=dots,
1943 usedots=dots,
1944 maxlinewidth=70):
1944 maxlinewidth=70):
1945 ui.write(line)
1945 ui.write(line)
1946 ui.write("\n")
1946 ui.write("\n")
1947
1947
1948 @command('debugdata',
1948 @command('debugdata',
1949 [('c', 'changelog', False, _('open changelog')),
1949 [('c', 'changelog', False, _('open changelog')),
1950 ('m', 'manifest', False, _('open manifest'))],
1950 ('m', 'manifest', False, _('open manifest'))],
1951 _('-c|-m|FILE REV'))
1951 _('-c|-m|FILE REV'))
1952 def debugdata(ui, repo, file_, rev=None, **opts):
1952 def debugdata(ui, repo, file_, rev=None, **opts):
1953 """dump the contents of a data file revision"""
1953 """dump the contents of a data file revision"""
1954 if opts.get('changelog') or opts.get('manifest'):
1954 if opts.get('changelog') or opts.get('manifest'):
1955 file_, rev = None, file_
1955 file_, rev = None, file_
1956 elif rev is None:
1956 elif rev is None:
1957 raise error.CommandError('debugdata', _('invalid arguments'))
1957 raise error.CommandError('debugdata', _('invalid arguments'))
1958 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1958 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1959 try:
1959 try:
1960 ui.write(r.revision(r.lookup(rev)))
1960 ui.write(r.revision(r.lookup(rev)))
1961 except KeyError:
1961 except KeyError:
1962 raise util.Abort(_('invalid revision identifier %s') % rev)
1962 raise util.Abort(_('invalid revision identifier %s') % rev)
1963
1963
1964 @command('debugdate',
1964 @command('debugdate',
1965 [('e', 'extended', None, _('try extended date formats'))],
1965 [('e', 'extended', None, _('try extended date formats'))],
1966 _('[-e] DATE [RANGE]'),
1966 _('[-e] DATE [RANGE]'),
1967 norepo=True, optionalrepo=True)
1967 norepo=True, optionalrepo=True)
1968 def debugdate(ui, date, range=None, **opts):
1968 def debugdate(ui, date, range=None, **opts):
1969 """parse and display a date"""
1969 """parse and display a date"""
1970 if opts["extended"]:
1970 if opts["extended"]:
1971 d = util.parsedate(date, util.extendeddateformats)
1971 d = util.parsedate(date, util.extendeddateformats)
1972 else:
1972 else:
1973 d = util.parsedate(date)
1973 d = util.parsedate(date)
1974 ui.write(("internal: %s %s\n") % d)
1974 ui.write(("internal: %s %s\n") % d)
1975 ui.write(("standard: %s\n") % util.datestr(d))
1975 ui.write(("standard: %s\n") % util.datestr(d))
1976 if range:
1976 if range:
1977 m = util.matchdate(range)
1977 m = util.matchdate(range)
1978 ui.write(("match: %s\n") % m(d[0]))
1978 ui.write(("match: %s\n") % m(d[0]))
1979
1979
1980 @command('debugdiscovery',
1980 @command('debugdiscovery',
1981 [('', 'old', None, _('use old-style discovery')),
1981 [('', 'old', None, _('use old-style discovery')),
1982 ('', 'nonheads', None,
1982 ('', 'nonheads', None,
1983 _('use old-style discovery with non-heads included')),
1983 _('use old-style discovery with non-heads included')),
1984 ] + remoteopts,
1984 ] + remoteopts,
1985 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1985 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1986 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1986 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1987 """runs the changeset discovery protocol in isolation"""
1987 """runs the changeset discovery protocol in isolation"""
1988 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1988 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1989 opts.get('branch'))
1989 opts.get('branch'))
1990 remote = hg.peer(repo, opts, remoteurl)
1990 remote = hg.peer(repo, opts, remoteurl)
1991 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1991 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1992
1992
1993 # make sure tests are repeatable
1993 # make sure tests are repeatable
1994 random.seed(12323)
1994 random.seed(12323)
1995
1995
1996 def doit(localheads, remoteheads, remote=remote):
1996 def doit(localheads, remoteheads, remote=remote):
1997 if opts.get('old'):
1997 if opts.get('old'):
1998 if localheads:
1998 if localheads:
1999 raise util.Abort('cannot use localheads with old style '
1999 raise util.Abort('cannot use localheads with old style '
2000 'discovery')
2000 'discovery')
2001 if not util.safehasattr(remote, 'branches'):
2001 if not util.safehasattr(remote, 'branches'):
2002 # enable in-client legacy support
2002 # enable in-client legacy support
2003 remote = localrepo.locallegacypeer(remote.local())
2003 remote = localrepo.locallegacypeer(remote.local())
2004 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2004 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2005 force=True)
2005 force=True)
2006 common = set(common)
2006 common = set(common)
2007 if not opts.get('nonheads'):
2007 if not opts.get('nonheads'):
2008 ui.write(("unpruned common: %s\n") %
2008 ui.write(("unpruned common: %s\n") %
2009 " ".join(sorted(short(n) for n in common)))
2009 " ".join(sorted(short(n) for n in common)))
2010 dag = dagutil.revlogdag(repo.changelog)
2010 dag = dagutil.revlogdag(repo.changelog)
2011 all = dag.ancestorset(dag.internalizeall(common))
2011 all = dag.ancestorset(dag.internalizeall(common))
2012 common = dag.externalizeall(dag.headsetofconnecteds(all))
2012 common = dag.externalizeall(dag.headsetofconnecteds(all))
2013 else:
2013 else:
2014 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2014 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2015 common = set(common)
2015 common = set(common)
2016 rheads = set(hds)
2016 rheads = set(hds)
2017 lheads = set(repo.heads())
2017 lheads = set(repo.heads())
2018 ui.write(("common heads: %s\n") %
2018 ui.write(("common heads: %s\n") %
2019 " ".join(sorted(short(n) for n in common)))
2019 " ".join(sorted(short(n) for n in common)))
2020 if lheads <= common:
2020 if lheads <= common:
2021 ui.write(("local is subset\n"))
2021 ui.write(("local is subset\n"))
2022 elif rheads <= common:
2022 elif rheads <= common:
2023 ui.write(("remote is subset\n"))
2023 ui.write(("remote is subset\n"))
2024
2024
2025 serverlogs = opts.get('serverlog')
2025 serverlogs = opts.get('serverlog')
2026 if serverlogs:
2026 if serverlogs:
2027 for filename in serverlogs:
2027 for filename in serverlogs:
2028 logfile = open(filename, 'r')
2028 logfile = open(filename, 'r')
2029 try:
2029 try:
2030 line = logfile.readline()
2030 line = logfile.readline()
2031 while line:
2031 while line:
2032 parts = line.strip().split(';')
2032 parts = line.strip().split(';')
2033 op = parts[1]
2033 op = parts[1]
2034 if op == 'cg':
2034 if op == 'cg':
2035 pass
2035 pass
2036 elif op == 'cgss':
2036 elif op == 'cgss':
2037 doit(parts[2].split(' '), parts[3].split(' '))
2037 doit(parts[2].split(' '), parts[3].split(' '))
2038 elif op == 'unb':
2038 elif op == 'unb':
2039 doit(parts[3].split(' '), parts[2].split(' '))
2039 doit(parts[3].split(' '), parts[2].split(' '))
2040 line = logfile.readline()
2040 line = logfile.readline()
2041 finally:
2041 finally:
2042 logfile.close()
2042 logfile.close()
2043
2043
2044 else:
2044 else:
2045 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2045 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2046 opts.get('remote_head'))
2046 opts.get('remote_head'))
2047 localrevs = opts.get('local_head')
2047 localrevs = opts.get('local_head')
2048 doit(localrevs, remoterevs)
2048 doit(localrevs, remoterevs)
2049
2049
2050 @command('debugfileset',
2050 @command('debugfileset',
2051 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2051 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2052 _('[-r REV] FILESPEC'))
2052 _('[-r REV] FILESPEC'))
2053 def debugfileset(ui, repo, expr, **opts):
2053 def debugfileset(ui, repo, expr, **opts):
2054 '''parse and apply a fileset specification'''
2054 '''parse and apply a fileset specification'''
2055 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2055 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2056 if ui.verbose:
2056 if ui.verbose:
2057 tree = fileset.parse(expr)[0]
2057 tree = fileset.parse(expr)[0]
2058 ui.note(tree, "\n")
2058 ui.note(tree, "\n")
2059
2059
2060 for f in ctx.getfileset(expr):
2060 for f in ctx.getfileset(expr):
2061 ui.write("%s\n" % f)
2061 ui.write("%s\n" % f)
2062
2062
2063 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2063 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2064 def debugfsinfo(ui, path="."):
2064 def debugfsinfo(ui, path="."):
2065 """show information detected about current filesystem"""
2065 """show information detected about current filesystem"""
2066 util.writefile('.debugfsinfo', '')
2066 util.writefile('.debugfsinfo', '')
2067 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2067 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2068 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2068 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2069 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2069 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2070 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2070 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2071 and 'yes' or 'no'))
2071 and 'yes' or 'no'))
2072 os.unlink('.debugfsinfo')
2072 os.unlink('.debugfsinfo')
2073
2073
2074 @command('debuggetbundle',
2074 @command('debuggetbundle',
2075 [('H', 'head', [], _('id of head node'), _('ID')),
2075 [('H', 'head', [], _('id of head node'), _('ID')),
2076 ('C', 'common', [], _('id of common node'), _('ID')),
2076 ('C', 'common', [], _('id of common node'), _('ID')),
2077 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2077 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2078 _('REPO FILE [-H|-C ID]...'),
2078 _('REPO FILE [-H|-C ID]...'),
2079 norepo=True)
2079 norepo=True)
2080 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2080 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2081 """retrieves a bundle from a repo
2081 """retrieves a bundle from a repo
2082
2082
2083 Every ID must be a full-length hex node id string. Saves the bundle to the
2083 Every ID must be a full-length hex node id string. Saves the bundle to the
2084 given file.
2084 given file.
2085 """
2085 """
2086 repo = hg.peer(ui, opts, repopath)
2086 repo = hg.peer(ui, opts, repopath)
2087 if not repo.capable('getbundle'):
2087 if not repo.capable('getbundle'):
2088 raise util.Abort("getbundle() not supported by target repository")
2088 raise util.Abort("getbundle() not supported by target repository")
2089 args = {}
2089 args = {}
2090 if common:
2090 if common:
2091 args['common'] = [bin(s) for s in common]
2091 args['common'] = [bin(s) for s in common]
2092 if head:
2092 if head:
2093 args['heads'] = [bin(s) for s in head]
2093 args['heads'] = [bin(s) for s in head]
2094 # TODO: get desired bundlecaps from command line.
2094 # TODO: get desired bundlecaps from command line.
2095 args['bundlecaps'] = None
2095 args['bundlecaps'] = None
2096 bundle = repo.getbundle('debug', **args)
2096 bundle = repo.getbundle('debug', **args)
2097
2097
2098 bundletype = opts.get('type', 'bzip2').lower()
2098 bundletype = opts.get('type', 'bzip2').lower()
2099 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2099 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2100 bundletype = btypes.get(bundletype)
2100 bundletype = btypes.get(bundletype)
2101 if bundletype not in changegroup.bundletypes:
2101 if bundletype not in changegroup.bundletypes:
2102 raise util.Abort(_('unknown bundle type specified with --type'))
2102 raise util.Abort(_('unknown bundle type specified with --type'))
2103 changegroup.writebundle(bundle, bundlepath, bundletype)
2103 changegroup.writebundle(bundle, bundlepath, bundletype)
2104
2104
2105 @command('debugignore', [], '')
2105 @command('debugignore', [], '')
2106 def debugignore(ui, repo, *values, **opts):
2106 def debugignore(ui, repo, *values, **opts):
2107 """display the combined ignore pattern"""
2107 """display the combined ignore pattern"""
2108 ignore = repo.dirstate._ignore
2108 ignore = repo.dirstate._ignore
2109 includepat = getattr(ignore, 'includepat', None)
2109 includepat = getattr(ignore, 'includepat', None)
2110 if includepat is not None:
2110 if includepat is not None:
2111 ui.write("%s\n" % includepat)
2111 ui.write("%s\n" % includepat)
2112 else:
2112 else:
2113 raise util.Abort(_("no ignore patterns found"))
2113 raise util.Abort(_("no ignore patterns found"))
2114
2114
2115 @command('debugindex',
2115 @command('debugindex',
2116 [('c', 'changelog', False, _('open changelog')),
2116 [('c', 'changelog', False, _('open changelog')),
2117 ('m', 'manifest', False, _('open manifest')),
2117 ('m', 'manifest', False, _('open manifest')),
2118 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2118 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2119 _('[-f FORMAT] -c|-m|FILE'),
2119 _('[-f FORMAT] -c|-m|FILE'),
2120 optionalrepo=True)
2120 optionalrepo=True)
2121 def debugindex(ui, repo, file_=None, **opts):
2121 def debugindex(ui, repo, file_=None, **opts):
2122 """dump the contents of an index file"""
2122 """dump the contents of an index file"""
2123 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2123 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2124 format = opts.get('format', 0)
2124 format = opts.get('format', 0)
2125 if format not in (0, 1):
2125 if format not in (0, 1):
2126 raise util.Abort(_("unknown format %d") % format)
2126 raise util.Abort(_("unknown format %d") % format)
2127
2127
2128 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2128 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2129 if generaldelta:
2129 if generaldelta:
2130 basehdr = ' delta'
2130 basehdr = ' delta'
2131 else:
2131 else:
2132 basehdr = ' base'
2132 basehdr = ' base'
2133
2133
2134 if format == 0:
2134 if format == 0:
2135 ui.write(" rev offset length " + basehdr + " linkrev"
2135 ui.write(" rev offset length " + basehdr + " linkrev"
2136 " nodeid p1 p2\n")
2136 " nodeid p1 p2\n")
2137 elif format == 1:
2137 elif format == 1:
2138 ui.write(" rev flag offset length"
2138 ui.write(" rev flag offset length"
2139 " size " + basehdr + " link p1 p2"
2139 " size " + basehdr + " link p1 p2"
2140 " nodeid\n")
2140 " nodeid\n")
2141
2141
2142 for i in r:
2142 for i in r:
2143 node = r.node(i)
2143 node = r.node(i)
2144 if generaldelta:
2144 if generaldelta:
2145 base = r.deltaparent(i)
2145 base = r.deltaparent(i)
2146 else:
2146 else:
2147 base = r.chainbase(i)
2147 base = r.chainbase(i)
2148 if format == 0:
2148 if format == 0:
2149 try:
2149 try:
2150 pp = r.parents(node)
2150 pp = r.parents(node)
2151 except Exception:
2151 except Exception:
2152 pp = [nullid, nullid]
2152 pp = [nullid, nullid]
2153 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2153 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2154 i, r.start(i), r.length(i), base, r.linkrev(i),
2154 i, r.start(i), r.length(i), base, r.linkrev(i),
2155 short(node), short(pp[0]), short(pp[1])))
2155 short(node), short(pp[0]), short(pp[1])))
2156 elif format == 1:
2156 elif format == 1:
2157 pr = r.parentrevs(i)
2157 pr = r.parentrevs(i)
2158 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2158 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2159 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2159 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2160 base, r.linkrev(i), pr[0], pr[1], short(node)))
2160 base, r.linkrev(i), pr[0], pr[1], short(node)))
2161
2161
2162 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2162 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2163 def debugindexdot(ui, repo, file_):
2163 def debugindexdot(ui, repo, file_):
2164 """dump an index DAG as a graphviz dot file"""
2164 """dump an index DAG as a graphviz dot file"""
2165 r = None
2165 r = None
2166 if repo:
2166 if repo:
2167 filelog = repo.file(file_)
2167 filelog = repo.file(file_)
2168 if len(filelog):
2168 if len(filelog):
2169 r = filelog
2169 r = filelog
2170 if not r:
2170 if not r:
2171 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2171 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2172 ui.write(("digraph G {\n"))
2172 ui.write(("digraph G {\n"))
2173 for i in r:
2173 for i in r:
2174 node = r.node(i)
2174 node = r.node(i)
2175 pp = r.parents(node)
2175 pp = r.parents(node)
2176 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2176 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2177 if pp[1] != nullid:
2177 if pp[1] != nullid:
2178 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2178 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2179 ui.write("}\n")
2179 ui.write("}\n")
2180
2180
2181 @command('debuginstall', [], '', norepo=True)
2181 @command('debuginstall', [], '', norepo=True)
2182 def debuginstall(ui):
2182 def debuginstall(ui):
2183 '''test Mercurial installation
2183 '''test Mercurial installation
2184
2184
2185 Returns 0 on success.
2185 Returns 0 on success.
2186 '''
2186 '''
2187
2187
2188 def writetemp(contents):
2188 def writetemp(contents):
2189 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2189 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2190 f = os.fdopen(fd, "wb")
2190 f = os.fdopen(fd, "wb")
2191 f.write(contents)
2191 f.write(contents)
2192 f.close()
2192 f.close()
2193 return name
2193 return name
2194
2194
2195 problems = 0
2195 problems = 0
2196
2196
2197 # encoding
2197 # encoding
2198 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2198 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2199 try:
2199 try:
2200 encoding.fromlocal("test")
2200 encoding.fromlocal("test")
2201 except util.Abort, inst:
2201 except util.Abort, inst:
2202 ui.write(" %s\n" % inst)
2202 ui.write(" %s\n" % inst)
2203 ui.write(_(" (check that your locale is properly set)\n"))
2203 ui.write(_(" (check that your locale is properly set)\n"))
2204 problems += 1
2204 problems += 1
2205
2205
2206 # Python
2206 # Python
2207 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2207 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2208 ui.status(_("checking Python version (%s)\n")
2208 ui.status(_("checking Python version (%s)\n")
2209 % ("%s.%s.%s" % sys.version_info[:3]))
2209 % ("%s.%s.%s" % sys.version_info[:3]))
2210 ui.status(_("checking Python lib (%s)...\n")
2210 ui.status(_("checking Python lib (%s)...\n")
2211 % os.path.dirname(os.__file__))
2211 % os.path.dirname(os.__file__))
2212
2212
2213 # compiled modules
2213 # compiled modules
2214 ui.status(_("checking installed modules (%s)...\n")
2214 ui.status(_("checking installed modules (%s)...\n")
2215 % os.path.dirname(__file__))
2215 % os.path.dirname(__file__))
2216 try:
2216 try:
2217 import bdiff, mpatch, base85, osutil
2217 import bdiff, mpatch, base85, osutil
2218 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2218 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2219 except Exception, inst:
2219 except Exception, inst:
2220 ui.write(" %s\n" % inst)
2220 ui.write(" %s\n" % inst)
2221 ui.write(_(" One or more extensions could not be found"))
2221 ui.write(_(" One or more extensions could not be found"))
2222 ui.write(_(" (check that you compiled the extensions)\n"))
2222 ui.write(_(" (check that you compiled the extensions)\n"))
2223 problems += 1
2223 problems += 1
2224
2224
2225 # templates
2225 # templates
2226 import templater
2226 import templater
2227 p = templater.templatepath()
2227 p = templater.templatepath()
2228 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2228 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2229 if p:
2229 if p:
2230 m = templater.templatepath("map-cmdline.default")
2230 m = templater.templatepath("map-cmdline.default")
2231 if m:
2231 if m:
2232 # template found, check if it is working
2232 # template found, check if it is working
2233 try:
2233 try:
2234 templater.templater(m)
2234 templater.templater(m)
2235 except Exception, inst:
2235 except Exception, inst:
2236 ui.write(" %s\n" % inst)
2236 ui.write(" %s\n" % inst)
2237 p = None
2237 p = None
2238 else:
2238 else:
2239 ui.write(_(" template 'default' not found\n"))
2239 ui.write(_(" template 'default' not found\n"))
2240 p = None
2240 p = None
2241 else:
2241 else:
2242 ui.write(_(" no template directories found\n"))
2242 ui.write(_(" no template directories found\n"))
2243 if not p:
2243 if not p:
2244 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2244 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2245 problems += 1
2245 problems += 1
2246
2246
2247 # editor
2247 # editor
2248 ui.status(_("checking commit editor...\n"))
2248 ui.status(_("checking commit editor...\n"))
2249 editor = ui.geteditor()
2249 editor = ui.geteditor()
2250 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2250 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2251 if not cmdpath:
2251 if not cmdpath:
2252 if editor == 'vi':
2252 if editor == 'vi':
2253 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2253 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2254 ui.write(_(" (specify a commit editor in your configuration"
2254 ui.write(_(" (specify a commit editor in your configuration"
2255 " file)\n"))
2255 " file)\n"))
2256 else:
2256 else:
2257 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2257 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2258 ui.write(_(" (specify a commit editor in your configuration"
2258 ui.write(_(" (specify a commit editor in your configuration"
2259 " file)\n"))
2259 " file)\n"))
2260 problems += 1
2260 problems += 1
2261
2261
2262 # check username
2262 # check username
2263 ui.status(_("checking username...\n"))
2263 ui.status(_("checking username...\n"))
2264 try:
2264 try:
2265 ui.username()
2265 ui.username()
2266 except util.Abort, e:
2266 except util.Abort, e:
2267 ui.write(" %s\n" % e)
2267 ui.write(" %s\n" % e)
2268 ui.write(_(" (specify a username in your configuration file)\n"))
2268 ui.write(_(" (specify a username in your configuration file)\n"))
2269 problems += 1
2269 problems += 1
2270
2270
2271 if not problems:
2271 if not problems:
2272 ui.status(_("no problems detected\n"))
2272 ui.status(_("no problems detected\n"))
2273 else:
2273 else:
2274 ui.write(_("%s problems detected,"
2274 ui.write(_("%s problems detected,"
2275 " please check your install!\n") % problems)
2275 " please check your install!\n") % problems)
2276
2276
2277 return problems
2277 return problems
2278
2278
2279 @command('debugknown', [], _('REPO ID...'), norepo=True)
2279 @command('debugknown', [], _('REPO ID...'), norepo=True)
2280 def debugknown(ui, repopath, *ids, **opts):
2280 def debugknown(ui, repopath, *ids, **opts):
2281 """test whether node ids are known to a repo
2281 """test whether node ids are known to a repo
2282
2282
2283 Every ID must be a full-length hex node id string. Returns a list of 0s
2283 Every ID must be a full-length hex node id string. Returns a list of 0s
2284 and 1s indicating unknown/known.
2284 and 1s indicating unknown/known.
2285 """
2285 """
2286 repo = hg.peer(ui, opts, repopath)
2286 repo = hg.peer(ui, opts, repopath)
2287 if not repo.capable('known'):
2287 if not repo.capable('known'):
2288 raise util.Abort("known() not supported by target repository")
2288 raise util.Abort("known() not supported by target repository")
2289 flags = repo.known([bin(s) for s in ids])
2289 flags = repo.known([bin(s) for s in ids])
2290 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2290 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2291
2291
2292 @command('debuglabelcomplete', [], _('LABEL...'))
2292 @command('debuglabelcomplete', [], _('LABEL...'))
2293 def debuglabelcomplete(ui, repo, *args):
2293 def debuglabelcomplete(ui, repo, *args):
2294 '''complete "labels" - tags, open branch names, bookmark names'''
2294 '''complete "labels" - tags, open branch names, bookmark names'''
2295
2295
2296 labels = set()
2296 labels = set()
2297 labels.update(t[0] for t in repo.tagslist())
2297 labels.update(t[0] for t in repo.tagslist())
2298 labels.update(repo._bookmarks.keys())
2298 labels.update(repo._bookmarks.keys())
2299 labels.update(tag for (tag, heads, tip, closed)
2299 labels.update(tag for (tag, heads, tip, closed)
2300 in repo.branchmap().iterbranches() if not closed)
2300 in repo.branchmap().iterbranches() if not closed)
2301 completions = set()
2301 completions = set()
2302 if not args:
2302 if not args:
2303 args = ['']
2303 args = ['']
2304 for a in args:
2304 for a in args:
2305 completions.update(l for l in labels if l.startswith(a))
2305 completions.update(l for l in labels if l.startswith(a))
2306 ui.write('\n'.join(sorted(completions)))
2306 ui.write('\n'.join(sorted(completions)))
2307 ui.write('\n')
2307 ui.write('\n')
2308
2308
2309 @command('debugobsolete',
2309 @command('debugobsolete',
2310 [('', 'flags', 0, _('markers flag')),
2310 [('', 'flags', 0, _('markers flag')),
2311 ] + commitopts2,
2311 ] + commitopts2,
2312 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2312 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2313 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2313 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2314 """create arbitrary obsolete marker
2314 """create arbitrary obsolete marker
2315
2315
2316 With no arguments, displays the list of obsolescence markers."""
2316 With no arguments, displays the list of obsolescence markers."""
2317
2317
2318 def parsenodeid(s):
2318 def parsenodeid(s):
2319 try:
2319 try:
2320 # We do not use revsingle/revrange functions here to accept
2320 # We do not use revsingle/revrange functions here to accept
2321 # arbitrary node identifiers, possibly not present in the
2321 # arbitrary node identifiers, possibly not present in the
2322 # local repository.
2322 # local repository.
2323 n = bin(s)
2323 n = bin(s)
2324 if len(n) != len(nullid):
2324 if len(n) != len(nullid):
2325 raise TypeError()
2325 raise TypeError()
2326 return n
2326 return n
2327 except TypeError:
2327 except TypeError:
2328 raise util.Abort('changeset references must be full hexadecimal '
2328 raise util.Abort('changeset references must be full hexadecimal '
2329 'node identifiers')
2329 'node identifiers')
2330
2330
2331 if precursor is not None:
2331 if precursor is not None:
2332 metadata = {}
2332 metadata = {}
2333 if 'date' in opts:
2333 if 'date' in opts:
2334 metadata['date'] = opts['date']
2334 metadata['date'] = opts['date']
2335 metadata['user'] = opts['user'] or ui.username()
2335 metadata['user'] = opts['user'] or ui.username()
2336 succs = tuple(parsenodeid(succ) for succ in successors)
2336 succs = tuple(parsenodeid(succ) for succ in successors)
2337 l = repo.lock()
2337 l = repo.lock()
2338 try:
2338 try:
2339 tr = repo.transaction('debugobsolete')
2339 tr = repo.transaction('debugobsolete')
2340 try:
2340 try:
2341 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2341 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2342 opts['flags'], metadata)
2342 opts['flags'], metadata)
2343 tr.close()
2343 tr.close()
2344 finally:
2344 finally:
2345 tr.release()
2345 tr.release()
2346 finally:
2346 finally:
2347 l.release()
2347 l.release()
2348 else:
2348 else:
2349 for m in obsolete.allmarkers(repo):
2349 for m in obsolete.allmarkers(repo):
2350 cmdutil.showmarker(ui, m)
2350 cmdutil.showmarker(ui, m)
2351
2351
2352 @command('debugpathcomplete',
2352 @command('debugpathcomplete',
2353 [('f', 'full', None, _('complete an entire path')),
2353 [('f', 'full', None, _('complete an entire path')),
2354 ('n', 'normal', None, _('show only normal files')),
2354 ('n', 'normal', None, _('show only normal files')),
2355 ('a', 'added', None, _('show only added files')),
2355 ('a', 'added', None, _('show only added files')),
2356 ('r', 'removed', None, _('show only removed files'))],
2356 ('r', 'removed', None, _('show only removed files'))],
2357 _('FILESPEC...'))
2357 _('FILESPEC...'))
2358 def debugpathcomplete(ui, repo, *specs, **opts):
2358 def debugpathcomplete(ui, repo, *specs, **opts):
2359 '''complete part or all of a tracked path
2359 '''complete part or all of a tracked path
2360
2360
2361 This command supports shells that offer path name completion. It
2361 This command supports shells that offer path name completion. It
2362 currently completes only files already known to the dirstate.
2362 currently completes only files already known to the dirstate.
2363
2363
2364 Completion extends only to the next path segment unless
2364 Completion extends only to the next path segment unless
2365 --full is specified, in which case entire paths are used.'''
2365 --full is specified, in which case entire paths are used.'''
2366
2366
2367 def complete(path, acceptable):
2367 def complete(path, acceptable):
2368 dirstate = repo.dirstate
2368 dirstate = repo.dirstate
2369 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2369 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2370 rootdir = repo.root + os.sep
2370 rootdir = repo.root + os.sep
2371 if spec != repo.root and not spec.startswith(rootdir):
2371 if spec != repo.root and not spec.startswith(rootdir):
2372 return [], []
2372 return [], []
2373 if os.path.isdir(spec):
2373 if os.path.isdir(spec):
2374 spec += '/'
2374 spec += '/'
2375 spec = spec[len(rootdir):]
2375 spec = spec[len(rootdir):]
2376 fixpaths = os.sep != '/'
2376 fixpaths = os.sep != '/'
2377 if fixpaths:
2377 if fixpaths:
2378 spec = spec.replace(os.sep, '/')
2378 spec = spec.replace(os.sep, '/')
2379 speclen = len(spec)
2379 speclen = len(spec)
2380 fullpaths = opts['full']
2380 fullpaths = opts['full']
2381 files, dirs = set(), set()
2381 files, dirs = set(), set()
2382 adddir, addfile = dirs.add, files.add
2382 adddir, addfile = dirs.add, files.add
2383 for f, st in dirstate.iteritems():
2383 for f, st in dirstate.iteritems():
2384 if f.startswith(spec) and st[0] in acceptable:
2384 if f.startswith(spec) and st[0] in acceptable:
2385 if fixpaths:
2385 if fixpaths:
2386 f = f.replace('/', os.sep)
2386 f = f.replace('/', os.sep)
2387 if fullpaths:
2387 if fullpaths:
2388 addfile(f)
2388 addfile(f)
2389 continue
2389 continue
2390 s = f.find(os.sep, speclen)
2390 s = f.find(os.sep, speclen)
2391 if s >= 0:
2391 if s >= 0:
2392 adddir(f[:s])
2392 adddir(f[:s])
2393 else:
2393 else:
2394 addfile(f)
2394 addfile(f)
2395 return files, dirs
2395 return files, dirs
2396
2396
2397 acceptable = ''
2397 acceptable = ''
2398 if opts['normal']:
2398 if opts['normal']:
2399 acceptable += 'nm'
2399 acceptable += 'nm'
2400 if opts['added']:
2400 if opts['added']:
2401 acceptable += 'a'
2401 acceptable += 'a'
2402 if opts['removed']:
2402 if opts['removed']:
2403 acceptable += 'r'
2403 acceptable += 'r'
2404 cwd = repo.getcwd()
2404 cwd = repo.getcwd()
2405 if not specs:
2405 if not specs:
2406 specs = ['.']
2406 specs = ['.']
2407
2407
2408 files, dirs = set(), set()
2408 files, dirs = set(), set()
2409 for spec in specs:
2409 for spec in specs:
2410 f, d = complete(spec, acceptable or 'nmar')
2410 f, d = complete(spec, acceptable or 'nmar')
2411 files.update(f)
2411 files.update(f)
2412 dirs.update(d)
2412 dirs.update(d)
2413 files.update(dirs)
2413 files.update(dirs)
2414 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2414 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2415 ui.write('\n')
2415 ui.write('\n')
2416
2416
2417 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2417 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2418 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2418 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2419 '''access the pushkey key/value protocol
2419 '''access the pushkey key/value protocol
2420
2420
2421 With two args, list the keys in the given namespace.
2421 With two args, list the keys in the given namespace.
2422
2422
2423 With five args, set a key to new if it currently is set to old.
2423 With five args, set a key to new if it currently is set to old.
2424 Reports success or failure.
2424 Reports success or failure.
2425 '''
2425 '''
2426
2426
2427 target = hg.peer(ui, {}, repopath)
2427 target = hg.peer(ui, {}, repopath)
2428 if keyinfo:
2428 if keyinfo:
2429 key, old, new = keyinfo
2429 key, old, new = keyinfo
2430 r = target.pushkey(namespace, key, old, new)
2430 r = target.pushkey(namespace, key, old, new)
2431 ui.status(str(r) + '\n')
2431 ui.status(str(r) + '\n')
2432 return not r
2432 return not r
2433 else:
2433 else:
2434 for k, v in sorted(target.listkeys(namespace).iteritems()):
2434 for k, v in sorted(target.listkeys(namespace).iteritems()):
2435 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2435 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2436 v.encode('string-escape')))
2436 v.encode('string-escape')))
2437
2437
2438 @command('debugpvec', [], _('A B'))
2438 @command('debugpvec', [], _('A B'))
2439 def debugpvec(ui, repo, a, b=None):
2439 def debugpvec(ui, repo, a, b=None):
2440 ca = scmutil.revsingle(repo, a)
2440 ca = scmutil.revsingle(repo, a)
2441 cb = scmutil.revsingle(repo, b)
2441 cb = scmutil.revsingle(repo, b)
2442 pa = pvec.ctxpvec(ca)
2442 pa = pvec.ctxpvec(ca)
2443 pb = pvec.ctxpvec(cb)
2443 pb = pvec.ctxpvec(cb)
2444 if pa == pb:
2444 if pa == pb:
2445 rel = "="
2445 rel = "="
2446 elif pa > pb:
2446 elif pa > pb:
2447 rel = ">"
2447 rel = ">"
2448 elif pa < pb:
2448 elif pa < pb:
2449 rel = "<"
2449 rel = "<"
2450 elif pa | pb:
2450 elif pa | pb:
2451 rel = "|"
2451 rel = "|"
2452 ui.write(_("a: %s\n") % pa)
2452 ui.write(_("a: %s\n") % pa)
2453 ui.write(_("b: %s\n") % pb)
2453 ui.write(_("b: %s\n") % pb)
2454 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2454 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2455 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2455 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2456 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2456 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2457 pa.distance(pb), rel))
2457 pa.distance(pb), rel))
2458
2458
2459 @command('debugrebuilddirstate|debugrebuildstate',
2459 @command('debugrebuilddirstate|debugrebuildstate',
2460 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2460 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2461 _('[-r REV]'))
2461 _('[-r REV]'))
2462 def debugrebuilddirstate(ui, repo, rev):
2462 def debugrebuilddirstate(ui, repo, rev):
2463 """rebuild the dirstate as it would look like for the given revision
2463 """rebuild the dirstate as it would look like for the given revision
2464
2464
2465 If no revision is specified the first current parent will be used.
2465 If no revision is specified the first current parent will be used.
2466
2466
2467 The dirstate will be set to the files of the given revision.
2467 The dirstate will be set to the files of the given revision.
2468 The actual working directory content or existing dirstate
2468 The actual working directory content or existing dirstate
2469 information such as adds or removes is not considered.
2469 information such as adds or removes is not considered.
2470
2470
2471 One use of this command is to make the next :hg:`status` invocation
2471 One use of this command is to make the next :hg:`status` invocation
2472 check the actual file content.
2472 check the actual file content.
2473 """
2473 """
2474 ctx = scmutil.revsingle(repo, rev)
2474 ctx = scmutil.revsingle(repo, rev)
2475 wlock = repo.wlock()
2475 wlock = repo.wlock()
2476 try:
2476 try:
2477 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2477 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2478 finally:
2478 finally:
2479 wlock.release()
2479 wlock.release()
2480
2480
2481 @command('debugrename',
2481 @command('debugrename',
2482 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2482 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2483 _('[-r REV] FILE'))
2483 _('[-r REV] FILE'))
2484 def debugrename(ui, repo, file1, *pats, **opts):
2484 def debugrename(ui, repo, file1, *pats, **opts):
2485 """dump rename information"""
2485 """dump rename information"""
2486
2486
2487 ctx = scmutil.revsingle(repo, opts.get('rev'))
2487 ctx = scmutil.revsingle(repo, opts.get('rev'))
2488 m = scmutil.match(ctx, (file1,) + pats, opts)
2488 m = scmutil.match(ctx, (file1,) + pats, opts)
2489 for abs in ctx.walk(m):
2489 for abs in ctx.walk(m):
2490 fctx = ctx[abs]
2490 fctx = ctx[abs]
2491 o = fctx.filelog().renamed(fctx.filenode())
2491 o = fctx.filelog().renamed(fctx.filenode())
2492 rel = m.rel(abs)
2492 rel = m.rel(abs)
2493 if o:
2493 if o:
2494 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2494 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2495 else:
2495 else:
2496 ui.write(_("%s not renamed\n") % rel)
2496 ui.write(_("%s not renamed\n") % rel)
2497
2497
2498 @command('debugrevlog',
2498 @command('debugrevlog',
2499 [('c', 'changelog', False, _('open changelog')),
2499 [('c', 'changelog', False, _('open changelog')),
2500 ('m', 'manifest', False, _('open manifest')),
2500 ('m', 'manifest', False, _('open manifest')),
2501 ('d', 'dump', False, _('dump index data'))],
2501 ('d', 'dump', False, _('dump index data'))],
2502 _('-c|-m|FILE'),
2502 _('-c|-m|FILE'),
2503 optionalrepo=True)
2503 optionalrepo=True)
2504 def debugrevlog(ui, repo, file_=None, **opts):
2504 def debugrevlog(ui, repo, file_=None, **opts):
2505 """show data and statistics about a revlog"""
2505 """show data and statistics about a revlog"""
2506 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2506 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2507
2507
2508 if opts.get("dump"):
2508 if opts.get("dump"):
2509 numrevs = len(r)
2509 numrevs = len(r)
2510 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2510 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2511 " rawsize totalsize compression heads\n")
2511 " rawsize totalsize compression heads\n")
2512 ts = 0
2512 ts = 0
2513 heads = set()
2513 heads = set()
2514 for rev in xrange(numrevs):
2514 for rev in xrange(numrevs):
2515 dbase = r.deltaparent(rev)
2515 dbase = r.deltaparent(rev)
2516 if dbase == -1:
2516 if dbase == -1:
2517 dbase = rev
2517 dbase = rev
2518 cbase = r.chainbase(rev)
2518 cbase = r.chainbase(rev)
2519 p1, p2 = r.parentrevs(rev)
2519 p1, p2 = r.parentrevs(rev)
2520 rs = r.rawsize(rev)
2520 rs = r.rawsize(rev)
2521 ts = ts + rs
2521 ts = ts + rs
2522 heads -= set(r.parentrevs(rev))
2522 heads -= set(r.parentrevs(rev))
2523 heads.add(rev)
2523 heads.add(rev)
2524 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2524 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2525 (rev, p1, p2, r.start(rev), r.end(rev),
2525 (rev, p1, p2, r.start(rev), r.end(rev),
2526 r.start(dbase), r.start(cbase),
2526 r.start(dbase), r.start(cbase),
2527 r.start(p1), r.start(p2),
2527 r.start(p1), r.start(p2),
2528 rs, ts, ts / r.end(rev), len(heads)))
2528 rs, ts, ts / r.end(rev), len(heads)))
2529 return 0
2529 return 0
2530
2530
2531 v = r.version
2531 v = r.version
2532 format = v & 0xFFFF
2532 format = v & 0xFFFF
2533 flags = []
2533 flags = []
2534 gdelta = False
2534 gdelta = False
2535 if v & revlog.REVLOGNGINLINEDATA:
2535 if v & revlog.REVLOGNGINLINEDATA:
2536 flags.append('inline')
2536 flags.append('inline')
2537 if v & revlog.REVLOGGENERALDELTA:
2537 if v & revlog.REVLOGGENERALDELTA:
2538 gdelta = True
2538 gdelta = True
2539 flags.append('generaldelta')
2539 flags.append('generaldelta')
2540 if not flags:
2540 if not flags:
2541 flags = ['(none)']
2541 flags = ['(none)']
2542
2542
2543 nummerges = 0
2543 nummerges = 0
2544 numfull = 0
2544 numfull = 0
2545 numprev = 0
2545 numprev = 0
2546 nump1 = 0
2546 nump1 = 0
2547 nump2 = 0
2547 nump2 = 0
2548 numother = 0
2548 numother = 0
2549 nump1prev = 0
2549 nump1prev = 0
2550 nump2prev = 0
2550 nump2prev = 0
2551 chainlengths = []
2551 chainlengths = []
2552
2552
2553 datasize = [None, 0, 0L]
2553 datasize = [None, 0, 0L]
2554 fullsize = [None, 0, 0L]
2554 fullsize = [None, 0, 0L]
2555 deltasize = [None, 0, 0L]
2555 deltasize = [None, 0, 0L]
2556
2556
2557 def addsize(size, l):
2557 def addsize(size, l):
2558 if l[0] is None or size < l[0]:
2558 if l[0] is None or size < l[0]:
2559 l[0] = size
2559 l[0] = size
2560 if size > l[1]:
2560 if size > l[1]:
2561 l[1] = size
2561 l[1] = size
2562 l[2] += size
2562 l[2] += size
2563
2563
2564 numrevs = len(r)
2564 numrevs = len(r)
2565 for rev in xrange(numrevs):
2565 for rev in xrange(numrevs):
2566 p1, p2 = r.parentrevs(rev)
2566 p1, p2 = r.parentrevs(rev)
2567 delta = r.deltaparent(rev)
2567 delta = r.deltaparent(rev)
2568 if format > 0:
2568 if format > 0:
2569 addsize(r.rawsize(rev), datasize)
2569 addsize(r.rawsize(rev), datasize)
2570 if p2 != nullrev:
2570 if p2 != nullrev:
2571 nummerges += 1
2571 nummerges += 1
2572 size = r.length(rev)
2572 size = r.length(rev)
2573 if delta == nullrev:
2573 if delta == nullrev:
2574 chainlengths.append(0)
2574 chainlengths.append(0)
2575 numfull += 1
2575 numfull += 1
2576 addsize(size, fullsize)
2576 addsize(size, fullsize)
2577 else:
2577 else:
2578 chainlengths.append(chainlengths[delta] + 1)
2578 chainlengths.append(chainlengths[delta] + 1)
2579 addsize(size, deltasize)
2579 addsize(size, deltasize)
2580 if delta == rev - 1:
2580 if delta == rev - 1:
2581 numprev += 1
2581 numprev += 1
2582 if delta == p1:
2582 if delta == p1:
2583 nump1prev += 1
2583 nump1prev += 1
2584 elif delta == p2:
2584 elif delta == p2:
2585 nump2prev += 1
2585 nump2prev += 1
2586 elif delta == p1:
2586 elif delta == p1:
2587 nump1 += 1
2587 nump1 += 1
2588 elif delta == p2:
2588 elif delta == p2:
2589 nump2 += 1
2589 nump2 += 1
2590 elif delta != nullrev:
2590 elif delta != nullrev:
2591 numother += 1
2591 numother += 1
2592
2592
2593 # Adjust size min value for empty cases
2593 # Adjust size min value for empty cases
2594 for size in (datasize, fullsize, deltasize):
2594 for size in (datasize, fullsize, deltasize):
2595 if size[0] is None:
2595 if size[0] is None:
2596 size[0] = 0
2596 size[0] = 0
2597
2597
2598 numdeltas = numrevs - numfull
2598 numdeltas = numrevs - numfull
2599 numoprev = numprev - nump1prev - nump2prev
2599 numoprev = numprev - nump1prev - nump2prev
2600 totalrawsize = datasize[2]
2600 totalrawsize = datasize[2]
2601 datasize[2] /= numrevs
2601 datasize[2] /= numrevs
2602 fulltotal = fullsize[2]
2602 fulltotal = fullsize[2]
2603 fullsize[2] /= numfull
2603 fullsize[2] /= numfull
2604 deltatotal = deltasize[2]
2604 deltatotal = deltasize[2]
2605 if numrevs - numfull > 0:
2605 if numrevs - numfull > 0:
2606 deltasize[2] /= numrevs - numfull
2606 deltasize[2] /= numrevs - numfull
2607 totalsize = fulltotal + deltatotal
2607 totalsize = fulltotal + deltatotal
2608 avgchainlen = sum(chainlengths) / numrevs
2608 avgchainlen = sum(chainlengths) / numrevs
2609 compratio = totalrawsize / totalsize
2609 compratio = totalrawsize / totalsize
2610
2610
2611 basedfmtstr = '%%%dd\n'
2611 basedfmtstr = '%%%dd\n'
2612 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2612 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2613
2613
2614 def dfmtstr(max):
2614 def dfmtstr(max):
2615 return basedfmtstr % len(str(max))
2615 return basedfmtstr % len(str(max))
2616 def pcfmtstr(max, padding=0):
2616 def pcfmtstr(max, padding=0):
2617 return basepcfmtstr % (len(str(max)), ' ' * padding)
2617 return basepcfmtstr % (len(str(max)), ' ' * padding)
2618
2618
2619 def pcfmt(value, total):
2619 def pcfmt(value, total):
2620 return (value, 100 * float(value) / total)
2620 return (value, 100 * float(value) / total)
2621
2621
2622 ui.write(('format : %d\n') % format)
2622 ui.write(('format : %d\n') % format)
2623 ui.write(('flags : %s\n') % ', '.join(flags))
2623 ui.write(('flags : %s\n') % ', '.join(flags))
2624
2624
2625 ui.write('\n')
2625 ui.write('\n')
2626 fmt = pcfmtstr(totalsize)
2626 fmt = pcfmtstr(totalsize)
2627 fmt2 = dfmtstr(totalsize)
2627 fmt2 = dfmtstr(totalsize)
2628 ui.write(('revisions : ') + fmt2 % numrevs)
2628 ui.write(('revisions : ') + fmt2 % numrevs)
2629 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2629 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2630 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2630 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2631 ui.write(('revisions : ') + fmt2 % numrevs)
2631 ui.write(('revisions : ') + fmt2 % numrevs)
2632 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2632 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2633 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2633 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2634 ui.write(('revision size : ') + fmt2 % totalsize)
2634 ui.write(('revision size : ') + fmt2 % totalsize)
2635 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2635 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2636 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2636 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2637
2637
2638 ui.write('\n')
2638 ui.write('\n')
2639 fmt = dfmtstr(max(avgchainlen, compratio))
2639 fmt = dfmtstr(max(avgchainlen, compratio))
2640 ui.write(('avg chain length : ') + fmt % avgchainlen)
2640 ui.write(('avg chain length : ') + fmt % avgchainlen)
2641 ui.write(('compression ratio : ') + fmt % compratio)
2641 ui.write(('compression ratio : ') + fmt % compratio)
2642
2642
2643 if format > 0:
2643 if format > 0:
2644 ui.write('\n')
2644 ui.write('\n')
2645 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2645 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2646 % tuple(datasize))
2646 % tuple(datasize))
2647 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2647 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2648 % tuple(fullsize))
2648 % tuple(fullsize))
2649 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2649 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2650 % tuple(deltasize))
2650 % tuple(deltasize))
2651
2651
2652 if numdeltas > 0:
2652 if numdeltas > 0:
2653 ui.write('\n')
2653 ui.write('\n')
2654 fmt = pcfmtstr(numdeltas)
2654 fmt = pcfmtstr(numdeltas)
2655 fmt2 = pcfmtstr(numdeltas, 4)
2655 fmt2 = pcfmtstr(numdeltas, 4)
2656 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2656 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2657 if numprev > 0:
2657 if numprev > 0:
2658 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2658 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2659 numprev))
2659 numprev))
2660 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2660 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2661 numprev))
2661 numprev))
2662 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2662 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2663 numprev))
2663 numprev))
2664 if gdelta:
2664 if gdelta:
2665 ui.write(('deltas against p1 : ')
2665 ui.write(('deltas against p1 : ')
2666 + fmt % pcfmt(nump1, numdeltas))
2666 + fmt % pcfmt(nump1, numdeltas))
2667 ui.write(('deltas against p2 : ')
2667 ui.write(('deltas against p2 : ')
2668 + fmt % pcfmt(nump2, numdeltas))
2668 + fmt % pcfmt(nump2, numdeltas))
2669 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2669 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2670 numdeltas))
2670 numdeltas))
2671
2671
2672 @command('debugrevspec',
2672 @command('debugrevspec',
2673 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2673 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2674 ('REVSPEC'))
2674 ('REVSPEC'))
2675 def debugrevspec(ui, repo, expr, **opts):
2675 def debugrevspec(ui, repo, expr, **opts):
2676 """parse and apply a revision specification
2676 """parse and apply a revision specification
2677
2677
2678 Use --verbose to print the parsed tree before and after aliases
2678 Use --verbose to print the parsed tree before and after aliases
2679 expansion.
2679 expansion.
2680 """
2680 """
2681 if ui.verbose:
2681 if ui.verbose:
2682 tree = revset.parse(expr)[0]
2682 tree = revset.parse(expr)[0]
2683 ui.note(revset.prettyformat(tree), "\n")
2683 ui.note(revset.prettyformat(tree), "\n")
2684 newtree = revset.findaliases(ui, tree)
2684 newtree = revset.findaliases(ui, tree)
2685 if newtree != tree:
2685 if newtree != tree:
2686 ui.note(revset.prettyformat(newtree), "\n")
2686 ui.note(revset.prettyformat(newtree), "\n")
2687 if opts["optimize"]:
2687 if opts["optimize"]:
2688 weight, optimizedtree = revset.optimize(newtree, True)
2688 weight, optimizedtree = revset.optimize(newtree, True)
2689 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2689 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2690 func = revset.match(ui, expr)
2690 func = revset.match(ui, expr)
2691 for c in func(repo, revset.spanset(repo)):
2691 for c in func(repo, revset.spanset(repo)):
2692 ui.write("%s\n" % c)
2692 ui.write("%s\n" % c)
2693
2693
2694 @command('debugsetparents', [], _('REV1 [REV2]'))
2694 @command('debugsetparents', [], _('REV1 [REV2]'))
2695 def debugsetparents(ui, repo, rev1, rev2=None):
2695 def debugsetparents(ui, repo, rev1, rev2=None):
2696 """manually set the parents of the current working directory
2696 """manually set the parents of the current working directory
2697
2697
2698 This is useful for writing repository conversion tools, but should
2698 This is useful for writing repository conversion tools, but should
2699 be used with care.
2699 be used with care.
2700
2700
2701 Returns 0 on success.
2701 Returns 0 on success.
2702 """
2702 """
2703
2703
2704 r1 = scmutil.revsingle(repo, rev1).node()
2704 r1 = scmutil.revsingle(repo, rev1).node()
2705 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2705 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2706
2706
2707 wlock = repo.wlock()
2707 wlock = repo.wlock()
2708 try:
2708 try:
2709 repo.setparents(r1, r2)
2709 repo.setparents(r1, r2)
2710 finally:
2710 finally:
2711 wlock.release()
2711 wlock.release()
2712
2712
2713 @command('debugdirstate|debugstate',
2713 @command('debugdirstate|debugstate',
2714 [('', 'nodates', None, _('do not display the saved mtime')),
2714 [('', 'nodates', None, _('do not display the saved mtime')),
2715 ('', 'datesort', None, _('sort by saved mtime'))],
2715 ('', 'datesort', None, _('sort by saved mtime'))],
2716 _('[OPTION]...'))
2716 _('[OPTION]...'))
2717 def debugstate(ui, repo, nodates=None, datesort=None):
2717 def debugstate(ui, repo, nodates=None, datesort=None):
2718 """show the contents of the current dirstate"""
2718 """show the contents of the current dirstate"""
2719 timestr = ""
2719 timestr = ""
2720 showdate = not nodates
2720 showdate = not nodates
2721 if datesort:
2721 if datesort:
2722 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2722 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2723 else:
2723 else:
2724 keyfunc = None # sort by filename
2724 keyfunc = None # sort by filename
2725 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2725 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2726 if showdate:
2726 if showdate:
2727 if ent[3] == -1:
2727 if ent[3] == -1:
2728 # Pad or slice to locale representation
2728 # Pad or slice to locale representation
2729 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2729 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2730 time.localtime(0)))
2730 time.localtime(0)))
2731 timestr = 'unset'
2731 timestr = 'unset'
2732 timestr = (timestr[:locale_len] +
2732 timestr = (timestr[:locale_len] +
2733 ' ' * (locale_len - len(timestr)))
2733 ' ' * (locale_len - len(timestr)))
2734 else:
2734 else:
2735 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2735 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2736 time.localtime(ent[3]))
2736 time.localtime(ent[3]))
2737 if ent[1] & 020000:
2737 if ent[1] & 020000:
2738 mode = 'lnk'
2738 mode = 'lnk'
2739 else:
2739 else:
2740 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2740 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2741 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2741 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2742 for f in repo.dirstate.copies():
2742 for f in repo.dirstate.copies():
2743 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2743 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2744
2744
2745 @command('debugsub',
2745 @command('debugsub',
2746 [('r', 'rev', '',
2746 [('r', 'rev', '',
2747 _('revision to check'), _('REV'))],
2747 _('revision to check'), _('REV'))],
2748 _('[-r REV] [REV]'))
2748 _('[-r REV] [REV]'))
2749 def debugsub(ui, repo, rev=None):
2749 def debugsub(ui, repo, rev=None):
2750 ctx = scmutil.revsingle(repo, rev, None)
2750 ctx = scmutil.revsingle(repo, rev, None)
2751 for k, v in sorted(ctx.substate.items()):
2751 for k, v in sorted(ctx.substate.items()):
2752 ui.write(('path %s\n') % k)
2752 ui.write(('path %s\n') % k)
2753 ui.write((' source %s\n') % v[0])
2753 ui.write((' source %s\n') % v[0])
2754 ui.write((' revision %s\n') % v[1])
2754 ui.write((' revision %s\n') % v[1])
2755
2755
2756 @command('debugsuccessorssets',
2756 @command('debugsuccessorssets',
2757 [],
2757 [],
2758 _('[REV]'))
2758 _('[REV]'))
2759 def debugsuccessorssets(ui, repo, *revs):
2759 def debugsuccessorssets(ui, repo, *revs):
2760 """show set of successors for revision
2760 """show set of successors for revision
2761
2761
2762 A successors set of changeset A is a consistent group of revisions that
2762 A successors set of changeset A is a consistent group of revisions that
2763 succeed A. It contains non-obsolete changesets only.
2763 succeed A. It contains non-obsolete changesets only.
2764
2764
2765 In most cases a changeset A has a single successors set containing a single
2765 In most cases a changeset A has a single successors set containing a single
2766 successor (changeset A replaced by A').
2766 successor (changeset A replaced by A').
2767
2767
2768 A changeset that is made obsolete with no successors are called "pruned".
2768 A changeset that is made obsolete with no successors are called "pruned".
2769 Such changesets have no successors sets at all.
2769 Such changesets have no successors sets at all.
2770
2770
2771 A changeset that has been "split" will have a successors set containing
2771 A changeset that has been "split" will have a successors set containing
2772 more than one successor.
2772 more than one successor.
2773
2773
2774 A changeset that has been rewritten in multiple different ways is called
2774 A changeset that has been rewritten in multiple different ways is called
2775 "divergent". Such changesets have multiple successor sets (each of which
2775 "divergent". Such changesets have multiple successor sets (each of which
2776 may also be split, i.e. have multiple successors).
2776 may also be split, i.e. have multiple successors).
2777
2777
2778 Results are displayed as follows::
2778 Results are displayed as follows::
2779
2779
2780 <rev1>
2780 <rev1>
2781 <successors-1A>
2781 <successors-1A>
2782 <rev2>
2782 <rev2>
2783 <successors-2A>
2783 <successors-2A>
2784 <successors-2B1> <successors-2B2> <successors-2B3>
2784 <successors-2B1> <successors-2B2> <successors-2B3>
2785
2785
2786 Here rev2 has two possible (i.e. divergent) successors sets. The first
2786 Here rev2 has two possible (i.e. divergent) successors sets. The first
2787 holds one element, whereas the second holds three (i.e. the changeset has
2787 holds one element, whereas the second holds three (i.e. the changeset has
2788 been split).
2788 been split).
2789 """
2789 """
2790 # passed to successorssets caching computation from one call to another
2790 # passed to successorssets caching computation from one call to another
2791 cache = {}
2791 cache = {}
2792 ctx2str = str
2792 ctx2str = str
2793 node2str = short
2793 node2str = short
2794 if ui.debug():
2794 if ui.debug():
2795 def ctx2str(ctx):
2795 def ctx2str(ctx):
2796 return ctx.hex()
2796 return ctx.hex()
2797 node2str = hex
2797 node2str = hex
2798 for rev in scmutil.revrange(repo, revs):
2798 for rev in scmutil.revrange(repo, revs):
2799 ctx = repo[rev]
2799 ctx = repo[rev]
2800 ui.write('%s\n'% ctx2str(ctx))
2800 ui.write('%s\n'% ctx2str(ctx))
2801 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2801 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2802 if succsset:
2802 if succsset:
2803 ui.write(' ')
2803 ui.write(' ')
2804 ui.write(node2str(succsset[0]))
2804 ui.write(node2str(succsset[0]))
2805 for node in succsset[1:]:
2805 for node in succsset[1:]:
2806 ui.write(' ')
2806 ui.write(' ')
2807 ui.write(node2str(node))
2807 ui.write(node2str(node))
2808 ui.write('\n')
2808 ui.write('\n')
2809
2809
2810 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2810 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2811 def debugwalk(ui, repo, *pats, **opts):
2811 def debugwalk(ui, repo, *pats, **opts):
2812 """show how files match on given patterns"""
2812 """show how files match on given patterns"""
2813 m = scmutil.match(repo[None], pats, opts)
2813 m = scmutil.match(repo[None], pats, opts)
2814 items = list(repo.walk(m))
2814 items = list(repo.walk(m))
2815 if not items:
2815 if not items:
2816 return
2816 return
2817 f = lambda fn: fn
2817 f = lambda fn: fn
2818 if ui.configbool('ui', 'slash') and os.sep != '/':
2818 if ui.configbool('ui', 'slash') and os.sep != '/':
2819 f = lambda fn: util.normpath(fn)
2819 f = lambda fn: util.normpath(fn)
2820 fmt = 'f %%-%ds %%-%ds %%s' % (
2820 fmt = 'f %%-%ds %%-%ds %%s' % (
2821 max([len(abs) for abs in items]),
2821 max([len(abs) for abs in items]),
2822 max([len(m.rel(abs)) for abs in items]))
2822 max([len(m.rel(abs)) for abs in items]))
2823 for abs in items:
2823 for abs in items:
2824 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2824 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2825 ui.write("%s\n" % line.rstrip())
2825 ui.write("%s\n" % line.rstrip())
2826
2826
2827 @command('debugwireargs',
2827 @command('debugwireargs',
2828 [('', 'three', '', 'three'),
2828 [('', 'three', '', 'three'),
2829 ('', 'four', '', 'four'),
2829 ('', 'four', '', 'four'),
2830 ('', 'five', '', 'five'),
2830 ('', 'five', '', 'five'),
2831 ] + remoteopts,
2831 ] + remoteopts,
2832 _('REPO [OPTIONS]... [ONE [TWO]]'),
2832 _('REPO [OPTIONS]... [ONE [TWO]]'),
2833 norepo=True)
2833 norepo=True)
2834 def debugwireargs(ui, repopath, *vals, **opts):
2834 def debugwireargs(ui, repopath, *vals, **opts):
2835 repo = hg.peer(ui, opts, repopath)
2835 repo = hg.peer(ui, opts, repopath)
2836 for opt in remoteopts:
2836 for opt in remoteopts:
2837 del opts[opt[1]]
2837 del opts[opt[1]]
2838 args = {}
2838 args = {}
2839 for k, v in opts.iteritems():
2839 for k, v in opts.iteritems():
2840 if v:
2840 if v:
2841 args[k] = v
2841 args[k] = v
2842 # run twice to check that we don't mess up the stream for the next command
2842 # run twice to check that we don't mess up the stream for the next command
2843 res1 = repo.debugwireargs(*vals, **args)
2843 res1 = repo.debugwireargs(*vals, **args)
2844 res2 = repo.debugwireargs(*vals, **args)
2844 res2 = repo.debugwireargs(*vals, **args)
2845 ui.write("%s\n" % res1)
2845 ui.write("%s\n" % res1)
2846 if res1 != res2:
2846 if res1 != res2:
2847 ui.warn("%s\n" % res2)
2847 ui.warn("%s\n" % res2)
2848
2848
2849 @command('^diff',
2849 @command('^diff',
2850 [('r', 'rev', [], _('revision'), _('REV')),
2850 [('r', 'rev', [], _('revision'), _('REV')),
2851 ('c', 'change', '', _('change made by revision'), _('REV'))
2851 ('c', 'change', '', _('change made by revision'), _('REV'))
2852 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2852 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2853 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2853 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2854 inferrepo=True)
2854 inferrepo=True)
2855 def diff(ui, repo, *pats, **opts):
2855 def diff(ui, repo, *pats, **opts):
2856 """diff repository (or selected files)
2856 """diff repository (or selected files)
2857
2857
2858 Show differences between revisions for the specified files.
2858 Show differences between revisions for the specified files.
2859
2859
2860 Differences between files are shown using the unified diff format.
2860 Differences between files are shown using the unified diff format.
2861
2861
2862 .. note::
2862 .. note::
2863
2863
2864 diff may generate unexpected results for merges, as it will
2864 diff may generate unexpected results for merges, as it will
2865 default to comparing against the working directory's first
2865 default to comparing against the working directory's first
2866 parent changeset if no revisions are specified.
2866 parent changeset if no revisions are specified.
2867
2867
2868 When two revision arguments are given, then changes are shown
2868 When two revision arguments are given, then changes are shown
2869 between those revisions. If only one revision is specified then
2869 between those revisions. If only one revision is specified then
2870 that revision is compared to the working directory, and, when no
2870 that revision is compared to the working directory, and, when no
2871 revisions are specified, the working directory files are compared
2871 revisions are specified, the working directory files are compared
2872 to its parent.
2872 to its parent.
2873
2873
2874 Alternatively you can specify -c/--change with a revision to see
2874 Alternatively you can specify -c/--change with a revision to see
2875 the changes in that changeset relative to its first parent.
2875 the changes in that changeset relative to its first parent.
2876
2876
2877 Without the -a/--text option, diff will avoid generating diffs of
2877 Without the -a/--text option, diff will avoid generating diffs of
2878 files it detects as binary. With -a, diff will generate a diff
2878 files it detects as binary. With -a, diff will generate a diff
2879 anyway, probably with undesirable results.
2879 anyway, probably with undesirable results.
2880
2880
2881 Use the -g/--git option to generate diffs in the git extended diff
2881 Use the -g/--git option to generate diffs in the git extended diff
2882 format. For more information, read :hg:`help diffs`.
2882 format. For more information, read :hg:`help diffs`.
2883
2883
2884 .. container:: verbose
2884 .. container:: verbose
2885
2885
2886 Examples:
2886 Examples:
2887
2887
2888 - compare a file in the current working directory to its parent::
2888 - compare a file in the current working directory to its parent::
2889
2889
2890 hg diff foo.c
2890 hg diff foo.c
2891
2891
2892 - compare two historical versions of a directory, with rename info::
2892 - compare two historical versions of a directory, with rename info::
2893
2893
2894 hg diff --git -r 1.0:1.2 lib/
2894 hg diff --git -r 1.0:1.2 lib/
2895
2895
2896 - get change stats relative to the last change on some date::
2896 - get change stats relative to the last change on some date::
2897
2897
2898 hg diff --stat -r "date('may 2')"
2898 hg diff --stat -r "date('may 2')"
2899
2899
2900 - diff all newly-added files that contain a keyword::
2900 - diff all newly-added files that contain a keyword::
2901
2901
2902 hg diff "set:added() and grep(GNU)"
2902 hg diff "set:added() and grep(GNU)"
2903
2903
2904 - compare a revision and its parents::
2904 - compare a revision and its parents::
2905
2905
2906 hg diff -c 9353 # compare against first parent
2906 hg diff -c 9353 # compare against first parent
2907 hg diff -r 9353^:9353 # same using revset syntax
2907 hg diff -r 9353^:9353 # same using revset syntax
2908 hg diff -r 9353^2:9353 # compare against the second parent
2908 hg diff -r 9353^2:9353 # compare against the second parent
2909
2909
2910 Returns 0 on success.
2910 Returns 0 on success.
2911 """
2911 """
2912
2912
2913 revs = opts.get('rev')
2913 revs = opts.get('rev')
2914 change = opts.get('change')
2914 change = opts.get('change')
2915 stat = opts.get('stat')
2915 stat = opts.get('stat')
2916 reverse = opts.get('reverse')
2916 reverse = opts.get('reverse')
2917
2917
2918 if revs and change:
2918 if revs and change:
2919 msg = _('cannot specify --rev and --change at the same time')
2919 msg = _('cannot specify --rev and --change at the same time')
2920 raise util.Abort(msg)
2920 raise util.Abort(msg)
2921 elif change:
2921 elif change:
2922 node2 = scmutil.revsingle(repo, change, None).node()
2922 node2 = scmutil.revsingle(repo, change, None).node()
2923 node1 = repo[node2].p1().node()
2923 node1 = repo[node2].p1().node()
2924 else:
2924 else:
2925 node1, node2 = scmutil.revpair(repo, revs)
2925 node1, node2 = scmutil.revpair(repo, revs)
2926
2926
2927 if reverse:
2927 if reverse:
2928 node1, node2 = node2, node1
2928 node1, node2 = node2, node1
2929
2929
2930 diffopts = patch.diffopts(ui, opts)
2930 diffopts = patch.diffopts(ui, opts)
2931 m = scmutil.match(repo[node2], pats, opts)
2931 m = scmutil.match(repo[node2], pats, opts)
2932 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2932 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2933 listsubrepos=opts.get('subrepos'))
2933 listsubrepos=opts.get('subrepos'))
2934
2934
2935 @command('^export',
2935 @command('^export',
2936 [('o', 'output', '',
2936 [('o', 'output', '',
2937 _('print output to file with formatted name'), _('FORMAT')),
2937 _('print output to file with formatted name'), _('FORMAT')),
2938 ('', 'switch-parent', None, _('diff against the second parent')),
2938 ('', 'switch-parent', None, _('diff against the second parent')),
2939 ('r', 'rev', [], _('revisions to export'), _('REV')),
2939 ('r', 'rev', [], _('revisions to export'), _('REV')),
2940 ] + diffopts,
2940 ] + diffopts,
2941 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2941 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2942 def export(ui, repo, *changesets, **opts):
2942 def export(ui, repo, *changesets, **opts):
2943 """dump the header and diffs for one or more changesets
2943 """dump the header and diffs for one or more changesets
2944
2944
2945 Print the changeset header and diffs for one or more revisions.
2945 Print the changeset header and diffs for one or more revisions.
2946 If no revision is given, the parent of the working directory is used.
2946 If no revision is given, the parent of the working directory is used.
2947
2947
2948 The information shown in the changeset header is: author, date,
2948 The information shown in the changeset header is: author, date,
2949 branch name (if non-default), changeset hash, parent(s) and commit
2949 branch name (if non-default), changeset hash, parent(s) and commit
2950 comment.
2950 comment.
2951
2951
2952 .. note::
2952 .. note::
2953
2953
2954 export may generate unexpected diff output for merge
2954 export may generate unexpected diff output for merge
2955 changesets, as it will compare the merge changeset against its
2955 changesets, as it will compare the merge changeset against its
2956 first parent only.
2956 first parent only.
2957
2957
2958 Output may be to a file, in which case the name of the file is
2958 Output may be to a file, in which case the name of the file is
2959 given using a format string. The formatting rules are as follows:
2959 given using a format string. The formatting rules are as follows:
2960
2960
2961 :``%%``: literal "%" character
2961 :``%%``: literal "%" character
2962 :``%H``: changeset hash (40 hexadecimal digits)
2962 :``%H``: changeset hash (40 hexadecimal digits)
2963 :``%N``: number of patches being generated
2963 :``%N``: number of patches being generated
2964 :``%R``: changeset revision number
2964 :``%R``: changeset revision number
2965 :``%b``: basename of the exporting repository
2965 :``%b``: basename of the exporting repository
2966 :``%h``: short-form changeset hash (12 hexadecimal digits)
2966 :``%h``: short-form changeset hash (12 hexadecimal digits)
2967 :``%m``: first line of the commit message (only alphanumeric characters)
2967 :``%m``: first line of the commit message (only alphanumeric characters)
2968 :``%n``: zero-padded sequence number, starting at 1
2968 :``%n``: zero-padded sequence number, starting at 1
2969 :``%r``: zero-padded changeset revision number
2969 :``%r``: zero-padded changeset revision number
2970
2970
2971 Without the -a/--text option, export will avoid generating diffs
2971 Without the -a/--text option, export will avoid generating diffs
2972 of files it detects as binary. With -a, export will generate a
2972 of files it detects as binary. With -a, export will generate a
2973 diff anyway, probably with undesirable results.
2973 diff anyway, probably with undesirable results.
2974
2974
2975 Use the -g/--git option to generate diffs in the git extended diff
2975 Use the -g/--git option to generate diffs in the git extended diff
2976 format. See :hg:`help diffs` for more information.
2976 format. See :hg:`help diffs` for more information.
2977
2977
2978 With the --switch-parent option, the diff will be against the
2978 With the --switch-parent option, the diff will be against the
2979 second parent. It can be useful to review a merge.
2979 second parent. It can be useful to review a merge.
2980
2980
2981 .. container:: verbose
2981 .. container:: verbose
2982
2982
2983 Examples:
2983 Examples:
2984
2984
2985 - use export and import to transplant a bugfix to the current
2985 - use export and import to transplant a bugfix to the current
2986 branch::
2986 branch::
2987
2987
2988 hg export -r 9353 | hg import -
2988 hg export -r 9353 | hg import -
2989
2989
2990 - export all the changesets between two revisions to a file with
2990 - export all the changesets between two revisions to a file with
2991 rename information::
2991 rename information::
2992
2992
2993 hg export --git -r 123:150 > changes.txt
2993 hg export --git -r 123:150 > changes.txt
2994
2994
2995 - split outgoing changes into a series of patches with
2995 - split outgoing changes into a series of patches with
2996 descriptive names::
2996 descriptive names::
2997
2997
2998 hg export -r "outgoing()" -o "%n-%m.patch"
2998 hg export -r "outgoing()" -o "%n-%m.patch"
2999
2999
3000 Returns 0 on success.
3000 Returns 0 on success.
3001 """
3001 """
3002 changesets += tuple(opts.get('rev', []))
3002 changesets += tuple(opts.get('rev', []))
3003 if not changesets:
3003 if not changesets:
3004 changesets = ['.']
3004 changesets = ['.']
3005 revs = scmutil.revrange(repo, changesets)
3005 revs = scmutil.revrange(repo, changesets)
3006 if not revs:
3006 if not revs:
3007 raise util.Abort(_("export requires at least one changeset"))
3007 raise util.Abort(_("export requires at least one changeset"))
3008 if len(revs) > 1:
3008 if len(revs) > 1:
3009 ui.note(_('exporting patches:\n'))
3009 ui.note(_('exporting patches:\n'))
3010 else:
3010 else:
3011 ui.note(_('exporting patch:\n'))
3011 ui.note(_('exporting patch:\n'))
3012 cmdutil.export(repo, revs, template=opts.get('output'),
3012 cmdutil.export(repo, revs, template=opts.get('output'),
3013 switch_parent=opts.get('switch_parent'),
3013 switch_parent=opts.get('switch_parent'),
3014 opts=patch.diffopts(ui, opts))
3014 opts=patch.diffopts(ui, opts))
3015
3015
3016 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3016 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3017 def forget(ui, repo, *pats, **opts):
3017 def forget(ui, repo, *pats, **opts):
3018 """forget the specified files on the next commit
3018 """forget the specified files on the next commit
3019
3019
3020 Mark the specified files so they will no longer be tracked
3020 Mark the specified files so they will no longer be tracked
3021 after the next commit.
3021 after the next commit.
3022
3022
3023 This only removes files from the current branch, not from the
3023 This only removes files from the current branch, not from the
3024 entire project history, and it does not delete them from the
3024 entire project history, and it does not delete them from the
3025 working directory.
3025 working directory.
3026
3026
3027 To undo a forget before the next commit, see :hg:`add`.
3027 To undo a forget before the next commit, see :hg:`add`.
3028
3028
3029 .. container:: verbose
3029 .. container:: verbose
3030
3030
3031 Examples:
3031 Examples:
3032
3032
3033 - forget newly-added binary files::
3033 - forget newly-added binary files::
3034
3034
3035 hg forget "set:added() and binary()"
3035 hg forget "set:added() and binary()"
3036
3036
3037 - forget files that would be excluded by .hgignore::
3037 - forget files that would be excluded by .hgignore::
3038
3038
3039 hg forget "set:hgignore()"
3039 hg forget "set:hgignore()"
3040
3040
3041 Returns 0 on success.
3041 Returns 0 on success.
3042 """
3042 """
3043
3043
3044 if not pats:
3044 if not pats:
3045 raise util.Abort(_('no files specified'))
3045 raise util.Abort(_('no files specified'))
3046
3046
3047 m = scmutil.match(repo[None], pats, opts)
3047 m = scmutil.match(repo[None], pats, opts)
3048 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3048 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3049 return rejected and 1 or 0
3049 return rejected and 1 or 0
3050
3050
3051 @command(
3051 @command(
3052 'graft',
3052 'graft',
3053 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3053 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3054 ('c', 'continue', False, _('resume interrupted graft')),
3054 ('c', 'continue', False, _('resume interrupted graft')),
3055 ('e', 'edit', False, _('invoke editor on commit messages')),
3055 ('e', 'edit', False, _('invoke editor on commit messages')),
3056 ('', 'log', None, _('append graft info to log message')),
3056 ('', 'log', None, _('append graft info to log message')),
3057 ('D', 'currentdate', False,
3057 ('D', 'currentdate', False,
3058 _('record the current date as commit date')),
3058 _('record the current date as commit date')),
3059 ('U', 'currentuser', False,
3059 ('U', 'currentuser', False,
3060 _('record the current user as committer'), _('DATE'))]
3060 _('record the current user as committer'), _('DATE'))]
3061 + commitopts2 + mergetoolopts + dryrunopts,
3061 + commitopts2 + mergetoolopts + dryrunopts,
3062 _('[OPTION]... [-r] REV...'))
3062 _('[OPTION]... [-r] REV...'))
3063 def graft(ui, repo, *revs, **opts):
3063 def graft(ui, repo, *revs, **opts):
3064 '''copy changes from other branches onto the current branch
3064 '''copy changes from other branches onto the current branch
3065
3065
3066 This command uses Mercurial's merge logic to copy individual
3066 This command uses Mercurial's merge logic to copy individual
3067 changes from other branches without merging branches in the
3067 changes from other branches without merging branches in the
3068 history graph. This is sometimes known as 'backporting' or
3068 history graph. This is sometimes known as 'backporting' or
3069 'cherry-picking'. By default, graft will copy user, date, and
3069 'cherry-picking'. By default, graft will copy user, date, and
3070 description from the source changesets.
3070 description from the source changesets.
3071
3071
3072 Changesets that are ancestors of the current revision, that have
3072 Changesets that are ancestors of the current revision, that have
3073 already been grafted, or that are merges will be skipped.
3073 already been grafted, or that are merges will be skipped.
3074
3074
3075 If --log is specified, log messages will have a comment appended
3075 If --log is specified, log messages will have a comment appended
3076 of the form::
3076 of the form::
3077
3077
3078 (grafted from CHANGESETHASH)
3078 (grafted from CHANGESETHASH)
3079
3079
3080 If a graft merge results in conflicts, the graft process is
3080 If a graft merge results in conflicts, the graft process is
3081 interrupted so that the current merge can be manually resolved.
3081 interrupted so that the current merge can be manually resolved.
3082 Once all conflicts are addressed, the graft process can be
3082 Once all conflicts are addressed, the graft process can be
3083 continued with the -c/--continue option.
3083 continued with the -c/--continue option.
3084
3084
3085 .. note::
3085 .. note::
3086
3086
3087 The -c/--continue option does not reapply earlier options.
3087 The -c/--continue option does not reapply earlier options.
3088
3088
3089 .. container:: verbose
3089 .. container:: verbose
3090
3090
3091 Examples:
3091 Examples:
3092
3092
3093 - copy a single change to the stable branch and edit its description::
3093 - copy a single change to the stable branch and edit its description::
3094
3094
3095 hg update stable
3095 hg update stable
3096 hg graft --edit 9393
3096 hg graft --edit 9393
3097
3097
3098 - graft a range of changesets with one exception, updating dates::
3098 - graft a range of changesets with one exception, updating dates::
3099
3099
3100 hg graft -D "2085::2093 and not 2091"
3100 hg graft -D "2085::2093 and not 2091"
3101
3101
3102 - continue a graft after resolving conflicts::
3102 - continue a graft after resolving conflicts::
3103
3103
3104 hg graft -c
3104 hg graft -c
3105
3105
3106 - show the source of a grafted changeset::
3106 - show the source of a grafted changeset::
3107
3107
3108 hg log --debug -r .
3108 hg log --debug -r .
3109
3109
3110 Returns 0 on successful completion.
3110 Returns 0 on successful completion.
3111 '''
3111 '''
3112
3112
3113 revs = list(revs)
3113 revs = list(revs)
3114 revs.extend(opts['rev'])
3114 revs.extend(opts['rev'])
3115
3115
3116 if not opts.get('user') and opts.get('currentuser'):
3116 if not opts.get('user') and opts.get('currentuser'):
3117 opts['user'] = ui.username()
3117 opts['user'] = ui.username()
3118 if not opts.get('date') and opts.get('currentdate'):
3118 if not opts.get('date') and opts.get('currentdate'):
3119 opts['date'] = "%d %d" % util.makedate()
3119 opts['date'] = "%d %d" % util.makedate()
3120
3120
3121 editor = cmdutil.getcommiteditor(**opts)
3121 editor = cmdutil.getcommiteditor(**opts)
3122
3122
3123 cont = False
3123 cont = False
3124 if opts['continue']:
3124 if opts['continue']:
3125 cont = True
3125 cont = True
3126 if revs:
3126 if revs:
3127 raise util.Abort(_("can't specify --continue and revisions"))
3127 raise util.Abort(_("can't specify --continue and revisions"))
3128 # read in unfinished revisions
3128 # read in unfinished revisions
3129 try:
3129 try:
3130 nodes = repo.opener.read('graftstate').splitlines()
3130 nodes = repo.opener.read('graftstate').splitlines()
3131 revs = [repo[node].rev() for node in nodes]
3131 revs = [repo[node].rev() for node in nodes]
3132 except IOError, inst:
3132 except IOError, inst:
3133 if inst.errno != errno.ENOENT:
3133 if inst.errno != errno.ENOENT:
3134 raise
3134 raise
3135 raise util.Abort(_("no graft state found, can't continue"))
3135 raise util.Abort(_("no graft state found, can't continue"))
3136 else:
3136 else:
3137 cmdutil.checkunfinished(repo)
3137 cmdutil.checkunfinished(repo)
3138 cmdutil.bailifchanged(repo)
3138 cmdutil.bailifchanged(repo)
3139 if not revs:
3139 if not revs:
3140 raise util.Abort(_('no revisions specified'))
3140 raise util.Abort(_('no revisions specified'))
3141 revs = scmutil.revrange(repo, revs)
3141 revs = scmutil.revrange(repo, revs)
3142
3142
3143 # check for merges
3143 # check for merges
3144 for rev in repo.revs('%ld and merge()', revs):
3144 for rev in repo.revs('%ld and merge()', revs):
3145 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3145 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3146 revs.remove(rev)
3146 revs.remove(rev)
3147 if not revs:
3147 if not revs:
3148 return -1
3148 return -1
3149
3149
3150 # check for ancestors of dest branch
3150 # check for ancestors of dest branch
3151 crev = repo['.'].rev()
3151 crev = repo['.'].rev()
3152 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3152 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3153 # Cannot use x.remove(y) on smart set, this has to be a list.
3153 # Cannot use x.remove(y) on smart set, this has to be a list.
3154 # XXX make this lazy in the future
3154 # XXX make this lazy in the future
3155 revs = list(revs)
3155 revs = list(revs)
3156 # don't mutate while iterating, create a copy
3156 # don't mutate while iterating, create a copy
3157 for rev in list(revs):
3157 for rev in list(revs):
3158 if rev in ancestors:
3158 if rev in ancestors:
3159 ui.warn(_('skipping ancestor revision %s\n') % rev)
3159 ui.warn(_('skipping ancestor revision %s\n') % rev)
3160 # XXX remove on list is slow
3160 # XXX remove on list is slow
3161 revs.remove(rev)
3161 revs.remove(rev)
3162 if not revs:
3162 if not revs:
3163 return -1
3163 return -1
3164
3164
3165 # analyze revs for earlier grafts
3165 # analyze revs for earlier grafts
3166 ids = {}
3166 ids = {}
3167 for ctx in repo.set("%ld", revs):
3167 for ctx in repo.set("%ld", revs):
3168 ids[ctx.hex()] = ctx.rev()
3168 ids[ctx.hex()] = ctx.rev()
3169 n = ctx.extra().get('source')
3169 n = ctx.extra().get('source')
3170 if n:
3170 if n:
3171 ids[n] = ctx.rev()
3171 ids[n] = ctx.rev()
3172
3172
3173 # check ancestors for earlier grafts
3173 # check ancestors for earlier grafts
3174 ui.debug('scanning for duplicate grafts\n')
3174 ui.debug('scanning for duplicate grafts\n')
3175
3175
3176 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3176 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3177 ctx = repo[rev]
3177 ctx = repo[rev]
3178 n = ctx.extra().get('source')
3178 n = ctx.extra().get('source')
3179 if n in ids:
3179 if n in ids:
3180 r = repo[n].rev()
3180 r = repo[n].rev()
3181 if r in revs:
3181 if r in revs:
3182 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3182 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3183 % (r, rev))
3183 % (r, rev))
3184 revs.remove(r)
3184 revs.remove(r)
3185 elif ids[n] in revs:
3185 elif ids[n] in revs:
3186 ui.warn(_('skipping already grafted revision %s '
3186 ui.warn(_('skipping already grafted revision %s '
3187 '(%s also has origin %d)\n') % (ids[n], rev, r))
3187 '(%s also has origin %d)\n') % (ids[n], rev, r))
3188 revs.remove(ids[n])
3188 revs.remove(ids[n])
3189 elif ctx.hex() in ids:
3189 elif ctx.hex() in ids:
3190 r = ids[ctx.hex()]
3190 r = ids[ctx.hex()]
3191 ui.warn(_('skipping already grafted revision %s '
3191 ui.warn(_('skipping already grafted revision %s '
3192 '(was grafted from %d)\n') % (r, rev))
3192 '(was grafted from %d)\n') % (r, rev))
3193 revs.remove(r)
3193 revs.remove(r)
3194 if not revs:
3194 if not revs:
3195 return -1
3195 return -1
3196
3196
3197 wlock = repo.wlock()
3197 wlock = repo.wlock()
3198 try:
3198 try:
3199 current = repo['.']
3199 current = repo['.']
3200 for pos, ctx in enumerate(repo.set("%ld", revs)):
3200 for pos, ctx in enumerate(repo.set("%ld", revs)):
3201
3201
3202 ui.status(_('grafting revision %s\n') % ctx.rev())
3202 ui.status(_('grafting revision %s\n') % ctx.rev())
3203 if opts.get('dry_run'):
3203 if opts.get('dry_run'):
3204 continue
3204 continue
3205
3205
3206 source = ctx.extra().get('source')
3206 source = ctx.extra().get('source')
3207 if not source:
3207 if not source:
3208 source = ctx.hex()
3208 source = ctx.hex()
3209 extra = {'source': source}
3209 extra = {'source': source}
3210 user = ctx.user()
3210 user = ctx.user()
3211 if opts.get('user'):
3211 if opts.get('user'):
3212 user = opts['user']
3212 user = opts['user']
3213 date = ctx.date()
3213 date = ctx.date()
3214 if opts.get('date'):
3214 if opts.get('date'):
3215 date = opts['date']
3215 date = opts['date']
3216 message = ctx.description()
3216 message = ctx.description()
3217 if opts.get('log'):
3217 if opts.get('log'):
3218 message += '\n(grafted from %s)' % ctx.hex()
3218 message += '\n(grafted from %s)' % ctx.hex()
3219
3219
3220 # we don't merge the first commit when continuing
3220 # we don't merge the first commit when continuing
3221 if not cont:
3221 if not cont:
3222 # perform the graft merge with p1(rev) as 'ancestor'
3222 # perform the graft merge with p1(rev) as 'ancestor'
3223 try:
3223 try:
3224 # ui.forcemerge is an internal variable, do not document
3224 # ui.forcemerge is an internal variable, do not document
3225 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3225 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3226 'graft')
3226 'graft')
3227 stats = mergemod.update(repo, ctx.node(), True, True, False,
3227 stats = mergemod.update(repo, ctx.node(), True, True, False,
3228 ctx.p1().node(),
3228 ctx.p1().node(),
3229 labels=['local', 'graft'])
3229 labels=['local', 'graft'])
3230 finally:
3230 finally:
3231 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3231 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3232 # report any conflicts
3232 # report any conflicts
3233 if stats and stats[3] > 0:
3233 if stats and stats[3] > 0:
3234 # write out state for --continue
3234 # write out state for --continue
3235 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3235 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3236 repo.opener.write('graftstate', ''.join(nodelines))
3236 repo.opener.write('graftstate', ''.join(nodelines))
3237 raise util.Abort(
3237 raise util.Abort(
3238 _("unresolved conflicts, can't continue"),
3238 _("unresolved conflicts, can't continue"),
3239 hint=_('use hg resolve and hg graft --continue'))
3239 hint=_('use hg resolve and hg graft --continue'))
3240 else:
3240 else:
3241 cont = False
3241 cont = False
3242
3242
3243 # drop the second merge parent
3243 # drop the second merge parent
3244 repo.setparents(current.node(), nullid)
3244 repo.setparents(current.node(), nullid)
3245 repo.dirstate.write()
3245 repo.dirstate.write()
3246 # fix up dirstate for copies and renames
3246 # fix up dirstate for copies and renames
3247 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3247 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3248
3248
3249 # commit
3249 # commit
3250 node = repo.commit(text=message, user=user,
3250 node = repo.commit(text=message, user=user,
3251 date=date, extra=extra, editor=editor)
3251 date=date, extra=extra, editor=editor)
3252 if node is None:
3252 if node is None:
3253 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3253 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3254 else:
3254 else:
3255 current = repo[node]
3255 current = repo[node]
3256 finally:
3256 finally:
3257 wlock.release()
3257 wlock.release()
3258
3258
3259 # remove state when we complete successfully
3259 # remove state when we complete successfully
3260 if not opts.get('dry_run'):
3260 if not opts.get('dry_run'):
3261 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3261 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3262
3262
3263 return 0
3263 return 0
3264
3264
3265 @command('grep',
3265 @command('grep',
3266 [('0', 'print0', None, _('end fields with NUL')),
3266 [('0', 'print0', None, _('end fields with NUL')),
3267 ('', 'all', None, _('print all revisions that match')),
3267 ('', 'all', None, _('print all revisions that match')),
3268 ('a', 'text', None, _('treat all files as text')),
3268 ('a', 'text', None, _('treat all files as text')),
3269 ('f', 'follow', None,
3269 ('f', 'follow', None,
3270 _('follow changeset history,'
3270 _('follow changeset history,'
3271 ' or file history across copies and renames')),
3271 ' or file history across copies and renames')),
3272 ('i', 'ignore-case', None, _('ignore case when matching')),
3272 ('i', 'ignore-case', None, _('ignore case when matching')),
3273 ('l', 'files-with-matches', None,
3273 ('l', 'files-with-matches', None,
3274 _('print only filenames and revisions that match')),
3274 _('print only filenames and revisions that match')),
3275 ('n', 'line-number', None, _('print matching line numbers')),
3275 ('n', 'line-number', None, _('print matching line numbers')),
3276 ('r', 'rev', [],
3276 ('r', 'rev', [],
3277 _('only search files changed within revision range'), _('REV')),
3277 _('only search files changed within revision range'), _('REV')),
3278 ('u', 'user', None, _('list the author (long with -v)')),
3278 ('u', 'user', None, _('list the author (long with -v)')),
3279 ('d', 'date', None, _('list the date (short with -q)')),
3279 ('d', 'date', None, _('list the date (short with -q)')),
3280 ] + walkopts,
3280 ] + walkopts,
3281 _('[OPTION]... PATTERN [FILE]...'),
3281 _('[OPTION]... PATTERN [FILE]...'),
3282 inferrepo=True)
3282 inferrepo=True)
3283 def grep(ui, repo, pattern, *pats, **opts):
3283 def grep(ui, repo, pattern, *pats, **opts):
3284 """search for a pattern in specified files and revisions
3284 """search for a pattern in specified files and revisions
3285
3285
3286 Search revisions of files for a regular expression.
3286 Search revisions of files for a regular expression.
3287
3287
3288 This command behaves differently than Unix grep. It only accepts
3288 This command behaves differently than Unix grep. It only accepts
3289 Python/Perl regexps. It searches repository history, not the
3289 Python/Perl regexps. It searches repository history, not the
3290 working directory. It always prints the revision number in which a
3290 working directory. It always prints the revision number in which a
3291 match appears.
3291 match appears.
3292
3292
3293 By default, grep only prints output for the first revision of a
3293 By default, grep only prints output for the first revision of a
3294 file in which it finds a match. To get it to print every revision
3294 file in which it finds a match. To get it to print every revision
3295 that contains a change in match status ("-" for a match that
3295 that contains a change in match status ("-" for a match that
3296 becomes a non-match, or "+" for a non-match that becomes a match),
3296 becomes a non-match, or "+" for a non-match that becomes a match),
3297 use the --all flag.
3297 use the --all flag.
3298
3298
3299 Returns 0 if a match is found, 1 otherwise.
3299 Returns 0 if a match is found, 1 otherwise.
3300 """
3300 """
3301 reflags = re.M
3301 reflags = re.M
3302 if opts.get('ignore_case'):
3302 if opts.get('ignore_case'):
3303 reflags |= re.I
3303 reflags |= re.I
3304 try:
3304 try:
3305 regexp = util.compilere(pattern, reflags)
3305 regexp = util.compilere(pattern, reflags)
3306 except re.error, inst:
3306 except re.error, inst:
3307 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3307 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3308 return 1
3308 return 1
3309 sep, eol = ':', '\n'
3309 sep, eol = ':', '\n'
3310 if opts.get('print0'):
3310 if opts.get('print0'):
3311 sep = eol = '\0'
3311 sep = eol = '\0'
3312
3312
3313 getfile = util.lrucachefunc(repo.file)
3313 getfile = util.lrucachefunc(repo.file)
3314
3314
3315 def matchlines(body):
3315 def matchlines(body):
3316 begin = 0
3316 begin = 0
3317 linenum = 0
3317 linenum = 0
3318 while begin < len(body):
3318 while begin < len(body):
3319 match = regexp.search(body, begin)
3319 match = regexp.search(body, begin)
3320 if not match:
3320 if not match:
3321 break
3321 break
3322 mstart, mend = match.span()
3322 mstart, mend = match.span()
3323 linenum += body.count('\n', begin, mstart) + 1
3323 linenum += body.count('\n', begin, mstart) + 1
3324 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3324 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3325 begin = body.find('\n', mend) + 1 or len(body) + 1
3325 begin = body.find('\n', mend) + 1 or len(body) + 1
3326 lend = begin - 1
3326 lend = begin - 1
3327 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3327 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3328
3328
3329 class linestate(object):
3329 class linestate(object):
3330 def __init__(self, line, linenum, colstart, colend):
3330 def __init__(self, line, linenum, colstart, colend):
3331 self.line = line
3331 self.line = line
3332 self.linenum = linenum
3332 self.linenum = linenum
3333 self.colstart = colstart
3333 self.colstart = colstart
3334 self.colend = colend
3334 self.colend = colend
3335
3335
3336 def __hash__(self):
3336 def __hash__(self):
3337 return hash((self.linenum, self.line))
3337 return hash((self.linenum, self.line))
3338
3338
3339 def __eq__(self, other):
3339 def __eq__(self, other):
3340 return self.line == other.line
3340 return self.line == other.line
3341
3341
3342 def __iter__(self):
3342 def __iter__(self):
3343 yield (self.line[:self.colstart], '')
3343 yield (self.line[:self.colstart], '')
3344 yield (self.line[self.colstart:self.colend], 'grep.match')
3344 yield (self.line[self.colstart:self.colend], 'grep.match')
3345 rest = self.line[self.colend:]
3345 rest = self.line[self.colend:]
3346 while rest != '':
3346 while rest != '':
3347 match = regexp.search(rest)
3347 match = regexp.search(rest)
3348 if not match:
3348 if not match:
3349 yield (rest, '')
3349 yield (rest, '')
3350 break
3350 break
3351 mstart, mend = match.span()
3351 mstart, mend = match.span()
3352 yield (rest[:mstart], '')
3352 yield (rest[:mstart], '')
3353 yield (rest[mstart:mend], 'grep.match')
3353 yield (rest[mstart:mend], 'grep.match')
3354 rest = rest[mend:]
3354 rest = rest[mend:]
3355
3355
3356 matches = {}
3356 matches = {}
3357 copies = {}
3357 copies = {}
3358 def grepbody(fn, rev, body):
3358 def grepbody(fn, rev, body):
3359 matches[rev].setdefault(fn, [])
3359 matches[rev].setdefault(fn, [])
3360 m = matches[rev][fn]
3360 m = matches[rev][fn]
3361 for lnum, cstart, cend, line in matchlines(body):
3361 for lnum, cstart, cend, line in matchlines(body):
3362 s = linestate(line, lnum, cstart, cend)
3362 s = linestate(line, lnum, cstart, cend)
3363 m.append(s)
3363 m.append(s)
3364
3364
3365 def difflinestates(a, b):
3365 def difflinestates(a, b):
3366 sm = difflib.SequenceMatcher(None, a, b)
3366 sm = difflib.SequenceMatcher(None, a, b)
3367 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3367 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3368 if tag == 'insert':
3368 if tag == 'insert':
3369 for i in xrange(blo, bhi):
3369 for i in xrange(blo, bhi):
3370 yield ('+', b[i])
3370 yield ('+', b[i])
3371 elif tag == 'delete':
3371 elif tag == 'delete':
3372 for i in xrange(alo, ahi):
3372 for i in xrange(alo, ahi):
3373 yield ('-', a[i])
3373 yield ('-', a[i])
3374 elif tag == 'replace':
3374 elif tag == 'replace':
3375 for i in xrange(alo, ahi):
3375 for i in xrange(alo, ahi):
3376 yield ('-', a[i])
3376 yield ('-', a[i])
3377 for i in xrange(blo, bhi):
3377 for i in xrange(blo, bhi):
3378 yield ('+', b[i])
3378 yield ('+', b[i])
3379
3379
3380 def display(fn, ctx, pstates, states):
3380 def display(fn, ctx, pstates, states):
3381 rev = ctx.rev()
3381 rev = ctx.rev()
3382 datefunc = ui.quiet and util.shortdate or util.datestr
3382 datefunc = ui.quiet and util.shortdate or util.datestr
3383 found = False
3383 found = False
3384 @util.cachefunc
3384 @util.cachefunc
3385 def binary():
3385 def binary():
3386 flog = getfile(fn)
3386 flog = getfile(fn)
3387 return util.binary(flog.read(ctx.filenode(fn)))
3387 return util.binary(flog.read(ctx.filenode(fn)))
3388
3388
3389 if opts.get('all'):
3389 if opts.get('all'):
3390 iter = difflinestates(pstates, states)
3390 iter = difflinestates(pstates, states)
3391 else:
3391 else:
3392 iter = [('', l) for l in states]
3392 iter = [('', l) for l in states]
3393 for change, l in iter:
3393 for change, l in iter:
3394 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3394 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3395
3395
3396 if opts.get('line_number'):
3396 if opts.get('line_number'):
3397 cols.append((str(l.linenum), 'grep.linenumber'))
3397 cols.append((str(l.linenum), 'grep.linenumber'))
3398 if opts.get('all'):
3398 if opts.get('all'):
3399 cols.append((change, 'grep.change'))
3399 cols.append((change, 'grep.change'))
3400 if opts.get('user'):
3400 if opts.get('user'):
3401 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3401 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3402 if opts.get('date'):
3402 if opts.get('date'):
3403 cols.append((datefunc(ctx.date()), 'grep.date'))
3403 cols.append((datefunc(ctx.date()), 'grep.date'))
3404 for col, label in cols[:-1]:
3404 for col, label in cols[:-1]:
3405 ui.write(col, label=label)
3405 ui.write(col, label=label)
3406 ui.write(sep, label='grep.sep')
3406 ui.write(sep, label='grep.sep')
3407 ui.write(cols[-1][0], label=cols[-1][1])
3407 ui.write(cols[-1][0], label=cols[-1][1])
3408 if not opts.get('files_with_matches'):
3408 if not opts.get('files_with_matches'):
3409 ui.write(sep, label='grep.sep')
3409 ui.write(sep, label='grep.sep')
3410 if not opts.get('text') and binary():
3410 if not opts.get('text') and binary():
3411 ui.write(" Binary file matches")
3411 ui.write(" Binary file matches")
3412 else:
3412 else:
3413 for s, label in l:
3413 for s, label in l:
3414 ui.write(s, label=label)
3414 ui.write(s, label=label)
3415 ui.write(eol)
3415 ui.write(eol)
3416 found = True
3416 found = True
3417 if opts.get('files_with_matches'):
3417 if opts.get('files_with_matches'):
3418 break
3418 break
3419 return found
3419 return found
3420
3420
3421 skip = {}
3421 skip = {}
3422 revfiles = {}
3422 revfiles = {}
3423 matchfn = scmutil.match(repo[None], pats, opts)
3423 matchfn = scmutil.match(repo[None], pats, opts)
3424 found = False
3424 found = False
3425 follow = opts.get('follow')
3425 follow = opts.get('follow')
3426
3426
3427 def prep(ctx, fns):
3427 def prep(ctx, fns):
3428 rev = ctx.rev()
3428 rev = ctx.rev()
3429 pctx = ctx.p1()
3429 pctx = ctx.p1()
3430 parent = pctx.rev()
3430 parent = pctx.rev()
3431 matches.setdefault(rev, {})
3431 matches.setdefault(rev, {})
3432 matches.setdefault(parent, {})
3432 matches.setdefault(parent, {})
3433 files = revfiles.setdefault(rev, [])
3433 files = revfiles.setdefault(rev, [])
3434 for fn in fns:
3434 for fn in fns:
3435 flog = getfile(fn)
3435 flog = getfile(fn)
3436 try:
3436 try:
3437 fnode = ctx.filenode(fn)
3437 fnode = ctx.filenode(fn)
3438 except error.LookupError:
3438 except error.LookupError:
3439 continue
3439 continue
3440
3440
3441 copied = flog.renamed(fnode)
3441 copied = flog.renamed(fnode)
3442 copy = follow and copied and copied[0]
3442 copy = follow and copied and copied[0]
3443 if copy:
3443 if copy:
3444 copies.setdefault(rev, {})[fn] = copy
3444 copies.setdefault(rev, {})[fn] = copy
3445 if fn in skip:
3445 if fn in skip:
3446 if copy:
3446 if copy:
3447 skip[copy] = True
3447 skip[copy] = True
3448 continue
3448 continue
3449 files.append(fn)
3449 files.append(fn)
3450
3450
3451 if fn not in matches[rev]:
3451 if fn not in matches[rev]:
3452 grepbody(fn, rev, flog.read(fnode))
3452 grepbody(fn, rev, flog.read(fnode))
3453
3453
3454 pfn = copy or fn
3454 pfn = copy or fn
3455 if pfn not in matches[parent]:
3455 if pfn not in matches[parent]:
3456 try:
3456 try:
3457 fnode = pctx.filenode(pfn)
3457 fnode = pctx.filenode(pfn)
3458 grepbody(pfn, parent, flog.read(fnode))
3458 grepbody(pfn, parent, flog.read(fnode))
3459 except error.LookupError:
3459 except error.LookupError:
3460 pass
3460 pass
3461
3461
3462 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3462 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3463 rev = ctx.rev()
3463 rev = ctx.rev()
3464 parent = ctx.p1().rev()
3464 parent = ctx.p1().rev()
3465 for fn in sorted(revfiles.get(rev, [])):
3465 for fn in sorted(revfiles.get(rev, [])):
3466 states = matches[rev][fn]
3466 states = matches[rev][fn]
3467 copy = copies.get(rev, {}).get(fn)
3467 copy = copies.get(rev, {}).get(fn)
3468 if fn in skip:
3468 if fn in skip:
3469 if copy:
3469 if copy:
3470 skip[copy] = True
3470 skip[copy] = True
3471 continue
3471 continue
3472 pstates = matches.get(parent, {}).get(copy or fn, [])
3472 pstates = matches.get(parent, {}).get(copy or fn, [])
3473 if pstates or states:
3473 if pstates or states:
3474 r = display(fn, ctx, pstates, states)
3474 r = display(fn, ctx, pstates, states)
3475 found = found or r
3475 found = found or r
3476 if r and not opts.get('all'):
3476 if r and not opts.get('all'):
3477 skip[fn] = True
3477 skip[fn] = True
3478 if copy:
3478 if copy:
3479 skip[copy] = True
3479 skip[copy] = True
3480 del matches[rev]
3480 del matches[rev]
3481 del revfiles[rev]
3481 del revfiles[rev]
3482
3482
3483 return not found
3483 return not found
3484
3484
3485 @command('heads',
3485 @command('heads',
3486 [('r', 'rev', '',
3486 [('r', 'rev', '',
3487 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3487 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3488 ('t', 'topo', False, _('show topological heads only')),
3488 ('t', 'topo', False, _('show topological heads only')),
3489 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3489 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3490 ('c', 'closed', False, _('show normal and closed branch heads')),
3490 ('c', 'closed', False, _('show normal and closed branch heads')),
3491 ] + templateopts,
3491 ] + templateopts,
3492 _('[-ct] [-r STARTREV] [REV]...'))
3492 _('[-ct] [-r STARTREV] [REV]...'))
3493 def heads(ui, repo, *branchrevs, **opts):
3493 def heads(ui, repo, *branchrevs, **opts):
3494 """show branch heads
3494 """show branch heads
3495
3495
3496 With no arguments, show all open branch heads in the repository.
3496 With no arguments, show all open branch heads in the repository.
3497 Branch heads are changesets that have no descendants on the
3497 Branch heads are changesets that have no descendants on the
3498 same branch. They are where development generally takes place and
3498 same branch. They are where development generally takes place and
3499 are the usual targets for update and merge operations.
3499 are the usual targets for update and merge operations.
3500
3500
3501 If one or more REVs are given, only open branch heads on the
3501 If one or more REVs are given, only open branch heads on the
3502 branches associated with the specified changesets are shown. This
3502 branches associated with the specified changesets are shown. This
3503 means that you can use :hg:`heads .` to see the heads on the
3503 means that you can use :hg:`heads .` to see the heads on the
3504 currently checked-out branch.
3504 currently checked-out branch.
3505
3505
3506 If -c/--closed is specified, also show branch heads marked closed
3506 If -c/--closed is specified, also show branch heads marked closed
3507 (see :hg:`commit --close-branch`).
3507 (see :hg:`commit --close-branch`).
3508
3508
3509 If STARTREV is specified, only those heads that are descendants of
3509 If STARTREV is specified, only those heads that are descendants of
3510 STARTREV will be displayed.
3510 STARTREV will be displayed.
3511
3511
3512 If -t/--topo is specified, named branch mechanics will be ignored and only
3512 If -t/--topo is specified, named branch mechanics will be ignored and only
3513 topological heads (changesets with no children) will be shown.
3513 topological heads (changesets with no children) will be shown.
3514
3514
3515 Returns 0 if matching heads are found, 1 if not.
3515 Returns 0 if matching heads are found, 1 if not.
3516 """
3516 """
3517
3517
3518 start = None
3518 start = None
3519 if 'rev' in opts:
3519 if 'rev' in opts:
3520 start = scmutil.revsingle(repo, opts['rev'], None).node()
3520 start = scmutil.revsingle(repo, opts['rev'], None).node()
3521
3521
3522 if opts.get('topo'):
3522 if opts.get('topo'):
3523 heads = [repo[h] for h in repo.heads(start)]
3523 heads = [repo[h] for h in repo.heads(start)]
3524 else:
3524 else:
3525 heads = []
3525 heads = []
3526 for branch in repo.branchmap():
3526 for branch in repo.branchmap():
3527 heads += repo.branchheads(branch, start, opts.get('closed'))
3527 heads += repo.branchheads(branch, start, opts.get('closed'))
3528 heads = [repo[h] for h in heads]
3528 heads = [repo[h] for h in heads]
3529
3529
3530 if branchrevs:
3530 if branchrevs:
3531 branches = set(repo[br].branch() for br in branchrevs)
3531 branches = set(repo[br].branch() for br in branchrevs)
3532 heads = [h for h in heads if h.branch() in branches]
3532 heads = [h for h in heads if h.branch() in branches]
3533
3533
3534 if opts.get('active') and branchrevs:
3534 if opts.get('active') and branchrevs:
3535 dagheads = repo.heads(start)
3535 dagheads = repo.heads(start)
3536 heads = [h for h in heads if h.node() in dagheads]
3536 heads = [h for h in heads if h.node() in dagheads]
3537
3537
3538 if branchrevs:
3538 if branchrevs:
3539 haveheads = set(h.branch() for h in heads)
3539 haveheads = set(h.branch() for h in heads)
3540 if branches - haveheads:
3540 if branches - haveheads:
3541 headless = ', '.join(b for b in branches - haveheads)
3541 headless = ', '.join(b for b in branches - haveheads)
3542 msg = _('no open branch heads found on branches %s')
3542 msg = _('no open branch heads found on branches %s')
3543 if opts.get('rev'):
3543 if opts.get('rev'):
3544 msg += _(' (started at %s)') % opts['rev']
3544 msg += _(' (started at %s)') % opts['rev']
3545 ui.warn((msg + '\n') % headless)
3545 ui.warn((msg + '\n') % headless)
3546
3546
3547 if not heads:
3547 if not heads:
3548 return 1
3548 return 1
3549
3549
3550 heads = sorted(heads, key=lambda x: -x.rev())
3550 heads = sorted(heads, key=lambda x: -x.rev())
3551 displayer = cmdutil.show_changeset(ui, repo, opts)
3551 displayer = cmdutil.show_changeset(ui, repo, opts)
3552 for ctx in heads:
3552 for ctx in heads:
3553 displayer.show(ctx)
3553 displayer.show(ctx)
3554 displayer.close()
3554 displayer.close()
3555
3555
3556 @command('help',
3556 @command('help',
3557 [('e', 'extension', None, _('show only help for extensions')),
3557 [('e', 'extension', None, _('show only help for extensions')),
3558 ('c', 'command', None, _('show only help for commands')),
3558 ('c', 'command', None, _('show only help for commands')),
3559 ('k', 'keyword', '', _('show topics matching keyword')),
3559 ('k', 'keyword', '', _('show topics matching keyword')),
3560 ],
3560 ],
3561 _('[-ec] [TOPIC]'),
3561 _('[-ec] [TOPIC]'),
3562 norepo=True)
3562 norepo=True)
3563 def help_(ui, name=None, **opts):
3563 def help_(ui, name=None, **opts):
3564 """show help for a given topic or a help overview
3564 """show help for a given topic or a help overview
3565
3565
3566 With no arguments, print a list of commands with short help messages.
3566 With no arguments, print a list of commands with short help messages.
3567
3567
3568 Given a topic, extension, or command name, print help for that
3568 Given a topic, extension, or command name, print help for that
3569 topic.
3569 topic.
3570
3570
3571 Returns 0 if successful.
3571 Returns 0 if successful.
3572 """
3572 """
3573
3573
3574 textwidth = min(ui.termwidth(), 80) - 2
3574 textwidth = min(ui.termwidth(), 80) - 2
3575
3575
3576 keep = ui.verbose and ['verbose'] or []
3576 keep = ui.verbose and ['verbose'] or []
3577 text = help.help_(ui, name, **opts)
3577 text = help.help_(ui, name, **opts)
3578
3578
3579 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3579 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3580 if 'verbose' in pruned:
3580 if 'verbose' in pruned:
3581 keep.append('omitted')
3581 keep.append('omitted')
3582 else:
3582 else:
3583 keep.append('notomitted')
3583 keep.append('notomitted')
3584 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3584 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3585 ui.write(formatted)
3585 ui.write(formatted)
3586
3586
3587
3587
3588 @command('identify|id',
3588 @command('identify|id',
3589 [('r', 'rev', '',
3589 [('r', 'rev', '',
3590 _('identify the specified revision'), _('REV')),
3590 _('identify the specified revision'), _('REV')),
3591 ('n', 'num', None, _('show local revision number')),
3591 ('n', 'num', None, _('show local revision number')),
3592 ('i', 'id', None, _('show global revision id')),
3592 ('i', 'id', None, _('show global revision id')),
3593 ('b', 'branch', None, _('show branch')),
3593 ('b', 'branch', None, _('show branch')),
3594 ('t', 'tags', None, _('show tags')),
3594 ('t', 'tags', None, _('show tags')),
3595 ('B', 'bookmarks', None, _('show bookmarks')),
3595 ('B', 'bookmarks', None, _('show bookmarks')),
3596 ] + remoteopts,
3596 ] + remoteopts,
3597 _('[-nibtB] [-r REV] [SOURCE]'),
3597 _('[-nibtB] [-r REV] [SOURCE]'),
3598 optionalrepo=True)
3598 optionalrepo=True)
3599 def identify(ui, repo, source=None, rev=None,
3599 def identify(ui, repo, source=None, rev=None,
3600 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3600 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3601 """identify the working copy or specified revision
3601 """identify the working copy or specified revision
3602
3602
3603 Print a summary identifying the repository state at REV using one or
3603 Print a summary identifying the repository state at REV using one or
3604 two parent hash identifiers, followed by a "+" if the working
3604 two parent hash identifiers, followed by a "+" if the working
3605 directory has uncommitted changes, the branch name (if not default),
3605 directory has uncommitted changes, the branch name (if not default),
3606 a list of tags, and a list of bookmarks.
3606 a list of tags, and a list of bookmarks.
3607
3607
3608 When REV is not given, print a summary of the current state of the
3608 When REV is not given, print a summary of the current state of the
3609 repository.
3609 repository.
3610
3610
3611 Specifying a path to a repository root or Mercurial bundle will
3611 Specifying a path to a repository root or Mercurial bundle will
3612 cause lookup to operate on that repository/bundle.
3612 cause lookup to operate on that repository/bundle.
3613
3613
3614 .. container:: verbose
3614 .. container:: verbose
3615
3615
3616 Examples:
3616 Examples:
3617
3617
3618 - generate a build identifier for the working directory::
3618 - generate a build identifier for the working directory::
3619
3619
3620 hg id --id > build-id.dat
3620 hg id --id > build-id.dat
3621
3621
3622 - find the revision corresponding to a tag::
3622 - find the revision corresponding to a tag::
3623
3623
3624 hg id -n -r 1.3
3624 hg id -n -r 1.3
3625
3625
3626 - check the most recent revision of a remote repository::
3626 - check the most recent revision of a remote repository::
3627
3627
3628 hg id -r tip http://selenic.com/hg/
3628 hg id -r tip http://selenic.com/hg/
3629
3629
3630 Returns 0 if successful.
3630 Returns 0 if successful.
3631 """
3631 """
3632
3632
3633 if not repo and not source:
3633 if not repo and not source:
3634 raise util.Abort(_("there is no Mercurial repository here "
3634 raise util.Abort(_("there is no Mercurial repository here "
3635 "(.hg not found)"))
3635 "(.hg not found)"))
3636
3636
3637 hexfunc = ui.debugflag and hex or short
3637 hexfunc = ui.debugflag and hex or short
3638 default = not (num or id or branch or tags or bookmarks)
3638 default = not (num or id or branch or tags or bookmarks)
3639 output = []
3639 output = []
3640 revs = []
3640 revs = []
3641
3641
3642 if source:
3642 if source:
3643 source, branches = hg.parseurl(ui.expandpath(source))
3643 source, branches = hg.parseurl(ui.expandpath(source))
3644 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3644 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3645 repo = peer.local()
3645 repo = peer.local()
3646 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3646 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3647
3647
3648 if not repo:
3648 if not repo:
3649 if num or branch or tags:
3649 if num or branch or tags:
3650 raise util.Abort(
3650 raise util.Abort(
3651 _("can't query remote revision number, branch, or tags"))
3651 _("can't query remote revision number, branch, or tags"))
3652 if not rev and revs:
3652 if not rev and revs:
3653 rev = revs[0]
3653 rev = revs[0]
3654 if not rev:
3654 if not rev:
3655 rev = "tip"
3655 rev = "tip"
3656
3656
3657 remoterev = peer.lookup(rev)
3657 remoterev = peer.lookup(rev)
3658 if default or id:
3658 if default or id:
3659 output = [hexfunc(remoterev)]
3659 output = [hexfunc(remoterev)]
3660
3660
3661 def getbms():
3661 def getbms():
3662 bms = []
3662 bms = []
3663
3663
3664 if 'bookmarks' in peer.listkeys('namespaces'):
3664 if 'bookmarks' in peer.listkeys('namespaces'):
3665 hexremoterev = hex(remoterev)
3665 hexremoterev = hex(remoterev)
3666 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3666 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3667 if bmr == hexremoterev]
3667 if bmr == hexremoterev]
3668
3668
3669 return sorted(bms)
3669 return sorted(bms)
3670
3670
3671 if bookmarks:
3671 if bookmarks:
3672 output.extend(getbms())
3672 output.extend(getbms())
3673 elif default and not ui.quiet:
3673 elif default and not ui.quiet:
3674 # multiple bookmarks for a single parent separated by '/'
3674 # multiple bookmarks for a single parent separated by '/'
3675 bm = '/'.join(getbms())
3675 bm = '/'.join(getbms())
3676 if bm:
3676 if bm:
3677 output.append(bm)
3677 output.append(bm)
3678 else:
3678 else:
3679 if not rev:
3679 if not rev:
3680 ctx = repo[None]
3680 ctx = repo[None]
3681 parents = ctx.parents()
3681 parents = ctx.parents()
3682 changed = ""
3682 changed = ""
3683 if default or id or num:
3683 if default or id or num:
3684 if (util.any(repo.status())
3684 if (util.any(repo.status())
3685 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3685 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3686 changed = '+'
3686 changed = '+'
3687 if default or id:
3687 if default or id:
3688 output = ["%s%s" %
3688 output = ["%s%s" %
3689 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3689 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3690 if num:
3690 if num:
3691 output.append("%s%s" %
3691 output.append("%s%s" %
3692 ('+'.join([str(p.rev()) for p in parents]), changed))
3692 ('+'.join([str(p.rev()) for p in parents]), changed))
3693 else:
3693 else:
3694 ctx = scmutil.revsingle(repo, rev)
3694 ctx = scmutil.revsingle(repo, rev)
3695 if default or id:
3695 if default or id:
3696 output = [hexfunc(ctx.node())]
3696 output = [hexfunc(ctx.node())]
3697 if num:
3697 if num:
3698 output.append(str(ctx.rev()))
3698 output.append(str(ctx.rev()))
3699
3699
3700 if default and not ui.quiet:
3700 if default and not ui.quiet:
3701 b = ctx.branch()
3701 b = ctx.branch()
3702 if b != 'default':
3702 if b != 'default':
3703 output.append("(%s)" % b)
3703 output.append("(%s)" % b)
3704
3704
3705 # multiple tags for a single parent separated by '/'
3705 # multiple tags for a single parent separated by '/'
3706 t = '/'.join(ctx.tags())
3706 t = '/'.join(ctx.tags())
3707 if t:
3707 if t:
3708 output.append(t)
3708 output.append(t)
3709
3709
3710 # multiple bookmarks for a single parent separated by '/'
3710 # multiple bookmarks for a single parent separated by '/'
3711 bm = '/'.join(ctx.bookmarks())
3711 bm = '/'.join(ctx.bookmarks())
3712 if bm:
3712 if bm:
3713 output.append(bm)
3713 output.append(bm)
3714 else:
3714 else:
3715 if branch:
3715 if branch:
3716 output.append(ctx.branch())
3716 output.append(ctx.branch())
3717
3717
3718 if tags:
3718 if tags:
3719 output.extend(ctx.tags())
3719 output.extend(ctx.tags())
3720
3720
3721 if bookmarks:
3721 if bookmarks:
3722 output.extend(ctx.bookmarks())
3722 output.extend(ctx.bookmarks())
3723
3723
3724 ui.write("%s\n" % ' '.join(output))
3724 ui.write("%s\n" % ' '.join(output))
3725
3725
3726 @command('import|patch',
3726 @command('import|patch',
3727 [('p', 'strip', 1,
3727 [('p', 'strip', 1,
3728 _('directory strip option for patch. This has the same '
3728 _('directory strip option for patch. This has the same '
3729 'meaning as the corresponding patch option'), _('NUM')),
3729 'meaning as the corresponding patch option'), _('NUM')),
3730 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3730 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3731 ('e', 'edit', False, _('invoke editor on commit messages')),
3731 ('e', 'edit', False, _('invoke editor on commit messages')),
3732 ('f', 'force', None,
3732 ('f', 'force', None,
3733 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3733 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3734 ('', 'no-commit', None,
3734 ('', 'no-commit', None,
3735 _("don't commit, just update the working directory")),
3735 _("don't commit, just update the working directory")),
3736 ('', 'bypass', None,
3736 ('', 'bypass', None,
3737 _("apply patch without touching the working directory")),
3737 _("apply patch without touching the working directory")),
3738 ('', 'partial', None,
3738 ('', 'partial', None,
3739 _('commit even if some hunks fail')),
3739 _('commit even if some hunks fail')),
3740 ('', 'exact', None,
3740 ('', 'exact', None,
3741 _('apply patch to the nodes from which it was generated')),
3741 _('apply patch to the nodes from which it was generated')),
3742 ('', 'import-branch', None,
3742 ('', 'import-branch', None,
3743 _('use any branch information in patch (implied by --exact)'))] +
3743 _('use any branch information in patch (implied by --exact)'))] +
3744 commitopts + commitopts2 + similarityopts,
3744 commitopts + commitopts2 + similarityopts,
3745 _('[OPTION]... PATCH...'))
3745 _('[OPTION]... PATCH...'))
3746 def import_(ui, repo, patch1=None, *patches, **opts):
3746 def import_(ui, repo, patch1=None, *patches, **opts):
3747 """import an ordered set of patches
3747 """import an ordered set of patches
3748
3748
3749 Import a list of patches and commit them individually (unless
3749 Import a list of patches and commit them individually (unless
3750 --no-commit is specified).
3750 --no-commit is specified).
3751
3751
3752 Because import first applies changes to the working directory,
3752 Because import first applies changes to the working directory,
3753 import will abort if there are outstanding changes.
3753 import will abort if there are outstanding changes.
3754
3754
3755 You can import a patch straight from a mail message. Even patches
3755 You can import a patch straight from a mail message. Even patches
3756 as attachments work (to use the body part, it must have type
3756 as attachments work (to use the body part, it must have type
3757 text/plain or text/x-patch). From and Subject headers of email
3757 text/plain or text/x-patch). From and Subject headers of email
3758 message are used as default committer and commit message. All
3758 message are used as default committer and commit message. All
3759 text/plain body parts before first diff are added to commit
3759 text/plain body parts before first diff are added to commit
3760 message.
3760 message.
3761
3761
3762 If the imported patch was generated by :hg:`export`, user and
3762 If the imported patch was generated by :hg:`export`, user and
3763 description from patch override values from message headers and
3763 description from patch override values from message headers and
3764 body. Values given on command line with -m/--message and -u/--user
3764 body. Values given on command line with -m/--message and -u/--user
3765 override these.
3765 override these.
3766
3766
3767 If --exact is specified, import will set the working directory to
3767 If --exact is specified, import will set the working directory to
3768 the parent of each patch before applying it, and will abort if the
3768 the parent of each patch before applying it, and will abort if the
3769 resulting changeset has a different ID than the one recorded in
3769 resulting changeset has a different ID than the one recorded in
3770 the patch. This may happen due to character set problems or other
3770 the patch. This may happen due to character set problems or other
3771 deficiencies in the text patch format.
3771 deficiencies in the text patch format.
3772
3772
3773 Use --bypass to apply and commit patches directly to the
3773 Use --bypass to apply and commit patches directly to the
3774 repository, not touching the working directory. Without --exact,
3774 repository, not touching the working directory. Without --exact,
3775 patches will be applied on top of the working directory parent
3775 patches will be applied on top of the working directory parent
3776 revision.
3776 revision.
3777
3777
3778 With -s/--similarity, hg will attempt to discover renames and
3778 With -s/--similarity, hg will attempt to discover renames and
3779 copies in the patch in the same way as :hg:`addremove`.
3779 copies in the patch in the same way as :hg:`addremove`.
3780
3780
3781 Use --partial to ensure a changeset will be created from the patch
3781 Use --partial to ensure a changeset will be created from the patch
3782 even if some hunks fail to apply. Hunks that fail to apply will be
3782 even if some hunks fail to apply. Hunks that fail to apply will be
3783 written to a <target-file>.rej file. Conflicts can then be resolved
3783 written to a <target-file>.rej file. Conflicts can then be resolved
3784 by hand before :hg:`commit --amend` is run to update the created
3784 by hand before :hg:`commit --amend` is run to update the created
3785 changeset. This flag exists to let people import patches that
3785 changeset. This flag exists to let people import patches that
3786 partially apply without losing the associated metadata (author,
3786 partially apply without losing the associated metadata (author,
3787 date, description, ...), Note that when none of the hunk applies
3787 date, description, ...), Note that when none of the hunk applies
3788 cleanly, :hg:`import --partial` will create an empty changeset,
3788 cleanly, :hg:`import --partial` will create an empty changeset,
3789 importing only the patch metadata.
3789 importing only the patch metadata.
3790
3790
3791 To read a patch from standard input, use "-" as the patch name. If
3791 To read a patch from standard input, use "-" as the patch name. If
3792 a URL is specified, the patch will be downloaded from it.
3792 a URL is specified, the patch will be downloaded from it.
3793 See :hg:`help dates` for a list of formats valid for -d/--date.
3793 See :hg:`help dates` for a list of formats valid for -d/--date.
3794
3794
3795 .. container:: verbose
3795 .. container:: verbose
3796
3796
3797 Examples:
3797 Examples:
3798
3798
3799 - import a traditional patch from a website and detect renames::
3799 - import a traditional patch from a website and detect renames::
3800
3800
3801 hg import -s 80 http://example.com/bugfix.patch
3801 hg import -s 80 http://example.com/bugfix.patch
3802
3802
3803 - import a changeset from an hgweb server::
3803 - import a changeset from an hgweb server::
3804
3804
3805 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3805 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3806
3806
3807 - import all the patches in an Unix-style mbox::
3807 - import all the patches in an Unix-style mbox::
3808
3808
3809 hg import incoming-patches.mbox
3809 hg import incoming-patches.mbox
3810
3810
3811 - attempt to exactly restore an exported changeset (not always
3811 - attempt to exactly restore an exported changeset (not always
3812 possible)::
3812 possible)::
3813
3813
3814 hg import --exact proposed-fix.patch
3814 hg import --exact proposed-fix.patch
3815
3815
3816 Returns 0 on success, 1 on partial success (see --partial).
3816 Returns 0 on success, 1 on partial success (see --partial).
3817 """
3817 """
3818
3818
3819 if not patch1:
3819 if not patch1:
3820 raise util.Abort(_('need at least one patch to import'))
3820 raise util.Abort(_('need at least one patch to import'))
3821
3821
3822 patches = (patch1,) + patches
3822 patches = (patch1,) + patches
3823
3823
3824 date = opts.get('date')
3824 date = opts.get('date')
3825 if date:
3825 if date:
3826 opts['date'] = util.parsedate(date)
3826 opts['date'] = util.parsedate(date)
3827
3827
3828 update = not opts.get('bypass')
3828 update = not opts.get('bypass')
3829 if not update and opts.get('no_commit'):
3829 if not update and opts.get('no_commit'):
3830 raise util.Abort(_('cannot use --no-commit with --bypass'))
3830 raise util.Abort(_('cannot use --no-commit with --bypass'))
3831 try:
3831 try:
3832 sim = float(opts.get('similarity') or 0)
3832 sim = float(opts.get('similarity') or 0)
3833 except ValueError:
3833 except ValueError:
3834 raise util.Abort(_('similarity must be a number'))
3834 raise util.Abort(_('similarity must be a number'))
3835 if sim < 0 or sim > 100:
3835 if sim < 0 or sim > 100:
3836 raise util.Abort(_('similarity must be between 0 and 100'))
3836 raise util.Abort(_('similarity must be between 0 and 100'))
3837 if sim and not update:
3837 if sim and not update:
3838 raise util.Abort(_('cannot use --similarity with --bypass'))
3838 raise util.Abort(_('cannot use --similarity with --bypass'))
3839
3839
3840 if update:
3840 if update:
3841 cmdutil.checkunfinished(repo)
3841 cmdutil.checkunfinished(repo)
3842 if (opts.get('exact') or not opts.get('force')) and update:
3842 if (opts.get('exact') or not opts.get('force')) and update:
3843 cmdutil.bailifchanged(repo)
3843 cmdutil.bailifchanged(repo)
3844
3844
3845 base = opts["base"]
3845 base = opts["base"]
3846 wlock = lock = tr = None
3846 wlock = lock = tr = None
3847 msgs = []
3847 msgs = []
3848 ret = 0
3848 ret = 0
3849
3849
3850
3850
3851 try:
3851 try:
3852 try:
3852 try:
3853 wlock = repo.wlock()
3853 wlock = repo.wlock()
3854 if not opts.get('no_commit'):
3854 if not opts.get('no_commit'):
3855 lock = repo.lock()
3855 lock = repo.lock()
3856 tr = repo.transaction('import')
3856 tr = repo.transaction('import')
3857 parents = repo.parents()
3857 parents = repo.parents()
3858 for patchurl in patches:
3858 for patchurl in patches:
3859 if patchurl == '-':
3859 if patchurl == '-':
3860 ui.status(_('applying patch from stdin\n'))
3860 ui.status(_('applying patch from stdin\n'))
3861 patchfile = ui.fin
3861 patchfile = ui.fin
3862 patchurl = 'stdin' # for error message
3862 patchurl = 'stdin' # for error message
3863 else:
3863 else:
3864 patchurl = os.path.join(base, patchurl)
3864 patchurl = os.path.join(base, patchurl)
3865 ui.status(_('applying %s\n') % patchurl)
3865 ui.status(_('applying %s\n') % patchurl)
3866 patchfile = hg.openpath(ui, patchurl)
3866 patchfile = hg.openpath(ui, patchurl)
3867
3867
3868 haspatch = False
3868 haspatch = False
3869 for hunk in patch.split(patchfile):
3869 for hunk in patch.split(patchfile):
3870 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3870 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3871 parents, opts,
3871 parents, opts,
3872 msgs, hg.clean)
3872 msgs, hg.clean)
3873 if msg:
3873 if msg:
3874 haspatch = True
3874 haspatch = True
3875 ui.note(msg + '\n')
3875 ui.note(msg + '\n')
3876 if update or opts.get('exact'):
3876 if update or opts.get('exact'):
3877 parents = repo.parents()
3877 parents = repo.parents()
3878 else:
3878 else:
3879 parents = [repo[node]]
3879 parents = [repo[node]]
3880 if rej:
3880 if rej:
3881 ui.write_err(_("patch applied partially\n"))
3881 ui.write_err(_("patch applied partially\n"))
3882 ui.write_err(("(fix the .rej files and run "
3882 ui.write_err(("(fix the .rej files and run "
3883 "`hg commit --amend`)\n"))
3883 "`hg commit --amend`)\n"))
3884 ret = 1
3884 ret = 1
3885 break
3885 break
3886
3886
3887 if not haspatch:
3887 if not haspatch:
3888 raise util.Abort(_('%s: no diffs found') % patchurl)
3888 raise util.Abort(_('%s: no diffs found') % patchurl)
3889
3889
3890 if tr:
3890 if tr:
3891 tr.close()
3891 tr.close()
3892 if msgs:
3892 if msgs:
3893 repo.savecommitmessage('\n* * *\n'.join(msgs))
3893 repo.savecommitmessage('\n* * *\n'.join(msgs))
3894 return ret
3894 return ret
3895 except: # re-raises
3895 except: # re-raises
3896 # wlock.release() indirectly calls dirstate.write(): since
3896 # wlock.release() indirectly calls dirstate.write(): since
3897 # we're crashing, we do not want to change the working dir
3897 # we're crashing, we do not want to change the working dir
3898 # parent after all, so make sure it writes nothing
3898 # parent after all, so make sure it writes nothing
3899 repo.dirstate.invalidate()
3899 repo.dirstate.invalidate()
3900 raise
3900 raise
3901 finally:
3901 finally:
3902 if tr:
3902 if tr:
3903 tr.release()
3903 tr.release()
3904 release(lock, wlock)
3904 release(lock, wlock)
3905
3905
3906 @command('incoming|in',
3906 @command('incoming|in',
3907 [('f', 'force', None,
3907 [('f', 'force', None,
3908 _('run even if remote repository is unrelated')),
3908 _('run even if remote repository is unrelated')),
3909 ('n', 'newest-first', None, _('show newest record first')),
3909 ('n', 'newest-first', None, _('show newest record first')),
3910 ('', 'bundle', '',
3910 ('', 'bundle', '',
3911 _('file to store the bundles into'), _('FILE')),
3911 _('file to store the bundles into'), _('FILE')),
3912 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3912 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3913 ('B', 'bookmarks', False, _("compare bookmarks")),
3913 ('B', 'bookmarks', False, _("compare bookmarks")),
3914 ('b', 'branch', [],
3914 ('b', 'branch', [],
3915 _('a specific branch you would like to pull'), _('BRANCH')),
3915 _('a specific branch you would like to pull'), _('BRANCH')),
3916 ] + logopts + remoteopts + subrepoopts,
3916 ] + logopts + remoteopts + subrepoopts,
3917 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3917 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3918 def incoming(ui, repo, source="default", **opts):
3918 def incoming(ui, repo, source="default", **opts):
3919 """show new changesets found in source
3919 """show new changesets found in source
3920
3920
3921 Show new changesets found in the specified path/URL or the default
3921 Show new changesets found in the specified path/URL or the default
3922 pull location. These are the changesets that would have been pulled
3922 pull location. These are the changesets that would have been pulled
3923 if a pull at the time you issued this command.
3923 if a pull at the time you issued this command.
3924
3924
3925 For remote repository, using --bundle avoids downloading the
3925 For remote repository, using --bundle avoids downloading the
3926 changesets twice if the incoming is followed by a pull.
3926 changesets twice if the incoming is followed by a pull.
3927
3927
3928 See pull for valid source format details.
3928 See pull for valid source format details.
3929
3929
3930 .. container:: verbose
3930 .. container:: verbose
3931
3931
3932 Examples:
3932 Examples:
3933
3933
3934 - show incoming changes with patches and full description::
3934 - show incoming changes with patches and full description::
3935
3935
3936 hg incoming -vp
3936 hg incoming -vp
3937
3937
3938 - show incoming changes excluding merges, store a bundle::
3938 - show incoming changes excluding merges, store a bundle::
3939
3939
3940 hg in -vpM --bundle incoming.hg
3940 hg in -vpM --bundle incoming.hg
3941 hg pull incoming.hg
3941 hg pull incoming.hg
3942
3942
3943 - briefly list changes inside a bundle::
3943 - briefly list changes inside a bundle::
3944
3944
3945 hg in changes.hg -T "{desc|firstline}\\n"
3945 hg in changes.hg -T "{desc|firstline}\\n"
3946
3946
3947 Returns 0 if there are incoming changes, 1 otherwise.
3947 Returns 0 if there are incoming changes, 1 otherwise.
3948 """
3948 """
3949 if opts.get('graph'):
3949 if opts.get('graph'):
3950 cmdutil.checkunsupportedgraphflags([], opts)
3950 cmdutil.checkunsupportedgraphflags([], opts)
3951 def display(other, chlist, displayer):
3951 def display(other, chlist, displayer):
3952 revdag = cmdutil.graphrevs(other, chlist, opts)
3952 revdag = cmdutil.graphrevs(other, chlist, opts)
3953 showparents = [ctx.node() for ctx in repo[None].parents()]
3953 showparents = [ctx.node() for ctx in repo[None].parents()]
3954 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3954 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3955 graphmod.asciiedges)
3955 graphmod.asciiedges)
3956
3956
3957 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3957 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3958 return 0
3958 return 0
3959
3959
3960 if opts.get('bundle') and opts.get('subrepos'):
3960 if opts.get('bundle') and opts.get('subrepos'):
3961 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3961 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3962
3962
3963 if opts.get('bookmarks'):
3963 if opts.get('bookmarks'):
3964 source, branches = hg.parseurl(ui.expandpath(source),
3964 source, branches = hg.parseurl(ui.expandpath(source),
3965 opts.get('branch'))
3965 opts.get('branch'))
3966 other = hg.peer(repo, opts, source)
3966 other = hg.peer(repo, opts, source)
3967 if 'bookmarks' not in other.listkeys('namespaces'):
3967 if 'bookmarks' not in other.listkeys('namespaces'):
3968 ui.warn(_("remote doesn't support bookmarks\n"))
3968 ui.warn(_("remote doesn't support bookmarks\n"))
3969 return 0
3969 return 0
3970 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3970 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3971 return bookmarks.diff(ui, repo, other)
3971 return bookmarks.diff(ui, repo, other)
3972
3972
3973 repo._subtoppath = ui.expandpath(source)
3973 repo._subtoppath = ui.expandpath(source)
3974 try:
3974 try:
3975 return hg.incoming(ui, repo, source, opts)
3975 return hg.incoming(ui, repo, source, opts)
3976 finally:
3976 finally:
3977 del repo._subtoppath
3977 del repo._subtoppath
3978
3978
3979
3979
3980 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3980 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3981 norepo=True)
3981 norepo=True)
3982 def init(ui, dest=".", **opts):
3982 def init(ui, dest=".", **opts):
3983 """create a new repository in the given directory
3983 """create a new repository in the given directory
3984
3984
3985 Initialize a new repository in the given directory. If the given
3985 Initialize a new repository in the given directory. If the given
3986 directory does not exist, it will be created.
3986 directory does not exist, it will be created.
3987
3987
3988 If no directory is given, the current directory is used.
3988 If no directory is given, the current directory is used.
3989
3989
3990 It is possible to specify an ``ssh://`` URL as the destination.
3990 It is possible to specify an ``ssh://`` URL as the destination.
3991 See :hg:`help urls` for more information.
3991 See :hg:`help urls` for more information.
3992
3992
3993 Returns 0 on success.
3993 Returns 0 on success.
3994 """
3994 """
3995 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3995 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3996
3996
3997 @command('locate',
3997 @command('locate',
3998 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3998 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3999 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3999 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4000 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4000 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4001 ] + walkopts,
4001 ] + walkopts,
4002 _('[OPTION]... [PATTERN]...'))
4002 _('[OPTION]... [PATTERN]...'))
4003 def locate(ui, repo, *pats, **opts):
4003 def locate(ui, repo, *pats, **opts):
4004 """locate files matching specific patterns
4004 """locate files matching specific patterns
4005
4005
4006 Print files under Mercurial control in the working directory whose
4006 Print files under Mercurial control in the working directory whose
4007 names match the given patterns.
4007 names match the given patterns.
4008
4008
4009 By default, this command searches all directories in the working
4009 By default, this command searches all directories in the working
4010 directory. To search just the current directory and its
4010 directory. To search just the current directory and its
4011 subdirectories, use "--include .".
4011 subdirectories, use "--include .".
4012
4012
4013 If no patterns are given to match, this command prints the names
4013 If no patterns are given to match, this command prints the names
4014 of all files under Mercurial control in the working directory.
4014 of all files under Mercurial control in the working directory.
4015
4015
4016 If you want to feed the output of this command into the "xargs"
4016 If you want to feed the output of this command into the "xargs"
4017 command, use the -0 option to both this command and "xargs". This
4017 command, use the -0 option to both this command and "xargs". This
4018 will avoid the problem of "xargs" treating single filenames that
4018 will avoid the problem of "xargs" treating single filenames that
4019 contain whitespace as multiple filenames.
4019 contain whitespace as multiple filenames.
4020
4020
4021 Returns 0 if a match is found, 1 otherwise.
4021 Returns 0 if a match is found, 1 otherwise.
4022 """
4022 """
4023 end = opts.get('print0') and '\0' or '\n'
4023 end = opts.get('print0') and '\0' or '\n'
4024 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4024 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4025
4025
4026 ret = 1
4026 ret = 1
4027 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4027 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4028 m.bad = lambda x, y: False
4028 m.bad = lambda x, y: False
4029 for abs in repo[rev].walk(m):
4029 for abs in repo[rev].walk(m):
4030 if not rev and abs not in repo.dirstate:
4030 if not rev and abs not in repo.dirstate:
4031 continue
4031 continue
4032 if opts.get('fullpath'):
4032 if opts.get('fullpath'):
4033 ui.write(repo.wjoin(abs), end)
4033 ui.write(repo.wjoin(abs), end)
4034 else:
4034 else:
4035 ui.write(((pats and m.rel(abs)) or abs), end)
4035 ui.write(((pats and m.rel(abs)) or abs), end)
4036 ret = 0
4036 ret = 0
4037
4037
4038 return ret
4038 return ret
4039
4039
4040 @command('^log|history',
4040 @command('^log|history',
4041 [('f', 'follow', None,
4041 [('f', 'follow', None,
4042 _('follow changeset history, or file history across copies and renames')),
4042 _('follow changeset history, or file history across copies and renames')),
4043 ('', 'follow-first', None,
4043 ('', 'follow-first', None,
4044 _('only follow the first parent of merge changesets (DEPRECATED)')),
4044 _('only follow the first parent of merge changesets (DEPRECATED)')),
4045 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4045 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4046 ('C', 'copies', None, _('show copied files')),
4046 ('C', 'copies', None, _('show copied files')),
4047 ('k', 'keyword', [],
4047 ('k', 'keyword', [],
4048 _('do case-insensitive search for a given text'), _('TEXT')),
4048 _('do case-insensitive search for a given text'), _('TEXT')),
4049 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4049 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4050 ('', 'removed', None, _('include revisions where files were removed')),
4050 ('', 'removed', None, _('include revisions where files were removed')),
4051 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4051 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4052 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4052 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4053 ('', 'only-branch', [],
4053 ('', 'only-branch', [],
4054 _('show only changesets within the given named branch (DEPRECATED)'),
4054 _('show only changesets within the given named branch (DEPRECATED)'),
4055 _('BRANCH')),
4055 _('BRANCH')),
4056 ('b', 'branch', [],
4056 ('b', 'branch', [],
4057 _('show changesets within the given named branch'), _('BRANCH')),
4057 _('show changesets within the given named branch'), _('BRANCH')),
4058 ('P', 'prune', [],
4058 ('P', 'prune', [],
4059 _('do not display revision or any of its ancestors'), _('REV')),
4059 _('do not display revision or any of its ancestors'), _('REV')),
4060 ] + logopts + walkopts,
4060 ] + logopts + walkopts,
4061 _('[OPTION]... [FILE]'),
4061 _('[OPTION]... [FILE]'),
4062 inferrepo=True)
4062 inferrepo=True)
4063 def log(ui, repo, *pats, **opts):
4063 def log(ui, repo, *pats, **opts):
4064 """show revision history of entire repository or files
4064 """show revision history of entire repository or files
4065
4065
4066 Print the revision history of the specified files or the entire
4066 Print the revision history of the specified files or the entire
4067 project.
4067 project.
4068
4068
4069 If no revision range is specified, the default is ``tip:0`` unless
4069 If no revision range is specified, the default is ``tip:0`` unless
4070 --follow is set, in which case the working directory parent is
4070 --follow is set, in which case the working directory parent is
4071 used as the starting revision.
4071 used as the starting revision.
4072
4072
4073 File history is shown without following rename or copy history of
4073 File history is shown without following rename or copy history of
4074 files. Use -f/--follow with a filename to follow history across
4074 files. Use -f/--follow with a filename to follow history across
4075 renames and copies. --follow without a filename will only show
4075 renames and copies. --follow without a filename will only show
4076 ancestors or descendants of the starting revision.
4076 ancestors or descendants of the starting revision.
4077
4077
4078 By default this command prints revision number and changeset id,
4078 By default this command prints revision number and changeset id,
4079 tags, non-trivial parents, user, date and time, and a summary for
4079 tags, non-trivial parents, user, date and time, and a summary for
4080 each commit. When the -v/--verbose switch is used, the list of
4080 each commit. When the -v/--verbose switch is used, the list of
4081 changed files and full commit message are shown.
4081 changed files and full commit message are shown.
4082
4082
4083 With --graph the revisions are shown as an ASCII art DAG with the most
4083 With --graph the revisions are shown as an ASCII art DAG with the most
4084 recent changeset at the top.
4084 recent changeset at the top.
4085 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4085 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4086 and '+' represents a fork where the changeset from the lines below is a
4086 and '+' represents a fork where the changeset from the lines below is a
4087 parent of the 'o' merge on the same line.
4087 parent of the 'o' merge on the same line.
4088
4088
4089 .. note::
4089 .. note::
4090
4090
4091 log -p/--patch may generate unexpected diff output for merge
4091 log -p/--patch may generate unexpected diff output for merge
4092 changesets, as it will only compare the merge changeset against
4092 changesets, as it will only compare the merge changeset against
4093 its first parent. Also, only files different from BOTH parents
4093 its first parent. Also, only files different from BOTH parents
4094 will appear in files:.
4094 will appear in files:.
4095
4095
4096 .. note::
4096 .. note::
4097
4097
4098 for performance reasons, log FILE may omit duplicate changes
4098 for performance reasons, log FILE may omit duplicate changes
4099 made on branches and will not show deletions. To see all
4099 made on branches and will not show deletions. To see all
4100 changes including duplicates and deletions, use the --removed
4100 changes including duplicates and deletions, use the --removed
4101 switch.
4101 switch.
4102
4102
4103 .. container:: verbose
4103 .. container:: verbose
4104
4104
4105 Some examples:
4105 Some examples:
4106
4106
4107 - changesets with full descriptions and file lists::
4107 - changesets with full descriptions and file lists::
4108
4108
4109 hg log -v
4109 hg log -v
4110
4110
4111 - changesets ancestral to the working directory::
4111 - changesets ancestral to the working directory::
4112
4112
4113 hg log -f
4113 hg log -f
4114
4114
4115 - last 10 commits on the current branch::
4115 - last 10 commits on the current branch::
4116
4116
4117 hg log -l 10 -b .
4117 hg log -l 10 -b .
4118
4118
4119 - changesets showing all modifications of a file, including removals::
4119 - changesets showing all modifications of a file, including removals::
4120
4120
4121 hg log --removed file.c
4121 hg log --removed file.c
4122
4122
4123 - all changesets that touch a directory, with diffs, excluding merges::
4123 - all changesets that touch a directory, with diffs, excluding merges::
4124
4124
4125 hg log -Mp lib/
4125 hg log -Mp lib/
4126
4126
4127 - all revision numbers that match a keyword::
4127 - all revision numbers that match a keyword::
4128
4128
4129 hg log -k bug --template "{rev}\\n"
4129 hg log -k bug --template "{rev}\\n"
4130
4130
4131 - check if a given changeset is included is a tagged release::
4131 - check if a given changeset is included is a tagged release::
4132
4132
4133 hg log -r "a21ccf and ancestor(1.9)"
4133 hg log -r "a21ccf and ancestor(1.9)"
4134
4134
4135 - find all changesets by some user in a date range::
4135 - find all changesets by some user in a date range::
4136
4136
4137 hg log -k alice -d "may 2008 to jul 2008"
4137 hg log -k alice -d "may 2008 to jul 2008"
4138
4138
4139 - summary of all changesets after the last tag::
4139 - summary of all changesets after the last tag::
4140
4140
4141 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4141 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4142
4142
4143 See :hg:`help dates` for a list of formats valid for -d/--date.
4143 See :hg:`help dates` for a list of formats valid for -d/--date.
4144
4144
4145 See :hg:`help revisions` and :hg:`help revsets` for more about
4145 See :hg:`help revisions` and :hg:`help revsets` for more about
4146 specifying revisions.
4146 specifying revisions.
4147
4147
4148 See :hg:`help templates` for more about pre-packaged styles and
4148 See :hg:`help templates` for more about pre-packaged styles and
4149 specifying custom templates.
4149 specifying custom templates.
4150
4150
4151 Returns 0 on success.
4151 Returns 0 on success.
4152 """
4152 """
4153 if opts.get('graph'):
4153 if opts.get('graph'):
4154 return cmdutil.graphlog(ui, repo, *pats, **opts)
4154 return cmdutil.graphlog(ui, repo, *pats, **opts)
4155
4155
4156 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4156 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4157 limit = cmdutil.loglimit(opts)
4157 limit = cmdutil.loglimit(opts)
4158 count = 0
4158 count = 0
4159
4159
4160 getrenamed = None
4160 getrenamed = None
4161 if opts.get('copies'):
4161 if opts.get('copies'):
4162 endrev = None
4162 endrev = None
4163 if opts.get('rev'):
4163 if opts.get('rev'):
4164 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4164 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4165 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4165 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4166
4166
4167 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4167 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4168 for rev in revs:
4168 for rev in revs:
4169 if count == limit:
4169 if count == limit:
4170 break
4170 break
4171 ctx = repo[rev]
4171 ctx = repo[rev]
4172 copies = None
4172 copies = None
4173 if getrenamed is not None and rev:
4173 if getrenamed is not None and rev:
4174 copies = []
4174 copies = []
4175 for fn in ctx.files():
4175 for fn in ctx.files():
4176 rename = getrenamed(fn, rev)
4176 rename = getrenamed(fn, rev)
4177 if rename:
4177 if rename:
4178 copies.append((fn, rename[0]))
4178 copies.append((fn, rename[0]))
4179 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4179 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4180 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4180 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4181 if displayer.flush(rev):
4181 if displayer.flush(rev):
4182 count += 1
4182 count += 1
4183
4183
4184 displayer.close()
4184 displayer.close()
4185
4185
4186 @command('manifest',
4186 @command('manifest',
4187 [('r', 'rev', '', _('revision to display'), _('REV')),
4187 [('r', 'rev', '', _('revision to display'), _('REV')),
4188 ('', 'all', False, _("list files from all revisions"))],
4188 ('', 'all', False, _("list files from all revisions"))],
4189 _('[-r REV]'))
4189 _('[-r REV]'))
4190 def manifest(ui, repo, node=None, rev=None, **opts):
4190 def manifest(ui, repo, node=None, rev=None, **opts):
4191 """output the current or given revision of the project manifest
4191 """output the current or given revision of the project manifest
4192
4192
4193 Print a list of version controlled files for the given revision.
4193 Print a list of version controlled files for the given revision.
4194 If no revision is given, the first parent of the working directory
4194 If no revision is given, the first parent of the working directory
4195 is used, or the null revision if no revision is checked out.
4195 is used, or the null revision if no revision is checked out.
4196
4196
4197 With -v, print file permissions, symlink and executable bits.
4197 With -v, print file permissions, symlink and executable bits.
4198 With --debug, print file revision hashes.
4198 With --debug, print file revision hashes.
4199
4199
4200 If option --all is specified, the list of all files from all revisions
4200 If option --all is specified, the list of all files from all revisions
4201 is printed. This includes deleted and renamed files.
4201 is printed. This includes deleted and renamed files.
4202
4202
4203 Returns 0 on success.
4203 Returns 0 on success.
4204 """
4204 """
4205
4205
4206 fm = ui.formatter('manifest', opts)
4206 fm = ui.formatter('manifest', opts)
4207
4207
4208 if opts.get('all'):
4208 if opts.get('all'):
4209 if rev or node:
4209 if rev or node:
4210 raise util.Abort(_("can't specify a revision with --all"))
4210 raise util.Abort(_("can't specify a revision with --all"))
4211
4211
4212 res = []
4212 res = []
4213 prefix = "data/"
4213 prefix = "data/"
4214 suffix = ".i"
4214 suffix = ".i"
4215 plen = len(prefix)
4215 plen = len(prefix)
4216 slen = len(suffix)
4216 slen = len(suffix)
4217 lock = repo.lock()
4217 lock = repo.lock()
4218 try:
4218 try:
4219 for fn, b, size in repo.store.datafiles():
4219 for fn, b, size in repo.store.datafiles():
4220 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4220 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4221 res.append(fn[plen:-slen])
4221 res.append(fn[plen:-slen])
4222 finally:
4222 finally:
4223 lock.release()
4223 lock.release()
4224 for f in res:
4224 for f in res:
4225 fm.startitem()
4225 fm.startitem()
4226 fm.write("path", '%s\n', f)
4226 fm.write("path", '%s\n', f)
4227 fm.end()
4227 fm.end()
4228 return
4228 return
4229
4229
4230 if rev and node:
4230 if rev and node:
4231 raise util.Abort(_("please specify just one revision"))
4231 raise util.Abort(_("please specify just one revision"))
4232
4232
4233 if not node:
4233 if not node:
4234 node = rev
4234 node = rev
4235
4235
4236 char = {'l': '@', 'x': '*', '': ''}
4236 char = {'l': '@', 'x': '*', '': ''}
4237 mode = {'l': '644', 'x': '755', '': '644'}
4237 mode = {'l': '644', 'x': '755', '': '644'}
4238 ctx = scmutil.revsingle(repo, node)
4238 ctx = scmutil.revsingle(repo, node)
4239 mf = ctx.manifest()
4239 mf = ctx.manifest()
4240 for f in ctx:
4240 for f in ctx:
4241 fm.startitem()
4241 fm.startitem()
4242 fl = ctx[f].flags()
4242 fl = ctx[f].flags()
4243 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4243 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4244 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4244 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4245 fm.write('path', '%s\n', f)
4245 fm.write('path', '%s\n', f)
4246 fm.end()
4246 fm.end()
4247
4247
4248 @command('^merge',
4248 @command('^merge',
4249 [('f', 'force', None,
4249 [('f', 'force', None,
4250 _('force a merge including outstanding changes (DEPRECATED)')),
4250 _('force a merge including outstanding changes (DEPRECATED)')),
4251 ('r', 'rev', '', _('revision to merge'), _('REV')),
4251 ('r', 'rev', '', _('revision to merge'), _('REV')),
4252 ('P', 'preview', None,
4252 ('P', 'preview', None,
4253 _('review revisions to merge (no merge is performed)'))
4253 _('review revisions to merge (no merge is performed)'))
4254 ] + mergetoolopts,
4254 ] + mergetoolopts,
4255 _('[-P] [-f] [[-r] REV]'))
4255 _('[-P] [-f] [[-r] REV]'))
4256 def merge(ui, repo, node=None, **opts):
4256 def merge(ui, repo, node=None, **opts):
4257 """merge working directory with another revision
4257 """merge working directory with another revision
4258
4258
4259 The current working directory is updated with all changes made in
4259 The current working directory is updated with all changes made in
4260 the requested revision since the last common predecessor revision.
4260 the requested revision since the last common predecessor revision.
4261
4261
4262 Files that changed between either parent are marked as changed for
4262 Files that changed between either parent are marked as changed for
4263 the next commit and a commit must be performed before any further
4263 the next commit and a commit must be performed before any further
4264 updates to the repository are allowed. The next commit will have
4264 updates to the repository are allowed. The next commit will have
4265 two parents.
4265 two parents.
4266
4266
4267 ``--tool`` can be used to specify the merge tool used for file
4267 ``--tool`` can be used to specify the merge tool used for file
4268 merges. It overrides the HGMERGE environment variable and your
4268 merges. It overrides the HGMERGE environment variable and your
4269 configuration files. See :hg:`help merge-tools` for options.
4269 configuration files. See :hg:`help merge-tools` for options.
4270
4270
4271 If no revision is specified, the working directory's parent is a
4271 If no revision is specified, the working directory's parent is a
4272 head revision, and the current branch contains exactly one other
4272 head revision, and the current branch contains exactly one other
4273 head, the other head is merged with by default. Otherwise, an
4273 head, the other head is merged with by default. Otherwise, an
4274 explicit revision with which to merge with must be provided.
4274 explicit revision with which to merge with must be provided.
4275
4275
4276 :hg:`resolve` must be used to resolve unresolved files.
4276 :hg:`resolve` must be used to resolve unresolved files.
4277
4277
4278 To undo an uncommitted merge, use :hg:`update --clean .` which
4278 To undo an uncommitted merge, use :hg:`update --clean .` which
4279 will check out a clean copy of the original merge parent, losing
4279 will check out a clean copy of the original merge parent, losing
4280 all changes.
4280 all changes.
4281
4281
4282 Returns 0 on success, 1 if there are unresolved files.
4282 Returns 0 on success, 1 if there are unresolved files.
4283 """
4283 """
4284
4284
4285 if opts.get('rev') and node:
4285 if opts.get('rev') and node:
4286 raise util.Abort(_("please specify just one revision"))
4286 raise util.Abort(_("please specify just one revision"))
4287 if not node:
4287 if not node:
4288 node = opts.get('rev')
4288 node = opts.get('rev')
4289
4289
4290 if node:
4290 if node:
4291 node = scmutil.revsingle(repo, node).node()
4291 node = scmutil.revsingle(repo, node).node()
4292
4292
4293 if not node and repo._bookmarkcurrent:
4293 if not node and repo._bookmarkcurrent:
4294 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4294 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4295 curhead = repo[repo._bookmarkcurrent].node()
4295 curhead = repo[repo._bookmarkcurrent].node()
4296 if len(bmheads) == 2:
4296 if len(bmheads) == 2:
4297 if curhead == bmheads[0]:
4297 if curhead == bmheads[0]:
4298 node = bmheads[1]
4298 node = bmheads[1]
4299 else:
4299 else:
4300 node = bmheads[0]
4300 node = bmheads[0]
4301 elif len(bmheads) > 2:
4301 elif len(bmheads) > 2:
4302 raise util.Abort(_("multiple matching bookmarks to merge - "
4302 raise util.Abort(_("multiple matching bookmarks to merge - "
4303 "please merge with an explicit rev or bookmark"),
4303 "please merge with an explicit rev or bookmark"),
4304 hint=_("run 'hg heads' to see all heads"))
4304 hint=_("run 'hg heads' to see all heads"))
4305 elif len(bmheads) <= 1:
4305 elif len(bmheads) <= 1:
4306 raise util.Abort(_("no matching bookmark to merge - "
4306 raise util.Abort(_("no matching bookmark to merge - "
4307 "please merge with an explicit rev or bookmark"),
4307 "please merge with an explicit rev or bookmark"),
4308 hint=_("run 'hg heads' to see all heads"))
4308 hint=_("run 'hg heads' to see all heads"))
4309
4309
4310 if not node and not repo._bookmarkcurrent:
4310 if not node and not repo._bookmarkcurrent:
4311 branch = repo[None].branch()
4311 branch = repo[None].branch()
4312 bheads = repo.branchheads(branch)
4312 bheads = repo.branchheads(branch)
4313 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4313 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4314
4314
4315 if len(nbhs) > 2:
4315 if len(nbhs) > 2:
4316 raise util.Abort(_("branch '%s' has %d heads - "
4316 raise util.Abort(_("branch '%s' has %d heads - "
4317 "please merge with an explicit rev")
4317 "please merge with an explicit rev")
4318 % (branch, len(bheads)),
4318 % (branch, len(bheads)),
4319 hint=_("run 'hg heads .' to see heads"))
4319 hint=_("run 'hg heads .' to see heads"))
4320
4320
4321 parent = repo.dirstate.p1()
4321 parent = repo.dirstate.p1()
4322 if len(nbhs) <= 1:
4322 if len(nbhs) <= 1:
4323 if len(bheads) > 1:
4323 if len(bheads) > 1:
4324 raise util.Abort(_("heads are bookmarked - "
4324 raise util.Abort(_("heads are bookmarked - "
4325 "please merge with an explicit rev"),
4325 "please merge with an explicit rev"),
4326 hint=_("run 'hg heads' to see all heads"))
4326 hint=_("run 'hg heads' to see all heads"))
4327 if len(repo.heads()) > 1:
4327 if len(repo.heads()) > 1:
4328 raise util.Abort(_("branch '%s' has one head - "
4328 raise util.Abort(_("branch '%s' has one head - "
4329 "please merge with an explicit rev")
4329 "please merge with an explicit rev")
4330 % branch,
4330 % branch,
4331 hint=_("run 'hg heads' to see all heads"))
4331 hint=_("run 'hg heads' to see all heads"))
4332 msg, hint = _('nothing to merge'), None
4332 msg, hint = _('nothing to merge'), None
4333 if parent != repo.lookup(branch):
4333 if parent != repo.lookup(branch):
4334 hint = _("use 'hg update' instead")
4334 hint = _("use 'hg update' instead")
4335 raise util.Abort(msg, hint=hint)
4335 raise util.Abort(msg, hint=hint)
4336
4336
4337 if parent not in bheads:
4337 if parent not in bheads:
4338 raise util.Abort(_('working directory not at a head revision'),
4338 raise util.Abort(_('working directory not at a head revision'),
4339 hint=_("use 'hg update' or merge with an "
4339 hint=_("use 'hg update' or merge with an "
4340 "explicit revision"))
4340 "explicit revision"))
4341 if parent == nbhs[0]:
4341 if parent == nbhs[0]:
4342 node = nbhs[-1]
4342 node = nbhs[-1]
4343 else:
4343 else:
4344 node = nbhs[0]
4344 node = nbhs[0]
4345
4345
4346 if opts.get('preview'):
4346 if opts.get('preview'):
4347 # find nodes that are ancestors of p2 but not of p1
4347 # find nodes that are ancestors of p2 but not of p1
4348 p1 = repo.lookup('.')
4348 p1 = repo.lookup('.')
4349 p2 = repo.lookup(node)
4349 p2 = repo.lookup(node)
4350 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4350 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4351
4351
4352 displayer = cmdutil.show_changeset(ui, repo, opts)
4352 displayer = cmdutil.show_changeset(ui, repo, opts)
4353 for node in nodes:
4353 for node in nodes:
4354 displayer.show(repo[node])
4354 displayer.show(repo[node])
4355 displayer.close()
4355 displayer.close()
4356 return 0
4356 return 0
4357
4357
4358 try:
4358 try:
4359 # ui.forcemerge is an internal variable, do not document
4359 # ui.forcemerge is an internal variable, do not document
4360 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4360 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4361 return hg.merge(repo, node, force=opts.get('force'))
4361 return hg.merge(repo, node, force=opts.get('force'))
4362 finally:
4362 finally:
4363 ui.setconfig('ui', 'forcemerge', '', 'merge')
4363 ui.setconfig('ui', 'forcemerge', '', 'merge')
4364
4364
4365 @command('outgoing|out',
4365 @command('outgoing|out',
4366 [('f', 'force', None, _('run even when the destination is unrelated')),
4366 [('f', 'force', None, _('run even when the destination is unrelated')),
4367 ('r', 'rev', [],
4367 ('r', 'rev', [],
4368 _('a changeset intended to be included in the destination'), _('REV')),
4368 _('a changeset intended to be included in the destination'), _('REV')),
4369 ('n', 'newest-first', None, _('show newest record first')),
4369 ('n', 'newest-first', None, _('show newest record first')),
4370 ('B', 'bookmarks', False, _('compare bookmarks')),
4370 ('B', 'bookmarks', False, _('compare bookmarks')),
4371 ('b', 'branch', [], _('a specific branch you would like to push'),
4371 ('b', 'branch', [], _('a specific branch you would like to push'),
4372 _('BRANCH')),
4372 _('BRANCH')),
4373 ] + logopts + remoteopts + subrepoopts,
4373 ] + logopts + remoteopts + subrepoopts,
4374 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4374 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4375 def outgoing(ui, repo, dest=None, **opts):
4375 def outgoing(ui, repo, dest=None, **opts):
4376 """show changesets not found in the destination
4376 """show changesets not found in the destination
4377
4377
4378 Show changesets not found in the specified destination repository
4378 Show changesets not found in the specified destination repository
4379 or the default push location. These are the changesets that would
4379 or the default push location. These are the changesets that would
4380 be pushed if a push was requested.
4380 be pushed if a push was requested.
4381
4381
4382 See pull for details of valid destination formats.
4382 See pull for details of valid destination formats.
4383
4383
4384 Returns 0 if there are outgoing changes, 1 otherwise.
4384 Returns 0 if there are outgoing changes, 1 otherwise.
4385 """
4385 """
4386 if opts.get('graph'):
4386 if opts.get('graph'):
4387 cmdutil.checkunsupportedgraphflags([], opts)
4387 cmdutil.checkunsupportedgraphflags([], opts)
4388 o, other = hg._outgoing(ui, repo, dest, opts)
4388 o, other = hg._outgoing(ui, repo, dest, opts)
4389 if not o:
4389 if not o:
4390 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4390 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4391 return
4391 return
4392
4392
4393 revdag = cmdutil.graphrevs(repo, o, opts)
4393 revdag = cmdutil.graphrevs(repo, o, opts)
4394 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4394 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4395 showparents = [ctx.node() for ctx in repo[None].parents()]
4395 showparents = [ctx.node() for ctx in repo[None].parents()]
4396 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4396 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4397 graphmod.asciiedges)
4397 graphmod.asciiedges)
4398 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4398 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4399 return 0
4399 return 0
4400
4400
4401 if opts.get('bookmarks'):
4401 if opts.get('bookmarks'):
4402 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4402 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4403 dest, branches = hg.parseurl(dest, opts.get('branch'))
4403 dest, branches = hg.parseurl(dest, opts.get('branch'))
4404 other = hg.peer(repo, opts, dest)
4404 other = hg.peer(repo, opts, dest)
4405 if 'bookmarks' not in other.listkeys('namespaces'):
4405 if 'bookmarks' not in other.listkeys('namespaces'):
4406 ui.warn(_("remote doesn't support bookmarks\n"))
4406 ui.warn(_("remote doesn't support bookmarks\n"))
4407 return 0
4407 return 0
4408 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4408 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4409 return bookmarks.diff(ui, other, repo)
4409 return bookmarks.diff(ui, other, repo)
4410
4410
4411 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4411 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4412 try:
4412 try:
4413 return hg.outgoing(ui, repo, dest, opts)
4413 return hg.outgoing(ui, repo, dest, opts)
4414 finally:
4414 finally:
4415 del repo._subtoppath
4415 del repo._subtoppath
4416
4416
4417 @command('parents',
4417 @command('parents',
4418 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4418 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4419 ] + templateopts,
4419 ] + templateopts,
4420 _('[-r REV] [FILE]'),
4420 _('[-r REV] [FILE]'),
4421 inferrepo=True)
4421 inferrepo=True)
4422 def parents(ui, repo, file_=None, **opts):
4422 def parents(ui, repo, file_=None, **opts):
4423 """show the parents of the working directory or revision
4423 """show the parents of the working directory or revision
4424
4424
4425 Print the working directory's parent revisions. If a revision is
4425 Print the working directory's parent revisions. If a revision is
4426 given via -r/--rev, the parent of that revision will be printed.
4426 given via -r/--rev, the parent of that revision will be printed.
4427 If a file argument is given, the revision in which the file was
4427 If a file argument is given, the revision in which the file was
4428 last changed (before the working directory revision or the
4428 last changed (before the working directory revision or the
4429 argument to --rev if given) is printed.
4429 argument to --rev if given) is printed.
4430
4430
4431 Returns 0 on success.
4431 Returns 0 on success.
4432 """
4432 """
4433
4433
4434 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4434 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4435
4435
4436 if file_:
4436 if file_:
4437 m = scmutil.match(ctx, (file_,), opts)
4437 m = scmutil.match(ctx, (file_,), opts)
4438 if m.anypats() or len(m.files()) != 1:
4438 if m.anypats() or len(m.files()) != 1:
4439 raise util.Abort(_('can only specify an explicit filename'))
4439 raise util.Abort(_('can only specify an explicit filename'))
4440 file_ = m.files()[0]
4440 file_ = m.files()[0]
4441 filenodes = []
4441 filenodes = []
4442 for cp in ctx.parents():
4442 for cp in ctx.parents():
4443 if not cp:
4443 if not cp:
4444 continue
4444 continue
4445 try:
4445 try:
4446 filenodes.append(cp.filenode(file_))
4446 filenodes.append(cp.filenode(file_))
4447 except error.LookupError:
4447 except error.LookupError:
4448 pass
4448 pass
4449 if not filenodes:
4449 if not filenodes:
4450 raise util.Abort(_("'%s' not found in manifest!") % file_)
4450 raise util.Abort(_("'%s' not found in manifest!") % file_)
4451 p = []
4451 p = []
4452 for fn in filenodes:
4452 for fn in filenodes:
4453 fctx = repo.filectx(file_, fileid=fn)
4453 fctx = repo.filectx(file_, fileid=fn)
4454 p.append(fctx.node())
4454 p.append(fctx.node())
4455 else:
4455 else:
4456 p = [cp.node() for cp in ctx.parents()]
4456 p = [cp.node() for cp in ctx.parents()]
4457
4457
4458 displayer = cmdutil.show_changeset(ui, repo, opts)
4458 displayer = cmdutil.show_changeset(ui, repo, opts)
4459 for n in p:
4459 for n in p:
4460 if n != nullid:
4460 if n != nullid:
4461 displayer.show(repo[n])
4461 displayer.show(repo[n])
4462 displayer.close()
4462 displayer.close()
4463
4463
4464 @command('paths', [], _('[NAME]'), optionalrepo=True)
4464 @command('paths', [], _('[NAME]'), optionalrepo=True)
4465 def paths(ui, repo, search=None):
4465 def paths(ui, repo, search=None):
4466 """show aliases for remote repositories
4466 """show aliases for remote repositories
4467
4467
4468 Show definition of symbolic path name NAME. If no name is given,
4468 Show definition of symbolic path name NAME. If no name is given,
4469 show definition of all available names.
4469 show definition of all available names.
4470
4470
4471 Option -q/--quiet suppresses all output when searching for NAME
4471 Option -q/--quiet suppresses all output when searching for NAME
4472 and shows only the path names when listing all definitions.
4472 and shows only the path names when listing all definitions.
4473
4473
4474 Path names are defined in the [paths] section of your
4474 Path names are defined in the [paths] section of your
4475 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4475 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4476 repository, ``.hg/hgrc`` is used, too.
4476 repository, ``.hg/hgrc`` is used, too.
4477
4477
4478 The path names ``default`` and ``default-push`` have a special
4478 The path names ``default`` and ``default-push`` have a special
4479 meaning. When performing a push or pull operation, they are used
4479 meaning. When performing a push or pull operation, they are used
4480 as fallbacks if no location is specified on the command-line.
4480 as fallbacks if no location is specified on the command-line.
4481 When ``default-push`` is set, it will be used for push and
4481 When ``default-push`` is set, it will be used for push and
4482 ``default`` will be used for pull; otherwise ``default`` is used
4482 ``default`` will be used for pull; otherwise ``default`` is used
4483 as the fallback for both. When cloning a repository, the clone
4483 as the fallback for both. When cloning a repository, the clone
4484 source is written as ``default`` in ``.hg/hgrc``. Note that
4484 source is written as ``default`` in ``.hg/hgrc``. Note that
4485 ``default`` and ``default-push`` apply to all inbound (e.g.
4485 ``default`` and ``default-push`` apply to all inbound (e.g.
4486 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4486 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4487 :hg:`bundle`) operations.
4487 :hg:`bundle`) operations.
4488
4488
4489 See :hg:`help urls` for more information.
4489 See :hg:`help urls` for more information.
4490
4490
4491 Returns 0 on success.
4491 Returns 0 on success.
4492 """
4492 """
4493 if search:
4493 if search:
4494 for name, path in ui.configitems("paths"):
4494 for name, path in ui.configitems("paths"):
4495 if name == search:
4495 if name == search:
4496 ui.status("%s\n" % util.hidepassword(path))
4496 ui.status("%s\n" % util.hidepassword(path))
4497 return
4497 return
4498 if not ui.quiet:
4498 if not ui.quiet:
4499 ui.warn(_("not found!\n"))
4499 ui.warn(_("not found!\n"))
4500 return 1
4500 return 1
4501 else:
4501 else:
4502 for name, path in ui.configitems("paths"):
4502 for name, path in ui.configitems("paths"):
4503 if ui.quiet:
4503 if ui.quiet:
4504 ui.write("%s\n" % name)
4504 ui.write("%s\n" % name)
4505 else:
4505 else:
4506 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4506 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4507
4507
4508 @command('phase',
4508 @command('phase',
4509 [('p', 'public', False, _('set changeset phase to public')),
4509 [('p', 'public', False, _('set changeset phase to public')),
4510 ('d', 'draft', False, _('set changeset phase to draft')),
4510 ('d', 'draft', False, _('set changeset phase to draft')),
4511 ('s', 'secret', False, _('set changeset phase to secret')),
4511 ('s', 'secret', False, _('set changeset phase to secret')),
4512 ('f', 'force', False, _('allow to move boundary backward')),
4512 ('f', 'force', False, _('allow to move boundary backward')),
4513 ('r', 'rev', [], _('target revision'), _('REV')),
4513 ('r', 'rev', [], _('target revision'), _('REV')),
4514 ],
4514 ],
4515 _('[-p|-d|-s] [-f] [-r] REV...'))
4515 _('[-p|-d|-s] [-f] [-r] REV...'))
4516 def phase(ui, repo, *revs, **opts):
4516 def phase(ui, repo, *revs, **opts):
4517 """set or show the current phase name
4517 """set or show the current phase name
4518
4518
4519 With no argument, show the phase name of specified revisions.
4519 With no argument, show the phase name of specified revisions.
4520
4520
4521 With one of -p/--public, -d/--draft or -s/--secret, change the
4521 With one of -p/--public, -d/--draft or -s/--secret, change the
4522 phase value of the specified revisions.
4522 phase value of the specified revisions.
4523
4523
4524 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4524 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4525 lower phase to an higher phase. Phases are ordered as follows::
4525 lower phase to an higher phase. Phases are ordered as follows::
4526
4526
4527 public < draft < secret
4527 public < draft < secret
4528
4528
4529 Returns 0 on success, 1 if no phases were changed or some could not
4529 Returns 0 on success, 1 if no phases were changed or some could not
4530 be changed.
4530 be changed.
4531 """
4531 """
4532 # search for a unique phase argument
4532 # search for a unique phase argument
4533 targetphase = None
4533 targetphase = None
4534 for idx, name in enumerate(phases.phasenames):
4534 for idx, name in enumerate(phases.phasenames):
4535 if opts[name]:
4535 if opts[name]:
4536 if targetphase is not None:
4536 if targetphase is not None:
4537 raise util.Abort(_('only one phase can be specified'))
4537 raise util.Abort(_('only one phase can be specified'))
4538 targetphase = idx
4538 targetphase = idx
4539
4539
4540 # look for specified revision
4540 # look for specified revision
4541 revs = list(revs)
4541 revs = list(revs)
4542 revs.extend(opts['rev'])
4542 revs.extend(opts['rev'])
4543 if not revs:
4543 if not revs:
4544 raise util.Abort(_('no revisions specified'))
4544 raise util.Abort(_('no revisions specified'))
4545
4545
4546 revs = scmutil.revrange(repo, revs)
4546 revs = scmutil.revrange(repo, revs)
4547
4547
4548 lock = None
4548 lock = None
4549 ret = 0
4549 ret = 0
4550 if targetphase is None:
4550 if targetphase is None:
4551 # display
4551 # display
4552 for r in revs:
4552 for r in revs:
4553 ctx = repo[r]
4553 ctx = repo[r]
4554 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4554 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4555 else:
4555 else:
4556 lock = repo.lock()
4556 lock = repo.lock()
4557 try:
4557 try:
4558 # set phase
4558 # set phase
4559 if not revs:
4559 if not revs:
4560 raise util.Abort(_('empty revision set'))
4560 raise util.Abort(_('empty revision set'))
4561 nodes = [repo[r].node() for r in revs]
4561 nodes = [repo[r].node() for r in revs]
4562 olddata = repo._phasecache.getphaserevs(repo)[:]
4562 olddata = repo._phasecache.getphaserevs(repo)[:]
4563 phases.advanceboundary(repo, targetphase, nodes)
4563 phases.advanceboundary(repo, targetphase, nodes)
4564 if opts['force']:
4564 if opts['force']:
4565 phases.retractboundary(repo, targetphase, nodes)
4565 phases.retractboundary(repo, targetphase, nodes)
4566 finally:
4566 finally:
4567 lock.release()
4567 lock.release()
4568 # moving revision from public to draft may hide them
4568 # moving revision from public to draft may hide them
4569 # We have to check result on an unfiltered repository
4569 # We have to check result on an unfiltered repository
4570 unfi = repo.unfiltered()
4570 unfi = repo.unfiltered()
4571 newdata = repo._phasecache.getphaserevs(unfi)
4571 newdata = repo._phasecache.getphaserevs(unfi)
4572 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4572 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4573 cl = unfi.changelog
4573 cl = unfi.changelog
4574 rejected = [n for n in nodes
4574 rejected = [n for n in nodes
4575 if newdata[cl.rev(n)] < targetphase]
4575 if newdata[cl.rev(n)] < targetphase]
4576 if rejected:
4576 if rejected:
4577 ui.warn(_('cannot move %i changesets to a higher '
4577 ui.warn(_('cannot move %i changesets to a higher '
4578 'phase, use --force\n') % len(rejected))
4578 'phase, use --force\n') % len(rejected))
4579 ret = 1
4579 ret = 1
4580 if changes:
4580 if changes:
4581 msg = _('phase changed for %i changesets\n') % changes
4581 msg = _('phase changed for %i changesets\n') % changes
4582 if ret:
4582 if ret:
4583 ui.status(msg)
4583 ui.status(msg)
4584 else:
4584 else:
4585 ui.note(msg)
4585 ui.note(msg)
4586 else:
4586 else:
4587 ui.warn(_('no phases changed\n'))
4587 ui.warn(_('no phases changed\n'))
4588 ret = 1
4588 ret = 1
4589 return ret
4589 return ret
4590
4590
4591 def postincoming(ui, repo, modheads, optupdate, checkout):
4591 def postincoming(ui, repo, modheads, optupdate, checkout):
4592 if modheads == 0:
4592 if modheads == 0:
4593 return
4593 return
4594 if optupdate:
4594 if optupdate:
4595 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4595 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4596 try:
4596 try:
4597 ret = hg.update(repo, checkout)
4597 ret = hg.update(repo, checkout)
4598 except util.Abort, inst:
4598 except util.Abort, inst:
4599 ui.warn(_("not updating: %s\n") % str(inst))
4599 ui.warn(_("not updating: %s\n") % str(inst))
4600 if inst.hint:
4600 if inst.hint:
4601 ui.warn(_("(%s)\n") % inst.hint)
4601 ui.warn(_("(%s)\n") % inst.hint)
4602 return 0
4602 return 0
4603 if not ret and not checkout:
4603 if not ret and not checkout:
4604 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4604 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4605 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4605 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4606 return ret
4606 return ret
4607 if modheads > 1:
4607 if modheads > 1:
4608 currentbranchheads = len(repo.branchheads())
4608 currentbranchheads = len(repo.branchheads())
4609 if currentbranchheads == modheads:
4609 if currentbranchheads == modheads:
4610 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4610 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4611 elif currentbranchheads > 1:
4611 elif currentbranchheads > 1:
4612 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4612 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4613 "merge)\n"))
4613 "merge)\n"))
4614 else:
4614 else:
4615 ui.status(_("(run 'hg heads' to see heads)\n"))
4615 ui.status(_("(run 'hg heads' to see heads)\n"))
4616 else:
4616 else:
4617 ui.status(_("(run 'hg update' to get a working copy)\n"))
4617 ui.status(_("(run 'hg update' to get a working copy)\n"))
4618
4618
4619 @command('^pull',
4619 @command('^pull',
4620 [('u', 'update', None,
4620 [('u', 'update', None,
4621 _('update to new branch head if changesets were pulled')),
4621 _('update to new branch head if changesets were pulled')),
4622 ('f', 'force', None, _('run even when remote repository is unrelated')),
4622 ('f', 'force', None, _('run even when remote repository is unrelated')),
4623 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4623 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4624 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4624 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4625 ('b', 'branch', [], _('a specific branch you would like to pull'),
4625 ('b', 'branch', [], _('a specific branch you would like to pull'),
4626 _('BRANCH')),
4626 _('BRANCH')),
4627 ] + remoteopts,
4627 ] + remoteopts,
4628 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4628 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4629 def pull(ui, repo, source="default", **opts):
4629 def pull(ui, repo, source="default", **opts):
4630 """pull changes from the specified source
4630 """pull changes from the specified source
4631
4631
4632 Pull changes from a remote repository to a local one.
4632 Pull changes from a remote repository to a local one.
4633
4633
4634 This finds all changes from the repository at the specified path
4634 This finds all changes from the repository at the specified path
4635 or URL and adds them to a local repository (the current one unless
4635 or URL and adds them to a local repository (the current one unless
4636 -R is specified). By default, this does not update the copy of the
4636 -R is specified). By default, this does not update the copy of the
4637 project in the working directory.
4637 project in the working directory.
4638
4638
4639 Use :hg:`incoming` if you want to see what would have been added
4639 Use :hg:`incoming` if you want to see what would have been added
4640 by a pull at the time you issued this command. If you then decide
4640 by a pull at the time you issued this command. If you then decide
4641 to add those changes to the repository, you should use :hg:`pull
4641 to add those changes to the repository, you should use :hg:`pull
4642 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4642 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4643
4643
4644 If SOURCE is omitted, the 'default' path will be used.
4644 If SOURCE is omitted, the 'default' path will be used.
4645 See :hg:`help urls` for more information.
4645 See :hg:`help urls` for more information.
4646
4646
4647 Returns 0 on success, 1 if an update had unresolved files.
4647 Returns 0 on success, 1 if an update had unresolved files.
4648 """
4648 """
4649 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4649 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4650 other = hg.peer(repo, opts, source)
4650 other = hg.peer(repo, opts, source)
4651 try:
4651 try:
4652 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4652 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4653 revs, checkout = hg.addbranchrevs(repo, other, branches,
4653 revs, checkout = hg.addbranchrevs(repo, other, branches,
4654 opts.get('rev'))
4654 opts.get('rev'))
4655
4655
4656 remotebookmarks = other.listkeys('bookmarks')
4656 remotebookmarks = other.listkeys('bookmarks')
4657
4657
4658 if opts.get('bookmark'):
4658 if opts.get('bookmark'):
4659 if not revs:
4659 if not revs:
4660 revs = []
4660 revs = []
4661 for b in opts['bookmark']:
4661 for b in opts['bookmark']:
4662 if b not in remotebookmarks:
4662 if b not in remotebookmarks:
4663 raise util.Abort(_('remote bookmark %s not found!') % b)
4663 raise util.Abort(_('remote bookmark %s not found!') % b)
4664 revs.append(remotebookmarks[b])
4664 revs.append(remotebookmarks[b])
4665
4665
4666 if revs:
4666 if revs:
4667 try:
4667 try:
4668 revs = [other.lookup(rev) for rev in revs]
4668 revs = [other.lookup(rev) for rev in revs]
4669 except error.CapabilityError:
4669 except error.CapabilityError:
4670 err = _("other repository doesn't support revision lookup, "
4670 err = _("other repository doesn't support revision lookup, "
4671 "so a rev cannot be specified.")
4671 "so a rev cannot be specified.")
4672 raise util.Abort(err)
4672 raise util.Abort(err)
4673
4673
4674 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4674 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4675 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4675 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4676 if checkout:
4676 if checkout:
4677 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4677 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4678 repo._subtoppath = source
4678 repo._subtoppath = source
4679 try:
4679 try:
4680 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4680 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4681
4681
4682 finally:
4682 finally:
4683 del repo._subtoppath
4683 del repo._subtoppath
4684
4684
4685 # update specified bookmarks
4685 # update specified bookmarks
4686 if opts.get('bookmark'):
4686 if opts.get('bookmark'):
4687 marks = repo._bookmarks
4687 marks = repo._bookmarks
4688 for b in opts['bookmark']:
4688 for b in opts['bookmark']:
4689 # explicit pull overrides local bookmark if any
4689 # explicit pull overrides local bookmark if any
4690 ui.status(_("importing bookmark %s\n") % b)
4690 ui.status(_("importing bookmark %s\n") % b)
4691 marks[b] = repo[remotebookmarks[b]].node()
4691 marks[b] = repo[remotebookmarks[b]].node()
4692 marks.write()
4692 marks.write()
4693 finally:
4693 finally:
4694 other.close()
4694 other.close()
4695 return ret
4695 return ret
4696
4696
4697 @command('^push',
4697 @command('^push',
4698 [('f', 'force', None, _('force push')),
4698 [('f', 'force', None, _('force push')),
4699 ('r', 'rev', [],
4699 ('r', 'rev', [],
4700 _('a changeset intended to be included in the destination'),
4700 _('a changeset intended to be included in the destination'),
4701 _('REV')),
4701 _('REV')),
4702 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4702 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4703 ('b', 'branch', [],
4703 ('b', 'branch', [],
4704 _('a specific branch you would like to push'), _('BRANCH')),
4704 _('a specific branch you would like to push'), _('BRANCH')),
4705 ('', 'new-branch', False, _('allow pushing a new branch')),
4705 ('', 'new-branch', False, _('allow pushing a new branch')),
4706 ] + remoteopts,
4706 ] + remoteopts,
4707 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4707 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4708 def push(ui, repo, dest=None, **opts):
4708 def push(ui, repo, dest=None, **opts):
4709 """push changes to the specified destination
4709 """push changes to the specified destination
4710
4710
4711 Push changesets from the local repository to the specified
4711 Push changesets from the local repository to the specified
4712 destination.
4712 destination.
4713
4713
4714 This operation is symmetrical to pull: it is identical to a pull
4714 This operation is symmetrical to pull: it is identical to a pull
4715 in the destination repository from the current one.
4715 in the destination repository from the current one.
4716
4716
4717 By default, push will not allow creation of new heads at the
4717 By default, push will not allow creation of new heads at the
4718 destination, since multiple heads would make it unclear which head
4718 destination, since multiple heads would make it unclear which head
4719 to use. In this situation, it is recommended to pull and merge
4719 to use. In this situation, it is recommended to pull and merge
4720 before pushing.
4720 before pushing.
4721
4721
4722 Use --new-branch if you want to allow push to create a new named
4722 Use --new-branch if you want to allow push to create a new named
4723 branch that is not present at the destination. This allows you to
4723 branch that is not present at the destination. This allows you to
4724 only create a new branch without forcing other changes.
4724 only create a new branch without forcing other changes.
4725
4725
4726 .. note::
4726 .. note::
4727
4727
4728 Extra care should be taken with the -f/--force option,
4728 Extra care should be taken with the -f/--force option,
4729 which will push all new heads on all branches, an action which will
4729 which will push all new heads on all branches, an action which will
4730 almost always cause confusion for collaborators.
4730 almost always cause confusion for collaborators.
4731
4731
4732 If -r/--rev is used, the specified revision and all its ancestors
4732 If -r/--rev is used, the specified revision and all its ancestors
4733 will be pushed to the remote repository.
4733 will be pushed to the remote repository.
4734
4734
4735 If -B/--bookmark is used, the specified bookmarked revision, its
4735 If -B/--bookmark is used, the specified bookmarked revision, its
4736 ancestors, and the bookmark will be pushed to the remote
4736 ancestors, and the bookmark will be pushed to the remote
4737 repository.
4737 repository.
4738
4738
4739 Please see :hg:`help urls` for important details about ``ssh://``
4739 Please see :hg:`help urls` for important details about ``ssh://``
4740 URLs. If DESTINATION is omitted, a default path will be used.
4740 URLs. If DESTINATION is omitted, a default path will be used.
4741
4741
4742 Returns 0 if push was successful, 1 if nothing to push.
4742 Returns 0 if push was successful, 1 if nothing to push.
4743 """
4743 """
4744
4744
4745 if opts.get('bookmark'):
4745 if opts.get('bookmark'):
4746 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4746 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4747 for b in opts['bookmark']:
4747 for b in opts['bookmark']:
4748 # translate -B options to -r so changesets get pushed
4748 # translate -B options to -r so changesets get pushed
4749 if b in repo._bookmarks:
4749 if b in repo._bookmarks:
4750 opts.setdefault('rev', []).append(b)
4750 opts.setdefault('rev', []).append(b)
4751 else:
4751 else:
4752 # if we try to push a deleted bookmark, translate it to null
4752 # if we try to push a deleted bookmark, translate it to null
4753 # this lets simultaneous -r, -b options continue working
4753 # this lets simultaneous -r, -b options continue working
4754 opts.setdefault('rev', []).append("null")
4754 opts.setdefault('rev', []).append("null")
4755
4755
4756 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4756 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4757 dest, branches = hg.parseurl(dest, opts.get('branch'))
4757 dest, branches = hg.parseurl(dest, opts.get('branch'))
4758 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4758 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4759 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4759 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4760 try:
4760 try:
4761 other = hg.peer(repo, opts, dest)
4761 other = hg.peer(repo, opts, dest)
4762 except error.RepoError:
4762 except error.RepoError:
4763 if dest == "default-push":
4763 if dest == "default-push":
4764 raise util.Abort(_("default repository not configured!"),
4764 raise util.Abort(_("default repository not configured!"),
4765 hint=_('see the "path" section in "hg help config"'))
4765 hint=_('see the "path" section in "hg help config"'))
4766 else:
4766 else:
4767 raise
4767 raise
4768
4768
4769 if revs:
4769 if revs:
4770 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4770 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4771
4771
4772 repo._subtoppath = dest
4772 repo._subtoppath = dest
4773 try:
4773 try:
4774 # push subrepos depth-first for coherent ordering
4774 # push subrepos depth-first for coherent ordering
4775 c = repo['']
4775 c = repo['']
4776 subs = c.substate # only repos that are committed
4776 subs = c.substate # only repos that are committed
4777 for s in sorted(subs):
4777 for s in sorted(subs):
4778 result = c.sub(s).push(opts)
4778 result = c.sub(s).push(opts)
4779 if result == 0:
4779 if result == 0:
4780 return not result
4780 return not result
4781 finally:
4781 finally:
4782 del repo._subtoppath
4782 del repo._subtoppath
4783 result = repo.push(other, opts.get('force'), revs=revs,
4783 result = repo.push(other, opts.get('force'), revs=revs,
4784 newbranch=opts.get('new_branch'))
4784 newbranch=opts.get('new_branch'))
4785
4785
4786 result = not result
4786 result = not result
4787
4787
4788 if opts.get('bookmark'):
4788 if opts.get('bookmark'):
4789 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4789 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4790 if bresult == 2:
4790 if bresult == 2:
4791 return 2
4791 return 2
4792 if not result and bresult:
4792 if not result and bresult:
4793 result = 2
4793 result = 2
4794
4794
4795 return result
4795 return result
4796
4796
4797 @command('recover', [])
4797 @command('recover', [])
4798 def recover(ui, repo):
4798 def recover(ui, repo):
4799 """roll back an interrupted transaction
4799 """roll back an interrupted transaction
4800
4800
4801 Recover from an interrupted commit or pull.
4801 Recover from an interrupted commit or pull.
4802
4802
4803 This command tries to fix the repository status after an
4803 This command tries to fix the repository status after an
4804 interrupted operation. It should only be necessary when Mercurial
4804 interrupted operation. It should only be necessary when Mercurial
4805 suggests it.
4805 suggests it.
4806
4806
4807 Returns 0 if successful, 1 if nothing to recover or verify fails.
4807 Returns 0 if successful, 1 if nothing to recover or verify fails.
4808 """
4808 """
4809 if repo.recover():
4809 if repo.recover():
4810 return hg.verify(repo)
4810 return hg.verify(repo)
4811 return 1
4811 return 1
4812
4812
4813 @command('^remove|rm',
4813 @command('^remove|rm',
4814 [('A', 'after', None, _('record delete for missing files')),
4814 [('A', 'after', None, _('record delete for missing files')),
4815 ('f', 'force', None,
4815 ('f', 'force', None,
4816 _('remove (and delete) file even if added or modified')),
4816 _('remove (and delete) file even if added or modified')),
4817 ] + walkopts,
4817 ] + walkopts,
4818 _('[OPTION]... FILE...'),
4818 _('[OPTION]... FILE...'),
4819 inferrepo=True)
4819 inferrepo=True)
4820 def remove(ui, repo, *pats, **opts):
4820 def remove(ui, repo, *pats, **opts):
4821 """remove the specified files on the next commit
4821 """remove the specified files on the next commit
4822
4822
4823 Schedule the indicated files for removal from the current branch.
4823 Schedule the indicated files for removal from the current branch.
4824
4824
4825 This command schedules the files to be removed at the next commit.
4825 This command schedules the files to be removed at the next commit.
4826 To undo a remove before that, see :hg:`revert`. To undo added
4826 To undo a remove before that, see :hg:`revert`. To undo added
4827 files, see :hg:`forget`.
4827 files, see :hg:`forget`.
4828
4828
4829 .. container:: verbose
4829 .. container:: verbose
4830
4830
4831 -A/--after can be used to remove only files that have already
4831 -A/--after can be used to remove only files that have already
4832 been deleted, -f/--force can be used to force deletion, and -Af
4832 been deleted, -f/--force can be used to force deletion, and -Af
4833 can be used to remove files from the next revision without
4833 can be used to remove files from the next revision without
4834 deleting them from the working directory.
4834 deleting them from the working directory.
4835
4835
4836 The following table details the behavior of remove for different
4836 The following table details the behavior of remove for different
4837 file states (columns) and option combinations (rows). The file
4837 file states (columns) and option combinations (rows). The file
4838 states are Added [A], Clean [C], Modified [M] and Missing [!]
4838 states are Added [A], Clean [C], Modified [M] and Missing [!]
4839 (as reported by :hg:`status`). The actions are Warn, Remove
4839 (as reported by :hg:`status`). The actions are Warn, Remove
4840 (from branch) and Delete (from disk):
4840 (from branch) and Delete (from disk):
4841
4841
4842 ========= == == == ==
4842 ========= == == == ==
4843 opt/state A C M !
4843 opt/state A C M !
4844 ========= == == == ==
4844 ========= == == == ==
4845 none W RD W R
4845 none W RD W R
4846 -f R RD RD R
4846 -f R RD RD R
4847 -A W W W R
4847 -A W W W R
4848 -Af R R R R
4848 -Af R R R R
4849 ========= == == == ==
4849 ========= == == == ==
4850
4850
4851 Note that remove never deletes files in Added [A] state from the
4851 Note that remove never deletes files in Added [A] state from the
4852 working directory, not even if option --force is specified.
4852 working directory, not even if option --force is specified.
4853
4853
4854 Returns 0 on success, 1 if any warnings encountered.
4854 Returns 0 on success, 1 if any warnings encountered.
4855 """
4855 """
4856
4856
4857 ret = 0
4857 ret = 0
4858 after, force = opts.get('after'), opts.get('force')
4858 after, force = opts.get('after'), opts.get('force')
4859 if not pats and not after:
4859 if not pats and not after:
4860 raise util.Abort(_('no files specified'))
4860 raise util.Abort(_('no files specified'))
4861
4861
4862 m = scmutil.match(repo[None], pats, opts)
4862 m = scmutil.match(repo[None], pats, opts)
4863 s = repo.status(match=m, clean=True)
4863 s = repo.status(match=m, clean=True)
4864 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4864 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4865
4865
4866 # warn about failure to delete explicit files/dirs
4866 # warn about failure to delete explicit files/dirs
4867 wctx = repo[None]
4867 wctx = repo[None]
4868 for f in m.files():
4868 for f in m.files():
4869 if f in repo.dirstate or f in wctx.dirs():
4869 if f in repo.dirstate or f in wctx.dirs():
4870 continue
4870 continue
4871 if os.path.exists(m.rel(f)):
4871 if os.path.exists(m.rel(f)):
4872 if os.path.isdir(m.rel(f)):
4872 if os.path.isdir(m.rel(f)):
4873 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4873 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4874 else:
4874 else:
4875 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4875 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4876 # missing files will generate a warning elsewhere
4876 # missing files will generate a warning elsewhere
4877 ret = 1
4877 ret = 1
4878
4878
4879 if force:
4879 if force:
4880 list = modified + deleted + clean + added
4880 list = modified + deleted + clean + added
4881 elif after:
4881 elif after:
4882 list = deleted
4882 list = deleted
4883 for f in modified + added + clean:
4883 for f in modified + added + clean:
4884 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4884 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4885 ret = 1
4885 ret = 1
4886 else:
4886 else:
4887 list = deleted + clean
4887 list = deleted + clean
4888 for f in modified:
4888 for f in modified:
4889 ui.warn(_('not removing %s: file is modified (use -f'
4889 ui.warn(_('not removing %s: file is modified (use -f'
4890 ' to force removal)\n') % m.rel(f))
4890 ' to force removal)\n') % m.rel(f))
4891 ret = 1
4891 ret = 1
4892 for f in added:
4892 for f in added:
4893 ui.warn(_('not removing %s: file has been marked for add'
4893 ui.warn(_('not removing %s: file has been marked for add'
4894 ' (use forget to undo)\n') % m.rel(f))
4894 ' (use forget to undo)\n') % m.rel(f))
4895 ret = 1
4895 ret = 1
4896
4896
4897 for f in sorted(list):
4897 for f in sorted(list):
4898 if ui.verbose or not m.exact(f):
4898 if ui.verbose or not m.exact(f):
4899 ui.status(_('removing %s\n') % m.rel(f))
4899 ui.status(_('removing %s\n') % m.rel(f))
4900
4900
4901 wlock = repo.wlock()
4901 wlock = repo.wlock()
4902 try:
4902 try:
4903 if not after:
4903 if not after:
4904 for f in list:
4904 for f in list:
4905 if f in added:
4905 if f in added:
4906 continue # we never unlink added files on remove
4906 continue # we never unlink added files on remove
4907 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4907 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4908 repo[None].forget(list)
4908 repo[None].forget(list)
4909 finally:
4909 finally:
4910 wlock.release()
4910 wlock.release()
4911
4911
4912 return ret
4912 return ret
4913
4913
4914 @command('rename|move|mv',
4914 @command('rename|move|mv',
4915 [('A', 'after', None, _('record a rename that has already occurred')),
4915 [('A', 'after', None, _('record a rename that has already occurred')),
4916 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4916 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4917 ] + walkopts + dryrunopts,
4917 ] + walkopts + dryrunopts,
4918 _('[OPTION]... SOURCE... DEST'))
4918 _('[OPTION]... SOURCE... DEST'))
4919 def rename(ui, repo, *pats, **opts):
4919 def rename(ui, repo, *pats, **opts):
4920 """rename files; equivalent of copy + remove
4920 """rename files; equivalent of copy + remove
4921
4921
4922 Mark dest as copies of sources; mark sources for deletion. If dest
4922 Mark dest as copies of sources; mark sources for deletion. If dest
4923 is a directory, copies are put in that directory. If dest is a
4923 is a directory, copies are put in that directory. If dest is a
4924 file, there can only be one source.
4924 file, there can only be one source.
4925
4925
4926 By default, this command copies the contents of files as they
4926 By default, this command copies the contents of files as they
4927 exist in the working directory. If invoked with -A/--after, the
4927 exist in the working directory. If invoked with -A/--after, the
4928 operation is recorded, but no copying is performed.
4928 operation is recorded, but no copying is performed.
4929
4929
4930 This command takes effect at the next commit. To undo a rename
4930 This command takes effect at the next commit. To undo a rename
4931 before that, see :hg:`revert`.
4931 before that, see :hg:`revert`.
4932
4932
4933 Returns 0 on success, 1 if errors are encountered.
4933 Returns 0 on success, 1 if errors are encountered.
4934 """
4934 """
4935 wlock = repo.wlock(False)
4935 wlock = repo.wlock(False)
4936 try:
4936 try:
4937 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4937 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4938 finally:
4938 finally:
4939 wlock.release()
4939 wlock.release()
4940
4940
4941 @command('resolve',
4941 @command('resolve',
4942 [('a', 'all', None, _('select all unresolved files')),
4942 [('a', 'all', None, _('select all unresolved files')),
4943 ('l', 'list', None, _('list state of files needing merge')),
4943 ('l', 'list', None, _('list state of files needing merge')),
4944 ('m', 'mark', None, _('mark files as resolved')),
4944 ('m', 'mark', None, _('mark files as resolved')),
4945 ('u', 'unmark', None, _('mark files as unresolved')),
4945 ('u', 'unmark', None, _('mark files as unresolved')),
4946 ('n', 'no-status', None, _('hide status prefix'))]
4946 ('n', 'no-status', None, _('hide status prefix'))]
4947 + mergetoolopts + walkopts,
4947 + mergetoolopts + walkopts,
4948 _('[OPTION]... [FILE]...'),
4948 _('[OPTION]... [FILE]...'),
4949 inferrepo=True)
4949 inferrepo=True)
4950 def resolve(ui, repo, *pats, **opts):
4950 def resolve(ui, repo, *pats, **opts):
4951 """redo merges or set/view the merge status of files
4951 """redo merges or set/view the merge status of files
4952
4952
4953 Merges with unresolved conflicts are often the result of
4953 Merges with unresolved conflicts are often the result of
4954 non-interactive merging using the ``internal:merge`` configuration
4954 non-interactive merging using the ``internal:merge`` configuration
4955 setting, or a command-line merge tool like ``diff3``. The resolve
4955 setting, or a command-line merge tool like ``diff3``. The resolve
4956 command is used to manage the files involved in a merge, after
4956 command is used to manage the files involved in a merge, after
4957 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4957 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4958 working directory must have two parents). See :hg:`help
4958 working directory must have two parents). See :hg:`help
4959 merge-tools` for information on configuring merge tools.
4959 merge-tools` for information on configuring merge tools.
4960
4960
4961 The resolve command can be used in the following ways:
4961 The resolve command can be used in the following ways:
4962
4962
4963 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4963 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4964 files, discarding any previous merge attempts. Re-merging is not
4964 files, discarding any previous merge attempts. Re-merging is not
4965 performed for files already marked as resolved. Use ``--all/-a``
4965 performed for files already marked as resolved. Use ``--all/-a``
4966 to select all unresolved files. ``--tool`` can be used to specify
4966 to select all unresolved files. ``--tool`` can be used to specify
4967 the merge tool used for the given files. It overrides the HGMERGE
4967 the merge tool used for the given files. It overrides the HGMERGE
4968 environment variable and your configuration files. Previous file
4968 environment variable and your configuration files. Previous file
4969 contents are saved with a ``.orig`` suffix.
4969 contents are saved with a ``.orig`` suffix.
4970
4970
4971 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4971 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4972 (e.g. after having manually fixed-up the files). The default is
4972 (e.g. after having manually fixed-up the files). The default is
4973 to mark all unresolved files.
4973 to mark all unresolved files.
4974
4974
4975 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4975 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4976 default is to mark all resolved files.
4976 default is to mark all resolved files.
4977
4977
4978 - :hg:`resolve -l`: list files which had or still have conflicts.
4978 - :hg:`resolve -l`: list files which had or still have conflicts.
4979 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4979 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4980
4980
4981 Note that Mercurial will not let you commit files with unresolved
4981 Note that Mercurial will not let you commit files with unresolved
4982 merge conflicts. You must use :hg:`resolve -m ...` before you can
4982 merge conflicts. You must use :hg:`resolve -m ...` before you can
4983 commit after a conflicting merge.
4983 commit after a conflicting merge.
4984
4984
4985 Returns 0 on success, 1 if any files fail a resolve attempt.
4985 Returns 0 on success, 1 if any files fail a resolve attempt.
4986 """
4986 """
4987
4987
4988 all, mark, unmark, show, nostatus = \
4988 all, mark, unmark, show, nostatus = \
4989 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4989 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4990
4990
4991 if (show and (mark or unmark)) or (mark and unmark):
4991 if (show and (mark or unmark)) or (mark and unmark):
4992 raise util.Abort(_("too many options specified"))
4992 raise util.Abort(_("too many options specified"))
4993 if pats and all:
4993 if pats and all:
4994 raise util.Abort(_("can't specify --all and patterns"))
4994 raise util.Abort(_("can't specify --all and patterns"))
4995 if not (all or pats or show or mark or unmark):
4995 if not (all or pats or show or mark or unmark):
4996 raise util.Abort(_('no files or directories specified; '
4996 raise util.Abort(_('no files or directories specified; '
4997 'use --all to remerge all files'))
4997 'use --all to remerge all files'))
4998
4998
4999 wlock = repo.wlock()
4999 wlock = repo.wlock()
5000 try:
5000 try:
5001 ms = mergemod.mergestate(repo)
5001 ms = mergemod.mergestate(repo)
5002
5002
5003 if not ms.active() and not show:
5003 if not ms.active() and not show:
5004 raise util.Abort(
5004 raise util.Abort(
5005 _('resolve command not applicable when not merging'))
5005 _('resolve command not applicable when not merging'))
5006
5006
5007 m = scmutil.match(repo[None], pats, opts)
5007 m = scmutil.match(repo[None], pats, opts)
5008 ret = 0
5008 ret = 0
5009 didwork = False
5009 didwork = False
5010
5010
5011 for f in ms:
5011 for f in ms:
5012 if not m(f):
5012 if not m(f):
5013 continue
5013 continue
5014
5014
5015 didwork = True
5015 didwork = True
5016
5016
5017 if show:
5017 if show:
5018 if nostatus:
5018 if nostatus:
5019 ui.write("%s\n" % f)
5019 ui.write("%s\n" % f)
5020 else:
5020 else:
5021 ui.write("%s %s\n" % (ms[f].upper(), f),
5021 ui.write("%s %s\n" % (ms[f].upper(), f),
5022 label='resolve.' +
5022 label='resolve.' +
5023 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5023 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5024 elif mark:
5024 elif mark:
5025 ms.mark(f, "r")
5025 ms.mark(f, "r")
5026 elif unmark:
5026 elif unmark:
5027 ms.mark(f, "u")
5027 ms.mark(f, "u")
5028 else:
5028 else:
5029 wctx = repo[None]
5029 wctx = repo[None]
5030
5030
5031 # backup pre-resolve (merge uses .orig for its own purposes)
5031 # backup pre-resolve (merge uses .orig for its own purposes)
5032 a = repo.wjoin(f)
5032 a = repo.wjoin(f)
5033 util.copyfile(a, a + ".resolve")
5033 util.copyfile(a, a + ".resolve")
5034
5034
5035 try:
5035 try:
5036 # resolve file
5036 # resolve file
5037 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5037 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5038 'resolve')
5038 'resolve')
5039 if ms.resolve(f, wctx):
5039 if ms.resolve(f, wctx):
5040 ret = 1
5040 ret = 1
5041 finally:
5041 finally:
5042 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5042 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5043 ms.commit()
5043 ms.commit()
5044
5044
5045 # replace filemerge's .orig file with our resolve file
5045 # replace filemerge's .orig file with our resolve file
5046 util.rename(a + ".resolve", a + ".orig")
5046 util.rename(a + ".resolve", a + ".orig")
5047
5047
5048 ms.commit()
5048 ms.commit()
5049
5049
5050 if not didwork and pats:
5050 if not didwork and pats:
5051 ui.warn(_("arguments do not match paths that need resolving\n"))
5051 ui.warn(_("arguments do not match paths that need resolving\n"))
5052
5052
5053 finally:
5053 finally:
5054 wlock.release()
5054 wlock.release()
5055
5055
5056 # Nudge users into finishing an unfinished operation. We don't print
5056 # Nudge users into finishing an unfinished operation. We don't print
5057 # this with the list/show operation because we want list/show to remain
5057 # this with the list/show operation because we want list/show to remain
5058 # machine readable.
5058 # machine readable.
5059 if not list(ms.unresolved()) and not show:
5059 if not list(ms.unresolved()) and not show:
5060 ui.status(_('no more unresolved files\n'))
5060 ui.status(_('no more unresolved files\n'))
5061
5061
5062 return ret
5062 return ret
5063
5063
5064 @command('revert',
5064 @command('revert',
5065 [('a', 'all', None, _('revert all changes when no arguments given')),
5065 [('a', 'all', None, _('revert all changes when no arguments given')),
5066 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5066 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5067 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5067 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5068 ('C', 'no-backup', None, _('do not save backup copies of files')),
5068 ('C', 'no-backup', None, _('do not save backup copies of files')),
5069 ] + walkopts + dryrunopts,
5069 ] + walkopts + dryrunopts,
5070 _('[OPTION]... [-r REV] [NAME]...'))
5070 _('[OPTION]... [-r REV] [NAME]...'))
5071 def revert(ui, repo, *pats, **opts):
5071 def revert(ui, repo, *pats, **opts):
5072 """restore files to their checkout state
5072 """restore files to their checkout state
5073
5073
5074 .. note::
5074 .. note::
5075
5075
5076 To check out earlier revisions, you should use :hg:`update REV`.
5076 To check out earlier revisions, you should use :hg:`update REV`.
5077 To cancel an uncommitted merge (and lose your changes),
5077 To cancel an uncommitted merge (and lose your changes),
5078 use :hg:`update --clean .`.
5078 use :hg:`update --clean .`.
5079
5079
5080 With no revision specified, revert the specified files or directories
5080 With no revision specified, revert the specified files or directories
5081 to the contents they had in the parent of the working directory.
5081 to the contents they had in the parent of the working directory.
5082 This restores the contents of files to an unmodified
5082 This restores the contents of files to an unmodified
5083 state and unschedules adds, removes, copies, and renames. If the
5083 state and unschedules adds, removes, copies, and renames. If the
5084 working directory has two parents, you must explicitly specify a
5084 working directory has two parents, you must explicitly specify a
5085 revision.
5085 revision.
5086
5086
5087 Using the -r/--rev or -d/--date options, revert the given files or
5087 Using the -r/--rev or -d/--date options, revert the given files or
5088 directories to their states as of a specific revision. Because
5088 directories to their states as of a specific revision. Because
5089 revert does not change the working directory parents, this will
5089 revert does not change the working directory parents, this will
5090 cause these files to appear modified. This can be helpful to "back
5090 cause these files to appear modified. This can be helpful to "back
5091 out" some or all of an earlier change. See :hg:`backout` for a
5091 out" some or all of an earlier change. See :hg:`backout` for a
5092 related method.
5092 related method.
5093
5093
5094 Modified files are saved with a .orig suffix before reverting.
5094 Modified files are saved with a .orig suffix before reverting.
5095 To disable these backups, use --no-backup.
5095 To disable these backups, use --no-backup.
5096
5096
5097 See :hg:`help dates` for a list of formats valid for -d/--date.
5097 See :hg:`help dates` for a list of formats valid for -d/--date.
5098
5098
5099 Returns 0 on success.
5099 Returns 0 on success.
5100 """
5100 """
5101
5101
5102 if opts.get("date"):
5102 if opts.get("date"):
5103 if opts.get("rev"):
5103 if opts.get("rev"):
5104 raise util.Abort(_("you can't specify a revision and a date"))
5104 raise util.Abort(_("you can't specify a revision and a date"))
5105 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5105 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5106
5106
5107 parent, p2 = repo.dirstate.parents()
5107 parent, p2 = repo.dirstate.parents()
5108 if not opts.get('rev') and p2 != nullid:
5108 if not opts.get('rev') and p2 != nullid:
5109 # revert after merge is a trap for new users (issue2915)
5109 # revert after merge is a trap for new users (issue2915)
5110 raise util.Abort(_('uncommitted merge with no revision specified'),
5110 raise util.Abort(_('uncommitted merge with no revision specified'),
5111 hint=_('use "hg update" or see "hg help revert"'))
5111 hint=_('use "hg update" or see "hg help revert"'))
5112
5112
5113 ctx = scmutil.revsingle(repo, opts.get('rev'))
5113 ctx = scmutil.revsingle(repo, opts.get('rev'))
5114
5114
5115 if not pats and not opts.get('all'):
5115 if not pats and not opts.get('all'):
5116 msg = _("no files or directories specified")
5116 msg = _("no files or directories specified")
5117 if p2 != nullid:
5117 if p2 != nullid:
5118 hint = _("uncommitted merge, use --all to discard all changes,"
5118 hint = _("uncommitted merge, use --all to discard all changes,"
5119 " or 'hg update -C .' to abort the merge")
5119 " or 'hg update -C .' to abort the merge")
5120 raise util.Abort(msg, hint=hint)
5120 raise util.Abort(msg, hint=hint)
5121 dirty = util.any(repo.status())
5121 dirty = util.any(repo.status())
5122 node = ctx.node()
5122 node = ctx.node()
5123 if node != parent:
5123 if node != parent:
5124 if dirty:
5124 if dirty:
5125 hint = _("uncommitted changes, use --all to discard all"
5125 hint = _("uncommitted changes, use --all to discard all"
5126 " changes, or 'hg update %s' to update") % ctx.rev()
5126 " changes, or 'hg update %s' to update") % ctx.rev()
5127 else:
5127 else:
5128 hint = _("use --all to revert all files,"
5128 hint = _("use --all to revert all files,"
5129 " or 'hg update %s' to update") % ctx.rev()
5129 " or 'hg update %s' to update") % ctx.rev()
5130 elif dirty:
5130 elif dirty:
5131 hint = _("uncommitted changes, use --all to discard all changes")
5131 hint = _("uncommitted changes, use --all to discard all changes")
5132 else:
5132 else:
5133 hint = _("use --all to revert all files")
5133 hint = _("use --all to revert all files")
5134 raise util.Abort(msg, hint=hint)
5134 raise util.Abort(msg, hint=hint)
5135
5135
5136 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5136 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5137
5137
5138 @command('rollback', dryrunopts +
5138 @command('rollback', dryrunopts +
5139 [('f', 'force', False, _('ignore safety measures'))])
5139 [('f', 'force', False, _('ignore safety measures'))])
5140 def rollback(ui, repo, **opts):
5140 def rollback(ui, repo, **opts):
5141 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5141 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5142
5142
5143 Please use :hg:`commit --amend` instead of rollback to correct
5143 Please use :hg:`commit --amend` instead of rollback to correct
5144 mistakes in the last commit.
5144 mistakes in the last commit.
5145
5145
5146 This command should be used with care. There is only one level of
5146 This command should be used with care. There is only one level of
5147 rollback, and there is no way to undo a rollback. It will also
5147 rollback, and there is no way to undo a rollback. It will also
5148 restore the dirstate at the time of the last transaction, losing
5148 restore the dirstate at the time of the last transaction, losing
5149 any dirstate changes since that time. This command does not alter
5149 any dirstate changes since that time. This command does not alter
5150 the working directory.
5150 the working directory.
5151
5151
5152 Transactions are used to encapsulate the effects of all commands
5152 Transactions are used to encapsulate the effects of all commands
5153 that create new changesets or propagate existing changesets into a
5153 that create new changesets or propagate existing changesets into a
5154 repository.
5154 repository.
5155
5155
5156 .. container:: verbose
5156 .. container:: verbose
5157
5157
5158 For example, the following commands are transactional, and their
5158 For example, the following commands are transactional, and their
5159 effects can be rolled back:
5159 effects can be rolled back:
5160
5160
5161 - commit
5161 - commit
5162 - import
5162 - import
5163 - pull
5163 - pull
5164 - push (with this repository as the destination)
5164 - push (with this repository as the destination)
5165 - unbundle
5165 - unbundle
5166
5166
5167 To avoid permanent data loss, rollback will refuse to rollback a
5167 To avoid permanent data loss, rollback will refuse to rollback a
5168 commit transaction if it isn't checked out. Use --force to
5168 commit transaction if it isn't checked out. Use --force to
5169 override this protection.
5169 override this protection.
5170
5170
5171 This command is not intended for use on public repositories. Once
5171 This command is not intended for use on public repositories. Once
5172 changes are visible for pull by other users, rolling a transaction
5172 changes are visible for pull by other users, rolling a transaction
5173 back locally is ineffective (someone else may already have pulled
5173 back locally is ineffective (someone else may already have pulled
5174 the changes). Furthermore, a race is possible with readers of the
5174 the changes). Furthermore, a race is possible with readers of the
5175 repository; for example an in-progress pull from the repository
5175 repository; for example an in-progress pull from the repository
5176 may fail if a rollback is performed.
5176 may fail if a rollback is performed.
5177
5177
5178 Returns 0 on success, 1 if no rollback data is available.
5178 Returns 0 on success, 1 if no rollback data is available.
5179 """
5179 """
5180 return repo.rollback(dryrun=opts.get('dry_run'),
5180 return repo.rollback(dryrun=opts.get('dry_run'),
5181 force=opts.get('force'))
5181 force=opts.get('force'))
5182
5182
5183 @command('root', [])
5183 @command('root', [])
5184 def root(ui, repo):
5184 def root(ui, repo):
5185 """print the root (top) of the current working directory
5185 """print the root (top) of the current working directory
5186
5186
5187 Print the root directory of the current repository.
5187 Print the root directory of the current repository.
5188
5188
5189 Returns 0 on success.
5189 Returns 0 on success.
5190 """
5190 """
5191 ui.write(repo.root + "\n")
5191 ui.write(repo.root + "\n")
5192
5192
5193 @command('^serve',
5193 @command('^serve',
5194 [('A', 'accesslog', '', _('name of access log file to write to'),
5194 [('A', 'accesslog', '', _('name of access log file to write to'),
5195 _('FILE')),
5195 _('FILE')),
5196 ('d', 'daemon', None, _('run server in background')),
5196 ('d', 'daemon', None, _('run server in background')),
5197 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5197 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5198 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5198 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5199 # use string type, then we can check if something was passed
5199 # use string type, then we can check if something was passed
5200 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5200 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5201 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5201 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5202 _('ADDR')),
5202 _('ADDR')),
5203 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5203 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5204 _('PREFIX')),
5204 _('PREFIX')),
5205 ('n', 'name', '',
5205 ('n', 'name', '',
5206 _('name to show in web pages (default: working directory)'), _('NAME')),
5206 _('name to show in web pages (default: working directory)'), _('NAME')),
5207 ('', 'web-conf', '',
5207 ('', 'web-conf', '',
5208 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5208 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5209 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5209 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5210 _('FILE')),
5210 _('FILE')),
5211 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5211 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5212 ('', 'stdio', None, _('for remote clients')),
5212 ('', 'stdio', None, _('for remote clients')),
5213 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5213 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5214 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5214 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5215 ('', 'style', '', _('template style to use'), _('STYLE')),
5215 ('', 'style', '', _('template style to use'), _('STYLE')),
5216 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5216 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5217 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5217 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5218 _('[OPTION]...'),
5218 _('[OPTION]...'),
5219 optionalrepo=True)
5219 optionalrepo=True)
5220 def serve(ui, repo, **opts):
5220 def serve(ui, repo, **opts):
5221 """start stand-alone webserver
5221 """start stand-alone webserver
5222
5222
5223 Start a local HTTP repository browser and pull server. You can use
5223 Start a local HTTP repository browser and pull server. You can use
5224 this for ad-hoc sharing and browsing of repositories. It is
5224 this for ad-hoc sharing and browsing of repositories. It is
5225 recommended to use a real web server to serve a repository for
5225 recommended to use a real web server to serve a repository for
5226 longer periods of time.
5226 longer periods of time.
5227
5227
5228 Please note that the server does not implement access control.
5228 Please note that the server does not implement access control.
5229 This means that, by default, anybody can read from the server and
5229 This means that, by default, anybody can read from the server and
5230 nobody can write to it by default. Set the ``web.allow_push``
5230 nobody can write to it by default. Set the ``web.allow_push``
5231 option to ``*`` to allow everybody to push to the server. You
5231 option to ``*`` to allow everybody to push to the server. You
5232 should use a real web server if you need to authenticate users.
5232 should use a real web server if you need to authenticate users.
5233
5233
5234 By default, the server logs accesses to stdout and errors to
5234 By default, the server logs accesses to stdout and errors to
5235 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5235 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5236 files.
5236 files.
5237
5237
5238 To have the server choose a free port number to listen on, specify
5238 To have the server choose a free port number to listen on, specify
5239 a port number of 0; in this case, the server will print the port
5239 a port number of 0; in this case, the server will print the port
5240 number it uses.
5240 number it uses.
5241
5241
5242 Returns 0 on success.
5242 Returns 0 on success.
5243 """
5243 """
5244
5244
5245 if opts["stdio"] and opts["cmdserver"]:
5245 if opts["stdio"] and opts["cmdserver"]:
5246 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5246 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5247
5247
5248 if opts["stdio"]:
5248 if opts["stdio"]:
5249 if repo is None:
5249 if repo is None:
5250 raise error.RepoError(_("there is no Mercurial repository here"
5250 raise error.RepoError(_("there is no Mercurial repository here"
5251 " (.hg not found)"))
5251 " (.hg not found)"))
5252 s = sshserver.sshserver(ui, repo)
5252 s = sshserver.sshserver(ui, repo)
5253 s.serve_forever()
5253 s.serve_forever()
5254
5254
5255 if opts["cmdserver"]:
5255 if opts["cmdserver"]:
5256 s = commandserver.server(ui, repo, opts["cmdserver"])
5256 s = commandserver.server(ui, repo, opts["cmdserver"])
5257 return s.serve()
5257 return s.serve()
5258
5258
5259 # this way we can check if something was given in the command-line
5259 # this way we can check if something was given in the command-line
5260 if opts.get('port'):
5260 if opts.get('port'):
5261 opts['port'] = util.getport(opts.get('port'))
5261 opts['port'] = util.getport(opts.get('port'))
5262
5262
5263 baseui = repo and repo.baseui or ui
5263 baseui = repo and repo.baseui or ui
5264 optlist = ("name templates style address port prefix ipv6"
5264 optlist = ("name templates style address port prefix ipv6"
5265 " accesslog errorlog certificate encoding")
5265 " accesslog errorlog certificate encoding")
5266 for o in optlist.split():
5266 for o in optlist.split():
5267 val = opts.get(o, '')
5267 val = opts.get(o, '')
5268 if val in (None, ''): # should check against default options instead
5268 if val in (None, ''): # should check against default options instead
5269 continue
5269 continue
5270 baseui.setconfig("web", o, val, 'serve')
5270 baseui.setconfig("web", o, val, 'serve')
5271 if repo and repo.ui != baseui:
5271 if repo and repo.ui != baseui:
5272 repo.ui.setconfig("web", o, val, 'serve')
5272 repo.ui.setconfig("web", o, val, 'serve')
5273
5273
5274 o = opts.get('web_conf') or opts.get('webdir_conf')
5274 o = opts.get('web_conf') or opts.get('webdir_conf')
5275 if not o:
5275 if not o:
5276 if not repo:
5276 if not repo:
5277 raise error.RepoError(_("there is no Mercurial repository"
5277 raise error.RepoError(_("there is no Mercurial repository"
5278 " here (.hg not found)"))
5278 " here (.hg not found)"))
5279 o = repo
5279 o = repo
5280
5280
5281 app = hgweb.hgweb(o, baseui=baseui)
5281 app = hgweb.hgweb(o, baseui=baseui)
5282 service = httpservice(ui, app, opts)
5282 service = httpservice(ui, app, opts)
5283 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5283 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5284
5284
5285 class httpservice(object):
5285 class httpservice(object):
5286 def __init__(self, ui, app, opts):
5286 def __init__(self, ui, app, opts):
5287 self.ui = ui
5287 self.ui = ui
5288 self.app = app
5288 self.app = app
5289 self.opts = opts
5289 self.opts = opts
5290
5290
5291 def init(self):
5291 def init(self):
5292 util.setsignalhandler()
5292 util.setsignalhandler()
5293 self.httpd = hgweb_server.create_server(self.ui, self.app)
5293 self.httpd = hgweb_server.create_server(self.ui, self.app)
5294
5294
5295 if self.opts['port'] and not self.ui.verbose:
5295 if self.opts['port'] and not self.ui.verbose:
5296 return
5296 return
5297
5297
5298 if self.httpd.prefix:
5298 if self.httpd.prefix:
5299 prefix = self.httpd.prefix.strip('/') + '/'
5299 prefix = self.httpd.prefix.strip('/') + '/'
5300 else:
5300 else:
5301 prefix = ''
5301 prefix = ''
5302
5302
5303 port = ':%d' % self.httpd.port
5303 port = ':%d' % self.httpd.port
5304 if port == ':80':
5304 if port == ':80':
5305 port = ''
5305 port = ''
5306
5306
5307 bindaddr = self.httpd.addr
5307 bindaddr = self.httpd.addr
5308 if bindaddr == '0.0.0.0':
5308 if bindaddr == '0.0.0.0':
5309 bindaddr = '*'
5309 bindaddr = '*'
5310 elif ':' in bindaddr: # IPv6
5310 elif ':' in bindaddr: # IPv6
5311 bindaddr = '[%s]' % bindaddr
5311 bindaddr = '[%s]' % bindaddr
5312
5312
5313 fqaddr = self.httpd.fqaddr
5313 fqaddr = self.httpd.fqaddr
5314 if ':' in fqaddr:
5314 if ':' in fqaddr:
5315 fqaddr = '[%s]' % fqaddr
5315 fqaddr = '[%s]' % fqaddr
5316 if self.opts['port']:
5316 if self.opts['port']:
5317 write = self.ui.status
5317 write = self.ui.status
5318 else:
5318 else:
5319 write = self.ui.write
5319 write = self.ui.write
5320 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5320 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5321 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5321 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5322 self.ui.flush() # avoid buffering of status message
5322 self.ui.flush() # avoid buffering of status message
5323
5323
5324 def run(self):
5324 def run(self):
5325 self.httpd.serve_forever()
5325 self.httpd.serve_forever()
5326
5326
5327
5327
5328 @command('^status|st',
5328 @command('^status|st',
5329 [('A', 'all', None, _('show status of all files')),
5329 [('A', 'all', None, _('show status of all files')),
5330 ('m', 'modified', None, _('show only modified files')),
5330 ('m', 'modified', None, _('show only modified files')),
5331 ('a', 'added', None, _('show only added files')),
5331 ('a', 'added', None, _('show only added files')),
5332 ('r', 'removed', None, _('show only removed files')),
5332 ('r', 'removed', None, _('show only removed files')),
5333 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5333 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5334 ('c', 'clean', None, _('show only files without changes')),
5334 ('c', 'clean', None, _('show only files without changes')),
5335 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5335 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5336 ('i', 'ignored', None, _('show only ignored files')),
5336 ('i', 'ignored', None, _('show only ignored files')),
5337 ('n', 'no-status', None, _('hide status prefix')),
5337 ('n', 'no-status', None, _('hide status prefix')),
5338 ('C', 'copies', None, _('show source of copied files')),
5338 ('C', 'copies', None, _('show source of copied files')),
5339 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5339 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5340 ('', 'rev', [], _('show difference from revision'), _('REV')),
5340 ('', 'rev', [], _('show difference from revision'), _('REV')),
5341 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5341 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5342 ] + walkopts + subrepoopts,
5342 ] + walkopts + subrepoopts,
5343 _('[OPTION]... [FILE]...'),
5343 _('[OPTION]... [FILE]...'),
5344 inferrepo=True)
5344 inferrepo=True)
5345 def status(ui, repo, *pats, **opts):
5345 def status(ui, repo, *pats, **opts):
5346 """show changed files in the working directory
5346 """show changed files in the working directory
5347
5347
5348 Show status of files in the repository. If names are given, only
5348 Show status of files in the repository. If names are given, only
5349 files that match are shown. Files that are clean or ignored or
5349 files that match are shown. Files that are clean or ignored or
5350 the source of a copy/move operation, are not listed unless
5350 the source of a copy/move operation, are not listed unless
5351 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5351 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5352 Unless options described with "show only ..." are given, the
5352 Unless options described with "show only ..." are given, the
5353 options -mardu are used.
5353 options -mardu are used.
5354
5354
5355 Option -q/--quiet hides untracked (unknown and ignored) files
5355 Option -q/--quiet hides untracked (unknown and ignored) files
5356 unless explicitly requested with -u/--unknown or -i/--ignored.
5356 unless explicitly requested with -u/--unknown or -i/--ignored.
5357
5357
5358 .. note::
5358 .. note::
5359
5359
5360 status may appear to disagree with diff if permissions have
5360 status may appear to disagree with diff if permissions have
5361 changed or a merge has occurred. The standard diff format does
5361 changed or a merge has occurred. The standard diff format does
5362 not report permission changes and diff only reports changes
5362 not report permission changes and diff only reports changes
5363 relative to one merge parent.
5363 relative to one merge parent.
5364
5364
5365 If one revision is given, it is used as the base revision.
5365 If one revision is given, it is used as the base revision.
5366 If two revisions are given, the differences between them are
5366 If two revisions are given, the differences between them are
5367 shown. The --change option can also be used as a shortcut to list
5367 shown. The --change option can also be used as a shortcut to list
5368 the changed files of a revision from its first parent.
5368 the changed files of a revision from its first parent.
5369
5369
5370 The codes used to show the status of files are::
5370 The codes used to show the status of files are::
5371
5371
5372 M = modified
5372 M = modified
5373 A = added
5373 A = added
5374 R = removed
5374 R = removed
5375 C = clean
5375 C = clean
5376 ! = missing (deleted by non-hg command, but still tracked)
5376 ! = missing (deleted by non-hg command, but still tracked)
5377 ? = not tracked
5377 ? = not tracked
5378 I = ignored
5378 I = ignored
5379 = origin of the previous file (with --copies)
5379 = origin of the previous file (with --copies)
5380
5380
5381 .. container:: verbose
5381 .. container:: verbose
5382
5382
5383 Examples:
5383 Examples:
5384
5384
5385 - show changes in the working directory relative to a
5385 - show changes in the working directory relative to a
5386 changeset::
5386 changeset::
5387
5387
5388 hg status --rev 9353
5388 hg status --rev 9353
5389
5389
5390 - show all changes including copies in an existing changeset::
5390 - show all changes including copies in an existing changeset::
5391
5391
5392 hg status --copies --change 9353
5392 hg status --copies --change 9353
5393
5393
5394 - get a NUL separated list of added files, suitable for xargs::
5394 - get a NUL separated list of added files, suitable for xargs::
5395
5395
5396 hg status -an0
5396 hg status -an0
5397
5397
5398 Returns 0 on success.
5398 Returns 0 on success.
5399 """
5399 """
5400
5400
5401 revs = opts.get('rev')
5401 revs = opts.get('rev')
5402 change = opts.get('change')
5402 change = opts.get('change')
5403
5403
5404 if revs and change:
5404 if revs and change:
5405 msg = _('cannot specify --rev and --change at the same time')
5405 msg = _('cannot specify --rev and --change at the same time')
5406 raise util.Abort(msg)
5406 raise util.Abort(msg)
5407 elif change:
5407 elif change:
5408 node2 = scmutil.revsingle(repo, change, None).node()
5408 node2 = scmutil.revsingle(repo, change, None).node()
5409 node1 = repo[node2].p1().node()
5409 node1 = repo[node2].p1().node()
5410 else:
5410 else:
5411 node1, node2 = scmutil.revpair(repo, revs)
5411 node1, node2 = scmutil.revpair(repo, revs)
5412
5412
5413 cwd = (pats and repo.getcwd()) or ''
5413 cwd = (pats and repo.getcwd()) or ''
5414 end = opts.get('print0') and '\0' or '\n'
5414 end = opts.get('print0') and '\0' or '\n'
5415 copy = {}
5415 copy = {}
5416 states = 'modified added removed deleted unknown ignored clean'.split()
5416 states = 'modified added removed deleted unknown ignored clean'.split()
5417 show = [k for k in states if opts.get(k)]
5417 show = [k for k in states if opts.get(k)]
5418 if opts.get('all'):
5418 if opts.get('all'):
5419 show += ui.quiet and (states[:4] + ['clean']) or states
5419 show += ui.quiet and (states[:4] + ['clean']) or states
5420 if not show:
5420 if not show:
5421 show = ui.quiet and states[:4] or states[:5]
5421 show = ui.quiet and states[:4] or states[:5]
5422
5422
5423 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5423 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5424 'ignored' in show, 'clean' in show, 'unknown' in show,
5424 'ignored' in show, 'clean' in show, 'unknown' in show,
5425 opts.get('subrepos'))
5425 opts.get('subrepos'))
5426 changestates = zip(states, 'MAR!?IC', stat)
5426 changestates = zip(states, 'MAR!?IC', stat)
5427
5427
5428 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5428 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5429 copy = copies.pathcopies(repo[node1], repo[node2])
5429 copy = copies.pathcopies(repo[node1], repo[node2])
5430
5430
5431 fm = ui.formatter('status', opts)
5431 fm = ui.formatter('status', opts)
5432 fmt = '%s' + end
5432 fmt = '%s' + end
5433 showchar = not opts.get('no_status')
5433 showchar = not opts.get('no_status')
5434
5434
5435 for state, char, files in changestates:
5435 for state, char, files in changestates:
5436 if state in show:
5436 if state in show:
5437 label = 'status.' + state
5437 label = 'status.' + state
5438 for f in files:
5438 for f in files:
5439 fm.startitem()
5439 fm.startitem()
5440 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5440 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5441 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5441 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5442 if f in copy:
5442 if f in copy:
5443 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5443 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5444 label='status.copied')
5444 label='status.copied')
5445 fm.end()
5445 fm.end()
5446
5446
5447 @command('^summary|sum',
5447 @command('^summary|sum',
5448 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5448 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5449 def summary(ui, repo, **opts):
5449 def summary(ui, repo, **opts):
5450 """summarize working directory state
5450 """summarize working directory state
5451
5451
5452 This generates a brief summary of the working directory state,
5452 This generates a brief summary of the working directory state,
5453 including parents, branch, commit status, and available updates.
5453 including parents, branch, commit status, and available updates.
5454
5454
5455 With the --remote option, this will check the default paths for
5455 With the --remote option, this will check the default paths for
5456 incoming and outgoing changes. This can be time-consuming.
5456 incoming and outgoing changes. This can be time-consuming.
5457
5457
5458 Returns 0 on success.
5458 Returns 0 on success.
5459 """
5459 """
5460
5460
5461 ctx = repo[None]
5461 ctx = repo[None]
5462 parents = ctx.parents()
5462 parents = ctx.parents()
5463 pnode = parents[0].node()
5463 pnode = parents[0].node()
5464 marks = []
5464 marks = []
5465
5465
5466 for p in parents:
5466 for p in parents:
5467 # label with log.changeset (instead of log.parent) since this
5467 # label with log.changeset (instead of log.parent) since this
5468 # shows a working directory parent *changeset*:
5468 # shows a working directory parent *changeset*:
5469 # i18n: column positioning for "hg summary"
5469 # i18n: column positioning for "hg summary"
5470 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5470 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5471 label='log.changeset changeset.%s' % p.phasestr())
5471 label='log.changeset changeset.%s' % p.phasestr())
5472 ui.write(' '.join(p.tags()), label='log.tag')
5472 ui.write(' '.join(p.tags()), label='log.tag')
5473 if p.bookmarks():
5473 if p.bookmarks():
5474 marks.extend(p.bookmarks())
5474 marks.extend(p.bookmarks())
5475 if p.rev() == -1:
5475 if p.rev() == -1:
5476 if not len(repo):
5476 if not len(repo):
5477 ui.write(_(' (empty repository)'))
5477 ui.write(_(' (empty repository)'))
5478 else:
5478 else:
5479 ui.write(_(' (no revision checked out)'))
5479 ui.write(_(' (no revision checked out)'))
5480 ui.write('\n')
5480 ui.write('\n')
5481 if p.description():
5481 if p.description():
5482 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5482 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5483 label='log.summary')
5483 label='log.summary')
5484
5484
5485 branch = ctx.branch()
5485 branch = ctx.branch()
5486 bheads = repo.branchheads(branch)
5486 bheads = repo.branchheads(branch)
5487 # i18n: column positioning for "hg summary"
5487 # i18n: column positioning for "hg summary"
5488 m = _('branch: %s\n') % branch
5488 m = _('branch: %s\n') % branch
5489 if branch != 'default':
5489 if branch != 'default':
5490 ui.write(m, label='log.branch')
5490 ui.write(m, label='log.branch')
5491 else:
5491 else:
5492 ui.status(m, label='log.branch')
5492 ui.status(m, label='log.branch')
5493
5493
5494 if marks:
5494 if marks:
5495 current = repo._bookmarkcurrent
5495 current = repo._bookmarkcurrent
5496 # i18n: column positioning for "hg summary"
5496 # i18n: column positioning for "hg summary"
5497 ui.write(_('bookmarks:'), label='log.bookmark')
5497 ui.write(_('bookmarks:'), label='log.bookmark')
5498 if current is not None:
5498 if current is not None:
5499 if current in marks:
5499 if current in marks:
5500 ui.write(' *' + current, label='bookmarks.current')
5500 ui.write(' *' + current, label='bookmarks.current')
5501 marks.remove(current)
5501 marks.remove(current)
5502 else:
5502 else:
5503 ui.write(' [%s]' % current, label='bookmarks.current')
5503 ui.write(' [%s]' % current, label='bookmarks.current')
5504 for m in marks:
5504 for m in marks:
5505 ui.write(' ' + m, label='log.bookmark')
5505 ui.write(' ' + m, label='log.bookmark')
5506 ui.write('\n', label='log.bookmark')
5506 ui.write('\n', label='log.bookmark')
5507
5507
5508 st = list(repo.status(unknown=True))[:6]
5508 st = list(repo.status(unknown=True))[:6]
5509
5509
5510 c = repo.dirstate.copies()
5510 c = repo.dirstate.copies()
5511 copied, renamed = [], []
5511 copied, renamed = [], []
5512 for d, s in c.iteritems():
5512 for d, s in c.iteritems():
5513 if s in st[2]:
5513 if s in st[2]:
5514 st[2].remove(s)
5514 st[2].remove(s)
5515 renamed.append(d)
5515 renamed.append(d)
5516 else:
5516 else:
5517 copied.append(d)
5517 copied.append(d)
5518 if d in st[1]:
5518 if d in st[1]:
5519 st[1].remove(d)
5519 st[1].remove(d)
5520 st.insert(3, renamed)
5520 st.insert(3, renamed)
5521 st.insert(4, copied)
5521 st.insert(4, copied)
5522
5522
5523 ms = mergemod.mergestate(repo)
5523 ms = mergemod.mergestate(repo)
5524 st.append([f for f in ms if ms[f] == 'u'])
5524 st.append([f for f in ms if ms[f] == 'u'])
5525
5525
5526 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5526 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5527 st.append(subs)
5527 st.append(subs)
5528
5528
5529 labels = [ui.label(_('%d modified'), 'status.modified'),
5529 labels = [ui.label(_('%d modified'), 'status.modified'),
5530 ui.label(_('%d added'), 'status.added'),
5530 ui.label(_('%d added'), 'status.added'),
5531 ui.label(_('%d removed'), 'status.removed'),
5531 ui.label(_('%d removed'), 'status.removed'),
5532 ui.label(_('%d renamed'), 'status.copied'),
5532 ui.label(_('%d renamed'), 'status.copied'),
5533 ui.label(_('%d copied'), 'status.copied'),
5533 ui.label(_('%d copied'), 'status.copied'),
5534 ui.label(_('%d deleted'), 'status.deleted'),
5534 ui.label(_('%d deleted'), 'status.deleted'),
5535 ui.label(_('%d unknown'), 'status.unknown'),
5535 ui.label(_('%d unknown'), 'status.unknown'),
5536 ui.label(_('%d ignored'), 'status.ignored'),
5536 ui.label(_('%d ignored'), 'status.ignored'),
5537 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5537 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5538 ui.label(_('%d subrepos'), 'status.modified')]
5538 ui.label(_('%d subrepos'), 'status.modified')]
5539 t = []
5539 t = []
5540 for s, l in zip(st, labels):
5540 for s, l in zip(st, labels):
5541 if s:
5541 if s:
5542 t.append(l % len(s))
5542 t.append(l % len(s))
5543
5543
5544 t = ', '.join(t)
5544 t = ', '.join(t)
5545 cleanworkdir = False
5545 cleanworkdir = False
5546
5546
5547 if repo.vfs.exists('updatestate'):
5547 if repo.vfs.exists('updatestate'):
5548 t += _(' (interrupted update)')
5548 t += _(' (interrupted update)')
5549 elif len(parents) > 1:
5549 elif len(parents) > 1:
5550 t += _(' (merge)')
5550 t += _(' (merge)')
5551 elif branch != parents[0].branch():
5551 elif branch != parents[0].branch():
5552 t += _(' (new branch)')
5552 t += _(' (new branch)')
5553 elif (parents[0].closesbranch() and
5553 elif (parents[0].closesbranch() and
5554 pnode in repo.branchheads(branch, closed=True)):
5554 pnode in repo.branchheads(branch, closed=True)):
5555 t += _(' (head closed)')
5555 t += _(' (head closed)')
5556 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5556 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5557 t += _(' (clean)')
5557 t += _(' (clean)')
5558 cleanworkdir = True
5558 cleanworkdir = True
5559 elif pnode not in bheads:
5559 elif pnode not in bheads:
5560 t += _(' (new branch head)')
5560 t += _(' (new branch head)')
5561
5561
5562 if cleanworkdir:
5562 if cleanworkdir:
5563 # i18n: column positioning for "hg summary"
5563 # i18n: column positioning for "hg summary"
5564 ui.status(_('commit: %s\n') % t.strip())
5564 ui.status(_('commit: %s\n') % t.strip())
5565 else:
5565 else:
5566 # i18n: column positioning for "hg summary"
5566 # i18n: column positioning for "hg summary"
5567 ui.write(_('commit: %s\n') % t.strip())
5567 ui.write(_('commit: %s\n') % t.strip())
5568
5568
5569 # all ancestors of branch heads - all ancestors of parent = new csets
5569 # all ancestors of branch heads - all ancestors of parent = new csets
5570 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5570 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5571 bheads))
5571 bheads))
5572
5572
5573 if new == 0:
5573 if new == 0:
5574 # i18n: column positioning for "hg summary"
5574 # i18n: column positioning for "hg summary"
5575 ui.status(_('update: (current)\n'))
5575 ui.status(_('update: (current)\n'))
5576 elif pnode not in bheads:
5576 elif pnode not in bheads:
5577 # i18n: column positioning for "hg summary"
5577 # i18n: column positioning for "hg summary"
5578 ui.write(_('update: %d new changesets (update)\n') % new)
5578 ui.write(_('update: %d new changesets (update)\n') % new)
5579 else:
5579 else:
5580 # i18n: column positioning for "hg summary"
5580 # i18n: column positioning for "hg summary"
5581 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5581 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5582 (new, len(bheads)))
5582 (new, len(bheads)))
5583
5583
5584 cmdutil.summaryhooks(ui, repo)
5584 cmdutil.summaryhooks(ui, repo)
5585
5585
5586 if opts.get('remote'):
5586 if opts.get('remote'):
5587 needsincoming, needsoutgoing = True, True
5587 needsincoming, needsoutgoing = True, True
5588 else:
5588 else:
5589 needsincoming, needsoutgoing = False, False
5589 needsincoming, needsoutgoing = False, False
5590 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5590 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5591 if i:
5591 if i:
5592 needsincoming = True
5592 needsincoming = True
5593 if o:
5593 if o:
5594 needsoutgoing = True
5594 needsoutgoing = True
5595 if not needsincoming and not needsoutgoing:
5595 if not needsincoming and not needsoutgoing:
5596 return
5596 return
5597
5597
5598 def getincoming():
5598 def getincoming():
5599 source, branches = hg.parseurl(ui.expandpath('default'))
5599 source, branches = hg.parseurl(ui.expandpath('default'))
5600 sbranch = branches[0]
5600 sbranch = branches[0]
5601 try:
5601 try:
5602 other = hg.peer(repo, {}, source)
5602 other = hg.peer(repo, {}, source)
5603 except error.RepoError:
5603 except error.RepoError:
5604 if opts.get('remote'):
5604 if opts.get('remote'):
5605 raise
5605 raise
5606 return source, sbranch, None, None, None
5606 return source, sbranch, None, None, None
5607 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5607 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5608 if revs:
5608 if revs:
5609 revs = [other.lookup(rev) for rev in revs]
5609 revs = [other.lookup(rev) for rev in revs]
5610 ui.debug('comparing with %s\n' % util.hidepassword(source))
5610 ui.debug('comparing with %s\n' % util.hidepassword(source))
5611 repo.ui.pushbuffer()
5611 repo.ui.pushbuffer()
5612 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5612 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5613 repo.ui.popbuffer()
5613 repo.ui.popbuffer()
5614 return source, sbranch, other, commoninc, commoninc[1]
5614 return source, sbranch, other, commoninc, commoninc[1]
5615
5615
5616 if needsincoming:
5616 if needsincoming:
5617 source, sbranch, sother, commoninc, incoming = getincoming()
5617 source, sbranch, sother, commoninc, incoming = getincoming()
5618 else:
5618 else:
5619 source = sbranch = sother = commoninc = incoming = None
5619 source = sbranch = sother = commoninc = incoming = None
5620
5620
5621 def getoutgoing():
5621 def getoutgoing():
5622 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5622 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5623 dbranch = branches[0]
5623 dbranch = branches[0]
5624 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5624 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5625 if source != dest:
5625 if source != dest:
5626 try:
5626 try:
5627 dother = hg.peer(repo, {}, dest)
5627 dother = hg.peer(repo, {}, dest)
5628 except error.RepoError:
5628 except error.RepoError:
5629 if opts.get('remote'):
5629 if opts.get('remote'):
5630 raise
5630 raise
5631 return dest, dbranch, None, None
5631 return dest, dbranch, None, None
5632 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5632 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5633 elif sother is None:
5633 elif sother is None:
5634 # there is no explicit destination peer, but source one is invalid
5634 # there is no explicit destination peer, but source one is invalid
5635 return dest, dbranch, None, None
5635 return dest, dbranch, None, None
5636 else:
5636 else:
5637 dother = sother
5637 dother = sother
5638 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5638 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5639 common = None
5639 common = None
5640 else:
5640 else:
5641 common = commoninc
5641 common = commoninc
5642 if revs:
5642 if revs:
5643 revs = [repo.lookup(rev) for rev in revs]
5643 revs = [repo.lookup(rev) for rev in revs]
5644 repo.ui.pushbuffer()
5644 repo.ui.pushbuffer()
5645 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5645 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5646 commoninc=common)
5646 commoninc=common)
5647 repo.ui.popbuffer()
5647 repo.ui.popbuffer()
5648 return dest, dbranch, dother, outgoing
5648 return dest, dbranch, dother, outgoing
5649
5649
5650 if needsoutgoing:
5650 if needsoutgoing:
5651 dest, dbranch, dother, outgoing = getoutgoing()
5651 dest, dbranch, dother, outgoing = getoutgoing()
5652 else:
5652 else:
5653 dest = dbranch = dother = outgoing = None
5653 dest = dbranch = dother = outgoing = None
5654
5654
5655 if opts.get('remote'):
5655 if opts.get('remote'):
5656 t = []
5656 t = []
5657 if incoming:
5657 if incoming:
5658 t.append(_('1 or more incoming'))
5658 t.append(_('1 or more incoming'))
5659 o = outgoing.missing
5659 o = outgoing.missing
5660 if o:
5660 if o:
5661 t.append(_('%d outgoing') % len(o))
5661 t.append(_('%d outgoing') % len(o))
5662 other = dother or sother
5662 other = dother or sother
5663 if 'bookmarks' in other.listkeys('namespaces'):
5663 if 'bookmarks' in other.listkeys('namespaces'):
5664 lmarks = repo.listkeys('bookmarks')
5664 lmarks = repo.listkeys('bookmarks')
5665 rmarks = other.listkeys('bookmarks')
5665 rmarks = other.listkeys('bookmarks')
5666 diff = set(rmarks) - set(lmarks)
5666 diff = set(rmarks) - set(lmarks)
5667 if len(diff) > 0:
5667 if len(diff) > 0:
5668 t.append(_('%d incoming bookmarks') % len(diff))
5668 t.append(_('%d incoming bookmarks') % len(diff))
5669 diff = set(lmarks) - set(rmarks)
5669 diff = set(lmarks) - set(rmarks)
5670 if len(diff) > 0:
5670 if len(diff) > 0:
5671 t.append(_('%d outgoing bookmarks') % len(diff))
5671 t.append(_('%d outgoing bookmarks') % len(diff))
5672
5672
5673 if t:
5673 if t:
5674 # i18n: column positioning for "hg summary"
5674 # i18n: column positioning for "hg summary"
5675 ui.write(_('remote: %s\n') % (', '.join(t)))
5675 ui.write(_('remote: %s\n') % (', '.join(t)))
5676 else:
5676 else:
5677 # i18n: column positioning for "hg summary"
5677 # i18n: column positioning for "hg summary"
5678 ui.status(_('remote: (synced)\n'))
5678 ui.status(_('remote: (synced)\n'))
5679
5679
5680 cmdutil.summaryremotehooks(ui, repo, opts,
5680 cmdutil.summaryremotehooks(ui, repo, opts,
5681 ((source, sbranch, sother, commoninc),
5681 ((source, sbranch, sother, commoninc),
5682 (dest, dbranch, dother, outgoing)))
5682 (dest, dbranch, dother, outgoing)))
5683
5683
5684 @command('tag',
5684 @command('tag',
5685 [('f', 'force', None, _('force tag')),
5685 [('f', 'force', None, _('force tag')),
5686 ('l', 'local', None, _('make the tag local')),
5686 ('l', 'local', None, _('make the tag local')),
5687 ('r', 'rev', '', _('revision to tag'), _('REV')),
5687 ('r', 'rev', '', _('revision to tag'), _('REV')),
5688 ('', 'remove', None, _('remove a tag')),
5688 ('', 'remove', None, _('remove a tag')),
5689 # -l/--local is already there, commitopts cannot be used
5689 # -l/--local is already there, commitopts cannot be used
5690 ('e', 'edit', None, _('edit commit message')),
5690 ('e', 'edit', None, _('edit commit message')),
5691 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5691 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5692 ] + commitopts2,
5692 ] + commitopts2,
5693 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5693 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5694 def tag(ui, repo, name1, *names, **opts):
5694 def tag(ui, repo, name1, *names, **opts):
5695 """add one or more tags for the current or given revision
5695 """add one or more tags for the current or given revision
5696
5696
5697 Name a particular revision using <name>.
5697 Name a particular revision using <name>.
5698
5698
5699 Tags are used to name particular revisions of the repository and are
5699 Tags are used to name particular revisions of the repository and are
5700 very useful to compare different revisions, to go back to significant
5700 very useful to compare different revisions, to go back to significant
5701 earlier versions or to mark branch points as releases, etc. Changing
5701 earlier versions or to mark branch points as releases, etc. Changing
5702 an existing tag is normally disallowed; use -f/--force to override.
5702 an existing tag is normally disallowed; use -f/--force to override.
5703
5703
5704 If no revision is given, the parent of the working directory is
5704 If no revision is given, the parent of the working directory is
5705 used.
5705 used.
5706
5706
5707 To facilitate version control, distribution, and merging of tags,
5707 To facilitate version control, distribution, and merging of tags,
5708 they are stored as a file named ".hgtags" which is managed similarly
5708 they are stored as a file named ".hgtags" which is managed similarly
5709 to other project files and can be hand-edited if necessary. This
5709 to other project files and can be hand-edited if necessary. This
5710 also means that tagging creates a new commit. The file
5710 also means that tagging creates a new commit. The file
5711 ".hg/localtags" is used for local tags (not shared among
5711 ".hg/localtags" is used for local tags (not shared among
5712 repositories).
5712 repositories).
5713
5713
5714 Tag commits are usually made at the head of a branch. If the parent
5714 Tag commits are usually made at the head of a branch. If the parent
5715 of the working directory is not a branch head, :hg:`tag` aborts; use
5715 of the working directory is not a branch head, :hg:`tag` aborts; use
5716 -f/--force to force the tag commit to be based on a non-head
5716 -f/--force to force the tag commit to be based on a non-head
5717 changeset.
5717 changeset.
5718
5718
5719 See :hg:`help dates` for a list of formats valid for -d/--date.
5719 See :hg:`help dates` for a list of formats valid for -d/--date.
5720
5720
5721 Since tag names have priority over branch names during revision
5721 Since tag names have priority over branch names during revision
5722 lookup, using an existing branch name as a tag name is discouraged.
5722 lookup, using an existing branch name as a tag name is discouraged.
5723
5723
5724 Returns 0 on success.
5724 Returns 0 on success.
5725 """
5725 """
5726 wlock = lock = None
5726 wlock = lock = None
5727 try:
5727 try:
5728 wlock = repo.wlock()
5728 wlock = repo.wlock()
5729 lock = repo.lock()
5729 lock = repo.lock()
5730 rev_ = "."
5730 rev_ = "."
5731 names = [t.strip() for t in (name1,) + names]
5731 names = [t.strip() for t in (name1,) + names]
5732 if len(names) != len(set(names)):
5732 if len(names) != len(set(names)):
5733 raise util.Abort(_('tag names must be unique'))
5733 raise util.Abort(_('tag names must be unique'))
5734 for n in names:
5734 for n in names:
5735 scmutil.checknewlabel(repo, n, 'tag')
5735 scmutil.checknewlabel(repo, n, 'tag')
5736 if not n:
5736 if not n:
5737 raise util.Abort(_('tag names cannot consist entirely of '
5737 raise util.Abort(_('tag names cannot consist entirely of '
5738 'whitespace'))
5738 'whitespace'))
5739 if opts.get('rev') and opts.get('remove'):
5739 if opts.get('rev') and opts.get('remove'):
5740 raise util.Abort(_("--rev and --remove are incompatible"))
5740 raise util.Abort(_("--rev and --remove are incompatible"))
5741 if opts.get('rev'):
5741 if opts.get('rev'):
5742 rev_ = opts['rev']
5742 rev_ = opts['rev']
5743 message = opts.get('message')
5743 message = opts.get('message')
5744 if opts.get('remove'):
5744 if opts.get('remove'):
5745 expectedtype = opts.get('local') and 'local' or 'global'
5745 expectedtype = opts.get('local') and 'local' or 'global'
5746 for n in names:
5746 for n in names:
5747 if not repo.tagtype(n):
5747 if not repo.tagtype(n):
5748 raise util.Abort(_("tag '%s' does not exist") % n)
5748 raise util.Abort(_("tag '%s' does not exist") % n)
5749 if repo.tagtype(n) != expectedtype:
5749 if repo.tagtype(n) != expectedtype:
5750 if expectedtype == 'global':
5750 if expectedtype == 'global':
5751 raise util.Abort(_("tag '%s' is not a global tag") % n)
5751 raise util.Abort(_("tag '%s' is not a global tag") % n)
5752 else:
5752 else:
5753 raise util.Abort(_("tag '%s' is not a local tag") % n)
5753 raise util.Abort(_("tag '%s' is not a local tag") % n)
5754 rev_ = nullid
5754 rev_ = nullid
5755 if not message:
5755 if not message:
5756 # we don't translate commit messages
5756 # we don't translate commit messages
5757 message = 'Removed tag %s' % ', '.join(names)
5757 message = 'Removed tag %s' % ', '.join(names)
5758 elif not opts.get('force'):
5758 elif not opts.get('force'):
5759 for n in names:
5759 for n in names:
5760 if n in repo.tags():
5760 if n in repo.tags():
5761 raise util.Abort(_("tag '%s' already exists "
5761 raise util.Abort(_("tag '%s' already exists "
5762 "(use -f to force)") % n)
5762 "(use -f to force)") % n)
5763 if not opts.get('local'):
5763 if not opts.get('local'):
5764 p1, p2 = repo.dirstate.parents()
5764 p1, p2 = repo.dirstate.parents()
5765 if p2 != nullid:
5765 if p2 != nullid:
5766 raise util.Abort(_('uncommitted merge'))
5766 raise util.Abort(_('uncommitted merge'))
5767 bheads = repo.branchheads()
5767 bheads = repo.branchheads()
5768 if not opts.get('force') and bheads and p1 not in bheads:
5768 if not opts.get('force') and bheads and p1 not in bheads:
5769 raise util.Abort(_('not at a branch head (use -f to force)'))
5769 raise util.Abort(_('not at a branch head (use -f to force)'))
5770 r = scmutil.revsingle(repo, rev_).node()
5770 r = scmutil.revsingle(repo, rev_).node()
5771
5771
5772 if not message:
5772 if not message:
5773 # we don't translate commit messages
5773 # we don't translate commit messages
5774 message = ('Added tag %s for changeset %s' %
5774 message = ('Added tag %s for changeset %s' %
5775 (', '.join(names), short(r)))
5775 (', '.join(names), short(r)))
5776
5776
5777 date = opts.get('date')
5777 date = opts.get('date')
5778 if date:
5778 if date:
5779 date = util.parsedate(date)
5779 date = util.parsedate(date)
5780
5780
5781 editor = cmdutil.getcommiteditor(**opts)
5781 editor = cmdutil.getcommiteditor(**opts)
5782
5782
5783 # don't allow tagging the null rev
5783 # don't allow tagging the null rev
5784 if (not opts.get('remove') and
5784 if (not opts.get('remove') and
5785 scmutil.revsingle(repo, rev_).rev() == nullrev):
5785 scmutil.revsingle(repo, rev_).rev() == nullrev):
5786 raise util.Abort(_("cannot tag null revision"))
5786 raise util.Abort(_("cannot tag null revision"))
5787
5787
5788 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5788 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5789 editor=editor)
5789 editor=editor)
5790 finally:
5790 finally:
5791 release(lock, wlock)
5791 release(lock, wlock)
5792
5792
5793 @command('tags', [], '')
5793 @command('tags', [], '')
5794 def tags(ui, repo, **opts):
5794 def tags(ui, repo, **opts):
5795 """list repository tags
5795 """list repository tags
5796
5796
5797 This lists both regular and local tags. When the -v/--verbose
5797 This lists both regular and local tags. When the -v/--verbose
5798 switch is used, a third column "local" is printed for local tags.
5798 switch is used, a third column "local" is printed for local tags.
5799
5799
5800 Returns 0 on success.
5800 Returns 0 on success.
5801 """
5801 """
5802
5802
5803 fm = ui.formatter('tags', opts)
5803 fm = ui.formatter('tags', opts)
5804 hexfunc = ui.debugflag and hex or short
5804 hexfunc = ui.debugflag and hex or short
5805 tagtype = ""
5805 tagtype = ""
5806
5806
5807 for t, n in reversed(repo.tagslist()):
5807 for t, n in reversed(repo.tagslist()):
5808 hn = hexfunc(n)
5808 hn = hexfunc(n)
5809 label = 'tags.normal'
5809 label = 'tags.normal'
5810 tagtype = ''
5810 tagtype = ''
5811 if repo.tagtype(t) == 'local':
5811 if repo.tagtype(t) == 'local':
5812 label = 'tags.local'
5812 label = 'tags.local'
5813 tagtype = 'local'
5813 tagtype = 'local'
5814
5814
5815 fm.startitem()
5815 fm.startitem()
5816 fm.write('tag', '%s', t, label=label)
5816 fm.write('tag', '%s', t, label=label)
5817 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5817 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5818 fm.condwrite(not ui.quiet, 'rev id', fmt,
5818 fm.condwrite(not ui.quiet, 'rev id', fmt,
5819 repo.changelog.rev(n), hn, label=label)
5819 repo.changelog.rev(n), hn, label=label)
5820 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5820 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5821 tagtype, label=label)
5821 tagtype, label=label)
5822 fm.plain('\n')
5822 fm.plain('\n')
5823 fm.end()
5823 fm.end()
5824
5824
5825 @command('tip',
5825 @command('tip',
5826 [('p', 'patch', None, _('show patch')),
5826 [('p', 'patch', None, _('show patch')),
5827 ('g', 'git', None, _('use git extended diff format')),
5827 ('g', 'git', None, _('use git extended diff format')),
5828 ] + templateopts,
5828 ] + templateopts,
5829 _('[-p] [-g]'))
5829 _('[-p] [-g]'))
5830 def tip(ui, repo, **opts):
5830 def tip(ui, repo, **opts):
5831 """show the tip revision (DEPRECATED)
5831 """show the tip revision (DEPRECATED)
5832
5832
5833 The tip revision (usually just called the tip) is the changeset
5833 The tip revision (usually just called the tip) is the changeset
5834 most recently added to the repository (and therefore the most
5834 most recently added to the repository (and therefore the most
5835 recently changed head).
5835 recently changed head).
5836
5836
5837 If you have just made a commit, that commit will be the tip. If
5837 If you have just made a commit, that commit will be the tip. If
5838 you have just pulled changes from another repository, the tip of
5838 you have just pulled changes from another repository, the tip of
5839 that repository becomes the current tip. The "tip" tag is special
5839 that repository becomes the current tip. The "tip" tag is special
5840 and cannot be renamed or assigned to a different changeset.
5840 and cannot be renamed or assigned to a different changeset.
5841
5841
5842 This command is deprecated, please use :hg:`heads` instead.
5842 This command is deprecated, please use :hg:`heads` instead.
5843
5843
5844 Returns 0 on success.
5844 Returns 0 on success.
5845 """
5845 """
5846 displayer = cmdutil.show_changeset(ui, repo, opts)
5846 displayer = cmdutil.show_changeset(ui, repo, opts)
5847 displayer.show(repo['tip'])
5847 displayer.show(repo['tip'])
5848 displayer.close()
5848 displayer.close()
5849
5849
5850 @command('unbundle',
5850 @command('unbundle',
5851 [('u', 'update', None,
5851 [('u', 'update', None,
5852 _('update to new branch head if changesets were unbundled'))],
5852 _('update to new branch head if changesets were unbundled'))],
5853 _('[-u] FILE...'))
5853 _('[-u] FILE...'))
5854 def unbundle(ui, repo, fname1, *fnames, **opts):
5854 def unbundle(ui, repo, fname1, *fnames, **opts):
5855 """apply one or more changegroup files
5855 """apply one or more changegroup files
5856
5856
5857 Apply one or more compressed changegroup files generated by the
5857 Apply one or more compressed changegroup files generated by the
5858 bundle command.
5858 bundle command.
5859
5859
5860 Returns 0 on success, 1 if an update has unresolved files.
5860 Returns 0 on success, 1 if an update has unresolved files.
5861 """
5861 """
5862 fnames = (fname1,) + fnames
5862 fnames = (fname1,) + fnames
5863
5863
5864 lock = repo.lock()
5864 lock = repo.lock()
5865 wc = repo['.']
5865 wc = repo['.']
5866 try:
5866 try:
5867 for fname in fnames:
5867 for fname in fnames:
5868 f = hg.openpath(ui, fname)
5868 f = hg.openpath(ui, fname)
5869 gen = exchange.readbundle(ui, f, fname)
5869 gen = exchange.readbundle(ui, f, fname)
5870 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5870 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5871 'bundle:' + fname)
5871 'bundle:' + fname)
5872 finally:
5872 finally:
5873 lock.release()
5873 lock.release()
5874 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5874 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5875 return postincoming(ui, repo, modheads, opts.get('update'), None)
5875 return postincoming(ui, repo, modheads, opts.get('update'), None)
5876
5876
5877 @command('^update|up|checkout|co',
5877 @command('^update|up|checkout|co',
5878 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5878 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5879 ('c', 'check', None,
5879 ('c', 'check', None,
5880 _('update across branches if no uncommitted changes')),
5880 _('update across branches if no uncommitted changes')),
5881 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5881 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5882 ('r', 'rev', '', _('revision'), _('REV'))
5882 ('r', 'rev', '', _('revision'), _('REV'))
5883 ] + mergetoolopts,
5883 ] + mergetoolopts,
5884 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5884 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5885 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5885 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5886 tool=None):
5886 tool=None):
5887 """update working directory (or switch revisions)
5887 """update working directory (or switch revisions)
5888
5888
5889 Update the repository's working directory to the specified
5889 Update the repository's working directory to the specified
5890 changeset. If no changeset is specified, update to the tip of the
5890 changeset. If no changeset is specified, update to the tip of the
5891 current named branch and move the current bookmark (see :hg:`help
5891 current named branch and move the current bookmark (see :hg:`help
5892 bookmarks`).
5892 bookmarks`).
5893
5893
5894 Update sets the working directory's parent revision to the specified
5894 Update sets the working directory's parent revision to the specified
5895 changeset (see :hg:`help parents`).
5895 changeset (see :hg:`help parents`).
5896
5896
5897 If the changeset is not a descendant or ancestor of the working
5897 If the changeset is not a descendant or ancestor of the working
5898 directory's parent, the update is aborted. With the -c/--check
5898 directory's parent, the update is aborted. With the -c/--check
5899 option, the working directory is checked for uncommitted changes; if
5899 option, the working directory is checked for uncommitted changes; if
5900 none are found, the working directory is updated to the specified
5900 none are found, the working directory is updated to the specified
5901 changeset.
5901 changeset.
5902
5902
5903 .. container:: verbose
5903 .. container:: verbose
5904
5904
5905 The following rules apply when the working directory contains
5905 The following rules apply when the working directory contains
5906 uncommitted changes:
5906 uncommitted changes:
5907
5907
5908 1. If neither -c/--check nor -C/--clean is specified, and if
5908 1. If neither -c/--check nor -C/--clean is specified, and if
5909 the requested changeset is an ancestor or descendant of
5909 the requested changeset is an ancestor or descendant of
5910 the working directory's parent, the uncommitted changes
5910 the working directory's parent, the uncommitted changes
5911 are merged into the requested changeset and the merged
5911 are merged into the requested changeset and the merged
5912 result is left uncommitted. If the requested changeset is
5912 result is left uncommitted. If the requested changeset is
5913 not an ancestor or descendant (that is, it is on another
5913 not an ancestor or descendant (that is, it is on another
5914 branch), the update is aborted and the uncommitted changes
5914 branch), the update is aborted and the uncommitted changes
5915 are preserved.
5915 are preserved.
5916
5916
5917 2. With the -c/--check option, the update is aborted and the
5917 2. With the -c/--check option, the update is aborted and the
5918 uncommitted changes are preserved.
5918 uncommitted changes are preserved.
5919
5919
5920 3. With the -C/--clean option, uncommitted changes are discarded and
5920 3. With the -C/--clean option, uncommitted changes are discarded and
5921 the working directory is updated to the requested changeset.
5921 the working directory is updated to the requested changeset.
5922
5922
5923 To cancel an uncommitted merge (and lose your changes), use
5923 To cancel an uncommitted merge (and lose your changes), use
5924 :hg:`update --clean .`.
5924 :hg:`update --clean .`.
5925
5925
5926 Use null as the changeset to remove the working directory (like
5926 Use null as the changeset to remove the working directory (like
5927 :hg:`clone -U`).
5927 :hg:`clone -U`).
5928
5928
5929 If you want to revert just one file to an older revision, use
5929 If you want to revert just one file to an older revision, use
5930 :hg:`revert [-r REV] NAME`.
5930 :hg:`revert [-r REV] NAME`.
5931
5931
5932 See :hg:`help dates` for a list of formats valid for -d/--date.
5932 See :hg:`help dates` for a list of formats valid for -d/--date.
5933
5933
5934 Returns 0 on success, 1 if there are unresolved files.
5934 Returns 0 on success, 1 if there are unresolved files.
5935 """
5935 """
5936 if rev and node:
5936 if rev and node:
5937 raise util.Abort(_("please specify just one revision"))
5937 raise util.Abort(_("please specify just one revision"))
5938
5938
5939 if rev is None or rev == '':
5939 if rev is None or rev == '':
5940 rev = node
5940 rev = node
5941
5941
5942 cmdutil.clearunfinished(repo)
5942 cmdutil.clearunfinished(repo)
5943
5943
5944 # with no argument, we also move the current bookmark, if any
5944 # with no argument, we also move the current bookmark, if any
5945 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5945 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5946
5946
5947 # if we defined a bookmark, we have to remember the original bookmark name
5947 # if we defined a bookmark, we have to remember the original bookmark name
5948 brev = rev
5948 brev = rev
5949 rev = scmutil.revsingle(repo, rev, rev).rev()
5949 rev = scmutil.revsingle(repo, rev, rev).rev()
5950
5950
5951 if check and clean:
5951 if check and clean:
5952 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5952 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5953
5953
5954 if date:
5954 if date:
5955 if rev is not None:
5955 if rev is not None:
5956 raise util.Abort(_("you can't specify a revision and a date"))
5956 raise util.Abort(_("you can't specify a revision and a date"))
5957 rev = cmdutil.finddate(ui, repo, date)
5957 rev = cmdutil.finddate(ui, repo, date)
5958
5958
5959 if check:
5959 if check:
5960 c = repo[None]
5960 c = repo[None]
5961 if c.dirty(merge=False, branch=False, missing=True):
5961 if c.dirty(merge=False, branch=False, missing=True):
5962 raise util.Abort(_("uncommitted changes"))
5962 raise util.Abort(_("uncommitted changes"))
5963 if rev is None:
5963 if rev is None:
5964 rev = repo[repo[None].branch()].rev()
5964 rev = repo[repo[None].branch()].rev()
5965 mergemod._checkunknown(repo, repo[None], repo[rev])
5965 mergemod._checkunknown(repo, repo[None], repo[rev])
5966
5966
5967 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5967 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5968
5968
5969 if clean:
5969 if clean:
5970 ret = hg.clean(repo, rev)
5970 ret = hg.clean(repo, rev)
5971 else:
5971 else:
5972 ret = hg.update(repo, rev)
5972 ret = hg.update(repo, rev)
5973
5973
5974 if not ret and movemarkfrom:
5974 if not ret and movemarkfrom:
5975 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5975 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5976 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5976 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5977 elif brev in repo._bookmarks:
5977 elif brev in repo._bookmarks:
5978 bookmarks.setcurrent(repo, brev)
5978 bookmarks.setcurrent(repo, brev)
5979 ui.status(_("(activating bookmark %s)\n") % brev)
5979 ui.status(_("(activating bookmark %s)\n") % brev)
5980 elif brev:
5980 elif brev:
5981 if repo._bookmarkcurrent:
5981 if repo._bookmarkcurrent:
5982 ui.status(_("(leaving bookmark %s)\n") %
5982 ui.status(_("(leaving bookmark %s)\n") %
5983 repo._bookmarkcurrent)
5983 repo._bookmarkcurrent)
5984 bookmarks.unsetcurrent(repo)
5984 bookmarks.unsetcurrent(repo)
5985
5985
5986 return ret
5986 return ret
5987
5987
5988 @command('verify', [])
5988 @command('verify', [])
5989 def verify(ui, repo):
5989 def verify(ui, repo):
5990 """verify the integrity of the repository
5990 """verify the integrity of the repository
5991
5991
5992 Verify the integrity of the current repository.
5992 Verify the integrity of the current repository.
5993
5993
5994 This will perform an extensive check of the repository's
5994 This will perform an extensive check of the repository's
5995 integrity, validating the hashes and checksums of each entry in
5995 integrity, validating the hashes and checksums of each entry in
5996 the changelog, manifest, and tracked files, as well as the
5996 the changelog, manifest, and tracked files, as well as the
5997 integrity of their crosslinks and indices.
5997 integrity of their crosslinks and indices.
5998
5998
5999 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5999 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6000 for more information about recovery from corruption of the
6000 for more information about recovery from corruption of the
6001 repository.
6001 repository.
6002
6002
6003 Returns 0 on success, 1 if errors are encountered.
6003 Returns 0 on success, 1 if errors are encountered.
6004 """
6004 """
6005 return hg.verify(repo)
6005 return hg.verify(repo)
6006
6006
6007 @command('version', [], norepo=True)
6007 @command('version', [], norepo=True)
6008 def version_(ui):
6008 def version_(ui):
6009 """output version and copyright information"""
6009 """output version and copyright information"""
6010 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6010 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6011 % util.version())
6011 % util.version())
6012 ui.status(_(
6012 ui.status(_(
6013 "(see http://mercurial.selenic.com for more information)\n"
6013 "(see http://mercurial.selenic.com for more information)\n"
6014 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6014 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6015 "This is free software; see the source for copying conditions. "
6015 "This is free software; see the source for copying conditions. "
6016 "There is NO\nwarranty; "
6016 "There is NO\nwarranty; "
6017 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6017 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6018 ))
6018 ))
General Comments 0
You need to be logged in to leave comments. Login now