##// END OF EJS Templates
bisect: move 'printresult' in the 'hbisect' module...
Pierre-Yves David -
r30067:6e88cd06 default
parent child Browse files
Show More
@@ -1,7381 +1,7356 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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import operator
12 import operator
13 import os
13 import os
14 import random
14 import random
15 import re
15 import re
16 import shlex
16 import shlex
17 import socket
17 import socket
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import time
20 import time
21
21
22 from .i18n import _
22 from .i18n import _
23 from .node import (
23 from .node import (
24 bin,
24 bin,
25 hex,
25 hex,
26 nullhex,
26 nullhex,
27 nullid,
27 nullid,
28 nullrev,
28 nullrev,
29 short,
29 short,
30 )
30 )
31 from . import (
31 from . import (
32 archival,
32 archival,
33 bookmarks,
33 bookmarks,
34 bundle2,
34 bundle2,
35 changegroup,
35 changegroup,
36 cmdutil,
36 cmdutil,
37 commandserver,
37 commandserver,
38 context,
38 context,
39 copies,
39 copies,
40 dagparser,
40 dagparser,
41 dagutil,
41 dagutil,
42 destutil,
42 destutil,
43 discovery,
43 discovery,
44 encoding,
44 encoding,
45 error,
45 error,
46 exchange,
46 exchange,
47 extensions,
47 extensions,
48 fileset,
48 fileset,
49 formatter,
49 formatter,
50 graphmod,
50 graphmod,
51 hbisect,
51 hbisect,
52 help,
52 help,
53 hg,
53 hg,
54 hgweb,
54 hgweb,
55 localrepo,
55 localrepo,
56 lock as lockmod,
56 lock as lockmod,
57 merge as mergemod,
57 merge as mergemod,
58 minirst,
58 minirst,
59 obsolete,
59 obsolete,
60 patch,
60 patch,
61 phases,
61 phases,
62 policy,
62 policy,
63 pvec,
63 pvec,
64 repair,
64 repair,
65 revlog,
65 revlog,
66 revset,
66 revset,
67 scmutil,
67 scmutil,
68 setdiscovery,
68 setdiscovery,
69 simplemerge,
69 simplemerge,
70 sshserver,
70 sshserver,
71 streamclone,
71 streamclone,
72 templatekw,
72 templatekw,
73 templater,
73 templater,
74 treediscovery,
74 treediscovery,
75 ui as uimod,
75 ui as uimod,
76 util,
76 util,
77 )
77 )
78
78
79 release = lockmod.release
79 release = lockmod.release
80
80
81 table = {}
81 table = {}
82
82
83 command = cmdutil.command(table)
83 command = cmdutil.command(table)
84
84
85 # label constants
85 # label constants
86 # until 3.5, bookmarks.current was the advertised name, not
86 # until 3.5, bookmarks.current was the advertised name, not
87 # bookmarks.active, so we must use both to avoid breaking old
87 # bookmarks.active, so we must use both to avoid breaking old
88 # custom styles
88 # custom styles
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
90
90
91 # common command options
91 # common command options
92
92
93 globalopts = [
93 globalopts = [
94 ('R', 'repository', '',
94 ('R', 'repository', '',
95 _('repository root directory or name of overlay bundle file'),
95 _('repository root directory or name of overlay bundle file'),
96 _('REPO')),
96 _('REPO')),
97 ('', 'cwd', '',
97 ('', 'cwd', '',
98 _('change working directory'), _('DIR')),
98 _('change working directory'), _('DIR')),
99 ('y', 'noninteractive', None,
99 ('y', 'noninteractive', None,
100 _('do not prompt, automatically pick the first choice for all prompts')),
100 _('do not prompt, automatically pick the first choice for all prompts')),
101 ('q', 'quiet', None, _('suppress output')),
101 ('q', 'quiet', None, _('suppress output')),
102 ('v', 'verbose', None, _('enable additional output')),
102 ('v', 'verbose', None, _('enable additional output')),
103 ('', 'config', [],
103 ('', 'config', [],
104 _('set/override config option (use \'section.name=value\')'),
104 _('set/override config option (use \'section.name=value\')'),
105 _('CONFIG')),
105 _('CONFIG')),
106 ('', 'debug', None, _('enable debugging output')),
106 ('', 'debug', None, _('enable debugging output')),
107 ('', 'debugger', None, _('start debugger')),
107 ('', 'debugger', None, _('start debugger')),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
109 _('ENCODE')),
109 _('ENCODE')),
110 ('', 'encodingmode', encoding.encodingmode,
110 ('', 'encodingmode', encoding.encodingmode,
111 _('set the charset encoding mode'), _('MODE')),
111 _('set the charset encoding mode'), _('MODE')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
113 ('', 'time', None, _('time how long the command takes')),
113 ('', 'time', None, _('time how long the command takes')),
114 ('', 'profile', None, _('print command execution profile')),
114 ('', 'profile', None, _('print command execution profile')),
115 ('', 'version', None, _('output version information and exit')),
115 ('', 'version', None, _('output version information and exit')),
116 ('h', 'help', None, _('display help and exit')),
116 ('h', 'help', None, _('display help and exit')),
117 ('', 'hidden', False, _('consider hidden changesets')),
117 ('', 'hidden', False, _('consider hidden changesets')),
118 ]
118 ]
119
119
120 dryrunopts = [('n', 'dry-run', None,
120 dryrunopts = [('n', 'dry-run', None,
121 _('do not perform actions, just print output'))]
121 _('do not perform actions, just print output'))]
122
122
123 remoteopts = [
123 remoteopts = [
124 ('e', 'ssh', '',
124 ('e', 'ssh', '',
125 _('specify ssh command to use'), _('CMD')),
125 _('specify ssh command to use'), _('CMD')),
126 ('', 'remotecmd', '',
126 ('', 'remotecmd', '',
127 _('specify hg command to run on the remote side'), _('CMD')),
127 _('specify hg command to run on the remote side'), _('CMD')),
128 ('', 'insecure', None,
128 ('', 'insecure', None,
129 _('do not verify server certificate (ignoring web.cacerts config)')),
129 _('do not verify server certificate (ignoring web.cacerts config)')),
130 ]
130 ]
131
131
132 walkopts = [
132 walkopts = [
133 ('I', 'include', [],
133 ('I', 'include', [],
134 _('include names matching the given patterns'), _('PATTERN')),
134 _('include names matching the given patterns'), _('PATTERN')),
135 ('X', 'exclude', [],
135 ('X', 'exclude', [],
136 _('exclude names matching the given patterns'), _('PATTERN')),
136 _('exclude names matching the given patterns'), _('PATTERN')),
137 ]
137 ]
138
138
139 commitopts = [
139 commitopts = [
140 ('m', 'message', '',
140 ('m', 'message', '',
141 _('use text as commit message'), _('TEXT')),
141 _('use text as commit message'), _('TEXT')),
142 ('l', 'logfile', '',
142 ('l', 'logfile', '',
143 _('read commit message from file'), _('FILE')),
143 _('read commit message from file'), _('FILE')),
144 ]
144 ]
145
145
146 commitopts2 = [
146 commitopts2 = [
147 ('d', 'date', '',
147 ('d', 'date', '',
148 _('record the specified date as commit date'), _('DATE')),
148 _('record the specified date as commit date'), _('DATE')),
149 ('u', 'user', '',
149 ('u', 'user', '',
150 _('record the specified user as committer'), _('USER')),
150 _('record the specified user as committer'), _('USER')),
151 ]
151 ]
152
152
153 # hidden for now
153 # hidden for now
154 formatteropts = [
154 formatteropts = [
155 ('T', 'template', '',
155 ('T', 'template', '',
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
157 ]
157 ]
158
158
159 templateopts = [
159 templateopts = [
160 ('', 'style', '',
160 ('', 'style', '',
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
162 ('T', 'template', '',
162 ('T', 'template', '',
163 _('display with template'), _('TEMPLATE')),
163 _('display with template'), _('TEMPLATE')),
164 ]
164 ]
165
165
166 logopts = [
166 logopts = [
167 ('p', 'patch', None, _('show patch')),
167 ('p', 'patch', None, _('show patch')),
168 ('g', 'git', None, _('use git extended diff format')),
168 ('g', 'git', None, _('use git extended diff format')),
169 ('l', 'limit', '',
169 ('l', 'limit', '',
170 _('limit number of changes displayed'), _('NUM')),
170 _('limit number of changes displayed'), _('NUM')),
171 ('M', 'no-merges', None, _('do not show merges')),
171 ('M', 'no-merges', None, _('do not show merges')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
173 ('G', 'graph', None, _("show the revision DAG")),
173 ('G', 'graph', None, _("show the revision DAG")),
174 ] + templateopts
174 ] + templateopts
175
175
176 diffopts = [
176 diffopts = [
177 ('a', 'text', None, _('treat all files as text')),
177 ('a', 'text', None, _('treat all files as text')),
178 ('g', 'git', None, _('use git extended diff format')),
178 ('g', 'git', None, _('use git extended diff format')),
179 ('', 'nodates', None, _('omit dates from diff headers'))
179 ('', 'nodates', None, _('omit dates from diff headers'))
180 ]
180 ]
181
181
182 diffwsopts = [
182 diffwsopts = [
183 ('w', 'ignore-all-space', None,
183 ('w', 'ignore-all-space', None,
184 _('ignore white space when comparing lines')),
184 _('ignore white space when comparing lines')),
185 ('b', 'ignore-space-change', None,
185 ('b', 'ignore-space-change', None,
186 _('ignore changes in the amount of white space')),
186 _('ignore changes in the amount of white space')),
187 ('B', 'ignore-blank-lines', None,
187 ('B', 'ignore-blank-lines', None,
188 _('ignore changes whose lines are all blank')),
188 _('ignore changes whose lines are all blank')),
189 ]
189 ]
190
190
191 diffopts2 = [
191 diffopts2 = [
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
193 ('p', 'show-function', None, _('show which function each change is in')),
193 ('p', 'show-function', None, _('show which function each change is in')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
195 ] + diffwsopts + [
195 ] + diffwsopts + [
196 ('U', 'unified', '',
196 ('U', 'unified', '',
197 _('number of lines of context to show'), _('NUM')),
197 _('number of lines of context to show'), _('NUM')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
200 ]
200 ]
201
201
202 mergetoolopts = [
202 mergetoolopts = [
203 ('t', 'tool', '', _('specify merge tool')),
203 ('t', 'tool', '', _('specify merge tool')),
204 ]
204 ]
205
205
206 similarityopts = [
206 similarityopts = [
207 ('s', 'similarity', '',
207 ('s', 'similarity', '',
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
209 ]
209 ]
210
210
211 subrepoopts = [
211 subrepoopts = [
212 ('S', 'subrepos', None,
212 ('S', 'subrepos', None,
213 _('recurse into subrepositories'))
213 _('recurse into subrepositories'))
214 ]
214 ]
215
215
216 debugrevlogopts = [
216 debugrevlogopts = [
217 ('c', 'changelog', False, _('open changelog')),
217 ('c', 'changelog', False, _('open changelog')),
218 ('m', 'manifest', False, _('open manifest')),
218 ('m', 'manifest', False, _('open manifest')),
219 ('', 'dir', '', _('open directory manifest')),
219 ('', 'dir', '', _('open directory manifest')),
220 ]
220 ]
221
221
222 # Commands start here, listed alphabetically
222 # Commands start here, listed alphabetically
223
223
224 @command('^add',
224 @command('^add',
225 walkopts + subrepoopts + dryrunopts,
225 walkopts + subrepoopts + dryrunopts,
226 _('[OPTION]... [FILE]...'),
226 _('[OPTION]... [FILE]...'),
227 inferrepo=True)
227 inferrepo=True)
228 def add(ui, repo, *pats, **opts):
228 def add(ui, repo, *pats, **opts):
229 """add the specified files on the next commit
229 """add the specified files on the next commit
230
230
231 Schedule files to be version controlled and added to the
231 Schedule files to be version controlled and added to the
232 repository.
232 repository.
233
233
234 The files will be added to the repository at the next commit. To
234 The files will be added to the repository at the next commit. To
235 undo an add before that, see :hg:`forget`.
235 undo an add before that, see :hg:`forget`.
236
236
237 If no names are given, add all files to the repository (except
237 If no names are given, add all files to the repository (except
238 files matching ``.hgignore``).
238 files matching ``.hgignore``).
239
239
240 .. container:: verbose
240 .. container:: verbose
241
241
242 Examples:
242 Examples:
243
243
244 - New (unknown) files are added
244 - New (unknown) files are added
245 automatically by :hg:`add`::
245 automatically by :hg:`add`::
246
246
247 $ ls
247 $ ls
248 foo.c
248 foo.c
249 $ hg status
249 $ hg status
250 ? foo.c
250 ? foo.c
251 $ hg add
251 $ hg add
252 adding foo.c
252 adding foo.c
253 $ hg status
253 $ hg status
254 A foo.c
254 A foo.c
255
255
256 - Specific files to be added can be specified::
256 - Specific files to be added can be specified::
257
257
258 $ ls
258 $ ls
259 bar.c foo.c
259 bar.c foo.c
260 $ hg status
260 $ hg status
261 ? bar.c
261 ? bar.c
262 ? foo.c
262 ? foo.c
263 $ hg add bar.c
263 $ hg add bar.c
264 $ hg status
264 $ hg status
265 A bar.c
265 A bar.c
266 ? foo.c
266 ? foo.c
267
267
268 Returns 0 if all files are successfully added.
268 Returns 0 if all files are successfully added.
269 """
269 """
270
270
271 m = scmutil.match(repo[None], pats, opts)
271 m = scmutil.match(repo[None], pats, opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
273 return rejected and 1 or 0
273 return rejected and 1 or 0
274
274
275 @command('addremove',
275 @command('addremove',
276 similarityopts + subrepoopts + walkopts + dryrunopts,
276 similarityopts + subrepoopts + walkopts + dryrunopts,
277 _('[OPTION]... [FILE]...'),
277 _('[OPTION]... [FILE]...'),
278 inferrepo=True)
278 inferrepo=True)
279 def addremove(ui, repo, *pats, **opts):
279 def addremove(ui, repo, *pats, **opts):
280 """add all new files, delete all missing files
280 """add all new files, delete all missing files
281
281
282 Add all new files and remove all missing files from the
282 Add all new files and remove all missing files from the
283 repository.
283 repository.
284
284
285 Unless names are given, new files are ignored if they match any of
285 Unless names are given, new files are ignored if they match any of
286 the patterns in ``.hgignore``. As with add, these changes take
286 the patterns in ``.hgignore``. As with add, these changes take
287 effect at the next commit.
287 effect at the next commit.
288
288
289 Use the -s/--similarity option to detect renamed files. This
289 Use the -s/--similarity option to detect renamed files. This
290 option takes a percentage between 0 (disabled) and 100 (files must
290 option takes a percentage between 0 (disabled) and 100 (files must
291 be identical) as its parameter. With a parameter greater than 0,
291 be identical) as its parameter. With a parameter greater than 0,
292 this compares every removed file with every added file and records
292 this compares every removed file with every added file and records
293 those similar enough as renames. Detecting renamed files this way
293 those similar enough as renames. Detecting renamed files this way
294 can be expensive. After using this option, :hg:`status -C` can be
294 can be expensive. After using this option, :hg:`status -C` can be
295 used to check which files were identified as moved or renamed. If
295 used to check which files were identified as moved or renamed. If
296 not specified, -s/--similarity defaults to 100 and only renames of
296 not specified, -s/--similarity defaults to 100 and only renames of
297 identical files are detected.
297 identical files are detected.
298
298
299 .. container:: verbose
299 .. container:: verbose
300
300
301 Examples:
301 Examples:
302
302
303 - A number of files (bar.c and foo.c) are new,
303 - A number of files (bar.c and foo.c) are new,
304 while foobar.c has been removed (without using :hg:`remove`)
304 while foobar.c has been removed (without using :hg:`remove`)
305 from the repository::
305 from the repository::
306
306
307 $ ls
307 $ ls
308 bar.c foo.c
308 bar.c foo.c
309 $ hg status
309 $ hg status
310 ! foobar.c
310 ! foobar.c
311 ? bar.c
311 ? bar.c
312 ? foo.c
312 ? foo.c
313 $ hg addremove
313 $ hg addremove
314 adding bar.c
314 adding bar.c
315 adding foo.c
315 adding foo.c
316 removing foobar.c
316 removing foobar.c
317 $ hg status
317 $ hg status
318 A bar.c
318 A bar.c
319 A foo.c
319 A foo.c
320 R foobar.c
320 R foobar.c
321
321
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
323 Afterwards, it was edited slightly::
323 Afterwards, it was edited slightly::
324
324
325 $ ls
325 $ ls
326 foo.c
326 foo.c
327 $ hg status
327 $ hg status
328 ! foobar.c
328 ! foobar.c
329 ? foo.c
329 ? foo.c
330 $ hg addremove --similarity 90
330 $ hg addremove --similarity 90
331 removing foobar.c
331 removing foobar.c
332 adding foo.c
332 adding foo.c
333 recording removal of foobar.c as rename to foo.c (94% similar)
333 recording removal of foobar.c as rename to foo.c (94% similar)
334 $ hg status -C
334 $ hg status -C
335 A foo.c
335 A foo.c
336 foobar.c
336 foobar.c
337 R foobar.c
337 R foobar.c
338
338
339 Returns 0 if all files are successfully added.
339 Returns 0 if all files are successfully added.
340 """
340 """
341 try:
341 try:
342 sim = float(opts.get('similarity') or 100)
342 sim = float(opts.get('similarity') or 100)
343 except ValueError:
343 except ValueError:
344 raise error.Abort(_('similarity must be a number'))
344 raise error.Abort(_('similarity must be a number'))
345 if sim < 0 or sim > 100:
345 if sim < 0 or sim > 100:
346 raise error.Abort(_('similarity must be between 0 and 100'))
346 raise error.Abort(_('similarity must be between 0 and 100'))
347 matcher = scmutil.match(repo[None], pats, opts)
347 matcher = scmutil.match(repo[None], pats, opts)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
349
349
350 @command('^annotate|blame',
350 @command('^annotate|blame',
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
352 ('', 'follow', None,
352 ('', 'follow', None,
353 _('follow copies/renames and list the filename (DEPRECATED)')),
353 _('follow copies/renames and list the filename (DEPRECATED)')),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
355 ('a', 'text', None, _('treat all files as text')),
355 ('a', 'text', None, _('treat all files as text')),
356 ('u', 'user', None, _('list the author (long with -v)')),
356 ('u', 'user', None, _('list the author (long with -v)')),
357 ('f', 'file', None, _('list the filename')),
357 ('f', 'file', None, _('list the filename')),
358 ('d', 'date', None, _('list the date (short with -q)')),
358 ('d', 'date', None, _('list the date (short with -q)')),
359 ('n', 'number', None, _('list the revision number (default)')),
359 ('n', 'number', None, _('list the revision number (default)')),
360 ('c', 'changeset', None, _('list the changeset')),
360 ('c', 'changeset', None, _('list the changeset')),
361 ('l', 'line-number', None, _('show line number at the first appearance'))
361 ('l', 'line-number', None, _('show line number at the first appearance'))
362 ] + diffwsopts + walkopts + formatteropts,
362 ] + diffwsopts + walkopts + formatteropts,
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
364 inferrepo=True)
364 inferrepo=True)
365 def annotate(ui, repo, *pats, **opts):
365 def annotate(ui, repo, *pats, **opts):
366 """show changeset information by line for each file
366 """show changeset information by line for each file
367
367
368 List changes in files, showing the revision id responsible for
368 List changes in files, showing the revision id responsible for
369 each line.
369 each line.
370
370
371 This command is useful for discovering when a change was made and
371 This command is useful for discovering when a change was made and
372 by whom.
372 by whom.
373
373
374 If you include --file, --user, or --date, the revision number is
374 If you include --file, --user, or --date, the revision number is
375 suppressed unless you also include --number.
375 suppressed unless you also include --number.
376
376
377 Without the -a/--text option, annotate will avoid processing files
377 Without the -a/--text option, annotate will avoid processing files
378 it detects as binary. With -a, annotate will annotate the file
378 it detects as binary. With -a, annotate will annotate the file
379 anyway, although the results will probably be neither useful
379 anyway, although the results will probably be neither useful
380 nor desirable.
380 nor desirable.
381
381
382 Returns 0 on success.
382 Returns 0 on success.
383 """
383 """
384 if not pats:
384 if not pats:
385 raise error.Abort(_('at least one filename or pattern is required'))
385 raise error.Abort(_('at least one filename or pattern is required'))
386
386
387 if opts.get('follow'):
387 if opts.get('follow'):
388 # --follow is deprecated and now just an alias for -f/--file
388 # --follow is deprecated and now just an alias for -f/--file
389 # to mimic the behavior of Mercurial before version 1.5
389 # to mimic the behavior of Mercurial before version 1.5
390 opts['file'] = True
390 opts['file'] = True
391
391
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
393
393
394 fm = ui.formatter('annotate', opts)
394 fm = ui.formatter('annotate', opts)
395 if ui.quiet:
395 if ui.quiet:
396 datefunc = util.shortdate
396 datefunc = util.shortdate
397 else:
397 else:
398 datefunc = util.datestr
398 datefunc = util.datestr
399 if ctx.rev() is None:
399 if ctx.rev() is None:
400 def hexfn(node):
400 def hexfn(node):
401 if node is None:
401 if node is None:
402 return None
402 return None
403 else:
403 else:
404 return fm.hexfunc(node)
404 return fm.hexfunc(node)
405 if opts.get('changeset'):
405 if opts.get('changeset'):
406 # omit "+" suffix which is appended to node hex
406 # omit "+" suffix which is appended to node hex
407 def formatrev(rev):
407 def formatrev(rev):
408 if rev is None:
408 if rev is None:
409 return '%d' % ctx.p1().rev()
409 return '%d' % ctx.p1().rev()
410 else:
410 else:
411 return '%d' % rev
411 return '%d' % rev
412 else:
412 else:
413 def formatrev(rev):
413 def formatrev(rev):
414 if rev is None:
414 if rev is None:
415 return '%d+' % ctx.p1().rev()
415 return '%d+' % ctx.p1().rev()
416 else:
416 else:
417 return '%d ' % rev
417 return '%d ' % rev
418 def formathex(hex):
418 def formathex(hex):
419 if hex is None:
419 if hex is None:
420 return '%s+' % fm.hexfunc(ctx.p1().node())
420 return '%s+' % fm.hexfunc(ctx.p1().node())
421 else:
421 else:
422 return '%s ' % hex
422 return '%s ' % hex
423 else:
423 else:
424 hexfn = fm.hexfunc
424 hexfn = fm.hexfunc
425 formatrev = formathex = str
425 formatrev = formathex = str
426
426
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
431 ('file', ' ', lambda x: x[0].path(), str),
431 ('file', ' ', lambda x: x[0].path(), str),
432 ('line_number', ':', lambda x: x[1], str),
432 ('line_number', ':', lambda x: x[1], str),
433 ]
433 ]
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
435
435
436 if (not opts.get('user') and not opts.get('changeset')
436 if (not opts.get('user') and not opts.get('changeset')
437 and not opts.get('date') and not opts.get('file')):
437 and not opts.get('date') and not opts.get('file')):
438 opts['number'] = True
438 opts['number'] = True
439
439
440 linenumber = opts.get('line_number') is not None
440 linenumber = opts.get('line_number') is not None
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
443
443
444 if fm.isplain():
444 if fm.isplain():
445 def makefunc(get, fmt):
445 def makefunc(get, fmt):
446 return lambda x: fmt(get(x))
446 return lambda x: fmt(get(x))
447 else:
447 else:
448 def makefunc(get, fmt):
448 def makefunc(get, fmt):
449 return get
449 return get
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
451 if opts.get(op)]
451 if opts.get(op)]
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
454 if opts.get(op))
454 if opts.get(op))
455
455
456 def bad(x, y):
456 def bad(x, y):
457 raise error.Abort("%s: %s" % (x, y))
457 raise error.Abort("%s: %s" % (x, y))
458
458
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
460
460
461 follow = not opts.get('no_follow')
461 follow = not opts.get('no_follow')
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
463 whitespace=True)
463 whitespace=True)
464 for abs in ctx.walk(m):
464 for abs in ctx.walk(m):
465 fctx = ctx[abs]
465 fctx = ctx[abs]
466 if not opts.get('text') and util.binary(fctx.data()):
466 if not opts.get('text') and util.binary(fctx.data()):
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
468 continue
468 continue
469
469
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
471 diffopts=diffopts)
471 diffopts=diffopts)
472 if not lines:
472 if not lines:
473 continue
473 continue
474 formats = []
474 formats = []
475 pieces = []
475 pieces = []
476
476
477 for f, sep in funcmap:
477 for f, sep in funcmap:
478 l = [f(n) for n, dummy in lines]
478 l = [f(n) for n, dummy in lines]
479 if fm.isplain():
479 if fm.isplain():
480 sizes = [encoding.colwidth(x) for x in l]
480 sizes = [encoding.colwidth(x) for x in l]
481 ml = max(sizes)
481 ml = max(sizes)
482 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
482 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
483 else:
483 else:
484 formats.append(['%s' for x in l])
484 formats.append(['%s' for x in l])
485 pieces.append(l)
485 pieces.append(l)
486
486
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
488 fm.startitem()
488 fm.startitem()
489 fm.write(fields, "".join(f), *p)
489 fm.write(fields, "".join(f), *p)
490 fm.write('line', ": %s", l[1])
490 fm.write('line', ": %s", l[1])
491
491
492 if not lines[-1][1].endswith('\n'):
492 if not lines[-1][1].endswith('\n'):
493 fm.plain('\n')
493 fm.plain('\n')
494
494
495 fm.end()
495 fm.end()
496
496
497 @command('archive',
497 @command('archive',
498 [('', 'no-decode', None, _('do not pass files through decoders')),
498 [('', 'no-decode', None, _('do not pass files through decoders')),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
500 _('PREFIX')),
500 _('PREFIX')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
503 ] + subrepoopts + walkopts,
503 ] + subrepoopts + walkopts,
504 _('[OPTION]... DEST'))
504 _('[OPTION]... DEST'))
505 def archive(ui, repo, dest, **opts):
505 def archive(ui, repo, dest, **opts):
506 '''create an unversioned archive of a repository revision
506 '''create an unversioned archive of a repository revision
507
507
508 By default, the revision used is the parent of the working
508 By default, the revision used is the parent of the working
509 directory; use -r/--rev to specify a different revision.
509 directory; use -r/--rev to specify a different revision.
510
510
511 The archive type is automatically detected based on file
511 The archive type is automatically detected based on file
512 extension (to override, use -t/--type).
512 extension (to override, use -t/--type).
513
513
514 .. container:: verbose
514 .. container:: verbose
515
515
516 Examples:
516 Examples:
517
517
518 - create a zip file containing the 1.0 release::
518 - create a zip file containing the 1.0 release::
519
519
520 hg archive -r 1.0 project-1.0.zip
520 hg archive -r 1.0 project-1.0.zip
521
521
522 - create a tarball excluding .hg files::
522 - create a tarball excluding .hg files::
523
523
524 hg archive project.tar.gz -X ".hg*"
524 hg archive project.tar.gz -X ".hg*"
525
525
526 Valid types are:
526 Valid types are:
527
527
528 :``files``: a directory full of files (default)
528 :``files``: a directory full of files (default)
529 :``tar``: tar archive, uncompressed
529 :``tar``: tar archive, uncompressed
530 :``tbz2``: tar archive, compressed using bzip2
530 :``tbz2``: tar archive, compressed using bzip2
531 :``tgz``: tar archive, compressed using gzip
531 :``tgz``: tar archive, compressed using gzip
532 :``uzip``: zip archive, uncompressed
532 :``uzip``: zip archive, uncompressed
533 :``zip``: zip archive, compressed using deflate
533 :``zip``: zip archive, compressed using deflate
534
534
535 The exact name of the destination archive or directory is given
535 The exact name of the destination archive or directory is given
536 using a format string; see :hg:`help export` for details.
536 using a format string; see :hg:`help export` for details.
537
537
538 Each member added to an archive file has a directory prefix
538 Each member added to an archive file has a directory prefix
539 prepended. Use -p/--prefix to specify a format string for the
539 prepended. Use -p/--prefix to specify a format string for the
540 prefix. The default is the basename of the archive, with suffixes
540 prefix. The default is the basename of the archive, with suffixes
541 removed.
541 removed.
542
542
543 Returns 0 on success.
543 Returns 0 on success.
544 '''
544 '''
545
545
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
547 if not ctx:
547 if not ctx:
548 raise error.Abort(_('no working directory: please specify a revision'))
548 raise error.Abort(_('no working directory: please specify a revision'))
549 node = ctx.node()
549 node = ctx.node()
550 dest = cmdutil.makefilename(repo, dest, node)
550 dest = cmdutil.makefilename(repo, dest, node)
551 if os.path.realpath(dest) == repo.root:
551 if os.path.realpath(dest) == repo.root:
552 raise error.Abort(_('repository root cannot be destination'))
552 raise error.Abort(_('repository root cannot be destination'))
553
553
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
555 prefix = opts.get('prefix')
555 prefix = opts.get('prefix')
556
556
557 if dest == '-':
557 if dest == '-':
558 if kind == 'files':
558 if kind == 'files':
559 raise error.Abort(_('cannot archive plain files to stdout'))
559 raise error.Abort(_('cannot archive plain files to stdout'))
560 dest = cmdutil.makefileobj(repo, dest)
560 dest = cmdutil.makefileobj(repo, dest)
561 if not prefix:
561 if not prefix:
562 prefix = os.path.basename(repo.root) + '-%h'
562 prefix = os.path.basename(repo.root) + '-%h'
563
563
564 prefix = cmdutil.makefilename(repo, prefix, node)
564 prefix = cmdutil.makefilename(repo, prefix, node)
565 matchfn = scmutil.match(ctx, [], opts)
565 matchfn = scmutil.match(ctx, [], opts)
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
567 matchfn, prefix, subrepos=opts.get('subrepos'))
567 matchfn, prefix, subrepos=opts.get('subrepos'))
568
568
569 @command('backout',
569 @command('backout',
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
571 ('', 'commit', None,
571 ('', 'commit', None,
572 _('commit if no conflicts were encountered (DEPRECATED)')),
572 _('commit if no conflicts were encountered (DEPRECATED)')),
573 ('', 'no-commit', None, _('do not commit')),
573 ('', 'no-commit', None, _('do not commit')),
574 ('', 'parent', '',
574 ('', 'parent', '',
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
579 _('[OPTION]... [-r] REV'))
579 _('[OPTION]... [-r] REV'))
580 def backout(ui, repo, node=None, rev=None, **opts):
580 def backout(ui, repo, node=None, rev=None, **opts):
581 '''reverse effect of earlier changeset
581 '''reverse effect of earlier changeset
582
582
583 Prepare a new changeset with the effect of REV undone in the
583 Prepare a new changeset with the effect of REV undone in the
584 current working directory. If no conflicts were encountered,
584 current working directory. If no conflicts were encountered,
585 it will be committed immediately.
585 it will be committed immediately.
586
586
587 If REV is the parent of the working directory, then this new changeset
587 If REV is the parent of the working directory, then this new changeset
588 is committed automatically (unless --no-commit is specified).
588 is committed automatically (unless --no-commit is specified).
589
589
590 .. note::
590 .. note::
591
591
592 :hg:`backout` cannot be used to fix either an unwanted or
592 :hg:`backout` cannot be used to fix either an unwanted or
593 incorrect merge.
593 incorrect merge.
594
594
595 .. container:: verbose
595 .. container:: verbose
596
596
597 Examples:
597 Examples:
598
598
599 - Reverse the effect of the parent of the working directory.
599 - Reverse the effect of the parent of the working directory.
600 This backout will be committed immediately::
600 This backout will be committed immediately::
601
601
602 hg backout -r .
602 hg backout -r .
603
603
604 - Reverse the effect of previous bad revision 23::
604 - Reverse the effect of previous bad revision 23::
605
605
606 hg backout -r 23
606 hg backout -r 23
607
607
608 - Reverse the effect of previous bad revision 23 and
608 - Reverse the effect of previous bad revision 23 and
609 leave changes uncommitted::
609 leave changes uncommitted::
610
610
611 hg backout -r 23 --no-commit
611 hg backout -r 23 --no-commit
612 hg commit -m "Backout revision 23"
612 hg commit -m "Backout revision 23"
613
613
614 By default, the pending changeset will have one parent,
614 By default, the pending changeset will have one parent,
615 maintaining a linear history. With --merge, the pending
615 maintaining a linear history. With --merge, the pending
616 changeset will instead have two parents: the old parent of the
616 changeset will instead have two parents: the old parent of the
617 working directory and a new child of REV that simply undoes REV.
617 working directory and a new child of REV that simply undoes REV.
618
618
619 Before version 1.7, the behavior without --merge was equivalent
619 Before version 1.7, the behavior without --merge was equivalent
620 to specifying --merge followed by :hg:`update --clean .` to
620 to specifying --merge followed by :hg:`update --clean .` to
621 cancel the merge and leave the child of REV as a head to be
621 cancel the merge and leave the child of REV as a head to be
622 merged separately.
622 merged separately.
623
623
624 See :hg:`help dates` for a list of formats valid for -d/--date.
624 See :hg:`help dates` for a list of formats valid for -d/--date.
625
625
626 See :hg:`help revert` for a way to restore files to the state
626 See :hg:`help revert` for a way to restore files to the state
627 of another revision.
627 of another revision.
628
628
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
630 files.
630 files.
631 '''
631 '''
632 wlock = lock = None
632 wlock = lock = None
633 try:
633 try:
634 wlock = repo.wlock()
634 wlock = repo.wlock()
635 lock = repo.lock()
635 lock = repo.lock()
636 return _dobackout(ui, repo, node, rev, **opts)
636 return _dobackout(ui, repo, node, rev, **opts)
637 finally:
637 finally:
638 release(lock, wlock)
638 release(lock, wlock)
639
639
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
641 if opts.get('commit') and opts.get('no_commit'):
641 if opts.get('commit') and opts.get('no_commit'):
642 raise error.Abort(_("cannot use --commit with --no-commit"))
642 raise error.Abort(_("cannot use --commit with --no-commit"))
643 if opts.get('merge') and opts.get('no_commit'):
643 if opts.get('merge') and opts.get('no_commit'):
644 raise error.Abort(_("cannot use --merge with --no-commit"))
644 raise error.Abort(_("cannot use --merge with --no-commit"))
645
645
646 if rev and node:
646 if rev and node:
647 raise error.Abort(_("please specify just one revision"))
647 raise error.Abort(_("please specify just one revision"))
648
648
649 if not rev:
649 if not rev:
650 rev = node
650 rev = node
651
651
652 if not rev:
652 if not rev:
653 raise error.Abort(_("please specify a revision to backout"))
653 raise error.Abort(_("please specify a revision to backout"))
654
654
655 date = opts.get('date')
655 date = opts.get('date')
656 if date:
656 if date:
657 opts['date'] = util.parsedate(date)
657 opts['date'] = util.parsedate(date)
658
658
659 cmdutil.checkunfinished(repo)
659 cmdutil.checkunfinished(repo)
660 cmdutil.bailifchanged(repo)
660 cmdutil.bailifchanged(repo)
661 node = scmutil.revsingle(repo, rev).node()
661 node = scmutil.revsingle(repo, rev).node()
662
662
663 op1, op2 = repo.dirstate.parents()
663 op1, op2 = repo.dirstate.parents()
664 if not repo.changelog.isancestor(node, op1):
664 if not repo.changelog.isancestor(node, op1):
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
666
666
667 p1, p2 = repo.changelog.parents(node)
667 p1, p2 = repo.changelog.parents(node)
668 if p1 == nullid:
668 if p1 == nullid:
669 raise error.Abort(_('cannot backout a change with no parents'))
669 raise error.Abort(_('cannot backout a change with no parents'))
670 if p2 != nullid:
670 if p2 != nullid:
671 if not opts.get('parent'):
671 if not opts.get('parent'):
672 raise error.Abort(_('cannot backout a merge changeset'))
672 raise error.Abort(_('cannot backout a merge changeset'))
673 p = repo.lookup(opts['parent'])
673 p = repo.lookup(opts['parent'])
674 if p not in (p1, p2):
674 if p not in (p1, p2):
675 raise error.Abort(_('%s is not a parent of %s') %
675 raise error.Abort(_('%s is not a parent of %s') %
676 (short(p), short(node)))
676 (short(p), short(node)))
677 parent = p
677 parent = p
678 else:
678 else:
679 if opts.get('parent'):
679 if opts.get('parent'):
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
681 parent = p1
681 parent = p1
682
682
683 # the backout should appear on the same branch
683 # the backout should appear on the same branch
684 branch = repo.dirstate.branch()
684 branch = repo.dirstate.branch()
685 bheads = repo.branchheads(branch)
685 bheads = repo.branchheads(branch)
686 rctx = scmutil.revsingle(repo, hex(parent))
686 rctx = scmutil.revsingle(repo, hex(parent))
687 if not opts.get('merge') and op1 != node:
687 if not opts.get('merge') and op1 != node:
688 dsguard = cmdutil.dirstateguard(repo, 'backout')
688 dsguard = cmdutil.dirstateguard(repo, 'backout')
689 try:
689 try:
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 'backout')
691 'backout')
692 stats = mergemod.update(repo, parent, True, True, node, False)
692 stats = mergemod.update(repo, parent, True, True, node, False)
693 repo.setparents(op1, op2)
693 repo.setparents(op1, op2)
694 dsguard.close()
694 dsguard.close()
695 hg._showstats(repo, stats)
695 hg._showstats(repo, stats)
696 if stats[3]:
696 if stats[3]:
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
698 "file merges\n"))
698 "file merges\n"))
699 return 1
699 return 1
700 finally:
700 finally:
701 ui.setconfig('ui', 'forcemerge', '', '')
701 ui.setconfig('ui', 'forcemerge', '', '')
702 lockmod.release(dsguard)
702 lockmod.release(dsguard)
703 else:
703 else:
704 hg.clean(repo, node, show_stats=False)
704 hg.clean(repo, node, show_stats=False)
705 repo.dirstate.setbranch(branch)
705 repo.dirstate.setbranch(branch)
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
707
707
708 if opts.get('no_commit'):
708 if opts.get('no_commit'):
709 msg = _("changeset %s backed out, "
709 msg = _("changeset %s backed out, "
710 "don't forget to commit.\n")
710 "don't forget to commit.\n")
711 ui.status(msg % short(node))
711 ui.status(msg % short(node))
712 return 0
712 return 0
713
713
714 def commitfunc(ui, repo, message, match, opts):
714 def commitfunc(ui, repo, message, match, opts):
715 editform = 'backout'
715 editform = 'backout'
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
717 if not message:
717 if not message:
718 # we don't translate commit messages
718 # we don't translate commit messages
719 message = "Backed out changeset %s" % short(node)
719 message = "Backed out changeset %s" % short(node)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
721 return repo.commit(message, opts.get('user'), opts.get('date'),
721 return repo.commit(message, opts.get('user'), opts.get('date'),
722 match, editor=e)
722 match, editor=e)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
724 if not newnode:
724 if not newnode:
725 ui.status(_("nothing changed\n"))
725 ui.status(_("nothing changed\n"))
726 return 1
726 return 1
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
728
728
729 def nice(node):
729 def nice(node):
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
731 ui.status(_('changeset %s backs out changeset %s\n') %
731 ui.status(_('changeset %s backs out changeset %s\n') %
732 (nice(repo.changelog.tip()), nice(node)))
732 (nice(repo.changelog.tip()), nice(node)))
733 if opts.get('merge') and op1 != node:
733 if opts.get('merge') and op1 != node:
734 hg.clean(repo, op1, show_stats=False)
734 hg.clean(repo, op1, show_stats=False)
735 ui.status(_('merging with changeset %s\n')
735 ui.status(_('merging with changeset %s\n')
736 % nice(repo.changelog.tip()))
736 % nice(repo.changelog.tip()))
737 try:
737 try:
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
739 'backout')
739 'backout')
740 return hg.merge(repo, hex(repo.changelog.tip()))
740 return hg.merge(repo, hex(repo.changelog.tip()))
741 finally:
741 finally:
742 ui.setconfig('ui', 'forcemerge', '', '')
742 ui.setconfig('ui', 'forcemerge', '', '')
743 return 0
743 return 0
744
744
745 @command('bisect',
745 @command('bisect',
746 [('r', 'reset', False, _('reset bisect state')),
746 [('r', 'reset', False, _('reset bisect state')),
747 ('g', 'good', False, _('mark changeset good')),
747 ('g', 'good', False, _('mark changeset good')),
748 ('b', 'bad', False, _('mark changeset bad')),
748 ('b', 'bad', False, _('mark changeset bad')),
749 ('s', 'skip', False, _('skip testing changeset')),
749 ('s', 'skip', False, _('skip testing changeset')),
750 ('e', 'extend', False, _('extend the bisect range')),
750 ('e', 'extend', False, _('extend the bisect range')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
752 ('U', 'noupdate', False, _('do not update to target'))],
752 ('U', 'noupdate', False, _('do not update to target'))],
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
754 def bisect(ui, repo, rev=None, extra=None, command=None,
754 def bisect(ui, repo, rev=None, extra=None, command=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
756 noupdate=None):
756 noupdate=None):
757 """subdivision search of changesets
757 """subdivision search of changesets
758
758
759 This command helps to find changesets which introduce problems. To
759 This command helps to find changesets which introduce problems. To
760 use, mark the earliest changeset you know exhibits the problem as
760 use, mark the earliest changeset you know exhibits the problem as
761 bad, then mark the latest changeset which is free from the problem
761 bad, then mark the latest changeset which is free from the problem
762 as good. Bisect will update your working directory to a revision
762 as good. Bisect will update your working directory to a revision
763 for testing (unless the -U/--noupdate option is specified). Once
763 for testing (unless the -U/--noupdate option is specified). Once
764 you have performed tests, mark the working directory as good or
764 you have performed tests, mark the working directory as good or
765 bad, and bisect will either update to another candidate changeset
765 bad, and bisect will either update to another candidate changeset
766 or announce that it has found the bad revision.
766 or announce that it has found the bad revision.
767
767
768 As a shortcut, you can also use the revision argument to mark a
768 As a shortcut, you can also use the revision argument to mark a
769 revision as good or bad without checking it out first.
769 revision as good or bad without checking it out first.
770
770
771 If you supply a command, it will be used for automatic bisection.
771 If you supply a command, it will be used for automatic bisection.
772 The environment variable HG_NODE will contain the ID of the
772 The environment variable HG_NODE will contain the ID of the
773 changeset being tested. The exit status of the command will be
773 changeset being tested. The exit status of the command will be
774 used to mark revisions as good or bad: status 0 means good, 125
774 used to mark revisions as good or bad: status 0 means good, 125
775 means to skip the revision, 127 (command not found) will abort the
775 means to skip the revision, 127 (command not found) will abort the
776 bisection, and any other non-zero exit status means the revision
776 bisection, and any other non-zero exit status means the revision
777 is bad.
777 is bad.
778
778
779 .. container:: verbose
779 .. container:: verbose
780
780
781 Some examples:
781 Some examples:
782
782
783 - start a bisection with known bad revision 34, and good revision 12::
783 - start a bisection with known bad revision 34, and good revision 12::
784
784
785 hg bisect --bad 34
785 hg bisect --bad 34
786 hg bisect --good 12
786 hg bisect --good 12
787
787
788 - advance the current bisection by marking current revision as good or
788 - advance the current bisection by marking current revision as good or
789 bad::
789 bad::
790
790
791 hg bisect --good
791 hg bisect --good
792 hg bisect --bad
792 hg bisect --bad
793
793
794 - mark the current revision, or a known revision, to be skipped (e.g. if
794 - mark the current revision, or a known revision, to be skipped (e.g. if
795 that revision is not usable because of another issue)::
795 that revision is not usable because of another issue)::
796
796
797 hg bisect --skip
797 hg bisect --skip
798 hg bisect --skip 23
798 hg bisect --skip 23
799
799
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
801
801
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
803
803
804 - forget the current bisection::
804 - forget the current bisection::
805
805
806 hg bisect --reset
806 hg bisect --reset
807
807
808 - use 'make && make tests' to automatically find the first broken
808 - use 'make && make tests' to automatically find the first broken
809 revision::
809 revision::
810
810
811 hg bisect --reset
811 hg bisect --reset
812 hg bisect --bad 34
812 hg bisect --bad 34
813 hg bisect --good 12
813 hg bisect --good 12
814 hg bisect --command "make && make tests"
814 hg bisect --command "make && make tests"
815
815
816 - see all changesets whose states are already known in the current
816 - see all changesets whose states are already known in the current
817 bisection::
817 bisection::
818
818
819 hg log -r "bisect(pruned)"
819 hg log -r "bisect(pruned)"
820
820
821 - see the changeset currently being bisected (especially useful
821 - see the changeset currently being bisected (especially useful
822 if running with -U/--noupdate)::
822 if running with -U/--noupdate)::
823
823
824 hg log -r "bisect(current)"
824 hg log -r "bisect(current)"
825
825
826 - see all changesets that took part in the current bisection::
826 - see all changesets that took part in the current bisection::
827
827
828 hg log -r "bisect(range)"
828 hg log -r "bisect(range)"
829
829
830 - you can even get a nice graph::
830 - you can even get a nice graph::
831
831
832 hg log --graph -r "bisect(range)"
832 hg log --graph -r "bisect(range)"
833
833
834 See :hg:`help revsets` for more about the `bisect()` keyword.
834 See :hg:`help revsets` for more about the `bisect()` keyword.
835
835
836 Returns 0 on success.
836 Returns 0 on success.
837 """
837 """
838 def print_result(nodes, good):
839 displayer = cmdutil.show_changeset(ui, repo, {})
840 if len(nodes) == 1:
841 # narrowed it down to a single revision
842 if good:
843 ui.write(_("The first good revision is:\n"))
844 else:
845 ui.write(_("The first bad revision is:\n"))
846 displayer.show(repo[nodes[0]])
847 extendnode = hbisect.extendrange(repo, state, nodes, good)
848 if extendnode is not None:
849 ui.write(_('Not all ancestors of this changeset have been'
850 ' checked.\nUse bisect --extend to continue the '
851 'bisection from\nthe common ancestor, %s.\n')
852 % extendnode)
853 else:
854 # multiple possible revisions
855 if good:
856 ui.write(_("Due to skipped revisions, the first "
857 "good revision could be any of:\n"))
858 else:
859 ui.write(_("Due to skipped revisions, the first "
860 "bad revision could be any of:\n"))
861 for n in nodes:
862 displayer.show(repo[n])
863 displayer.close()
864
865 def check_state(state, interactive=True):
838 def check_state(state, interactive=True):
866 if not state['good'] or not state['bad']:
839 if not state['good'] or not state['bad']:
867 if (good or bad or skip or reset) and interactive:
840 if (good or bad or skip or reset) and interactive:
868 return
841 return
869 if not state['good']:
842 if not state['good']:
870 raise error.Abort(_('cannot bisect (no known good revisions)'))
843 raise error.Abort(_('cannot bisect (no known good revisions)'))
871 else:
844 else:
872 raise error.Abort(_('cannot bisect (no known bad revisions)'))
845 raise error.Abort(_('cannot bisect (no known bad revisions)'))
873 return True
846 return True
874
847
875 # backward compatibility
848 # backward compatibility
876 if rev in "good bad reset init".split():
849 if rev in "good bad reset init".split():
877 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
850 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
878 cmd, rev, extra = rev, extra, None
851 cmd, rev, extra = rev, extra, None
879 if cmd == "good":
852 if cmd == "good":
880 good = True
853 good = True
881 elif cmd == "bad":
854 elif cmd == "bad":
882 bad = True
855 bad = True
883 else:
856 else:
884 reset = True
857 reset = True
885 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
858 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
886 raise error.Abort(_('incompatible arguments'))
859 raise error.Abort(_('incompatible arguments'))
887
860
888 cmdutil.checkunfinished(repo)
861 cmdutil.checkunfinished(repo)
889
862
890 if reset:
863 if reset:
891 hbisect.resetstate(repo)
864 hbisect.resetstate(repo)
892 return
865 return
893
866
894 state = hbisect.load_state(repo)
867 state = hbisect.load_state(repo)
895
868
896 if command:
869 if command:
897 changesets = 1
870 changesets = 1
898 if noupdate:
871 if noupdate:
899 try:
872 try:
900 node = state['current'][0]
873 node = state['current'][0]
901 except LookupError:
874 except LookupError:
902 raise error.Abort(_('current bisect revision is unknown - '
875 raise error.Abort(_('current bisect revision is unknown - '
903 'start a new bisect to fix'))
876 'start a new bisect to fix'))
904 else:
877 else:
905 node, p2 = repo.dirstate.parents()
878 node, p2 = repo.dirstate.parents()
906 if p2 != nullid:
879 if p2 != nullid:
907 raise error.Abort(_('current bisect revision is a merge'))
880 raise error.Abort(_('current bisect revision is a merge'))
908 try:
881 try:
909 while changesets:
882 while changesets:
910 # update state
883 # update state
911 state['current'] = [node]
884 state['current'] = [node]
912 hbisect.save_state(repo, state)
885 hbisect.save_state(repo, state)
913 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 status = ui.system(command, environ={'HG_NODE': hex(node)})
914 if status == 125:
887 if status == 125:
915 transition = "skip"
888 transition = "skip"
916 elif status == 0:
889 elif status == 0:
917 transition = "good"
890 transition = "good"
918 # status < 0 means process was killed
891 # status < 0 means process was killed
919 elif status == 127:
892 elif status == 127:
920 raise error.Abort(_("failed to execute %s") % command)
893 raise error.Abort(_("failed to execute %s") % command)
921 elif status < 0:
894 elif status < 0:
922 raise error.Abort(_("%s killed") % command)
895 raise error.Abort(_("%s killed") % command)
923 else:
896 else:
924 transition = "bad"
897 transition = "bad"
925 ctx = scmutil.revsingle(repo, rev, node)
898 ctx = scmutil.revsingle(repo, rev, node)
926 rev = None # clear for future iterations
899 rev = None # clear for future iterations
927 state[transition].append(ctx.node())
900 state[transition].append(ctx.node())
928 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
901 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
929 check_state(state, interactive=False)
902 check_state(state, interactive=False)
930 # bisect
903 # bisect
931 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
904 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
932 # update to next check
905 # update to next check
933 node = nodes[0]
906 node = nodes[0]
934 if not noupdate:
907 if not noupdate:
935 cmdutil.bailifchanged(repo)
908 cmdutil.bailifchanged(repo)
936 hg.clean(repo, node, show_stats=False)
909 hg.clean(repo, node, show_stats=False)
937 finally:
910 finally:
938 state['current'] = [node]
911 state['current'] = [node]
939 hbisect.save_state(repo, state)
912 hbisect.save_state(repo, state)
940 print_result(nodes, bgood)
913 displayer = cmdutil.show_changeset(ui, repo, {})
914 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
941 return
915 return
942
916
943 # update state
917 # update state
944
918
945 if rev:
919 if rev:
946 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
920 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
947 else:
921 else:
948 nodes = [repo.lookup('.')]
922 nodes = [repo.lookup('.')]
949
923
950 if good or bad or skip:
924 if good or bad or skip:
951 if good:
925 if good:
952 state['good'] += nodes
926 state['good'] += nodes
953 elif bad:
927 elif bad:
954 state['bad'] += nodes
928 state['bad'] += nodes
955 elif skip:
929 elif skip:
956 state['skip'] += nodes
930 state['skip'] += nodes
957 hbisect.save_state(repo, state)
931 hbisect.save_state(repo, state)
958
932
959 if not check_state(state):
933 if not check_state(state):
960 return
934 return
961
935
962 # actually bisect
936 # actually bisect
963 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
937 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
964 if extend:
938 if extend:
965 if not changesets:
939 if not changesets:
966 extendnode = hbisect.extendrange(repo, state, nodes, good)
940 extendnode = hbisect.extendrange(repo, state, nodes, good)
967 if extendnode is not None:
941 if extendnode is not None:
968 ui.write(_("Extending search to changeset %d:%s\n")
942 ui.write(_("Extending search to changeset %d:%s\n")
969 % (extendnode.rev(), extendnode))
943 % (extendnode.rev(), extendnode))
970 state['current'] = [extendnode.node()]
944 state['current'] = [extendnode.node()]
971 hbisect.save_state(repo, state)
945 hbisect.save_state(repo, state)
972 if noupdate:
946 if noupdate:
973 return
947 return
974 cmdutil.bailifchanged(repo)
948 cmdutil.bailifchanged(repo)
975 return hg.clean(repo, extendnode.node())
949 return hg.clean(repo, extendnode.node())
976 raise error.Abort(_("nothing to extend"))
950 raise error.Abort(_("nothing to extend"))
977
951
978 if changesets == 0:
952 if changesets == 0:
979 print_result(nodes, good)
953 displayer = cmdutil.show_changeset(ui, repo, {})
954 hbisect.printresult(ui, repo, state, displayer, nodes, good)
980 else:
955 else:
981 assert len(nodes) == 1 # only a single node can be tested next
956 assert len(nodes) == 1 # only a single node can be tested next
982 node = nodes[0]
957 node = nodes[0]
983 # compute the approximate number of remaining tests
958 # compute the approximate number of remaining tests
984 tests, size = 0, 2
959 tests, size = 0, 2
985 while size <= changesets:
960 while size <= changesets:
986 tests, size = tests + 1, size * 2
961 tests, size = tests + 1, size * 2
987 rev = repo.changelog.rev(node)
962 rev = repo.changelog.rev(node)
988 ui.write(_("Testing changeset %d:%s "
963 ui.write(_("Testing changeset %d:%s "
989 "(%d changesets remaining, ~%d tests)\n")
964 "(%d changesets remaining, ~%d tests)\n")
990 % (rev, short(node), changesets, tests))
965 % (rev, short(node), changesets, tests))
991 state['current'] = [node]
966 state['current'] = [node]
992 hbisect.save_state(repo, state)
967 hbisect.save_state(repo, state)
993 if not noupdate:
968 if not noupdate:
994 cmdutil.bailifchanged(repo)
969 cmdutil.bailifchanged(repo)
995 return hg.clean(repo, node)
970 return hg.clean(repo, node)
996
971
997 @command('bookmarks|bookmark',
972 @command('bookmarks|bookmark',
998 [('f', 'force', False, _('force')),
973 [('f', 'force', False, _('force')),
999 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
974 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
1000 ('d', 'delete', False, _('delete a given bookmark')),
975 ('d', 'delete', False, _('delete a given bookmark')),
1001 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
976 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
1002 ('i', 'inactive', False, _('mark a bookmark inactive')),
977 ('i', 'inactive', False, _('mark a bookmark inactive')),
1003 ] + formatteropts,
978 ] + formatteropts,
1004 _('hg bookmarks [OPTIONS]... [NAME]...'))
979 _('hg bookmarks [OPTIONS]... [NAME]...'))
1005 def bookmark(ui, repo, *names, **opts):
980 def bookmark(ui, repo, *names, **opts):
1006 '''create a new bookmark or list existing bookmarks
981 '''create a new bookmark or list existing bookmarks
1007
982
1008 Bookmarks are labels on changesets to help track lines of development.
983 Bookmarks are labels on changesets to help track lines of development.
1009 Bookmarks are unversioned and can be moved, renamed and deleted.
984 Bookmarks are unversioned and can be moved, renamed and deleted.
1010 Deleting or moving a bookmark has no effect on the associated changesets.
985 Deleting or moving a bookmark has no effect on the associated changesets.
1011
986
1012 Creating or updating to a bookmark causes it to be marked as 'active'.
987 Creating or updating to a bookmark causes it to be marked as 'active'.
1013 The active bookmark is indicated with a '*'.
988 The active bookmark is indicated with a '*'.
1014 When a commit is made, the active bookmark will advance to the new commit.
989 When a commit is made, the active bookmark will advance to the new commit.
1015 A plain :hg:`update` will also advance an active bookmark, if possible.
990 A plain :hg:`update` will also advance an active bookmark, if possible.
1016 Updating away from a bookmark will cause it to be deactivated.
991 Updating away from a bookmark will cause it to be deactivated.
1017
992
1018 Bookmarks can be pushed and pulled between repositories (see
993 Bookmarks can be pushed and pulled between repositories (see
1019 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
994 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1020 diverged, a new 'divergent bookmark' of the form 'name@path' will
995 diverged, a new 'divergent bookmark' of the form 'name@path' will
1021 be created. Using :hg:`merge` will resolve the divergence.
996 be created. Using :hg:`merge` will resolve the divergence.
1022
997
1023 A bookmark named '@' has the special property that :hg:`clone` will
998 A bookmark named '@' has the special property that :hg:`clone` will
1024 check it out by default if it exists.
999 check it out by default if it exists.
1025
1000
1026 .. container:: verbose
1001 .. container:: verbose
1027
1002
1028 Examples:
1003 Examples:
1029
1004
1030 - create an active bookmark for a new line of development::
1005 - create an active bookmark for a new line of development::
1031
1006
1032 hg book new-feature
1007 hg book new-feature
1033
1008
1034 - create an inactive bookmark as a place marker::
1009 - create an inactive bookmark as a place marker::
1035
1010
1036 hg book -i reviewed
1011 hg book -i reviewed
1037
1012
1038 - create an inactive bookmark on another changeset::
1013 - create an inactive bookmark on another changeset::
1039
1014
1040 hg book -r .^ tested
1015 hg book -r .^ tested
1041
1016
1042 - rename bookmark turkey to dinner::
1017 - rename bookmark turkey to dinner::
1043
1018
1044 hg book -m turkey dinner
1019 hg book -m turkey dinner
1045
1020
1046 - move the '@' bookmark from another branch::
1021 - move the '@' bookmark from another branch::
1047
1022
1048 hg book -f @
1023 hg book -f @
1049 '''
1024 '''
1050 force = opts.get('force')
1025 force = opts.get('force')
1051 rev = opts.get('rev')
1026 rev = opts.get('rev')
1052 delete = opts.get('delete')
1027 delete = opts.get('delete')
1053 rename = opts.get('rename')
1028 rename = opts.get('rename')
1054 inactive = opts.get('inactive')
1029 inactive = opts.get('inactive')
1055
1030
1056 def checkformat(mark):
1031 def checkformat(mark):
1057 mark = mark.strip()
1032 mark = mark.strip()
1058 if not mark:
1033 if not mark:
1059 raise error.Abort(_("bookmark names cannot consist entirely of "
1034 raise error.Abort(_("bookmark names cannot consist entirely of "
1060 "whitespace"))
1035 "whitespace"))
1061 scmutil.checknewlabel(repo, mark, 'bookmark')
1036 scmutil.checknewlabel(repo, mark, 'bookmark')
1062 return mark
1037 return mark
1063
1038
1064 def checkconflict(repo, mark, cur, force=False, target=None):
1039 def checkconflict(repo, mark, cur, force=False, target=None):
1065 if mark in marks and not force:
1040 if mark in marks and not force:
1066 if target:
1041 if target:
1067 if marks[mark] == target and target == cur:
1042 if marks[mark] == target and target == cur:
1068 # re-activating a bookmark
1043 # re-activating a bookmark
1069 return
1044 return
1070 anc = repo.changelog.ancestors([repo[target].rev()])
1045 anc = repo.changelog.ancestors([repo[target].rev()])
1071 bmctx = repo[marks[mark]]
1046 bmctx = repo[marks[mark]]
1072 divs = [repo[b].node() for b in marks
1047 divs = [repo[b].node() for b in marks
1073 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1048 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1074
1049
1075 # allow resolving a single divergent bookmark even if moving
1050 # allow resolving a single divergent bookmark even if moving
1076 # the bookmark across branches when a revision is specified
1051 # the bookmark across branches when a revision is specified
1077 # that contains a divergent bookmark
1052 # that contains a divergent bookmark
1078 if bmctx.rev() not in anc and target in divs:
1053 if bmctx.rev() not in anc and target in divs:
1079 bookmarks.deletedivergent(repo, [target], mark)
1054 bookmarks.deletedivergent(repo, [target], mark)
1080 return
1055 return
1081
1056
1082 deletefrom = [b for b in divs
1057 deletefrom = [b for b in divs
1083 if repo[b].rev() in anc or b == target]
1058 if repo[b].rev() in anc or b == target]
1084 bookmarks.deletedivergent(repo, deletefrom, mark)
1059 bookmarks.deletedivergent(repo, deletefrom, mark)
1085 if bookmarks.validdest(repo, bmctx, repo[target]):
1060 if bookmarks.validdest(repo, bmctx, repo[target]):
1086 ui.status(_("moving bookmark '%s' forward from %s\n") %
1061 ui.status(_("moving bookmark '%s' forward from %s\n") %
1087 (mark, short(bmctx.node())))
1062 (mark, short(bmctx.node())))
1088 return
1063 return
1089 raise error.Abort(_("bookmark '%s' already exists "
1064 raise error.Abort(_("bookmark '%s' already exists "
1090 "(use -f to force)") % mark)
1065 "(use -f to force)") % mark)
1091 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1066 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1092 and not force):
1067 and not force):
1093 raise error.Abort(
1068 raise error.Abort(
1094 _("a bookmark cannot have the name of an existing branch"))
1069 _("a bookmark cannot have the name of an existing branch"))
1095
1070
1096 if delete and rename:
1071 if delete and rename:
1097 raise error.Abort(_("--delete and --rename are incompatible"))
1072 raise error.Abort(_("--delete and --rename are incompatible"))
1098 if delete and rev:
1073 if delete and rev:
1099 raise error.Abort(_("--rev is incompatible with --delete"))
1074 raise error.Abort(_("--rev is incompatible with --delete"))
1100 if rename and rev:
1075 if rename and rev:
1101 raise error.Abort(_("--rev is incompatible with --rename"))
1076 raise error.Abort(_("--rev is incompatible with --rename"))
1102 if not names and (delete or rev):
1077 if not names and (delete or rev):
1103 raise error.Abort(_("bookmark name required"))
1078 raise error.Abort(_("bookmark name required"))
1104
1079
1105 if delete or rename or names or inactive:
1080 if delete or rename or names or inactive:
1106 wlock = lock = tr = None
1081 wlock = lock = tr = None
1107 try:
1082 try:
1108 wlock = repo.wlock()
1083 wlock = repo.wlock()
1109 lock = repo.lock()
1084 lock = repo.lock()
1110 cur = repo.changectx('.').node()
1085 cur = repo.changectx('.').node()
1111 marks = repo._bookmarks
1086 marks = repo._bookmarks
1112 if delete:
1087 if delete:
1113 tr = repo.transaction('bookmark')
1088 tr = repo.transaction('bookmark')
1114 for mark in names:
1089 for mark in names:
1115 if mark not in marks:
1090 if mark not in marks:
1116 raise error.Abort(_("bookmark '%s' does not exist") %
1091 raise error.Abort(_("bookmark '%s' does not exist") %
1117 mark)
1092 mark)
1118 if mark == repo._activebookmark:
1093 if mark == repo._activebookmark:
1119 bookmarks.deactivate(repo)
1094 bookmarks.deactivate(repo)
1120 del marks[mark]
1095 del marks[mark]
1121
1096
1122 elif rename:
1097 elif rename:
1123 tr = repo.transaction('bookmark')
1098 tr = repo.transaction('bookmark')
1124 if not names:
1099 if not names:
1125 raise error.Abort(_("new bookmark name required"))
1100 raise error.Abort(_("new bookmark name required"))
1126 elif len(names) > 1:
1101 elif len(names) > 1:
1127 raise error.Abort(_("only one new bookmark name allowed"))
1102 raise error.Abort(_("only one new bookmark name allowed"))
1128 mark = checkformat(names[0])
1103 mark = checkformat(names[0])
1129 if rename not in marks:
1104 if rename not in marks:
1130 raise error.Abort(_("bookmark '%s' does not exist")
1105 raise error.Abort(_("bookmark '%s' does not exist")
1131 % rename)
1106 % rename)
1132 checkconflict(repo, mark, cur, force)
1107 checkconflict(repo, mark, cur, force)
1133 marks[mark] = marks[rename]
1108 marks[mark] = marks[rename]
1134 if repo._activebookmark == rename and not inactive:
1109 if repo._activebookmark == rename and not inactive:
1135 bookmarks.activate(repo, mark)
1110 bookmarks.activate(repo, mark)
1136 del marks[rename]
1111 del marks[rename]
1137 elif names:
1112 elif names:
1138 tr = repo.transaction('bookmark')
1113 tr = repo.transaction('bookmark')
1139 newact = None
1114 newact = None
1140 for mark in names:
1115 for mark in names:
1141 mark = checkformat(mark)
1116 mark = checkformat(mark)
1142 if newact is None:
1117 if newact is None:
1143 newact = mark
1118 newact = mark
1144 if inactive and mark == repo._activebookmark:
1119 if inactive and mark == repo._activebookmark:
1145 bookmarks.deactivate(repo)
1120 bookmarks.deactivate(repo)
1146 return
1121 return
1147 tgt = cur
1122 tgt = cur
1148 if rev:
1123 if rev:
1149 tgt = scmutil.revsingle(repo, rev).node()
1124 tgt = scmutil.revsingle(repo, rev).node()
1150 checkconflict(repo, mark, cur, force, tgt)
1125 checkconflict(repo, mark, cur, force, tgt)
1151 marks[mark] = tgt
1126 marks[mark] = tgt
1152 if not inactive and cur == marks[newact] and not rev:
1127 if not inactive and cur == marks[newact] and not rev:
1153 bookmarks.activate(repo, newact)
1128 bookmarks.activate(repo, newact)
1154 elif cur != tgt and newact == repo._activebookmark:
1129 elif cur != tgt and newact == repo._activebookmark:
1155 bookmarks.deactivate(repo)
1130 bookmarks.deactivate(repo)
1156 elif inactive:
1131 elif inactive:
1157 if len(marks) == 0:
1132 if len(marks) == 0:
1158 ui.status(_("no bookmarks set\n"))
1133 ui.status(_("no bookmarks set\n"))
1159 elif not repo._activebookmark:
1134 elif not repo._activebookmark:
1160 ui.status(_("no active bookmark\n"))
1135 ui.status(_("no active bookmark\n"))
1161 else:
1136 else:
1162 bookmarks.deactivate(repo)
1137 bookmarks.deactivate(repo)
1163 if tr is not None:
1138 if tr is not None:
1164 marks.recordchange(tr)
1139 marks.recordchange(tr)
1165 tr.close()
1140 tr.close()
1166 finally:
1141 finally:
1167 lockmod.release(tr, lock, wlock)
1142 lockmod.release(tr, lock, wlock)
1168 else: # show bookmarks
1143 else: # show bookmarks
1169 fm = ui.formatter('bookmarks', opts)
1144 fm = ui.formatter('bookmarks', opts)
1170 hexfn = fm.hexfunc
1145 hexfn = fm.hexfunc
1171 marks = repo._bookmarks
1146 marks = repo._bookmarks
1172 if len(marks) == 0 and fm.isplain():
1147 if len(marks) == 0 and fm.isplain():
1173 ui.status(_("no bookmarks set\n"))
1148 ui.status(_("no bookmarks set\n"))
1174 for bmark, n in sorted(marks.iteritems()):
1149 for bmark, n in sorted(marks.iteritems()):
1175 active = repo._activebookmark
1150 active = repo._activebookmark
1176 if bmark == active:
1151 if bmark == active:
1177 prefix, label = '*', activebookmarklabel
1152 prefix, label = '*', activebookmarklabel
1178 else:
1153 else:
1179 prefix, label = ' ', ''
1154 prefix, label = ' ', ''
1180
1155
1181 fm.startitem()
1156 fm.startitem()
1182 if not ui.quiet:
1157 if not ui.quiet:
1183 fm.plain(' %s ' % prefix, label=label)
1158 fm.plain(' %s ' % prefix, label=label)
1184 fm.write('bookmark', '%s', bmark, label=label)
1159 fm.write('bookmark', '%s', bmark, label=label)
1185 pad = " " * (25 - encoding.colwidth(bmark))
1160 pad = " " * (25 - encoding.colwidth(bmark))
1186 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1161 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1187 repo.changelog.rev(n), hexfn(n), label=label)
1162 repo.changelog.rev(n), hexfn(n), label=label)
1188 fm.data(active=(bmark == active))
1163 fm.data(active=(bmark == active))
1189 fm.plain('\n')
1164 fm.plain('\n')
1190 fm.end()
1165 fm.end()
1191
1166
1192 @command('branch',
1167 @command('branch',
1193 [('f', 'force', None,
1168 [('f', 'force', None,
1194 _('set branch name even if it shadows an existing branch')),
1169 _('set branch name even if it shadows an existing branch')),
1195 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1170 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1196 _('[-fC] [NAME]'))
1171 _('[-fC] [NAME]'))
1197 def branch(ui, repo, label=None, **opts):
1172 def branch(ui, repo, label=None, **opts):
1198 """set or show the current branch name
1173 """set or show the current branch name
1199
1174
1200 .. note::
1175 .. note::
1201
1176
1202 Branch names are permanent and global. Use :hg:`bookmark` to create a
1177 Branch names are permanent and global. Use :hg:`bookmark` to create a
1203 light-weight bookmark instead. See :hg:`help glossary` for more
1178 light-weight bookmark instead. See :hg:`help glossary` for more
1204 information about named branches and bookmarks.
1179 information about named branches and bookmarks.
1205
1180
1206 With no argument, show the current branch name. With one argument,
1181 With no argument, show the current branch name. With one argument,
1207 set the working directory branch name (the branch will not exist
1182 set the working directory branch name (the branch will not exist
1208 in the repository until the next commit). Standard practice
1183 in the repository until the next commit). Standard practice
1209 recommends that primary development take place on the 'default'
1184 recommends that primary development take place on the 'default'
1210 branch.
1185 branch.
1211
1186
1212 Unless -f/--force is specified, branch will not let you set a
1187 Unless -f/--force is specified, branch will not let you set a
1213 branch name that already exists.
1188 branch name that already exists.
1214
1189
1215 Use -C/--clean to reset the working directory branch to that of
1190 Use -C/--clean to reset the working directory branch to that of
1216 the parent of the working directory, negating a previous branch
1191 the parent of the working directory, negating a previous branch
1217 change.
1192 change.
1218
1193
1219 Use the command :hg:`update` to switch to an existing branch. Use
1194 Use the command :hg:`update` to switch to an existing branch. Use
1220 :hg:`commit --close-branch` to mark this branch head as closed.
1195 :hg:`commit --close-branch` to mark this branch head as closed.
1221 When all heads of a branch are closed, the branch will be
1196 When all heads of a branch are closed, the branch will be
1222 considered closed.
1197 considered closed.
1223
1198
1224 Returns 0 on success.
1199 Returns 0 on success.
1225 """
1200 """
1226 if label:
1201 if label:
1227 label = label.strip()
1202 label = label.strip()
1228
1203
1229 if not opts.get('clean') and not label:
1204 if not opts.get('clean') and not label:
1230 ui.write("%s\n" % repo.dirstate.branch())
1205 ui.write("%s\n" % repo.dirstate.branch())
1231 return
1206 return
1232
1207
1233 with repo.wlock():
1208 with repo.wlock():
1234 if opts.get('clean'):
1209 if opts.get('clean'):
1235 label = repo[None].p1().branch()
1210 label = repo[None].p1().branch()
1236 repo.dirstate.setbranch(label)
1211 repo.dirstate.setbranch(label)
1237 ui.status(_('reset working directory to branch %s\n') % label)
1212 ui.status(_('reset working directory to branch %s\n') % label)
1238 elif label:
1213 elif label:
1239 if not opts.get('force') and label in repo.branchmap():
1214 if not opts.get('force') and label in repo.branchmap():
1240 if label not in [p.branch() for p in repo[None].parents()]:
1215 if label not in [p.branch() for p in repo[None].parents()]:
1241 raise error.Abort(_('a branch of the same name already'
1216 raise error.Abort(_('a branch of the same name already'
1242 ' exists'),
1217 ' exists'),
1243 # i18n: "it" refers to an existing branch
1218 # i18n: "it" refers to an existing branch
1244 hint=_("use 'hg update' to switch to it"))
1219 hint=_("use 'hg update' to switch to it"))
1245 scmutil.checknewlabel(repo, label, 'branch')
1220 scmutil.checknewlabel(repo, label, 'branch')
1246 repo.dirstate.setbranch(label)
1221 repo.dirstate.setbranch(label)
1247 ui.status(_('marked working directory as branch %s\n') % label)
1222 ui.status(_('marked working directory as branch %s\n') % label)
1248
1223
1249 # find any open named branches aside from default
1224 # find any open named branches aside from default
1250 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1225 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1251 if n != "default" and not c]
1226 if n != "default" and not c]
1252 if not others:
1227 if not others:
1253 ui.status(_('(branches are permanent and global, '
1228 ui.status(_('(branches are permanent and global, '
1254 'did you want a bookmark?)\n'))
1229 'did you want a bookmark?)\n'))
1255
1230
1256 @command('branches',
1231 @command('branches',
1257 [('a', 'active', False,
1232 [('a', 'active', False,
1258 _('show only branches that have unmerged heads (DEPRECATED)')),
1233 _('show only branches that have unmerged heads (DEPRECATED)')),
1259 ('c', 'closed', False, _('show normal and closed branches')),
1234 ('c', 'closed', False, _('show normal and closed branches')),
1260 ] + formatteropts,
1235 ] + formatteropts,
1261 _('[-c]'))
1236 _('[-c]'))
1262 def branches(ui, repo, active=False, closed=False, **opts):
1237 def branches(ui, repo, active=False, closed=False, **opts):
1263 """list repository named branches
1238 """list repository named branches
1264
1239
1265 List the repository's named branches, indicating which ones are
1240 List the repository's named branches, indicating which ones are
1266 inactive. If -c/--closed is specified, also list branches which have
1241 inactive. If -c/--closed is specified, also list branches which have
1267 been marked closed (see :hg:`commit --close-branch`).
1242 been marked closed (see :hg:`commit --close-branch`).
1268
1243
1269 Use the command :hg:`update` to switch to an existing branch.
1244 Use the command :hg:`update` to switch to an existing branch.
1270
1245
1271 Returns 0.
1246 Returns 0.
1272 """
1247 """
1273
1248
1274 fm = ui.formatter('branches', opts)
1249 fm = ui.formatter('branches', opts)
1275 hexfunc = fm.hexfunc
1250 hexfunc = fm.hexfunc
1276
1251
1277 allheads = set(repo.heads())
1252 allheads = set(repo.heads())
1278 branches = []
1253 branches = []
1279 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1254 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1280 isactive = not isclosed and bool(set(heads) & allheads)
1255 isactive = not isclosed and bool(set(heads) & allheads)
1281 branches.append((tag, repo[tip], isactive, not isclosed))
1256 branches.append((tag, repo[tip], isactive, not isclosed))
1282 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1257 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1283 reverse=True)
1258 reverse=True)
1284
1259
1285 for tag, ctx, isactive, isopen in branches:
1260 for tag, ctx, isactive, isopen in branches:
1286 if active and not isactive:
1261 if active and not isactive:
1287 continue
1262 continue
1288 if isactive:
1263 if isactive:
1289 label = 'branches.active'
1264 label = 'branches.active'
1290 notice = ''
1265 notice = ''
1291 elif not isopen:
1266 elif not isopen:
1292 if not closed:
1267 if not closed:
1293 continue
1268 continue
1294 label = 'branches.closed'
1269 label = 'branches.closed'
1295 notice = _(' (closed)')
1270 notice = _(' (closed)')
1296 else:
1271 else:
1297 label = 'branches.inactive'
1272 label = 'branches.inactive'
1298 notice = _(' (inactive)')
1273 notice = _(' (inactive)')
1299 current = (tag == repo.dirstate.branch())
1274 current = (tag == repo.dirstate.branch())
1300 if current:
1275 if current:
1301 label = 'branches.current'
1276 label = 'branches.current'
1302
1277
1303 fm.startitem()
1278 fm.startitem()
1304 fm.write('branch', '%s', tag, label=label)
1279 fm.write('branch', '%s', tag, label=label)
1305 rev = ctx.rev()
1280 rev = ctx.rev()
1306 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1281 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1307 fmt = ' ' * padsize + ' %d:%s'
1282 fmt = ' ' * padsize + ' %d:%s'
1308 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1283 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1309 label='log.changeset changeset.%s' % ctx.phasestr())
1284 label='log.changeset changeset.%s' % ctx.phasestr())
1310 fm.data(active=isactive, closed=not isopen, current=current)
1285 fm.data(active=isactive, closed=not isopen, current=current)
1311 if not ui.quiet:
1286 if not ui.quiet:
1312 fm.plain(notice)
1287 fm.plain(notice)
1313 fm.plain('\n')
1288 fm.plain('\n')
1314 fm.end()
1289 fm.end()
1315
1290
1316 @command('bundle',
1291 @command('bundle',
1317 [('f', 'force', None, _('run even when the destination is unrelated')),
1292 [('f', 'force', None, _('run even when the destination is unrelated')),
1318 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1293 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1319 _('REV')),
1294 _('REV')),
1320 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1295 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1321 _('BRANCH')),
1296 _('BRANCH')),
1322 ('', 'base', [],
1297 ('', 'base', [],
1323 _('a base changeset assumed to be available at the destination'),
1298 _('a base changeset assumed to be available at the destination'),
1324 _('REV')),
1299 _('REV')),
1325 ('a', 'all', None, _('bundle all changesets in the repository')),
1300 ('a', 'all', None, _('bundle all changesets in the repository')),
1326 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1301 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1327 ] + remoteopts,
1302 ] + remoteopts,
1328 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1303 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1329 def bundle(ui, repo, fname, dest=None, **opts):
1304 def bundle(ui, repo, fname, dest=None, **opts):
1330 """create a changegroup file
1305 """create a changegroup file
1331
1306
1332 Generate a changegroup file collecting changesets to be added
1307 Generate a changegroup file collecting changesets to be added
1333 to a repository.
1308 to a repository.
1334
1309
1335 To create a bundle containing all changesets, use -a/--all
1310 To create a bundle containing all changesets, use -a/--all
1336 (or --base null). Otherwise, hg assumes the destination will have
1311 (or --base null). Otherwise, hg assumes the destination will have
1337 all the nodes you specify with --base parameters. Otherwise, hg
1312 all the nodes you specify with --base parameters. Otherwise, hg
1338 will assume the repository has all the nodes in destination, or
1313 will assume the repository has all the nodes in destination, or
1339 default-push/default if no destination is specified.
1314 default-push/default if no destination is specified.
1340
1315
1341 You can change bundle format with the -t/--type option. You can
1316 You can change bundle format with the -t/--type option. You can
1342 specify a compression, a bundle version or both using a dash
1317 specify a compression, a bundle version or both using a dash
1343 (comp-version). The available compression methods are: none, bzip2,
1318 (comp-version). The available compression methods are: none, bzip2,
1344 and gzip (by default, bundles are compressed using bzip2). The
1319 and gzip (by default, bundles are compressed using bzip2). The
1345 available formats are: v1, v2 (default to most suitable).
1320 available formats are: v1, v2 (default to most suitable).
1346
1321
1347 The bundle file can then be transferred using conventional means
1322 The bundle file can then be transferred using conventional means
1348 and applied to another repository with the unbundle or pull
1323 and applied to another repository with the unbundle or pull
1349 command. This is useful when direct push and pull are not
1324 command. This is useful when direct push and pull are not
1350 available or when exporting an entire repository is undesirable.
1325 available or when exporting an entire repository is undesirable.
1351
1326
1352 Applying bundles preserves all changeset contents including
1327 Applying bundles preserves all changeset contents including
1353 permissions, copy/rename information, and revision history.
1328 permissions, copy/rename information, and revision history.
1354
1329
1355 Returns 0 on success, 1 if no changes found.
1330 Returns 0 on success, 1 if no changes found.
1356 """
1331 """
1357 revs = None
1332 revs = None
1358 if 'rev' in opts:
1333 if 'rev' in opts:
1359 revstrings = opts['rev']
1334 revstrings = opts['rev']
1360 revs = scmutil.revrange(repo, revstrings)
1335 revs = scmutil.revrange(repo, revstrings)
1361 if revstrings and not revs:
1336 if revstrings and not revs:
1362 raise error.Abort(_('no commits to bundle'))
1337 raise error.Abort(_('no commits to bundle'))
1363
1338
1364 bundletype = opts.get('type', 'bzip2').lower()
1339 bundletype = opts.get('type', 'bzip2').lower()
1365 try:
1340 try:
1366 bcompression, cgversion, params = exchange.parsebundlespec(
1341 bcompression, cgversion, params = exchange.parsebundlespec(
1367 repo, bundletype, strict=False)
1342 repo, bundletype, strict=False)
1368 except error.UnsupportedBundleSpecification as e:
1343 except error.UnsupportedBundleSpecification as e:
1369 raise error.Abort(str(e),
1344 raise error.Abort(str(e),
1370 hint=_("see 'hg help bundle' for supported "
1345 hint=_("see 'hg help bundle' for supported "
1371 "values for --type"))
1346 "values for --type"))
1372
1347
1373 # Packed bundles are a pseudo bundle format for now.
1348 # Packed bundles are a pseudo bundle format for now.
1374 if cgversion == 's1':
1349 if cgversion == 's1':
1375 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1350 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1376 hint=_("use 'hg debugcreatestreamclonebundle'"))
1351 hint=_("use 'hg debugcreatestreamclonebundle'"))
1377
1352
1378 if opts.get('all'):
1353 if opts.get('all'):
1379 if dest:
1354 if dest:
1380 raise error.Abort(_("--all is incompatible with specifying "
1355 raise error.Abort(_("--all is incompatible with specifying "
1381 "a destination"))
1356 "a destination"))
1382 if opts.get('base'):
1357 if opts.get('base'):
1383 ui.warn(_("ignoring --base because --all was specified\n"))
1358 ui.warn(_("ignoring --base because --all was specified\n"))
1384 base = ['null']
1359 base = ['null']
1385 else:
1360 else:
1386 base = scmutil.revrange(repo, opts.get('base'))
1361 base = scmutil.revrange(repo, opts.get('base'))
1387 # TODO: get desired bundlecaps from command line.
1362 # TODO: get desired bundlecaps from command line.
1388 bundlecaps = None
1363 bundlecaps = None
1389 if cgversion not in changegroup.supportedoutgoingversions(repo):
1364 if cgversion not in changegroup.supportedoutgoingversions(repo):
1390 raise error.Abort(_("repository does not support bundle version %s") %
1365 raise error.Abort(_("repository does not support bundle version %s") %
1391 cgversion)
1366 cgversion)
1392
1367
1393 if base:
1368 if base:
1394 if dest:
1369 if dest:
1395 raise error.Abort(_("--base is incompatible with specifying "
1370 raise error.Abort(_("--base is incompatible with specifying "
1396 "a destination"))
1371 "a destination"))
1397 common = [repo.lookup(rev) for rev in base]
1372 common = [repo.lookup(rev) for rev in base]
1398 heads = revs and map(repo.lookup, revs) or None
1373 heads = revs and map(repo.lookup, revs) or None
1399 outgoing = discovery.outgoing(repo, common, heads)
1374 outgoing = discovery.outgoing(repo, common, heads)
1400 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1375 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1401 bundlecaps=bundlecaps,
1376 bundlecaps=bundlecaps,
1402 version=cgversion)
1377 version=cgversion)
1403 outgoing = None
1378 outgoing = None
1404 else:
1379 else:
1405 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1380 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1406 dest, branches = hg.parseurl(dest, opts.get('branch'))
1381 dest, branches = hg.parseurl(dest, opts.get('branch'))
1407 other = hg.peer(repo, opts, dest)
1382 other = hg.peer(repo, opts, dest)
1408 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1383 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1409 heads = revs and map(repo.lookup, revs) or revs
1384 heads = revs and map(repo.lookup, revs) or revs
1410 outgoing = discovery.findcommonoutgoing(repo, other,
1385 outgoing = discovery.findcommonoutgoing(repo, other,
1411 onlyheads=heads,
1386 onlyheads=heads,
1412 force=opts.get('force'),
1387 force=opts.get('force'),
1413 portable=True)
1388 portable=True)
1414 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1389 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1415 bundlecaps, version=cgversion)
1390 bundlecaps, version=cgversion)
1416 if not cg:
1391 if not cg:
1417 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1392 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1418 return 1
1393 return 1
1419
1394
1420 if cgversion == '01': #bundle1
1395 if cgversion == '01': #bundle1
1421 if bcompression is None:
1396 if bcompression is None:
1422 bcompression = 'UN'
1397 bcompression = 'UN'
1423 bversion = 'HG10' + bcompression
1398 bversion = 'HG10' + bcompression
1424 bcompression = None
1399 bcompression = None
1425 else:
1400 else:
1426 assert cgversion == '02'
1401 assert cgversion == '02'
1427 bversion = 'HG20'
1402 bversion = 'HG20'
1428
1403
1429 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1404 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1430
1405
1431 @command('cat',
1406 @command('cat',
1432 [('o', 'output', '',
1407 [('o', 'output', '',
1433 _('print output to file with formatted name'), _('FORMAT')),
1408 _('print output to file with formatted name'), _('FORMAT')),
1434 ('r', 'rev', '', _('print the given revision'), _('REV')),
1409 ('r', 'rev', '', _('print the given revision'), _('REV')),
1435 ('', 'decode', None, _('apply any matching decode filter')),
1410 ('', 'decode', None, _('apply any matching decode filter')),
1436 ] + walkopts,
1411 ] + walkopts,
1437 _('[OPTION]... FILE...'),
1412 _('[OPTION]... FILE...'),
1438 inferrepo=True)
1413 inferrepo=True)
1439 def cat(ui, repo, file1, *pats, **opts):
1414 def cat(ui, repo, file1, *pats, **opts):
1440 """output the current or given revision of files
1415 """output the current or given revision of files
1441
1416
1442 Print the specified files as they were at the given revision. If
1417 Print the specified files as they were at the given revision. If
1443 no revision is given, the parent of the working directory is used.
1418 no revision is given, the parent of the working directory is used.
1444
1419
1445 Output may be to a file, in which case the name of the file is
1420 Output may be to a file, in which case the name of the file is
1446 given using a format string. The formatting rules as follows:
1421 given using a format string. The formatting rules as follows:
1447
1422
1448 :``%%``: literal "%" character
1423 :``%%``: literal "%" character
1449 :``%s``: basename of file being printed
1424 :``%s``: basename of file being printed
1450 :``%d``: dirname of file being printed, or '.' if in repository root
1425 :``%d``: dirname of file being printed, or '.' if in repository root
1451 :``%p``: root-relative path name of file being printed
1426 :``%p``: root-relative path name of file being printed
1452 :``%H``: changeset hash (40 hexadecimal digits)
1427 :``%H``: changeset hash (40 hexadecimal digits)
1453 :``%R``: changeset revision number
1428 :``%R``: changeset revision number
1454 :``%h``: short-form changeset hash (12 hexadecimal digits)
1429 :``%h``: short-form changeset hash (12 hexadecimal digits)
1455 :``%r``: zero-padded changeset revision number
1430 :``%r``: zero-padded changeset revision number
1456 :``%b``: basename of the exporting repository
1431 :``%b``: basename of the exporting repository
1457
1432
1458 Returns 0 on success.
1433 Returns 0 on success.
1459 """
1434 """
1460 ctx = scmutil.revsingle(repo, opts.get('rev'))
1435 ctx = scmutil.revsingle(repo, opts.get('rev'))
1461 m = scmutil.match(ctx, (file1,) + pats, opts)
1436 m = scmutil.match(ctx, (file1,) + pats, opts)
1462
1437
1463 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1438 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1464
1439
1465 @command('^clone',
1440 @command('^clone',
1466 [('U', 'noupdate', None, _('the clone will include an empty working '
1441 [('U', 'noupdate', None, _('the clone will include an empty working '
1467 'directory (only a repository)')),
1442 'directory (only a repository)')),
1468 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1443 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1469 _('REV')),
1444 _('REV')),
1470 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1445 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1471 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1446 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1472 ('', 'pull', None, _('use pull protocol to copy metadata')),
1447 ('', 'pull', None, _('use pull protocol to copy metadata')),
1473 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1448 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1474 ] + remoteopts,
1449 ] + remoteopts,
1475 _('[OPTION]... SOURCE [DEST]'),
1450 _('[OPTION]... SOURCE [DEST]'),
1476 norepo=True)
1451 norepo=True)
1477 def clone(ui, source, dest=None, **opts):
1452 def clone(ui, source, dest=None, **opts):
1478 """make a copy of an existing repository
1453 """make a copy of an existing repository
1479
1454
1480 Create a copy of an existing repository in a new directory.
1455 Create a copy of an existing repository in a new directory.
1481
1456
1482 If no destination directory name is specified, it defaults to the
1457 If no destination directory name is specified, it defaults to the
1483 basename of the source.
1458 basename of the source.
1484
1459
1485 The location of the source is added to the new repository's
1460 The location of the source is added to the new repository's
1486 ``.hg/hgrc`` file, as the default to be used for future pulls.
1461 ``.hg/hgrc`` file, as the default to be used for future pulls.
1487
1462
1488 Only local paths and ``ssh://`` URLs are supported as
1463 Only local paths and ``ssh://`` URLs are supported as
1489 destinations. For ``ssh://`` destinations, no working directory or
1464 destinations. For ``ssh://`` destinations, no working directory or
1490 ``.hg/hgrc`` will be created on the remote side.
1465 ``.hg/hgrc`` will be created on the remote side.
1491
1466
1492 If the source repository has a bookmark called '@' set, that
1467 If the source repository has a bookmark called '@' set, that
1493 revision will be checked out in the new repository by default.
1468 revision will be checked out in the new repository by default.
1494
1469
1495 To check out a particular version, use -u/--update, or
1470 To check out a particular version, use -u/--update, or
1496 -U/--noupdate to create a clone with no working directory.
1471 -U/--noupdate to create a clone with no working directory.
1497
1472
1498 To pull only a subset of changesets, specify one or more revisions
1473 To pull only a subset of changesets, specify one or more revisions
1499 identifiers with -r/--rev or branches with -b/--branch. The
1474 identifiers with -r/--rev or branches with -b/--branch. The
1500 resulting clone will contain only the specified changesets and
1475 resulting clone will contain only the specified changesets and
1501 their ancestors. These options (or 'clone src#rev dest') imply
1476 their ancestors. These options (or 'clone src#rev dest') imply
1502 --pull, even for local source repositories.
1477 --pull, even for local source repositories.
1503
1478
1504 .. note::
1479 .. note::
1505
1480
1506 Specifying a tag will include the tagged changeset but not the
1481 Specifying a tag will include the tagged changeset but not the
1507 changeset containing the tag.
1482 changeset containing the tag.
1508
1483
1509 .. container:: verbose
1484 .. container:: verbose
1510
1485
1511 For efficiency, hardlinks are used for cloning whenever the
1486 For efficiency, hardlinks are used for cloning whenever the
1512 source and destination are on the same filesystem (note this
1487 source and destination are on the same filesystem (note this
1513 applies only to the repository data, not to the working
1488 applies only to the repository data, not to the working
1514 directory). Some filesystems, such as AFS, implement hardlinking
1489 directory). Some filesystems, such as AFS, implement hardlinking
1515 incorrectly, but do not report errors. In these cases, use the
1490 incorrectly, but do not report errors. In these cases, use the
1516 --pull option to avoid hardlinking.
1491 --pull option to avoid hardlinking.
1517
1492
1518 In some cases, you can clone repositories and the working
1493 In some cases, you can clone repositories and the working
1519 directory using full hardlinks with ::
1494 directory using full hardlinks with ::
1520
1495
1521 $ cp -al REPO REPOCLONE
1496 $ cp -al REPO REPOCLONE
1522
1497
1523 This is the fastest way to clone, but it is not always safe. The
1498 This is the fastest way to clone, but it is not always safe. The
1524 operation is not atomic (making sure REPO is not modified during
1499 operation is not atomic (making sure REPO is not modified during
1525 the operation is up to you) and you have to make sure your
1500 the operation is up to you) and you have to make sure your
1526 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1501 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1527 so). Also, this is not compatible with certain extensions that
1502 so). Also, this is not compatible with certain extensions that
1528 place their metadata under the .hg directory, such as mq.
1503 place their metadata under the .hg directory, such as mq.
1529
1504
1530 Mercurial will update the working directory to the first applicable
1505 Mercurial will update the working directory to the first applicable
1531 revision from this list:
1506 revision from this list:
1532
1507
1533 a) null if -U or the source repository has no changesets
1508 a) null if -U or the source repository has no changesets
1534 b) if -u . and the source repository is local, the first parent of
1509 b) if -u . and the source repository is local, the first parent of
1535 the source repository's working directory
1510 the source repository's working directory
1536 c) the changeset specified with -u (if a branch name, this means the
1511 c) the changeset specified with -u (if a branch name, this means the
1537 latest head of that branch)
1512 latest head of that branch)
1538 d) the changeset specified with -r
1513 d) the changeset specified with -r
1539 e) the tipmost head specified with -b
1514 e) the tipmost head specified with -b
1540 f) the tipmost head specified with the url#branch source syntax
1515 f) the tipmost head specified with the url#branch source syntax
1541 g) the revision marked with the '@' bookmark, if present
1516 g) the revision marked with the '@' bookmark, if present
1542 h) the tipmost head of the default branch
1517 h) the tipmost head of the default branch
1543 i) tip
1518 i) tip
1544
1519
1545 When cloning from servers that support it, Mercurial may fetch
1520 When cloning from servers that support it, Mercurial may fetch
1546 pre-generated data from a server-advertised URL. When this is done,
1521 pre-generated data from a server-advertised URL. When this is done,
1547 hooks operating on incoming changesets and changegroups may fire twice,
1522 hooks operating on incoming changesets and changegroups may fire twice,
1548 once for the bundle fetched from the URL and another for any additional
1523 once for the bundle fetched from the URL and another for any additional
1549 data not fetched from this URL. In addition, if an error occurs, the
1524 data not fetched from this URL. In addition, if an error occurs, the
1550 repository may be rolled back to a partial clone. This behavior may
1525 repository may be rolled back to a partial clone. This behavior may
1551 change in future releases. See :hg:`help -e clonebundles` for more.
1526 change in future releases. See :hg:`help -e clonebundles` for more.
1552
1527
1553 Examples:
1528 Examples:
1554
1529
1555 - clone a remote repository to a new directory named hg/::
1530 - clone a remote repository to a new directory named hg/::
1556
1531
1557 hg clone http://selenic.com/hg
1532 hg clone http://selenic.com/hg
1558
1533
1559 - create a lightweight local clone::
1534 - create a lightweight local clone::
1560
1535
1561 hg clone project/ project-feature/
1536 hg clone project/ project-feature/
1562
1537
1563 - clone from an absolute path on an ssh server (note double-slash)::
1538 - clone from an absolute path on an ssh server (note double-slash)::
1564
1539
1565 hg clone ssh://user@server//home/projects/alpha/
1540 hg clone ssh://user@server//home/projects/alpha/
1566
1541
1567 - do a high-speed clone over a LAN while checking out a
1542 - do a high-speed clone over a LAN while checking out a
1568 specified version::
1543 specified version::
1569
1544
1570 hg clone --uncompressed http://server/repo -u 1.5
1545 hg clone --uncompressed http://server/repo -u 1.5
1571
1546
1572 - create a repository without changesets after a particular revision::
1547 - create a repository without changesets after a particular revision::
1573
1548
1574 hg clone -r 04e544 experimental/ good/
1549 hg clone -r 04e544 experimental/ good/
1575
1550
1576 - clone (and track) a particular named branch::
1551 - clone (and track) a particular named branch::
1577
1552
1578 hg clone http://selenic.com/hg#stable
1553 hg clone http://selenic.com/hg#stable
1579
1554
1580 See :hg:`help urls` for details on specifying URLs.
1555 See :hg:`help urls` for details on specifying URLs.
1581
1556
1582 Returns 0 on success.
1557 Returns 0 on success.
1583 """
1558 """
1584 if opts.get('noupdate') and opts.get('updaterev'):
1559 if opts.get('noupdate') and opts.get('updaterev'):
1585 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1560 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1586
1561
1587 r = hg.clone(ui, opts, source, dest,
1562 r = hg.clone(ui, opts, source, dest,
1588 pull=opts.get('pull'),
1563 pull=opts.get('pull'),
1589 stream=opts.get('uncompressed'),
1564 stream=opts.get('uncompressed'),
1590 rev=opts.get('rev'),
1565 rev=opts.get('rev'),
1591 update=opts.get('updaterev') or not opts.get('noupdate'),
1566 update=opts.get('updaterev') or not opts.get('noupdate'),
1592 branch=opts.get('branch'),
1567 branch=opts.get('branch'),
1593 shareopts=opts.get('shareopts'))
1568 shareopts=opts.get('shareopts'))
1594
1569
1595 return r is None
1570 return r is None
1596
1571
1597 @command('^commit|ci',
1572 @command('^commit|ci',
1598 [('A', 'addremove', None,
1573 [('A', 'addremove', None,
1599 _('mark new/missing files as added/removed before committing')),
1574 _('mark new/missing files as added/removed before committing')),
1600 ('', 'close-branch', None,
1575 ('', 'close-branch', None,
1601 _('mark a branch head as closed')),
1576 _('mark a branch head as closed')),
1602 ('', 'amend', None, _('amend the parent of the working directory')),
1577 ('', 'amend', None, _('amend the parent of the working directory')),
1603 ('s', 'secret', None, _('use the secret phase for committing')),
1578 ('s', 'secret', None, _('use the secret phase for committing')),
1604 ('e', 'edit', None, _('invoke editor on commit messages')),
1579 ('e', 'edit', None, _('invoke editor on commit messages')),
1605 ('i', 'interactive', None, _('use interactive mode')),
1580 ('i', 'interactive', None, _('use interactive mode')),
1606 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1581 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1607 _('[OPTION]... [FILE]...'),
1582 _('[OPTION]... [FILE]...'),
1608 inferrepo=True)
1583 inferrepo=True)
1609 def commit(ui, repo, *pats, **opts):
1584 def commit(ui, repo, *pats, **opts):
1610 """commit the specified files or all outstanding changes
1585 """commit the specified files or all outstanding changes
1611
1586
1612 Commit changes to the given files into the repository. Unlike a
1587 Commit changes to the given files into the repository. Unlike a
1613 centralized SCM, this operation is a local operation. See
1588 centralized SCM, this operation is a local operation. See
1614 :hg:`push` for a way to actively distribute your changes.
1589 :hg:`push` for a way to actively distribute your changes.
1615
1590
1616 If a list of files is omitted, all changes reported by :hg:`status`
1591 If a list of files is omitted, all changes reported by :hg:`status`
1617 will be committed.
1592 will be committed.
1618
1593
1619 If you are committing the result of a merge, do not provide any
1594 If you are committing the result of a merge, do not provide any
1620 filenames or -I/-X filters.
1595 filenames or -I/-X filters.
1621
1596
1622 If no commit message is specified, Mercurial starts your
1597 If no commit message is specified, Mercurial starts your
1623 configured editor where you can enter a message. In case your
1598 configured editor where you can enter a message. In case your
1624 commit fails, you will find a backup of your message in
1599 commit fails, you will find a backup of your message in
1625 ``.hg/last-message.txt``.
1600 ``.hg/last-message.txt``.
1626
1601
1627 The --close-branch flag can be used to mark the current branch
1602 The --close-branch flag can be used to mark the current branch
1628 head closed. When all heads of a branch are closed, the branch
1603 head closed. When all heads of a branch are closed, the branch
1629 will be considered closed and no longer listed.
1604 will be considered closed and no longer listed.
1630
1605
1631 The --amend flag can be used to amend the parent of the
1606 The --amend flag can be used to amend the parent of the
1632 working directory with a new commit that contains the changes
1607 working directory with a new commit that contains the changes
1633 in the parent in addition to those currently reported by :hg:`status`,
1608 in the parent in addition to those currently reported by :hg:`status`,
1634 if there are any. The old commit is stored in a backup bundle in
1609 if there are any. The old commit is stored in a backup bundle in
1635 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1610 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1636 on how to restore it).
1611 on how to restore it).
1637
1612
1638 Message, user and date are taken from the amended commit unless
1613 Message, user and date are taken from the amended commit unless
1639 specified. When a message isn't specified on the command line,
1614 specified. When a message isn't specified on the command line,
1640 the editor will open with the message of the amended commit.
1615 the editor will open with the message of the amended commit.
1641
1616
1642 It is not possible to amend public changesets (see :hg:`help phases`)
1617 It is not possible to amend public changesets (see :hg:`help phases`)
1643 or changesets that have children.
1618 or changesets that have children.
1644
1619
1645 See :hg:`help dates` for a list of formats valid for -d/--date.
1620 See :hg:`help dates` for a list of formats valid for -d/--date.
1646
1621
1647 Returns 0 on success, 1 if nothing changed.
1622 Returns 0 on success, 1 if nothing changed.
1648
1623
1649 .. container:: verbose
1624 .. container:: verbose
1650
1625
1651 Examples:
1626 Examples:
1652
1627
1653 - commit all files ending in .py::
1628 - commit all files ending in .py::
1654
1629
1655 hg commit --include "set:**.py"
1630 hg commit --include "set:**.py"
1656
1631
1657 - commit all non-binary files::
1632 - commit all non-binary files::
1658
1633
1659 hg commit --exclude "set:binary()"
1634 hg commit --exclude "set:binary()"
1660
1635
1661 - amend the current commit and set the date to now::
1636 - amend the current commit and set the date to now::
1662
1637
1663 hg commit --amend --date now
1638 hg commit --amend --date now
1664 """
1639 """
1665 wlock = lock = None
1640 wlock = lock = None
1666 try:
1641 try:
1667 wlock = repo.wlock()
1642 wlock = repo.wlock()
1668 lock = repo.lock()
1643 lock = repo.lock()
1669 return _docommit(ui, repo, *pats, **opts)
1644 return _docommit(ui, repo, *pats, **opts)
1670 finally:
1645 finally:
1671 release(lock, wlock)
1646 release(lock, wlock)
1672
1647
1673 def _docommit(ui, repo, *pats, **opts):
1648 def _docommit(ui, repo, *pats, **opts):
1674 if opts.get('interactive'):
1649 if opts.get('interactive'):
1675 opts.pop('interactive')
1650 opts.pop('interactive')
1676 cmdutil.dorecord(ui, repo, commit, None, False,
1651 cmdutil.dorecord(ui, repo, commit, None, False,
1677 cmdutil.recordfilter, *pats, **opts)
1652 cmdutil.recordfilter, *pats, **opts)
1678 return
1653 return
1679
1654
1680 if opts.get('subrepos'):
1655 if opts.get('subrepos'):
1681 if opts.get('amend'):
1656 if opts.get('amend'):
1682 raise error.Abort(_('cannot amend with --subrepos'))
1657 raise error.Abort(_('cannot amend with --subrepos'))
1683 # Let --subrepos on the command line override config setting.
1658 # Let --subrepos on the command line override config setting.
1684 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1659 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1685
1660
1686 cmdutil.checkunfinished(repo, commit=True)
1661 cmdutil.checkunfinished(repo, commit=True)
1687
1662
1688 branch = repo[None].branch()
1663 branch = repo[None].branch()
1689 bheads = repo.branchheads(branch)
1664 bheads = repo.branchheads(branch)
1690
1665
1691 extra = {}
1666 extra = {}
1692 if opts.get('close_branch'):
1667 if opts.get('close_branch'):
1693 extra['close'] = 1
1668 extra['close'] = 1
1694
1669
1695 if not bheads:
1670 if not bheads:
1696 raise error.Abort(_('can only close branch heads'))
1671 raise error.Abort(_('can only close branch heads'))
1697 elif opts.get('amend'):
1672 elif opts.get('amend'):
1698 if repo[None].parents()[0].p1().branch() != branch and \
1673 if repo[None].parents()[0].p1().branch() != branch and \
1699 repo[None].parents()[0].p2().branch() != branch:
1674 repo[None].parents()[0].p2().branch() != branch:
1700 raise error.Abort(_('can only close branch heads'))
1675 raise error.Abort(_('can only close branch heads'))
1701
1676
1702 if opts.get('amend'):
1677 if opts.get('amend'):
1703 if ui.configbool('ui', 'commitsubrepos'):
1678 if ui.configbool('ui', 'commitsubrepos'):
1704 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1679 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1705
1680
1706 old = repo['.']
1681 old = repo['.']
1707 if not old.mutable():
1682 if not old.mutable():
1708 raise error.Abort(_('cannot amend public changesets'))
1683 raise error.Abort(_('cannot amend public changesets'))
1709 if len(repo[None].parents()) > 1:
1684 if len(repo[None].parents()) > 1:
1710 raise error.Abort(_('cannot amend while merging'))
1685 raise error.Abort(_('cannot amend while merging'))
1711 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1686 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1712 if not allowunstable and old.children():
1687 if not allowunstable and old.children():
1713 raise error.Abort(_('cannot amend changeset with children'))
1688 raise error.Abort(_('cannot amend changeset with children'))
1714
1689
1715 # Currently histedit gets confused if an amend happens while histedit
1690 # Currently histedit gets confused if an amend happens while histedit
1716 # is in progress. Since we have a checkunfinished command, we are
1691 # is in progress. Since we have a checkunfinished command, we are
1717 # temporarily honoring it.
1692 # temporarily honoring it.
1718 #
1693 #
1719 # Note: eventually this guard will be removed. Please do not expect
1694 # Note: eventually this guard will be removed. Please do not expect
1720 # this behavior to remain.
1695 # this behavior to remain.
1721 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1696 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1722 cmdutil.checkunfinished(repo)
1697 cmdutil.checkunfinished(repo)
1723
1698
1724 # commitfunc is used only for temporary amend commit by cmdutil.amend
1699 # commitfunc is used only for temporary amend commit by cmdutil.amend
1725 def commitfunc(ui, repo, message, match, opts):
1700 def commitfunc(ui, repo, message, match, opts):
1726 return repo.commit(message,
1701 return repo.commit(message,
1727 opts.get('user') or old.user(),
1702 opts.get('user') or old.user(),
1728 opts.get('date') or old.date(),
1703 opts.get('date') or old.date(),
1729 match,
1704 match,
1730 extra=extra)
1705 extra=extra)
1731
1706
1732 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1707 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1733 if node == old.node():
1708 if node == old.node():
1734 ui.status(_("nothing changed\n"))
1709 ui.status(_("nothing changed\n"))
1735 return 1
1710 return 1
1736 else:
1711 else:
1737 def commitfunc(ui, repo, message, match, opts):
1712 def commitfunc(ui, repo, message, match, opts):
1738 backup = ui.backupconfig('phases', 'new-commit')
1713 backup = ui.backupconfig('phases', 'new-commit')
1739 baseui = repo.baseui
1714 baseui = repo.baseui
1740 basebackup = baseui.backupconfig('phases', 'new-commit')
1715 basebackup = baseui.backupconfig('phases', 'new-commit')
1741 try:
1716 try:
1742 if opts.get('secret'):
1717 if opts.get('secret'):
1743 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1718 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1744 # Propagate to subrepos
1719 # Propagate to subrepos
1745 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1720 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1746
1721
1747 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1722 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1748 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1723 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1749 return repo.commit(message, opts.get('user'), opts.get('date'),
1724 return repo.commit(message, opts.get('user'), opts.get('date'),
1750 match,
1725 match,
1751 editor=editor,
1726 editor=editor,
1752 extra=extra)
1727 extra=extra)
1753 finally:
1728 finally:
1754 ui.restoreconfig(backup)
1729 ui.restoreconfig(backup)
1755 repo.baseui.restoreconfig(basebackup)
1730 repo.baseui.restoreconfig(basebackup)
1756
1731
1757
1732
1758 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1733 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1759
1734
1760 if not node:
1735 if not node:
1761 stat = cmdutil.postcommitstatus(repo, pats, opts)
1736 stat = cmdutil.postcommitstatus(repo, pats, opts)
1762 if stat[3]:
1737 if stat[3]:
1763 ui.status(_("nothing changed (%d missing files, see "
1738 ui.status(_("nothing changed (%d missing files, see "
1764 "'hg status')\n") % len(stat[3]))
1739 "'hg status')\n") % len(stat[3]))
1765 else:
1740 else:
1766 ui.status(_("nothing changed\n"))
1741 ui.status(_("nothing changed\n"))
1767 return 1
1742 return 1
1768
1743
1769 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1744 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1770
1745
1771 @command('config|showconfig|debugconfig',
1746 @command('config|showconfig|debugconfig',
1772 [('u', 'untrusted', None, _('show untrusted configuration options')),
1747 [('u', 'untrusted', None, _('show untrusted configuration options')),
1773 ('e', 'edit', None, _('edit user config')),
1748 ('e', 'edit', None, _('edit user config')),
1774 ('l', 'local', None, _('edit repository config')),
1749 ('l', 'local', None, _('edit repository config')),
1775 ('g', 'global', None, _('edit global config'))] + formatteropts,
1750 ('g', 'global', None, _('edit global config'))] + formatteropts,
1776 _('[-u] [NAME]...'),
1751 _('[-u] [NAME]...'),
1777 optionalrepo=True)
1752 optionalrepo=True)
1778 def config(ui, repo, *values, **opts):
1753 def config(ui, repo, *values, **opts):
1779 """show combined config settings from all hgrc files
1754 """show combined config settings from all hgrc files
1780
1755
1781 With no arguments, print names and values of all config items.
1756 With no arguments, print names and values of all config items.
1782
1757
1783 With one argument of the form section.name, print just the value
1758 With one argument of the form section.name, print just the value
1784 of that config item.
1759 of that config item.
1785
1760
1786 With multiple arguments, print names and values of all config
1761 With multiple arguments, print names and values of all config
1787 items with matching section names.
1762 items with matching section names.
1788
1763
1789 With --edit, start an editor on the user-level config file. With
1764 With --edit, start an editor on the user-level config file. With
1790 --global, edit the system-wide config file. With --local, edit the
1765 --global, edit the system-wide config file. With --local, edit the
1791 repository-level config file.
1766 repository-level config file.
1792
1767
1793 With --debug, the source (filename and line number) is printed
1768 With --debug, the source (filename and line number) is printed
1794 for each config item.
1769 for each config item.
1795
1770
1796 See :hg:`help config` for more information about config files.
1771 See :hg:`help config` for more information about config files.
1797
1772
1798 Returns 0 on success, 1 if NAME does not exist.
1773 Returns 0 on success, 1 if NAME does not exist.
1799
1774
1800 """
1775 """
1801
1776
1802 if opts.get('edit') or opts.get('local') or opts.get('global'):
1777 if opts.get('edit') or opts.get('local') or opts.get('global'):
1803 if opts.get('local') and opts.get('global'):
1778 if opts.get('local') and opts.get('global'):
1804 raise error.Abort(_("can't use --local and --global together"))
1779 raise error.Abort(_("can't use --local and --global together"))
1805
1780
1806 if opts.get('local'):
1781 if opts.get('local'):
1807 if not repo:
1782 if not repo:
1808 raise error.Abort(_("can't use --local outside a repository"))
1783 raise error.Abort(_("can't use --local outside a repository"))
1809 paths = [repo.join('hgrc')]
1784 paths = [repo.join('hgrc')]
1810 elif opts.get('global'):
1785 elif opts.get('global'):
1811 paths = scmutil.systemrcpath()
1786 paths = scmutil.systemrcpath()
1812 else:
1787 else:
1813 paths = scmutil.userrcpath()
1788 paths = scmutil.userrcpath()
1814
1789
1815 for f in paths:
1790 for f in paths:
1816 if os.path.exists(f):
1791 if os.path.exists(f):
1817 break
1792 break
1818 else:
1793 else:
1819 if opts.get('global'):
1794 if opts.get('global'):
1820 samplehgrc = uimod.samplehgrcs['global']
1795 samplehgrc = uimod.samplehgrcs['global']
1821 elif opts.get('local'):
1796 elif opts.get('local'):
1822 samplehgrc = uimod.samplehgrcs['local']
1797 samplehgrc = uimod.samplehgrcs['local']
1823 else:
1798 else:
1824 samplehgrc = uimod.samplehgrcs['user']
1799 samplehgrc = uimod.samplehgrcs['user']
1825
1800
1826 f = paths[0]
1801 f = paths[0]
1827 fp = open(f, "w")
1802 fp = open(f, "w")
1828 fp.write(samplehgrc)
1803 fp.write(samplehgrc)
1829 fp.close()
1804 fp.close()
1830
1805
1831 editor = ui.geteditor()
1806 editor = ui.geteditor()
1832 ui.system("%s \"%s\"" % (editor, f),
1807 ui.system("%s \"%s\"" % (editor, f),
1833 onerr=error.Abort, errprefix=_("edit failed"))
1808 onerr=error.Abort, errprefix=_("edit failed"))
1834 return
1809 return
1835
1810
1836 fm = ui.formatter('config', opts)
1811 fm = ui.formatter('config', opts)
1837 for f in scmutil.rcpath():
1812 for f in scmutil.rcpath():
1838 ui.debug('read config from: %s\n' % f)
1813 ui.debug('read config from: %s\n' % f)
1839 untrusted = bool(opts.get('untrusted'))
1814 untrusted = bool(opts.get('untrusted'))
1840 if values:
1815 if values:
1841 sections = [v for v in values if '.' not in v]
1816 sections = [v for v in values if '.' not in v]
1842 items = [v for v in values if '.' in v]
1817 items = [v for v in values if '.' in v]
1843 if len(items) > 1 or items and sections:
1818 if len(items) > 1 or items and sections:
1844 raise error.Abort(_('only one config item permitted'))
1819 raise error.Abort(_('only one config item permitted'))
1845 matched = False
1820 matched = False
1846 for section, name, value in ui.walkconfig(untrusted=untrusted):
1821 for section, name, value in ui.walkconfig(untrusted=untrusted):
1847 value = str(value)
1822 value = str(value)
1848 if fm.isplain():
1823 if fm.isplain():
1849 value = value.replace('\n', '\\n')
1824 value = value.replace('\n', '\\n')
1850 entryname = section + '.' + name
1825 entryname = section + '.' + name
1851 if values:
1826 if values:
1852 for v in values:
1827 for v in values:
1853 if v == section:
1828 if v == section:
1854 fm.startitem()
1829 fm.startitem()
1855 fm.condwrite(ui.debugflag, 'source', '%s: ',
1830 fm.condwrite(ui.debugflag, 'source', '%s: ',
1856 ui.configsource(section, name, untrusted))
1831 ui.configsource(section, name, untrusted))
1857 fm.write('name value', '%s=%s\n', entryname, value)
1832 fm.write('name value', '%s=%s\n', entryname, value)
1858 matched = True
1833 matched = True
1859 elif v == entryname:
1834 elif v == entryname:
1860 fm.startitem()
1835 fm.startitem()
1861 fm.condwrite(ui.debugflag, 'source', '%s: ',
1836 fm.condwrite(ui.debugflag, 'source', '%s: ',
1862 ui.configsource(section, name, untrusted))
1837 ui.configsource(section, name, untrusted))
1863 fm.write('value', '%s\n', value)
1838 fm.write('value', '%s\n', value)
1864 fm.data(name=entryname)
1839 fm.data(name=entryname)
1865 matched = True
1840 matched = True
1866 else:
1841 else:
1867 fm.startitem()
1842 fm.startitem()
1868 fm.condwrite(ui.debugflag, 'source', '%s: ',
1843 fm.condwrite(ui.debugflag, 'source', '%s: ',
1869 ui.configsource(section, name, untrusted))
1844 ui.configsource(section, name, untrusted))
1870 fm.write('name value', '%s=%s\n', entryname, value)
1845 fm.write('name value', '%s=%s\n', entryname, value)
1871 matched = True
1846 matched = True
1872 fm.end()
1847 fm.end()
1873 if matched:
1848 if matched:
1874 return 0
1849 return 0
1875 return 1
1850 return 1
1876
1851
1877 @command('copy|cp',
1852 @command('copy|cp',
1878 [('A', 'after', None, _('record a copy that has already occurred')),
1853 [('A', 'after', None, _('record a copy that has already occurred')),
1879 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1854 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1880 ] + walkopts + dryrunopts,
1855 ] + walkopts + dryrunopts,
1881 _('[OPTION]... [SOURCE]... DEST'))
1856 _('[OPTION]... [SOURCE]... DEST'))
1882 def copy(ui, repo, *pats, **opts):
1857 def copy(ui, repo, *pats, **opts):
1883 """mark files as copied for the next commit
1858 """mark files as copied for the next commit
1884
1859
1885 Mark dest as having copies of source files. If dest is a
1860 Mark dest as having copies of source files. If dest is a
1886 directory, copies are put in that directory. If dest is a file,
1861 directory, copies are put in that directory. If dest is a file,
1887 the source must be a single file.
1862 the source must be a single file.
1888
1863
1889 By default, this command copies the contents of files as they
1864 By default, this command copies the contents of files as they
1890 exist in the working directory. If invoked with -A/--after, the
1865 exist in the working directory. If invoked with -A/--after, the
1891 operation is recorded, but no copying is performed.
1866 operation is recorded, but no copying is performed.
1892
1867
1893 This command takes effect with the next commit. To undo a copy
1868 This command takes effect with the next commit. To undo a copy
1894 before that, see :hg:`revert`.
1869 before that, see :hg:`revert`.
1895
1870
1896 Returns 0 on success, 1 if errors are encountered.
1871 Returns 0 on success, 1 if errors are encountered.
1897 """
1872 """
1898 with repo.wlock(False):
1873 with repo.wlock(False):
1899 return cmdutil.copy(ui, repo, pats, opts)
1874 return cmdutil.copy(ui, repo, pats, opts)
1900
1875
1901 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1876 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1902 def debugancestor(ui, repo, *args):
1877 def debugancestor(ui, repo, *args):
1903 """find the ancestor revision of two revisions in a given index"""
1878 """find the ancestor revision of two revisions in a given index"""
1904 if len(args) == 3:
1879 if len(args) == 3:
1905 index, rev1, rev2 = args
1880 index, rev1, rev2 = args
1906 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1881 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1907 lookup = r.lookup
1882 lookup = r.lookup
1908 elif len(args) == 2:
1883 elif len(args) == 2:
1909 if not repo:
1884 if not repo:
1910 raise error.Abort(_("there is no Mercurial repository here "
1885 raise error.Abort(_("there is no Mercurial repository here "
1911 "(.hg not found)"))
1886 "(.hg not found)"))
1912 rev1, rev2 = args
1887 rev1, rev2 = args
1913 r = repo.changelog
1888 r = repo.changelog
1914 lookup = repo.lookup
1889 lookup = repo.lookup
1915 else:
1890 else:
1916 raise error.Abort(_('either two or three arguments required'))
1891 raise error.Abort(_('either two or three arguments required'))
1917 a = r.ancestor(lookup(rev1), lookup(rev2))
1892 a = r.ancestor(lookup(rev1), lookup(rev2))
1918 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1893 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1919
1894
1920 @command('debugbuilddag',
1895 @command('debugbuilddag',
1921 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1896 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1922 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1897 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1923 ('n', 'new-file', None, _('add new file at each rev'))],
1898 ('n', 'new-file', None, _('add new file at each rev'))],
1924 _('[OPTION]... [TEXT]'))
1899 _('[OPTION]... [TEXT]'))
1925 def debugbuilddag(ui, repo, text=None,
1900 def debugbuilddag(ui, repo, text=None,
1926 mergeable_file=False,
1901 mergeable_file=False,
1927 overwritten_file=False,
1902 overwritten_file=False,
1928 new_file=False):
1903 new_file=False):
1929 """builds a repo with a given DAG from scratch in the current empty repo
1904 """builds a repo with a given DAG from scratch in the current empty repo
1930
1905
1931 The description of the DAG is read from stdin if not given on the
1906 The description of the DAG is read from stdin if not given on the
1932 command line.
1907 command line.
1933
1908
1934 Elements:
1909 Elements:
1935
1910
1936 - "+n" is a linear run of n nodes based on the current default parent
1911 - "+n" is a linear run of n nodes based on the current default parent
1937 - "." is a single node based on the current default parent
1912 - "." is a single node based on the current default parent
1938 - "$" resets the default parent to null (implied at the start);
1913 - "$" resets the default parent to null (implied at the start);
1939 otherwise the default parent is always the last node created
1914 otherwise the default parent is always the last node created
1940 - "<p" sets the default parent to the backref p
1915 - "<p" sets the default parent to the backref p
1941 - "*p" is a fork at parent p, which is a backref
1916 - "*p" is a fork at parent p, which is a backref
1942 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1917 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1943 - "/p2" is a merge of the preceding node and p2
1918 - "/p2" is a merge of the preceding node and p2
1944 - ":tag" defines a local tag for the preceding node
1919 - ":tag" defines a local tag for the preceding node
1945 - "@branch" sets the named branch for subsequent nodes
1920 - "@branch" sets the named branch for subsequent nodes
1946 - "#...\\n" is a comment up to the end of the line
1921 - "#...\\n" is a comment up to the end of the line
1947
1922
1948 Whitespace between the above elements is ignored.
1923 Whitespace between the above elements is ignored.
1949
1924
1950 A backref is either
1925 A backref is either
1951
1926
1952 - a number n, which references the node curr-n, where curr is the current
1927 - a number n, which references the node curr-n, where curr is the current
1953 node, or
1928 node, or
1954 - the name of a local tag you placed earlier using ":tag", or
1929 - the name of a local tag you placed earlier using ":tag", or
1955 - empty to denote the default parent.
1930 - empty to denote the default parent.
1956
1931
1957 All string valued-elements are either strictly alphanumeric, or must
1932 All string valued-elements are either strictly alphanumeric, or must
1958 be enclosed in double quotes ("..."), with "\\" as escape character.
1933 be enclosed in double quotes ("..."), with "\\" as escape character.
1959 """
1934 """
1960
1935
1961 if text is None:
1936 if text is None:
1962 ui.status(_("reading DAG from stdin\n"))
1937 ui.status(_("reading DAG from stdin\n"))
1963 text = ui.fin.read()
1938 text = ui.fin.read()
1964
1939
1965 cl = repo.changelog
1940 cl = repo.changelog
1966 if len(cl) > 0:
1941 if len(cl) > 0:
1967 raise error.Abort(_('repository is not empty'))
1942 raise error.Abort(_('repository is not empty'))
1968
1943
1969 # determine number of revs in DAG
1944 # determine number of revs in DAG
1970 total = 0
1945 total = 0
1971 for type, data in dagparser.parsedag(text):
1946 for type, data in dagparser.parsedag(text):
1972 if type == 'n':
1947 if type == 'n':
1973 total += 1
1948 total += 1
1974
1949
1975 if mergeable_file:
1950 if mergeable_file:
1976 linesperrev = 2
1951 linesperrev = 2
1977 # make a file with k lines per rev
1952 # make a file with k lines per rev
1978 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1953 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1979 initialmergedlines.append("")
1954 initialmergedlines.append("")
1980
1955
1981 tags = []
1956 tags = []
1982
1957
1983 wlock = lock = tr = None
1958 wlock = lock = tr = None
1984 try:
1959 try:
1985 wlock = repo.wlock()
1960 wlock = repo.wlock()
1986 lock = repo.lock()
1961 lock = repo.lock()
1987 tr = repo.transaction("builddag")
1962 tr = repo.transaction("builddag")
1988
1963
1989 at = -1
1964 at = -1
1990 atbranch = 'default'
1965 atbranch = 'default'
1991 nodeids = []
1966 nodeids = []
1992 id = 0
1967 id = 0
1993 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1968 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1994 for type, data in dagparser.parsedag(text):
1969 for type, data in dagparser.parsedag(text):
1995 if type == 'n':
1970 if type == 'n':
1996 ui.note(('node %s\n' % str(data)))
1971 ui.note(('node %s\n' % str(data)))
1997 id, ps = data
1972 id, ps = data
1998
1973
1999 files = []
1974 files = []
2000 fctxs = {}
1975 fctxs = {}
2001
1976
2002 p2 = None
1977 p2 = None
2003 if mergeable_file:
1978 if mergeable_file:
2004 fn = "mf"
1979 fn = "mf"
2005 p1 = repo[ps[0]]
1980 p1 = repo[ps[0]]
2006 if len(ps) > 1:
1981 if len(ps) > 1:
2007 p2 = repo[ps[1]]
1982 p2 = repo[ps[1]]
2008 pa = p1.ancestor(p2)
1983 pa = p1.ancestor(p2)
2009 base, local, other = [x[fn].data() for x in (pa, p1,
1984 base, local, other = [x[fn].data() for x in (pa, p1,
2010 p2)]
1985 p2)]
2011 m3 = simplemerge.Merge3Text(base, local, other)
1986 m3 = simplemerge.Merge3Text(base, local, other)
2012 ml = [l.strip() for l in m3.merge_lines()]
1987 ml = [l.strip() for l in m3.merge_lines()]
2013 ml.append("")
1988 ml.append("")
2014 elif at > 0:
1989 elif at > 0:
2015 ml = p1[fn].data().split("\n")
1990 ml = p1[fn].data().split("\n")
2016 else:
1991 else:
2017 ml = initialmergedlines
1992 ml = initialmergedlines
2018 ml[id * linesperrev] += " r%i" % id
1993 ml[id * linesperrev] += " r%i" % id
2019 mergedtext = "\n".join(ml)
1994 mergedtext = "\n".join(ml)
2020 files.append(fn)
1995 files.append(fn)
2021 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1996 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
2022
1997
2023 if overwritten_file:
1998 if overwritten_file:
2024 fn = "of"
1999 fn = "of"
2025 files.append(fn)
2000 files.append(fn)
2026 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2001 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2027
2002
2028 if new_file:
2003 if new_file:
2029 fn = "nf%i" % id
2004 fn = "nf%i" % id
2030 files.append(fn)
2005 files.append(fn)
2031 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2006 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
2032 if len(ps) > 1:
2007 if len(ps) > 1:
2033 if not p2:
2008 if not p2:
2034 p2 = repo[ps[1]]
2009 p2 = repo[ps[1]]
2035 for fn in p2:
2010 for fn in p2:
2036 if fn.startswith("nf"):
2011 if fn.startswith("nf"):
2037 files.append(fn)
2012 files.append(fn)
2038 fctxs[fn] = p2[fn]
2013 fctxs[fn] = p2[fn]
2039
2014
2040 def fctxfn(repo, cx, path):
2015 def fctxfn(repo, cx, path):
2041 return fctxs.get(path)
2016 return fctxs.get(path)
2042
2017
2043 if len(ps) == 0 or ps[0] < 0:
2018 if len(ps) == 0 or ps[0] < 0:
2044 pars = [None, None]
2019 pars = [None, None]
2045 elif len(ps) == 1:
2020 elif len(ps) == 1:
2046 pars = [nodeids[ps[0]], None]
2021 pars = [nodeids[ps[0]], None]
2047 else:
2022 else:
2048 pars = [nodeids[p] for p in ps]
2023 pars = [nodeids[p] for p in ps]
2049 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2024 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2050 date=(id, 0),
2025 date=(id, 0),
2051 user="debugbuilddag",
2026 user="debugbuilddag",
2052 extra={'branch': atbranch})
2027 extra={'branch': atbranch})
2053 nodeid = repo.commitctx(cx)
2028 nodeid = repo.commitctx(cx)
2054 nodeids.append(nodeid)
2029 nodeids.append(nodeid)
2055 at = id
2030 at = id
2056 elif type == 'l':
2031 elif type == 'l':
2057 id, name = data
2032 id, name = data
2058 ui.note(('tag %s\n' % name))
2033 ui.note(('tag %s\n' % name))
2059 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2034 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2060 elif type == 'a':
2035 elif type == 'a':
2061 ui.note(('branch %s\n' % data))
2036 ui.note(('branch %s\n' % data))
2062 atbranch = data
2037 atbranch = data
2063 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2038 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2064 tr.close()
2039 tr.close()
2065
2040
2066 if tags:
2041 if tags:
2067 repo.vfs.write("localtags", "".join(tags))
2042 repo.vfs.write("localtags", "".join(tags))
2068 finally:
2043 finally:
2069 ui.progress(_('building'), None)
2044 ui.progress(_('building'), None)
2070 release(tr, lock, wlock)
2045 release(tr, lock, wlock)
2071
2046
2072 @command('debugbundle',
2047 @command('debugbundle',
2073 [('a', 'all', None, _('show all details')),
2048 [('a', 'all', None, _('show all details')),
2074 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2049 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2075 _('FILE'),
2050 _('FILE'),
2076 norepo=True)
2051 norepo=True)
2077 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2052 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2078 """lists the contents of a bundle"""
2053 """lists the contents of a bundle"""
2079 with hg.openpath(ui, bundlepath) as f:
2054 with hg.openpath(ui, bundlepath) as f:
2080 if spec:
2055 if spec:
2081 spec = exchange.getbundlespec(ui, f)
2056 spec = exchange.getbundlespec(ui, f)
2082 ui.write('%s\n' % spec)
2057 ui.write('%s\n' % spec)
2083 return
2058 return
2084
2059
2085 gen = exchange.readbundle(ui, f, bundlepath)
2060 gen = exchange.readbundle(ui, f, bundlepath)
2086 if isinstance(gen, bundle2.unbundle20):
2061 if isinstance(gen, bundle2.unbundle20):
2087 return _debugbundle2(ui, gen, all=all, **opts)
2062 return _debugbundle2(ui, gen, all=all, **opts)
2088 _debugchangegroup(ui, gen, all=all, **opts)
2063 _debugchangegroup(ui, gen, all=all, **opts)
2089
2064
2090 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2065 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
2091 indent_string = ' ' * indent
2066 indent_string = ' ' * indent
2092 if all:
2067 if all:
2093 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2068 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
2094 % indent_string)
2069 % indent_string)
2095
2070
2096 def showchunks(named):
2071 def showchunks(named):
2097 ui.write("\n%s%s\n" % (indent_string, named))
2072 ui.write("\n%s%s\n" % (indent_string, named))
2098 chain = None
2073 chain = None
2099 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2074 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2100 node = chunkdata['node']
2075 node = chunkdata['node']
2101 p1 = chunkdata['p1']
2076 p1 = chunkdata['p1']
2102 p2 = chunkdata['p2']
2077 p2 = chunkdata['p2']
2103 cs = chunkdata['cs']
2078 cs = chunkdata['cs']
2104 deltabase = chunkdata['deltabase']
2079 deltabase = chunkdata['deltabase']
2105 delta = chunkdata['delta']
2080 delta = chunkdata['delta']
2106 ui.write("%s%s %s %s %s %s %s\n" %
2081 ui.write("%s%s %s %s %s %s %s\n" %
2107 (indent_string, hex(node), hex(p1), hex(p2),
2082 (indent_string, hex(node), hex(p1), hex(p2),
2108 hex(cs), hex(deltabase), len(delta)))
2083 hex(cs), hex(deltabase), len(delta)))
2109 chain = node
2084 chain = node
2110
2085
2111 chunkdata = gen.changelogheader()
2086 chunkdata = gen.changelogheader()
2112 showchunks("changelog")
2087 showchunks("changelog")
2113 chunkdata = gen.manifestheader()
2088 chunkdata = gen.manifestheader()
2114 showchunks("manifest")
2089 showchunks("manifest")
2115 for chunkdata in iter(gen.filelogheader, {}):
2090 for chunkdata in iter(gen.filelogheader, {}):
2116 fname = chunkdata['filename']
2091 fname = chunkdata['filename']
2117 showchunks(fname)
2092 showchunks(fname)
2118 else:
2093 else:
2119 if isinstance(gen, bundle2.unbundle20):
2094 if isinstance(gen, bundle2.unbundle20):
2120 raise error.Abort(_('use debugbundle2 for this file'))
2095 raise error.Abort(_('use debugbundle2 for this file'))
2121 chunkdata = gen.changelogheader()
2096 chunkdata = gen.changelogheader()
2122 chain = None
2097 chain = None
2123 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2098 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
2124 node = chunkdata['node']
2099 node = chunkdata['node']
2125 ui.write("%s%s\n" % (indent_string, hex(node)))
2100 ui.write("%s%s\n" % (indent_string, hex(node)))
2126 chain = node
2101 chain = node
2127
2102
2128 def _debugbundle2(ui, gen, all=None, **opts):
2103 def _debugbundle2(ui, gen, all=None, **opts):
2129 """lists the contents of a bundle2"""
2104 """lists the contents of a bundle2"""
2130 if not isinstance(gen, bundle2.unbundle20):
2105 if not isinstance(gen, bundle2.unbundle20):
2131 raise error.Abort(_('not a bundle2 file'))
2106 raise error.Abort(_('not a bundle2 file'))
2132 ui.write(('Stream params: %s\n' % repr(gen.params)))
2107 ui.write(('Stream params: %s\n' % repr(gen.params)))
2133 for part in gen.iterparts():
2108 for part in gen.iterparts():
2134 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2109 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2135 if part.type == 'changegroup':
2110 if part.type == 'changegroup':
2136 version = part.params.get('version', '01')
2111 version = part.params.get('version', '01')
2137 cg = changegroup.getunbundler(version, part, 'UN')
2112 cg = changegroup.getunbundler(version, part, 'UN')
2138 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2113 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
2139
2114
2140 @command('debugcreatestreamclonebundle', [], 'FILE')
2115 @command('debugcreatestreamclonebundle', [], 'FILE')
2141 def debugcreatestreamclonebundle(ui, repo, fname):
2116 def debugcreatestreamclonebundle(ui, repo, fname):
2142 """create a stream clone bundle file
2117 """create a stream clone bundle file
2143
2118
2144 Stream bundles are special bundles that are essentially archives of
2119 Stream bundles are special bundles that are essentially archives of
2145 revlog files. They are commonly used for cloning very quickly.
2120 revlog files. They are commonly used for cloning very quickly.
2146 """
2121 """
2147 requirements, gen = streamclone.generatebundlev1(repo)
2122 requirements, gen = streamclone.generatebundlev1(repo)
2148 changegroup.writechunks(ui, gen, fname)
2123 changegroup.writechunks(ui, gen, fname)
2149
2124
2150 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2125 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2151
2126
2152 @command('debugapplystreamclonebundle', [], 'FILE')
2127 @command('debugapplystreamclonebundle', [], 'FILE')
2153 def debugapplystreamclonebundle(ui, repo, fname):
2128 def debugapplystreamclonebundle(ui, repo, fname):
2154 """apply a stream clone bundle file"""
2129 """apply a stream clone bundle file"""
2155 f = hg.openpath(ui, fname)
2130 f = hg.openpath(ui, fname)
2156 gen = exchange.readbundle(ui, f, fname)
2131 gen = exchange.readbundle(ui, f, fname)
2157 gen.apply(repo)
2132 gen.apply(repo)
2158
2133
2159 @command('debugcheckstate', [], '')
2134 @command('debugcheckstate', [], '')
2160 def debugcheckstate(ui, repo):
2135 def debugcheckstate(ui, repo):
2161 """validate the correctness of the current dirstate"""
2136 """validate the correctness of the current dirstate"""
2162 parent1, parent2 = repo.dirstate.parents()
2137 parent1, parent2 = repo.dirstate.parents()
2163 m1 = repo[parent1].manifest()
2138 m1 = repo[parent1].manifest()
2164 m2 = repo[parent2].manifest()
2139 m2 = repo[parent2].manifest()
2165 errors = 0
2140 errors = 0
2166 for f in repo.dirstate:
2141 for f in repo.dirstate:
2167 state = repo.dirstate[f]
2142 state = repo.dirstate[f]
2168 if state in "nr" and f not in m1:
2143 if state in "nr" and f not in m1:
2169 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2144 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2170 errors += 1
2145 errors += 1
2171 if state in "a" and f in m1:
2146 if state in "a" and f in m1:
2172 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2147 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2173 errors += 1
2148 errors += 1
2174 if state in "m" and f not in m1 and f not in m2:
2149 if state in "m" and f not in m1 and f not in m2:
2175 ui.warn(_("%s in state %s, but not in either manifest\n") %
2150 ui.warn(_("%s in state %s, but not in either manifest\n") %
2176 (f, state))
2151 (f, state))
2177 errors += 1
2152 errors += 1
2178 for f in m1:
2153 for f in m1:
2179 state = repo.dirstate[f]
2154 state = repo.dirstate[f]
2180 if state not in "nrm":
2155 if state not in "nrm":
2181 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2156 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2182 errors += 1
2157 errors += 1
2183 if errors:
2158 if errors:
2184 error = _(".hg/dirstate inconsistent with current parent's manifest")
2159 error = _(".hg/dirstate inconsistent with current parent's manifest")
2185 raise error.Abort(error)
2160 raise error.Abort(error)
2186
2161
2187 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2162 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2188 def debugcommands(ui, cmd='', *args):
2163 def debugcommands(ui, cmd='', *args):
2189 """list all available commands and options"""
2164 """list all available commands and options"""
2190 for cmd, vals in sorted(table.iteritems()):
2165 for cmd, vals in sorted(table.iteritems()):
2191 cmd = cmd.split('|')[0].strip('^')
2166 cmd = cmd.split('|')[0].strip('^')
2192 opts = ', '.join([i[1] for i in vals[1]])
2167 opts = ', '.join([i[1] for i in vals[1]])
2193 ui.write('%s: %s\n' % (cmd, opts))
2168 ui.write('%s: %s\n' % (cmd, opts))
2194
2169
2195 @command('debugcomplete',
2170 @command('debugcomplete',
2196 [('o', 'options', None, _('show the command options'))],
2171 [('o', 'options', None, _('show the command options'))],
2197 _('[-o] CMD'),
2172 _('[-o] CMD'),
2198 norepo=True)
2173 norepo=True)
2199 def debugcomplete(ui, cmd='', **opts):
2174 def debugcomplete(ui, cmd='', **opts):
2200 """returns the completion list associated with the given command"""
2175 """returns the completion list associated with the given command"""
2201
2176
2202 if opts.get('options'):
2177 if opts.get('options'):
2203 options = []
2178 options = []
2204 otables = [globalopts]
2179 otables = [globalopts]
2205 if cmd:
2180 if cmd:
2206 aliases, entry = cmdutil.findcmd(cmd, table, False)
2181 aliases, entry = cmdutil.findcmd(cmd, table, False)
2207 otables.append(entry[1])
2182 otables.append(entry[1])
2208 for t in otables:
2183 for t in otables:
2209 for o in t:
2184 for o in t:
2210 if "(DEPRECATED)" in o[3]:
2185 if "(DEPRECATED)" in o[3]:
2211 continue
2186 continue
2212 if o[0]:
2187 if o[0]:
2213 options.append('-%s' % o[0])
2188 options.append('-%s' % o[0])
2214 options.append('--%s' % o[1])
2189 options.append('--%s' % o[1])
2215 ui.write("%s\n" % "\n".join(options))
2190 ui.write("%s\n" % "\n".join(options))
2216 return
2191 return
2217
2192
2218 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2193 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2219 if ui.verbose:
2194 if ui.verbose:
2220 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2195 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2221 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2196 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2222
2197
2223 @command('debugdag',
2198 @command('debugdag',
2224 [('t', 'tags', None, _('use tags as labels')),
2199 [('t', 'tags', None, _('use tags as labels')),
2225 ('b', 'branches', None, _('annotate with branch names')),
2200 ('b', 'branches', None, _('annotate with branch names')),
2226 ('', 'dots', None, _('use dots for runs')),
2201 ('', 'dots', None, _('use dots for runs')),
2227 ('s', 'spaces', None, _('separate elements by spaces'))],
2202 ('s', 'spaces', None, _('separate elements by spaces'))],
2228 _('[OPTION]... [FILE [REV]...]'),
2203 _('[OPTION]... [FILE [REV]...]'),
2229 optionalrepo=True)
2204 optionalrepo=True)
2230 def debugdag(ui, repo, file_=None, *revs, **opts):
2205 def debugdag(ui, repo, file_=None, *revs, **opts):
2231 """format the changelog or an index DAG as a concise textual description
2206 """format the changelog or an index DAG as a concise textual description
2232
2207
2233 If you pass a revlog index, the revlog's DAG is emitted. If you list
2208 If you pass a revlog index, the revlog's DAG is emitted. If you list
2234 revision numbers, they get labeled in the output as rN.
2209 revision numbers, they get labeled in the output as rN.
2235
2210
2236 Otherwise, the changelog DAG of the current repo is emitted.
2211 Otherwise, the changelog DAG of the current repo is emitted.
2237 """
2212 """
2238 spaces = opts.get('spaces')
2213 spaces = opts.get('spaces')
2239 dots = opts.get('dots')
2214 dots = opts.get('dots')
2240 if file_:
2215 if file_:
2241 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2216 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2242 revs = set((int(r) for r in revs))
2217 revs = set((int(r) for r in revs))
2243 def events():
2218 def events():
2244 for r in rlog:
2219 for r in rlog:
2245 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2220 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2246 if p != -1))
2221 if p != -1))
2247 if r in revs:
2222 if r in revs:
2248 yield 'l', (r, "r%i" % r)
2223 yield 'l', (r, "r%i" % r)
2249 elif repo:
2224 elif repo:
2250 cl = repo.changelog
2225 cl = repo.changelog
2251 tags = opts.get('tags')
2226 tags = opts.get('tags')
2252 branches = opts.get('branches')
2227 branches = opts.get('branches')
2253 if tags:
2228 if tags:
2254 labels = {}
2229 labels = {}
2255 for l, n in repo.tags().items():
2230 for l, n in repo.tags().items():
2256 labels.setdefault(cl.rev(n), []).append(l)
2231 labels.setdefault(cl.rev(n), []).append(l)
2257 def events():
2232 def events():
2258 b = "default"
2233 b = "default"
2259 for r in cl:
2234 for r in cl:
2260 if branches:
2235 if branches:
2261 newb = cl.read(cl.node(r))[5]['branch']
2236 newb = cl.read(cl.node(r))[5]['branch']
2262 if newb != b:
2237 if newb != b:
2263 yield 'a', newb
2238 yield 'a', newb
2264 b = newb
2239 b = newb
2265 yield 'n', (r, list(p for p in cl.parentrevs(r)
2240 yield 'n', (r, list(p for p in cl.parentrevs(r)
2266 if p != -1))
2241 if p != -1))
2267 if tags:
2242 if tags:
2268 ls = labels.get(r)
2243 ls = labels.get(r)
2269 if ls:
2244 if ls:
2270 for l in ls:
2245 for l in ls:
2271 yield 'l', (r, l)
2246 yield 'l', (r, l)
2272 else:
2247 else:
2273 raise error.Abort(_('need repo for changelog dag'))
2248 raise error.Abort(_('need repo for changelog dag'))
2274
2249
2275 for line in dagparser.dagtextlines(events(),
2250 for line in dagparser.dagtextlines(events(),
2276 addspaces=spaces,
2251 addspaces=spaces,
2277 wraplabels=True,
2252 wraplabels=True,
2278 wrapannotations=True,
2253 wrapannotations=True,
2279 wrapnonlinear=dots,
2254 wrapnonlinear=dots,
2280 usedots=dots,
2255 usedots=dots,
2281 maxlinewidth=70):
2256 maxlinewidth=70):
2282 ui.write(line)
2257 ui.write(line)
2283 ui.write("\n")
2258 ui.write("\n")
2284
2259
2285 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2260 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2286 def debugdata(ui, repo, file_, rev=None, **opts):
2261 def debugdata(ui, repo, file_, rev=None, **opts):
2287 """dump the contents of a data file revision"""
2262 """dump the contents of a data file revision"""
2288 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2263 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2289 if rev is not None:
2264 if rev is not None:
2290 raise error.CommandError('debugdata', _('invalid arguments'))
2265 raise error.CommandError('debugdata', _('invalid arguments'))
2291 file_, rev = None, file_
2266 file_, rev = None, file_
2292 elif rev is None:
2267 elif rev is None:
2293 raise error.CommandError('debugdata', _('invalid arguments'))
2268 raise error.CommandError('debugdata', _('invalid arguments'))
2294 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2269 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2295 try:
2270 try:
2296 ui.write(r.revision(r.lookup(rev)))
2271 ui.write(r.revision(r.lookup(rev)))
2297 except KeyError:
2272 except KeyError:
2298 raise error.Abort(_('invalid revision identifier %s') % rev)
2273 raise error.Abort(_('invalid revision identifier %s') % rev)
2299
2274
2300 @command('debugdate',
2275 @command('debugdate',
2301 [('e', 'extended', None, _('try extended date formats'))],
2276 [('e', 'extended', None, _('try extended date formats'))],
2302 _('[-e] DATE [RANGE]'),
2277 _('[-e] DATE [RANGE]'),
2303 norepo=True, optionalrepo=True)
2278 norepo=True, optionalrepo=True)
2304 def debugdate(ui, date, range=None, **opts):
2279 def debugdate(ui, date, range=None, **opts):
2305 """parse and display a date"""
2280 """parse and display a date"""
2306 if opts["extended"]:
2281 if opts["extended"]:
2307 d = util.parsedate(date, util.extendeddateformats)
2282 d = util.parsedate(date, util.extendeddateformats)
2308 else:
2283 else:
2309 d = util.parsedate(date)
2284 d = util.parsedate(date)
2310 ui.write(("internal: %s %s\n") % d)
2285 ui.write(("internal: %s %s\n") % d)
2311 ui.write(("standard: %s\n") % util.datestr(d))
2286 ui.write(("standard: %s\n") % util.datestr(d))
2312 if range:
2287 if range:
2313 m = util.matchdate(range)
2288 m = util.matchdate(range)
2314 ui.write(("match: %s\n") % m(d[0]))
2289 ui.write(("match: %s\n") % m(d[0]))
2315
2290
2316 @command('debugdiscovery',
2291 @command('debugdiscovery',
2317 [('', 'old', None, _('use old-style discovery')),
2292 [('', 'old', None, _('use old-style discovery')),
2318 ('', 'nonheads', None,
2293 ('', 'nonheads', None,
2319 _('use old-style discovery with non-heads included')),
2294 _('use old-style discovery with non-heads included')),
2320 ] + remoteopts,
2295 ] + remoteopts,
2321 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2296 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2322 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2297 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2323 """runs the changeset discovery protocol in isolation"""
2298 """runs the changeset discovery protocol in isolation"""
2324 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2299 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2325 opts.get('branch'))
2300 opts.get('branch'))
2326 remote = hg.peer(repo, opts, remoteurl)
2301 remote = hg.peer(repo, opts, remoteurl)
2327 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2302 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2328
2303
2329 # make sure tests are repeatable
2304 # make sure tests are repeatable
2330 random.seed(12323)
2305 random.seed(12323)
2331
2306
2332 def doit(localheads, remoteheads, remote=remote):
2307 def doit(localheads, remoteheads, remote=remote):
2333 if opts.get('old'):
2308 if opts.get('old'):
2334 if localheads:
2309 if localheads:
2335 raise error.Abort('cannot use localheads with old style '
2310 raise error.Abort('cannot use localheads with old style '
2336 'discovery')
2311 'discovery')
2337 if not util.safehasattr(remote, 'branches'):
2312 if not util.safehasattr(remote, 'branches'):
2338 # enable in-client legacy support
2313 # enable in-client legacy support
2339 remote = localrepo.locallegacypeer(remote.local())
2314 remote = localrepo.locallegacypeer(remote.local())
2340 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2315 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2341 force=True)
2316 force=True)
2342 common = set(common)
2317 common = set(common)
2343 if not opts.get('nonheads'):
2318 if not opts.get('nonheads'):
2344 ui.write(("unpruned common: %s\n") %
2319 ui.write(("unpruned common: %s\n") %
2345 " ".join(sorted(short(n) for n in common)))
2320 " ".join(sorted(short(n) for n in common)))
2346 dag = dagutil.revlogdag(repo.changelog)
2321 dag = dagutil.revlogdag(repo.changelog)
2347 all = dag.ancestorset(dag.internalizeall(common))
2322 all = dag.ancestorset(dag.internalizeall(common))
2348 common = dag.externalizeall(dag.headsetofconnecteds(all))
2323 common = dag.externalizeall(dag.headsetofconnecteds(all))
2349 else:
2324 else:
2350 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2325 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2351 common = set(common)
2326 common = set(common)
2352 rheads = set(hds)
2327 rheads = set(hds)
2353 lheads = set(repo.heads())
2328 lheads = set(repo.heads())
2354 ui.write(("common heads: %s\n") %
2329 ui.write(("common heads: %s\n") %
2355 " ".join(sorted(short(n) for n in common)))
2330 " ".join(sorted(short(n) for n in common)))
2356 if lheads <= common:
2331 if lheads <= common:
2357 ui.write(("local is subset\n"))
2332 ui.write(("local is subset\n"))
2358 elif rheads <= common:
2333 elif rheads <= common:
2359 ui.write(("remote is subset\n"))
2334 ui.write(("remote is subset\n"))
2360
2335
2361 serverlogs = opts.get('serverlog')
2336 serverlogs = opts.get('serverlog')
2362 if serverlogs:
2337 if serverlogs:
2363 for filename in serverlogs:
2338 for filename in serverlogs:
2364 with open(filename, 'r') as logfile:
2339 with open(filename, 'r') as logfile:
2365 line = logfile.readline()
2340 line = logfile.readline()
2366 while line:
2341 while line:
2367 parts = line.strip().split(';')
2342 parts = line.strip().split(';')
2368 op = parts[1]
2343 op = parts[1]
2369 if op == 'cg':
2344 if op == 'cg':
2370 pass
2345 pass
2371 elif op == 'cgss':
2346 elif op == 'cgss':
2372 doit(parts[2].split(' '), parts[3].split(' '))
2347 doit(parts[2].split(' '), parts[3].split(' '))
2373 elif op == 'unb':
2348 elif op == 'unb':
2374 doit(parts[3].split(' '), parts[2].split(' '))
2349 doit(parts[3].split(' '), parts[2].split(' '))
2375 line = logfile.readline()
2350 line = logfile.readline()
2376 else:
2351 else:
2377 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2352 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2378 opts.get('remote_head'))
2353 opts.get('remote_head'))
2379 localrevs = opts.get('local_head')
2354 localrevs = opts.get('local_head')
2380 doit(localrevs, remoterevs)
2355 doit(localrevs, remoterevs)
2381
2356
2382 @command('debugextensions', formatteropts, [], norepo=True)
2357 @command('debugextensions', formatteropts, [], norepo=True)
2383 def debugextensions(ui, **opts):
2358 def debugextensions(ui, **opts):
2384 '''show information about active extensions'''
2359 '''show information about active extensions'''
2385 exts = extensions.extensions(ui)
2360 exts = extensions.extensions(ui)
2386 hgver = util.version()
2361 hgver = util.version()
2387 fm = ui.formatter('debugextensions', opts)
2362 fm = ui.formatter('debugextensions', opts)
2388 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2363 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2389 isinternal = extensions.ismoduleinternal(extmod)
2364 isinternal = extensions.ismoduleinternal(extmod)
2390 extsource = extmod.__file__
2365 extsource = extmod.__file__
2391 if isinternal:
2366 if isinternal:
2392 exttestedwith = [] # never expose magic string to users
2367 exttestedwith = [] # never expose magic string to users
2393 else:
2368 else:
2394 exttestedwith = getattr(extmod, 'testedwith', '').split()
2369 exttestedwith = getattr(extmod, 'testedwith', '').split()
2395 extbuglink = getattr(extmod, 'buglink', None)
2370 extbuglink = getattr(extmod, 'buglink', None)
2396
2371
2397 fm.startitem()
2372 fm.startitem()
2398
2373
2399 if ui.quiet or ui.verbose:
2374 if ui.quiet or ui.verbose:
2400 fm.write('name', '%s\n', extname)
2375 fm.write('name', '%s\n', extname)
2401 else:
2376 else:
2402 fm.write('name', '%s', extname)
2377 fm.write('name', '%s', extname)
2403 if isinternal or hgver in exttestedwith:
2378 if isinternal or hgver in exttestedwith:
2404 fm.plain('\n')
2379 fm.plain('\n')
2405 elif not exttestedwith:
2380 elif not exttestedwith:
2406 fm.plain(_(' (untested!)\n'))
2381 fm.plain(_(' (untested!)\n'))
2407 else:
2382 else:
2408 lasttestedversion = exttestedwith[-1]
2383 lasttestedversion = exttestedwith[-1]
2409 fm.plain(' (%s!)\n' % lasttestedversion)
2384 fm.plain(' (%s!)\n' % lasttestedversion)
2410
2385
2411 fm.condwrite(ui.verbose and extsource, 'source',
2386 fm.condwrite(ui.verbose and extsource, 'source',
2412 _(' location: %s\n'), extsource or "")
2387 _(' location: %s\n'), extsource or "")
2413
2388
2414 if ui.verbose:
2389 if ui.verbose:
2415 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2390 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2416 fm.data(bundled=isinternal)
2391 fm.data(bundled=isinternal)
2417
2392
2418 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2393 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2419 _(' tested with: %s\n'),
2394 _(' tested with: %s\n'),
2420 fm.formatlist(exttestedwith, name='ver'))
2395 fm.formatlist(exttestedwith, name='ver'))
2421
2396
2422 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2397 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2423 _(' bug reporting: %s\n'), extbuglink or "")
2398 _(' bug reporting: %s\n'), extbuglink or "")
2424
2399
2425 fm.end()
2400 fm.end()
2426
2401
2427 @command('debugfileset',
2402 @command('debugfileset',
2428 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2403 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2429 _('[-r REV] FILESPEC'))
2404 _('[-r REV] FILESPEC'))
2430 def debugfileset(ui, repo, expr, **opts):
2405 def debugfileset(ui, repo, expr, **opts):
2431 '''parse and apply a fileset specification'''
2406 '''parse and apply a fileset specification'''
2432 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2407 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2433 if ui.verbose:
2408 if ui.verbose:
2434 tree = fileset.parse(expr)
2409 tree = fileset.parse(expr)
2435 ui.note(fileset.prettyformat(tree), "\n")
2410 ui.note(fileset.prettyformat(tree), "\n")
2436
2411
2437 for f in ctx.getfileset(expr):
2412 for f in ctx.getfileset(expr):
2438 ui.write("%s\n" % f)
2413 ui.write("%s\n" % f)
2439
2414
2440 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2415 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2441 def debugfsinfo(ui, path="."):
2416 def debugfsinfo(ui, path="."):
2442 """show information detected about current filesystem"""
2417 """show information detected about current filesystem"""
2443 util.writefile('.debugfsinfo', '')
2418 util.writefile('.debugfsinfo', '')
2444 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2419 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2445 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2420 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2446 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2421 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2447 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2422 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2448 and 'yes' or 'no'))
2423 and 'yes' or 'no'))
2449 os.unlink('.debugfsinfo')
2424 os.unlink('.debugfsinfo')
2450
2425
2451 @command('debuggetbundle',
2426 @command('debuggetbundle',
2452 [('H', 'head', [], _('id of head node'), _('ID')),
2427 [('H', 'head', [], _('id of head node'), _('ID')),
2453 ('C', 'common', [], _('id of common node'), _('ID')),
2428 ('C', 'common', [], _('id of common node'), _('ID')),
2454 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2429 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2455 _('REPO FILE [-H|-C ID]...'),
2430 _('REPO FILE [-H|-C ID]...'),
2456 norepo=True)
2431 norepo=True)
2457 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2432 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2458 """retrieves a bundle from a repo
2433 """retrieves a bundle from a repo
2459
2434
2460 Every ID must be a full-length hex node id string. Saves the bundle to the
2435 Every ID must be a full-length hex node id string. Saves the bundle to the
2461 given file.
2436 given file.
2462 """
2437 """
2463 repo = hg.peer(ui, opts, repopath)
2438 repo = hg.peer(ui, opts, repopath)
2464 if not repo.capable('getbundle'):
2439 if not repo.capable('getbundle'):
2465 raise error.Abort("getbundle() not supported by target repository")
2440 raise error.Abort("getbundle() not supported by target repository")
2466 args = {}
2441 args = {}
2467 if common:
2442 if common:
2468 args['common'] = [bin(s) for s in common]
2443 args['common'] = [bin(s) for s in common]
2469 if head:
2444 if head:
2470 args['heads'] = [bin(s) for s in head]
2445 args['heads'] = [bin(s) for s in head]
2471 # TODO: get desired bundlecaps from command line.
2446 # TODO: get desired bundlecaps from command line.
2472 args['bundlecaps'] = None
2447 args['bundlecaps'] = None
2473 bundle = repo.getbundle('debug', **args)
2448 bundle = repo.getbundle('debug', **args)
2474
2449
2475 bundletype = opts.get('type', 'bzip2').lower()
2450 bundletype = opts.get('type', 'bzip2').lower()
2476 btypes = {'none': 'HG10UN',
2451 btypes = {'none': 'HG10UN',
2477 'bzip2': 'HG10BZ',
2452 'bzip2': 'HG10BZ',
2478 'gzip': 'HG10GZ',
2453 'gzip': 'HG10GZ',
2479 'bundle2': 'HG20'}
2454 'bundle2': 'HG20'}
2480 bundletype = btypes.get(bundletype)
2455 bundletype = btypes.get(bundletype)
2481 if bundletype not in bundle2.bundletypes:
2456 if bundletype not in bundle2.bundletypes:
2482 raise error.Abort(_('unknown bundle type specified with --type'))
2457 raise error.Abort(_('unknown bundle type specified with --type'))
2483 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2458 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2484
2459
2485 @command('debugignore', [], '[FILE]')
2460 @command('debugignore', [], '[FILE]')
2486 def debugignore(ui, repo, *files, **opts):
2461 def debugignore(ui, repo, *files, **opts):
2487 """display the combined ignore pattern and information about ignored files
2462 """display the combined ignore pattern and information about ignored files
2488
2463
2489 With no argument display the combined ignore pattern.
2464 With no argument display the combined ignore pattern.
2490
2465
2491 Given space separated file names, shows if the given file is ignored and
2466 Given space separated file names, shows if the given file is ignored and
2492 if so, show the ignore rule (file and line number) that matched it.
2467 if so, show the ignore rule (file and line number) that matched it.
2493 """
2468 """
2494 ignore = repo.dirstate._ignore
2469 ignore = repo.dirstate._ignore
2495 if not files:
2470 if not files:
2496 # Show all the patterns
2471 # Show all the patterns
2497 includepat = getattr(ignore, 'includepat', None)
2472 includepat = getattr(ignore, 'includepat', None)
2498 if includepat is not None:
2473 if includepat is not None:
2499 ui.write("%s\n" % includepat)
2474 ui.write("%s\n" % includepat)
2500 else:
2475 else:
2501 raise error.Abort(_("no ignore patterns found"))
2476 raise error.Abort(_("no ignore patterns found"))
2502 else:
2477 else:
2503 for f in files:
2478 for f in files:
2504 nf = util.normpath(f)
2479 nf = util.normpath(f)
2505 ignored = None
2480 ignored = None
2506 ignoredata = None
2481 ignoredata = None
2507 if nf != '.':
2482 if nf != '.':
2508 if ignore(nf):
2483 if ignore(nf):
2509 ignored = nf
2484 ignored = nf
2510 ignoredata = repo.dirstate._ignorefileandline(nf)
2485 ignoredata = repo.dirstate._ignorefileandline(nf)
2511 else:
2486 else:
2512 for p in util.finddirs(nf):
2487 for p in util.finddirs(nf):
2513 if ignore(p):
2488 if ignore(p):
2514 ignored = p
2489 ignored = p
2515 ignoredata = repo.dirstate._ignorefileandline(p)
2490 ignoredata = repo.dirstate._ignorefileandline(p)
2516 break
2491 break
2517 if ignored:
2492 if ignored:
2518 if ignored == nf:
2493 if ignored == nf:
2519 ui.write(_("%s is ignored\n") % f)
2494 ui.write(_("%s is ignored\n") % f)
2520 else:
2495 else:
2521 ui.write(_("%s is ignored because of "
2496 ui.write(_("%s is ignored because of "
2522 "containing folder %s\n")
2497 "containing folder %s\n")
2523 % (f, ignored))
2498 % (f, ignored))
2524 ignorefile, lineno, line = ignoredata
2499 ignorefile, lineno, line = ignoredata
2525 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2500 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2526 % (ignorefile, lineno, line))
2501 % (ignorefile, lineno, line))
2527 else:
2502 else:
2528 ui.write(_("%s is not ignored\n") % f)
2503 ui.write(_("%s is not ignored\n") % f)
2529
2504
2530 @command('debugindex', debugrevlogopts +
2505 @command('debugindex', debugrevlogopts +
2531 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2506 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2532 _('[-f FORMAT] -c|-m|FILE'),
2507 _('[-f FORMAT] -c|-m|FILE'),
2533 optionalrepo=True)
2508 optionalrepo=True)
2534 def debugindex(ui, repo, file_=None, **opts):
2509 def debugindex(ui, repo, file_=None, **opts):
2535 """dump the contents of an index file"""
2510 """dump the contents of an index file"""
2536 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2511 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2537 format = opts.get('format', 0)
2512 format = opts.get('format', 0)
2538 if format not in (0, 1):
2513 if format not in (0, 1):
2539 raise error.Abort(_("unknown format %d") % format)
2514 raise error.Abort(_("unknown format %d") % format)
2540
2515
2541 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2516 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2542 if generaldelta:
2517 if generaldelta:
2543 basehdr = ' delta'
2518 basehdr = ' delta'
2544 else:
2519 else:
2545 basehdr = ' base'
2520 basehdr = ' base'
2546
2521
2547 if ui.debugflag:
2522 if ui.debugflag:
2548 shortfn = hex
2523 shortfn = hex
2549 else:
2524 else:
2550 shortfn = short
2525 shortfn = short
2551
2526
2552 # There might not be anything in r, so have a sane default
2527 # There might not be anything in r, so have a sane default
2553 idlen = 12
2528 idlen = 12
2554 for i in r:
2529 for i in r:
2555 idlen = len(shortfn(r.node(i)))
2530 idlen = len(shortfn(r.node(i)))
2556 break
2531 break
2557
2532
2558 if format == 0:
2533 if format == 0:
2559 ui.write((" rev offset length " + basehdr + " linkrev"
2534 ui.write((" rev offset length " + basehdr + " linkrev"
2560 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2535 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2561 elif format == 1:
2536 elif format == 1:
2562 ui.write((" rev flag offset length"
2537 ui.write((" rev flag offset length"
2563 " size " + basehdr + " link p1 p2"
2538 " size " + basehdr + " link p1 p2"
2564 " %s\n") % "nodeid".rjust(idlen))
2539 " %s\n") % "nodeid".rjust(idlen))
2565
2540
2566 for i in r:
2541 for i in r:
2567 node = r.node(i)
2542 node = r.node(i)
2568 if generaldelta:
2543 if generaldelta:
2569 base = r.deltaparent(i)
2544 base = r.deltaparent(i)
2570 else:
2545 else:
2571 base = r.chainbase(i)
2546 base = r.chainbase(i)
2572 if format == 0:
2547 if format == 0:
2573 try:
2548 try:
2574 pp = r.parents(node)
2549 pp = r.parents(node)
2575 except Exception:
2550 except Exception:
2576 pp = [nullid, nullid]
2551 pp = [nullid, nullid]
2577 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2552 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2578 i, r.start(i), r.length(i), base, r.linkrev(i),
2553 i, r.start(i), r.length(i), base, r.linkrev(i),
2579 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2554 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2580 elif format == 1:
2555 elif format == 1:
2581 pr = r.parentrevs(i)
2556 pr = r.parentrevs(i)
2582 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2557 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2583 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2558 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2584 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2559 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2585
2560
2586 @command('debugindexdot', debugrevlogopts,
2561 @command('debugindexdot', debugrevlogopts,
2587 _('-c|-m|FILE'), optionalrepo=True)
2562 _('-c|-m|FILE'), optionalrepo=True)
2588 def debugindexdot(ui, repo, file_=None, **opts):
2563 def debugindexdot(ui, repo, file_=None, **opts):
2589 """dump an index DAG as a graphviz dot file"""
2564 """dump an index DAG as a graphviz dot file"""
2590 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2565 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2591 ui.write(("digraph G {\n"))
2566 ui.write(("digraph G {\n"))
2592 for i in r:
2567 for i in r:
2593 node = r.node(i)
2568 node = r.node(i)
2594 pp = r.parents(node)
2569 pp = r.parents(node)
2595 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2570 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2596 if pp[1] != nullid:
2571 if pp[1] != nullid:
2597 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2572 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2598 ui.write("}\n")
2573 ui.write("}\n")
2599
2574
2600 @command('debugdeltachain',
2575 @command('debugdeltachain',
2601 debugrevlogopts + formatteropts,
2576 debugrevlogopts + formatteropts,
2602 _('-c|-m|FILE'),
2577 _('-c|-m|FILE'),
2603 optionalrepo=True)
2578 optionalrepo=True)
2604 def debugdeltachain(ui, repo, file_=None, **opts):
2579 def debugdeltachain(ui, repo, file_=None, **opts):
2605 """dump information about delta chains in a revlog
2580 """dump information about delta chains in a revlog
2606
2581
2607 Output can be templatized. Available template keywords are:
2582 Output can be templatized. Available template keywords are:
2608
2583
2609 :``rev``: revision number
2584 :``rev``: revision number
2610 :``chainid``: delta chain identifier (numbered by unique base)
2585 :``chainid``: delta chain identifier (numbered by unique base)
2611 :``chainlen``: delta chain length to this revision
2586 :``chainlen``: delta chain length to this revision
2612 :``prevrev``: previous revision in delta chain
2587 :``prevrev``: previous revision in delta chain
2613 :``deltatype``: role of delta / how it was computed
2588 :``deltatype``: role of delta / how it was computed
2614 :``compsize``: compressed size of revision
2589 :``compsize``: compressed size of revision
2615 :``uncompsize``: uncompressed size of revision
2590 :``uncompsize``: uncompressed size of revision
2616 :``chainsize``: total size of compressed revisions in chain
2591 :``chainsize``: total size of compressed revisions in chain
2617 :``chainratio``: total chain size divided by uncompressed revision size
2592 :``chainratio``: total chain size divided by uncompressed revision size
2618 (new delta chains typically start at ratio 2.00)
2593 (new delta chains typically start at ratio 2.00)
2619 :``lindist``: linear distance from base revision in delta chain to end
2594 :``lindist``: linear distance from base revision in delta chain to end
2620 of this revision
2595 of this revision
2621 :``extradist``: total size of revisions not part of this delta chain from
2596 :``extradist``: total size of revisions not part of this delta chain from
2622 base of delta chain to end of this revision; a measurement
2597 base of delta chain to end of this revision; a measurement
2623 of how much extra data we need to read/seek across to read
2598 of how much extra data we need to read/seek across to read
2624 the delta chain for this revision
2599 the delta chain for this revision
2625 :``extraratio``: extradist divided by chainsize; another representation of
2600 :``extraratio``: extradist divided by chainsize; another representation of
2626 how much unrelated data is needed to load this delta chain
2601 how much unrelated data is needed to load this delta chain
2627 """
2602 """
2628 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2603 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2629 index = r.index
2604 index = r.index
2630 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2605 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2631
2606
2632 def revinfo(rev):
2607 def revinfo(rev):
2633 e = index[rev]
2608 e = index[rev]
2634 compsize = e[1]
2609 compsize = e[1]
2635 uncompsize = e[2]
2610 uncompsize = e[2]
2636 chainsize = 0
2611 chainsize = 0
2637
2612
2638 if generaldelta:
2613 if generaldelta:
2639 if e[3] == e[5]:
2614 if e[3] == e[5]:
2640 deltatype = 'p1'
2615 deltatype = 'p1'
2641 elif e[3] == e[6]:
2616 elif e[3] == e[6]:
2642 deltatype = 'p2'
2617 deltatype = 'p2'
2643 elif e[3] == rev - 1:
2618 elif e[3] == rev - 1:
2644 deltatype = 'prev'
2619 deltatype = 'prev'
2645 elif e[3] == rev:
2620 elif e[3] == rev:
2646 deltatype = 'base'
2621 deltatype = 'base'
2647 else:
2622 else:
2648 deltatype = 'other'
2623 deltatype = 'other'
2649 else:
2624 else:
2650 if e[3] == rev:
2625 if e[3] == rev:
2651 deltatype = 'base'
2626 deltatype = 'base'
2652 else:
2627 else:
2653 deltatype = 'prev'
2628 deltatype = 'prev'
2654
2629
2655 chain = r._deltachain(rev)[0]
2630 chain = r._deltachain(rev)[0]
2656 for iterrev in chain:
2631 for iterrev in chain:
2657 e = index[iterrev]
2632 e = index[iterrev]
2658 chainsize += e[1]
2633 chainsize += e[1]
2659
2634
2660 return compsize, uncompsize, deltatype, chain, chainsize
2635 return compsize, uncompsize, deltatype, chain, chainsize
2661
2636
2662 fm = ui.formatter('debugdeltachain', opts)
2637 fm = ui.formatter('debugdeltachain', opts)
2663
2638
2664 fm.plain(' rev chain# chainlen prev delta '
2639 fm.plain(' rev chain# chainlen prev delta '
2665 'size rawsize chainsize ratio lindist extradist '
2640 'size rawsize chainsize ratio lindist extradist '
2666 'extraratio\n')
2641 'extraratio\n')
2667
2642
2668 chainbases = {}
2643 chainbases = {}
2669 for rev in r:
2644 for rev in r:
2670 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2645 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2671 chainbase = chain[0]
2646 chainbase = chain[0]
2672 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2647 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2673 basestart = r.start(chainbase)
2648 basestart = r.start(chainbase)
2674 revstart = r.start(rev)
2649 revstart = r.start(rev)
2675 lineardist = revstart + comp - basestart
2650 lineardist = revstart + comp - basestart
2676 extradist = lineardist - chainsize
2651 extradist = lineardist - chainsize
2677 try:
2652 try:
2678 prevrev = chain[-2]
2653 prevrev = chain[-2]
2679 except IndexError:
2654 except IndexError:
2680 prevrev = -1
2655 prevrev = -1
2681
2656
2682 chainratio = float(chainsize) / float(uncomp)
2657 chainratio = float(chainsize) / float(uncomp)
2683 extraratio = float(extradist) / float(chainsize)
2658 extraratio = float(extradist) / float(chainsize)
2684
2659
2685 fm.startitem()
2660 fm.startitem()
2686 fm.write('rev chainid chainlen prevrev deltatype compsize '
2661 fm.write('rev chainid chainlen prevrev deltatype compsize '
2687 'uncompsize chainsize chainratio lindist extradist '
2662 'uncompsize chainsize chainratio lindist extradist '
2688 'extraratio',
2663 'extraratio',
2689 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2664 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2690 rev, chainid, len(chain), prevrev, deltatype, comp,
2665 rev, chainid, len(chain), prevrev, deltatype, comp,
2691 uncomp, chainsize, chainratio, lineardist, extradist,
2666 uncomp, chainsize, chainratio, lineardist, extradist,
2692 extraratio,
2667 extraratio,
2693 rev=rev, chainid=chainid, chainlen=len(chain),
2668 rev=rev, chainid=chainid, chainlen=len(chain),
2694 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2669 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2695 uncompsize=uncomp, chainsize=chainsize,
2670 uncompsize=uncomp, chainsize=chainsize,
2696 chainratio=chainratio, lindist=lineardist,
2671 chainratio=chainratio, lindist=lineardist,
2697 extradist=extradist, extraratio=extraratio)
2672 extradist=extradist, extraratio=extraratio)
2698
2673
2699 fm.end()
2674 fm.end()
2700
2675
2701 @command('debuginstall', [] + formatteropts, '', norepo=True)
2676 @command('debuginstall', [] + formatteropts, '', norepo=True)
2702 def debuginstall(ui, **opts):
2677 def debuginstall(ui, **opts):
2703 '''test Mercurial installation
2678 '''test Mercurial installation
2704
2679
2705 Returns 0 on success.
2680 Returns 0 on success.
2706 '''
2681 '''
2707
2682
2708 def writetemp(contents):
2683 def writetemp(contents):
2709 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2684 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2710 f = os.fdopen(fd, "wb")
2685 f = os.fdopen(fd, "wb")
2711 f.write(contents)
2686 f.write(contents)
2712 f.close()
2687 f.close()
2713 return name
2688 return name
2714
2689
2715 problems = 0
2690 problems = 0
2716
2691
2717 fm = ui.formatter('debuginstall', opts)
2692 fm = ui.formatter('debuginstall', opts)
2718 fm.startitem()
2693 fm.startitem()
2719
2694
2720 # encoding
2695 # encoding
2721 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2696 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2722 err = None
2697 err = None
2723 try:
2698 try:
2724 encoding.fromlocal("test")
2699 encoding.fromlocal("test")
2725 except error.Abort as inst:
2700 except error.Abort as inst:
2726 err = inst
2701 err = inst
2727 problems += 1
2702 problems += 1
2728 fm.condwrite(err, 'encodingerror', _(" %s\n"
2703 fm.condwrite(err, 'encodingerror', _(" %s\n"
2729 " (check that your locale is properly set)\n"), err)
2704 " (check that your locale is properly set)\n"), err)
2730
2705
2731 # Python
2706 # Python
2732 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2707 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2733 sys.executable)
2708 sys.executable)
2734 fm.write('pythonver', _("checking Python version (%s)\n"),
2709 fm.write('pythonver', _("checking Python version (%s)\n"),
2735 ("%s.%s.%s" % sys.version_info[:3]))
2710 ("%s.%s.%s" % sys.version_info[:3]))
2736 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2711 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2737 os.path.dirname(os.__file__))
2712 os.path.dirname(os.__file__))
2738
2713
2739 # hg version
2714 # hg version
2740 hgver = util.version()
2715 hgver = util.version()
2741 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2716 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2742 hgver.split('+')[0])
2717 hgver.split('+')[0])
2743 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2718 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2744 '+'.join(hgver.split('+')[1:]))
2719 '+'.join(hgver.split('+')[1:]))
2745
2720
2746 # compiled modules
2721 # compiled modules
2747 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2722 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2748 policy.policy)
2723 policy.policy)
2749 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2724 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2750 os.path.dirname(__file__))
2725 os.path.dirname(__file__))
2751
2726
2752 err = None
2727 err = None
2753 try:
2728 try:
2754 from . import (
2729 from . import (
2755 base85,
2730 base85,
2756 bdiff,
2731 bdiff,
2757 mpatch,
2732 mpatch,
2758 osutil,
2733 osutil,
2759 )
2734 )
2760 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2735 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2761 except Exception as inst:
2736 except Exception as inst:
2762 err = inst
2737 err = inst
2763 problems += 1
2738 problems += 1
2764 fm.condwrite(err, 'extensionserror', " %s\n", err)
2739 fm.condwrite(err, 'extensionserror', " %s\n", err)
2765
2740
2766 # templates
2741 # templates
2767 p = templater.templatepaths()
2742 p = templater.templatepaths()
2768 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2743 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2769 fm.condwrite(not p, '', _(" no template directories found\n"))
2744 fm.condwrite(not p, '', _(" no template directories found\n"))
2770 if p:
2745 if p:
2771 m = templater.templatepath("map-cmdline.default")
2746 m = templater.templatepath("map-cmdline.default")
2772 if m:
2747 if m:
2773 # template found, check if it is working
2748 # template found, check if it is working
2774 err = None
2749 err = None
2775 try:
2750 try:
2776 templater.templater.frommapfile(m)
2751 templater.templater.frommapfile(m)
2777 except Exception as inst:
2752 except Exception as inst:
2778 err = inst
2753 err = inst
2779 p = None
2754 p = None
2780 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2755 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2781 else:
2756 else:
2782 p = None
2757 p = None
2783 fm.condwrite(p, 'defaulttemplate',
2758 fm.condwrite(p, 'defaulttemplate',
2784 _("checking default template (%s)\n"), m)
2759 _("checking default template (%s)\n"), m)
2785 fm.condwrite(not m, 'defaulttemplatenotfound',
2760 fm.condwrite(not m, 'defaulttemplatenotfound',
2786 _(" template '%s' not found\n"), "default")
2761 _(" template '%s' not found\n"), "default")
2787 if not p:
2762 if not p:
2788 problems += 1
2763 problems += 1
2789 fm.condwrite(not p, '',
2764 fm.condwrite(not p, '',
2790 _(" (templates seem to have been installed incorrectly)\n"))
2765 _(" (templates seem to have been installed incorrectly)\n"))
2791
2766
2792 # editor
2767 # editor
2793 editor = ui.geteditor()
2768 editor = ui.geteditor()
2794 editor = util.expandpath(editor)
2769 editor = util.expandpath(editor)
2795 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2770 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2796 cmdpath = util.findexe(shlex.split(editor)[0])
2771 cmdpath = util.findexe(shlex.split(editor)[0])
2797 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2772 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2798 _(" No commit editor set and can't find %s in PATH\n"
2773 _(" No commit editor set and can't find %s in PATH\n"
2799 " (specify a commit editor in your configuration"
2774 " (specify a commit editor in your configuration"
2800 " file)\n"), not cmdpath and editor == 'vi' and editor)
2775 " file)\n"), not cmdpath and editor == 'vi' and editor)
2801 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2776 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2802 _(" Can't find editor '%s' in PATH\n"
2777 _(" Can't find editor '%s' in PATH\n"
2803 " (specify a commit editor in your configuration"
2778 " (specify a commit editor in your configuration"
2804 " file)\n"), not cmdpath and editor)
2779 " file)\n"), not cmdpath and editor)
2805 if not cmdpath and editor != 'vi':
2780 if not cmdpath and editor != 'vi':
2806 problems += 1
2781 problems += 1
2807
2782
2808 # check username
2783 # check username
2809 username = None
2784 username = None
2810 err = None
2785 err = None
2811 try:
2786 try:
2812 username = ui.username()
2787 username = ui.username()
2813 except error.Abort as e:
2788 except error.Abort as e:
2814 err = e
2789 err = e
2815 problems += 1
2790 problems += 1
2816
2791
2817 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2792 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2818 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2793 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2819 " (specify a username in your configuration file)\n"), err)
2794 " (specify a username in your configuration file)\n"), err)
2820
2795
2821 fm.condwrite(not problems, '',
2796 fm.condwrite(not problems, '',
2822 _("no problems detected\n"))
2797 _("no problems detected\n"))
2823 if not problems:
2798 if not problems:
2824 fm.data(problems=problems)
2799 fm.data(problems=problems)
2825 fm.condwrite(problems, 'problems',
2800 fm.condwrite(problems, 'problems',
2826 _("%s problems detected,"
2801 _("%s problems detected,"
2827 " please check your install!\n"), problems)
2802 " please check your install!\n"), problems)
2828 fm.end()
2803 fm.end()
2829
2804
2830 return problems
2805 return problems
2831
2806
2832 @command('debugknown', [], _('REPO ID...'), norepo=True)
2807 @command('debugknown', [], _('REPO ID...'), norepo=True)
2833 def debugknown(ui, repopath, *ids, **opts):
2808 def debugknown(ui, repopath, *ids, **opts):
2834 """test whether node ids are known to a repo
2809 """test whether node ids are known to a repo
2835
2810
2836 Every ID must be a full-length hex node id string. Returns a list of 0s
2811 Every ID must be a full-length hex node id string. Returns a list of 0s
2837 and 1s indicating unknown/known.
2812 and 1s indicating unknown/known.
2838 """
2813 """
2839 repo = hg.peer(ui, opts, repopath)
2814 repo = hg.peer(ui, opts, repopath)
2840 if not repo.capable('known'):
2815 if not repo.capable('known'):
2841 raise error.Abort("known() not supported by target repository")
2816 raise error.Abort("known() not supported by target repository")
2842 flags = repo.known([bin(s) for s in ids])
2817 flags = repo.known([bin(s) for s in ids])
2843 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2818 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2844
2819
2845 @command('debuglabelcomplete', [], _('LABEL...'))
2820 @command('debuglabelcomplete', [], _('LABEL...'))
2846 def debuglabelcomplete(ui, repo, *args):
2821 def debuglabelcomplete(ui, repo, *args):
2847 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2822 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2848 debugnamecomplete(ui, repo, *args)
2823 debugnamecomplete(ui, repo, *args)
2849
2824
2850 @command('debugmergestate', [], '')
2825 @command('debugmergestate', [], '')
2851 def debugmergestate(ui, repo, *args):
2826 def debugmergestate(ui, repo, *args):
2852 """print merge state
2827 """print merge state
2853
2828
2854 Use --verbose to print out information about whether v1 or v2 merge state
2829 Use --verbose to print out information about whether v1 or v2 merge state
2855 was chosen."""
2830 was chosen."""
2856 def _hashornull(h):
2831 def _hashornull(h):
2857 if h == nullhex:
2832 if h == nullhex:
2858 return 'null'
2833 return 'null'
2859 else:
2834 else:
2860 return h
2835 return h
2861
2836
2862 def printrecords(version):
2837 def printrecords(version):
2863 ui.write(('* version %s records\n') % version)
2838 ui.write(('* version %s records\n') % version)
2864 if version == 1:
2839 if version == 1:
2865 records = v1records
2840 records = v1records
2866 else:
2841 else:
2867 records = v2records
2842 records = v2records
2868
2843
2869 for rtype, record in records:
2844 for rtype, record in records:
2870 # pretty print some record types
2845 # pretty print some record types
2871 if rtype == 'L':
2846 if rtype == 'L':
2872 ui.write(('local: %s\n') % record)
2847 ui.write(('local: %s\n') % record)
2873 elif rtype == 'O':
2848 elif rtype == 'O':
2874 ui.write(('other: %s\n') % record)
2849 ui.write(('other: %s\n') % record)
2875 elif rtype == 'm':
2850 elif rtype == 'm':
2876 driver, mdstate = record.split('\0', 1)
2851 driver, mdstate = record.split('\0', 1)
2877 ui.write(('merge driver: %s (state "%s")\n')
2852 ui.write(('merge driver: %s (state "%s")\n')
2878 % (driver, mdstate))
2853 % (driver, mdstate))
2879 elif rtype in 'FDC':
2854 elif rtype in 'FDC':
2880 r = record.split('\0')
2855 r = record.split('\0')
2881 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2856 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2882 if version == 1:
2857 if version == 1:
2883 onode = 'not stored in v1 format'
2858 onode = 'not stored in v1 format'
2884 flags = r[7]
2859 flags = r[7]
2885 else:
2860 else:
2886 onode, flags = r[7:9]
2861 onode, flags = r[7:9]
2887 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2862 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2888 % (f, rtype, state, _hashornull(hash)))
2863 % (f, rtype, state, _hashornull(hash)))
2889 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2864 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2890 ui.write((' ancestor path: %s (node %s)\n')
2865 ui.write((' ancestor path: %s (node %s)\n')
2891 % (afile, _hashornull(anode)))
2866 % (afile, _hashornull(anode)))
2892 ui.write((' other path: %s (node %s)\n')
2867 ui.write((' other path: %s (node %s)\n')
2893 % (ofile, _hashornull(onode)))
2868 % (ofile, _hashornull(onode)))
2894 elif rtype == 'f':
2869 elif rtype == 'f':
2895 filename, rawextras = record.split('\0', 1)
2870 filename, rawextras = record.split('\0', 1)
2896 extras = rawextras.split('\0')
2871 extras = rawextras.split('\0')
2897 i = 0
2872 i = 0
2898 extrastrings = []
2873 extrastrings = []
2899 while i < len(extras):
2874 while i < len(extras):
2900 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2875 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2901 i += 2
2876 i += 2
2902
2877
2903 ui.write(('file extras: %s (%s)\n')
2878 ui.write(('file extras: %s (%s)\n')
2904 % (filename, ', '.join(extrastrings)))
2879 % (filename, ', '.join(extrastrings)))
2905 elif rtype == 'l':
2880 elif rtype == 'l':
2906 labels = record.split('\0', 2)
2881 labels = record.split('\0', 2)
2907 labels = [l for l in labels if len(l) > 0]
2882 labels = [l for l in labels if len(l) > 0]
2908 ui.write(('labels:\n'))
2883 ui.write(('labels:\n'))
2909 ui.write((' local: %s\n' % labels[0]))
2884 ui.write((' local: %s\n' % labels[0]))
2910 ui.write((' other: %s\n' % labels[1]))
2885 ui.write((' other: %s\n' % labels[1]))
2911 if len(labels) > 2:
2886 if len(labels) > 2:
2912 ui.write((' base: %s\n' % labels[2]))
2887 ui.write((' base: %s\n' % labels[2]))
2913 else:
2888 else:
2914 ui.write(('unrecognized entry: %s\t%s\n')
2889 ui.write(('unrecognized entry: %s\t%s\n')
2915 % (rtype, record.replace('\0', '\t')))
2890 % (rtype, record.replace('\0', '\t')))
2916
2891
2917 # Avoid mergestate.read() since it may raise an exception for unsupported
2892 # Avoid mergestate.read() since it may raise an exception for unsupported
2918 # merge state records. We shouldn't be doing this, but this is OK since this
2893 # merge state records. We shouldn't be doing this, but this is OK since this
2919 # command is pretty low-level.
2894 # command is pretty low-level.
2920 ms = mergemod.mergestate(repo)
2895 ms = mergemod.mergestate(repo)
2921
2896
2922 # sort so that reasonable information is on top
2897 # sort so that reasonable information is on top
2923 v1records = ms._readrecordsv1()
2898 v1records = ms._readrecordsv1()
2924 v2records = ms._readrecordsv2()
2899 v2records = ms._readrecordsv2()
2925 order = 'LOml'
2900 order = 'LOml'
2926 def key(r):
2901 def key(r):
2927 idx = order.find(r[0])
2902 idx = order.find(r[0])
2928 if idx == -1:
2903 if idx == -1:
2929 return (1, r[1])
2904 return (1, r[1])
2930 else:
2905 else:
2931 return (0, idx)
2906 return (0, idx)
2932 v1records.sort(key=key)
2907 v1records.sort(key=key)
2933 v2records.sort(key=key)
2908 v2records.sort(key=key)
2934
2909
2935 if not v1records and not v2records:
2910 if not v1records and not v2records:
2936 ui.write(('no merge state found\n'))
2911 ui.write(('no merge state found\n'))
2937 elif not v2records:
2912 elif not v2records:
2938 ui.note(('no version 2 merge state\n'))
2913 ui.note(('no version 2 merge state\n'))
2939 printrecords(1)
2914 printrecords(1)
2940 elif ms._v1v2match(v1records, v2records):
2915 elif ms._v1v2match(v1records, v2records):
2941 ui.note(('v1 and v2 states match: using v2\n'))
2916 ui.note(('v1 and v2 states match: using v2\n'))
2942 printrecords(2)
2917 printrecords(2)
2943 else:
2918 else:
2944 ui.note(('v1 and v2 states mismatch: using v1\n'))
2919 ui.note(('v1 and v2 states mismatch: using v1\n'))
2945 printrecords(1)
2920 printrecords(1)
2946 if ui.verbose:
2921 if ui.verbose:
2947 printrecords(2)
2922 printrecords(2)
2948
2923
2949 @command('debugnamecomplete', [], _('NAME...'))
2924 @command('debugnamecomplete', [], _('NAME...'))
2950 def debugnamecomplete(ui, repo, *args):
2925 def debugnamecomplete(ui, repo, *args):
2951 '''complete "names" - tags, open branch names, bookmark names'''
2926 '''complete "names" - tags, open branch names, bookmark names'''
2952
2927
2953 names = set()
2928 names = set()
2954 # since we previously only listed open branches, we will handle that
2929 # since we previously only listed open branches, we will handle that
2955 # specially (after this for loop)
2930 # specially (after this for loop)
2956 for name, ns in repo.names.iteritems():
2931 for name, ns in repo.names.iteritems():
2957 if name != 'branches':
2932 if name != 'branches':
2958 names.update(ns.listnames(repo))
2933 names.update(ns.listnames(repo))
2959 names.update(tag for (tag, heads, tip, closed)
2934 names.update(tag for (tag, heads, tip, closed)
2960 in repo.branchmap().iterbranches() if not closed)
2935 in repo.branchmap().iterbranches() if not closed)
2961 completions = set()
2936 completions = set()
2962 if not args:
2937 if not args:
2963 args = ['']
2938 args = ['']
2964 for a in args:
2939 for a in args:
2965 completions.update(n for n in names if n.startswith(a))
2940 completions.update(n for n in names if n.startswith(a))
2966 ui.write('\n'.join(sorted(completions)))
2941 ui.write('\n'.join(sorted(completions)))
2967 ui.write('\n')
2942 ui.write('\n')
2968
2943
2969 @command('debuglocks',
2944 @command('debuglocks',
2970 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2945 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2971 ('W', 'force-wlock', None,
2946 ('W', 'force-wlock', None,
2972 _('free the working state lock (DANGEROUS)'))],
2947 _('free the working state lock (DANGEROUS)'))],
2973 _('[OPTION]...'))
2948 _('[OPTION]...'))
2974 def debuglocks(ui, repo, **opts):
2949 def debuglocks(ui, repo, **opts):
2975 """show or modify state of locks
2950 """show or modify state of locks
2976
2951
2977 By default, this command will show which locks are held. This
2952 By default, this command will show which locks are held. This
2978 includes the user and process holding the lock, the amount of time
2953 includes the user and process holding the lock, the amount of time
2979 the lock has been held, and the machine name where the process is
2954 the lock has been held, and the machine name where the process is
2980 running if it's not local.
2955 running if it's not local.
2981
2956
2982 Locks protect the integrity of Mercurial's data, so should be
2957 Locks protect the integrity of Mercurial's data, so should be
2983 treated with care. System crashes or other interruptions may cause
2958 treated with care. System crashes or other interruptions may cause
2984 locks to not be properly released, though Mercurial will usually
2959 locks to not be properly released, though Mercurial will usually
2985 detect and remove such stale locks automatically.
2960 detect and remove such stale locks automatically.
2986
2961
2987 However, detecting stale locks may not always be possible (for
2962 However, detecting stale locks may not always be possible (for
2988 instance, on a shared filesystem). Removing locks may also be
2963 instance, on a shared filesystem). Removing locks may also be
2989 blocked by filesystem permissions.
2964 blocked by filesystem permissions.
2990
2965
2991 Returns 0 if no locks are held.
2966 Returns 0 if no locks are held.
2992
2967
2993 """
2968 """
2994
2969
2995 if opts.get('force_lock'):
2970 if opts.get('force_lock'):
2996 repo.svfs.unlink('lock')
2971 repo.svfs.unlink('lock')
2997 if opts.get('force_wlock'):
2972 if opts.get('force_wlock'):
2998 repo.vfs.unlink('wlock')
2973 repo.vfs.unlink('wlock')
2999 if opts.get('force_lock') or opts.get('force_lock'):
2974 if opts.get('force_lock') or opts.get('force_lock'):
3000 return 0
2975 return 0
3001
2976
3002 now = time.time()
2977 now = time.time()
3003 held = 0
2978 held = 0
3004
2979
3005 def report(vfs, name, method):
2980 def report(vfs, name, method):
3006 # this causes stale locks to get reaped for more accurate reporting
2981 # this causes stale locks to get reaped for more accurate reporting
3007 try:
2982 try:
3008 l = method(False)
2983 l = method(False)
3009 except error.LockHeld:
2984 except error.LockHeld:
3010 l = None
2985 l = None
3011
2986
3012 if l:
2987 if l:
3013 l.release()
2988 l.release()
3014 else:
2989 else:
3015 try:
2990 try:
3016 stat = vfs.lstat(name)
2991 stat = vfs.lstat(name)
3017 age = now - stat.st_mtime
2992 age = now - stat.st_mtime
3018 user = util.username(stat.st_uid)
2993 user = util.username(stat.st_uid)
3019 locker = vfs.readlock(name)
2994 locker = vfs.readlock(name)
3020 if ":" in locker:
2995 if ":" in locker:
3021 host, pid = locker.split(':')
2996 host, pid = locker.split(':')
3022 if host == socket.gethostname():
2997 if host == socket.gethostname():
3023 locker = 'user %s, process %s' % (user, pid)
2998 locker = 'user %s, process %s' % (user, pid)
3024 else:
2999 else:
3025 locker = 'user %s, process %s, host %s' \
3000 locker = 'user %s, process %s, host %s' \
3026 % (user, pid, host)
3001 % (user, pid, host)
3027 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3002 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
3028 return 1
3003 return 1
3029 except OSError as e:
3004 except OSError as e:
3030 if e.errno != errno.ENOENT:
3005 if e.errno != errno.ENOENT:
3031 raise
3006 raise
3032
3007
3033 ui.write(("%-6s free\n") % (name + ":"))
3008 ui.write(("%-6s free\n") % (name + ":"))
3034 return 0
3009 return 0
3035
3010
3036 held += report(repo.svfs, "lock", repo.lock)
3011 held += report(repo.svfs, "lock", repo.lock)
3037 held += report(repo.vfs, "wlock", repo.wlock)
3012 held += report(repo.vfs, "wlock", repo.wlock)
3038
3013
3039 return held
3014 return held
3040
3015
3041 @command('debugobsolete',
3016 @command('debugobsolete',
3042 [('', 'flags', 0, _('markers flag')),
3017 [('', 'flags', 0, _('markers flag')),
3043 ('', 'record-parents', False,
3018 ('', 'record-parents', False,
3044 _('record parent information for the precursor')),
3019 _('record parent information for the precursor')),
3045 ('r', 'rev', [], _('display markers relevant to REV')),
3020 ('r', 'rev', [], _('display markers relevant to REV')),
3046 ('', 'index', False, _('display index of the marker')),
3021 ('', 'index', False, _('display index of the marker')),
3047 ('', 'delete', [], _('delete markers specified by indices')),
3022 ('', 'delete', [], _('delete markers specified by indices')),
3048 ] + commitopts2 + formatteropts,
3023 ] + commitopts2 + formatteropts,
3049 _('[OBSOLETED [REPLACEMENT ...]]'))
3024 _('[OBSOLETED [REPLACEMENT ...]]'))
3050 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3025 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
3051 """create arbitrary obsolete marker
3026 """create arbitrary obsolete marker
3052
3027
3053 With no arguments, displays the list of obsolescence markers."""
3028 With no arguments, displays the list of obsolescence markers."""
3054
3029
3055 def parsenodeid(s):
3030 def parsenodeid(s):
3056 try:
3031 try:
3057 # We do not use revsingle/revrange functions here to accept
3032 # We do not use revsingle/revrange functions here to accept
3058 # arbitrary node identifiers, possibly not present in the
3033 # arbitrary node identifiers, possibly not present in the
3059 # local repository.
3034 # local repository.
3060 n = bin(s)
3035 n = bin(s)
3061 if len(n) != len(nullid):
3036 if len(n) != len(nullid):
3062 raise TypeError()
3037 raise TypeError()
3063 return n
3038 return n
3064 except TypeError:
3039 except TypeError:
3065 raise error.Abort('changeset references must be full hexadecimal '
3040 raise error.Abort('changeset references must be full hexadecimal '
3066 'node identifiers')
3041 'node identifiers')
3067
3042
3068 if opts.get('delete'):
3043 if opts.get('delete'):
3069 indices = []
3044 indices = []
3070 for v in opts.get('delete'):
3045 for v in opts.get('delete'):
3071 try:
3046 try:
3072 indices.append(int(v))
3047 indices.append(int(v))
3073 except ValueError:
3048 except ValueError:
3074 raise error.Abort(_('invalid index value: %r') % v,
3049 raise error.Abort(_('invalid index value: %r') % v,
3075 hint=_('use integers for indices'))
3050 hint=_('use integers for indices'))
3076
3051
3077 if repo.currenttransaction():
3052 if repo.currenttransaction():
3078 raise error.Abort(_('cannot delete obsmarkers in the middle '
3053 raise error.Abort(_('cannot delete obsmarkers in the middle '
3079 'of transaction.'))
3054 'of transaction.'))
3080
3055
3081 with repo.lock():
3056 with repo.lock():
3082 n = repair.deleteobsmarkers(repo.obsstore, indices)
3057 n = repair.deleteobsmarkers(repo.obsstore, indices)
3083 ui.write(_('deleted %i obsolescense markers\n') % n)
3058 ui.write(_('deleted %i obsolescense markers\n') % n)
3084
3059
3085 return
3060 return
3086
3061
3087 if precursor is not None:
3062 if precursor is not None:
3088 if opts['rev']:
3063 if opts['rev']:
3089 raise error.Abort('cannot select revision when creating marker')
3064 raise error.Abort('cannot select revision when creating marker')
3090 metadata = {}
3065 metadata = {}
3091 metadata['user'] = opts['user'] or ui.username()
3066 metadata['user'] = opts['user'] or ui.username()
3092 succs = tuple(parsenodeid(succ) for succ in successors)
3067 succs = tuple(parsenodeid(succ) for succ in successors)
3093 l = repo.lock()
3068 l = repo.lock()
3094 try:
3069 try:
3095 tr = repo.transaction('debugobsolete')
3070 tr = repo.transaction('debugobsolete')
3096 try:
3071 try:
3097 date = opts.get('date')
3072 date = opts.get('date')
3098 if date:
3073 if date:
3099 date = util.parsedate(date)
3074 date = util.parsedate(date)
3100 else:
3075 else:
3101 date = None
3076 date = None
3102 prec = parsenodeid(precursor)
3077 prec = parsenodeid(precursor)
3103 parents = None
3078 parents = None
3104 if opts['record_parents']:
3079 if opts['record_parents']:
3105 if prec not in repo.unfiltered():
3080 if prec not in repo.unfiltered():
3106 raise error.Abort('cannot used --record-parents on '
3081 raise error.Abort('cannot used --record-parents on '
3107 'unknown changesets')
3082 'unknown changesets')
3108 parents = repo.unfiltered()[prec].parents()
3083 parents = repo.unfiltered()[prec].parents()
3109 parents = tuple(p.node() for p in parents)
3084 parents = tuple(p.node() for p in parents)
3110 repo.obsstore.create(tr, prec, succs, opts['flags'],
3085 repo.obsstore.create(tr, prec, succs, opts['flags'],
3111 parents=parents, date=date,
3086 parents=parents, date=date,
3112 metadata=metadata)
3087 metadata=metadata)
3113 tr.close()
3088 tr.close()
3114 except ValueError as exc:
3089 except ValueError as exc:
3115 raise error.Abort(_('bad obsmarker input: %s') % exc)
3090 raise error.Abort(_('bad obsmarker input: %s') % exc)
3116 finally:
3091 finally:
3117 tr.release()
3092 tr.release()
3118 finally:
3093 finally:
3119 l.release()
3094 l.release()
3120 else:
3095 else:
3121 if opts['rev']:
3096 if opts['rev']:
3122 revs = scmutil.revrange(repo, opts['rev'])
3097 revs = scmutil.revrange(repo, opts['rev'])
3123 nodes = [repo[r].node() for r in revs]
3098 nodes = [repo[r].node() for r in revs]
3124 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3099 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3125 markers.sort(key=lambda x: x._data)
3100 markers.sort(key=lambda x: x._data)
3126 else:
3101 else:
3127 markers = obsolete.getmarkers(repo)
3102 markers = obsolete.getmarkers(repo)
3128
3103
3129 markerstoiter = markers
3104 markerstoiter = markers
3130 isrelevant = lambda m: True
3105 isrelevant = lambda m: True
3131 if opts.get('rev') and opts.get('index'):
3106 if opts.get('rev') and opts.get('index'):
3132 markerstoiter = obsolete.getmarkers(repo)
3107 markerstoiter = obsolete.getmarkers(repo)
3133 markerset = set(markers)
3108 markerset = set(markers)
3134 isrelevant = lambda m: m in markerset
3109 isrelevant = lambda m: m in markerset
3135
3110
3136 fm = ui.formatter('debugobsolete', opts)
3111 fm = ui.formatter('debugobsolete', opts)
3137 for i, m in enumerate(markerstoiter):
3112 for i, m in enumerate(markerstoiter):
3138 if not isrelevant(m):
3113 if not isrelevant(m):
3139 # marker can be irrelevant when we're iterating over a set
3114 # marker can be irrelevant when we're iterating over a set
3140 # of markers (markerstoiter) which is bigger than the set
3115 # of markers (markerstoiter) which is bigger than the set
3141 # of markers we want to display (markers)
3116 # of markers we want to display (markers)
3142 # this can happen if both --index and --rev options are
3117 # this can happen if both --index and --rev options are
3143 # provided and thus we need to iterate over all of the markers
3118 # provided and thus we need to iterate over all of the markers
3144 # to get the correct indices, but only display the ones that
3119 # to get the correct indices, but only display the ones that
3145 # are relevant to --rev value
3120 # are relevant to --rev value
3146 continue
3121 continue
3147 fm.startitem()
3122 fm.startitem()
3148 ind = i if opts.get('index') else None
3123 ind = i if opts.get('index') else None
3149 cmdutil.showmarker(fm, m, index=ind)
3124 cmdutil.showmarker(fm, m, index=ind)
3150 fm.end()
3125 fm.end()
3151
3126
3152 @command('debugpathcomplete',
3127 @command('debugpathcomplete',
3153 [('f', 'full', None, _('complete an entire path')),
3128 [('f', 'full', None, _('complete an entire path')),
3154 ('n', 'normal', None, _('show only normal files')),
3129 ('n', 'normal', None, _('show only normal files')),
3155 ('a', 'added', None, _('show only added files')),
3130 ('a', 'added', None, _('show only added files')),
3156 ('r', 'removed', None, _('show only removed files'))],
3131 ('r', 'removed', None, _('show only removed files'))],
3157 _('FILESPEC...'))
3132 _('FILESPEC...'))
3158 def debugpathcomplete(ui, repo, *specs, **opts):
3133 def debugpathcomplete(ui, repo, *specs, **opts):
3159 '''complete part or all of a tracked path
3134 '''complete part or all of a tracked path
3160
3135
3161 This command supports shells that offer path name completion. It
3136 This command supports shells that offer path name completion. It
3162 currently completes only files already known to the dirstate.
3137 currently completes only files already known to the dirstate.
3163
3138
3164 Completion extends only to the next path segment unless
3139 Completion extends only to the next path segment unless
3165 --full is specified, in which case entire paths are used.'''
3140 --full is specified, in which case entire paths are used.'''
3166
3141
3167 def complete(path, acceptable):
3142 def complete(path, acceptable):
3168 dirstate = repo.dirstate
3143 dirstate = repo.dirstate
3169 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3144 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3170 rootdir = repo.root + os.sep
3145 rootdir = repo.root + os.sep
3171 if spec != repo.root and not spec.startswith(rootdir):
3146 if spec != repo.root and not spec.startswith(rootdir):
3172 return [], []
3147 return [], []
3173 if os.path.isdir(spec):
3148 if os.path.isdir(spec):
3174 spec += '/'
3149 spec += '/'
3175 spec = spec[len(rootdir):]
3150 spec = spec[len(rootdir):]
3176 fixpaths = os.sep != '/'
3151 fixpaths = os.sep != '/'
3177 if fixpaths:
3152 if fixpaths:
3178 spec = spec.replace(os.sep, '/')
3153 spec = spec.replace(os.sep, '/')
3179 speclen = len(spec)
3154 speclen = len(spec)
3180 fullpaths = opts['full']
3155 fullpaths = opts['full']
3181 files, dirs = set(), set()
3156 files, dirs = set(), set()
3182 adddir, addfile = dirs.add, files.add
3157 adddir, addfile = dirs.add, files.add
3183 for f, st in dirstate.iteritems():
3158 for f, st in dirstate.iteritems():
3184 if f.startswith(spec) and st[0] in acceptable:
3159 if f.startswith(spec) and st[0] in acceptable:
3185 if fixpaths:
3160 if fixpaths:
3186 f = f.replace('/', os.sep)
3161 f = f.replace('/', os.sep)
3187 if fullpaths:
3162 if fullpaths:
3188 addfile(f)
3163 addfile(f)
3189 continue
3164 continue
3190 s = f.find(os.sep, speclen)
3165 s = f.find(os.sep, speclen)
3191 if s >= 0:
3166 if s >= 0:
3192 adddir(f[:s])
3167 adddir(f[:s])
3193 else:
3168 else:
3194 addfile(f)
3169 addfile(f)
3195 return files, dirs
3170 return files, dirs
3196
3171
3197 acceptable = ''
3172 acceptable = ''
3198 if opts['normal']:
3173 if opts['normal']:
3199 acceptable += 'nm'
3174 acceptable += 'nm'
3200 if opts['added']:
3175 if opts['added']:
3201 acceptable += 'a'
3176 acceptable += 'a'
3202 if opts['removed']:
3177 if opts['removed']:
3203 acceptable += 'r'
3178 acceptable += 'r'
3204 cwd = repo.getcwd()
3179 cwd = repo.getcwd()
3205 if not specs:
3180 if not specs:
3206 specs = ['.']
3181 specs = ['.']
3207
3182
3208 files, dirs = set(), set()
3183 files, dirs = set(), set()
3209 for spec in specs:
3184 for spec in specs:
3210 f, d = complete(spec, acceptable or 'nmar')
3185 f, d = complete(spec, acceptable or 'nmar')
3211 files.update(f)
3186 files.update(f)
3212 dirs.update(d)
3187 dirs.update(d)
3213 files.update(dirs)
3188 files.update(dirs)
3214 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3189 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3215 ui.write('\n')
3190 ui.write('\n')
3216
3191
3217 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3192 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3218 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3193 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3219 '''access the pushkey key/value protocol
3194 '''access the pushkey key/value protocol
3220
3195
3221 With two args, list the keys in the given namespace.
3196 With two args, list the keys in the given namespace.
3222
3197
3223 With five args, set a key to new if it currently is set to old.
3198 With five args, set a key to new if it currently is set to old.
3224 Reports success or failure.
3199 Reports success or failure.
3225 '''
3200 '''
3226
3201
3227 target = hg.peer(ui, {}, repopath)
3202 target = hg.peer(ui, {}, repopath)
3228 if keyinfo:
3203 if keyinfo:
3229 key, old, new = keyinfo
3204 key, old, new = keyinfo
3230 r = target.pushkey(namespace, key, old, new)
3205 r = target.pushkey(namespace, key, old, new)
3231 ui.status(str(r) + '\n')
3206 ui.status(str(r) + '\n')
3232 return not r
3207 return not r
3233 else:
3208 else:
3234 for k, v in sorted(target.listkeys(namespace).iteritems()):
3209 for k, v in sorted(target.listkeys(namespace).iteritems()):
3235 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3210 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3236 v.encode('string-escape')))
3211 v.encode('string-escape')))
3237
3212
3238 @command('debugpvec', [], _('A B'))
3213 @command('debugpvec', [], _('A B'))
3239 def debugpvec(ui, repo, a, b=None):
3214 def debugpvec(ui, repo, a, b=None):
3240 ca = scmutil.revsingle(repo, a)
3215 ca = scmutil.revsingle(repo, a)
3241 cb = scmutil.revsingle(repo, b)
3216 cb = scmutil.revsingle(repo, b)
3242 pa = pvec.ctxpvec(ca)
3217 pa = pvec.ctxpvec(ca)
3243 pb = pvec.ctxpvec(cb)
3218 pb = pvec.ctxpvec(cb)
3244 if pa == pb:
3219 if pa == pb:
3245 rel = "="
3220 rel = "="
3246 elif pa > pb:
3221 elif pa > pb:
3247 rel = ">"
3222 rel = ">"
3248 elif pa < pb:
3223 elif pa < pb:
3249 rel = "<"
3224 rel = "<"
3250 elif pa | pb:
3225 elif pa | pb:
3251 rel = "|"
3226 rel = "|"
3252 ui.write(_("a: %s\n") % pa)
3227 ui.write(_("a: %s\n") % pa)
3253 ui.write(_("b: %s\n") % pb)
3228 ui.write(_("b: %s\n") % pb)
3254 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3229 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3255 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3230 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3256 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3231 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3257 pa.distance(pb), rel))
3232 pa.distance(pb), rel))
3258
3233
3259 @command('debugrebuilddirstate|debugrebuildstate',
3234 @command('debugrebuilddirstate|debugrebuildstate',
3260 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3235 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3261 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3236 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3262 'the working copy parent')),
3237 'the working copy parent')),
3263 ],
3238 ],
3264 _('[-r REV]'))
3239 _('[-r REV]'))
3265 def debugrebuilddirstate(ui, repo, rev, **opts):
3240 def debugrebuilddirstate(ui, repo, rev, **opts):
3266 """rebuild the dirstate as it would look like for the given revision
3241 """rebuild the dirstate as it would look like for the given revision
3267
3242
3268 If no revision is specified the first current parent will be used.
3243 If no revision is specified the first current parent will be used.
3269
3244
3270 The dirstate will be set to the files of the given revision.
3245 The dirstate will be set to the files of the given revision.
3271 The actual working directory content or existing dirstate
3246 The actual working directory content or existing dirstate
3272 information such as adds or removes is not considered.
3247 information such as adds or removes is not considered.
3273
3248
3274 ``minimal`` will only rebuild the dirstate status for files that claim to be
3249 ``minimal`` will only rebuild the dirstate status for files that claim to be
3275 tracked but are not in the parent manifest, or that exist in the parent
3250 tracked but are not in the parent manifest, or that exist in the parent
3276 manifest but are not in the dirstate. It will not change adds, removes, or
3251 manifest but are not in the dirstate. It will not change adds, removes, or
3277 modified files that are in the working copy parent.
3252 modified files that are in the working copy parent.
3278
3253
3279 One use of this command is to make the next :hg:`status` invocation
3254 One use of this command is to make the next :hg:`status` invocation
3280 check the actual file content.
3255 check the actual file content.
3281 """
3256 """
3282 ctx = scmutil.revsingle(repo, rev)
3257 ctx = scmutil.revsingle(repo, rev)
3283 with repo.wlock():
3258 with repo.wlock():
3284 dirstate = repo.dirstate
3259 dirstate = repo.dirstate
3285 changedfiles = None
3260 changedfiles = None
3286 # See command doc for what minimal does.
3261 # See command doc for what minimal does.
3287 if opts.get('minimal'):
3262 if opts.get('minimal'):
3288 manifestfiles = set(ctx.manifest().keys())
3263 manifestfiles = set(ctx.manifest().keys())
3289 dirstatefiles = set(dirstate)
3264 dirstatefiles = set(dirstate)
3290 manifestonly = manifestfiles - dirstatefiles
3265 manifestonly = manifestfiles - dirstatefiles
3291 dsonly = dirstatefiles - manifestfiles
3266 dsonly = dirstatefiles - manifestfiles
3292 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3267 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3293 changedfiles = manifestonly | dsnotadded
3268 changedfiles = manifestonly | dsnotadded
3294
3269
3295 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3270 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3296
3271
3297 @command('debugrebuildfncache', [], '')
3272 @command('debugrebuildfncache', [], '')
3298 def debugrebuildfncache(ui, repo):
3273 def debugrebuildfncache(ui, repo):
3299 """rebuild the fncache file"""
3274 """rebuild the fncache file"""
3300 repair.rebuildfncache(ui, repo)
3275 repair.rebuildfncache(ui, repo)
3301
3276
3302 @command('debugrename',
3277 @command('debugrename',
3303 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3278 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3304 _('[-r REV] FILE'))
3279 _('[-r REV] FILE'))
3305 def debugrename(ui, repo, file1, *pats, **opts):
3280 def debugrename(ui, repo, file1, *pats, **opts):
3306 """dump rename information"""
3281 """dump rename information"""
3307
3282
3308 ctx = scmutil.revsingle(repo, opts.get('rev'))
3283 ctx = scmutil.revsingle(repo, opts.get('rev'))
3309 m = scmutil.match(ctx, (file1,) + pats, opts)
3284 m = scmutil.match(ctx, (file1,) + pats, opts)
3310 for abs in ctx.walk(m):
3285 for abs in ctx.walk(m):
3311 fctx = ctx[abs]
3286 fctx = ctx[abs]
3312 o = fctx.filelog().renamed(fctx.filenode())
3287 o = fctx.filelog().renamed(fctx.filenode())
3313 rel = m.rel(abs)
3288 rel = m.rel(abs)
3314 if o:
3289 if o:
3315 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3290 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3316 else:
3291 else:
3317 ui.write(_("%s not renamed\n") % rel)
3292 ui.write(_("%s not renamed\n") % rel)
3318
3293
3319 @command('debugrevlog', debugrevlogopts +
3294 @command('debugrevlog', debugrevlogopts +
3320 [('d', 'dump', False, _('dump index data'))],
3295 [('d', 'dump', False, _('dump index data'))],
3321 _('-c|-m|FILE'),
3296 _('-c|-m|FILE'),
3322 optionalrepo=True)
3297 optionalrepo=True)
3323 def debugrevlog(ui, repo, file_=None, **opts):
3298 def debugrevlog(ui, repo, file_=None, **opts):
3324 """show data and statistics about a revlog"""
3299 """show data and statistics about a revlog"""
3325 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3300 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3326
3301
3327 if opts.get("dump"):
3302 if opts.get("dump"):
3328 numrevs = len(r)
3303 numrevs = len(r)
3329 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3304 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3330 " rawsize totalsize compression heads chainlen\n"))
3305 " rawsize totalsize compression heads chainlen\n"))
3331 ts = 0
3306 ts = 0
3332 heads = set()
3307 heads = set()
3333
3308
3334 for rev in xrange(numrevs):
3309 for rev in xrange(numrevs):
3335 dbase = r.deltaparent(rev)
3310 dbase = r.deltaparent(rev)
3336 if dbase == -1:
3311 if dbase == -1:
3337 dbase = rev
3312 dbase = rev
3338 cbase = r.chainbase(rev)
3313 cbase = r.chainbase(rev)
3339 clen = r.chainlen(rev)
3314 clen = r.chainlen(rev)
3340 p1, p2 = r.parentrevs(rev)
3315 p1, p2 = r.parentrevs(rev)
3341 rs = r.rawsize(rev)
3316 rs = r.rawsize(rev)
3342 ts = ts + rs
3317 ts = ts + rs
3343 heads -= set(r.parentrevs(rev))
3318 heads -= set(r.parentrevs(rev))
3344 heads.add(rev)
3319 heads.add(rev)
3345 try:
3320 try:
3346 compression = ts / r.end(rev)
3321 compression = ts / r.end(rev)
3347 except ZeroDivisionError:
3322 except ZeroDivisionError:
3348 compression = 0
3323 compression = 0
3349 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3324 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3350 "%11d %5d %8d\n" %
3325 "%11d %5d %8d\n" %
3351 (rev, p1, p2, r.start(rev), r.end(rev),
3326 (rev, p1, p2, r.start(rev), r.end(rev),
3352 r.start(dbase), r.start(cbase),
3327 r.start(dbase), r.start(cbase),
3353 r.start(p1), r.start(p2),
3328 r.start(p1), r.start(p2),
3354 rs, ts, compression, len(heads), clen))
3329 rs, ts, compression, len(heads), clen))
3355 return 0
3330 return 0
3356
3331
3357 v = r.version
3332 v = r.version
3358 format = v & 0xFFFF
3333 format = v & 0xFFFF
3359 flags = []
3334 flags = []
3360 gdelta = False
3335 gdelta = False
3361 if v & revlog.REVLOGNGINLINEDATA:
3336 if v & revlog.REVLOGNGINLINEDATA:
3362 flags.append('inline')
3337 flags.append('inline')
3363 if v & revlog.REVLOGGENERALDELTA:
3338 if v & revlog.REVLOGGENERALDELTA:
3364 gdelta = True
3339 gdelta = True
3365 flags.append('generaldelta')
3340 flags.append('generaldelta')
3366 if not flags:
3341 if not flags:
3367 flags = ['(none)']
3342 flags = ['(none)']
3368
3343
3369 nummerges = 0
3344 nummerges = 0
3370 numfull = 0
3345 numfull = 0
3371 numprev = 0
3346 numprev = 0
3372 nump1 = 0
3347 nump1 = 0
3373 nump2 = 0
3348 nump2 = 0
3374 numother = 0
3349 numother = 0
3375 nump1prev = 0
3350 nump1prev = 0
3376 nump2prev = 0
3351 nump2prev = 0
3377 chainlengths = []
3352 chainlengths = []
3378
3353
3379 datasize = [None, 0, 0]
3354 datasize = [None, 0, 0]
3380 fullsize = [None, 0, 0]
3355 fullsize = [None, 0, 0]
3381 deltasize = [None, 0, 0]
3356 deltasize = [None, 0, 0]
3382
3357
3383 def addsize(size, l):
3358 def addsize(size, l):
3384 if l[0] is None or size < l[0]:
3359 if l[0] is None or size < l[0]:
3385 l[0] = size
3360 l[0] = size
3386 if size > l[1]:
3361 if size > l[1]:
3387 l[1] = size
3362 l[1] = size
3388 l[2] += size
3363 l[2] += size
3389
3364
3390 numrevs = len(r)
3365 numrevs = len(r)
3391 for rev in xrange(numrevs):
3366 for rev in xrange(numrevs):
3392 p1, p2 = r.parentrevs(rev)
3367 p1, p2 = r.parentrevs(rev)
3393 delta = r.deltaparent(rev)
3368 delta = r.deltaparent(rev)
3394 if format > 0:
3369 if format > 0:
3395 addsize(r.rawsize(rev), datasize)
3370 addsize(r.rawsize(rev), datasize)
3396 if p2 != nullrev:
3371 if p2 != nullrev:
3397 nummerges += 1
3372 nummerges += 1
3398 size = r.length(rev)
3373 size = r.length(rev)
3399 if delta == nullrev:
3374 if delta == nullrev:
3400 chainlengths.append(0)
3375 chainlengths.append(0)
3401 numfull += 1
3376 numfull += 1
3402 addsize(size, fullsize)
3377 addsize(size, fullsize)
3403 else:
3378 else:
3404 chainlengths.append(chainlengths[delta] + 1)
3379 chainlengths.append(chainlengths[delta] + 1)
3405 addsize(size, deltasize)
3380 addsize(size, deltasize)
3406 if delta == rev - 1:
3381 if delta == rev - 1:
3407 numprev += 1
3382 numprev += 1
3408 if delta == p1:
3383 if delta == p1:
3409 nump1prev += 1
3384 nump1prev += 1
3410 elif delta == p2:
3385 elif delta == p2:
3411 nump2prev += 1
3386 nump2prev += 1
3412 elif delta == p1:
3387 elif delta == p1:
3413 nump1 += 1
3388 nump1 += 1
3414 elif delta == p2:
3389 elif delta == p2:
3415 nump2 += 1
3390 nump2 += 1
3416 elif delta != nullrev:
3391 elif delta != nullrev:
3417 numother += 1
3392 numother += 1
3418
3393
3419 # Adjust size min value for empty cases
3394 # Adjust size min value for empty cases
3420 for size in (datasize, fullsize, deltasize):
3395 for size in (datasize, fullsize, deltasize):
3421 if size[0] is None:
3396 if size[0] is None:
3422 size[0] = 0
3397 size[0] = 0
3423
3398
3424 numdeltas = numrevs - numfull
3399 numdeltas = numrevs - numfull
3425 numoprev = numprev - nump1prev - nump2prev
3400 numoprev = numprev - nump1prev - nump2prev
3426 totalrawsize = datasize[2]
3401 totalrawsize = datasize[2]
3427 datasize[2] /= numrevs
3402 datasize[2] /= numrevs
3428 fulltotal = fullsize[2]
3403 fulltotal = fullsize[2]
3429 fullsize[2] /= numfull
3404 fullsize[2] /= numfull
3430 deltatotal = deltasize[2]
3405 deltatotal = deltasize[2]
3431 if numrevs - numfull > 0:
3406 if numrevs - numfull > 0:
3432 deltasize[2] /= numrevs - numfull
3407 deltasize[2] /= numrevs - numfull
3433 totalsize = fulltotal + deltatotal
3408 totalsize = fulltotal + deltatotal
3434 avgchainlen = sum(chainlengths) / numrevs
3409 avgchainlen = sum(chainlengths) / numrevs
3435 maxchainlen = max(chainlengths)
3410 maxchainlen = max(chainlengths)
3436 compratio = 1
3411 compratio = 1
3437 if totalsize:
3412 if totalsize:
3438 compratio = totalrawsize / totalsize
3413 compratio = totalrawsize / totalsize
3439
3414
3440 basedfmtstr = '%%%dd\n'
3415 basedfmtstr = '%%%dd\n'
3441 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3416 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3442
3417
3443 def dfmtstr(max):
3418 def dfmtstr(max):
3444 return basedfmtstr % len(str(max))
3419 return basedfmtstr % len(str(max))
3445 def pcfmtstr(max, padding=0):
3420 def pcfmtstr(max, padding=0):
3446 return basepcfmtstr % (len(str(max)), ' ' * padding)
3421 return basepcfmtstr % (len(str(max)), ' ' * padding)
3447
3422
3448 def pcfmt(value, total):
3423 def pcfmt(value, total):
3449 if total:
3424 if total:
3450 return (value, 100 * float(value) / total)
3425 return (value, 100 * float(value) / total)
3451 else:
3426 else:
3452 return value, 100.0
3427 return value, 100.0
3453
3428
3454 ui.write(('format : %d\n') % format)
3429 ui.write(('format : %d\n') % format)
3455 ui.write(('flags : %s\n') % ', '.join(flags))
3430 ui.write(('flags : %s\n') % ', '.join(flags))
3456
3431
3457 ui.write('\n')
3432 ui.write('\n')
3458 fmt = pcfmtstr(totalsize)
3433 fmt = pcfmtstr(totalsize)
3459 fmt2 = dfmtstr(totalsize)
3434 fmt2 = dfmtstr(totalsize)
3460 ui.write(('revisions : ') + fmt2 % numrevs)
3435 ui.write(('revisions : ') + fmt2 % numrevs)
3461 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3436 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3462 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3437 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3463 ui.write(('revisions : ') + fmt2 % numrevs)
3438 ui.write(('revisions : ') + fmt2 % numrevs)
3464 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3439 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3465 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3440 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3466 ui.write(('revision size : ') + fmt2 % totalsize)
3441 ui.write(('revision size : ') + fmt2 % totalsize)
3467 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3442 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3468 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3443 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3469
3444
3470 ui.write('\n')
3445 ui.write('\n')
3471 fmt = dfmtstr(max(avgchainlen, compratio))
3446 fmt = dfmtstr(max(avgchainlen, compratio))
3472 ui.write(('avg chain length : ') + fmt % avgchainlen)
3447 ui.write(('avg chain length : ') + fmt % avgchainlen)
3473 ui.write(('max chain length : ') + fmt % maxchainlen)
3448 ui.write(('max chain length : ') + fmt % maxchainlen)
3474 ui.write(('compression ratio : ') + fmt % compratio)
3449 ui.write(('compression ratio : ') + fmt % compratio)
3475
3450
3476 if format > 0:
3451 if format > 0:
3477 ui.write('\n')
3452 ui.write('\n')
3478 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3453 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3479 % tuple(datasize))
3454 % tuple(datasize))
3480 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3455 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3481 % tuple(fullsize))
3456 % tuple(fullsize))
3482 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3457 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3483 % tuple(deltasize))
3458 % tuple(deltasize))
3484
3459
3485 if numdeltas > 0:
3460 if numdeltas > 0:
3486 ui.write('\n')
3461 ui.write('\n')
3487 fmt = pcfmtstr(numdeltas)
3462 fmt = pcfmtstr(numdeltas)
3488 fmt2 = pcfmtstr(numdeltas, 4)
3463 fmt2 = pcfmtstr(numdeltas, 4)
3489 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3464 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3490 if numprev > 0:
3465 if numprev > 0:
3491 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3466 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3492 numprev))
3467 numprev))
3493 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3468 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3494 numprev))
3469 numprev))
3495 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3470 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3496 numprev))
3471 numprev))
3497 if gdelta:
3472 if gdelta:
3498 ui.write(('deltas against p1 : ')
3473 ui.write(('deltas against p1 : ')
3499 + fmt % pcfmt(nump1, numdeltas))
3474 + fmt % pcfmt(nump1, numdeltas))
3500 ui.write(('deltas against p2 : ')
3475 ui.write(('deltas against p2 : ')
3501 + fmt % pcfmt(nump2, numdeltas))
3476 + fmt % pcfmt(nump2, numdeltas))
3502 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3477 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3503 numdeltas))
3478 numdeltas))
3504
3479
3505 @command('debugrevspec',
3480 @command('debugrevspec',
3506 [('', 'optimize', None,
3481 [('', 'optimize', None,
3507 _('print parsed tree after optimizing (DEPRECATED)')),
3482 _('print parsed tree after optimizing (DEPRECATED)')),
3508 ('p', 'show-stage', [],
3483 ('p', 'show-stage', [],
3509 _('print parsed tree at the given stage'), _('NAME')),
3484 _('print parsed tree at the given stage'), _('NAME')),
3510 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3485 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3511 ('', 'verify-optimized', False, _('verify optimized result')),
3486 ('', 'verify-optimized', False, _('verify optimized result')),
3512 ],
3487 ],
3513 ('REVSPEC'))
3488 ('REVSPEC'))
3514 def debugrevspec(ui, repo, expr, **opts):
3489 def debugrevspec(ui, repo, expr, **opts):
3515 """parse and apply a revision specification
3490 """parse and apply a revision specification
3516
3491
3517 Use -p/--show-stage option to print the parsed tree at the given stages.
3492 Use -p/--show-stage option to print the parsed tree at the given stages.
3518 Use -p all to print tree at every stage.
3493 Use -p all to print tree at every stage.
3519
3494
3520 Use --verify-optimized to compare the optimized result with the unoptimized
3495 Use --verify-optimized to compare the optimized result with the unoptimized
3521 one. Returns 1 if the optimized result differs.
3496 one. Returns 1 if the optimized result differs.
3522 """
3497 """
3523 stages = [
3498 stages = [
3524 ('parsed', lambda tree: tree),
3499 ('parsed', lambda tree: tree),
3525 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3500 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3526 ('concatenated', revset.foldconcat),
3501 ('concatenated', revset.foldconcat),
3527 ('analyzed', revset.analyze),
3502 ('analyzed', revset.analyze),
3528 ('optimized', revset.optimize),
3503 ('optimized', revset.optimize),
3529 ]
3504 ]
3530 if opts['no_optimized']:
3505 if opts['no_optimized']:
3531 stages = stages[:-1]
3506 stages = stages[:-1]
3532 if opts['verify_optimized'] and opts['no_optimized']:
3507 if opts['verify_optimized'] and opts['no_optimized']:
3533 raise error.Abort(_('cannot use --verify-optimized with '
3508 raise error.Abort(_('cannot use --verify-optimized with '
3534 '--no-optimized'))
3509 '--no-optimized'))
3535 stagenames = set(n for n, f in stages)
3510 stagenames = set(n for n, f in stages)
3536
3511
3537 showalways = set()
3512 showalways = set()
3538 showchanged = set()
3513 showchanged = set()
3539 if ui.verbose and not opts['show_stage']:
3514 if ui.verbose and not opts['show_stage']:
3540 # show parsed tree by --verbose (deprecated)
3515 # show parsed tree by --verbose (deprecated)
3541 showalways.add('parsed')
3516 showalways.add('parsed')
3542 showchanged.update(['expanded', 'concatenated'])
3517 showchanged.update(['expanded', 'concatenated'])
3543 if opts['optimize']:
3518 if opts['optimize']:
3544 showalways.add('optimized')
3519 showalways.add('optimized')
3545 if opts['show_stage'] and opts['optimize']:
3520 if opts['show_stage'] and opts['optimize']:
3546 raise error.Abort(_('cannot use --optimize with --show-stage'))
3521 raise error.Abort(_('cannot use --optimize with --show-stage'))
3547 if opts['show_stage'] == ['all']:
3522 if opts['show_stage'] == ['all']:
3548 showalways.update(stagenames)
3523 showalways.update(stagenames)
3549 else:
3524 else:
3550 for n in opts['show_stage']:
3525 for n in opts['show_stage']:
3551 if n not in stagenames:
3526 if n not in stagenames:
3552 raise error.Abort(_('invalid stage name: %s') % n)
3527 raise error.Abort(_('invalid stage name: %s') % n)
3553 showalways.update(opts['show_stage'])
3528 showalways.update(opts['show_stage'])
3554
3529
3555 treebystage = {}
3530 treebystage = {}
3556 printedtree = None
3531 printedtree = None
3557 tree = revset.parse(expr, lookup=repo.__contains__)
3532 tree = revset.parse(expr, lookup=repo.__contains__)
3558 for n, f in stages:
3533 for n, f in stages:
3559 treebystage[n] = tree = f(tree)
3534 treebystage[n] = tree = f(tree)
3560 if n in showalways or (n in showchanged and tree != printedtree):
3535 if n in showalways or (n in showchanged and tree != printedtree):
3561 if opts['show_stage'] or n != 'parsed':
3536 if opts['show_stage'] or n != 'parsed':
3562 ui.write(("* %s:\n") % n)
3537 ui.write(("* %s:\n") % n)
3563 ui.write(revset.prettyformat(tree), "\n")
3538 ui.write(revset.prettyformat(tree), "\n")
3564 printedtree = tree
3539 printedtree = tree
3565
3540
3566 if opts['verify_optimized']:
3541 if opts['verify_optimized']:
3567 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3542 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3568 brevs = revset.makematcher(treebystage['optimized'])(repo)
3543 brevs = revset.makematcher(treebystage['optimized'])(repo)
3569 if ui.verbose:
3544 if ui.verbose:
3570 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3545 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3571 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3546 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3572 arevs = list(arevs)
3547 arevs = list(arevs)
3573 brevs = list(brevs)
3548 brevs = list(brevs)
3574 if arevs == brevs:
3549 if arevs == brevs:
3575 return 0
3550 return 0
3576 ui.write(('--- analyzed\n'), label='diff.file_a')
3551 ui.write(('--- analyzed\n'), label='diff.file_a')
3577 ui.write(('+++ optimized\n'), label='diff.file_b')
3552 ui.write(('+++ optimized\n'), label='diff.file_b')
3578 sm = difflib.SequenceMatcher(None, arevs, brevs)
3553 sm = difflib.SequenceMatcher(None, arevs, brevs)
3579 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3554 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3580 if tag in ('delete', 'replace'):
3555 if tag in ('delete', 'replace'):
3581 for c in arevs[alo:ahi]:
3556 for c in arevs[alo:ahi]:
3582 ui.write('-%s\n' % c, label='diff.deleted')
3557 ui.write('-%s\n' % c, label='diff.deleted')
3583 if tag in ('insert', 'replace'):
3558 if tag in ('insert', 'replace'):
3584 for c in brevs[blo:bhi]:
3559 for c in brevs[blo:bhi]:
3585 ui.write('+%s\n' % c, label='diff.inserted')
3560 ui.write('+%s\n' % c, label='diff.inserted')
3586 if tag == 'equal':
3561 if tag == 'equal':
3587 for c in arevs[alo:ahi]:
3562 for c in arevs[alo:ahi]:
3588 ui.write(' %s\n' % c)
3563 ui.write(' %s\n' % c)
3589 return 1
3564 return 1
3590
3565
3591 func = revset.makematcher(tree)
3566 func = revset.makematcher(tree)
3592 revs = func(repo)
3567 revs = func(repo)
3593 if ui.verbose:
3568 if ui.verbose:
3594 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3569 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3595 for c in revs:
3570 for c in revs:
3596 ui.write("%s\n" % c)
3571 ui.write("%s\n" % c)
3597
3572
3598 @command('debugsetparents', [], _('REV1 [REV2]'))
3573 @command('debugsetparents', [], _('REV1 [REV2]'))
3599 def debugsetparents(ui, repo, rev1, rev2=None):
3574 def debugsetparents(ui, repo, rev1, rev2=None):
3600 """manually set the parents of the current working directory
3575 """manually set the parents of the current working directory
3601
3576
3602 This is useful for writing repository conversion tools, but should
3577 This is useful for writing repository conversion tools, but should
3603 be used with care. For example, neither the working directory nor the
3578 be used with care. For example, neither the working directory nor the
3604 dirstate is updated, so file status may be incorrect after running this
3579 dirstate is updated, so file status may be incorrect after running this
3605 command.
3580 command.
3606
3581
3607 Returns 0 on success.
3582 Returns 0 on success.
3608 """
3583 """
3609
3584
3610 r1 = scmutil.revsingle(repo, rev1).node()
3585 r1 = scmutil.revsingle(repo, rev1).node()
3611 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3586 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3612
3587
3613 with repo.wlock():
3588 with repo.wlock():
3614 repo.setparents(r1, r2)
3589 repo.setparents(r1, r2)
3615
3590
3616 @command('debugdirstate|debugstate',
3591 @command('debugdirstate|debugstate',
3617 [('', 'nodates', None, _('do not display the saved mtime')),
3592 [('', 'nodates', None, _('do not display the saved mtime')),
3618 ('', 'datesort', None, _('sort by saved mtime'))],
3593 ('', 'datesort', None, _('sort by saved mtime'))],
3619 _('[OPTION]...'))
3594 _('[OPTION]...'))
3620 def debugstate(ui, repo, **opts):
3595 def debugstate(ui, repo, **opts):
3621 """show the contents of the current dirstate"""
3596 """show the contents of the current dirstate"""
3622
3597
3623 nodates = opts.get('nodates')
3598 nodates = opts.get('nodates')
3624 datesort = opts.get('datesort')
3599 datesort = opts.get('datesort')
3625
3600
3626 timestr = ""
3601 timestr = ""
3627 if datesort:
3602 if datesort:
3628 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3603 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3629 else:
3604 else:
3630 keyfunc = None # sort by filename
3605 keyfunc = None # sort by filename
3631 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3606 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3632 if ent[3] == -1:
3607 if ent[3] == -1:
3633 timestr = 'unset '
3608 timestr = 'unset '
3634 elif nodates:
3609 elif nodates:
3635 timestr = 'set '
3610 timestr = 'set '
3636 else:
3611 else:
3637 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3612 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3638 time.localtime(ent[3]))
3613 time.localtime(ent[3]))
3639 if ent[1] & 0o20000:
3614 if ent[1] & 0o20000:
3640 mode = 'lnk'
3615 mode = 'lnk'
3641 else:
3616 else:
3642 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3617 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3643 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3618 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3644 for f in repo.dirstate.copies():
3619 for f in repo.dirstate.copies():
3645 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3620 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3646
3621
3647 @command('debugsub',
3622 @command('debugsub',
3648 [('r', 'rev', '',
3623 [('r', 'rev', '',
3649 _('revision to check'), _('REV'))],
3624 _('revision to check'), _('REV'))],
3650 _('[-r REV] [REV]'))
3625 _('[-r REV] [REV]'))
3651 def debugsub(ui, repo, rev=None):
3626 def debugsub(ui, repo, rev=None):
3652 ctx = scmutil.revsingle(repo, rev, None)
3627 ctx = scmutil.revsingle(repo, rev, None)
3653 for k, v in sorted(ctx.substate.items()):
3628 for k, v in sorted(ctx.substate.items()):
3654 ui.write(('path %s\n') % k)
3629 ui.write(('path %s\n') % k)
3655 ui.write((' source %s\n') % v[0])
3630 ui.write((' source %s\n') % v[0])
3656 ui.write((' revision %s\n') % v[1])
3631 ui.write((' revision %s\n') % v[1])
3657
3632
3658 @command('debugsuccessorssets',
3633 @command('debugsuccessorssets',
3659 [],
3634 [],
3660 _('[REV]'))
3635 _('[REV]'))
3661 def debugsuccessorssets(ui, repo, *revs):
3636 def debugsuccessorssets(ui, repo, *revs):
3662 """show set of successors for revision
3637 """show set of successors for revision
3663
3638
3664 A successors set of changeset A is a consistent group of revisions that
3639 A successors set of changeset A is a consistent group of revisions that
3665 succeed A. It contains non-obsolete changesets only.
3640 succeed A. It contains non-obsolete changesets only.
3666
3641
3667 In most cases a changeset A has a single successors set containing a single
3642 In most cases a changeset A has a single successors set containing a single
3668 successor (changeset A replaced by A').
3643 successor (changeset A replaced by A').
3669
3644
3670 A changeset that is made obsolete with no successors are called "pruned".
3645 A changeset that is made obsolete with no successors are called "pruned".
3671 Such changesets have no successors sets at all.
3646 Such changesets have no successors sets at all.
3672
3647
3673 A changeset that has been "split" will have a successors set containing
3648 A changeset that has been "split" will have a successors set containing
3674 more than one successor.
3649 more than one successor.
3675
3650
3676 A changeset that has been rewritten in multiple different ways is called
3651 A changeset that has been rewritten in multiple different ways is called
3677 "divergent". Such changesets have multiple successor sets (each of which
3652 "divergent". Such changesets have multiple successor sets (each of which
3678 may also be split, i.e. have multiple successors).
3653 may also be split, i.e. have multiple successors).
3679
3654
3680 Results are displayed as follows::
3655 Results are displayed as follows::
3681
3656
3682 <rev1>
3657 <rev1>
3683 <successors-1A>
3658 <successors-1A>
3684 <rev2>
3659 <rev2>
3685 <successors-2A>
3660 <successors-2A>
3686 <successors-2B1> <successors-2B2> <successors-2B3>
3661 <successors-2B1> <successors-2B2> <successors-2B3>
3687
3662
3688 Here rev2 has two possible (i.e. divergent) successors sets. The first
3663 Here rev2 has two possible (i.e. divergent) successors sets. The first
3689 holds one element, whereas the second holds three (i.e. the changeset has
3664 holds one element, whereas the second holds three (i.e. the changeset has
3690 been split).
3665 been split).
3691 """
3666 """
3692 # passed to successorssets caching computation from one call to another
3667 # passed to successorssets caching computation from one call to another
3693 cache = {}
3668 cache = {}
3694 ctx2str = str
3669 ctx2str = str
3695 node2str = short
3670 node2str = short
3696 if ui.debug():
3671 if ui.debug():
3697 def ctx2str(ctx):
3672 def ctx2str(ctx):
3698 return ctx.hex()
3673 return ctx.hex()
3699 node2str = hex
3674 node2str = hex
3700 for rev in scmutil.revrange(repo, revs):
3675 for rev in scmutil.revrange(repo, revs):
3701 ctx = repo[rev]
3676 ctx = repo[rev]
3702 ui.write('%s\n'% ctx2str(ctx))
3677 ui.write('%s\n'% ctx2str(ctx))
3703 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3678 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3704 if succsset:
3679 if succsset:
3705 ui.write(' ')
3680 ui.write(' ')
3706 ui.write(node2str(succsset[0]))
3681 ui.write(node2str(succsset[0]))
3707 for node in succsset[1:]:
3682 for node in succsset[1:]:
3708 ui.write(' ')
3683 ui.write(' ')
3709 ui.write(node2str(node))
3684 ui.write(node2str(node))
3710 ui.write('\n')
3685 ui.write('\n')
3711
3686
3712 @command('debugtemplate',
3687 @command('debugtemplate',
3713 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3688 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3714 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3689 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3715 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3690 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3716 optionalrepo=True)
3691 optionalrepo=True)
3717 def debugtemplate(ui, repo, tmpl, **opts):
3692 def debugtemplate(ui, repo, tmpl, **opts):
3718 """parse and apply a template
3693 """parse and apply a template
3719
3694
3720 If -r/--rev is given, the template is processed as a log template and
3695 If -r/--rev is given, the template is processed as a log template and
3721 applied to the given changesets. Otherwise, it is processed as a generic
3696 applied to the given changesets. Otherwise, it is processed as a generic
3722 template.
3697 template.
3723
3698
3724 Use --verbose to print the parsed tree.
3699 Use --verbose to print the parsed tree.
3725 """
3700 """
3726 revs = None
3701 revs = None
3727 if opts['rev']:
3702 if opts['rev']:
3728 if repo is None:
3703 if repo is None:
3729 raise error.RepoError(_('there is no Mercurial repository here '
3704 raise error.RepoError(_('there is no Mercurial repository here '
3730 '(.hg not found)'))
3705 '(.hg not found)'))
3731 revs = scmutil.revrange(repo, opts['rev'])
3706 revs = scmutil.revrange(repo, opts['rev'])
3732
3707
3733 props = {}
3708 props = {}
3734 for d in opts['define']:
3709 for d in opts['define']:
3735 try:
3710 try:
3736 k, v = (e.strip() for e in d.split('=', 1))
3711 k, v = (e.strip() for e in d.split('=', 1))
3737 if not k:
3712 if not k:
3738 raise ValueError
3713 raise ValueError
3739 props[k] = v
3714 props[k] = v
3740 except ValueError:
3715 except ValueError:
3741 raise error.Abort(_('malformed keyword definition: %s') % d)
3716 raise error.Abort(_('malformed keyword definition: %s') % d)
3742
3717
3743 if ui.verbose:
3718 if ui.verbose:
3744 aliases = ui.configitems('templatealias')
3719 aliases = ui.configitems('templatealias')
3745 tree = templater.parse(tmpl)
3720 tree = templater.parse(tmpl)
3746 ui.note(templater.prettyformat(tree), '\n')
3721 ui.note(templater.prettyformat(tree), '\n')
3747 newtree = templater.expandaliases(tree, aliases)
3722 newtree = templater.expandaliases(tree, aliases)
3748 if newtree != tree:
3723 if newtree != tree:
3749 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3724 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3750
3725
3751 mapfile = None
3726 mapfile = None
3752 if revs is None:
3727 if revs is None:
3753 k = 'debugtemplate'
3728 k = 'debugtemplate'
3754 t = formatter.maketemplater(ui, k, tmpl)
3729 t = formatter.maketemplater(ui, k, tmpl)
3755 ui.write(templater.stringify(t(k, **props)))
3730 ui.write(templater.stringify(t(k, **props)))
3756 else:
3731 else:
3757 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3732 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3758 mapfile, buffered=False)
3733 mapfile, buffered=False)
3759 for r in revs:
3734 for r in revs:
3760 displayer.show(repo[r], **props)
3735 displayer.show(repo[r], **props)
3761 displayer.close()
3736 displayer.close()
3762
3737
3763 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3738 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3764 def debugwalk(ui, repo, *pats, **opts):
3739 def debugwalk(ui, repo, *pats, **opts):
3765 """show how files match on given patterns"""
3740 """show how files match on given patterns"""
3766 m = scmutil.match(repo[None], pats, opts)
3741 m = scmutil.match(repo[None], pats, opts)
3767 items = list(repo.walk(m))
3742 items = list(repo.walk(m))
3768 if not items:
3743 if not items:
3769 return
3744 return
3770 f = lambda fn: fn
3745 f = lambda fn: fn
3771 if ui.configbool('ui', 'slash') and os.sep != '/':
3746 if ui.configbool('ui', 'slash') and os.sep != '/':
3772 f = lambda fn: util.normpath(fn)
3747 f = lambda fn: util.normpath(fn)
3773 fmt = 'f %%-%ds %%-%ds %%s' % (
3748 fmt = 'f %%-%ds %%-%ds %%s' % (
3774 max([len(abs) for abs in items]),
3749 max([len(abs) for abs in items]),
3775 max([len(m.rel(abs)) for abs in items]))
3750 max([len(m.rel(abs)) for abs in items]))
3776 for abs in items:
3751 for abs in items:
3777 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3752 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3778 ui.write("%s\n" % line.rstrip())
3753 ui.write("%s\n" % line.rstrip())
3779
3754
3780 @command('debugwireargs',
3755 @command('debugwireargs',
3781 [('', 'three', '', 'three'),
3756 [('', 'three', '', 'three'),
3782 ('', 'four', '', 'four'),
3757 ('', 'four', '', 'four'),
3783 ('', 'five', '', 'five'),
3758 ('', 'five', '', 'five'),
3784 ] + remoteopts,
3759 ] + remoteopts,
3785 _('REPO [OPTIONS]... [ONE [TWO]]'),
3760 _('REPO [OPTIONS]... [ONE [TWO]]'),
3786 norepo=True)
3761 norepo=True)
3787 def debugwireargs(ui, repopath, *vals, **opts):
3762 def debugwireargs(ui, repopath, *vals, **opts):
3788 repo = hg.peer(ui, opts, repopath)
3763 repo = hg.peer(ui, opts, repopath)
3789 for opt in remoteopts:
3764 for opt in remoteopts:
3790 del opts[opt[1]]
3765 del opts[opt[1]]
3791 args = {}
3766 args = {}
3792 for k, v in opts.iteritems():
3767 for k, v in opts.iteritems():
3793 if v:
3768 if v:
3794 args[k] = v
3769 args[k] = v
3795 # run twice to check that we don't mess up the stream for the next command
3770 # run twice to check that we don't mess up the stream for the next command
3796 res1 = repo.debugwireargs(*vals, **args)
3771 res1 = repo.debugwireargs(*vals, **args)
3797 res2 = repo.debugwireargs(*vals, **args)
3772 res2 = repo.debugwireargs(*vals, **args)
3798 ui.write("%s\n" % res1)
3773 ui.write("%s\n" % res1)
3799 if res1 != res2:
3774 if res1 != res2:
3800 ui.warn("%s\n" % res2)
3775 ui.warn("%s\n" % res2)
3801
3776
3802 @command('^diff',
3777 @command('^diff',
3803 [('r', 'rev', [], _('revision'), _('REV')),
3778 [('r', 'rev', [], _('revision'), _('REV')),
3804 ('c', 'change', '', _('change made by revision'), _('REV'))
3779 ('c', 'change', '', _('change made by revision'), _('REV'))
3805 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3780 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3806 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3781 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3807 inferrepo=True)
3782 inferrepo=True)
3808 def diff(ui, repo, *pats, **opts):
3783 def diff(ui, repo, *pats, **opts):
3809 """diff repository (or selected files)
3784 """diff repository (or selected files)
3810
3785
3811 Show differences between revisions for the specified files.
3786 Show differences between revisions for the specified files.
3812
3787
3813 Differences between files are shown using the unified diff format.
3788 Differences between files are shown using the unified diff format.
3814
3789
3815 .. note::
3790 .. note::
3816
3791
3817 :hg:`diff` may generate unexpected results for merges, as it will
3792 :hg:`diff` may generate unexpected results for merges, as it will
3818 default to comparing against the working directory's first
3793 default to comparing against the working directory's first
3819 parent changeset if no revisions are specified.
3794 parent changeset if no revisions are specified.
3820
3795
3821 When two revision arguments are given, then changes are shown
3796 When two revision arguments are given, then changes are shown
3822 between those revisions. If only one revision is specified then
3797 between those revisions. If only one revision is specified then
3823 that revision is compared to the working directory, and, when no
3798 that revision is compared to the working directory, and, when no
3824 revisions are specified, the working directory files are compared
3799 revisions are specified, the working directory files are compared
3825 to its first parent.
3800 to its first parent.
3826
3801
3827 Alternatively you can specify -c/--change with a revision to see
3802 Alternatively you can specify -c/--change with a revision to see
3828 the changes in that changeset relative to its first parent.
3803 the changes in that changeset relative to its first parent.
3829
3804
3830 Without the -a/--text option, diff will avoid generating diffs of
3805 Without the -a/--text option, diff will avoid generating diffs of
3831 files it detects as binary. With -a, diff will generate a diff
3806 files it detects as binary. With -a, diff will generate a diff
3832 anyway, probably with undesirable results.
3807 anyway, probably with undesirable results.
3833
3808
3834 Use the -g/--git option to generate diffs in the git extended diff
3809 Use the -g/--git option to generate diffs in the git extended diff
3835 format. For more information, read :hg:`help diffs`.
3810 format. For more information, read :hg:`help diffs`.
3836
3811
3837 .. container:: verbose
3812 .. container:: verbose
3838
3813
3839 Examples:
3814 Examples:
3840
3815
3841 - compare a file in the current working directory to its parent::
3816 - compare a file in the current working directory to its parent::
3842
3817
3843 hg diff foo.c
3818 hg diff foo.c
3844
3819
3845 - compare two historical versions of a directory, with rename info::
3820 - compare two historical versions of a directory, with rename info::
3846
3821
3847 hg diff --git -r 1.0:1.2 lib/
3822 hg diff --git -r 1.0:1.2 lib/
3848
3823
3849 - get change stats relative to the last change on some date::
3824 - get change stats relative to the last change on some date::
3850
3825
3851 hg diff --stat -r "date('may 2')"
3826 hg diff --stat -r "date('may 2')"
3852
3827
3853 - diff all newly-added files that contain a keyword::
3828 - diff all newly-added files that contain a keyword::
3854
3829
3855 hg diff "set:added() and grep(GNU)"
3830 hg diff "set:added() and grep(GNU)"
3856
3831
3857 - compare a revision and its parents::
3832 - compare a revision and its parents::
3858
3833
3859 hg diff -c 9353 # compare against first parent
3834 hg diff -c 9353 # compare against first parent
3860 hg diff -r 9353^:9353 # same using revset syntax
3835 hg diff -r 9353^:9353 # same using revset syntax
3861 hg diff -r 9353^2:9353 # compare against the second parent
3836 hg diff -r 9353^2:9353 # compare against the second parent
3862
3837
3863 Returns 0 on success.
3838 Returns 0 on success.
3864 """
3839 """
3865
3840
3866 revs = opts.get('rev')
3841 revs = opts.get('rev')
3867 change = opts.get('change')
3842 change = opts.get('change')
3868 stat = opts.get('stat')
3843 stat = opts.get('stat')
3869 reverse = opts.get('reverse')
3844 reverse = opts.get('reverse')
3870
3845
3871 if revs and change:
3846 if revs and change:
3872 msg = _('cannot specify --rev and --change at the same time')
3847 msg = _('cannot specify --rev and --change at the same time')
3873 raise error.Abort(msg)
3848 raise error.Abort(msg)
3874 elif change:
3849 elif change:
3875 node2 = scmutil.revsingle(repo, change, None).node()
3850 node2 = scmutil.revsingle(repo, change, None).node()
3876 node1 = repo[node2].p1().node()
3851 node1 = repo[node2].p1().node()
3877 else:
3852 else:
3878 node1, node2 = scmutil.revpair(repo, revs)
3853 node1, node2 = scmutil.revpair(repo, revs)
3879
3854
3880 if reverse:
3855 if reverse:
3881 node1, node2 = node2, node1
3856 node1, node2 = node2, node1
3882
3857
3883 diffopts = patch.diffallopts(ui, opts)
3858 diffopts = patch.diffallopts(ui, opts)
3884 m = scmutil.match(repo[node2], pats, opts)
3859 m = scmutil.match(repo[node2], pats, opts)
3885 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3860 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3886 listsubrepos=opts.get('subrepos'),
3861 listsubrepos=opts.get('subrepos'),
3887 root=opts.get('root'))
3862 root=opts.get('root'))
3888
3863
3889 @command('^export',
3864 @command('^export',
3890 [('o', 'output', '',
3865 [('o', 'output', '',
3891 _('print output to file with formatted name'), _('FORMAT')),
3866 _('print output to file with formatted name'), _('FORMAT')),
3892 ('', 'switch-parent', None, _('diff against the second parent')),
3867 ('', 'switch-parent', None, _('diff against the second parent')),
3893 ('r', 'rev', [], _('revisions to export'), _('REV')),
3868 ('r', 'rev', [], _('revisions to export'), _('REV')),
3894 ] + diffopts,
3869 ] + diffopts,
3895 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3870 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3896 def export(ui, repo, *changesets, **opts):
3871 def export(ui, repo, *changesets, **opts):
3897 """dump the header and diffs for one or more changesets
3872 """dump the header and diffs for one or more changesets
3898
3873
3899 Print the changeset header and diffs for one or more revisions.
3874 Print the changeset header and diffs for one or more revisions.
3900 If no revision is given, the parent of the working directory is used.
3875 If no revision is given, the parent of the working directory is used.
3901
3876
3902 The information shown in the changeset header is: author, date,
3877 The information shown in the changeset header is: author, date,
3903 branch name (if non-default), changeset hash, parent(s) and commit
3878 branch name (if non-default), changeset hash, parent(s) and commit
3904 comment.
3879 comment.
3905
3880
3906 .. note::
3881 .. note::
3907
3882
3908 :hg:`export` may generate unexpected diff output for merge
3883 :hg:`export` may generate unexpected diff output for merge
3909 changesets, as it will compare the merge changeset against its
3884 changesets, as it will compare the merge changeset against its
3910 first parent only.
3885 first parent only.
3911
3886
3912 Output may be to a file, in which case the name of the file is
3887 Output may be to a file, in which case the name of the file is
3913 given using a format string. The formatting rules are as follows:
3888 given using a format string. The formatting rules are as follows:
3914
3889
3915 :``%%``: literal "%" character
3890 :``%%``: literal "%" character
3916 :``%H``: changeset hash (40 hexadecimal digits)
3891 :``%H``: changeset hash (40 hexadecimal digits)
3917 :``%N``: number of patches being generated
3892 :``%N``: number of patches being generated
3918 :``%R``: changeset revision number
3893 :``%R``: changeset revision number
3919 :``%b``: basename of the exporting repository
3894 :``%b``: basename of the exporting repository
3920 :``%h``: short-form changeset hash (12 hexadecimal digits)
3895 :``%h``: short-form changeset hash (12 hexadecimal digits)
3921 :``%m``: first line of the commit message (only alphanumeric characters)
3896 :``%m``: first line of the commit message (only alphanumeric characters)
3922 :``%n``: zero-padded sequence number, starting at 1
3897 :``%n``: zero-padded sequence number, starting at 1
3923 :``%r``: zero-padded changeset revision number
3898 :``%r``: zero-padded changeset revision number
3924
3899
3925 Without the -a/--text option, export will avoid generating diffs
3900 Without the -a/--text option, export will avoid generating diffs
3926 of files it detects as binary. With -a, export will generate a
3901 of files it detects as binary. With -a, export will generate a
3927 diff anyway, probably with undesirable results.
3902 diff anyway, probably with undesirable results.
3928
3903
3929 Use the -g/--git option to generate diffs in the git extended diff
3904 Use the -g/--git option to generate diffs in the git extended diff
3930 format. See :hg:`help diffs` for more information.
3905 format. See :hg:`help diffs` for more information.
3931
3906
3932 With the --switch-parent option, the diff will be against the
3907 With the --switch-parent option, the diff will be against the
3933 second parent. It can be useful to review a merge.
3908 second parent. It can be useful to review a merge.
3934
3909
3935 .. container:: verbose
3910 .. container:: verbose
3936
3911
3937 Examples:
3912 Examples:
3938
3913
3939 - use export and import to transplant a bugfix to the current
3914 - use export and import to transplant a bugfix to the current
3940 branch::
3915 branch::
3941
3916
3942 hg export -r 9353 | hg import -
3917 hg export -r 9353 | hg import -
3943
3918
3944 - export all the changesets between two revisions to a file with
3919 - export all the changesets between two revisions to a file with
3945 rename information::
3920 rename information::
3946
3921
3947 hg export --git -r 123:150 > changes.txt
3922 hg export --git -r 123:150 > changes.txt
3948
3923
3949 - split outgoing changes into a series of patches with
3924 - split outgoing changes into a series of patches with
3950 descriptive names::
3925 descriptive names::
3951
3926
3952 hg export -r "outgoing()" -o "%n-%m.patch"
3927 hg export -r "outgoing()" -o "%n-%m.patch"
3953
3928
3954 Returns 0 on success.
3929 Returns 0 on success.
3955 """
3930 """
3956 changesets += tuple(opts.get('rev', []))
3931 changesets += tuple(opts.get('rev', []))
3957 if not changesets:
3932 if not changesets:
3958 changesets = ['.']
3933 changesets = ['.']
3959 revs = scmutil.revrange(repo, changesets)
3934 revs = scmutil.revrange(repo, changesets)
3960 if not revs:
3935 if not revs:
3961 raise error.Abort(_("export requires at least one changeset"))
3936 raise error.Abort(_("export requires at least one changeset"))
3962 if len(revs) > 1:
3937 if len(revs) > 1:
3963 ui.note(_('exporting patches:\n'))
3938 ui.note(_('exporting patches:\n'))
3964 else:
3939 else:
3965 ui.note(_('exporting patch:\n'))
3940 ui.note(_('exporting patch:\n'))
3966 cmdutil.export(repo, revs, template=opts.get('output'),
3941 cmdutil.export(repo, revs, template=opts.get('output'),
3967 switch_parent=opts.get('switch_parent'),
3942 switch_parent=opts.get('switch_parent'),
3968 opts=patch.diffallopts(ui, opts))
3943 opts=patch.diffallopts(ui, opts))
3969
3944
3970 @command('files',
3945 @command('files',
3971 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3946 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3972 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3947 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3973 ] + walkopts + formatteropts + subrepoopts,
3948 ] + walkopts + formatteropts + subrepoopts,
3974 _('[OPTION]... [FILE]...'))
3949 _('[OPTION]... [FILE]...'))
3975 def files(ui, repo, *pats, **opts):
3950 def files(ui, repo, *pats, **opts):
3976 """list tracked files
3951 """list tracked files
3977
3952
3978 Print files under Mercurial control in the working directory or
3953 Print files under Mercurial control in the working directory or
3979 specified revision for given files (excluding removed files).
3954 specified revision for given files (excluding removed files).
3980 Files can be specified as filenames or filesets.
3955 Files can be specified as filenames or filesets.
3981
3956
3982 If no files are given to match, this command prints the names
3957 If no files are given to match, this command prints the names
3983 of all files under Mercurial control.
3958 of all files under Mercurial control.
3984
3959
3985 .. container:: verbose
3960 .. container:: verbose
3986
3961
3987 Examples:
3962 Examples:
3988
3963
3989 - list all files under the current directory::
3964 - list all files under the current directory::
3990
3965
3991 hg files .
3966 hg files .
3992
3967
3993 - shows sizes and flags for current revision::
3968 - shows sizes and flags for current revision::
3994
3969
3995 hg files -vr .
3970 hg files -vr .
3996
3971
3997 - list all files named README::
3972 - list all files named README::
3998
3973
3999 hg files -I "**/README"
3974 hg files -I "**/README"
4000
3975
4001 - list all binary files::
3976 - list all binary files::
4002
3977
4003 hg files "set:binary()"
3978 hg files "set:binary()"
4004
3979
4005 - find files containing a regular expression::
3980 - find files containing a regular expression::
4006
3981
4007 hg files "set:grep('bob')"
3982 hg files "set:grep('bob')"
4008
3983
4009 - search tracked file contents with xargs and grep::
3984 - search tracked file contents with xargs and grep::
4010
3985
4011 hg files -0 | xargs -0 grep foo
3986 hg files -0 | xargs -0 grep foo
4012
3987
4013 See :hg:`help patterns` and :hg:`help filesets` for more information
3988 See :hg:`help patterns` and :hg:`help filesets` for more information
4014 on specifying file patterns.
3989 on specifying file patterns.
4015
3990
4016 Returns 0 if a match is found, 1 otherwise.
3991 Returns 0 if a match is found, 1 otherwise.
4017
3992
4018 """
3993 """
4019 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3994 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4020
3995
4021 end = '\n'
3996 end = '\n'
4022 if opts.get('print0'):
3997 if opts.get('print0'):
4023 end = '\0'
3998 end = '\0'
4024 fmt = '%s' + end
3999 fmt = '%s' + end
4025
4000
4026 m = scmutil.match(ctx, pats, opts)
4001 m = scmutil.match(ctx, pats, opts)
4027 with ui.formatter('files', opts) as fm:
4002 with ui.formatter('files', opts) as fm:
4028 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
4003 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
4029
4004
4030 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
4005 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
4031 def forget(ui, repo, *pats, **opts):
4006 def forget(ui, repo, *pats, **opts):
4032 """forget the specified files on the next commit
4007 """forget the specified files on the next commit
4033
4008
4034 Mark the specified files so they will no longer be tracked
4009 Mark the specified files so they will no longer be tracked
4035 after the next commit.
4010 after the next commit.
4036
4011
4037 This only removes files from the current branch, not from the
4012 This only removes files from the current branch, not from the
4038 entire project history, and it does not delete them from the
4013 entire project history, and it does not delete them from the
4039 working directory.
4014 working directory.
4040
4015
4041 To delete the file from the working directory, see :hg:`remove`.
4016 To delete the file from the working directory, see :hg:`remove`.
4042
4017
4043 To undo a forget before the next commit, see :hg:`add`.
4018 To undo a forget before the next commit, see :hg:`add`.
4044
4019
4045 .. container:: verbose
4020 .. container:: verbose
4046
4021
4047 Examples:
4022 Examples:
4048
4023
4049 - forget newly-added binary files::
4024 - forget newly-added binary files::
4050
4025
4051 hg forget "set:added() and binary()"
4026 hg forget "set:added() and binary()"
4052
4027
4053 - forget files that would be excluded by .hgignore::
4028 - forget files that would be excluded by .hgignore::
4054
4029
4055 hg forget "set:hgignore()"
4030 hg forget "set:hgignore()"
4056
4031
4057 Returns 0 on success.
4032 Returns 0 on success.
4058 """
4033 """
4059
4034
4060 if not pats:
4035 if not pats:
4061 raise error.Abort(_('no files specified'))
4036 raise error.Abort(_('no files specified'))
4062
4037
4063 m = scmutil.match(repo[None], pats, opts)
4038 m = scmutil.match(repo[None], pats, opts)
4064 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4039 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
4065 return rejected and 1 or 0
4040 return rejected and 1 or 0
4066
4041
4067 @command(
4042 @command(
4068 'graft',
4043 'graft',
4069 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4044 [('r', 'rev', [], _('revisions to graft'), _('REV')),
4070 ('c', 'continue', False, _('resume interrupted graft')),
4045 ('c', 'continue', False, _('resume interrupted graft')),
4071 ('e', 'edit', False, _('invoke editor on commit messages')),
4046 ('e', 'edit', False, _('invoke editor on commit messages')),
4072 ('', 'log', None, _('append graft info to log message')),
4047 ('', 'log', None, _('append graft info to log message')),
4073 ('f', 'force', False, _('force graft')),
4048 ('f', 'force', False, _('force graft')),
4074 ('D', 'currentdate', False,
4049 ('D', 'currentdate', False,
4075 _('record the current date as commit date')),
4050 _('record the current date as commit date')),
4076 ('U', 'currentuser', False,
4051 ('U', 'currentuser', False,
4077 _('record the current user as committer'), _('DATE'))]
4052 _('record the current user as committer'), _('DATE'))]
4078 + commitopts2 + mergetoolopts + dryrunopts,
4053 + commitopts2 + mergetoolopts + dryrunopts,
4079 _('[OPTION]... [-r REV]... REV...'))
4054 _('[OPTION]... [-r REV]... REV...'))
4080 def graft(ui, repo, *revs, **opts):
4055 def graft(ui, repo, *revs, **opts):
4081 '''copy changes from other branches onto the current branch
4056 '''copy changes from other branches onto the current branch
4082
4057
4083 This command uses Mercurial's merge logic to copy individual
4058 This command uses Mercurial's merge logic to copy individual
4084 changes from other branches without merging branches in the
4059 changes from other branches without merging branches in the
4085 history graph. This is sometimes known as 'backporting' or
4060 history graph. This is sometimes known as 'backporting' or
4086 'cherry-picking'. By default, graft will copy user, date, and
4061 'cherry-picking'. By default, graft will copy user, date, and
4087 description from the source changesets.
4062 description from the source changesets.
4088
4063
4089 Changesets that are ancestors of the current revision, that have
4064 Changesets that are ancestors of the current revision, that have
4090 already been grafted, or that are merges will be skipped.
4065 already been grafted, or that are merges will be skipped.
4091
4066
4092 If --log is specified, log messages will have a comment appended
4067 If --log is specified, log messages will have a comment appended
4093 of the form::
4068 of the form::
4094
4069
4095 (grafted from CHANGESETHASH)
4070 (grafted from CHANGESETHASH)
4096
4071
4097 If --force is specified, revisions will be grafted even if they
4072 If --force is specified, revisions will be grafted even if they
4098 are already ancestors of or have been grafted to the destination.
4073 are already ancestors of or have been grafted to the destination.
4099 This is useful when the revisions have since been backed out.
4074 This is useful when the revisions have since been backed out.
4100
4075
4101 If a graft merge results in conflicts, the graft process is
4076 If a graft merge results in conflicts, the graft process is
4102 interrupted so that the current merge can be manually resolved.
4077 interrupted so that the current merge can be manually resolved.
4103 Once all conflicts are addressed, the graft process can be
4078 Once all conflicts are addressed, the graft process can be
4104 continued with the -c/--continue option.
4079 continued with the -c/--continue option.
4105
4080
4106 .. note::
4081 .. note::
4107
4082
4108 The -c/--continue option does not reapply earlier options, except
4083 The -c/--continue option does not reapply earlier options, except
4109 for --force.
4084 for --force.
4110
4085
4111 .. container:: verbose
4086 .. container:: verbose
4112
4087
4113 Examples:
4088 Examples:
4114
4089
4115 - copy a single change to the stable branch and edit its description::
4090 - copy a single change to the stable branch and edit its description::
4116
4091
4117 hg update stable
4092 hg update stable
4118 hg graft --edit 9393
4093 hg graft --edit 9393
4119
4094
4120 - graft a range of changesets with one exception, updating dates::
4095 - graft a range of changesets with one exception, updating dates::
4121
4096
4122 hg graft -D "2085::2093 and not 2091"
4097 hg graft -D "2085::2093 and not 2091"
4123
4098
4124 - continue a graft after resolving conflicts::
4099 - continue a graft after resolving conflicts::
4125
4100
4126 hg graft -c
4101 hg graft -c
4127
4102
4128 - show the source of a grafted changeset::
4103 - show the source of a grafted changeset::
4129
4104
4130 hg log --debug -r .
4105 hg log --debug -r .
4131
4106
4132 - show revisions sorted by date::
4107 - show revisions sorted by date::
4133
4108
4134 hg log -r "sort(all(), date)"
4109 hg log -r "sort(all(), date)"
4135
4110
4136 See :hg:`help revisions` and :hg:`help revsets` for more about
4111 See :hg:`help revisions` and :hg:`help revsets` for more about
4137 specifying revisions.
4112 specifying revisions.
4138
4113
4139 Returns 0 on successful completion.
4114 Returns 0 on successful completion.
4140 '''
4115 '''
4141 with repo.wlock():
4116 with repo.wlock():
4142 return _dograft(ui, repo, *revs, **opts)
4117 return _dograft(ui, repo, *revs, **opts)
4143
4118
4144 def _dograft(ui, repo, *revs, **opts):
4119 def _dograft(ui, repo, *revs, **opts):
4145 if revs and opts.get('rev'):
4120 if revs and opts.get('rev'):
4146 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4121 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4147 'revision ordering!\n'))
4122 'revision ordering!\n'))
4148
4123
4149 revs = list(revs)
4124 revs = list(revs)
4150 revs.extend(opts.get('rev'))
4125 revs.extend(opts.get('rev'))
4151
4126
4152 if not opts.get('user') and opts.get('currentuser'):
4127 if not opts.get('user') and opts.get('currentuser'):
4153 opts['user'] = ui.username()
4128 opts['user'] = ui.username()
4154 if not opts.get('date') and opts.get('currentdate'):
4129 if not opts.get('date') and opts.get('currentdate'):
4155 opts['date'] = "%d %d" % util.makedate()
4130 opts['date'] = "%d %d" % util.makedate()
4156
4131
4157 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4132 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4158
4133
4159 cont = False
4134 cont = False
4160 if opts.get('continue'):
4135 if opts.get('continue'):
4161 cont = True
4136 cont = True
4162 if revs:
4137 if revs:
4163 raise error.Abort(_("can't specify --continue and revisions"))
4138 raise error.Abort(_("can't specify --continue and revisions"))
4164 # read in unfinished revisions
4139 # read in unfinished revisions
4165 try:
4140 try:
4166 nodes = repo.vfs.read('graftstate').splitlines()
4141 nodes = repo.vfs.read('graftstate').splitlines()
4167 revs = [repo[node].rev() for node in nodes]
4142 revs = [repo[node].rev() for node in nodes]
4168 except IOError as inst:
4143 except IOError as inst:
4169 if inst.errno != errno.ENOENT:
4144 if inst.errno != errno.ENOENT:
4170 raise
4145 raise
4171 cmdutil.wrongtooltocontinue(repo, _('graft'))
4146 cmdutil.wrongtooltocontinue(repo, _('graft'))
4172 else:
4147 else:
4173 cmdutil.checkunfinished(repo)
4148 cmdutil.checkunfinished(repo)
4174 cmdutil.bailifchanged(repo)
4149 cmdutil.bailifchanged(repo)
4175 if not revs:
4150 if not revs:
4176 raise error.Abort(_('no revisions specified'))
4151 raise error.Abort(_('no revisions specified'))
4177 revs = scmutil.revrange(repo, revs)
4152 revs = scmutil.revrange(repo, revs)
4178
4153
4179 skipped = set()
4154 skipped = set()
4180 # check for merges
4155 # check for merges
4181 for rev in repo.revs('%ld and merge()', revs):
4156 for rev in repo.revs('%ld and merge()', revs):
4182 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4157 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4183 skipped.add(rev)
4158 skipped.add(rev)
4184 revs = [r for r in revs if r not in skipped]
4159 revs = [r for r in revs if r not in skipped]
4185 if not revs:
4160 if not revs:
4186 return -1
4161 return -1
4187
4162
4188 # Don't check in the --continue case, in effect retaining --force across
4163 # Don't check in the --continue case, in effect retaining --force across
4189 # --continues. That's because without --force, any revisions we decided to
4164 # --continues. That's because without --force, any revisions we decided to
4190 # skip would have been filtered out here, so they wouldn't have made their
4165 # skip would have been filtered out here, so they wouldn't have made their
4191 # way to the graftstate. With --force, any revisions we would have otherwise
4166 # way to the graftstate. With --force, any revisions we would have otherwise
4192 # skipped would not have been filtered out, and if they hadn't been applied
4167 # skipped would not have been filtered out, and if they hadn't been applied
4193 # already, they'd have been in the graftstate.
4168 # already, they'd have been in the graftstate.
4194 if not (cont or opts.get('force')):
4169 if not (cont or opts.get('force')):
4195 # check for ancestors of dest branch
4170 # check for ancestors of dest branch
4196 crev = repo['.'].rev()
4171 crev = repo['.'].rev()
4197 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4172 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4198 # XXX make this lazy in the future
4173 # XXX make this lazy in the future
4199 # don't mutate while iterating, create a copy
4174 # don't mutate while iterating, create a copy
4200 for rev in list(revs):
4175 for rev in list(revs):
4201 if rev in ancestors:
4176 if rev in ancestors:
4202 ui.warn(_('skipping ancestor revision %d:%s\n') %
4177 ui.warn(_('skipping ancestor revision %d:%s\n') %
4203 (rev, repo[rev]))
4178 (rev, repo[rev]))
4204 # XXX remove on list is slow
4179 # XXX remove on list is slow
4205 revs.remove(rev)
4180 revs.remove(rev)
4206 if not revs:
4181 if not revs:
4207 return -1
4182 return -1
4208
4183
4209 # analyze revs for earlier grafts
4184 # analyze revs for earlier grafts
4210 ids = {}
4185 ids = {}
4211 for ctx in repo.set("%ld", revs):
4186 for ctx in repo.set("%ld", revs):
4212 ids[ctx.hex()] = ctx.rev()
4187 ids[ctx.hex()] = ctx.rev()
4213 n = ctx.extra().get('source')
4188 n = ctx.extra().get('source')
4214 if n:
4189 if n:
4215 ids[n] = ctx.rev()
4190 ids[n] = ctx.rev()
4216
4191
4217 # check ancestors for earlier grafts
4192 # check ancestors for earlier grafts
4218 ui.debug('scanning for duplicate grafts\n')
4193 ui.debug('scanning for duplicate grafts\n')
4219
4194
4220 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4195 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4221 ctx = repo[rev]
4196 ctx = repo[rev]
4222 n = ctx.extra().get('source')
4197 n = ctx.extra().get('source')
4223 if n in ids:
4198 if n in ids:
4224 try:
4199 try:
4225 r = repo[n].rev()
4200 r = repo[n].rev()
4226 except error.RepoLookupError:
4201 except error.RepoLookupError:
4227 r = None
4202 r = None
4228 if r in revs:
4203 if r in revs:
4229 ui.warn(_('skipping revision %d:%s '
4204 ui.warn(_('skipping revision %d:%s '
4230 '(already grafted to %d:%s)\n')
4205 '(already grafted to %d:%s)\n')
4231 % (r, repo[r], rev, ctx))
4206 % (r, repo[r], rev, ctx))
4232 revs.remove(r)
4207 revs.remove(r)
4233 elif ids[n] in revs:
4208 elif ids[n] in revs:
4234 if r is None:
4209 if r is None:
4235 ui.warn(_('skipping already grafted revision %d:%s '
4210 ui.warn(_('skipping already grafted revision %d:%s '
4236 '(%d:%s also has unknown origin %s)\n')
4211 '(%d:%s also has unknown origin %s)\n')
4237 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4212 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4238 else:
4213 else:
4239 ui.warn(_('skipping already grafted revision %d:%s '
4214 ui.warn(_('skipping already grafted revision %d:%s '
4240 '(%d:%s also has origin %d:%s)\n')
4215 '(%d:%s also has origin %d:%s)\n')
4241 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4216 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4242 revs.remove(ids[n])
4217 revs.remove(ids[n])
4243 elif ctx.hex() in ids:
4218 elif ctx.hex() in ids:
4244 r = ids[ctx.hex()]
4219 r = ids[ctx.hex()]
4245 ui.warn(_('skipping already grafted revision %d:%s '
4220 ui.warn(_('skipping already grafted revision %d:%s '
4246 '(was grafted from %d:%s)\n') %
4221 '(was grafted from %d:%s)\n') %
4247 (r, repo[r], rev, ctx))
4222 (r, repo[r], rev, ctx))
4248 revs.remove(r)
4223 revs.remove(r)
4249 if not revs:
4224 if not revs:
4250 return -1
4225 return -1
4251
4226
4252 for pos, ctx in enumerate(repo.set("%ld", revs)):
4227 for pos, ctx in enumerate(repo.set("%ld", revs)):
4253 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4228 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4254 ctx.description().split('\n', 1)[0])
4229 ctx.description().split('\n', 1)[0])
4255 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4230 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4256 if names:
4231 if names:
4257 desc += ' (%s)' % ' '.join(names)
4232 desc += ' (%s)' % ' '.join(names)
4258 ui.status(_('grafting %s\n') % desc)
4233 ui.status(_('grafting %s\n') % desc)
4259 if opts.get('dry_run'):
4234 if opts.get('dry_run'):
4260 continue
4235 continue
4261
4236
4262 source = ctx.extra().get('source')
4237 source = ctx.extra().get('source')
4263 extra = {}
4238 extra = {}
4264 if source:
4239 if source:
4265 extra['source'] = source
4240 extra['source'] = source
4266 extra['intermediate-source'] = ctx.hex()
4241 extra['intermediate-source'] = ctx.hex()
4267 else:
4242 else:
4268 extra['source'] = ctx.hex()
4243 extra['source'] = ctx.hex()
4269 user = ctx.user()
4244 user = ctx.user()
4270 if opts.get('user'):
4245 if opts.get('user'):
4271 user = opts['user']
4246 user = opts['user']
4272 date = ctx.date()
4247 date = ctx.date()
4273 if opts.get('date'):
4248 if opts.get('date'):
4274 date = opts['date']
4249 date = opts['date']
4275 message = ctx.description()
4250 message = ctx.description()
4276 if opts.get('log'):
4251 if opts.get('log'):
4277 message += '\n(grafted from %s)' % ctx.hex()
4252 message += '\n(grafted from %s)' % ctx.hex()
4278
4253
4279 # we don't merge the first commit when continuing
4254 # we don't merge the first commit when continuing
4280 if not cont:
4255 if not cont:
4281 # perform the graft merge with p1(rev) as 'ancestor'
4256 # perform the graft merge with p1(rev) as 'ancestor'
4282 try:
4257 try:
4283 # ui.forcemerge is an internal variable, do not document
4258 # ui.forcemerge is an internal variable, do not document
4284 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4259 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4285 'graft')
4260 'graft')
4286 stats = mergemod.graft(repo, ctx, ctx.p1(),
4261 stats = mergemod.graft(repo, ctx, ctx.p1(),
4287 ['local', 'graft'])
4262 ['local', 'graft'])
4288 finally:
4263 finally:
4289 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4264 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4290 # report any conflicts
4265 # report any conflicts
4291 if stats and stats[3] > 0:
4266 if stats and stats[3] > 0:
4292 # write out state for --continue
4267 # write out state for --continue
4293 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4268 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4294 repo.vfs.write('graftstate', ''.join(nodelines))
4269 repo.vfs.write('graftstate', ''.join(nodelines))
4295 extra = ''
4270 extra = ''
4296 if opts.get('user'):
4271 if opts.get('user'):
4297 extra += ' --user %s' % util.shellquote(opts['user'])
4272 extra += ' --user %s' % util.shellquote(opts['user'])
4298 if opts.get('date'):
4273 if opts.get('date'):
4299 extra += ' --date %s' % util.shellquote(opts['date'])
4274 extra += ' --date %s' % util.shellquote(opts['date'])
4300 if opts.get('log'):
4275 if opts.get('log'):
4301 extra += ' --log'
4276 extra += ' --log'
4302 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4277 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4303 raise error.Abort(
4278 raise error.Abort(
4304 _("unresolved conflicts, can't continue"),
4279 _("unresolved conflicts, can't continue"),
4305 hint=hint)
4280 hint=hint)
4306 else:
4281 else:
4307 cont = False
4282 cont = False
4308
4283
4309 # commit
4284 # commit
4310 node = repo.commit(text=message, user=user,
4285 node = repo.commit(text=message, user=user,
4311 date=date, extra=extra, editor=editor)
4286 date=date, extra=extra, editor=editor)
4312 if node is None:
4287 if node is None:
4313 ui.warn(
4288 ui.warn(
4314 _('note: graft of %d:%s created no changes to commit\n') %
4289 _('note: graft of %d:%s created no changes to commit\n') %
4315 (ctx.rev(), ctx))
4290 (ctx.rev(), ctx))
4316
4291
4317 # remove state when we complete successfully
4292 # remove state when we complete successfully
4318 if not opts.get('dry_run'):
4293 if not opts.get('dry_run'):
4319 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4294 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4320
4295
4321 return 0
4296 return 0
4322
4297
4323 @command('grep',
4298 @command('grep',
4324 [('0', 'print0', None, _('end fields with NUL')),
4299 [('0', 'print0', None, _('end fields with NUL')),
4325 ('', 'all', None, _('print all revisions that match')),
4300 ('', 'all', None, _('print all revisions that match')),
4326 ('a', 'text', None, _('treat all files as text')),
4301 ('a', 'text', None, _('treat all files as text')),
4327 ('f', 'follow', None,
4302 ('f', 'follow', None,
4328 _('follow changeset history,'
4303 _('follow changeset history,'
4329 ' or file history across copies and renames')),
4304 ' or file history across copies and renames')),
4330 ('i', 'ignore-case', None, _('ignore case when matching')),
4305 ('i', 'ignore-case', None, _('ignore case when matching')),
4331 ('l', 'files-with-matches', None,
4306 ('l', 'files-with-matches', None,
4332 _('print only filenames and revisions that match')),
4307 _('print only filenames and revisions that match')),
4333 ('n', 'line-number', None, _('print matching line numbers')),
4308 ('n', 'line-number', None, _('print matching line numbers')),
4334 ('r', 'rev', [],
4309 ('r', 'rev', [],
4335 _('only search files changed within revision range'), _('REV')),
4310 _('only search files changed within revision range'), _('REV')),
4336 ('u', 'user', None, _('list the author (long with -v)')),
4311 ('u', 'user', None, _('list the author (long with -v)')),
4337 ('d', 'date', None, _('list the date (short with -q)')),
4312 ('d', 'date', None, _('list the date (short with -q)')),
4338 ] + formatteropts + walkopts,
4313 ] + formatteropts + walkopts,
4339 _('[OPTION]... PATTERN [FILE]...'),
4314 _('[OPTION]... PATTERN [FILE]...'),
4340 inferrepo=True)
4315 inferrepo=True)
4341 def grep(ui, repo, pattern, *pats, **opts):
4316 def grep(ui, repo, pattern, *pats, **opts):
4342 """search revision history for a pattern in specified files
4317 """search revision history for a pattern in specified files
4343
4318
4344 Search revision history for a regular expression in the specified
4319 Search revision history for a regular expression in the specified
4345 files or the entire project.
4320 files or the entire project.
4346
4321
4347 By default, grep prints the most recent revision number for each
4322 By default, grep prints the most recent revision number for each
4348 file in which it finds a match. To get it to print every revision
4323 file in which it finds a match. To get it to print every revision
4349 that contains a change in match status ("-" for a match that becomes
4324 that contains a change in match status ("-" for a match that becomes
4350 a non-match, or "+" for a non-match that becomes a match), use the
4325 a non-match, or "+" for a non-match that becomes a match), use the
4351 --all flag.
4326 --all flag.
4352
4327
4353 PATTERN can be any Python (roughly Perl-compatible) regular
4328 PATTERN can be any Python (roughly Perl-compatible) regular
4354 expression.
4329 expression.
4355
4330
4356 If no FILEs are specified (and -f/--follow isn't set), all files in
4331 If no FILEs are specified (and -f/--follow isn't set), all files in
4357 the repository are searched, including those that don't exist in the
4332 the repository are searched, including those that don't exist in the
4358 current branch or have been deleted in a prior changeset.
4333 current branch or have been deleted in a prior changeset.
4359
4334
4360 Returns 0 if a match is found, 1 otherwise.
4335 Returns 0 if a match is found, 1 otherwise.
4361 """
4336 """
4362 reflags = re.M
4337 reflags = re.M
4363 if opts.get('ignore_case'):
4338 if opts.get('ignore_case'):
4364 reflags |= re.I
4339 reflags |= re.I
4365 try:
4340 try:
4366 regexp = util.re.compile(pattern, reflags)
4341 regexp = util.re.compile(pattern, reflags)
4367 except re.error as inst:
4342 except re.error as inst:
4368 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4343 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4369 return 1
4344 return 1
4370 sep, eol = ':', '\n'
4345 sep, eol = ':', '\n'
4371 if opts.get('print0'):
4346 if opts.get('print0'):
4372 sep = eol = '\0'
4347 sep = eol = '\0'
4373
4348
4374 getfile = util.lrucachefunc(repo.file)
4349 getfile = util.lrucachefunc(repo.file)
4375
4350
4376 def matchlines(body):
4351 def matchlines(body):
4377 begin = 0
4352 begin = 0
4378 linenum = 0
4353 linenum = 0
4379 while begin < len(body):
4354 while begin < len(body):
4380 match = regexp.search(body, begin)
4355 match = regexp.search(body, begin)
4381 if not match:
4356 if not match:
4382 break
4357 break
4383 mstart, mend = match.span()
4358 mstart, mend = match.span()
4384 linenum += body.count('\n', begin, mstart) + 1
4359 linenum += body.count('\n', begin, mstart) + 1
4385 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4360 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4386 begin = body.find('\n', mend) + 1 or len(body) + 1
4361 begin = body.find('\n', mend) + 1 or len(body) + 1
4387 lend = begin - 1
4362 lend = begin - 1
4388 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4363 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4389
4364
4390 class linestate(object):
4365 class linestate(object):
4391 def __init__(self, line, linenum, colstart, colend):
4366 def __init__(self, line, linenum, colstart, colend):
4392 self.line = line
4367 self.line = line
4393 self.linenum = linenum
4368 self.linenum = linenum
4394 self.colstart = colstart
4369 self.colstart = colstart
4395 self.colend = colend
4370 self.colend = colend
4396
4371
4397 def __hash__(self):
4372 def __hash__(self):
4398 return hash((self.linenum, self.line))
4373 return hash((self.linenum, self.line))
4399
4374
4400 def __eq__(self, other):
4375 def __eq__(self, other):
4401 return self.line == other.line
4376 return self.line == other.line
4402
4377
4403 def findpos(self):
4378 def findpos(self):
4404 """Iterate all (start, end) indices of matches"""
4379 """Iterate all (start, end) indices of matches"""
4405 yield self.colstart, self.colend
4380 yield self.colstart, self.colend
4406 p = self.colend
4381 p = self.colend
4407 while p < len(self.line):
4382 while p < len(self.line):
4408 m = regexp.search(self.line, p)
4383 m = regexp.search(self.line, p)
4409 if not m:
4384 if not m:
4410 break
4385 break
4411 yield m.span()
4386 yield m.span()
4412 p = m.end()
4387 p = m.end()
4413
4388
4414 matches = {}
4389 matches = {}
4415 copies = {}
4390 copies = {}
4416 def grepbody(fn, rev, body):
4391 def grepbody(fn, rev, body):
4417 matches[rev].setdefault(fn, [])
4392 matches[rev].setdefault(fn, [])
4418 m = matches[rev][fn]
4393 m = matches[rev][fn]
4419 for lnum, cstart, cend, line in matchlines(body):
4394 for lnum, cstart, cend, line in matchlines(body):
4420 s = linestate(line, lnum, cstart, cend)
4395 s = linestate(line, lnum, cstart, cend)
4421 m.append(s)
4396 m.append(s)
4422
4397
4423 def difflinestates(a, b):
4398 def difflinestates(a, b):
4424 sm = difflib.SequenceMatcher(None, a, b)
4399 sm = difflib.SequenceMatcher(None, a, b)
4425 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4400 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4426 if tag == 'insert':
4401 if tag == 'insert':
4427 for i in xrange(blo, bhi):
4402 for i in xrange(blo, bhi):
4428 yield ('+', b[i])
4403 yield ('+', b[i])
4429 elif tag == 'delete':
4404 elif tag == 'delete':
4430 for i in xrange(alo, ahi):
4405 for i in xrange(alo, ahi):
4431 yield ('-', a[i])
4406 yield ('-', a[i])
4432 elif tag == 'replace':
4407 elif tag == 'replace':
4433 for i in xrange(alo, ahi):
4408 for i in xrange(alo, ahi):
4434 yield ('-', a[i])
4409 yield ('-', a[i])
4435 for i in xrange(blo, bhi):
4410 for i in xrange(blo, bhi):
4436 yield ('+', b[i])
4411 yield ('+', b[i])
4437
4412
4438 def display(fm, fn, ctx, pstates, states):
4413 def display(fm, fn, ctx, pstates, states):
4439 rev = ctx.rev()
4414 rev = ctx.rev()
4440 if fm.isplain():
4415 if fm.isplain():
4441 formatuser = ui.shortuser
4416 formatuser = ui.shortuser
4442 else:
4417 else:
4443 formatuser = str
4418 formatuser = str
4444 if ui.quiet:
4419 if ui.quiet:
4445 datefmt = '%Y-%m-%d'
4420 datefmt = '%Y-%m-%d'
4446 else:
4421 else:
4447 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4422 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4448 found = False
4423 found = False
4449 @util.cachefunc
4424 @util.cachefunc
4450 def binary():
4425 def binary():
4451 flog = getfile(fn)
4426 flog = getfile(fn)
4452 return util.binary(flog.read(ctx.filenode(fn)))
4427 return util.binary(flog.read(ctx.filenode(fn)))
4453
4428
4454 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4429 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4455 if opts.get('all'):
4430 if opts.get('all'):
4456 iter = difflinestates(pstates, states)
4431 iter = difflinestates(pstates, states)
4457 else:
4432 else:
4458 iter = [('', l) for l in states]
4433 iter = [('', l) for l in states]
4459 for change, l in iter:
4434 for change, l in iter:
4460 fm.startitem()
4435 fm.startitem()
4461 fm.data(node=fm.hexfunc(ctx.node()))
4436 fm.data(node=fm.hexfunc(ctx.node()))
4462 cols = [
4437 cols = [
4463 ('filename', fn, True),
4438 ('filename', fn, True),
4464 ('rev', rev, True),
4439 ('rev', rev, True),
4465 ('linenumber', l.linenum, opts.get('line_number')),
4440 ('linenumber', l.linenum, opts.get('line_number')),
4466 ]
4441 ]
4467 if opts.get('all'):
4442 if opts.get('all'):
4468 cols.append(('change', change, True))
4443 cols.append(('change', change, True))
4469 cols.extend([
4444 cols.extend([
4470 ('user', formatuser(ctx.user()), opts.get('user')),
4445 ('user', formatuser(ctx.user()), opts.get('user')),
4471 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4446 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4472 ])
4447 ])
4473 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4448 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4474 for name, data, cond in cols:
4449 for name, data, cond in cols:
4475 field = fieldnamemap.get(name, name)
4450 field = fieldnamemap.get(name, name)
4476 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4451 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4477 if cond and name != lastcol:
4452 if cond and name != lastcol:
4478 fm.plain(sep, label='grep.sep')
4453 fm.plain(sep, label='grep.sep')
4479 if not opts.get('files_with_matches'):
4454 if not opts.get('files_with_matches'):
4480 fm.plain(sep, label='grep.sep')
4455 fm.plain(sep, label='grep.sep')
4481 if not opts.get('text') and binary():
4456 if not opts.get('text') and binary():
4482 fm.plain(_(" Binary file matches"))
4457 fm.plain(_(" Binary file matches"))
4483 else:
4458 else:
4484 displaymatches(fm.nested('texts'), l)
4459 displaymatches(fm.nested('texts'), l)
4485 fm.plain(eol)
4460 fm.plain(eol)
4486 found = True
4461 found = True
4487 if opts.get('files_with_matches'):
4462 if opts.get('files_with_matches'):
4488 break
4463 break
4489 return found
4464 return found
4490
4465
4491 def displaymatches(fm, l):
4466 def displaymatches(fm, l):
4492 p = 0
4467 p = 0
4493 for s, e in l.findpos():
4468 for s, e in l.findpos():
4494 if p < s:
4469 if p < s:
4495 fm.startitem()
4470 fm.startitem()
4496 fm.write('text', '%s', l.line[p:s])
4471 fm.write('text', '%s', l.line[p:s])
4497 fm.data(matched=False)
4472 fm.data(matched=False)
4498 fm.startitem()
4473 fm.startitem()
4499 fm.write('text', '%s', l.line[s:e], label='grep.match')
4474 fm.write('text', '%s', l.line[s:e], label='grep.match')
4500 fm.data(matched=True)
4475 fm.data(matched=True)
4501 p = e
4476 p = e
4502 if p < len(l.line):
4477 if p < len(l.line):
4503 fm.startitem()
4478 fm.startitem()
4504 fm.write('text', '%s', l.line[p:])
4479 fm.write('text', '%s', l.line[p:])
4505 fm.data(matched=False)
4480 fm.data(matched=False)
4506 fm.end()
4481 fm.end()
4507
4482
4508 skip = {}
4483 skip = {}
4509 revfiles = {}
4484 revfiles = {}
4510 matchfn = scmutil.match(repo[None], pats, opts)
4485 matchfn = scmutil.match(repo[None], pats, opts)
4511 found = False
4486 found = False
4512 follow = opts.get('follow')
4487 follow = opts.get('follow')
4513
4488
4514 def prep(ctx, fns):
4489 def prep(ctx, fns):
4515 rev = ctx.rev()
4490 rev = ctx.rev()
4516 pctx = ctx.p1()
4491 pctx = ctx.p1()
4517 parent = pctx.rev()
4492 parent = pctx.rev()
4518 matches.setdefault(rev, {})
4493 matches.setdefault(rev, {})
4519 matches.setdefault(parent, {})
4494 matches.setdefault(parent, {})
4520 files = revfiles.setdefault(rev, [])
4495 files = revfiles.setdefault(rev, [])
4521 for fn in fns:
4496 for fn in fns:
4522 flog = getfile(fn)
4497 flog = getfile(fn)
4523 try:
4498 try:
4524 fnode = ctx.filenode(fn)
4499 fnode = ctx.filenode(fn)
4525 except error.LookupError:
4500 except error.LookupError:
4526 continue
4501 continue
4527
4502
4528 copied = flog.renamed(fnode)
4503 copied = flog.renamed(fnode)
4529 copy = follow and copied and copied[0]
4504 copy = follow and copied and copied[0]
4530 if copy:
4505 if copy:
4531 copies.setdefault(rev, {})[fn] = copy
4506 copies.setdefault(rev, {})[fn] = copy
4532 if fn in skip:
4507 if fn in skip:
4533 if copy:
4508 if copy:
4534 skip[copy] = True
4509 skip[copy] = True
4535 continue
4510 continue
4536 files.append(fn)
4511 files.append(fn)
4537
4512
4538 if fn not in matches[rev]:
4513 if fn not in matches[rev]:
4539 grepbody(fn, rev, flog.read(fnode))
4514 grepbody(fn, rev, flog.read(fnode))
4540
4515
4541 pfn = copy or fn
4516 pfn = copy or fn
4542 if pfn not in matches[parent]:
4517 if pfn not in matches[parent]:
4543 try:
4518 try:
4544 fnode = pctx.filenode(pfn)
4519 fnode = pctx.filenode(pfn)
4545 grepbody(pfn, parent, flog.read(fnode))
4520 grepbody(pfn, parent, flog.read(fnode))
4546 except error.LookupError:
4521 except error.LookupError:
4547 pass
4522 pass
4548
4523
4549 fm = ui.formatter('grep', opts)
4524 fm = ui.formatter('grep', opts)
4550 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4525 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4551 rev = ctx.rev()
4526 rev = ctx.rev()
4552 parent = ctx.p1().rev()
4527 parent = ctx.p1().rev()
4553 for fn in sorted(revfiles.get(rev, [])):
4528 for fn in sorted(revfiles.get(rev, [])):
4554 states = matches[rev][fn]
4529 states = matches[rev][fn]
4555 copy = copies.get(rev, {}).get(fn)
4530 copy = copies.get(rev, {}).get(fn)
4556 if fn in skip:
4531 if fn in skip:
4557 if copy:
4532 if copy:
4558 skip[copy] = True
4533 skip[copy] = True
4559 continue
4534 continue
4560 pstates = matches.get(parent, {}).get(copy or fn, [])
4535 pstates = matches.get(parent, {}).get(copy or fn, [])
4561 if pstates or states:
4536 if pstates or states:
4562 r = display(fm, fn, ctx, pstates, states)
4537 r = display(fm, fn, ctx, pstates, states)
4563 found = found or r
4538 found = found or r
4564 if r and not opts.get('all'):
4539 if r and not opts.get('all'):
4565 skip[fn] = True
4540 skip[fn] = True
4566 if copy:
4541 if copy:
4567 skip[copy] = True
4542 skip[copy] = True
4568 del matches[rev]
4543 del matches[rev]
4569 del revfiles[rev]
4544 del revfiles[rev]
4570 fm.end()
4545 fm.end()
4571
4546
4572 return not found
4547 return not found
4573
4548
4574 @command('heads',
4549 @command('heads',
4575 [('r', 'rev', '',
4550 [('r', 'rev', '',
4576 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4551 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4577 ('t', 'topo', False, _('show topological heads only')),
4552 ('t', 'topo', False, _('show topological heads only')),
4578 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4553 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4579 ('c', 'closed', False, _('show normal and closed branch heads')),
4554 ('c', 'closed', False, _('show normal and closed branch heads')),
4580 ] + templateopts,
4555 ] + templateopts,
4581 _('[-ct] [-r STARTREV] [REV]...'))
4556 _('[-ct] [-r STARTREV] [REV]...'))
4582 def heads(ui, repo, *branchrevs, **opts):
4557 def heads(ui, repo, *branchrevs, **opts):
4583 """show branch heads
4558 """show branch heads
4584
4559
4585 With no arguments, show all open branch heads in the repository.
4560 With no arguments, show all open branch heads in the repository.
4586 Branch heads are changesets that have no descendants on the
4561 Branch heads are changesets that have no descendants on the
4587 same branch. They are where development generally takes place and
4562 same branch. They are where development generally takes place and
4588 are the usual targets for update and merge operations.
4563 are the usual targets for update and merge operations.
4589
4564
4590 If one or more REVs are given, only open branch heads on the
4565 If one or more REVs are given, only open branch heads on the
4591 branches associated with the specified changesets are shown. This
4566 branches associated with the specified changesets are shown. This
4592 means that you can use :hg:`heads .` to see the heads on the
4567 means that you can use :hg:`heads .` to see the heads on the
4593 currently checked-out branch.
4568 currently checked-out branch.
4594
4569
4595 If -c/--closed is specified, also show branch heads marked closed
4570 If -c/--closed is specified, also show branch heads marked closed
4596 (see :hg:`commit --close-branch`).
4571 (see :hg:`commit --close-branch`).
4597
4572
4598 If STARTREV is specified, only those heads that are descendants of
4573 If STARTREV is specified, only those heads that are descendants of
4599 STARTREV will be displayed.
4574 STARTREV will be displayed.
4600
4575
4601 If -t/--topo is specified, named branch mechanics will be ignored and only
4576 If -t/--topo is specified, named branch mechanics will be ignored and only
4602 topological heads (changesets with no children) will be shown.
4577 topological heads (changesets with no children) will be shown.
4603
4578
4604 Returns 0 if matching heads are found, 1 if not.
4579 Returns 0 if matching heads are found, 1 if not.
4605 """
4580 """
4606
4581
4607 start = None
4582 start = None
4608 if 'rev' in opts:
4583 if 'rev' in opts:
4609 start = scmutil.revsingle(repo, opts['rev'], None).node()
4584 start = scmutil.revsingle(repo, opts['rev'], None).node()
4610
4585
4611 if opts.get('topo'):
4586 if opts.get('topo'):
4612 heads = [repo[h] for h in repo.heads(start)]
4587 heads = [repo[h] for h in repo.heads(start)]
4613 else:
4588 else:
4614 heads = []
4589 heads = []
4615 for branch in repo.branchmap():
4590 for branch in repo.branchmap():
4616 heads += repo.branchheads(branch, start, opts.get('closed'))
4591 heads += repo.branchheads(branch, start, opts.get('closed'))
4617 heads = [repo[h] for h in heads]
4592 heads = [repo[h] for h in heads]
4618
4593
4619 if branchrevs:
4594 if branchrevs:
4620 branches = set(repo[br].branch() for br in branchrevs)
4595 branches = set(repo[br].branch() for br in branchrevs)
4621 heads = [h for h in heads if h.branch() in branches]
4596 heads = [h for h in heads if h.branch() in branches]
4622
4597
4623 if opts.get('active') and branchrevs:
4598 if opts.get('active') and branchrevs:
4624 dagheads = repo.heads(start)
4599 dagheads = repo.heads(start)
4625 heads = [h for h in heads if h.node() in dagheads]
4600 heads = [h for h in heads if h.node() in dagheads]
4626
4601
4627 if branchrevs:
4602 if branchrevs:
4628 haveheads = set(h.branch() for h in heads)
4603 haveheads = set(h.branch() for h in heads)
4629 if branches - haveheads:
4604 if branches - haveheads:
4630 headless = ', '.join(b for b in branches - haveheads)
4605 headless = ', '.join(b for b in branches - haveheads)
4631 msg = _('no open branch heads found on branches %s')
4606 msg = _('no open branch heads found on branches %s')
4632 if opts.get('rev'):
4607 if opts.get('rev'):
4633 msg += _(' (started at %s)') % opts['rev']
4608 msg += _(' (started at %s)') % opts['rev']
4634 ui.warn((msg + '\n') % headless)
4609 ui.warn((msg + '\n') % headless)
4635
4610
4636 if not heads:
4611 if not heads:
4637 return 1
4612 return 1
4638
4613
4639 heads = sorted(heads, key=lambda x: -x.rev())
4614 heads = sorted(heads, key=lambda x: -x.rev())
4640 displayer = cmdutil.show_changeset(ui, repo, opts)
4615 displayer = cmdutil.show_changeset(ui, repo, opts)
4641 for ctx in heads:
4616 for ctx in heads:
4642 displayer.show(ctx)
4617 displayer.show(ctx)
4643 displayer.close()
4618 displayer.close()
4644
4619
4645 @command('help',
4620 @command('help',
4646 [('e', 'extension', None, _('show only help for extensions')),
4621 [('e', 'extension', None, _('show only help for extensions')),
4647 ('c', 'command', None, _('show only help for commands')),
4622 ('c', 'command', None, _('show only help for commands')),
4648 ('k', 'keyword', None, _('show topics matching keyword')),
4623 ('k', 'keyword', None, _('show topics matching keyword')),
4649 ('s', 'system', [], _('show help for specific platform(s)')),
4624 ('s', 'system', [], _('show help for specific platform(s)')),
4650 ],
4625 ],
4651 _('[-ecks] [TOPIC]'),
4626 _('[-ecks] [TOPIC]'),
4652 norepo=True)
4627 norepo=True)
4653 def help_(ui, name=None, **opts):
4628 def help_(ui, name=None, **opts):
4654 """show help for a given topic or a help overview
4629 """show help for a given topic or a help overview
4655
4630
4656 With no arguments, print a list of commands with short help messages.
4631 With no arguments, print a list of commands with short help messages.
4657
4632
4658 Given a topic, extension, or command name, print help for that
4633 Given a topic, extension, or command name, print help for that
4659 topic.
4634 topic.
4660
4635
4661 Returns 0 if successful.
4636 Returns 0 if successful.
4662 """
4637 """
4663
4638
4664 textwidth = ui.configint('ui', 'textwidth', 78)
4639 textwidth = ui.configint('ui', 'textwidth', 78)
4665 termwidth = ui.termwidth() - 2
4640 termwidth = ui.termwidth() - 2
4666 if textwidth <= 0 or termwidth < textwidth:
4641 if textwidth <= 0 or termwidth < textwidth:
4667 textwidth = termwidth
4642 textwidth = termwidth
4668
4643
4669 keep = opts.get('system') or []
4644 keep = opts.get('system') or []
4670 if len(keep) == 0:
4645 if len(keep) == 0:
4671 if sys.platform.startswith('win'):
4646 if sys.platform.startswith('win'):
4672 keep.append('windows')
4647 keep.append('windows')
4673 elif sys.platform == 'OpenVMS':
4648 elif sys.platform == 'OpenVMS':
4674 keep.append('vms')
4649 keep.append('vms')
4675 elif sys.platform == 'plan9':
4650 elif sys.platform == 'plan9':
4676 keep.append('plan9')
4651 keep.append('plan9')
4677 else:
4652 else:
4678 keep.append('unix')
4653 keep.append('unix')
4679 keep.append(sys.platform.lower())
4654 keep.append(sys.platform.lower())
4680 if ui.verbose:
4655 if ui.verbose:
4681 keep.append('verbose')
4656 keep.append('verbose')
4682
4657
4683 section = None
4658 section = None
4684 subtopic = None
4659 subtopic = None
4685 if name and '.' in name:
4660 if name and '.' in name:
4686 name, remaining = name.split('.', 1)
4661 name, remaining = name.split('.', 1)
4687 remaining = encoding.lower(remaining)
4662 remaining = encoding.lower(remaining)
4688 if '.' in remaining:
4663 if '.' in remaining:
4689 subtopic, section = remaining.split('.', 1)
4664 subtopic, section = remaining.split('.', 1)
4690 else:
4665 else:
4691 if name in help.subtopics:
4666 if name in help.subtopics:
4692 subtopic = remaining
4667 subtopic = remaining
4693 else:
4668 else:
4694 section = remaining
4669 section = remaining
4695
4670
4696 text = help.help_(ui, name, subtopic=subtopic, **opts)
4671 text = help.help_(ui, name, subtopic=subtopic, **opts)
4697
4672
4698 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4673 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4699 section=section)
4674 section=section)
4700
4675
4701 # We could have been given a weird ".foo" section without a name
4676 # We could have been given a weird ".foo" section without a name
4702 # to look for, or we could have simply failed to found "foo.bar"
4677 # to look for, or we could have simply failed to found "foo.bar"
4703 # because bar isn't a section of foo
4678 # because bar isn't a section of foo
4704 if section and not (formatted and name):
4679 if section and not (formatted and name):
4705 raise error.Abort(_("help section not found"))
4680 raise error.Abort(_("help section not found"))
4706
4681
4707 if 'verbose' in pruned:
4682 if 'verbose' in pruned:
4708 keep.append('omitted')
4683 keep.append('omitted')
4709 else:
4684 else:
4710 keep.append('notomitted')
4685 keep.append('notomitted')
4711 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4686 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4712 section=section)
4687 section=section)
4713 ui.write(formatted)
4688 ui.write(formatted)
4714
4689
4715
4690
4716 @command('identify|id',
4691 @command('identify|id',
4717 [('r', 'rev', '',
4692 [('r', 'rev', '',
4718 _('identify the specified revision'), _('REV')),
4693 _('identify the specified revision'), _('REV')),
4719 ('n', 'num', None, _('show local revision number')),
4694 ('n', 'num', None, _('show local revision number')),
4720 ('i', 'id', None, _('show global revision id')),
4695 ('i', 'id', None, _('show global revision id')),
4721 ('b', 'branch', None, _('show branch')),
4696 ('b', 'branch', None, _('show branch')),
4722 ('t', 'tags', None, _('show tags')),
4697 ('t', 'tags', None, _('show tags')),
4723 ('B', 'bookmarks', None, _('show bookmarks')),
4698 ('B', 'bookmarks', None, _('show bookmarks')),
4724 ] + remoteopts,
4699 ] + remoteopts,
4725 _('[-nibtB] [-r REV] [SOURCE]'),
4700 _('[-nibtB] [-r REV] [SOURCE]'),
4726 optionalrepo=True)
4701 optionalrepo=True)
4727 def identify(ui, repo, source=None, rev=None,
4702 def identify(ui, repo, source=None, rev=None,
4728 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4703 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4729 """identify the working directory or specified revision
4704 """identify the working directory or specified revision
4730
4705
4731 Print a summary identifying the repository state at REV using one or
4706 Print a summary identifying the repository state at REV using one or
4732 two parent hash identifiers, followed by a "+" if the working
4707 two parent hash identifiers, followed by a "+" if the working
4733 directory has uncommitted changes, the branch name (if not default),
4708 directory has uncommitted changes, the branch name (if not default),
4734 a list of tags, and a list of bookmarks.
4709 a list of tags, and a list of bookmarks.
4735
4710
4736 When REV is not given, print a summary of the current state of the
4711 When REV is not given, print a summary of the current state of the
4737 repository.
4712 repository.
4738
4713
4739 Specifying a path to a repository root or Mercurial bundle will
4714 Specifying a path to a repository root or Mercurial bundle will
4740 cause lookup to operate on that repository/bundle.
4715 cause lookup to operate on that repository/bundle.
4741
4716
4742 .. container:: verbose
4717 .. container:: verbose
4743
4718
4744 Examples:
4719 Examples:
4745
4720
4746 - generate a build identifier for the working directory::
4721 - generate a build identifier for the working directory::
4747
4722
4748 hg id --id > build-id.dat
4723 hg id --id > build-id.dat
4749
4724
4750 - find the revision corresponding to a tag::
4725 - find the revision corresponding to a tag::
4751
4726
4752 hg id -n -r 1.3
4727 hg id -n -r 1.3
4753
4728
4754 - check the most recent revision of a remote repository::
4729 - check the most recent revision of a remote repository::
4755
4730
4756 hg id -r tip http://selenic.com/hg/
4731 hg id -r tip http://selenic.com/hg/
4757
4732
4758 See :hg:`log` for generating more information about specific revisions,
4733 See :hg:`log` for generating more information about specific revisions,
4759 including full hash identifiers.
4734 including full hash identifiers.
4760
4735
4761 Returns 0 if successful.
4736 Returns 0 if successful.
4762 """
4737 """
4763
4738
4764 if not repo and not source:
4739 if not repo and not source:
4765 raise error.Abort(_("there is no Mercurial repository here "
4740 raise error.Abort(_("there is no Mercurial repository here "
4766 "(.hg not found)"))
4741 "(.hg not found)"))
4767
4742
4768 if ui.debugflag:
4743 if ui.debugflag:
4769 hexfunc = hex
4744 hexfunc = hex
4770 else:
4745 else:
4771 hexfunc = short
4746 hexfunc = short
4772 default = not (num or id or branch or tags or bookmarks)
4747 default = not (num or id or branch or tags or bookmarks)
4773 output = []
4748 output = []
4774 revs = []
4749 revs = []
4775
4750
4776 if source:
4751 if source:
4777 source, branches = hg.parseurl(ui.expandpath(source))
4752 source, branches = hg.parseurl(ui.expandpath(source))
4778 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4753 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4779 repo = peer.local()
4754 repo = peer.local()
4780 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4755 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4781
4756
4782 if not repo:
4757 if not repo:
4783 if num or branch or tags:
4758 if num or branch or tags:
4784 raise error.Abort(
4759 raise error.Abort(
4785 _("can't query remote revision number, branch, or tags"))
4760 _("can't query remote revision number, branch, or tags"))
4786 if not rev and revs:
4761 if not rev and revs:
4787 rev = revs[0]
4762 rev = revs[0]
4788 if not rev:
4763 if not rev:
4789 rev = "tip"
4764 rev = "tip"
4790
4765
4791 remoterev = peer.lookup(rev)
4766 remoterev = peer.lookup(rev)
4792 if default or id:
4767 if default or id:
4793 output = [hexfunc(remoterev)]
4768 output = [hexfunc(remoterev)]
4794
4769
4795 def getbms():
4770 def getbms():
4796 bms = []
4771 bms = []
4797
4772
4798 if 'bookmarks' in peer.listkeys('namespaces'):
4773 if 'bookmarks' in peer.listkeys('namespaces'):
4799 hexremoterev = hex(remoterev)
4774 hexremoterev = hex(remoterev)
4800 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4775 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4801 if bmr == hexremoterev]
4776 if bmr == hexremoterev]
4802
4777
4803 return sorted(bms)
4778 return sorted(bms)
4804
4779
4805 if bookmarks:
4780 if bookmarks:
4806 output.extend(getbms())
4781 output.extend(getbms())
4807 elif default and not ui.quiet:
4782 elif default and not ui.quiet:
4808 # multiple bookmarks for a single parent separated by '/'
4783 # multiple bookmarks for a single parent separated by '/'
4809 bm = '/'.join(getbms())
4784 bm = '/'.join(getbms())
4810 if bm:
4785 if bm:
4811 output.append(bm)
4786 output.append(bm)
4812 else:
4787 else:
4813 ctx = scmutil.revsingle(repo, rev, None)
4788 ctx = scmutil.revsingle(repo, rev, None)
4814
4789
4815 if ctx.rev() is None:
4790 if ctx.rev() is None:
4816 ctx = repo[None]
4791 ctx = repo[None]
4817 parents = ctx.parents()
4792 parents = ctx.parents()
4818 taglist = []
4793 taglist = []
4819 for p in parents:
4794 for p in parents:
4820 taglist.extend(p.tags())
4795 taglist.extend(p.tags())
4821
4796
4822 changed = ""
4797 changed = ""
4823 if default or id or num:
4798 if default or id or num:
4824 if (any(repo.status())
4799 if (any(repo.status())
4825 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4800 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4826 changed = '+'
4801 changed = '+'
4827 if default or id:
4802 if default or id:
4828 output = ["%s%s" %
4803 output = ["%s%s" %
4829 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4804 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4830 if num:
4805 if num:
4831 output.append("%s%s" %
4806 output.append("%s%s" %
4832 ('+'.join([str(p.rev()) for p in parents]), changed))
4807 ('+'.join([str(p.rev()) for p in parents]), changed))
4833 else:
4808 else:
4834 if default or id:
4809 if default or id:
4835 output = [hexfunc(ctx.node())]
4810 output = [hexfunc(ctx.node())]
4836 if num:
4811 if num:
4837 output.append(str(ctx.rev()))
4812 output.append(str(ctx.rev()))
4838 taglist = ctx.tags()
4813 taglist = ctx.tags()
4839
4814
4840 if default and not ui.quiet:
4815 if default and not ui.quiet:
4841 b = ctx.branch()
4816 b = ctx.branch()
4842 if b != 'default':
4817 if b != 'default':
4843 output.append("(%s)" % b)
4818 output.append("(%s)" % b)
4844
4819
4845 # multiple tags for a single parent separated by '/'
4820 # multiple tags for a single parent separated by '/'
4846 t = '/'.join(taglist)
4821 t = '/'.join(taglist)
4847 if t:
4822 if t:
4848 output.append(t)
4823 output.append(t)
4849
4824
4850 # multiple bookmarks for a single parent separated by '/'
4825 # multiple bookmarks for a single parent separated by '/'
4851 bm = '/'.join(ctx.bookmarks())
4826 bm = '/'.join(ctx.bookmarks())
4852 if bm:
4827 if bm:
4853 output.append(bm)
4828 output.append(bm)
4854 else:
4829 else:
4855 if branch:
4830 if branch:
4856 output.append(ctx.branch())
4831 output.append(ctx.branch())
4857
4832
4858 if tags:
4833 if tags:
4859 output.extend(taglist)
4834 output.extend(taglist)
4860
4835
4861 if bookmarks:
4836 if bookmarks:
4862 output.extend(ctx.bookmarks())
4837 output.extend(ctx.bookmarks())
4863
4838
4864 ui.write("%s\n" % ' '.join(output))
4839 ui.write("%s\n" % ' '.join(output))
4865
4840
4866 @command('import|patch',
4841 @command('import|patch',
4867 [('p', 'strip', 1,
4842 [('p', 'strip', 1,
4868 _('directory strip option for patch. This has the same '
4843 _('directory strip option for patch. This has the same '
4869 'meaning as the corresponding patch option'), _('NUM')),
4844 'meaning as the corresponding patch option'), _('NUM')),
4870 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4845 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4871 ('e', 'edit', False, _('invoke editor on commit messages')),
4846 ('e', 'edit', False, _('invoke editor on commit messages')),
4872 ('f', 'force', None,
4847 ('f', 'force', None,
4873 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4848 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4874 ('', 'no-commit', None,
4849 ('', 'no-commit', None,
4875 _("don't commit, just update the working directory")),
4850 _("don't commit, just update the working directory")),
4876 ('', 'bypass', None,
4851 ('', 'bypass', None,
4877 _("apply patch without touching the working directory")),
4852 _("apply patch without touching the working directory")),
4878 ('', 'partial', None,
4853 ('', 'partial', None,
4879 _('commit even if some hunks fail')),
4854 _('commit even if some hunks fail')),
4880 ('', 'exact', None,
4855 ('', 'exact', None,
4881 _('abort if patch would apply lossily')),
4856 _('abort if patch would apply lossily')),
4882 ('', 'prefix', '',
4857 ('', 'prefix', '',
4883 _('apply patch to subdirectory'), _('DIR')),
4858 _('apply patch to subdirectory'), _('DIR')),
4884 ('', 'import-branch', None,
4859 ('', 'import-branch', None,
4885 _('use any branch information in patch (implied by --exact)'))] +
4860 _('use any branch information in patch (implied by --exact)'))] +
4886 commitopts + commitopts2 + similarityopts,
4861 commitopts + commitopts2 + similarityopts,
4887 _('[OPTION]... PATCH...'))
4862 _('[OPTION]... PATCH...'))
4888 def import_(ui, repo, patch1=None, *patches, **opts):
4863 def import_(ui, repo, patch1=None, *patches, **opts):
4889 """import an ordered set of patches
4864 """import an ordered set of patches
4890
4865
4891 Import a list of patches and commit them individually (unless
4866 Import a list of patches and commit them individually (unless
4892 --no-commit is specified).
4867 --no-commit is specified).
4893
4868
4894 To read a patch from standard input, use "-" as the patch name. If
4869 To read a patch from standard input, use "-" as the patch name. If
4895 a URL is specified, the patch will be downloaded from there.
4870 a URL is specified, the patch will be downloaded from there.
4896
4871
4897 Import first applies changes to the working directory (unless
4872 Import first applies changes to the working directory (unless
4898 --bypass is specified), import will abort if there are outstanding
4873 --bypass is specified), import will abort if there are outstanding
4899 changes.
4874 changes.
4900
4875
4901 Use --bypass to apply and commit patches directly to the
4876 Use --bypass to apply and commit patches directly to the
4902 repository, without affecting the working directory. Without
4877 repository, without affecting the working directory. Without
4903 --exact, patches will be applied on top of the working directory
4878 --exact, patches will be applied on top of the working directory
4904 parent revision.
4879 parent revision.
4905
4880
4906 You can import a patch straight from a mail message. Even patches
4881 You can import a patch straight from a mail message. Even patches
4907 as attachments work (to use the body part, it must have type
4882 as attachments work (to use the body part, it must have type
4908 text/plain or text/x-patch). From and Subject headers of email
4883 text/plain or text/x-patch). From and Subject headers of email
4909 message are used as default committer and commit message. All
4884 message are used as default committer and commit message. All
4910 text/plain body parts before first diff are added to the commit
4885 text/plain body parts before first diff are added to the commit
4911 message.
4886 message.
4912
4887
4913 If the imported patch was generated by :hg:`export`, user and
4888 If the imported patch was generated by :hg:`export`, user and
4914 description from patch override values from message headers and
4889 description from patch override values from message headers and
4915 body. Values given on command line with -m/--message and -u/--user
4890 body. Values given on command line with -m/--message and -u/--user
4916 override these.
4891 override these.
4917
4892
4918 If --exact is specified, import will set the working directory to
4893 If --exact is specified, import will set the working directory to
4919 the parent of each patch before applying it, and will abort if the
4894 the parent of each patch before applying it, and will abort if the
4920 resulting changeset has a different ID than the one recorded in
4895 resulting changeset has a different ID than the one recorded in
4921 the patch. This will guard against various ways that portable
4896 the patch. This will guard against various ways that portable
4922 patch formats and mail systems might fail to transfer Mercurial
4897 patch formats and mail systems might fail to transfer Mercurial
4923 data or metadata. See :hg:`bundle` for lossless transmission.
4898 data or metadata. See :hg:`bundle` for lossless transmission.
4924
4899
4925 Use --partial to ensure a changeset will be created from the patch
4900 Use --partial to ensure a changeset will be created from the patch
4926 even if some hunks fail to apply. Hunks that fail to apply will be
4901 even if some hunks fail to apply. Hunks that fail to apply will be
4927 written to a <target-file>.rej file. Conflicts can then be resolved
4902 written to a <target-file>.rej file. Conflicts can then be resolved
4928 by hand before :hg:`commit --amend` is run to update the created
4903 by hand before :hg:`commit --amend` is run to update the created
4929 changeset. This flag exists to let people import patches that
4904 changeset. This flag exists to let people import patches that
4930 partially apply without losing the associated metadata (author,
4905 partially apply without losing the associated metadata (author,
4931 date, description, ...).
4906 date, description, ...).
4932
4907
4933 .. note::
4908 .. note::
4934
4909
4935 When no hunks apply cleanly, :hg:`import --partial` will create
4910 When no hunks apply cleanly, :hg:`import --partial` will create
4936 an empty changeset, importing only the patch metadata.
4911 an empty changeset, importing only the patch metadata.
4937
4912
4938 With -s/--similarity, hg will attempt to discover renames and
4913 With -s/--similarity, hg will attempt to discover renames and
4939 copies in the patch in the same way as :hg:`addremove`.
4914 copies in the patch in the same way as :hg:`addremove`.
4940
4915
4941 It is possible to use external patch programs to perform the patch
4916 It is possible to use external patch programs to perform the patch
4942 by setting the ``ui.patch`` configuration option. For the default
4917 by setting the ``ui.patch`` configuration option. For the default
4943 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4918 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4944 See :hg:`help config` for more information about configuration
4919 See :hg:`help config` for more information about configuration
4945 files and how to use these options.
4920 files and how to use these options.
4946
4921
4947 See :hg:`help dates` for a list of formats valid for -d/--date.
4922 See :hg:`help dates` for a list of formats valid for -d/--date.
4948
4923
4949 .. container:: verbose
4924 .. container:: verbose
4950
4925
4951 Examples:
4926 Examples:
4952
4927
4953 - import a traditional patch from a website and detect renames::
4928 - import a traditional patch from a website and detect renames::
4954
4929
4955 hg import -s 80 http://example.com/bugfix.patch
4930 hg import -s 80 http://example.com/bugfix.patch
4956
4931
4957 - import a changeset from an hgweb server::
4932 - import a changeset from an hgweb server::
4958
4933
4959 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4934 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4960
4935
4961 - import all the patches in an Unix-style mbox::
4936 - import all the patches in an Unix-style mbox::
4962
4937
4963 hg import incoming-patches.mbox
4938 hg import incoming-patches.mbox
4964
4939
4965 - attempt to exactly restore an exported changeset (not always
4940 - attempt to exactly restore an exported changeset (not always
4966 possible)::
4941 possible)::
4967
4942
4968 hg import --exact proposed-fix.patch
4943 hg import --exact proposed-fix.patch
4969
4944
4970 - use an external tool to apply a patch which is too fuzzy for
4945 - use an external tool to apply a patch which is too fuzzy for
4971 the default internal tool.
4946 the default internal tool.
4972
4947
4973 hg import --config ui.patch="patch --merge" fuzzy.patch
4948 hg import --config ui.patch="patch --merge" fuzzy.patch
4974
4949
4975 - change the default fuzzing from 2 to a less strict 7
4950 - change the default fuzzing from 2 to a less strict 7
4976
4951
4977 hg import --config ui.fuzz=7 fuzz.patch
4952 hg import --config ui.fuzz=7 fuzz.patch
4978
4953
4979 Returns 0 on success, 1 on partial success (see --partial).
4954 Returns 0 on success, 1 on partial success (see --partial).
4980 """
4955 """
4981
4956
4982 if not patch1:
4957 if not patch1:
4983 raise error.Abort(_('need at least one patch to import'))
4958 raise error.Abort(_('need at least one patch to import'))
4984
4959
4985 patches = (patch1,) + patches
4960 patches = (patch1,) + patches
4986
4961
4987 date = opts.get('date')
4962 date = opts.get('date')
4988 if date:
4963 if date:
4989 opts['date'] = util.parsedate(date)
4964 opts['date'] = util.parsedate(date)
4990
4965
4991 exact = opts.get('exact')
4966 exact = opts.get('exact')
4992 update = not opts.get('bypass')
4967 update = not opts.get('bypass')
4993 if not update and opts.get('no_commit'):
4968 if not update and opts.get('no_commit'):
4994 raise error.Abort(_('cannot use --no-commit with --bypass'))
4969 raise error.Abort(_('cannot use --no-commit with --bypass'))
4995 try:
4970 try:
4996 sim = float(opts.get('similarity') or 0)
4971 sim = float(opts.get('similarity') or 0)
4997 except ValueError:
4972 except ValueError:
4998 raise error.Abort(_('similarity must be a number'))
4973 raise error.Abort(_('similarity must be a number'))
4999 if sim < 0 or sim > 100:
4974 if sim < 0 or sim > 100:
5000 raise error.Abort(_('similarity must be between 0 and 100'))
4975 raise error.Abort(_('similarity must be between 0 and 100'))
5001 if sim and not update:
4976 if sim and not update:
5002 raise error.Abort(_('cannot use --similarity with --bypass'))
4977 raise error.Abort(_('cannot use --similarity with --bypass'))
5003 if exact:
4978 if exact:
5004 if opts.get('edit'):
4979 if opts.get('edit'):
5005 raise error.Abort(_('cannot use --exact with --edit'))
4980 raise error.Abort(_('cannot use --exact with --edit'))
5006 if opts.get('prefix'):
4981 if opts.get('prefix'):
5007 raise error.Abort(_('cannot use --exact with --prefix'))
4982 raise error.Abort(_('cannot use --exact with --prefix'))
5008
4983
5009 base = opts["base"]
4984 base = opts["base"]
5010 wlock = dsguard = lock = tr = None
4985 wlock = dsguard = lock = tr = None
5011 msgs = []
4986 msgs = []
5012 ret = 0
4987 ret = 0
5013
4988
5014
4989
5015 try:
4990 try:
5016 wlock = repo.wlock()
4991 wlock = repo.wlock()
5017
4992
5018 if update:
4993 if update:
5019 cmdutil.checkunfinished(repo)
4994 cmdutil.checkunfinished(repo)
5020 if (exact or not opts.get('force')):
4995 if (exact or not opts.get('force')):
5021 cmdutil.bailifchanged(repo)
4996 cmdutil.bailifchanged(repo)
5022
4997
5023 if not opts.get('no_commit'):
4998 if not opts.get('no_commit'):
5024 lock = repo.lock()
4999 lock = repo.lock()
5025 tr = repo.transaction('import')
5000 tr = repo.transaction('import')
5026 else:
5001 else:
5027 dsguard = cmdutil.dirstateguard(repo, 'import')
5002 dsguard = cmdutil.dirstateguard(repo, 'import')
5028 parents = repo[None].parents()
5003 parents = repo[None].parents()
5029 for patchurl in patches:
5004 for patchurl in patches:
5030 if patchurl == '-':
5005 if patchurl == '-':
5031 ui.status(_('applying patch from stdin\n'))
5006 ui.status(_('applying patch from stdin\n'))
5032 patchfile = ui.fin
5007 patchfile = ui.fin
5033 patchurl = 'stdin' # for error message
5008 patchurl = 'stdin' # for error message
5034 else:
5009 else:
5035 patchurl = os.path.join(base, patchurl)
5010 patchurl = os.path.join(base, patchurl)
5036 ui.status(_('applying %s\n') % patchurl)
5011 ui.status(_('applying %s\n') % patchurl)
5037 patchfile = hg.openpath(ui, patchurl)
5012 patchfile = hg.openpath(ui, patchurl)
5038
5013
5039 haspatch = False
5014 haspatch = False
5040 for hunk in patch.split(patchfile):
5015 for hunk in patch.split(patchfile):
5041 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
5016 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
5042 parents, opts,
5017 parents, opts,
5043 msgs, hg.clean)
5018 msgs, hg.clean)
5044 if msg:
5019 if msg:
5045 haspatch = True
5020 haspatch = True
5046 ui.note(msg + '\n')
5021 ui.note(msg + '\n')
5047 if update or exact:
5022 if update or exact:
5048 parents = repo[None].parents()
5023 parents = repo[None].parents()
5049 else:
5024 else:
5050 parents = [repo[node]]
5025 parents = [repo[node]]
5051 if rej:
5026 if rej:
5052 ui.write_err(_("patch applied partially\n"))
5027 ui.write_err(_("patch applied partially\n"))
5053 ui.write_err(_("(fix the .rej files and run "
5028 ui.write_err(_("(fix the .rej files and run "
5054 "`hg commit --amend`)\n"))
5029 "`hg commit --amend`)\n"))
5055 ret = 1
5030 ret = 1
5056 break
5031 break
5057
5032
5058 if not haspatch:
5033 if not haspatch:
5059 raise error.Abort(_('%s: no diffs found') % patchurl)
5034 raise error.Abort(_('%s: no diffs found') % patchurl)
5060
5035
5061 if tr:
5036 if tr:
5062 tr.close()
5037 tr.close()
5063 if msgs:
5038 if msgs:
5064 repo.savecommitmessage('\n* * *\n'.join(msgs))
5039 repo.savecommitmessage('\n* * *\n'.join(msgs))
5065 if dsguard:
5040 if dsguard:
5066 dsguard.close()
5041 dsguard.close()
5067 return ret
5042 return ret
5068 finally:
5043 finally:
5069 if tr:
5044 if tr:
5070 tr.release()
5045 tr.release()
5071 release(lock, dsguard, wlock)
5046 release(lock, dsguard, wlock)
5072
5047
5073 @command('incoming|in',
5048 @command('incoming|in',
5074 [('f', 'force', None,
5049 [('f', 'force', None,
5075 _('run even if remote repository is unrelated')),
5050 _('run even if remote repository is unrelated')),
5076 ('n', 'newest-first', None, _('show newest record first')),
5051 ('n', 'newest-first', None, _('show newest record first')),
5077 ('', 'bundle', '',
5052 ('', 'bundle', '',
5078 _('file to store the bundles into'), _('FILE')),
5053 _('file to store the bundles into'), _('FILE')),
5079 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5054 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5080 ('B', 'bookmarks', False, _("compare bookmarks")),
5055 ('B', 'bookmarks', False, _("compare bookmarks")),
5081 ('b', 'branch', [],
5056 ('b', 'branch', [],
5082 _('a specific branch you would like to pull'), _('BRANCH')),
5057 _('a specific branch you would like to pull'), _('BRANCH')),
5083 ] + logopts + remoteopts + subrepoopts,
5058 ] + logopts + remoteopts + subrepoopts,
5084 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
5059 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
5085 def incoming(ui, repo, source="default", **opts):
5060 def incoming(ui, repo, source="default", **opts):
5086 """show new changesets found in source
5061 """show new changesets found in source
5087
5062
5088 Show new changesets found in the specified path/URL or the default
5063 Show new changesets found in the specified path/URL or the default
5089 pull location. These are the changesets that would have been pulled
5064 pull location. These are the changesets that would have been pulled
5090 if a pull at the time you issued this command.
5065 if a pull at the time you issued this command.
5091
5066
5092 See pull for valid source format details.
5067 See pull for valid source format details.
5093
5068
5094 .. container:: verbose
5069 .. container:: verbose
5095
5070
5096 With -B/--bookmarks, the result of bookmark comparison between
5071 With -B/--bookmarks, the result of bookmark comparison between
5097 local and remote repositories is displayed. With -v/--verbose,
5072 local and remote repositories is displayed. With -v/--verbose,
5098 status is also displayed for each bookmark like below::
5073 status is also displayed for each bookmark like below::
5099
5074
5100 BM1 01234567890a added
5075 BM1 01234567890a added
5101 BM2 1234567890ab advanced
5076 BM2 1234567890ab advanced
5102 BM3 234567890abc diverged
5077 BM3 234567890abc diverged
5103 BM4 34567890abcd changed
5078 BM4 34567890abcd changed
5104
5079
5105 The action taken locally when pulling depends on the
5080 The action taken locally when pulling depends on the
5106 status of each bookmark:
5081 status of each bookmark:
5107
5082
5108 :``added``: pull will create it
5083 :``added``: pull will create it
5109 :``advanced``: pull will update it
5084 :``advanced``: pull will update it
5110 :``diverged``: pull will create a divergent bookmark
5085 :``diverged``: pull will create a divergent bookmark
5111 :``changed``: result depends on remote changesets
5086 :``changed``: result depends on remote changesets
5112
5087
5113 From the point of view of pulling behavior, bookmark
5088 From the point of view of pulling behavior, bookmark
5114 existing only in the remote repository are treated as ``added``,
5089 existing only in the remote repository are treated as ``added``,
5115 even if it is in fact locally deleted.
5090 even if it is in fact locally deleted.
5116
5091
5117 .. container:: verbose
5092 .. container:: verbose
5118
5093
5119 For remote repository, using --bundle avoids downloading the
5094 For remote repository, using --bundle avoids downloading the
5120 changesets twice if the incoming is followed by a pull.
5095 changesets twice if the incoming is followed by a pull.
5121
5096
5122 Examples:
5097 Examples:
5123
5098
5124 - show incoming changes with patches and full description::
5099 - show incoming changes with patches and full description::
5125
5100
5126 hg incoming -vp
5101 hg incoming -vp
5127
5102
5128 - show incoming changes excluding merges, store a bundle::
5103 - show incoming changes excluding merges, store a bundle::
5129
5104
5130 hg in -vpM --bundle incoming.hg
5105 hg in -vpM --bundle incoming.hg
5131 hg pull incoming.hg
5106 hg pull incoming.hg
5132
5107
5133 - briefly list changes inside a bundle::
5108 - briefly list changes inside a bundle::
5134
5109
5135 hg in changes.hg -T "{desc|firstline}\\n"
5110 hg in changes.hg -T "{desc|firstline}\\n"
5136
5111
5137 Returns 0 if there are incoming changes, 1 otherwise.
5112 Returns 0 if there are incoming changes, 1 otherwise.
5138 """
5113 """
5139 if opts.get('graph'):
5114 if opts.get('graph'):
5140 cmdutil.checkunsupportedgraphflags([], opts)
5115 cmdutil.checkunsupportedgraphflags([], opts)
5141 def display(other, chlist, displayer):
5116 def display(other, chlist, displayer):
5142 revdag = cmdutil.graphrevs(other, chlist, opts)
5117 revdag = cmdutil.graphrevs(other, chlist, opts)
5143 cmdutil.displaygraph(ui, repo, revdag, displayer,
5118 cmdutil.displaygraph(ui, repo, revdag, displayer,
5144 graphmod.asciiedges)
5119 graphmod.asciiedges)
5145
5120
5146 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5121 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5147 return 0
5122 return 0
5148
5123
5149 if opts.get('bundle') and opts.get('subrepos'):
5124 if opts.get('bundle') and opts.get('subrepos'):
5150 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5125 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5151
5126
5152 if opts.get('bookmarks'):
5127 if opts.get('bookmarks'):
5153 source, branches = hg.parseurl(ui.expandpath(source),
5128 source, branches = hg.parseurl(ui.expandpath(source),
5154 opts.get('branch'))
5129 opts.get('branch'))
5155 other = hg.peer(repo, opts, source)
5130 other = hg.peer(repo, opts, source)
5156 if 'bookmarks' not in other.listkeys('namespaces'):
5131 if 'bookmarks' not in other.listkeys('namespaces'):
5157 ui.warn(_("remote doesn't support bookmarks\n"))
5132 ui.warn(_("remote doesn't support bookmarks\n"))
5158 return 0
5133 return 0
5159 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5134 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5160 return bookmarks.incoming(ui, repo, other)
5135 return bookmarks.incoming(ui, repo, other)
5161
5136
5162 repo._subtoppath = ui.expandpath(source)
5137 repo._subtoppath = ui.expandpath(source)
5163 try:
5138 try:
5164 return hg.incoming(ui, repo, source, opts)
5139 return hg.incoming(ui, repo, source, opts)
5165 finally:
5140 finally:
5166 del repo._subtoppath
5141 del repo._subtoppath
5167
5142
5168
5143
5169 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5144 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5170 norepo=True)
5145 norepo=True)
5171 def init(ui, dest=".", **opts):
5146 def init(ui, dest=".", **opts):
5172 """create a new repository in the given directory
5147 """create a new repository in the given directory
5173
5148
5174 Initialize a new repository in the given directory. If the given
5149 Initialize a new repository in the given directory. If the given
5175 directory does not exist, it will be created.
5150 directory does not exist, it will be created.
5176
5151
5177 If no directory is given, the current directory is used.
5152 If no directory is given, the current directory is used.
5178
5153
5179 It is possible to specify an ``ssh://`` URL as the destination.
5154 It is possible to specify an ``ssh://`` URL as the destination.
5180 See :hg:`help urls` for more information.
5155 See :hg:`help urls` for more information.
5181
5156
5182 Returns 0 on success.
5157 Returns 0 on success.
5183 """
5158 """
5184 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5159 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5185
5160
5186 @command('locate',
5161 @command('locate',
5187 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5162 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5188 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5163 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5189 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5164 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5190 ] + walkopts,
5165 ] + walkopts,
5191 _('[OPTION]... [PATTERN]...'))
5166 _('[OPTION]... [PATTERN]...'))
5192 def locate(ui, repo, *pats, **opts):
5167 def locate(ui, repo, *pats, **opts):
5193 """locate files matching specific patterns (DEPRECATED)
5168 """locate files matching specific patterns (DEPRECATED)
5194
5169
5195 Print files under Mercurial control in the working directory whose
5170 Print files under Mercurial control in the working directory whose
5196 names match the given patterns.
5171 names match the given patterns.
5197
5172
5198 By default, this command searches all directories in the working
5173 By default, this command searches all directories in the working
5199 directory. To search just the current directory and its
5174 directory. To search just the current directory and its
5200 subdirectories, use "--include .".
5175 subdirectories, use "--include .".
5201
5176
5202 If no patterns are given to match, this command prints the names
5177 If no patterns are given to match, this command prints the names
5203 of all files under Mercurial control in the working directory.
5178 of all files under Mercurial control in the working directory.
5204
5179
5205 If you want to feed the output of this command into the "xargs"
5180 If you want to feed the output of this command into the "xargs"
5206 command, use the -0 option to both this command and "xargs". This
5181 command, use the -0 option to both this command and "xargs". This
5207 will avoid the problem of "xargs" treating single filenames that
5182 will avoid the problem of "xargs" treating single filenames that
5208 contain whitespace as multiple filenames.
5183 contain whitespace as multiple filenames.
5209
5184
5210 See :hg:`help files` for a more versatile command.
5185 See :hg:`help files` for a more versatile command.
5211
5186
5212 Returns 0 if a match is found, 1 otherwise.
5187 Returns 0 if a match is found, 1 otherwise.
5213 """
5188 """
5214 if opts.get('print0'):
5189 if opts.get('print0'):
5215 end = '\0'
5190 end = '\0'
5216 else:
5191 else:
5217 end = '\n'
5192 end = '\n'
5218 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5193 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5219
5194
5220 ret = 1
5195 ret = 1
5221 ctx = repo[rev]
5196 ctx = repo[rev]
5222 m = scmutil.match(ctx, pats, opts, default='relglob',
5197 m = scmutil.match(ctx, pats, opts, default='relglob',
5223 badfn=lambda x, y: False)
5198 badfn=lambda x, y: False)
5224
5199
5225 for abs in ctx.matches(m):
5200 for abs in ctx.matches(m):
5226 if opts.get('fullpath'):
5201 if opts.get('fullpath'):
5227 ui.write(repo.wjoin(abs), end)
5202 ui.write(repo.wjoin(abs), end)
5228 else:
5203 else:
5229 ui.write(((pats and m.rel(abs)) or abs), end)
5204 ui.write(((pats and m.rel(abs)) or abs), end)
5230 ret = 0
5205 ret = 0
5231
5206
5232 return ret
5207 return ret
5233
5208
5234 @command('^log|history',
5209 @command('^log|history',
5235 [('f', 'follow', None,
5210 [('f', 'follow', None,
5236 _('follow changeset history, or file history across copies and renames')),
5211 _('follow changeset history, or file history across copies and renames')),
5237 ('', 'follow-first', None,
5212 ('', 'follow-first', None,
5238 _('only follow the first parent of merge changesets (DEPRECATED)')),
5213 _('only follow the first parent of merge changesets (DEPRECATED)')),
5239 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5214 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5240 ('C', 'copies', None, _('show copied files')),
5215 ('C', 'copies', None, _('show copied files')),
5241 ('k', 'keyword', [],
5216 ('k', 'keyword', [],
5242 _('do case-insensitive search for a given text'), _('TEXT')),
5217 _('do case-insensitive search for a given text'), _('TEXT')),
5243 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5218 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5244 ('', 'removed', None, _('include revisions where files were removed')),
5219 ('', 'removed', None, _('include revisions where files were removed')),
5245 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5220 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5246 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5221 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5247 ('', 'only-branch', [],
5222 ('', 'only-branch', [],
5248 _('show only changesets within the given named branch (DEPRECATED)'),
5223 _('show only changesets within the given named branch (DEPRECATED)'),
5249 _('BRANCH')),
5224 _('BRANCH')),
5250 ('b', 'branch', [],
5225 ('b', 'branch', [],
5251 _('show changesets within the given named branch'), _('BRANCH')),
5226 _('show changesets within the given named branch'), _('BRANCH')),
5252 ('P', 'prune', [],
5227 ('P', 'prune', [],
5253 _('do not display revision or any of its ancestors'), _('REV')),
5228 _('do not display revision or any of its ancestors'), _('REV')),
5254 ] + logopts + walkopts,
5229 ] + logopts + walkopts,
5255 _('[OPTION]... [FILE]'),
5230 _('[OPTION]... [FILE]'),
5256 inferrepo=True)
5231 inferrepo=True)
5257 def log(ui, repo, *pats, **opts):
5232 def log(ui, repo, *pats, **opts):
5258 """show revision history of entire repository or files
5233 """show revision history of entire repository or files
5259
5234
5260 Print the revision history of the specified files or the entire
5235 Print the revision history of the specified files or the entire
5261 project.
5236 project.
5262
5237
5263 If no revision range is specified, the default is ``tip:0`` unless
5238 If no revision range is specified, the default is ``tip:0`` unless
5264 --follow is set, in which case the working directory parent is
5239 --follow is set, in which case the working directory parent is
5265 used as the starting revision.
5240 used as the starting revision.
5266
5241
5267 File history is shown without following rename or copy history of
5242 File history is shown without following rename or copy history of
5268 files. Use -f/--follow with a filename to follow history across
5243 files. Use -f/--follow with a filename to follow history across
5269 renames and copies. --follow without a filename will only show
5244 renames and copies. --follow without a filename will only show
5270 ancestors or descendants of the starting revision.
5245 ancestors or descendants of the starting revision.
5271
5246
5272 By default this command prints revision number and changeset id,
5247 By default this command prints revision number and changeset id,
5273 tags, non-trivial parents, user, date and time, and a summary for
5248 tags, non-trivial parents, user, date and time, and a summary for
5274 each commit. When the -v/--verbose switch is used, the list of
5249 each commit. When the -v/--verbose switch is used, the list of
5275 changed files and full commit message are shown.
5250 changed files and full commit message are shown.
5276
5251
5277 With --graph the revisions are shown as an ASCII art DAG with the most
5252 With --graph the revisions are shown as an ASCII art DAG with the most
5278 recent changeset at the top.
5253 recent changeset at the top.
5279 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5254 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5280 and '+' represents a fork where the changeset from the lines below is a
5255 and '+' represents a fork where the changeset from the lines below is a
5281 parent of the 'o' merge on the same line.
5256 parent of the 'o' merge on the same line.
5282
5257
5283 .. note::
5258 .. note::
5284
5259
5285 :hg:`log --patch` may generate unexpected diff output for merge
5260 :hg:`log --patch` may generate unexpected diff output for merge
5286 changesets, as it will only compare the merge changeset against
5261 changesets, as it will only compare the merge changeset against
5287 its first parent. Also, only files different from BOTH parents
5262 its first parent. Also, only files different from BOTH parents
5288 will appear in files:.
5263 will appear in files:.
5289
5264
5290 .. note::
5265 .. note::
5291
5266
5292 For performance reasons, :hg:`log FILE` may omit duplicate changes
5267 For performance reasons, :hg:`log FILE` may omit duplicate changes
5293 made on branches and will not show removals or mode changes. To
5268 made on branches and will not show removals or mode changes. To
5294 see all such changes, use the --removed switch.
5269 see all such changes, use the --removed switch.
5295
5270
5296 .. container:: verbose
5271 .. container:: verbose
5297
5272
5298 Some examples:
5273 Some examples:
5299
5274
5300 - changesets with full descriptions and file lists::
5275 - changesets with full descriptions and file lists::
5301
5276
5302 hg log -v
5277 hg log -v
5303
5278
5304 - changesets ancestral to the working directory::
5279 - changesets ancestral to the working directory::
5305
5280
5306 hg log -f
5281 hg log -f
5307
5282
5308 - last 10 commits on the current branch::
5283 - last 10 commits on the current branch::
5309
5284
5310 hg log -l 10 -b .
5285 hg log -l 10 -b .
5311
5286
5312 - changesets showing all modifications of a file, including removals::
5287 - changesets showing all modifications of a file, including removals::
5313
5288
5314 hg log --removed file.c
5289 hg log --removed file.c
5315
5290
5316 - all changesets that touch a directory, with diffs, excluding merges::
5291 - all changesets that touch a directory, with diffs, excluding merges::
5317
5292
5318 hg log -Mp lib/
5293 hg log -Mp lib/
5319
5294
5320 - all revision numbers that match a keyword::
5295 - all revision numbers that match a keyword::
5321
5296
5322 hg log -k bug --template "{rev}\\n"
5297 hg log -k bug --template "{rev}\\n"
5323
5298
5324 - the full hash identifier of the working directory parent::
5299 - the full hash identifier of the working directory parent::
5325
5300
5326 hg log -r . --template "{node}\\n"
5301 hg log -r . --template "{node}\\n"
5327
5302
5328 - list available log templates::
5303 - list available log templates::
5329
5304
5330 hg log -T list
5305 hg log -T list
5331
5306
5332 - check if a given changeset is included in a tagged release::
5307 - check if a given changeset is included in a tagged release::
5333
5308
5334 hg log -r "a21ccf and ancestor(1.9)"
5309 hg log -r "a21ccf and ancestor(1.9)"
5335
5310
5336 - find all changesets by some user in a date range::
5311 - find all changesets by some user in a date range::
5337
5312
5338 hg log -k alice -d "may 2008 to jul 2008"
5313 hg log -k alice -d "may 2008 to jul 2008"
5339
5314
5340 - summary of all changesets after the last tag::
5315 - summary of all changesets after the last tag::
5341
5316
5342 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5317 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5343
5318
5344 See :hg:`help dates` for a list of formats valid for -d/--date.
5319 See :hg:`help dates` for a list of formats valid for -d/--date.
5345
5320
5346 See :hg:`help revisions` and :hg:`help revsets` for more about
5321 See :hg:`help revisions` and :hg:`help revsets` for more about
5347 specifying and ordering revisions.
5322 specifying and ordering revisions.
5348
5323
5349 See :hg:`help templates` for more about pre-packaged styles and
5324 See :hg:`help templates` for more about pre-packaged styles and
5350 specifying custom templates.
5325 specifying custom templates.
5351
5326
5352 Returns 0 on success.
5327 Returns 0 on success.
5353
5328
5354 """
5329 """
5355 if opts.get('follow') and opts.get('rev'):
5330 if opts.get('follow') and opts.get('rev'):
5356 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5331 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5357 del opts['follow']
5332 del opts['follow']
5358
5333
5359 if opts.get('graph'):
5334 if opts.get('graph'):
5360 return cmdutil.graphlog(ui, repo, *pats, **opts)
5335 return cmdutil.graphlog(ui, repo, *pats, **opts)
5361
5336
5362 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5337 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5363 limit = cmdutil.loglimit(opts)
5338 limit = cmdutil.loglimit(opts)
5364 count = 0
5339 count = 0
5365
5340
5366 getrenamed = None
5341 getrenamed = None
5367 if opts.get('copies'):
5342 if opts.get('copies'):
5368 endrev = None
5343 endrev = None
5369 if opts.get('rev'):
5344 if opts.get('rev'):
5370 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5345 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5371 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5346 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5372
5347
5373 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5348 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5374 for rev in revs:
5349 for rev in revs:
5375 if count == limit:
5350 if count == limit:
5376 break
5351 break
5377 ctx = repo[rev]
5352 ctx = repo[rev]
5378 copies = None
5353 copies = None
5379 if getrenamed is not None and rev:
5354 if getrenamed is not None and rev:
5380 copies = []
5355 copies = []
5381 for fn in ctx.files():
5356 for fn in ctx.files():
5382 rename = getrenamed(fn, rev)
5357 rename = getrenamed(fn, rev)
5383 if rename:
5358 if rename:
5384 copies.append((fn, rename[0]))
5359 copies.append((fn, rename[0]))
5385 if filematcher:
5360 if filematcher:
5386 revmatchfn = filematcher(ctx.rev())
5361 revmatchfn = filematcher(ctx.rev())
5387 else:
5362 else:
5388 revmatchfn = None
5363 revmatchfn = None
5389 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5364 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5390 if displayer.flush(ctx):
5365 if displayer.flush(ctx):
5391 count += 1
5366 count += 1
5392
5367
5393 displayer.close()
5368 displayer.close()
5394
5369
5395 @command('manifest',
5370 @command('manifest',
5396 [('r', 'rev', '', _('revision to display'), _('REV')),
5371 [('r', 'rev', '', _('revision to display'), _('REV')),
5397 ('', 'all', False, _("list files from all revisions"))]
5372 ('', 'all', False, _("list files from all revisions"))]
5398 + formatteropts,
5373 + formatteropts,
5399 _('[-r REV]'))
5374 _('[-r REV]'))
5400 def manifest(ui, repo, node=None, rev=None, **opts):
5375 def manifest(ui, repo, node=None, rev=None, **opts):
5401 """output the current or given revision of the project manifest
5376 """output the current or given revision of the project manifest
5402
5377
5403 Print a list of version controlled files for the given revision.
5378 Print a list of version controlled files for the given revision.
5404 If no revision is given, the first parent of the working directory
5379 If no revision is given, the first parent of the working directory
5405 is used, or the null revision if no revision is checked out.
5380 is used, or the null revision if no revision is checked out.
5406
5381
5407 With -v, print file permissions, symlink and executable bits.
5382 With -v, print file permissions, symlink and executable bits.
5408 With --debug, print file revision hashes.
5383 With --debug, print file revision hashes.
5409
5384
5410 If option --all is specified, the list of all files from all revisions
5385 If option --all is specified, the list of all files from all revisions
5411 is printed. This includes deleted and renamed files.
5386 is printed. This includes deleted and renamed files.
5412
5387
5413 Returns 0 on success.
5388 Returns 0 on success.
5414 """
5389 """
5415
5390
5416 fm = ui.formatter('manifest', opts)
5391 fm = ui.formatter('manifest', opts)
5417
5392
5418 if opts.get('all'):
5393 if opts.get('all'):
5419 if rev or node:
5394 if rev or node:
5420 raise error.Abort(_("can't specify a revision with --all"))
5395 raise error.Abort(_("can't specify a revision with --all"))
5421
5396
5422 res = []
5397 res = []
5423 prefix = "data/"
5398 prefix = "data/"
5424 suffix = ".i"
5399 suffix = ".i"
5425 plen = len(prefix)
5400 plen = len(prefix)
5426 slen = len(suffix)
5401 slen = len(suffix)
5427 with repo.lock():
5402 with repo.lock():
5428 for fn, b, size in repo.store.datafiles():
5403 for fn, b, size in repo.store.datafiles():
5429 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5404 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5430 res.append(fn[plen:-slen])
5405 res.append(fn[plen:-slen])
5431 for f in res:
5406 for f in res:
5432 fm.startitem()
5407 fm.startitem()
5433 fm.write("path", '%s\n', f)
5408 fm.write("path", '%s\n', f)
5434 fm.end()
5409 fm.end()
5435 return
5410 return
5436
5411
5437 if rev and node:
5412 if rev and node:
5438 raise error.Abort(_("please specify just one revision"))
5413 raise error.Abort(_("please specify just one revision"))
5439
5414
5440 if not node:
5415 if not node:
5441 node = rev
5416 node = rev
5442
5417
5443 char = {'l': '@', 'x': '*', '': ''}
5418 char = {'l': '@', 'x': '*', '': ''}
5444 mode = {'l': '644', 'x': '755', '': '644'}
5419 mode = {'l': '644', 'x': '755', '': '644'}
5445 ctx = scmutil.revsingle(repo, node)
5420 ctx = scmutil.revsingle(repo, node)
5446 mf = ctx.manifest()
5421 mf = ctx.manifest()
5447 for f in ctx:
5422 for f in ctx:
5448 fm.startitem()
5423 fm.startitem()
5449 fl = ctx[f].flags()
5424 fl = ctx[f].flags()
5450 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5425 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5451 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5426 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5452 fm.write('path', '%s\n', f)
5427 fm.write('path', '%s\n', f)
5453 fm.end()
5428 fm.end()
5454
5429
5455 @command('^merge',
5430 @command('^merge',
5456 [('f', 'force', None,
5431 [('f', 'force', None,
5457 _('force a merge including outstanding changes (DEPRECATED)')),
5432 _('force a merge including outstanding changes (DEPRECATED)')),
5458 ('r', 'rev', '', _('revision to merge'), _('REV')),
5433 ('r', 'rev', '', _('revision to merge'), _('REV')),
5459 ('P', 'preview', None,
5434 ('P', 'preview', None,
5460 _('review revisions to merge (no merge is performed)'))
5435 _('review revisions to merge (no merge is performed)'))
5461 ] + mergetoolopts,
5436 ] + mergetoolopts,
5462 _('[-P] [[-r] REV]'))
5437 _('[-P] [[-r] REV]'))
5463 def merge(ui, repo, node=None, **opts):
5438 def merge(ui, repo, node=None, **opts):
5464 """merge another revision into working directory
5439 """merge another revision into working directory
5465
5440
5466 The current working directory is updated with all changes made in
5441 The current working directory is updated with all changes made in
5467 the requested revision since the last common predecessor revision.
5442 the requested revision since the last common predecessor revision.
5468
5443
5469 Files that changed between either parent are marked as changed for
5444 Files that changed between either parent are marked as changed for
5470 the next commit and a commit must be performed before any further
5445 the next commit and a commit must be performed before any further
5471 updates to the repository are allowed. The next commit will have
5446 updates to the repository are allowed. The next commit will have
5472 two parents.
5447 two parents.
5473
5448
5474 ``--tool`` can be used to specify the merge tool used for file
5449 ``--tool`` can be used to specify the merge tool used for file
5475 merges. It overrides the HGMERGE environment variable and your
5450 merges. It overrides the HGMERGE environment variable and your
5476 configuration files. See :hg:`help merge-tools` for options.
5451 configuration files. See :hg:`help merge-tools` for options.
5477
5452
5478 If no revision is specified, the working directory's parent is a
5453 If no revision is specified, the working directory's parent is a
5479 head revision, and the current branch contains exactly one other
5454 head revision, and the current branch contains exactly one other
5480 head, the other head is merged with by default. Otherwise, an
5455 head, the other head is merged with by default. Otherwise, an
5481 explicit revision with which to merge with must be provided.
5456 explicit revision with which to merge with must be provided.
5482
5457
5483 See :hg:`help resolve` for information on handling file conflicts.
5458 See :hg:`help resolve` for information on handling file conflicts.
5484
5459
5485 To undo an uncommitted merge, use :hg:`update --clean .` which
5460 To undo an uncommitted merge, use :hg:`update --clean .` which
5486 will check out a clean copy of the original merge parent, losing
5461 will check out a clean copy of the original merge parent, losing
5487 all changes.
5462 all changes.
5488
5463
5489 Returns 0 on success, 1 if there are unresolved files.
5464 Returns 0 on success, 1 if there are unresolved files.
5490 """
5465 """
5491
5466
5492 if opts.get('rev') and node:
5467 if opts.get('rev') and node:
5493 raise error.Abort(_("please specify just one revision"))
5468 raise error.Abort(_("please specify just one revision"))
5494 if not node:
5469 if not node:
5495 node = opts.get('rev')
5470 node = opts.get('rev')
5496
5471
5497 if node:
5472 if node:
5498 node = scmutil.revsingle(repo, node).node()
5473 node = scmutil.revsingle(repo, node).node()
5499
5474
5500 if not node:
5475 if not node:
5501 node = repo[destutil.destmerge(repo)].node()
5476 node = repo[destutil.destmerge(repo)].node()
5502
5477
5503 if opts.get('preview'):
5478 if opts.get('preview'):
5504 # find nodes that are ancestors of p2 but not of p1
5479 # find nodes that are ancestors of p2 but not of p1
5505 p1 = repo.lookup('.')
5480 p1 = repo.lookup('.')
5506 p2 = repo.lookup(node)
5481 p2 = repo.lookup(node)
5507 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5482 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5508
5483
5509 displayer = cmdutil.show_changeset(ui, repo, opts)
5484 displayer = cmdutil.show_changeset(ui, repo, opts)
5510 for node in nodes:
5485 for node in nodes:
5511 displayer.show(repo[node])
5486 displayer.show(repo[node])
5512 displayer.close()
5487 displayer.close()
5513 return 0
5488 return 0
5514
5489
5515 try:
5490 try:
5516 # ui.forcemerge is an internal variable, do not document
5491 # ui.forcemerge is an internal variable, do not document
5517 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5492 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5518 force = opts.get('force')
5493 force = opts.get('force')
5519 labels = ['working copy', 'merge rev']
5494 labels = ['working copy', 'merge rev']
5520 return hg.merge(repo, node, force=force, mergeforce=force,
5495 return hg.merge(repo, node, force=force, mergeforce=force,
5521 labels=labels)
5496 labels=labels)
5522 finally:
5497 finally:
5523 ui.setconfig('ui', 'forcemerge', '', 'merge')
5498 ui.setconfig('ui', 'forcemerge', '', 'merge')
5524
5499
5525 @command('outgoing|out',
5500 @command('outgoing|out',
5526 [('f', 'force', None, _('run even when the destination is unrelated')),
5501 [('f', 'force', None, _('run even when the destination is unrelated')),
5527 ('r', 'rev', [],
5502 ('r', 'rev', [],
5528 _('a changeset intended to be included in the destination'), _('REV')),
5503 _('a changeset intended to be included in the destination'), _('REV')),
5529 ('n', 'newest-first', None, _('show newest record first')),
5504 ('n', 'newest-first', None, _('show newest record first')),
5530 ('B', 'bookmarks', False, _('compare bookmarks')),
5505 ('B', 'bookmarks', False, _('compare bookmarks')),
5531 ('b', 'branch', [], _('a specific branch you would like to push'),
5506 ('b', 'branch', [], _('a specific branch you would like to push'),
5532 _('BRANCH')),
5507 _('BRANCH')),
5533 ] + logopts + remoteopts + subrepoopts,
5508 ] + logopts + remoteopts + subrepoopts,
5534 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5509 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5535 def outgoing(ui, repo, dest=None, **opts):
5510 def outgoing(ui, repo, dest=None, **opts):
5536 """show changesets not found in the destination
5511 """show changesets not found in the destination
5537
5512
5538 Show changesets not found in the specified destination repository
5513 Show changesets not found in the specified destination repository
5539 or the default push location. These are the changesets that would
5514 or the default push location. These are the changesets that would
5540 be pushed if a push was requested.
5515 be pushed if a push was requested.
5541
5516
5542 See pull for details of valid destination formats.
5517 See pull for details of valid destination formats.
5543
5518
5544 .. container:: verbose
5519 .. container:: verbose
5545
5520
5546 With -B/--bookmarks, the result of bookmark comparison between
5521 With -B/--bookmarks, the result of bookmark comparison between
5547 local and remote repositories is displayed. With -v/--verbose,
5522 local and remote repositories is displayed. With -v/--verbose,
5548 status is also displayed for each bookmark like below::
5523 status is also displayed for each bookmark like below::
5549
5524
5550 BM1 01234567890a added
5525 BM1 01234567890a added
5551 BM2 deleted
5526 BM2 deleted
5552 BM3 234567890abc advanced
5527 BM3 234567890abc advanced
5553 BM4 34567890abcd diverged
5528 BM4 34567890abcd diverged
5554 BM5 4567890abcde changed
5529 BM5 4567890abcde changed
5555
5530
5556 The action taken when pushing depends on the
5531 The action taken when pushing depends on the
5557 status of each bookmark:
5532 status of each bookmark:
5558
5533
5559 :``added``: push with ``-B`` will create it
5534 :``added``: push with ``-B`` will create it
5560 :``deleted``: push with ``-B`` will delete it
5535 :``deleted``: push with ``-B`` will delete it
5561 :``advanced``: push will update it
5536 :``advanced``: push will update it
5562 :``diverged``: push with ``-B`` will update it
5537 :``diverged``: push with ``-B`` will update it
5563 :``changed``: push with ``-B`` will update it
5538 :``changed``: push with ``-B`` will update it
5564
5539
5565 From the point of view of pushing behavior, bookmarks
5540 From the point of view of pushing behavior, bookmarks
5566 existing only in the remote repository are treated as
5541 existing only in the remote repository are treated as
5567 ``deleted``, even if it is in fact added remotely.
5542 ``deleted``, even if it is in fact added remotely.
5568
5543
5569 Returns 0 if there are outgoing changes, 1 otherwise.
5544 Returns 0 if there are outgoing changes, 1 otherwise.
5570 """
5545 """
5571 if opts.get('graph'):
5546 if opts.get('graph'):
5572 cmdutil.checkunsupportedgraphflags([], opts)
5547 cmdutil.checkunsupportedgraphflags([], opts)
5573 o, other = hg._outgoing(ui, repo, dest, opts)
5548 o, other = hg._outgoing(ui, repo, dest, opts)
5574 if not o:
5549 if not o:
5575 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5550 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5576 return
5551 return
5577
5552
5578 revdag = cmdutil.graphrevs(repo, o, opts)
5553 revdag = cmdutil.graphrevs(repo, o, opts)
5579 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5554 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5580 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5555 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5581 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5556 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5582 return 0
5557 return 0
5583
5558
5584 if opts.get('bookmarks'):
5559 if opts.get('bookmarks'):
5585 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5560 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5586 dest, branches = hg.parseurl(dest, opts.get('branch'))
5561 dest, branches = hg.parseurl(dest, opts.get('branch'))
5587 other = hg.peer(repo, opts, dest)
5562 other = hg.peer(repo, opts, dest)
5588 if 'bookmarks' not in other.listkeys('namespaces'):
5563 if 'bookmarks' not in other.listkeys('namespaces'):
5589 ui.warn(_("remote doesn't support bookmarks\n"))
5564 ui.warn(_("remote doesn't support bookmarks\n"))
5590 return 0
5565 return 0
5591 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5566 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5592 return bookmarks.outgoing(ui, repo, other)
5567 return bookmarks.outgoing(ui, repo, other)
5593
5568
5594 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5569 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5595 try:
5570 try:
5596 return hg.outgoing(ui, repo, dest, opts)
5571 return hg.outgoing(ui, repo, dest, opts)
5597 finally:
5572 finally:
5598 del repo._subtoppath
5573 del repo._subtoppath
5599
5574
5600 @command('parents',
5575 @command('parents',
5601 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5576 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5602 ] + templateopts,
5577 ] + templateopts,
5603 _('[-r REV] [FILE]'),
5578 _('[-r REV] [FILE]'),
5604 inferrepo=True)
5579 inferrepo=True)
5605 def parents(ui, repo, file_=None, **opts):
5580 def parents(ui, repo, file_=None, **opts):
5606 """show the parents of the working directory or revision (DEPRECATED)
5581 """show the parents of the working directory or revision (DEPRECATED)
5607
5582
5608 Print the working directory's parent revisions. If a revision is
5583 Print the working directory's parent revisions. If a revision is
5609 given via -r/--rev, the parent of that revision will be printed.
5584 given via -r/--rev, the parent of that revision will be printed.
5610 If a file argument is given, the revision in which the file was
5585 If a file argument is given, the revision in which the file was
5611 last changed (before the working directory revision or the
5586 last changed (before the working directory revision or the
5612 argument to --rev if given) is printed.
5587 argument to --rev if given) is printed.
5613
5588
5614 This command is equivalent to::
5589 This command is equivalent to::
5615
5590
5616 hg log -r "p1()+p2()" or
5591 hg log -r "p1()+p2()" or
5617 hg log -r "p1(REV)+p2(REV)" or
5592 hg log -r "p1(REV)+p2(REV)" or
5618 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5593 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5619 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5594 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5620
5595
5621 See :hg:`summary` and :hg:`help revsets` for related information.
5596 See :hg:`summary` and :hg:`help revsets` for related information.
5622
5597
5623 Returns 0 on success.
5598 Returns 0 on success.
5624 """
5599 """
5625
5600
5626 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5601 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5627
5602
5628 if file_:
5603 if file_:
5629 m = scmutil.match(ctx, (file_,), opts)
5604 m = scmutil.match(ctx, (file_,), opts)
5630 if m.anypats() or len(m.files()) != 1:
5605 if m.anypats() or len(m.files()) != 1:
5631 raise error.Abort(_('can only specify an explicit filename'))
5606 raise error.Abort(_('can only specify an explicit filename'))
5632 file_ = m.files()[0]
5607 file_ = m.files()[0]
5633 filenodes = []
5608 filenodes = []
5634 for cp in ctx.parents():
5609 for cp in ctx.parents():
5635 if not cp:
5610 if not cp:
5636 continue
5611 continue
5637 try:
5612 try:
5638 filenodes.append(cp.filenode(file_))
5613 filenodes.append(cp.filenode(file_))
5639 except error.LookupError:
5614 except error.LookupError:
5640 pass
5615 pass
5641 if not filenodes:
5616 if not filenodes:
5642 raise error.Abort(_("'%s' not found in manifest!") % file_)
5617 raise error.Abort(_("'%s' not found in manifest!") % file_)
5643 p = []
5618 p = []
5644 for fn in filenodes:
5619 for fn in filenodes:
5645 fctx = repo.filectx(file_, fileid=fn)
5620 fctx = repo.filectx(file_, fileid=fn)
5646 p.append(fctx.node())
5621 p.append(fctx.node())
5647 else:
5622 else:
5648 p = [cp.node() for cp in ctx.parents()]
5623 p = [cp.node() for cp in ctx.parents()]
5649
5624
5650 displayer = cmdutil.show_changeset(ui, repo, opts)
5625 displayer = cmdutil.show_changeset(ui, repo, opts)
5651 for n in p:
5626 for n in p:
5652 if n != nullid:
5627 if n != nullid:
5653 displayer.show(repo[n])
5628 displayer.show(repo[n])
5654 displayer.close()
5629 displayer.close()
5655
5630
5656 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5631 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5657 def paths(ui, repo, search=None, **opts):
5632 def paths(ui, repo, search=None, **opts):
5658 """show aliases for remote repositories
5633 """show aliases for remote repositories
5659
5634
5660 Show definition of symbolic path name NAME. If no name is given,
5635 Show definition of symbolic path name NAME. If no name is given,
5661 show definition of all available names.
5636 show definition of all available names.
5662
5637
5663 Option -q/--quiet suppresses all output when searching for NAME
5638 Option -q/--quiet suppresses all output when searching for NAME
5664 and shows only the path names when listing all definitions.
5639 and shows only the path names when listing all definitions.
5665
5640
5666 Path names are defined in the [paths] section of your
5641 Path names are defined in the [paths] section of your
5667 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5642 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5668 repository, ``.hg/hgrc`` is used, too.
5643 repository, ``.hg/hgrc`` is used, too.
5669
5644
5670 The path names ``default`` and ``default-push`` have a special
5645 The path names ``default`` and ``default-push`` have a special
5671 meaning. When performing a push or pull operation, they are used
5646 meaning. When performing a push or pull operation, they are used
5672 as fallbacks if no location is specified on the command-line.
5647 as fallbacks if no location is specified on the command-line.
5673 When ``default-push`` is set, it will be used for push and
5648 When ``default-push`` is set, it will be used for push and
5674 ``default`` will be used for pull; otherwise ``default`` is used
5649 ``default`` will be used for pull; otherwise ``default`` is used
5675 as the fallback for both. When cloning a repository, the clone
5650 as the fallback for both. When cloning a repository, the clone
5676 source is written as ``default`` in ``.hg/hgrc``.
5651 source is written as ``default`` in ``.hg/hgrc``.
5677
5652
5678 .. note::
5653 .. note::
5679
5654
5680 ``default`` and ``default-push`` apply to all inbound (e.g.
5655 ``default`` and ``default-push`` apply to all inbound (e.g.
5681 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5656 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5682 and :hg:`bundle`) operations.
5657 and :hg:`bundle`) operations.
5683
5658
5684 See :hg:`help urls` for more information.
5659 See :hg:`help urls` for more information.
5685
5660
5686 Returns 0 on success.
5661 Returns 0 on success.
5687 """
5662 """
5688 if search:
5663 if search:
5689 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5664 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5690 if name == search]
5665 if name == search]
5691 else:
5666 else:
5692 pathitems = sorted(ui.paths.iteritems())
5667 pathitems = sorted(ui.paths.iteritems())
5693
5668
5694 fm = ui.formatter('paths', opts)
5669 fm = ui.formatter('paths', opts)
5695 if fm.isplain():
5670 if fm.isplain():
5696 hidepassword = util.hidepassword
5671 hidepassword = util.hidepassword
5697 else:
5672 else:
5698 hidepassword = str
5673 hidepassword = str
5699 if ui.quiet:
5674 if ui.quiet:
5700 namefmt = '%s\n'
5675 namefmt = '%s\n'
5701 else:
5676 else:
5702 namefmt = '%s = '
5677 namefmt = '%s = '
5703 showsubopts = not search and not ui.quiet
5678 showsubopts = not search and not ui.quiet
5704
5679
5705 for name, path in pathitems:
5680 for name, path in pathitems:
5706 fm.startitem()
5681 fm.startitem()
5707 fm.condwrite(not search, 'name', namefmt, name)
5682 fm.condwrite(not search, 'name', namefmt, name)
5708 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5683 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5709 for subopt, value in sorted(path.suboptions.items()):
5684 for subopt, value in sorted(path.suboptions.items()):
5710 assert subopt not in ('name', 'url')
5685 assert subopt not in ('name', 'url')
5711 if showsubopts:
5686 if showsubopts:
5712 fm.plain('%s:%s = ' % (name, subopt))
5687 fm.plain('%s:%s = ' % (name, subopt))
5713 fm.condwrite(showsubopts, subopt, '%s\n', value)
5688 fm.condwrite(showsubopts, subopt, '%s\n', value)
5714
5689
5715 fm.end()
5690 fm.end()
5716
5691
5717 if search and not pathitems:
5692 if search and not pathitems:
5718 if not ui.quiet:
5693 if not ui.quiet:
5719 ui.warn(_("not found!\n"))
5694 ui.warn(_("not found!\n"))
5720 return 1
5695 return 1
5721 else:
5696 else:
5722 return 0
5697 return 0
5723
5698
5724 @command('phase',
5699 @command('phase',
5725 [('p', 'public', False, _('set changeset phase to public')),
5700 [('p', 'public', False, _('set changeset phase to public')),
5726 ('d', 'draft', False, _('set changeset phase to draft')),
5701 ('d', 'draft', False, _('set changeset phase to draft')),
5727 ('s', 'secret', False, _('set changeset phase to secret')),
5702 ('s', 'secret', False, _('set changeset phase to secret')),
5728 ('f', 'force', False, _('allow to move boundary backward')),
5703 ('f', 'force', False, _('allow to move boundary backward')),
5729 ('r', 'rev', [], _('target revision'), _('REV')),
5704 ('r', 'rev', [], _('target revision'), _('REV')),
5730 ],
5705 ],
5731 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5706 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5732 def phase(ui, repo, *revs, **opts):
5707 def phase(ui, repo, *revs, **opts):
5733 """set or show the current phase name
5708 """set or show the current phase name
5734
5709
5735 With no argument, show the phase name of the current revision(s).
5710 With no argument, show the phase name of the current revision(s).
5736
5711
5737 With one of -p/--public, -d/--draft or -s/--secret, change the
5712 With one of -p/--public, -d/--draft or -s/--secret, change the
5738 phase value of the specified revisions.
5713 phase value of the specified revisions.
5739
5714
5740 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5715 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5741 lower phase to an higher phase. Phases are ordered as follows::
5716 lower phase to an higher phase. Phases are ordered as follows::
5742
5717
5743 public < draft < secret
5718 public < draft < secret
5744
5719
5745 Returns 0 on success, 1 if some phases could not be changed.
5720 Returns 0 on success, 1 if some phases could not be changed.
5746
5721
5747 (For more information about the phases concept, see :hg:`help phases`.)
5722 (For more information about the phases concept, see :hg:`help phases`.)
5748 """
5723 """
5749 # search for a unique phase argument
5724 # search for a unique phase argument
5750 targetphase = None
5725 targetphase = None
5751 for idx, name in enumerate(phases.phasenames):
5726 for idx, name in enumerate(phases.phasenames):
5752 if opts[name]:
5727 if opts[name]:
5753 if targetphase is not None:
5728 if targetphase is not None:
5754 raise error.Abort(_('only one phase can be specified'))
5729 raise error.Abort(_('only one phase can be specified'))
5755 targetphase = idx
5730 targetphase = idx
5756
5731
5757 # look for specified revision
5732 # look for specified revision
5758 revs = list(revs)
5733 revs = list(revs)
5759 revs.extend(opts['rev'])
5734 revs.extend(opts['rev'])
5760 if not revs:
5735 if not revs:
5761 # display both parents as the second parent phase can influence
5736 # display both parents as the second parent phase can influence
5762 # the phase of a merge commit
5737 # the phase of a merge commit
5763 revs = [c.rev() for c in repo[None].parents()]
5738 revs = [c.rev() for c in repo[None].parents()]
5764
5739
5765 revs = scmutil.revrange(repo, revs)
5740 revs = scmutil.revrange(repo, revs)
5766
5741
5767 lock = None
5742 lock = None
5768 ret = 0
5743 ret = 0
5769 if targetphase is None:
5744 if targetphase is None:
5770 # display
5745 # display
5771 for r in revs:
5746 for r in revs:
5772 ctx = repo[r]
5747 ctx = repo[r]
5773 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5748 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5774 else:
5749 else:
5775 tr = None
5750 tr = None
5776 lock = repo.lock()
5751 lock = repo.lock()
5777 try:
5752 try:
5778 tr = repo.transaction("phase")
5753 tr = repo.transaction("phase")
5779 # set phase
5754 # set phase
5780 if not revs:
5755 if not revs:
5781 raise error.Abort(_('empty revision set'))
5756 raise error.Abort(_('empty revision set'))
5782 nodes = [repo[r].node() for r in revs]
5757 nodes = [repo[r].node() for r in revs]
5783 # moving revision from public to draft may hide them
5758 # moving revision from public to draft may hide them
5784 # We have to check result on an unfiltered repository
5759 # We have to check result on an unfiltered repository
5785 unfi = repo.unfiltered()
5760 unfi = repo.unfiltered()
5786 getphase = unfi._phasecache.phase
5761 getphase = unfi._phasecache.phase
5787 olddata = [getphase(unfi, r) for r in unfi]
5762 olddata = [getphase(unfi, r) for r in unfi]
5788 phases.advanceboundary(repo, tr, targetphase, nodes)
5763 phases.advanceboundary(repo, tr, targetphase, nodes)
5789 if opts['force']:
5764 if opts['force']:
5790 phases.retractboundary(repo, tr, targetphase, nodes)
5765 phases.retractboundary(repo, tr, targetphase, nodes)
5791 tr.close()
5766 tr.close()
5792 finally:
5767 finally:
5793 if tr is not None:
5768 if tr is not None:
5794 tr.release()
5769 tr.release()
5795 lock.release()
5770 lock.release()
5796 getphase = unfi._phasecache.phase
5771 getphase = unfi._phasecache.phase
5797 newdata = [getphase(unfi, r) for r in unfi]
5772 newdata = [getphase(unfi, r) for r in unfi]
5798 changes = sum(newdata[r] != olddata[r] for r in unfi)
5773 changes = sum(newdata[r] != olddata[r] for r in unfi)
5799 cl = unfi.changelog
5774 cl = unfi.changelog
5800 rejected = [n for n in nodes
5775 rejected = [n for n in nodes
5801 if newdata[cl.rev(n)] < targetphase]
5776 if newdata[cl.rev(n)] < targetphase]
5802 if rejected:
5777 if rejected:
5803 ui.warn(_('cannot move %i changesets to a higher '
5778 ui.warn(_('cannot move %i changesets to a higher '
5804 'phase, use --force\n') % len(rejected))
5779 'phase, use --force\n') % len(rejected))
5805 ret = 1
5780 ret = 1
5806 if changes:
5781 if changes:
5807 msg = _('phase changed for %i changesets\n') % changes
5782 msg = _('phase changed for %i changesets\n') % changes
5808 if ret:
5783 if ret:
5809 ui.status(msg)
5784 ui.status(msg)
5810 else:
5785 else:
5811 ui.note(msg)
5786 ui.note(msg)
5812 else:
5787 else:
5813 ui.warn(_('no phases changed\n'))
5788 ui.warn(_('no phases changed\n'))
5814 return ret
5789 return ret
5815
5790
5816 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5791 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5817 """Run after a changegroup has been added via pull/unbundle
5792 """Run after a changegroup has been added via pull/unbundle
5818
5793
5819 This takes arguments below:
5794 This takes arguments below:
5820
5795
5821 :modheads: change of heads by pull/unbundle
5796 :modheads: change of heads by pull/unbundle
5822 :optupdate: updating working directory is needed or not
5797 :optupdate: updating working directory is needed or not
5823 :checkout: update destination revision (or None to default destination)
5798 :checkout: update destination revision (or None to default destination)
5824 :brev: a name, which might be a bookmark to be activated after updating
5799 :brev: a name, which might be a bookmark to be activated after updating
5825 """
5800 """
5826 if modheads == 0:
5801 if modheads == 0:
5827 return
5802 return
5828 if optupdate:
5803 if optupdate:
5829 try:
5804 try:
5830 return hg.updatetotally(ui, repo, checkout, brev)
5805 return hg.updatetotally(ui, repo, checkout, brev)
5831 except error.UpdateAbort as inst:
5806 except error.UpdateAbort as inst:
5832 msg = _("not updating: %s") % str(inst)
5807 msg = _("not updating: %s") % str(inst)
5833 hint = inst.hint
5808 hint = inst.hint
5834 raise error.UpdateAbort(msg, hint=hint)
5809 raise error.UpdateAbort(msg, hint=hint)
5835 if modheads > 1:
5810 if modheads > 1:
5836 currentbranchheads = len(repo.branchheads())
5811 currentbranchheads = len(repo.branchheads())
5837 if currentbranchheads == modheads:
5812 if currentbranchheads == modheads:
5838 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5813 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5839 elif currentbranchheads > 1:
5814 elif currentbranchheads > 1:
5840 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5815 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5841 "merge)\n"))
5816 "merge)\n"))
5842 else:
5817 else:
5843 ui.status(_("(run 'hg heads' to see heads)\n"))
5818 ui.status(_("(run 'hg heads' to see heads)\n"))
5844 else:
5819 else:
5845 ui.status(_("(run 'hg update' to get a working copy)\n"))
5820 ui.status(_("(run 'hg update' to get a working copy)\n"))
5846
5821
5847 @command('^pull',
5822 @command('^pull',
5848 [('u', 'update', None,
5823 [('u', 'update', None,
5849 _('update to new branch head if changesets were pulled')),
5824 _('update to new branch head if changesets were pulled')),
5850 ('f', 'force', None, _('run even when remote repository is unrelated')),
5825 ('f', 'force', None, _('run even when remote repository is unrelated')),
5851 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5826 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5852 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5827 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5853 ('b', 'branch', [], _('a specific branch you would like to pull'),
5828 ('b', 'branch', [], _('a specific branch you would like to pull'),
5854 _('BRANCH')),
5829 _('BRANCH')),
5855 ] + remoteopts,
5830 ] + remoteopts,
5856 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5831 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5857 def pull(ui, repo, source="default", **opts):
5832 def pull(ui, repo, source="default", **opts):
5858 """pull changes from the specified source
5833 """pull changes from the specified source
5859
5834
5860 Pull changes from a remote repository to a local one.
5835 Pull changes from a remote repository to a local one.
5861
5836
5862 This finds all changes from the repository at the specified path
5837 This finds all changes from the repository at the specified path
5863 or URL and adds them to a local repository (the current one unless
5838 or URL and adds them to a local repository (the current one unless
5864 -R is specified). By default, this does not update the copy of the
5839 -R is specified). By default, this does not update the copy of the
5865 project in the working directory.
5840 project in the working directory.
5866
5841
5867 Use :hg:`incoming` if you want to see what would have been added
5842 Use :hg:`incoming` if you want to see what would have been added
5868 by a pull at the time you issued this command. If you then decide
5843 by a pull at the time you issued this command. If you then decide
5869 to add those changes to the repository, you should use :hg:`pull
5844 to add those changes to the repository, you should use :hg:`pull
5870 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5845 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5871
5846
5872 If SOURCE is omitted, the 'default' path will be used.
5847 If SOURCE is omitted, the 'default' path will be used.
5873 See :hg:`help urls` for more information.
5848 See :hg:`help urls` for more information.
5874
5849
5875 Specifying bookmark as ``.`` is equivalent to specifying the active
5850 Specifying bookmark as ``.`` is equivalent to specifying the active
5876 bookmark's name.
5851 bookmark's name.
5877
5852
5878 Returns 0 on success, 1 if an update had unresolved files.
5853 Returns 0 on success, 1 if an update had unresolved files.
5879 """
5854 """
5880 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5855 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5881 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5856 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5882 other = hg.peer(repo, opts, source)
5857 other = hg.peer(repo, opts, source)
5883 try:
5858 try:
5884 revs, checkout = hg.addbranchrevs(repo, other, branches,
5859 revs, checkout = hg.addbranchrevs(repo, other, branches,
5885 opts.get('rev'))
5860 opts.get('rev'))
5886
5861
5887
5862
5888 pullopargs = {}
5863 pullopargs = {}
5889 if opts.get('bookmark'):
5864 if opts.get('bookmark'):
5890 if not revs:
5865 if not revs:
5891 revs = []
5866 revs = []
5892 # The list of bookmark used here is not the one used to actually
5867 # The list of bookmark used here is not the one used to actually
5893 # update the bookmark name. This can result in the revision pulled
5868 # update the bookmark name. This can result in the revision pulled
5894 # not ending up with the name of the bookmark because of a race
5869 # not ending up with the name of the bookmark because of a race
5895 # condition on the server. (See issue 4689 for details)
5870 # condition on the server. (See issue 4689 for details)
5896 remotebookmarks = other.listkeys('bookmarks')
5871 remotebookmarks = other.listkeys('bookmarks')
5897 pullopargs['remotebookmarks'] = remotebookmarks
5872 pullopargs['remotebookmarks'] = remotebookmarks
5898 for b in opts['bookmark']:
5873 for b in opts['bookmark']:
5899 b = repo._bookmarks.expandname(b)
5874 b = repo._bookmarks.expandname(b)
5900 if b not in remotebookmarks:
5875 if b not in remotebookmarks:
5901 raise error.Abort(_('remote bookmark %s not found!') % b)
5876 raise error.Abort(_('remote bookmark %s not found!') % b)
5902 revs.append(remotebookmarks[b])
5877 revs.append(remotebookmarks[b])
5903
5878
5904 if revs:
5879 if revs:
5905 try:
5880 try:
5906 # When 'rev' is a bookmark name, we cannot guarantee that it
5881 # When 'rev' is a bookmark name, we cannot guarantee that it
5907 # will be updated with that name because of a race condition
5882 # will be updated with that name because of a race condition
5908 # server side. (See issue 4689 for details)
5883 # server side. (See issue 4689 for details)
5909 oldrevs = revs
5884 oldrevs = revs
5910 revs = [] # actually, nodes
5885 revs = [] # actually, nodes
5911 for r in oldrevs:
5886 for r in oldrevs:
5912 node = other.lookup(r)
5887 node = other.lookup(r)
5913 revs.append(node)
5888 revs.append(node)
5914 if r == checkout:
5889 if r == checkout:
5915 checkout = node
5890 checkout = node
5916 except error.CapabilityError:
5891 except error.CapabilityError:
5917 err = _("other repository doesn't support revision lookup, "
5892 err = _("other repository doesn't support revision lookup, "
5918 "so a rev cannot be specified.")
5893 "so a rev cannot be specified.")
5919 raise error.Abort(err)
5894 raise error.Abort(err)
5920
5895
5921 pullopargs.update(opts.get('opargs', {}))
5896 pullopargs.update(opts.get('opargs', {}))
5922 modheads = exchange.pull(repo, other, heads=revs,
5897 modheads = exchange.pull(repo, other, heads=revs,
5923 force=opts.get('force'),
5898 force=opts.get('force'),
5924 bookmarks=opts.get('bookmark', ()),
5899 bookmarks=opts.get('bookmark', ()),
5925 opargs=pullopargs).cgresult
5900 opargs=pullopargs).cgresult
5926
5901
5927 # brev is a name, which might be a bookmark to be activated at
5902 # brev is a name, which might be a bookmark to be activated at
5928 # the end of the update. In other words, it is an explicit
5903 # the end of the update. In other words, it is an explicit
5929 # destination of the update
5904 # destination of the update
5930 brev = None
5905 brev = None
5931
5906
5932 if checkout:
5907 if checkout:
5933 checkout = str(repo.changelog.rev(checkout))
5908 checkout = str(repo.changelog.rev(checkout))
5934
5909
5935 # order below depends on implementation of
5910 # order below depends on implementation of
5936 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5911 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5937 # because 'checkout' is determined without it.
5912 # because 'checkout' is determined without it.
5938 if opts.get('rev'):
5913 if opts.get('rev'):
5939 brev = opts['rev'][0]
5914 brev = opts['rev'][0]
5940 elif opts.get('branch'):
5915 elif opts.get('branch'):
5941 brev = opts['branch'][0]
5916 brev = opts['branch'][0]
5942 else:
5917 else:
5943 brev = branches[0]
5918 brev = branches[0]
5944 repo._subtoppath = source
5919 repo._subtoppath = source
5945 try:
5920 try:
5946 ret = postincoming(ui, repo, modheads, opts.get('update'),
5921 ret = postincoming(ui, repo, modheads, opts.get('update'),
5947 checkout, brev)
5922 checkout, brev)
5948
5923
5949 finally:
5924 finally:
5950 del repo._subtoppath
5925 del repo._subtoppath
5951
5926
5952 finally:
5927 finally:
5953 other.close()
5928 other.close()
5954 return ret
5929 return ret
5955
5930
5956 @command('^push',
5931 @command('^push',
5957 [('f', 'force', None, _('force push')),
5932 [('f', 'force', None, _('force push')),
5958 ('r', 'rev', [],
5933 ('r', 'rev', [],
5959 _('a changeset intended to be included in the destination'),
5934 _('a changeset intended to be included in the destination'),
5960 _('REV')),
5935 _('REV')),
5961 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5936 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5962 ('b', 'branch', [],
5937 ('b', 'branch', [],
5963 _('a specific branch you would like to push'), _('BRANCH')),
5938 _('a specific branch you would like to push'), _('BRANCH')),
5964 ('', 'new-branch', False, _('allow pushing a new branch')),
5939 ('', 'new-branch', False, _('allow pushing a new branch')),
5965 ] + remoteopts,
5940 ] + remoteopts,
5966 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5941 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5967 def push(ui, repo, dest=None, **opts):
5942 def push(ui, repo, dest=None, **opts):
5968 """push changes to the specified destination
5943 """push changes to the specified destination
5969
5944
5970 Push changesets from the local repository to the specified
5945 Push changesets from the local repository to the specified
5971 destination.
5946 destination.
5972
5947
5973 This operation is symmetrical to pull: it is identical to a pull
5948 This operation is symmetrical to pull: it is identical to a pull
5974 in the destination repository from the current one.
5949 in the destination repository from the current one.
5975
5950
5976 By default, push will not allow creation of new heads at the
5951 By default, push will not allow creation of new heads at the
5977 destination, since multiple heads would make it unclear which head
5952 destination, since multiple heads would make it unclear which head
5978 to use. In this situation, it is recommended to pull and merge
5953 to use. In this situation, it is recommended to pull and merge
5979 before pushing.
5954 before pushing.
5980
5955
5981 Use --new-branch if you want to allow push to create a new named
5956 Use --new-branch if you want to allow push to create a new named
5982 branch that is not present at the destination. This allows you to
5957 branch that is not present at the destination. This allows you to
5983 only create a new branch without forcing other changes.
5958 only create a new branch without forcing other changes.
5984
5959
5985 .. note::
5960 .. note::
5986
5961
5987 Extra care should be taken with the -f/--force option,
5962 Extra care should be taken with the -f/--force option,
5988 which will push all new heads on all branches, an action which will
5963 which will push all new heads on all branches, an action which will
5989 almost always cause confusion for collaborators.
5964 almost always cause confusion for collaborators.
5990
5965
5991 If -r/--rev is used, the specified revision and all its ancestors
5966 If -r/--rev is used, the specified revision and all its ancestors
5992 will be pushed to the remote repository.
5967 will be pushed to the remote repository.
5993
5968
5994 If -B/--bookmark is used, the specified bookmarked revision, its
5969 If -B/--bookmark is used, the specified bookmarked revision, its
5995 ancestors, and the bookmark will be pushed to the remote
5970 ancestors, and the bookmark will be pushed to the remote
5996 repository. Specifying ``.`` is equivalent to specifying the active
5971 repository. Specifying ``.`` is equivalent to specifying the active
5997 bookmark's name.
5972 bookmark's name.
5998
5973
5999 Please see :hg:`help urls` for important details about ``ssh://``
5974 Please see :hg:`help urls` for important details about ``ssh://``
6000 URLs. If DESTINATION is omitted, a default path will be used.
5975 URLs. If DESTINATION is omitted, a default path will be used.
6001
5976
6002 Returns 0 if push was successful, 1 if nothing to push.
5977 Returns 0 if push was successful, 1 if nothing to push.
6003 """
5978 """
6004
5979
6005 if opts.get('bookmark'):
5980 if opts.get('bookmark'):
6006 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5981 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
6007 for b in opts['bookmark']:
5982 for b in opts['bookmark']:
6008 # translate -B options to -r so changesets get pushed
5983 # translate -B options to -r so changesets get pushed
6009 b = repo._bookmarks.expandname(b)
5984 b = repo._bookmarks.expandname(b)
6010 if b in repo._bookmarks:
5985 if b in repo._bookmarks:
6011 opts.setdefault('rev', []).append(b)
5986 opts.setdefault('rev', []).append(b)
6012 else:
5987 else:
6013 # if we try to push a deleted bookmark, translate it to null
5988 # if we try to push a deleted bookmark, translate it to null
6014 # this lets simultaneous -r, -b options continue working
5989 # this lets simultaneous -r, -b options continue working
6015 opts.setdefault('rev', []).append("null")
5990 opts.setdefault('rev', []).append("null")
6016
5991
6017 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5992 path = ui.paths.getpath(dest, default=('default-push', 'default'))
6018 if not path:
5993 if not path:
6019 raise error.Abort(_('default repository not configured!'),
5994 raise error.Abort(_('default repository not configured!'),
6020 hint=_("see 'hg help config.paths'"))
5995 hint=_("see 'hg help config.paths'"))
6021 dest = path.pushloc or path.loc
5996 dest = path.pushloc or path.loc
6022 branches = (path.branch, opts.get('branch') or [])
5997 branches = (path.branch, opts.get('branch') or [])
6023 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5998 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
6024 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5999 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
6025 other = hg.peer(repo, opts, dest)
6000 other = hg.peer(repo, opts, dest)
6026
6001
6027 if revs:
6002 if revs:
6028 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
6003 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
6029 if not revs:
6004 if not revs:
6030 raise error.Abort(_("specified revisions evaluate to an empty set"),
6005 raise error.Abort(_("specified revisions evaluate to an empty set"),
6031 hint=_("use different revision arguments"))
6006 hint=_("use different revision arguments"))
6032 elif path.pushrev:
6007 elif path.pushrev:
6033 # It doesn't make any sense to specify ancestor revisions. So limit
6008 # It doesn't make any sense to specify ancestor revisions. So limit
6034 # to DAG heads to make discovery simpler.
6009 # to DAG heads to make discovery simpler.
6035 expr = revset.formatspec('heads(%r)', path.pushrev)
6010 expr = revset.formatspec('heads(%r)', path.pushrev)
6036 revs = scmutil.revrange(repo, [expr])
6011 revs = scmutil.revrange(repo, [expr])
6037 revs = [repo[rev].node() for rev in revs]
6012 revs = [repo[rev].node() for rev in revs]
6038 if not revs:
6013 if not revs:
6039 raise error.Abort(_('default push revset for path evaluates to an '
6014 raise error.Abort(_('default push revset for path evaluates to an '
6040 'empty set'))
6015 'empty set'))
6041
6016
6042 repo._subtoppath = dest
6017 repo._subtoppath = dest
6043 try:
6018 try:
6044 # push subrepos depth-first for coherent ordering
6019 # push subrepos depth-first for coherent ordering
6045 c = repo['']
6020 c = repo['']
6046 subs = c.substate # only repos that are committed
6021 subs = c.substate # only repos that are committed
6047 for s in sorted(subs):
6022 for s in sorted(subs):
6048 result = c.sub(s).push(opts)
6023 result = c.sub(s).push(opts)
6049 if result == 0:
6024 if result == 0:
6050 return not result
6025 return not result
6051 finally:
6026 finally:
6052 del repo._subtoppath
6027 del repo._subtoppath
6053 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
6028 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
6054 newbranch=opts.get('new_branch'),
6029 newbranch=opts.get('new_branch'),
6055 bookmarks=opts.get('bookmark', ()),
6030 bookmarks=opts.get('bookmark', ()),
6056 opargs=opts.get('opargs'))
6031 opargs=opts.get('opargs'))
6057
6032
6058 result = not pushop.cgresult
6033 result = not pushop.cgresult
6059
6034
6060 if pushop.bkresult is not None:
6035 if pushop.bkresult is not None:
6061 if pushop.bkresult == 2:
6036 if pushop.bkresult == 2:
6062 result = 2
6037 result = 2
6063 elif not result and pushop.bkresult:
6038 elif not result and pushop.bkresult:
6064 result = 2
6039 result = 2
6065
6040
6066 return result
6041 return result
6067
6042
6068 @command('recover', [])
6043 @command('recover', [])
6069 def recover(ui, repo):
6044 def recover(ui, repo):
6070 """roll back an interrupted transaction
6045 """roll back an interrupted transaction
6071
6046
6072 Recover from an interrupted commit or pull.
6047 Recover from an interrupted commit or pull.
6073
6048
6074 This command tries to fix the repository status after an
6049 This command tries to fix the repository status after an
6075 interrupted operation. It should only be necessary when Mercurial
6050 interrupted operation. It should only be necessary when Mercurial
6076 suggests it.
6051 suggests it.
6077
6052
6078 Returns 0 if successful, 1 if nothing to recover or verify fails.
6053 Returns 0 if successful, 1 if nothing to recover or verify fails.
6079 """
6054 """
6080 if repo.recover():
6055 if repo.recover():
6081 return hg.verify(repo)
6056 return hg.verify(repo)
6082 return 1
6057 return 1
6083
6058
6084 @command('^remove|rm',
6059 @command('^remove|rm',
6085 [('A', 'after', None, _('record delete for missing files')),
6060 [('A', 'after', None, _('record delete for missing files')),
6086 ('f', 'force', None,
6061 ('f', 'force', None,
6087 _('forget added files, delete modified files')),
6062 _('forget added files, delete modified files')),
6088 ] + subrepoopts + walkopts,
6063 ] + subrepoopts + walkopts,
6089 _('[OPTION]... FILE...'),
6064 _('[OPTION]... FILE...'),
6090 inferrepo=True)
6065 inferrepo=True)
6091 def remove(ui, repo, *pats, **opts):
6066 def remove(ui, repo, *pats, **opts):
6092 """remove the specified files on the next commit
6067 """remove the specified files on the next commit
6093
6068
6094 Schedule the indicated files for removal from the current branch.
6069 Schedule the indicated files for removal from the current branch.
6095
6070
6096 This command schedules the files to be removed at the next commit.
6071 This command schedules the files to be removed at the next commit.
6097 To undo a remove before that, see :hg:`revert`. To undo added
6072 To undo a remove before that, see :hg:`revert`. To undo added
6098 files, see :hg:`forget`.
6073 files, see :hg:`forget`.
6099
6074
6100 .. container:: verbose
6075 .. container:: verbose
6101
6076
6102 -A/--after can be used to remove only files that have already
6077 -A/--after can be used to remove only files that have already
6103 been deleted, -f/--force can be used to force deletion, and -Af
6078 been deleted, -f/--force can be used to force deletion, and -Af
6104 can be used to remove files from the next revision without
6079 can be used to remove files from the next revision without
6105 deleting them from the working directory.
6080 deleting them from the working directory.
6106
6081
6107 The following table details the behavior of remove for different
6082 The following table details the behavior of remove for different
6108 file states (columns) and option combinations (rows). The file
6083 file states (columns) and option combinations (rows). The file
6109 states are Added [A], Clean [C], Modified [M] and Missing [!]
6084 states are Added [A], Clean [C], Modified [M] and Missing [!]
6110 (as reported by :hg:`status`). The actions are Warn, Remove
6085 (as reported by :hg:`status`). The actions are Warn, Remove
6111 (from branch) and Delete (from disk):
6086 (from branch) and Delete (from disk):
6112
6087
6113 ========= == == == ==
6088 ========= == == == ==
6114 opt/state A C M !
6089 opt/state A C M !
6115 ========= == == == ==
6090 ========= == == == ==
6116 none W RD W R
6091 none W RD W R
6117 -f R RD RD R
6092 -f R RD RD R
6118 -A W W W R
6093 -A W W W R
6119 -Af R R R R
6094 -Af R R R R
6120 ========= == == == ==
6095 ========= == == == ==
6121
6096
6122 .. note::
6097 .. note::
6123
6098
6124 :hg:`remove` never deletes files in Added [A] state from the
6099 :hg:`remove` never deletes files in Added [A] state from the
6125 working directory, not even if ``--force`` is specified.
6100 working directory, not even if ``--force`` is specified.
6126
6101
6127 Returns 0 on success, 1 if any warnings encountered.
6102 Returns 0 on success, 1 if any warnings encountered.
6128 """
6103 """
6129
6104
6130 after, force = opts.get('after'), opts.get('force')
6105 after, force = opts.get('after'), opts.get('force')
6131 if not pats and not after:
6106 if not pats and not after:
6132 raise error.Abort(_('no files specified'))
6107 raise error.Abort(_('no files specified'))
6133
6108
6134 m = scmutil.match(repo[None], pats, opts)
6109 m = scmutil.match(repo[None], pats, opts)
6135 subrepos = opts.get('subrepos')
6110 subrepos = opts.get('subrepos')
6136 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6111 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
6137
6112
6138 @command('rename|move|mv',
6113 @command('rename|move|mv',
6139 [('A', 'after', None, _('record a rename that has already occurred')),
6114 [('A', 'after', None, _('record a rename that has already occurred')),
6140 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6115 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6141 ] + walkopts + dryrunopts,
6116 ] + walkopts + dryrunopts,
6142 _('[OPTION]... SOURCE... DEST'))
6117 _('[OPTION]... SOURCE... DEST'))
6143 def rename(ui, repo, *pats, **opts):
6118 def rename(ui, repo, *pats, **opts):
6144 """rename files; equivalent of copy + remove
6119 """rename files; equivalent of copy + remove
6145
6120
6146 Mark dest as copies of sources; mark sources for deletion. If dest
6121 Mark dest as copies of sources; mark sources for deletion. If dest
6147 is a directory, copies are put in that directory. If dest is a
6122 is a directory, copies are put in that directory. If dest is a
6148 file, there can only be one source.
6123 file, there can only be one source.
6149
6124
6150 By default, this command copies the contents of files as they
6125 By default, this command copies the contents of files as they
6151 exist in the working directory. If invoked with -A/--after, the
6126 exist in the working directory. If invoked with -A/--after, the
6152 operation is recorded, but no copying is performed.
6127 operation is recorded, but no copying is performed.
6153
6128
6154 This command takes effect at the next commit. To undo a rename
6129 This command takes effect at the next commit. To undo a rename
6155 before that, see :hg:`revert`.
6130 before that, see :hg:`revert`.
6156
6131
6157 Returns 0 on success, 1 if errors are encountered.
6132 Returns 0 on success, 1 if errors are encountered.
6158 """
6133 """
6159 with repo.wlock(False):
6134 with repo.wlock(False):
6160 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6135 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6161
6136
6162 @command('resolve',
6137 @command('resolve',
6163 [('a', 'all', None, _('select all unresolved files')),
6138 [('a', 'all', None, _('select all unresolved files')),
6164 ('l', 'list', None, _('list state of files needing merge')),
6139 ('l', 'list', None, _('list state of files needing merge')),
6165 ('m', 'mark', None, _('mark files as resolved')),
6140 ('m', 'mark', None, _('mark files as resolved')),
6166 ('u', 'unmark', None, _('mark files as unresolved')),
6141 ('u', 'unmark', None, _('mark files as unresolved')),
6167 ('n', 'no-status', None, _('hide status prefix'))]
6142 ('n', 'no-status', None, _('hide status prefix'))]
6168 + mergetoolopts + walkopts + formatteropts,
6143 + mergetoolopts + walkopts + formatteropts,
6169 _('[OPTION]... [FILE]...'),
6144 _('[OPTION]... [FILE]...'),
6170 inferrepo=True)
6145 inferrepo=True)
6171 def resolve(ui, repo, *pats, **opts):
6146 def resolve(ui, repo, *pats, **opts):
6172 """redo merges or set/view the merge status of files
6147 """redo merges or set/view the merge status of files
6173
6148
6174 Merges with unresolved conflicts are often the result of
6149 Merges with unresolved conflicts are often the result of
6175 non-interactive merging using the ``internal:merge`` configuration
6150 non-interactive merging using the ``internal:merge`` configuration
6176 setting, or a command-line merge tool like ``diff3``. The resolve
6151 setting, or a command-line merge tool like ``diff3``. The resolve
6177 command is used to manage the files involved in a merge, after
6152 command is used to manage the files involved in a merge, after
6178 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6153 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6179 working directory must have two parents). See :hg:`help
6154 working directory must have two parents). See :hg:`help
6180 merge-tools` for information on configuring merge tools.
6155 merge-tools` for information on configuring merge tools.
6181
6156
6182 The resolve command can be used in the following ways:
6157 The resolve command can be used in the following ways:
6183
6158
6184 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6159 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6185 files, discarding any previous merge attempts. Re-merging is not
6160 files, discarding any previous merge attempts. Re-merging is not
6186 performed for files already marked as resolved. Use ``--all/-a``
6161 performed for files already marked as resolved. Use ``--all/-a``
6187 to select all unresolved files. ``--tool`` can be used to specify
6162 to select all unresolved files. ``--tool`` can be used to specify
6188 the merge tool used for the given files. It overrides the HGMERGE
6163 the merge tool used for the given files. It overrides the HGMERGE
6189 environment variable and your configuration files. Previous file
6164 environment variable and your configuration files. Previous file
6190 contents are saved with a ``.orig`` suffix.
6165 contents are saved with a ``.orig`` suffix.
6191
6166
6192 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6167 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6193 (e.g. after having manually fixed-up the files). The default is
6168 (e.g. after having manually fixed-up the files). The default is
6194 to mark all unresolved files.
6169 to mark all unresolved files.
6195
6170
6196 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6171 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6197 default is to mark all resolved files.
6172 default is to mark all resolved files.
6198
6173
6199 - :hg:`resolve -l`: list files which had or still have conflicts.
6174 - :hg:`resolve -l`: list files which had or still have conflicts.
6200 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6175 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6201
6176
6202 .. note::
6177 .. note::
6203
6178
6204 Mercurial will not let you commit files with unresolved merge
6179 Mercurial will not let you commit files with unresolved merge
6205 conflicts. You must use :hg:`resolve -m ...` before you can
6180 conflicts. You must use :hg:`resolve -m ...` before you can
6206 commit after a conflicting merge.
6181 commit after a conflicting merge.
6207
6182
6208 Returns 0 on success, 1 if any files fail a resolve attempt.
6183 Returns 0 on success, 1 if any files fail a resolve attempt.
6209 """
6184 """
6210
6185
6211 flaglist = 'all mark unmark list no_status'.split()
6186 flaglist = 'all mark unmark list no_status'.split()
6212 all, mark, unmark, show, nostatus = \
6187 all, mark, unmark, show, nostatus = \
6213 [opts.get(o) for o in flaglist]
6188 [opts.get(o) for o in flaglist]
6214
6189
6215 if (show and (mark or unmark)) or (mark and unmark):
6190 if (show and (mark or unmark)) or (mark and unmark):
6216 raise error.Abort(_("too many options specified"))
6191 raise error.Abort(_("too many options specified"))
6217 if pats and all:
6192 if pats and all:
6218 raise error.Abort(_("can't specify --all and patterns"))
6193 raise error.Abort(_("can't specify --all and patterns"))
6219 if not (all or pats or show or mark or unmark):
6194 if not (all or pats or show or mark or unmark):
6220 raise error.Abort(_('no files or directories specified'),
6195 raise error.Abort(_('no files or directories specified'),
6221 hint=('use --all to re-merge all unresolved files'))
6196 hint=('use --all to re-merge all unresolved files'))
6222
6197
6223 if show:
6198 if show:
6224 fm = ui.formatter('resolve', opts)
6199 fm = ui.formatter('resolve', opts)
6225 ms = mergemod.mergestate.read(repo)
6200 ms = mergemod.mergestate.read(repo)
6226 m = scmutil.match(repo[None], pats, opts)
6201 m = scmutil.match(repo[None], pats, opts)
6227 for f in ms:
6202 for f in ms:
6228 if not m(f):
6203 if not m(f):
6229 continue
6204 continue
6230 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6205 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6231 'd': 'driverresolved'}[ms[f]]
6206 'd': 'driverresolved'}[ms[f]]
6232 fm.startitem()
6207 fm.startitem()
6233 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6208 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6234 fm.write('path', '%s\n', f, label=l)
6209 fm.write('path', '%s\n', f, label=l)
6235 fm.end()
6210 fm.end()
6236 return 0
6211 return 0
6237
6212
6238 with repo.wlock():
6213 with repo.wlock():
6239 ms = mergemod.mergestate.read(repo)
6214 ms = mergemod.mergestate.read(repo)
6240
6215
6241 if not (ms.active() or repo.dirstate.p2() != nullid):
6216 if not (ms.active() or repo.dirstate.p2() != nullid):
6242 raise error.Abort(
6217 raise error.Abort(
6243 _('resolve command not applicable when not merging'))
6218 _('resolve command not applicable when not merging'))
6244
6219
6245 wctx = repo[None]
6220 wctx = repo[None]
6246
6221
6247 if ms.mergedriver and ms.mdstate() == 'u':
6222 if ms.mergedriver and ms.mdstate() == 'u':
6248 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6223 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6249 ms.commit()
6224 ms.commit()
6250 # allow mark and unmark to go through
6225 # allow mark and unmark to go through
6251 if not mark and not unmark and not proceed:
6226 if not mark and not unmark and not proceed:
6252 return 1
6227 return 1
6253
6228
6254 m = scmutil.match(wctx, pats, opts)
6229 m = scmutil.match(wctx, pats, opts)
6255 ret = 0
6230 ret = 0
6256 didwork = False
6231 didwork = False
6257 runconclude = False
6232 runconclude = False
6258
6233
6259 tocomplete = []
6234 tocomplete = []
6260 for f in ms:
6235 for f in ms:
6261 if not m(f):
6236 if not m(f):
6262 continue
6237 continue
6263
6238
6264 didwork = True
6239 didwork = True
6265
6240
6266 # don't let driver-resolved files be marked, and run the conclude
6241 # don't let driver-resolved files be marked, and run the conclude
6267 # step if asked to resolve
6242 # step if asked to resolve
6268 if ms[f] == "d":
6243 if ms[f] == "d":
6269 exact = m.exact(f)
6244 exact = m.exact(f)
6270 if mark:
6245 if mark:
6271 if exact:
6246 if exact:
6272 ui.warn(_('not marking %s as it is driver-resolved\n')
6247 ui.warn(_('not marking %s as it is driver-resolved\n')
6273 % f)
6248 % f)
6274 elif unmark:
6249 elif unmark:
6275 if exact:
6250 if exact:
6276 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6251 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6277 % f)
6252 % f)
6278 else:
6253 else:
6279 runconclude = True
6254 runconclude = True
6280 continue
6255 continue
6281
6256
6282 if mark:
6257 if mark:
6283 ms.mark(f, "r")
6258 ms.mark(f, "r")
6284 elif unmark:
6259 elif unmark:
6285 ms.mark(f, "u")
6260 ms.mark(f, "u")
6286 else:
6261 else:
6287 # backup pre-resolve (merge uses .orig for its own purposes)
6262 # backup pre-resolve (merge uses .orig for its own purposes)
6288 a = repo.wjoin(f)
6263 a = repo.wjoin(f)
6289 try:
6264 try:
6290 util.copyfile(a, a + ".resolve")
6265 util.copyfile(a, a + ".resolve")
6291 except (IOError, OSError) as inst:
6266 except (IOError, OSError) as inst:
6292 if inst.errno != errno.ENOENT:
6267 if inst.errno != errno.ENOENT:
6293 raise
6268 raise
6294
6269
6295 try:
6270 try:
6296 # preresolve file
6271 # preresolve file
6297 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6272 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6298 'resolve')
6273 'resolve')
6299 complete, r = ms.preresolve(f, wctx)
6274 complete, r = ms.preresolve(f, wctx)
6300 if not complete:
6275 if not complete:
6301 tocomplete.append(f)
6276 tocomplete.append(f)
6302 elif r:
6277 elif r:
6303 ret = 1
6278 ret = 1
6304 finally:
6279 finally:
6305 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6280 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6306 ms.commit()
6281 ms.commit()
6307
6282
6308 # replace filemerge's .orig file with our resolve file, but only
6283 # replace filemerge's .orig file with our resolve file, but only
6309 # for merges that are complete
6284 # for merges that are complete
6310 if complete:
6285 if complete:
6311 try:
6286 try:
6312 util.rename(a + ".resolve",
6287 util.rename(a + ".resolve",
6313 scmutil.origpath(ui, repo, a))
6288 scmutil.origpath(ui, repo, a))
6314 except OSError as inst:
6289 except OSError as inst:
6315 if inst.errno != errno.ENOENT:
6290 if inst.errno != errno.ENOENT:
6316 raise
6291 raise
6317
6292
6318 for f in tocomplete:
6293 for f in tocomplete:
6319 try:
6294 try:
6320 # resolve file
6295 # resolve file
6321 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6296 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6322 'resolve')
6297 'resolve')
6323 r = ms.resolve(f, wctx)
6298 r = ms.resolve(f, wctx)
6324 if r:
6299 if r:
6325 ret = 1
6300 ret = 1
6326 finally:
6301 finally:
6327 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6302 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6328 ms.commit()
6303 ms.commit()
6329
6304
6330 # replace filemerge's .orig file with our resolve file
6305 # replace filemerge's .orig file with our resolve file
6331 a = repo.wjoin(f)
6306 a = repo.wjoin(f)
6332 try:
6307 try:
6333 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6308 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6334 except OSError as inst:
6309 except OSError as inst:
6335 if inst.errno != errno.ENOENT:
6310 if inst.errno != errno.ENOENT:
6336 raise
6311 raise
6337
6312
6338 ms.commit()
6313 ms.commit()
6339 ms.recordactions()
6314 ms.recordactions()
6340
6315
6341 if not didwork and pats:
6316 if not didwork and pats:
6342 hint = None
6317 hint = None
6343 if not any([p for p in pats if p.find(':') >= 0]):
6318 if not any([p for p in pats if p.find(':') >= 0]):
6344 pats = ['path:%s' % p for p in pats]
6319 pats = ['path:%s' % p for p in pats]
6345 m = scmutil.match(wctx, pats, opts)
6320 m = scmutil.match(wctx, pats, opts)
6346 for f in ms:
6321 for f in ms:
6347 if not m(f):
6322 if not m(f):
6348 continue
6323 continue
6349 flags = ''.join(['-%s ' % o[0] for o in flaglist
6324 flags = ''.join(['-%s ' % o[0] for o in flaglist
6350 if opts.get(o)])
6325 if opts.get(o)])
6351 hint = _("(try: hg resolve %s%s)\n") % (
6326 hint = _("(try: hg resolve %s%s)\n") % (
6352 flags,
6327 flags,
6353 ' '.join(pats))
6328 ' '.join(pats))
6354 break
6329 break
6355 ui.warn(_("arguments do not match paths that need resolving\n"))
6330 ui.warn(_("arguments do not match paths that need resolving\n"))
6356 if hint:
6331 if hint:
6357 ui.warn(hint)
6332 ui.warn(hint)
6358 elif ms.mergedriver and ms.mdstate() != 's':
6333 elif ms.mergedriver and ms.mdstate() != 's':
6359 # run conclude step when either a driver-resolved file is requested
6334 # run conclude step when either a driver-resolved file is requested
6360 # or there are no driver-resolved files
6335 # or there are no driver-resolved files
6361 # we can't use 'ret' to determine whether any files are unresolved
6336 # we can't use 'ret' to determine whether any files are unresolved
6362 # because we might not have tried to resolve some
6337 # because we might not have tried to resolve some
6363 if ((runconclude or not list(ms.driverresolved()))
6338 if ((runconclude or not list(ms.driverresolved()))
6364 and not list(ms.unresolved())):
6339 and not list(ms.unresolved())):
6365 proceed = mergemod.driverconclude(repo, ms, wctx)
6340 proceed = mergemod.driverconclude(repo, ms, wctx)
6366 ms.commit()
6341 ms.commit()
6367 if not proceed:
6342 if not proceed:
6368 return 1
6343 return 1
6369
6344
6370 # Nudge users into finishing an unfinished operation
6345 # Nudge users into finishing an unfinished operation
6371 unresolvedf = list(ms.unresolved())
6346 unresolvedf = list(ms.unresolved())
6372 driverresolvedf = list(ms.driverresolved())
6347 driverresolvedf = list(ms.driverresolved())
6373 if not unresolvedf and not driverresolvedf:
6348 if not unresolvedf and not driverresolvedf:
6374 ui.status(_('(no more unresolved files)\n'))
6349 ui.status(_('(no more unresolved files)\n'))
6375 cmdutil.checkafterresolved(repo)
6350 cmdutil.checkafterresolved(repo)
6376 elif not unresolvedf:
6351 elif not unresolvedf:
6377 ui.status(_('(no more unresolved files -- '
6352 ui.status(_('(no more unresolved files -- '
6378 'run "hg resolve --all" to conclude)\n'))
6353 'run "hg resolve --all" to conclude)\n'))
6379
6354
6380 return ret
6355 return ret
6381
6356
6382 @command('revert',
6357 @command('revert',
6383 [('a', 'all', None, _('revert all changes when no arguments given')),
6358 [('a', 'all', None, _('revert all changes when no arguments given')),
6384 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6359 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6385 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6360 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6386 ('C', 'no-backup', None, _('do not save backup copies of files')),
6361 ('C', 'no-backup', None, _('do not save backup copies of files')),
6387 ('i', 'interactive', None,
6362 ('i', 'interactive', None,
6388 _('interactively select the changes (EXPERIMENTAL)')),
6363 _('interactively select the changes (EXPERIMENTAL)')),
6389 ] + walkopts + dryrunopts,
6364 ] + walkopts + dryrunopts,
6390 _('[OPTION]... [-r REV] [NAME]...'))
6365 _('[OPTION]... [-r REV] [NAME]...'))
6391 def revert(ui, repo, *pats, **opts):
6366 def revert(ui, repo, *pats, **opts):
6392 """restore files to their checkout state
6367 """restore files to their checkout state
6393
6368
6394 .. note::
6369 .. note::
6395
6370
6396 To check out earlier revisions, you should use :hg:`update REV`.
6371 To check out earlier revisions, you should use :hg:`update REV`.
6397 To cancel an uncommitted merge (and lose your changes),
6372 To cancel an uncommitted merge (and lose your changes),
6398 use :hg:`update --clean .`.
6373 use :hg:`update --clean .`.
6399
6374
6400 With no revision specified, revert the specified files or directories
6375 With no revision specified, revert the specified files or directories
6401 to the contents they had in the parent of the working directory.
6376 to the contents they had in the parent of the working directory.
6402 This restores the contents of files to an unmodified
6377 This restores the contents of files to an unmodified
6403 state and unschedules adds, removes, copies, and renames. If the
6378 state and unschedules adds, removes, copies, and renames. If the
6404 working directory has two parents, you must explicitly specify a
6379 working directory has two parents, you must explicitly specify a
6405 revision.
6380 revision.
6406
6381
6407 Using the -r/--rev or -d/--date options, revert the given files or
6382 Using the -r/--rev or -d/--date options, revert the given files or
6408 directories to their states as of a specific revision. Because
6383 directories to their states as of a specific revision. Because
6409 revert does not change the working directory parents, this will
6384 revert does not change the working directory parents, this will
6410 cause these files to appear modified. This can be helpful to "back
6385 cause these files to appear modified. This can be helpful to "back
6411 out" some or all of an earlier change. See :hg:`backout` for a
6386 out" some or all of an earlier change. See :hg:`backout` for a
6412 related method.
6387 related method.
6413
6388
6414 Modified files are saved with a .orig suffix before reverting.
6389 Modified files are saved with a .orig suffix before reverting.
6415 To disable these backups, use --no-backup. It is possible to store
6390 To disable these backups, use --no-backup. It is possible to store
6416 the backup files in a custom directory relative to the root of the
6391 the backup files in a custom directory relative to the root of the
6417 repository by setting the ``ui.origbackuppath`` configuration
6392 repository by setting the ``ui.origbackuppath`` configuration
6418 option.
6393 option.
6419
6394
6420 See :hg:`help dates` for a list of formats valid for -d/--date.
6395 See :hg:`help dates` for a list of formats valid for -d/--date.
6421
6396
6422 See :hg:`help backout` for a way to reverse the effect of an
6397 See :hg:`help backout` for a way to reverse the effect of an
6423 earlier changeset.
6398 earlier changeset.
6424
6399
6425 Returns 0 on success.
6400 Returns 0 on success.
6426 """
6401 """
6427
6402
6428 if opts.get("date"):
6403 if opts.get("date"):
6429 if opts.get("rev"):
6404 if opts.get("rev"):
6430 raise error.Abort(_("you can't specify a revision and a date"))
6405 raise error.Abort(_("you can't specify a revision and a date"))
6431 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6406 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6432
6407
6433 parent, p2 = repo.dirstate.parents()
6408 parent, p2 = repo.dirstate.parents()
6434 if not opts.get('rev') and p2 != nullid:
6409 if not opts.get('rev') and p2 != nullid:
6435 # revert after merge is a trap for new users (issue2915)
6410 # revert after merge is a trap for new users (issue2915)
6436 raise error.Abort(_('uncommitted merge with no revision specified'),
6411 raise error.Abort(_('uncommitted merge with no revision specified'),
6437 hint=_("use 'hg update' or see 'hg help revert'"))
6412 hint=_("use 'hg update' or see 'hg help revert'"))
6438
6413
6439 ctx = scmutil.revsingle(repo, opts.get('rev'))
6414 ctx = scmutil.revsingle(repo, opts.get('rev'))
6440
6415
6441 if (not (pats or opts.get('include') or opts.get('exclude') or
6416 if (not (pats or opts.get('include') or opts.get('exclude') or
6442 opts.get('all') or opts.get('interactive'))):
6417 opts.get('all') or opts.get('interactive'))):
6443 msg = _("no files or directories specified")
6418 msg = _("no files or directories specified")
6444 if p2 != nullid:
6419 if p2 != nullid:
6445 hint = _("uncommitted merge, use --all to discard all changes,"
6420 hint = _("uncommitted merge, use --all to discard all changes,"
6446 " or 'hg update -C .' to abort the merge")
6421 " or 'hg update -C .' to abort the merge")
6447 raise error.Abort(msg, hint=hint)
6422 raise error.Abort(msg, hint=hint)
6448 dirty = any(repo.status())
6423 dirty = any(repo.status())
6449 node = ctx.node()
6424 node = ctx.node()
6450 if node != parent:
6425 if node != parent:
6451 if dirty:
6426 if dirty:
6452 hint = _("uncommitted changes, use --all to discard all"
6427 hint = _("uncommitted changes, use --all to discard all"
6453 " changes, or 'hg update %s' to update") % ctx.rev()
6428 " changes, or 'hg update %s' to update") % ctx.rev()
6454 else:
6429 else:
6455 hint = _("use --all to revert all files,"
6430 hint = _("use --all to revert all files,"
6456 " or 'hg update %s' to update") % ctx.rev()
6431 " or 'hg update %s' to update") % ctx.rev()
6457 elif dirty:
6432 elif dirty:
6458 hint = _("uncommitted changes, use --all to discard all changes")
6433 hint = _("uncommitted changes, use --all to discard all changes")
6459 else:
6434 else:
6460 hint = _("use --all to revert all files")
6435 hint = _("use --all to revert all files")
6461 raise error.Abort(msg, hint=hint)
6436 raise error.Abort(msg, hint=hint)
6462
6437
6463 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6438 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6464
6439
6465 @command('rollback', dryrunopts +
6440 @command('rollback', dryrunopts +
6466 [('f', 'force', False, _('ignore safety measures'))])
6441 [('f', 'force', False, _('ignore safety measures'))])
6467 def rollback(ui, repo, **opts):
6442 def rollback(ui, repo, **opts):
6468 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6443 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6469
6444
6470 Please use :hg:`commit --amend` instead of rollback to correct
6445 Please use :hg:`commit --amend` instead of rollback to correct
6471 mistakes in the last commit.
6446 mistakes in the last commit.
6472
6447
6473 This command should be used with care. There is only one level of
6448 This command should be used with care. There is only one level of
6474 rollback, and there is no way to undo a rollback. It will also
6449 rollback, and there is no way to undo a rollback. It will also
6475 restore the dirstate at the time of the last transaction, losing
6450 restore the dirstate at the time of the last transaction, losing
6476 any dirstate changes since that time. This command does not alter
6451 any dirstate changes since that time. This command does not alter
6477 the working directory.
6452 the working directory.
6478
6453
6479 Transactions are used to encapsulate the effects of all commands
6454 Transactions are used to encapsulate the effects of all commands
6480 that create new changesets or propagate existing changesets into a
6455 that create new changesets or propagate existing changesets into a
6481 repository.
6456 repository.
6482
6457
6483 .. container:: verbose
6458 .. container:: verbose
6484
6459
6485 For example, the following commands are transactional, and their
6460 For example, the following commands are transactional, and their
6486 effects can be rolled back:
6461 effects can be rolled back:
6487
6462
6488 - commit
6463 - commit
6489 - import
6464 - import
6490 - pull
6465 - pull
6491 - push (with this repository as the destination)
6466 - push (with this repository as the destination)
6492 - unbundle
6467 - unbundle
6493
6468
6494 To avoid permanent data loss, rollback will refuse to rollback a
6469 To avoid permanent data loss, rollback will refuse to rollback a
6495 commit transaction if it isn't checked out. Use --force to
6470 commit transaction if it isn't checked out. Use --force to
6496 override this protection.
6471 override this protection.
6497
6472
6498 The rollback command can be entirely disabled by setting the
6473 The rollback command can be entirely disabled by setting the
6499 ``ui.rollback`` configuration setting to false. If you're here
6474 ``ui.rollback`` configuration setting to false. If you're here
6500 because you want to use rollback and it's disabled, you can
6475 because you want to use rollback and it's disabled, you can
6501 re-enable the command by setting ``ui.rollback`` to true.
6476 re-enable the command by setting ``ui.rollback`` to true.
6502
6477
6503 This command is not intended for use on public repositories. Once
6478 This command is not intended for use on public repositories. Once
6504 changes are visible for pull by other users, rolling a transaction
6479 changes are visible for pull by other users, rolling a transaction
6505 back locally is ineffective (someone else may already have pulled
6480 back locally is ineffective (someone else may already have pulled
6506 the changes). Furthermore, a race is possible with readers of the
6481 the changes). Furthermore, a race is possible with readers of the
6507 repository; for example an in-progress pull from the repository
6482 repository; for example an in-progress pull from the repository
6508 may fail if a rollback is performed.
6483 may fail if a rollback is performed.
6509
6484
6510 Returns 0 on success, 1 if no rollback data is available.
6485 Returns 0 on success, 1 if no rollback data is available.
6511 """
6486 """
6512 if not ui.configbool('ui', 'rollback', True):
6487 if not ui.configbool('ui', 'rollback', True):
6513 raise error.Abort(_('rollback is disabled because it is unsafe'),
6488 raise error.Abort(_('rollback is disabled because it is unsafe'),
6514 hint=('see `hg help -v rollback` for information'))
6489 hint=('see `hg help -v rollback` for information'))
6515 return repo.rollback(dryrun=opts.get('dry_run'),
6490 return repo.rollback(dryrun=opts.get('dry_run'),
6516 force=opts.get('force'))
6491 force=opts.get('force'))
6517
6492
6518 @command('root', [])
6493 @command('root', [])
6519 def root(ui, repo):
6494 def root(ui, repo):
6520 """print the root (top) of the current working directory
6495 """print the root (top) of the current working directory
6521
6496
6522 Print the root directory of the current repository.
6497 Print the root directory of the current repository.
6523
6498
6524 Returns 0 on success.
6499 Returns 0 on success.
6525 """
6500 """
6526 ui.write(repo.root + "\n")
6501 ui.write(repo.root + "\n")
6527
6502
6528 @command('^serve',
6503 @command('^serve',
6529 [('A', 'accesslog', '', _('name of access log file to write to'),
6504 [('A', 'accesslog', '', _('name of access log file to write to'),
6530 _('FILE')),
6505 _('FILE')),
6531 ('d', 'daemon', None, _('run server in background')),
6506 ('d', 'daemon', None, _('run server in background')),
6532 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6507 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6533 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6508 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6534 # use string type, then we can check if something was passed
6509 # use string type, then we can check if something was passed
6535 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6510 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6536 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6511 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6537 _('ADDR')),
6512 _('ADDR')),
6538 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6513 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6539 _('PREFIX')),
6514 _('PREFIX')),
6540 ('n', 'name', '',
6515 ('n', 'name', '',
6541 _('name to show in web pages (default: working directory)'), _('NAME')),
6516 _('name to show in web pages (default: working directory)'), _('NAME')),
6542 ('', 'web-conf', '',
6517 ('', 'web-conf', '',
6543 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6518 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6544 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6519 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6545 _('FILE')),
6520 _('FILE')),
6546 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6521 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6547 ('', 'stdio', None, _('for remote clients')),
6522 ('', 'stdio', None, _('for remote clients')),
6548 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6523 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6549 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6524 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6550 ('', 'style', '', _('template style to use'), _('STYLE')),
6525 ('', 'style', '', _('template style to use'), _('STYLE')),
6551 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6526 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6552 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6527 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6553 _('[OPTION]...'),
6528 _('[OPTION]...'),
6554 optionalrepo=True)
6529 optionalrepo=True)
6555 def serve(ui, repo, **opts):
6530 def serve(ui, repo, **opts):
6556 """start stand-alone webserver
6531 """start stand-alone webserver
6557
6532
6558 Start a local HTTP repository browser and pull server. You can use
6533 Start a local HTTP repository browser and pull server. You can use
6559 this for ad-hoc sharing and browsing of repositories. It is
6534 this for ad-hoc sharing and browsing of repositories. It is
6560 recommended to use a real web server to serve a repository for
6535 recommended to use a real web server to serve a repository for
6561 longer periods of time.
6536 longer periods of time.
6562
6537
6563 Please note that the server does not implement access control.
6538 Please note that the server does not implement access control.
6564 This means that, by default, anybody can read from the server and
6539 This means that, by default, anybody can read from the server and
6565 nobody can write to it by default. Set the ``web.allow_push``
6540 nobody can write to it by default. Set the ``web.allow_push``
6566 option to ``*`` to allow everybody to push to the server. You
6541 option to ``*`` to allow everybody to push to the server. You
6567 should use a real web server if you need to authenticate users.
6542 should use a real web server if you need to authenticate users.
6568
6543
6569 By default, the server logs accesses to stdout and errors to
6544 By default, the server logs accesses to stdout and errors to
6570 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6545 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6571 files.
6546 files.
6572
6547
6573 To have the server choose a free port number to listen on, specify
6548 To have the server choose a free port number to listen on, specify
6574 a port number of 0; in this case, the server will print the port
6549 a port number of 0; in this case, the server will print the port
6575 number it uses.
6550 number it uses.
6576
6551
6577 Returns 0 on success.
6552 Returns 0 on success.
6578 """
6553 """
6579
6554
6580 if opts["stdio"] and opts["cmdserver"]:
6555 if opts["stdio"] and opts["cmdserver"]:
6581 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6556 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6582
6557
6583 if opts["stdio"]:
6558 if opts["stdio"]:
6584 if repo is None:
6559 if repo is None:
6585 raise error.RepoError(_("there is no Mercurial repository here"
6560 raise error.RepoError(_("there is no Mercurial repository here"
6586 " (.hg not found)"))
6561 " (.hg not found)"))
6587 s = sshserver.sshserver(ui, repo)
6562 s = sshserver.sshserver(ui, repo)
6588 s.serve_forever()
6563 s.serve_forever()
6589
6564
6590 if opts["cmdserver"]:
6565 if opts["cmdserver"]:
6591 service = commandserver.createservice(ui, repo, opts)
6566 service = commandserver.createservice(ui, repo, opts)
6592 else:
6567 else:
6593 service = hgweb.createservice(ui, repo, opts)
6568 service = hgweb.createservice(ui, repo, opts)
6594 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6569 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6595
6570
6596 @command('^status|st',
6571 @command('^status|st',
6597 [('A', 'all', None, _('show status of all files')),
6572 [('A', 'all', None, _('show status of all files')),
6598 ('m', 'modified', None, _('show only modified files')),
6573 ('m', 'modified', None, _('show only modified files')),
6599 ('a', 'added', None, _('show only added files')),
6574 ('a', 'added', None, _('show only added files')),
6600 ('r', 'removed', None, _('show only removed files')),
6575 ('r', 'removed', None, _('show only removed files')),
6601 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6576 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6602 ('c', 'clean', None, _('show only files without changes')),
6577 ('c', 'clean', None, _('show only files without changes')),
6603 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6578 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6604 ('i', 'ignored', None, _('show only ignored files')),
6579 ('i', 'ignored', None, _('show only ignored files')),
6605 ('n', 'no-status', None, _('hide status prefix')),
6580 ('n', 'no-status', None, _('hide status prefix')),
6606 ('C', 'copies', None, _('show source of copied files')),
6581 ('C', 'copies', None, _('show source of copied files')),
6607 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6582 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6608 ('', 'rev', [], _('show difference from revision'), _('REV')),
6583 ('', 'rev', [], _('show difference from revision'), _('REV')),
6609 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6584 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6610 ] + walkopts + subrepoopts + formatteropts,
6585 ] + walkopts + subrepoopts + formatteropts,
6611 _('[OPTION]... [FILE]...'),
6586 _('[OPTION]... [FILE]...'),
6612 inferrepo=True)
6587 inferrepo=True)
6613 def status(ui, repo, *pats, **opts):
6588 def status(ui, repo, *pats, **opts):
6614 """show changed files in the working directory
6589 """show changed files in the working directory
6615
6590
6616 Show status of files in the repository. If names are given, only
6591 Show status of files in the repository. If names are given, only
6617 files that match are shown. Files that are clean or ignored or
6592 files that match are shown. Files that are clean or ignored or
6618 the source of a copy/move operation, are not listed unless
6593 the source of a copy/move operation, are not listed unless
6619 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6594 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6620 Unless options described with "show only ..." are given, the
6595 Unless options described with "show only ..." are given, the
6621 options -mardu are used.
6596 options -mardu are used.
6622
6597
6623 Option -q/--quiet hides untracked (unknown and ignored) files
6598 Option -q/--quiet hides untracked (unknown and ignored) files
6624 unless explicitly requested with -u/--unknown or -i/--ignored.
6599 unless explicitly requested with -u/--unknown or -i/--ignored.
6625
6600
6626 .. note::
6601 .. note::
6627
6602
6628 :hg:`status` may appear to disagree with diff if permissions have
6603 :hg:`status` may appear to disagree with diff if permissions have
6629 changed or a merge has occurred. The standard diff format does
6604 changed or a merge has occurred. The standard diff format does
6630 not report permission changes and diff only reports changes
6605 not report permission changes and diff only reports changes
6631 relative to one merge parent.
6606 relative to one merge parent.
6632
6607
6633 If one revision is given, it is used as the base revision.
6608 If one revision is given, it is used as the base revision.
6634 If two revisions are given, the differences between them are
6609 If two revisions are given, the differences between them are
6635 shown. The --change option can also be used as a shortcut to list
6610 shown. The --change option can also be used as a shortcut to list
6636 the changed files of a revision from its first parent.
6611 the changed files of a revision from its first parent.
6637
6612
6638 The codes used to show the status of files are::
6613 The codes used to show the status of files are::
6639
6614
6640 M = modified
6615 M = modified
6641 A = added
6616 A = added
6642 R = removed
6617 R = removed
6643 C = clean
6618 C = clean
6644 ! = missing (deleted by non-hg command, but still tracked)
6619 ! = missing (deleted by non-hg command, but still tracked)
6645 ? = not tracked
6620 ? = not tracked
6646 I = ignored
6621 I = ignored
6647 = origin of the previous file (with --copies)
6622 = origin of the previous file (with --copies)
6648
6623
6649 .. container:: verbose
6624 .. container:: verbose
6650
6625
6651 Examples:
6626 Examples:
6652
6627
6653 - show changes in the working directory relative to a
6628 - show changes in the working directory relative to a
6654 changeset::
6629 changeset::
6655
6630
6656 hg status --rev 9353
6631 hg status --rev 9353
6657
6632
6658 - show changes in the working directory relative to the
6633 - show changes in the working directory relative to the
6659 current directory (see :hg:`help patterns` for more information)::
6634 current directory (see :hg:`help patterns` for more information)::
6660
6635
6661 hg status re:
6636 hg status re:
6662
6637
6663 - show all changes including copies in an existing changeset::
6638 - show all changes including copies in an existing changeset::
6664
6639
6665 hg status --copies --change 9353
6640 hg status --copies --change 9353
6666
6641
6667 - get a NUL separated list of added files, suitable for xargs::
6642 - get a NUL separated list of added files, suitable for xargs::
6668
6643
6669 hg status -an0
6644 hg status -an0
6670
6645
6671 Returns 0 on success.
6646 Returns 0 on success.
6672 """
6647 """
6673
6648
6674 revs = opts.get('rev')
6649 revs = opts.get('rev')
6675 change = opts.get('change')
6650 change = opts.get('change')
6676
6651
6677 if revs and change:
6652 if revs and change:
6678 msg = _('cannot specify --rev and --change at the same time')
6653 msg = _('cannot specify --rev and --change at the same time')
6679 raise error.Abort(msg)
6654 raise error.Abort(msg)
6680 elif change:
6655 elif change:
6681 node2 = scmutil.revsingle(repo, change, None).node()
6656 node2 = scmutil.revsingle(repo, change, None).node()
6682 node1 = repo[node2].p1().node()
6657 node1 = repo[node2].p1().node()
6683 else:
6658 else:
6684 node1, node2 = scmutil.revpair(repo, revs)
6659 node1, node2 = scmutil.revpair(repo, revs)
6685
6660
6686 if pats:
6661 if pats:
6687 cwd = repo.getcwd()
6662 cwd = repo.getcwd()
6688 else:
6663 else:
6689 cwd = ''
6664 cwd = ''
6690
6665
6691 if opts.get('print0'):
6666 if opts.get('print0'):
6692 end = '\0'
6667 end = '\0'
6693 else:
6668 else:
6694 end = '\n'
6669 end = '\n'
6695 copy = {}
6670 copy = {}
6696 states = 'modified added removed deleted unknown ignored clean'.split()
6671 states = 'modified added removed deleted unknown ignored clean'.split()
6697 show = [k for k in states if opts.get(k)]
6672 show = [k for k in states if opts.get(k)]
6698 if opts.get('all'):
6673 if opts.get('all'):
6699 show += ui.quiet and (states[:4] + ['clean']) or states
6674 show += ui.quiet and (states[:4] + ['clean']) or states
6700 if not show:
6675 if not show:
6701 if ui.quiet:
6676 if ui.quiet:
6702 show = states[:4]
6677 show = states[:4]
6703 else:
6678 else:
6704 show = states[:5]
6679 show = states[:5]
6705
6680
6706 m = scmutil.match(repo[node2], pats, opts)
6681 m = scmutil.match(repo[node2], pats, opts)
6707 stat = repo.status(node1, node2, m,
6682 stat = repo.status(node1, node2, m,
6708 'ignored' in show, 'clean' in show, 'unknown' in show,
6683 'ignored' in show, 'clean' in show, 'unknown' in show,
6709 opts.get('subrepos'))
6684 opts.get('subrepos'))
6710 changestates = zip(states, 'MAR!?IC', stat)
6685 changestates = zip(states, 'MAR!?IC', stat)
6711
6686
6712 if (opts.get('all') or opts.get('copies')
6687 if (opts.get('all') or opts.get('copies')
6713 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6688 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6714 copy = copies.pathcopies(repo[node1], repo[node2], m)
6689 copy = copies.pathcopies(repo[node1], repo[node2], m)
6715
6690
6716 fm = ui.formatter('status', opts)
6691 fm = ui.formatter('status', opts)
6717 fmt = '%s' + end
6692 fmt = '%s' + end
6718 showchar = not opts.get('no_status')
6693 showchar = not opts.get('no_status')
6719
6694
6720 for state, char, files in changestates:
6695 for state, char, files in changestates:
6721 if state in show:
6696 if state in show:
6722 label = 'status.' + state
6697 label = 'status.' + state
6723 for f in files:
6698 for f in files:
6724 fm.startitem()
6699 fm.startitem()
6725 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6700 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6726 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6701 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6727 if f in copy:
6702 if f in copy:
6728 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6703 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6729 label='status.copied')
6704 label='status.copied')
6730 fm.end()
6705 fm.end()
6731
6706
6732 @command('^summary|sum',
6707 @command('^summary|sum',
6733 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6708 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6734 def summary(ui, repo, **opts):
6709 def summary(ui, repo, **opts):
6735 """summarize working directory state
6710 """summarize working directory state
6736
6711
6737 This generates a brief summary of the working directory state,
6712 This generates a brief summary of the working directory state,
6738 including parents, branch, commit status, phase and available updates.
6713 including parents, branch, commit status, phase and available updates.
6739
6714
6740 With the --remote option, this will check the default paths for
6715 With the --remote option, this will check the default paths for
6741 incoming and outgoing changes. This can be time-consuming.
6716 incoming and outgoing changes. This can be time-consuming.
6742
6717
6743 Returns 0 on success.
6718 Returns 0 on success.
6744 """
6719 """
6745
6720
6746 ctx = repo[None]
6721 ctx = repo[None]
6747 parents = ctx.parents()
6722 parents = ctx.parents()
6748 pnode = parents[0].node()
6723 pnode = parents[0].node()
6749 marks = []
6724 marks = []
6750
6725
6751 ms = None
6726 ms = None
6752 try:
6727 try:
6753 ms = mergemod.mergestate.read(repo)
6728 ms = mergemod.mergestate.read(repo)
6754 except error.UnsupportedMergeRecords as e:
6729 except error.UnsupportedMergeRecords as e:
6755 s = ' '.join(e.recordtypes)
6730 s = ' '.join(e.recordtypes)
6756 ui.warn(
6731 ui.warn(
6757 _('warning: merge state has unsupported record types: %s\n') % s)
6732 _('warning: merge state has unsupported record types: %s\n') % s)
6758 unresolved = 0
6733 unresolved = 0
6759 else:
6734 else:
6760 unresolved = [f for f in ms if ms[f] == 'u']
6735 unresolved = [f for f in ms if ms[f] == 'u']
6761
6736
6762 for p in parents:
6737 for p in parents:
6763 # label with log.changeset (instead of log.parent) since this
6738 # label with log.changeset (instead of log.parent) since this
6764 # shows a working directory parent *changeset*:
6739 # shows a working directory parent *changeset*:
6765 # i18n: column positioning for "hg summary"
6740 # i18n: column positioning for "hg summary"
6766 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6741 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6767 label='log.changeset changeset.%s' % p.phasestr())
6742 label='log.changeset changeset.%s' % p.phasestr())
6768 ui.write(' '.join(p.tags()), label='log.tag')
6743 ui.write(' '.join(p.tags()), label='log.tag')
6769 if p.bookmarks():
6744 if p.bookmarks():
6770 marks.extend(p.bookmarks())
6745 marks.extend(p.bookmarks())
6771 if p.rev() == -1:
6746 if p.rev() == -1:
6772 if not len(repo):
6747 if not len(repo):
6773 ui.write(_(' (empty repository)'))
6748 ui.write(_(' (empty repository)'))
6774 else:
6749 else:
6775 ui.write(_(' (no revision checked out)'))
6750 ui.write(_(' (no revision checked out)'))
6776 ui.write('\n')
6751 ui.write('\n')
6777 if p.description():
6752 if p.description():
6778 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6753 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6779 label='log.summary')
6754 label='log.summary')
6780
6755
6781 branch = ctx.branch()
6756 branch = ctx.branch()
6782 bheads = repo.branchheads(branch)
6757 bheads = repo.branchheads(branch)
6783 # i18n: column positioning for "hg summary"
6758 # i18n: column positioning for "hg summary"
6784 m = _('branch: %s\n') % branch
6759 m = _('branch: %s\n') % branch
6785 if branch != 'default':
6760 if branch != 'default':
6786 ui.write(m, label='log.branch')
6761 ui.write(m, label='log.branch')
6787 else:
6762 else:
6788 ui.status(m, label='log.branch')
6763 ui.status(m, label='log.branch')
6789
6764
6790 if marks:
6765 if marks:
6791 active = repo._activebookmark
6766 active = repo._activebookmark
6792 # i18n: column positioning for "hg summary"
6767 # i18n: column positioning for "hg summary"
6793 ui.write(_('bookmarks:'), label='log.bookmark')
6768 ui.write(_('bookmarks:'), label='log.bookmark')
6794 if active is not None:
6769 if active is not None:
6795 if active in marks:
6770 if active in marks:
6796 ui.write(' *' + active, label=activebookmarklabel)
6771 ui.write(' *' + active, label=activebookmarklabel)
6797 marks.remove(active)
6772 marks.remove(active)
6798 else:
6773 else:
6799 ui.write(' [%s]' % active, label=activebookmarklabel)
6774 ui.write(' [%s]' % active, label=activebookmarklabel)
6800 for m in marks:
6775 for m in marks:
6801 ui.write(' ' + m, label='log.bookmark')
6776 ui.write(' ' + m, label='log.bookmark')
6802 ui.write('\n', label='log.bookmark')
6777 ui.write('\n', label='log.bookmark')
6803
6778
6804 status = repo.status(unknown=True)
6779 status = repo.status(unknown=True)
6805
6780
6806 c = repo.dirstate.copies()
6781 c = repo.dirstate.copies()
6807 copied, renamed = [], []
6782 copied, renamed = [], []
6808 for d, s in c.iteritems():
6783 for d, s in c.iteritems():
6809 if s in status.removed:
6784 if s in status.removed:
6810 status.removed.remove(s)
6785 status.removed.remove(s)
6811 renamed.append(d)
6786 renamed.append(d)
6812 else:
6787 else:
6813 copied.append(d)
6788 copied.append(d)
6814 if d in status.added:
6789 if d in status.added:
6815 status.added.remove(d)
6790 status.added.remove(d)
6816
6791
6817 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6792 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6818
6793
6819 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6794 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6820 (ui.label(_('%d added'), 'status.added'), status.added),
6795 (ui.label(_('%d added'), 'status.added'), status.added),
6821 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6796 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6822 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6797 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6823 (ui.label(_('%d copied'), 'status.copied'), copied),
6798 (ui.label(_('%d copied'), 'status.copied'), copied),
6824 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6799 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6825 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6800 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6826 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6801 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6827 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6802 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6828 t = []
6803 t = []
6829 for l, s in labels:
6804 for l, s in labels:
6830 if s:
6805 if s:
6831 t.append(l % len(s))
6806 t.append(l % len(s))
6832
6807
6833 t = ', '.join(t)
6808 t = ', '.join(t)
6834 cleanworkdir = False
6809 cleanworkdir = False
6835
6810
6836 if repo.vfs.exists('graftstate'):
6811 if repo.vfs.exists('graftstate'):
6837 t += _(' (graft in progress)')
6812 t += _(' (graft in progress)')
6838 if repo.vfs.exists('updatestate'):
6813 if repo.vfs.exists('updatestate'):
6839 t += _(' (interrupted update)')
6814 t += _(' (interrupted update)')
6840 elif len(parents) > 1:
6815 elif len(parents) > 1:
6841 t += _(' (merge)')
6816 t += _(' (merge)')
6842 elif branch != parents[0].branch():
6817 elif branch != parents[0].branch():
6843 t += _(' (new branch)')
6818 t += _(' (new branch)')
6844 elif (parents[0].closesbranch() and
6819 elif (parents[0].closesbranch() and
6845 pnode in repo.branchheads(branch, closed=True)):
6820 pnode in repo.branchheads(branch, closed=True)):
6846 t += _(' (head closed)')
6821 t += _(' (head closed)')
6847 elif not (status.modified or status.added or status.removed or renamed or
6822 elif not (status.modified or status.added or status.removed or renamed or
6848 copied or subs):
6823 copied or subs):
6849 t += _(' (clean)')
6824 t += _(' (clean)')
6850 cleanworkdir = True
6825 cleanworkdir = True
6851 elif pnode not in bheads:
6826 elif pnode not in bheads:
6852 t += _(' (new branch head)')
6827 t += _(' (new branch head)')
6853
6828
6854 if parents:
6829 if parents:
6855 pendingphase = max(p.phase() for p in parents)
6830 pendingphase = max(p.phase() for p in parents)
6856 else:
6831 else:
6857 pendingphase = phases.public
6832 pendingphase = phases.public
6858
6833
6859 if pendingphase > phases.newcommitphase(ui):
6834 if pendingphase > phases.newcommitphase(ui):
6860 t += ' (%s)' % phases.phasenames[pendingphase]
6835 t += ' (%s)' % phases.phasenames[pendingphase]
6861
6836
6862 if cleanworkdir:
6837 if cleanworkdir:
6863 # i18n: column positioning for "hg summary"
6838 # i18n: column positioning for "hg summary"
6864 ui.status(_('commit: %s\n') % t.strip())
6839 ui.status(_('commit: %s\n') % t.strip())
6865 else:
6840 else:
6866 # i18n: column positioning for "hg summary"
6841 # i18n: column positioning for "hg summary"
6867 ui.write(_('commit: %s\n') % t.strip())
6842 ui.write(_('commit: %s\n') % t.strip())
6868
6843
6869 # all ancestors of branch heads - all ancestors of parent = new csets
6844 # all ancestors of branch heads - all ancestors of parent = new csets
6870 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6845 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6871 bheads))
6846 bheads))
6872
6847
6873 if new == 0:
6848 if new == 0:
6874 # i18n: column positioning for "hg summary"
6849 # i18n: column positioning for "hg summary"
6875 ui.status(_('update: (current)\n'))
6850 ui.status(_('update: (current)\n'))
6876 elif pnode not in bheads:
6851 elif pnode not in bheads:
6877 # i18n: column positioning for "hg summary"
6852 # i18n: column positioning for "hg summary"
6878 ui.write(_('update: %d new changesets (update)\n') % new)
6853 ui.write(_('update: %d new changesets (update)\n') % new)
6879 else:
6854 else:
6880 # i18n: column positioning for "hg summary"
6855 # i18n: column positioning for "hg summary"
6881 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6856 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6882 (new, len(bheads)))
6857 (new, len(bheads)))
6883
6858
6884 t = []
6859 t = []
6885 draft = len(repo.revs('draft()'))
6860 draft = len(repo.revs('draft()'))
6886 if draft:
6861 if draft:
6887 t.append(_('%d draft') % draft)
6862 t.append(_('%d draft') % draft)
6888 secret = len(repo.revs('secret()'))
6863 secret = len(repo.revs('secret()'))
6889 if secret:
6864 if secret:
6890 t.append(_('%d secret') % secret)
6865 t.append(_('%d secret') % secret)
6891
6866
6892 if draft or secret:
6867 if draft or secret:
6893 ui.status(_('phases: %s\n') % ', '.join(t))
6868 ui.status(_('phases: %s\n') % ', '.join(t))
6894
6869
6895 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6870 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6896 for trouble in ("unstable", "divergent", "bumped"):
6871 for trouble in ("unstable", "divergent", "bumped"):
6897 numtrouble = len(repo.revs(trouble + "()"))
6872 numtrouble = len(repo.revs(trouble + "()"))
6898 # We write all the possibilities to ease translation
6873 # We write all the possibilities to ease translation
6899 troublemsg = {
6874 troublemsg = {
6900 "unstable": _("unstable: %d changesets"),
6875 "unstable": _("unstable: %d changesets"),
6901 "divergent": _("divergent: %d changesets"),
6876 "divergent": _("divergent: %d changesets"),
6902 "bumped": _("bumped: %d changesets"),
6877 "bumped": _("bumped: %d changesets"),
6903 }
6878 }
6904 if numtrouble > 0:
6879 if numtrouble > 0:
6905 ui.status(troublemsg[trouble] % numtrouble + "\n")
6880 ui.status(troublemsg[trouble] % numtrouble + "\n")
6906
6881
6907 cmdutil.summaryhooks(ui, repo)
6882 cmdutil.summaryhooks(ui, repo)
6908
6883
6909 if opts.get('remote'):
6884 if opts.get('remote'):
6910 needsincoming, needsoutgoing = True, True
6885 needsincoming, needsoutgoing = True, True
6911 else:
6886 else:
6912 needsincoming, needsoutgoing = False, False
6887 needsincoming, needsoutgoing = False, False
6913 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6888 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6914 if i:
6889 if i:
6915 needsincoming = True
6890 needsincoming = True
6916 if o:
6891 if o:
6917 needsoutgoing = True
6892 needsoutgoing = True
6918 if not needsincoming and not needsoutgoing:
6893 if not needsincoming and not needsoutgoing:
6919 return
6894 return
6920
6895
6921 def getincoming():
6896 def getincoming():
6922 source, branches = hg.parseurl(ui.expandpath('default'))
6897 source, branches = hg.parseurl(ui.expandpath('default'))
6923 sbranch = branches[0]
6898 sbranch = branches[0]
6924 try:
6899 try:
6925 other = hg.peer(repo, {}, source)
6900 other = hg.peer(repo, {}, source)
6926 except error.RepoError:
6901 except error.RepoError:
6927 if opts.get('remote'):
6902 if opts.get('remote'):
6928 raise
6903 raise
6929 return source, sbranch, None, None, None
6904 return source, sbranch, None, None, None
6930 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6905 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6931 if revs:
6906 if revs:
6932 revs = [other.lookup(rev) for rev in revs]
6907 revs = [other.lookup(rev) for rev in revs]
6933 ui.debug('comparing with %s\n' % util.hidepassword(source))
6908 ui.debug('comparing with %s\n' % util.hidepassword(source))
6934 repo.ui.pushbuffer()
6909 repo.ui.pushbuffer()
6935 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6910 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6936 repo.ui.popbuffer()
6911 repo.ui.popbuffer()
6937 return source, sbranch, other, commoninc, commoninc[1]
6912 return source, sbranch, other, commoninc, commoninc[1]
6938
6913
6939 if needsincoming:
6914 if needsincoming:
6940 source, sbranch, sother, commoninc, incoming = getincoming()
6915 source, sbranch, sother, commoninc, incoming = getincoming()
6941 else:
6916 else:
6942 source = sbranch = sother = commoninc = incoming = None
6917 source = sbranch = sother = commoninc = incoming = None
6943
6918
6944 def getoutgoing():
6919 def getoutgoing():
6945 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6920 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6946 dbranch = branches[0]
6921 dbranch = branches[0]
6947 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6922 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6948 if source != dest:
6923 if source != dest:
6949 try:
6924 try:
6950 dother = hg.peer(repo, {}, dest)
6925 dother = hg.peer(repo, {}, dest)
6951 except error.RepoError:
6926 except error.RepoError:
6952 if opts.get('remote'):
6927 if opts.get('remote'):
6953 raise
6928 raise
6954 return dest, dbranch, None, None
6929 return dest, dbranch, None, None
6955 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6930 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6956 elif sother is None:
6931 elif sother is None:
6957 # there is no explicit destination peer, but source one is invalid
6932 # there is no explicit destination peer, but source one is invalid
6958 return dest, dbranch, None, None
6933 return dest, dbranch, None, None
6959 else:
6934 else:
6960 dother = sother
6935 dother = sother
6961 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6936 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6962 common = None
6937 common = None
6963 else:
6938 else:
6964 common = commoninc
6939 common = commoninc
6965 if revs:
6940 if revs:
6966 revs = [repo.lookup(rev) for rev in revs]
6941 revs = [repo.lookup(rev) for rev in revs]
6967 repo.ui.pushbuffer()
6942 repo.ui.pushbuffer()
6968 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6943 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6969 commoninc=common)
6944 commoninc=common)
6970 repo.ui.popbuffer()
6945 repo.ui.popbuffer()
6971 return dest, dbranch, dother, outgoing
6946 return dest, dbranch, dother, outgoing
6972
6947
6973 if needsoutgoing:
6948 if needsoutgoing:
6974 dest, dbranch, dother, outgoing = getoutgoing()
6949 dest, dbranch, dother, outgoing = getoutgoing()
6975 else:
6950 else:
6976 dest = dbranch = dother = outgoing = None
6951 dest = dbranch = dother = outgoing = None
6977
6952
6978 if opts.get('remote'):
6953 if opts.get('remote'):
6979 t = []
6954 t = []
6980 if incoming:
6955 if incoming:
6981 t.append(_('1 or more incoming'))
6956 t.append(_('1 or more incoming'))
6982 o = outgoing.missing
6957 o = outgoing.missing
6983 if o:
6958 if o:
6984 t.append(_('%d outgoing') % len(o))
6959 t.append(_('%d outgoing') % len(o))
6985 other = dother or sother
6960 other = dother or sother
6986 if 'bookmarks' in other.listkeys('namespaces'):
6961 if 'bookmarks' in other.listkeys('namespaces'):
6987 counts = bookmarks.summary(repo, other)
6962 counts = bookmarks.summary(repo, other)
6988 if counts[0] > 0:
6963 if counts[0] > 0:
6989 t.append(_('%d incoming bookmarks') % counts[0])
6964 t.append(_('%d incoming bookmarks') % counts[0])
6990 if counts[1] > 0:
6965 if counts[1] > 0:
6991 t.append(_('%d outgoing bookmarks') % counts[1])
6966 t.append(_('%d outgoing bookmarks') % counts[1])
6992
6967
6993 if t:
6968 if t:
6994 # i18n: column positioning for "hg summary"
6969 # i18n: column positioning for "hg summary"
6995 ui.write(_('remote: %s\n') % (', '.join(t)))
6970 ui.write(_('remote: %s\n') % (', '.join(t)))
6996 else:
6971 else:
6997 # i18n: column positioning for "hg summary"
6972 # i18n: column positioning for "hg summary"
6998 ui.status(_('remote: (synced)\n'))
6973 ui.status(_('remote: (synced)\n'))
6999
6974
7000 cmdutil.summaryremotehooks(ui, repo, opts,
6975 cmdutil.summaryremotehooks(ui, repo, opts,
7001 ((source, sbranch, sother, commoninc),
6976 ((source, sbranch, sother, commoninc),
7002 (dest, dbranch, dother, outgoing)))
6977 (dest, dbranch, dother, outgoing)))
7003
6978
7004 @command('tag',
6979 @command('tag',
7005 [('f', 'force', None, _('force tag')),
6980 [('f', 'force', None, _('force tag')),
7006 ('l', 'local', None, _('make the tag local')),
6981 ('l', 'local', None, _('make the tag local')),
7007 ('r', 'rev', '', _('revision to tag'), _('REV')),
6982 ('r', 'rev', '', _('revision to tag'), _('REV')),
7008 ('', 'remove', None, _('remove a tag')),
6983 ('', 'remove', None, _('remove a tag')),
7009 # -l/--local is already there, commitopts cannot be used
6984 # -l/--local is already there, commitopts cannot be used
7010 ('e', 'edit', None, _('invoke editor on commit messages')),
6985 ('e', 'edit', None, _('invoke editor on commit messages')),
7011 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6986 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
7012 ] + commitopts2,
6987 ] + commitopts2,
7013 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6988 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
7014 def tag(ui, repo, name1, *names, **opts):
6989 def tag(ui, repo, name1, *names, **opts):
7015 """add one or more tags for the current or given revision
6990 """add one or more tags for the current or given revision
7016
6991
7017 Name a particular revision using <name>.
6992 Name a particular revision using <name>.
7018
6993
7019 Tags are used to name particular revisions of the repository and are
6994 Tags are used to name particular revisions of the repository and are
7020 very useful to compare different revisions, to go back to significant
6995 very useful to compare different revisions, to go back to significant
7021 earlier versions or to mark branch points as releases, etc. Changing
6996 earlier versions or to mark branch points as releases, etc. Changing
7022 an existing tag is normally disallowed; use -f/--force to override.
6997 an existing tag is normally disallowed; use -f/--force to override.
7023
6998
7024 If no revision is given, the parent of the working directory is
6999 If no revision is given, the parent of the working directory is
7025 used.
7000 used.
7026
7001
7027 To facilitate version control, distribution, and merging of tags,
7002 To facilitate version control, distribution, and merging of tags,
7028 they are stored as a file named ".hgtags" which is managed similarly
7003 they are stored as a file named ".hgtags" which is managed similarly
7029 to other project files and can be hand-edited if necessary. This
7004 to other project files and can be hand-edited if necessary. This
7030 also means that tagging creates a new commit. The file
7005 also means that tagging creates a new commit. The file
7031 ".hg/localtags" is used for local tags (not shared among
7006 ".hg/localtags" is used for local tags (not shared among
7032 repositories).
7007 repositories).
7033
7008
7034 Tag commits are usually made at the head of a branch. If the parent
7009 Tag commits are usually made at the head of a branch. If the parent
7035 of the working directory is not a branch head, :hg:`tag` aborts; use
7010 of the working directory is not a branch head, :hg:`tag` aborts; use
7036 -f/--force to force the tag commit to be based on a non-head
7011 -f/--force to force the tag commit to be based on a non-head
7037 changeset.
7012 changeset.
7038
7013
7039 See :hg:`help dates` for a list of formats valid for -d/--date.
7014 See :hg:`help dates` for a list of formats valid for -d/--date.
7040
7015
7041 Since tag names have priority over branch names during revision
7016 Since tag names have priority over branch names during revision
7042 lookup, using an existing branch name as a tag name is discouraged.
7017 lookup, using an existing branch name as a tag name is discouraged.
7043
7018
7044 Returns 0 on success.
7019 Returns 0 on success.
7045 """
7020 """
7046 wlock = lock = None
7021 wlock = lock = None
7047 try:
7022 try:
7048 wlock = repo.wlock()
7023 wlock = repo.wlock()
7049 lock = repo.lock()
7024 lock = repo.lock()
7050 rev_ = "."
7025 rev_ = "."
7051 names = [t.strip() for t in (name1,) + names]
7026 names = [t.strip() for t in (name1,) + names]
7052 if len(names) != len(set(names)):
7027 if len(names) != len(set(names)):
7053 raise error.Abort(_('tag names must be unique'))
7028 raise error.Abort(_('tag names must be unique'))
7054 for n in names:
7029 for n in names:
7055 scmutil.checknewlabel(repo, n, 'tag')
7030 scmutil.checknewlabel(repo, n, 'tag')
7056 if not n:
7031 if not n:
7057 raise error.Abort(_('tag names cannot consist entirely of '
7032 raise error.Abort(_('tag names cannot consist entirely of '
7058 'whitespace'))
7033 'whitespace'))
7059 if opts.get('rev') and opts.get('remove'):
7034 if opts.get('rev') and opts.get('remove'):
7060 raise error.Abort(_("--rev and --remove are incompatible"))
7035 raise error.Abort(_("--rev and --remove are incompatible"))
7061 if opts.get('rev'):
7036 if opts.get('rev'):
7062 rev_ = opts['rev']
7037 rev_ = opts['rev']
7063 message = opts.get('message')
7038 message = opts.get('message')
7064 if opts.get('remove'):
7039 if opts.get('remove'):
7065 if opts.get('local'):
7040 if opts.get('local'):
7066 expectedtype = 'local'
7041 expectedtype = 'local'
7067 else:
7042 else:
7068 expectedtype = 'global'
7043 expectedtype = 'global'
7069
7044
7070 for n in names:
7045 for n in names:
7071 if not repo.tagtype(n):
7046 if not repo.tagtype(n):
7072 raise error.Abort(_("tag '%s' does not exist") % n)
7047 raise error.Abort(_("tag '%s' does not exist") % n)
7073 if repo.tagtype(n) != expectedtype:
7048 if repo.tagtype(n) != expectedtype:
7074 if expectedtype == 'global':
7049 if expectedtype == 'global':
7075 raise error.Abort(_("tag '%s' is not a global tag") % n)
7050 raise error.Abort(_("tag '%s' is not a global tag") % n)
7076 else:
7051 else:
7077 raise error.Abort(_("tag '%s' is not a local tag") % n)
7052 raise error.Abort(_("tag '%s' is not a local tag") % n)
7078 rev_ = 'null'
7053 rev_ = 'null'
7079 if not message:
7054 if not message:
7080 # we don't translate commit messages
7055 # we don't translate commit messages
7081 message = 'Removed tag %s' % ', '.join(names)
7056 message = 'Removed tag %s' % ', '.join(names)
7082 elif not opts.get('force'):
7057 elif not opts.get('force'):
7083 for n in names:
7058 for n in names:
7084 if n in repo.tags():
7059 if n in repo.tags():
7085 raise error.Abort(_("tag '%s' already exists "
7060 raise error.Abort(_("tag '%s' already exists "
7086 "(use -f to force)") % n)
7061 "(use -f to force)") % n)
7087 if not opts.get('local'):
7062 if not opts.get('local'):
7088 p1, p2 = repo.dirstate.parents()
7063 p1, p2 = repo.dirstate.parents()
7089 if p2 != nullid:
7064 if p2 != nullid:
7090 raise error.Abort(_('uncommitted merge'))
7065 raise error.Abort(_('uncommitted merge'))
7091 bheads = repo.branchheads()
7066 bheads = repo.branchheads()
7092 if not opts.get('force') and bheads and p1 not in bheads:
7067 if not opts.get('force') and bheads and p1 not in bheads:
7093 raise error.Abort(_('not at a branch head (use -f to force)'))
7068 raise error.Abort(_('not at a branch head (use -f to force)'))
7094 r = scmutil.revsingle(repo, rev_).node()
7069 r = scmutil.revsingle(repo, rev_).node()
7095
7070
7096 if not message:
7071 if not message:
7097 # we don't translate commit messages
7072 # we don't translate commit messages
7098 message = ('Added tag %s for changeset %s' %
7073 message = ('Added tag %s for changeset %s' %
7099 (', '.join(names), short(r)))
7074 (', '.join(names), short(r)))
7100
7075
7101 date = opts.get('date')
7076 date = opts.get('date')
7102 if date:
7077 if date:
7103 date = util.parsedate(date)
7078 date = util.parsedate(date)
7104
7079
7105 if opts.get('remove'):
7080 if opts.get('remove'):
7106 editform = 'tag.remove'
7081 editform = 'tag.remove'
7107 else:
7082 else:
7108 editform = 'tag.add'
7083 editform = 'tag.add'
7109 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7084 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7110
7085
7111 # don't allow tagging the null rev
7086 # don't allow tagging the null rev
7112 if (not opts.get('remove') and
7087 if (not opts.get('remove') and
7113 scmutil.revsingle(repo, rev_).rev() == nullrev):
7088 scmutil.revsingle(repo, rev_).rev() == nullrev):
7114 raise error.Abort(_("cannot tag null revision"))
7089 raise error.Abort(_("cannot tag null revision"))
7115
7090
7116 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7091 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
7117 editor=editor)
7092 editor=editor)
7118 finally:
7093 finally:
7119 release(lock, wlock)
7094 release(lock, wlock)
7120
7095
7121 @command('tags', formatteropts, '')
7096 @command('tags', formatteropts, '')
7122 def tags(ui, repo, **opts):
7097 def tags(ui, repo, **opts):
7123 """list repository tags
7098 """list repository tags
7124
7099
7125 This lists both regular and local tags. When the -v/--verbose
7100 This lists both regular and local tags. When the -v/--verbose
7126 switch is used, a third column "local" is printed for local tags.
7101 switch is used, a third column "local" is printed for local tags.
7127 When the -q/--quiet switch is used, only the tag name is printed.
7102 When the -q/--quiet switch is used, only the tag name is printed.
7128
7103
7129 Returns 0 on success.
7104 Returns 0 on success.
7130 """
7105 """
7131
7106
7132 fm = ui.formatter('tags', opts)
7107 fm = ui.formatter('tags', opts)
7133 hexfunc = fm.hexfunc
7108 hexfunc = fm.hexfunc
7134 tagtype = ""
7109 tagtype = ""
7135
7110
7136 for t, n in reversed(repo.tagslist()):
7111 for t, n in reversed(repo.tagslist()):
7137 hn = hexfunc(n)
7112 hn = hexfunc(n)
7138 label = 'tags.normal'
7113 label = 'tags.normal'
7139 tagtype = ''
7114 tagtype = ''
7140 if repo.tagtype(t) == 'local':
7115 if repo.tagtype(t) == 'local':
7141 label = 'tags.local'
7116 label = 'tags.local'
7142 tagtype = 'local'
7117 tagtype = 'local'
7143
7118
7144 fm.startitem()
7119 fm.startitem()
7145 fm.write('tag', '%s', t, label=label)
7120 fm.write('tag', '%s', t, label=label)
7146 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7121 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7147 fm.condwrite(not ui.quiet, 'rev node', fmt,
7122 fm.condwrite(not ui.quiet, 'rev node', fmt,
7148 repo.changelog.rev(n), hn, label=label)
7123 repo.changelog.rev(n), hn, label=label)
7149 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7124 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7150 tagtype, label=label)
7125 tagtype, label=label)
7151 fm.plain('\n')
7126 fm.plain('\n')
7152 fm.end()
7127 fm.end()
7153
7128
7154 @command('tip',
7129 @command('tip',
7155 [('p', 'patch', None, _('show patch')),
7130 [('p', 'patch', None, _('show patch')),
7156 ('g', 'git', None, _('use git extended diff format')),
7131 ('g', 'git', None, _('use git extended diff format')),
7157 ] + templateopts,
7132 ] + templateopts,
7158 _('[-p] [-g]'))
7133 _('[-p] [-g]'))
7159 def tip(ui, repo, **opts):
7134 def tip(ui, repo, **opts):
7160 """show the tip revision (DEPRECATED)
7135 """show the tip revision (DEPRECATED)
7161
7136
7162 The tip revision (usually just called the tip) is the changeset
7137 The tip revision (usually just called the tip) is the changeset
7163 most recently added to the repository (and therefore the most
7138 most recently added to the repository (and therefore the most
7164 recently changed head).
7139 recently changed head).
7165
7140
7166 If you have just made a commit, that commit will be the tip. If
7141 If you have just made a commit, that commit will be the tip. If
7167 you have just pulled changes from another repository, the tip of
7142 you have just pulled changes from another repository, the tip of
7168 that repository becomes the current tip. The "tip" tag is special
7143 that repository becomes the current tip. The "tip" tag is special
7169 and cannot be renamed or assigned to a different changeset.
7144 and cannot be renamed or assigned to a different changeset.
7170
7145
7171 This command is deprecated, please use :hg:`heads` instead.
7146 This command is deprecated, please use :hg:`heads` instead.
7172
7147
7173 Returns 0 on success.
7148 Returns 0 on success.
7174 """
7149 """
7175 displayer = cmdutil.show_changeset(ui, repo, opts)
7150 displayer = cmdutil.show_changeset(ui, repo, opts)
7176 displayer.show(repo['tip'])
7151 displayer.show(repo['tip'])
7177 displayer.close()
7152 displayer.close()
7178
7153
7179 @command('unbundle',
7154 @command('unbundle',
7180 [('u', 'update', None,
7155 [('u', 'update', None,
7181 _('update to new branch head if changesets were unbundled'))],
7156 _('update to new branch head if changesets were unbundled'))],
7182 _('[-u] FILE...'))
7157 _('[-u] FILE...'))
7183 def unbundle(ui, repo, fname1, *fnames, **opts):
7158 def unbundle(ui, repo, fname1, *fnames, **opts):
7184 """apply one or more changegroup files
7159 """apply one or more changegroup files
7185
7160
7186 Apply one or more compressed changegroup files generated by the
7161 Apply one or more compressed changegroup files generated by the
7187 bundle command.
7162 bundle command.
7188
7163
7189 Returns 0 on success, 1 if an update has unresolved files.
7164 Returns 0 on success, 1 if an update has unresolved files.
7190 """
7165 """
7191 fnames = (fname1,) + fnames
7166 fnames = (fname1,) + fnames
7192
7167
7193 with repo.lock():
7168 with repo.lock():
7194 for fname in fnames:
7169 for fname in fnames:
7195 f = hg.openpath(ui, fname)
7170 f = hg.openpath(ui, fname)
7196 gen = exchange.readbundle(ui, f, fname)
7171 gen = exchange.readbundle(ui, f, fname)
7197 if isinstance(gen, bundle2.unbundle20):
7172 if isinstance(gen, bundle2.unbundle20):
7198 tr = repo.transaction('unbundle')
7173 tr = repo.transaction('unbundle')
7199 try:
7174 try:
7200 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7175 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7201 url='bundle:' + fname)
7176 url='bundle:' + fname)
7202 tr.close()
7177 tr.close()
7203 except error.BundleUnknownFeatureError as exc:
7178 except error.BundleUnknownFeatureError as exc:
7204 raise error.Abort(_('%s: unknown bundle feature, %s')
7179 raise error.Abort(_('%s: unknown bundle feature, %s')
7205 % (fname, exc),
7180 % (fname, exc),
7206 hint=_("see https://mercurial-scm.org/"
7181 hint=_("see https://mercurial-scm.org/"
7207 "wiki/BundleFeature for more "
7182 "wiki/BundleFeature for more "
7208 "information"))
7183 "information"))
7209 finally:
7184 finally:
7210 if tr:
7185 if tr:
7211 tr.release()
7186 tr.release()
7212 changes = [r.get('return', 0)
7187 changes = [r.get('return', 0)
7213 for r in op.records['changegroup']]
7188 for r in op.records['changegroup']]
7214 modheads = changegroup.combineresults(changes)
7189 modheads = changegroup.combineresults(changes)
7215 elif isinstance(gen, streamclone.streamcloneapplier):
7190 elif isinstance(gen, streamclone.streamcloneapplier):
7216 raise error.Abort(
7191 raise error.Abort(
7217 _('packed bundles cannot be applied with '
7192 _('packed bundles cannot be applied with '
7218 '"hg unbundle"'),
7193 '"hg unbundle"'),
7219 hint=_('use "hg debugapplystreamclonebundle"'))
7194 hint=_('use "hg debugapplystreamclonebundle"'))
7220 else:
7195 else:
7221 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7196 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7222
7197
7223 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7198 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7224
7199
7225 @command('^update|up|checkout|co',
7200 @command('^update|up|checkout|co',
7226 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7201 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7227 ('c', 'check', None, _('require clean working directory')),
7202 ('c', 'check', None, _('require clean working directory')),
7228 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7203 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7229 ('r', 'rev', '', _('revision'), _('REV'))
7204 ('r', 'rev', '', _('revision'), _('REV'))
7230 ] + mergetoolopts,
7205 ] + mergetoolopts,
7231 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7206 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7232 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7207 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7233 tool=None):
7208 tool=None):
7234 """update working directory (or switch revisions)
7209 """update working directory (or switch revisions)
7235
7210
7236 Update the repository's working directory to the specified
7211 Update the repository's working directory to the specified
7237 changeset. If no changeset is specified, update to the tip of the
7212 changeset. If no changeset is specified, update to the tip of the
7238 current named branch and move the active bookmark (see :hg:`help
7213 current named branch and move the active bookmark (see :hg:`help
7239 bookmarks`).
7214 bookmarks`).
7240
7215
7241 Update sets the working directory's parent revision to the specified
7216 Update sets the working directory's parent revision to the specified
7242 changeset (see :hg:`help parents`).
7217 changeset (see :hg:`help parents`).
7243
7218
7244 If the changeset is not a descendant or ancestor of the working
7219 If the changeset is not a descendant or ancestor of the working
7245 directory's parent, the update is aborted. With the -c/--check
7220 directory's parent, the update is aborted. With the -c/--check
7246 option, the working directory is checked for uncommitted changes; if
7221 option, the working directory is checked for uncommitted changes; if
7247 none are found, the working directory is updated to the specified
7222 none are found, the working directory is updated to the specified
7248 changeset.
7223 changeset.
7249
7224
7250 .. container:: verbose
7225 .. container:: verbose
7251
7226
7252 The following rules apply when the working directory contains
7227 The following rules apply when the working directory contains
7253 uncommitted changes:
7228 uncommitted changes:
7254
7229
7255 1. If neither -c/--check nor -C/--clean is specified, and if
7230 1. If neither -c/--check nor -C/--clean is specified, and if
7256 the requested changeset is an ancestor or descendant of
7231 the requested changeset is an ancestor or descendant of
7257 the working directory's parent, the uncommitted changes
7232 the working directory's parent, the uncommitted changes
7258 are merged into the requested changeset and the merged
7233 are merged into the requested changeset and the merged
7259 result is left uncommitted. If the requested changeset is
7234 result is left uncommitted. If the requested changeset is
7260 not an ancestor or descendant (that is, it is on another
7235 not an ancestor or descendant (that is, it is on another
7261 branch), the update is aborted and the uncommitted changes
7236 branch), the update is aborted and the uncommitted changes
7262 are preserved.
7237 are preserved.
7263
7238
7264 2. With the -c/--check option, the update is aborted and the
7239 2. With the -c/--check option, the update is aborted and the
7265 uncommitted changes are preserved.
7240 uncommitted changes are preserved.
7266
7241
7267 3. With the -C/--clean option, uncommitted changes are discarded and
7242 3. With the -C/--clean option, uncommitted changes are discarded and
7268 the working directory is updated to the requested changeset.
7243 the working directory is updated to the requested changeset.
7269
7244
7270 To cancel an uncommitted merge (and lose your changes), use
7245 To cancel an uncommitted merge (and lose your changes), use
7271 :hg:`update --clean .`.
7246 :hg:`update --clean .`.
7272
7247
7273 Use null as the changeset to remove the working directory (like
7248 Use null as the changeset to remove the working directory (like
7274 :hg:`clone -U`).
7249 :hg:`clone -U`).
7275
7250
7276 If you want to revert just one file to an older revision, use
7251 If you want to revert just one file to an older revision, use
7277 :hg:`revert [-r REV] NAME`.
7252 :hg:`revert [-r REV] NAME`.
7278
7253
7279 See :hg:`help dates` for a list of formats valid for -d/--date.
7254 See :hg:`help dates` for a list of formats valid for -d/--date.
7280
7255
7281 Returns 0 on success, 1 if there are unresolved files.
7256 Returns 0 on success, 1 if there are unresolved files.
7282 """
7257 """
7283 if rev and node:
7258 if rev and node:
7284 raise error.Abort(_("please specify just one revision"))
7259 raise error.Abort(_("please specify just one revision"))
7285
7260
7286 if rev is None or rev == '':
7261 if rev is None or rev == '':
7287 rev = node
7262 rev = node
7288
7263
7289 if date and rev is not None:
7264 if date and rev is not None:
7290 raise error.Abort(_("you can't specify a revision and a date"))
7265 raise error.Abort(_("you can't specify a revision and a date"))
7291
7266
7292 if check and clean:
7267 if check and clean:
7293 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7268 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7294
7269
7295 with repo.wlock():
7270 with repo.wlock():
7296 cmdutil.clearunfinished(repo)
7271 cmdutil.clearunfinished(repo)
7297
7272
7298 if date:
7273 if date:
7299 rev = cmdutil.finddate(ui, repo, date)
7274 rev = cmdutil.finddate(ui, repo, date)
7300
7275
7301 # if we defined a bookmark, we have to remember the original name
7276 # if we defined a bookmark, we have to remember the original name
7302 brev = rev
7277 brev = rev
7303 rev = scmutil.revsingle(repo, rev, rev).rev()
7278 rev = scmutil.revsingle(repo, rev, rev).rev()
7304
7279
7305 if check:
7280 if check:
7306 cmdutil.bailifchanged(repo, merge=False)
7281 cmdutil.bailifchanged(repo, merge=False)
7307
7282
7308 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7283 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7309
7284
7310 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7285 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7311
7286
7312 @command('verify', [])
7287 @command('verify', [])
7313 def verify(ui, repo):
7288 def verify(ui, repo):
7314 """verify the integrity of the repository
7289 """verify the integrity of the repository
7315
7290
7316 Verify the integrity of the current repository.
7291 Verify the integrity of the current repository.
7317
7292
7318 This will perform an extensive check of the repository's
7293 This will perform an extensive check of the repository's
7319 integrity, validating the hashes and checksums of each entry in
7294 integrity, validating the hashes and checksums of each entry in
7320 the changelog, manifest, and tracked files, as well as the
7295 the changelog, manifest, and tracked files, as well as the
7321 integrity of their crosslinks and indices.
7296 integrity of their crosslinks and indices.
7322
7297
7323 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7298 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7324 for more information about recovery from corruption of the
7299 for more information about recovery from corruption of the
7325 repository.
7300 repository.
7326
7301
7327 Returns 0 on success, 1 if errors are encountered.
7302 Returns 0 on success, 1 if errors are encountered.
7328 """
7303 """
7329 return hg.verify(repo)
7304 return hg.verify(repo)
7330
7305
7331 @command('version', [] + formatteropts, norepo=True)
7306 @command('version', [] + formatteropts, norepo=True)
7332 def version_(ui, **opts):
7307 def version_(ui, **opts):
7333 """output version and copyright information"""
7308 """output version and copyright information"""
7334 fm = ui.formatter("version", opts)
7309 fm = ui.formatter("version", opts)
7335 fm.startitem()
7310 fm.startitem()
7336 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7311 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7337 util.version())
7312 util.version())
7338 license = _(
7313 license = _(
7339 "(see https://mercurial-scm.org for more information)\n"
7314 "(see https://mercurial-scm.org for more information)\n"
7340 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7315 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7341 "This is free software; see the source for copying conditions. "
7316 "This is free software; see the source for copying conditions. "
7342 "There is NO\nwarranty; "
7317 "There is NO\nwarranty; "
7343 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7318 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7344 )
7319 )
7345 if not ui.quiet:
7320 if not ui.quiet:
7346 fm.plain(license)
7321 fm.plain(license)
7347
7322
7348 if ui.verbose:
7323 if ui.verbose:
7349 fm.plain(_("\nEnabled extensions:\n\n"))
7324 fm.plain(_("\nEnabled extensions:\n\n"))
7350 # format names and versions into columns
7325 # format names and versions into columns
7351 names = []
7326 names = []
7352 vers = []
7327 vers = []
7353 isinternals = []
7328 isinternals = []
7354 for name, module in extensions.extensions():
7329 for name, module in extensions.extensions():
7355 names.append(name)
7330 names.append(name)
7356 vers.append(extensions.moduleversion(module) or None)
7331 vers.append(extensions.moduleversion(module) or None)
7357 isinternals.append(extensions.ismoduleinternal(module))
7332 isinternals.append(extensions.ismoduleinternal(module))
7358 fn = fm.nested("extensions")
7333 fn = fm.nested("extensions")
7359 if names:
7334 if names:
7360 namefmt = " %%-%ds " % max(len(n) for n in names)
7335 namefmt = " %%-%ds " % max(len(n) for n in names)
7361 places = [_("external"), _("internal")]
7336 places = [_("external"), _("internal")]
7362 for n, v, p in zip(names, vers, isinternals):
7337 for n, v, p in zip(names, vers, isinternals):
7363 fn.startitem()
7338 fn.startitem()
7364 fn.condwrite(ui.verbose, "name", namefmt, n)
7339 fn.condwrite(ui.verbose, "name", namefmt, n)
7365 if ui.verbose:
7340 if ui.verbose:
7366 fn.plain("%s " % places[p])
7341 fn.plain("%s " % places[p])
7367 fn.data(bundled=p)
7342 fn.data(bundled=p)
7368 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7343 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7369 if ui.verbose:
7344 if ui.verbose:
7370 fn.plain("\n")
7345 fn.plain("\n")
7371 fn.end()
7346 fn.end()
7372 fm.end()
7347 fm.end()
7373
7348
7374 def loadcmdtable(ui, name, cmdtable):
7349 def loadcmdtable(ui, name, cmdtable):
7375 """Load command functions from specified cmdtable
7350 """Load command functions from specified cmdtable
7376 """
7351 """
7377 overrides = [cmd for cmd in cmdtable if cmd in table]
7352 overrides = [cmd for cmd in cmdtable if cmd in table]
7378 if overrides:
7353 if overrides:
7379 ui.warn(_("extension '%s' overrides commands: %s\n")
7354 ui.warn(_("extension '%s' overrides commands: %s\n")
7380 % (name, " ".join(overrides)))
7355 % (name, " ".join(overrides)))
7381 table.update(cmdtable)
7356 table.update(cmdtable)
@@ -1,281 +1,307 b''
1 # changelog bisection for mercurial
1 # changelog bisection for mercurial
2 #
2 #
3 # Copyright 2007 Matt Mackall
3 # Copyright 2007 Matt Mackall
4 # Copyright 2005, 2006 Benoit Boissinot <benoit.boissinot@ens-lyon.org>
4 # Copyright 2005, 2006 Benoit Boissinot <benoit.boissinot@ens-lyon.org>
5 #
5 #
6 # Inspired by git bisect, extension skeleton taken from mq.py.
6 # Inspired by git bisect, extension skeleton taken from mq.py.
7 #
7 #
8 # This software may be used and distributed according to the terms of the
8 # This software may be used and distributed according to the terms of the
9 # GNU General Public License version 2 or any later version.
9 # GNU General Public License version 2 or any later version.
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12
12
13 import collections
13 import collections
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 short,
18 short,
19 )
19 )
20 from . import (
20 from . import (
21 error,
21 error,
22 )
22 )
23
23
24 def bisect(changelog, state):
24 def bisect(changelog, state):
25 """find the next node (if any) for testing during a bisect search.
25 """find the next node (if any) for testing during a bisect search.
26 returns a (nodes, number, good) tuple.
26 returns a (nodes, number, good) tuple.
27
27
28 'nodes' is the final result of the bisect if 'number' is 0.
28 'nodes' is the final result of the bisect if 'number' is 0.
29 Otherwise 'number' indicates the remaining possible candidates for
29 Otherwise 'number' indicates the remaining possible candidates for
30 the search and 'nodes' contains the next bisect target.
30 the search and 'nodes' contains the next bisect target.
31 'good' is True if bisect is searching for a first good changeset, False
31 'good' is True if bisect is searching for a first good changeset, False
32 if searching for a first bad one.
32 if searching for a first bad one.
33 """
33 """
34
34
35 clparents = changelog.parentrevs
35 clparents = changelog.parentrevs
36 skip = set([changelog.rev(n) for n in state['skip']])
36 skip = set([changelog.rev(n) for n in state['skip']])
37
37
38 def buildancestors(bad, good):
38 def buildancestors(bad, good):
39 # only the earliest bad revision matters
39 # only the earliest bad revision matters
40 badrev = min([changelog.rev(n) for n in bad])
40 badrev = min([changelog.rev(n) for n in bad])
41 goodrevs = [changelog.rev(n) for n in good]
41 goodrevs = [changelog.rev(n) for n in good]
42 goodrev = min(goodrevs)
42 goodrev = min(goodrevs)
43 # build visit array
43 # build visit array
44 ancestors = [None] * (len(changelog) + 1) # an extra for [-1]
44 ancestors = [None] * (len(changelog) + 1) # an extra for [-1]
45
45
46 # set nodes descended from goodrevs
46 # set nodes descended from goodrevs
47 for rev in goodrevs:
47 for rev in goodrevs:
48 ancestors[rev] = []
48 ancestors[rev] = []
49 for rev in changelog.revs(goodrev + 1):
49 for rev in changelog.revs(goodrev + 1):
50 for prev in clparents(rev):
50 for prev in clparents(rev):
51 if ancestors[prev] == []:
51 if ancestors[prev] == []:
52 ancestors[rev] = []
52 ancestors[rev] = []
53
53
54 # clear good revs from array
54 # clear good revs from array
55 for rev in goodrevs:
55 for rev in goodrevs:
56 ancestors[rev] = None
56 ancestors[rev] = None
57 for rev in changelog.revs(len(changelog), goodrev):
57 for rev in changelog.revs(len(changelog), goodrev):
58 if ancestors[rev] is None:
58 if ancestors[rev] is None:
59 for prev in clparents(rev):
59 for prev in clparents(rev):
60 ancestors[prev] = None
60 ancestors[prev] = None
61
61
62 if ancestors[badrev] is None:
62 if ancestors[badrev] is None:
63 return badrev, None
63 return badrev, None
64 return badrev, ancestors
64 return badrev, ancestors
65
65
66 good = False
66 good = False
67 badrev, ancestors = buildancestors(state['bad'], state['good'])
67 badrev, ancestors = buildancestors(state['bad'], state['good'])
68 if not ancestors: # looking for bad to good transition?
68 if not ancestors: # looking for bad to good transition?
69 good = True
69 good = True
70 badrev, ancestors = buildancestors(state['good'], state['bad'])
70 badrev, ancestors = buildancestors(state['good'], state['bad'])
71 bad = changelog.node(badrev)
71 bad = changelog.node(badrev)
72 if not ancestors: # now we're confused
72 if not ancestors: # now we're confused
73 if (len(state['bad']) == 1 and len(state['good']) == 1 and
73 if (len(state['bad']) == 1 and len(state['good']) == 1 and
74 state['bad'] != state['good']):
74 state['bad'] != state['good']):
75 raise error.Abort(_("starting revisions are not directly related"))
75 raise error.Abort(_("starting revisions are not directly related"))
76 raise error.Abort(_("inconsistent state, %s:%s is good and bad")
76 raise error.Abort(_("inconsistent state, %s:%s is good and bad")
77 % (badrev, short(bad)))
77 % (badrev, short(bad)))
78
78
79 # build children dict
79 # build children dict
80 children = {}
80 children = {}
81 visit = collections.deque([badrev])
81 visit = collections.deque([badrev])
82 candidates = []
82 candidates = []
83 while visit:
83 while visit:
84 rev = visit.popleft()
84 rev = visit.popleft()
85 if ancestors[rev] == []:
85 if ancestors[rev] == []:
86 candidates.append(rev)
86 candidates.append(rev)
87 for prev in clparents(rev):
87 for prev in clparents(rev):
88 if prev != -1:
88 if prev != -1:
89 if prev in children:
89 if prev in children:
90 children[prev].append(rev)
90 children[prev].append(rev)
91 else:
91 else:
92 children[prev] = [rev]
92 children[prev] = [rev]
93 visit.append(prev)
93 visit.append(prev)
94
94
95 candidates.sort()
95 candidates.sort()
96 # have we narrowed it down to one entry?
96 # have we narrowed it down to one entry?
97 # or have all other possible candidates besides 'bad' have been skipped?
97 # or have all other possible candidates besides 'bad' have been skipped?
98 tot = len(candidates)
98 tot = len(candidates)
99 unskipped = [c for c in candidates if (c not in skip) and (c != badrev)]
99 unskipped = [c for c in candidates if (c not in skip) and (c != badrev)]
100 if tot == 1 or not unskipped:
100 if tot == 1 or not unskipped:
101 return ([changelog.node(rev) for rev in candidates], 0, good)
101 return ([changelog.node(rev) for rev in candidates], 0, good)
102 perfect = tot // 2
102 perfect = tot // 2
103
103
104 # find the best node to test
104 # find the best node to test
105 best_rev = None
105 best_rev = None
106 best_len = -1
106 best_len = -1
107 poison = set()
107 poison = set()
108 for rev in candidates:
108 for rev in candidates:
109 if rev in poison:
109 if rev in poison:
110 # poison children
110 # poison children
111 poison.update(children.get(rev, []))
111 poison.update(children.get(rev, []))
112 continue
112 continue
113
113
114 a = ancestors[rev] or [rev]
114 a = ancestors[rev] or [rev]
115 ancestors[rev] = None
115 ancestors[rev] = None
116
116
117 x = len(a) # number of ancestors
117 x = len(a) # number of ancestors
118 y = tot - x # number of non-ancestors
118 y = tot - x # number of non-ancestors
119 value = min(x, y) # how good is this test?
119 value = min(x, y) # how good is this test?
120 if value > best_len and rev not in skip:
120 if value > best_len and rev not in skip:
121 best_len = value
121 best_len = value
122 best_rev = rev
122 best_rev = rev
123 if value == perfect: # found a perfect candidate? quit early
123 if value == perfect: # found a perfect candidate? quit early
124 break
124 break
125
125
126 if y < perfect and rev not in skip: # all downhill from here?
126 if y < perfect and rev not in skip: # all downhill from here?
127 # poison children
127 # poison children
128 poison.update(children.get(rev, []))
128 poison.update(children.get(rev, []))
129 continue
129 continue
130
130
131 for c in children.get(rev, []):
131 for c in children.get(rev, []):
132 if ancestors[c]:
132 if ancestors[c]:
133 ancestors[c] = list(set(ancestors[c] + a))
133 ancestors[c] = list(set(ancestors[c] + a))
134 else:
134 else:
135 ancestors[c] = a + [c]
135 ancestors[c] = a + [c]
136
136
137 assert best_rev is not None
137 assert best_rev is not None
138 best_node = changelog.node(best_rev)
138 best_node = changelog.node(best_rev)
139
139
140 return ([best_node], tot, good)
140 return ([best_node], tot, good)
141
141
142 def extendrange(repo, state, nodes, good):
142 def extendrange(repo, state, nodes, good):
143 # bisect is incomplete when it ends on a merge node and
143 # bisect is incomplete when it ends on a merge node and
144 # one of the parent was not checked.
144 # one of the parent was not checked.
145 parents = repo[nodes[0]].parents()
145 parents = repo[nodes[0]].parents()
146 if len(parents) > 1:
146 if len(parents) > 1:
147 if good:
147 if good:
148 side = state['bad']
148 side = state['bad']
149 else:
149 else:
150 side = state['good']
150 side = state['good']
151 num = len(set(i.node() for i in parents) & set(side))
151 num = len(set(i.node() for i in parents) & set(side))
152 if num == 1:
152 if num == 1:
153 return parents[0].ancestor(parents[1])
153 return parents[0].ancestor(parents[1])
154 return None
154 return None
155
155
156 def load_state(repo):
156 def load_state(repo):
157 state = {'current': [], 'good': [], 'bad': [], 'skip': []}
157 state = {'current': [], 'good': [], 'bad': [], 'skip': []}
158 for l in repo.vfs.tryreadlines("bisect.state"):
158 for l in repo.vfs.tryreadlines("bisect.state"):
159 kind, node = l[:-1].split()
159 kind, node = l[:-1].split()
160 node = repo.lookup(node)
160 node = repo.lookup(node)
161 if kind not in state:
161 if kind not in state:
162 raise error.Abort(_("unknown bisect kind %s") % kind)
162 raise error.Abort(_("unknown bisect kind %s") % kind)
163 state[kind].append(node)
163 state[kind].append(node)
164 return state
164 return state
165
165
166
166
167 def save_state(repo, state):
167 def save_state(repo, state):
168 f = repo.vfs("bisect.state", "w", atomictemp=True)
168 f = repo.vfs("bisect.state", "w", atomictemp=True)
169 with repo.wlock():
169 with repo.wlock():
170 for kind in sorted(state):
170 for kind in sorted(state):
171 for node in state[kind]:
171 for node in state[kind]:
172 f.write("%s %s\n" % (kind, hex(node)))
172 f.write("%s %s\n" % (kind, hex(node)))
173 f.close()
173 f.close()
174
174
175 def resetstate(repo):
175 def resetstate(repo):
176 """remove any bisect state from the repository"""
176 """remove any bisect state from the repository"""
177 if repo.vfs.exists("bisect.state"):
177 if repo.vfs.exists("bisect.state"):
178 repo.vfs.unlink("bisect.state")
178 repo.vfs.unlink("bisect.state")
179
179
180 def get(repo, status):
180 def get(repo, status):
181 """
181 """
182 Return a list of revision(s) that match the given status:
182 Return a list of revision(s) that match the given status:
183
183
184 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
184 - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
185 - ``goods``, ``bads`` : csets topologically good/bad
185 - ``goods``, ``bads`` : csets topologically good/bad
186 - ``range`` : csets taking part in the bisection
186 - ``range`` : csets taking part in the bisection
187 - ``pruned`` : csets that are goods, bads or skipped
187 - ``pruned`` : csets that are goods, bads or skipped
188 - ``untested`` : csets whose fate is yet unknown
188 - ``untested`` : csets whose fate is yet unknown
189 - ``ignored`` : csets ignored due to DAG topology
189 - ``ignored`` : csets ignored due to DAG topology
190 - ``current`` : the cset currently being bisected
190 - ``current`` : the cset currently being bisected
191 """
191 """
192 state = load_state(repo)
192 state = load_state(repo)
193 if status in ('good', 'bad', 'skip', 'current'):
193 if status in ('good', 'bad', 'skip', 'current'):
194 return map(repo.changelog.rev, state[status])
194 return map(repo.changelog.rev, state[status])
195 else:
195 else:
196 # In the following sets, we do *not* call 'bisect()' with more
196 # In the following sets, we do *not* call 'bisect()' with more
197 # than one level of recursion, because that can be very, very
197 # than one level of recursion, because that can be very, very
198 # time consuming. Instead, we always develop the expression as
198 # time consuming. Instead, we always develop the expression as
199 # much as possible.
199 # much as possible.
200
200
201 # 'range' is all csets that make the bisection:
201 # 'range' is all csets that make the bisection:
202 # - have a good ancestor and a bad descendant, or conversely
202 # - have a good ancestor and a bad descendant, or conversely
203 # that's because the bisection can go either way
203 # that's because the bisection can go either way
204 range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
204 range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
205
205
206 _t = repo.revs('bisect(good)::bisect(bad)')
206 _t = repo.revs('bisect(good)::bisect(bad)')
207 # The sets of topologically good or bad csets
207 # The sets of topologically good or bad csets
208 if len(_t) == 0:
208 if len(_t) == 0:
209 # Goods are topologically after bads
209 # Goods are topologically after bads
210 goods = 'bisect(good)::' # Pruned good csets
210 goods = 'bisect(good)::' # Pruned good csets
211 bads = '::bisect(bad)' # Pruned bad csets
211 bads = '::bisect(bad)' # Pruned bad csets
212 else:
212 else:
213 # Goods are topologically before bads
213 # Goods are topologically before bads
214 goods = '::bisect(good)' # Pruned good csets
214 goods = '::bisect(good)' # Pruned good csets
215 bads = 'bisect(bad)::' # Pruned bad csets
215 bads = 'bisect(bad)::' # Pruned bad csets
216
216
217 # 'pruned' is all csets whose fate is already known: good, bad, skip
217 # 'pruned' is all csets whose fate is already known: good, bad, skip
218 skips = 'bisect(skip)' # Pruned skipped csets
218 skips = 'bisect(skip)' # Pruned skipped csets
219 pruned = '( (%s) | (%s) | (%s) )' % (goods, bads, skips)
219 pruned = '( (%s) | (%s) | (%s) )' % (goods, bads, skips)
220
220
221 # 'untested' is all cset that are- in 'range', but not in 'pruned'
221 # 'untested' is all cset that are- in 'range', but not in 'pruned'
222 untested = '( (%s) - (%s) )' % (range, pruned)
222 untested = '( (%s) - (%s) )' % (range, pruned)
223
223
224 # 'ignored' is all csets that were not used during the bisection
224 # 'ignored' is all csets that were not used during the bisection
225 # due to DAG topology, but may however have had an impact.
225 # due to DAG topology, but may however have had an impact.
226 # E.g., a branch merged between bads and goods, but whose branch-
226 # E.g., a branch merged between bads and goods, but whose branch-
227 # point is out-side of the range.
227 # point is out-side of the range.
228 iba = '::bisect(bad) - ::bisect(good)' # Ignored bads' ancestors
228 iba = '::bisect(bad) - ::bisect(good)' # Ignored bads' ancestors
229 iga = '::bisect(good) - ::bisect(bad)' # Ignored goods' ancestors
229 iga = '::bisect(good) - ::bisect(bad)' # Ignored goods' ancestors
230 ignored = '( ( (%s) | (%s) ) - (%s) )' % (iba, iga, range)
230 ignored = '( ( (%s) | (%s) ) - (%s) )' % (iba, iga, range)
231
231
232 if status == 'range':
232 if status == 'range':
233 return repo.revs(range)
233 return repo.revs(range)
234 elif status == 'pruned':
234 elif status == 'pruned':
235 return repo.revs(pruned)
235 return repo.revs(pruned)
236 elif status == 'untested':
236 elif status == 'untested':
237 return repo.revs(untested)
237 return repo.revs(untested)
238 elif status == 'ignored':
238 elif status == 'ignored':
239 return repo.revs(ignored)
239 return repo.revs(ignored)
240 elif status == "goods":
240 elif status == "goods":
241 return repo.revs(goods)
241 return repo.revs(goods)
242 elif status == "bads":
242 elif status == "bads":
243 return repo.revs(bads)
243 return repo.revs(bads)
244 else:
244 else:
245 raise error.ParseError(_('invalid bisect state'))
245 raise error.ParseError(_('invalid bisect state'))
246
246
247 def label(repo, node):
247 def label(repo, node):
248 rev = repo.changelog.rev(node)
248 rev = repo.changelog.rev(node)
249
249
250 # Try explicit sets
250 # Try explicit sets
251 if rev in get(repo, 'good'):
251 if rev in get(repo, 'good'):
252 # i18n: bisect changeset status
252 # i18n: bisect changeset status
253 return _('good')
253 return _('good')
254 if rev in get(repo, 'bad'):
254 if rev in get(repo, 'bad'):
255 # i18n: bisect changeset status
255 # i18n: bisect changeset status
256 return _('bad')
256 return _('bad')
257 if rev in get(repo, 'skip'):
257 if rev in get(repo, 'skip'):
258 # i18n: bisect changeset status
258 # i18n: bisect changeset status
259 return _('skipped')
259 return _('skipped')
260 if rev in get(repo, 'untested') or rev in get(repo, 'current'):
260 if rev in get(repo, 'untested') or rev in get(repo, 'current'):
261 # i18n: bisect changeset status
261 # i18n: bisect changeset status
262 return _('untested')
262 return _('untested')
263 if rev in get(repo, 'ignored'):
263 if rev in get(repo, 'ignored'):
264 # i18n: bisect changeset status
264 # i18n: bisect changeset status
265 return _('ignored')
265 return _('ignored')
266
266
267 # Try implicit sets
267 # Try implicit sets
268 if rev in get(repo, 'goods'):
268 if rev in get(repo, 'goods'):
269 # i18n: bisect changeset status
269 # i18n: bisect changeset status
270 return _('good (implicit)')
270 return _('good (implicit)')
271 if rev in get(repo, 'bads'):
271 if rev in get(repo, 'bads'):
272 # i18n: bisect changeset status
272 # i18n: bisect changeset status
273 return _('bad (implicit)')
273 return _('bad (implicit)')
274
274
275 return None
275 return None
276
276
277 def shortlabel(label):
277 def shortlabel(label):
278 if label:
278 if label:
279 return label[0].upper()
279 return label[0].upper()
280
280
281 return None
281 return None
282
283 def printresult(ui, repo, state, displayer, nodes, good):
284 if len(nodes) == 1:
285 # narrowed it down to a single revision
286 if good:
287 ui.write(_("The first good revision is:\n"))
288 else:
289 ui.write(_("The first bad revision is:\n"))
290 displayer.show(repo[nodes[0]])
291 extendnode = extendrange(repo, state, nodes, good)
292 if extendnode is not None:
293 ui.write(_('Not all ancestors of this changeset have been'
294 ' checked.\nUse bisect --extend to continue the '
295 'bisection from\nthe common ancestor, %s.\n')
296 % extendnode)
297 else:
298 # multiple possible revisions
299 if good:
300 ui.write(_("Due to skipped revisions, the first "
301 "good revision could be any of:\n"))
302 else:
303 ui.write(_("Due to skipped revisions, the first "
304 "bad revision could be any of:\n"))
305 for n in nodes:
306 displayer.show(repo[n])
307 displayer.close()
General Comments 0
You need to be logged in to leave comments. Login now