##// END OF EJS Templates
debugcommands: move 'debugbundle' in the new module
Gregory Szorc -
r30501:a87e4692 default
parent child Browse files
Show More
@@ -1,7243 +1,7175
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 string
18 import string
19 import sys
19 import sys
20 import tempfile
20 import tempfile
21 import time
21 import time
22
22
23 from .i18n import _
23 from .i18n import _
24 from .node import (
24 from .node import (
25 bin,
25 bin,
26 hex,
26 hex,
27 nullhex,
27 nullhex,
28 nullid,
28 nullid,
29 nullrev,
29 nullrev,
30 short,
30 short,
31 )
31 )
32 from . import (
32 from . import (
33 archival,
33 archival,
34 bookmarks,
34 bookmarks,
35 bundle2,
35 bundle2,
36 changegroup,
36 changegroup,
37 cmdutil,
37 cmdutil,
38 commandserver,
38 commandserver,
39 copies,
39 copies,
40 dagparser,
40 dagparser,
41 dagutil,
41 dagutil,
42 destutil,
42 destutil,
43 dirstateguard,
43 dirstateguard,
44 discovery,
44 discovery,
45 encoding,
45 encoding,
46 error,
46 error,
47 exchange,
47 exchange,
48 extensions,
48 extensions,
49 fileset,
49 fileset,
50 formatter,
50 formatter,
51 graphmod,
51 graphmod,
52 hbisect,
52 hbisect,
53 help,
53 help,
54 hg,
54 hg,
55 hgweb,
55 hgweb,
56 localrepo,
56 localrepo,
57 lock as lockmod,
57 lock as lockmod,
58 merge as mergemod,
58 merge as mergemod,
59 minirst,
59 minirst,
60 obsolete,
60 obsolete,
61 patch,
61 patch,
62 phases,
62 phases,
63 policy,
63 policy,
64 pvec,
64 pvec,
65 pycompat,
65 pycompat,
66 repair,
66 repair,
67 revlog,
67 revlog,
68 revset,
68 revset,
69 scmutil,
69 scmutil,
70 setdiscovery,
70 setdiscovery,
71 sshserver,
71 sshserver,
72 sslutil,
72 sslutil,
73 streamclone,
73 streamclone,
74 templatekw,
74 templatekw,
75 templater,
75 templater,
76 treediscovery,
76 treediscovery,
77 ui as uimod,
77 ui as uimod,
78 util,
78 util,
79 )
79 )
80
80
81 release = lockmod.release
81 release = lockmod.release
82
82
83 table = {}
83 table = {}
84
84
85 command = cmdutil.command(table)
85 command = cmdutil.command(table)
86
86
87 # label constants
87 # label constants
88 # until 3.5, bookmarks.current was the advertised name, not
88 # until 3.5, bookmarks.current was the advertised name, not
89 # bookmarks.active, so we must use both to avoid breaking old
89 # bookmarks.active, so we must use both to avoid breaking old
90 # custom styles
90 # custom styles
91 activebookmarklabel = 'bookmarks.active bookmarks.current'
91 activebookmarklabel = 'bookmarks.active bookmarks.current'
92
92
93 # common command options
93 # common command options
94
94
95 globalopts = [
95 globalopts = [
96 ('R', 'repository', '',
96 ('R', 'repository', '',
97 _('repository root directory or name of overlay bundle file'),
97 _('repository root directory or name of overlay bundle file'),
98 _('REPO')),
98 _('REPO')),
99 ('', 'cwd', '',
99 ('', 'cwd', '',
100 _('change working directory'), _('DIR')),
100 _('change working directory'), _('DIR')),
101 ('y', 'noninteractive', None,
101 ('y', 'noninteractive', None,
102 _('do not prompt, automatically pick the first choice for all prompts')),
102 _('do not prompt, automatically pick the first choice for all prompts')),
103 ('q', 'quiet', None, _('suppress output')),
103 ('q', 'quiet', None, _('suppress output')),
104 ('v', 'verbose', None, _('enable additional output')),
104 ('v', 'verbose', None, _('enable additional output')),
105 ('', 'config', [],
105 ('', 'config', [],
106 _('set/override config option (use \'section.name=value\')'),
106 _('set/override config option (use \'section.name=value\')'),
107 _('CONFIG')),
107 _('CONFIG')),
108 ('', 'debug', None, _('enable debugging output')),
108 ('', 'debug', None, _('enable debugging output')),
109 ('', 'debugger', None, _('start debugger')),
109 ('', 'debugger', None, _('start debugger')),
110 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
110 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
111 _('ENCODE')),
111 _('ENCODE')),
112 ('', 'encodingmode', encoding.encodingmode,
112 ('', 'encodingmode', encoding.encodingmode,
113 _('set the charset encoding mode'), _('MODE')),
113 _('set the charset encoding mode'), _('MODE')),
114 ('', 'traceback', None, _('always print a traceback on exception')),
114 ('', 'traceback', None, _('always print a traceback on exception')),
115 ('', 'time', None, _('time how long the command takes')),
115 ('', 'time', None, _('time how long the command takes')),
116 ('', 'profile', None, _('print command execution profile')),
116 ('', 'profile', None, _('print command execution profile')),
117 ('', 'version', None, _('output version information and exit')),
117 ('', 'version', None, _('output version information and exit')),
118 ('h', 'help', None, _('display help and exit')),
118 ('h', 'help', None, _('display help and exit')),
119 ('', 'hidden', False, _('consider hidden changesets')),
119 ('', 'hidden', False, _('consider hidden changesets')),
120 ]
120 ]
121
121
122 dryrunopts = [('n', 'dry-run', None,
122 dryrunopts = [('n', 'dry-run', None,
123 _('do not perform actions, just print output'))]
123 _('do not perform actions, just print output'))]
124
124
125 remoteopts = [
125 remoteopts = [
126 ('e', 'ssh', '',
126 ('e', 'ssh', '',
127 _('specify ssh command to use'), _('CMD')),
127 _('specify ssh command to use'), _('CMD')),
128 ('', 'remotecmd', '',
128 ('', 'remotecmd', '',
129 _('specify hg command to run on the remote side'), _('CMD')),
129 _('specify hg command to run on the remote side'), _('CMD')),
130 ('', 'insecure', None,
130 ('', 'insecure', None,
131 _('do not verify server certificate (ignoring web.cacerts config)')),
131 _('do not verify server certificate (ignoring web.cacerts config)')),
132 ]
132 ]
133
133
134 walkopts = [
134 walkopts = [
135 ('I', 'include', [],
135 ('I', 'include', [],
136 _('include names matching the given patterns'), _('PATTERN')),
136 _('include names matching the given patterns'), _('PATTERN')),
137 ('X', 'exclude', [],
137 ('X', 'exclude', [],
138 _('exclude names matching the given patterns'), _('PATTERN')),
138 _('exclude names matching the given patterns'), _('PATTERN')),
139 ]
139 ]
140
140
141 commitopts = [
141 commitopts = [
142 ('m', 'message', '',
142 ('m', 'message', '',
143 _('use text as commit message'), _('TEXT')),
143 _('use text as commit message'), _('TEXT')),
144 ('l', 'logfile', '',
144 ('l', 'logfile', '',
145 _('read commit message from file'), _('FILE')),
145 _('read commit message from file'), _('FILE')),
146 ]
146 ]
147
147
148 commitopts2 = [
148 commitopts2 = [
149 ('d', 'date', '',
149 ('d', 'date', '',
150 _('record the specified date as commit date'), _('DATE')),
150 _('record the specified date as commit date'), _('DATE')),
151 ('u', 'user', '',
151 ('u', 'user', '',
152 _('record the specified user as committer'), _('USER')),
152 _('record the specified user as committer'), _('USER')),
153 ]
153 ]
154
154
155 # hidden for now
155 # hidden for now
156 formatteropts = [
156 formatteropts = [
157 ('T', 'template', '',
157 ('T', 'template', '',
158 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
158 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
159 ]
159 ]
160
160
161 templateopts = [
161 templateopts = [
162 ('', 'style', '',
162 ('', 'style', '',
163 _('display using template map file (DEPRECATED)'), _('STYLE')),
163 _('display using template map file (DEPRECATED)'), _('STYLE')),
164 ('T', 'template', '',
164 ('T', 'template', '',
165 _('display with template'), _('TEMPLATE')),
165 _('display with template'), _('TEMPLATE')),
166 ]
166 ]
167
167
168 logopts = [
168 logopts = [
169 ('p', 'patch', None, _('show patch')),
169 ('p', 'patch', None, _('show patch')),
170 ('g', 'git', None, _('use git extended diff format')),
170 ('g', 'git', None, _('use git extended diff format')),
171 ('l', 'limit', '',
171 ('l', 'limit', '',
172 _('limit number of changes displayed'), _('NUM')),
172 _('limit number of changes displayed'), _('NUM')),
173 ('M', 'no-merges', None, _('do not show merges')),
173 ('M', 'no-merges', None, _('do not show merges')),
174 ('', 'stat', None, _('output diffstat-style summary of changes')),
174 ('', 'stat', None, _('output diffstat-style summary of changes')),
175 ('G', 'graph', None, _("show the revision DAG")),
175 ('G', 'graph', None, _("show the revision DAG")),
176 ] + templateopts
176 ] + templateopts
177
177
178 diffopts = [
178 diffopts = [
179 ('a', 'text', None, _('treat all files as text')),
179 ('a', 'text', None, _('treat all files as text')),
180 ('g', 'git', None, _('use git extended diff format')),
180 ('g', 'git', None, _('use git extended diff format')),
181 ('', 'nodates', None, _('omit dates from diff headers'))
181 ('', 'nodates', None, _('omit dates from diff headers'))
182 ]
182 ]
183
183
184 diffwsopts = [
184 diffwsopts = [
185 ('w', 'ignore-all-space', None,
185 ('w', 'ignore-all-space', None,
186 _('ignore white space when comparing lines')),
186 _('ignore white space when comparing lines')),
187 ('b', 'ignore-space-change', None,
187 ('b', 'ignore-space-change', None,
188 _('ignore changes in the amount of white space')),
188 _('ignore changes in the amount of white space')),
189 ('B', 'ignore-blank-lines', None,
189 ('B', 'ignore-blank-lines', None,
190 _('ignore changes whose lines are all blank')),
190 _('ignore changes whose lines are all blank')),
191 ]
191 ]
192
192
193 diffopts2 = [
193 diffopts2 = [
194 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
194 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
195 ('p', 'show-function', None, _('show which function each change is in')),
195 ('p', 'show-function', None, _('show which function each change is in')),
196 ('', 'reverse', None, _('produce a diff that undoes the changes')),
196 ('', 'reverse', None, _('produce a diff that undoes the changes')),
197 ] + diffwsopts + [
197 ] + diffwsopts + [
198 ('U', 'unified', '',
198 ('U', 'unified', '',
199 _('number of lines of context to show'), _('NUM')),
199 _('number of lines of context to show'), _('NUM')),
200 ('', 'stat', None, _('output diffstat-style summary of changes')),
200 ('', 'stat', None, _('output diffstat-style summary of changes')),
201 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
201 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
202 ]
202 ]
203
203
204 mergetoolopts = [
204 mergetoolopts = [
205 ('t', 'tool', '', _('specify merge tool')),
205 ('t', 'tool', '', _('specify merge tool')),
206 ]
206 ]
207
207
208 similarityopts = [
208 similarityopts = [
209 ('s', 'similarity', '',
209 ('s', 'similarity', '',
210 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
210 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
211 ]
211 ]
212
212
213 subrepoopts = [
213 subrepoopts = [
214 ('S', 'subrepos', None,
214 ('S', 'subrepos', None,
215 _('recurse into subrepositories'))
215 _('recurse into subrepositories'))
216 ]
216 ]
217
217
218 debugrevlogopts = [
218 debugrevlogopts = [
219 ('c', 'changelog', False, _('open changelog')),
219 ('c', 'changelog', False, _('open changelog')),
220 ('m', 'manifest', False, _('open manifest')),
220 ('m', 'manifest', False, _('open manifest')),
221 ('', 'dir', '', _('open directory manifest')),
221 ('', 'dir', '', _('open directory manifest')),
222 ]
222 ]
223
223
224 # Commands start here, listed alphabetically
224 # Commands start here, listed alphabetically
225
225
226 @command('^add',
226 @command('^add',
227 walkopts + subrepoopts + dryrunopts,
227 walkopts + subrepoopts + dryrunopts,
228 _('[OPTION]... [FILE]...'),
228 _('[OPTION]... [FILE]...'),
229 inferrepo=True)
229 inferrepo=True)
230 def add(ui, repo, *pats, **opts):
230 def add(ui, repo, *pats, **opts):
231 """add the specified files on the next commit
231 """add the specified files on the next commit
232
232
233 Schedule files to be version controlled and added to the
233 Schedule files to be version controlled and added to the
234 repository.
234 repository.
235
235
236 The files will be added to the repository at the next commit. To
236 The files will be added to the repository at the next commit. To
237 undo an add before that, see :hg:`forget`.
237 undo an add before that, see :hg:`forget`.
238
238
239 If no names are given, add all files to the repository (except
239 If no names are given, add all files to the repository (except
240 files matching ``.hgignore``).
240 files matching ``.hgignore``).
241
241
242 .. container:: verbose
242 .. container:: verbose
243
243
244 Examples:
244 Examples:
245
245
246 - New (unknown) files are added
246 - New (unknown) files are added
247 automatically by :hg:`add`::
247 automatically by :hg:`add`::
248
248
249 $ ls
249 $ ls
250 foo.c
250 foo.c
251 $ hg status
251 $ hg status
252 ? foo.c
252 ? foo.c
253 $ hg add
253 $ hg add
254 adding foo.c
254 adding foo.c
255 $ hg status
255 $ hg status
256 A foo.c
256 A foo.c
257
257
258 - Specific files to be added can be specified::
258 - Specific files to be added can be specified::
259
259
260 $ ls
260 $ ls
261 bar.c foo.c
261 bar.c foo.c
262 $ hg status
262 $ hg status
263 ? bar.c
263 ? bar.c
264 ? foo.c
264 ? foo.c
265 $ hg add bar.c
265 $ hg add bar.c
266 $ hg status
266 $ hg status
267 A bar.c
267 A bar.c
268 ? foo.c
268 ? foo.c
269
269
270 Returns 0 if all files are successfully added.
270 Returns 0 if all files are successfully added.
271 """
271 """
272
272
273 m = scmutil.match(repo[None], pats, opts)
273 m = scmutil.match(repo[None], pats, opts)
274 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
274 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
275 return rejected and 1 or 0
275 return rejected and 1 or 0
276
276
277 @command('addremove',
277 @command('addremove',
278 similarityopts + subrepoopts + walkopts + dryrunopts,
278 similarityopts + subrepoopts + walkopts + dryrunopts,
279 _('[OPTION]... [FILE]...'),
279 _('[OPTION]... [FILE]...'),
280 inferrepo=True)
280 inferrepo=True)
281 def addremove(ui, repo, *pats, **opts):
281 def addremove(ui, repo, *pats, **opts):
282 """add all new files, delete all missing files
282 """add all new files, delete all missing files
283
283
284 Add all new files and remove all missing files from the
284 Add all new files and remove all missing files from the
285 repository.
285 repository.
286
286
287 Unless names are given, new files are ignored if they match any of
287 Unless names are given, new files are ignored if they match any of
288 the patterns in ``.hgignore``. As with add, these changes take
288 the patterns in ``.hgignore``. As with add, these changes take
289 effect at the next commit.
289 effect at the next commit.
290
290
291 Use the -s/--similarity option to detect renamed files. This
291 Use the -s/--similarity option to detect renamed files. This
292 option takes a percentage between 0 (disabled) and 100 (files must
292 option takes a percentage between 0 (disabled) and 100 (files must
293 be identical) as its parameter. With a parameter greater than 0,
293 be identical) as its parameter. With a parameter greater than 0,
294 this compares every removed file with every added file and records
294 this compares every removed file with every added file and records
295 those similar enough as renames. Detecting renamed files this way
295 those similar enough as renames. Detecting renamed files this way
296 can be expensive. After using this option, :hg:`status -C` can be
296 can be expensive. After using this option, :hg:`status -C` can be
297 used to check which files were identified as moved or renamed. If
297 used to check which files were identified as moved or renamed. If
298 not specified, -s/--similarity defaults to 100 and only renames of
298 not specified, -s/--similarity defaults to 100 and only renames of
299 identical files are detected.
299 identical files are detected.
300
300
301 .. container:: verbose
301 .. container:: verbose
302
302
303 Examples:
303 Examples:
304
304
305 - A number of files (bar.c and foo.c) are new,
305 - A number of files (bar.c and foo.c) are new,
306 while foobar.c has been removed (without using :hg:`remove`)
306 while foobar.c has been removed (without using :hg:`remove`)
307 from the repository::
307 from the repository::
308
308
309 $ ls
309 $ ls
310 bar.c foo.c
310 bar.c foo.c
311 $ hg status
311 $ hg status
312 ! foobar.c
312 ! foobar.c
313 ? bar.c
313 ? bar.c
314 ? foo.c
314 ? foo.c
315 $ hg addremove
315 $ hg addremove
316 adding bar.c
316 adding bar.c
317 adding foo.c
317 adding foo.c
318 removing foobar.c
318 removing foobar.c
319 $ hg status
319 $ hg status
320 A bar.c
320 A bar.c
321 A foo.c
321 A foo.c
322 R foobar.c
322 R foobar.c
323
323
324 - A file foobar.c was moved to foo.c without using :hg:`rename`.
324 - A file foobar.c was moved to foo.c without using :hg:`rename`.
325 Afterwards, it was edited slightly::
325 Afterwards, it was edited slightly::
326
326
327 $ ls
327 $ ls
328 foo.c
328 foo.c
329 $ hg status
329 $ hg status
330 ! foobar.c
330 ! foobar.c
331 ? foo.c
331 ? foo.c
332 $ hg addremove --similarity 90
332 $ hg addremove --similarity 90
333 removing foobar.c
333 removing foobar.c
334 adding foo.c
334 adding foo.c
335 recording removal of foobar.c as rename to foo.c (94% similar)
335 recording removal of foobar.c as rename to foo.c (94% similar)
336 $ hg status -C
336 $ hg status -C
337 A foo.c
337 A foo.c
338 foobar.c
338 foobar.c
339 R foobar.c
339 R foobar.c
340
340
341 Returns 0 if all files are successfully added.
341 Returns 0 if all files are successfully added.
342 """
342 """
343 try:
343 try:
344 sim = float(opts.get('similarity') or 100)
344 sim = float(opts.get('similarity') or 100)
345 except ValueError:
345 except ValueError:
346 raise error.Abort(_('similarity must be a number'))
346 raise error.Abort(_('similarity must be a number'))
347 if sim < 0 or sim > 100:
347 if sim < 0 or sim > 100:
348 raise error.Abort(_('similarity must be between 0 and 100'))
348 raise error.Abort(_('similarity must be between 0 and 100'))
349 matcher = scmutil.match(repo[None], pats, opts)
349 matcher = scmutil.match(repo[None], pats, opts)
350 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
350 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
351
351
352 @command('^annotate|blame',
352 @command('^annotate|blame',
353 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
353 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
354 ('', 'follow', None,
354 ('', 'follow', None,
355 _('follow copies/renames and list the filename (DEPRECATED)')),
355 _('follow copies/renames and list the filename (DEPRECATED)')),
356 ('', 'no-follow', None, _("don't follow copies and renames")),
356 ('', 'no-follow', None, _("don't follow copies and renames")),
357 ('a', 'text', None, _('treat all files as text')),
357 ('a', 'text', None, _('treat all files as text')),
358 ('u', 'user', None, _('list the author (long with -v)')),
358 ('u', 'user', None, _('list the author (long with -v)')),
359 ('f', 'file', None, _('list the filename')),
359 ('f', 'file', None, _('list the filename')),
360 ('d', 'date', None, _('list the date (short with -q)')),
360 ('d', 'date', None, _('list the date (short with -q)')),
361 ('n', 'number', None, _('list the revision number (default)')),
361 ('n', 'number', None, _('list the revision number (default)')),
362 ('c', 'changeset', None, _('list the changeset')),
362 ('c', 'changeset', None, _('list the changeset')),
363 ('l', 'line-number', None, _('show line number at the first appearance'))
363 ('l', 'line-number', None, _('show line number at the first appearance'))
364 ] + diffwsopts + walkopts + formatteropts,
364 ] + diffwsopts + walkopts + formatteropts,
365 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
365 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
366 inferrepo=True)
366 inferrepo=True)
367 def annotate(ui, repo, *pats, **opts):
367 def annotate(ui, repo, *pats, **opts):
368 """show changeset information by line for each file
368 """show changeset information by line for each file
369
369
370 List changes in files, showing the revision id responsible for
370 List changes in files, showing the revision id responsible for
371 each line.
371 each line.
372
372
373 This command is useful for discovering when a change was made and
373 This command is useful for discovering when a change was made and
374 by whom.
374 by whom.
375
375
376 If you include --file, --user, or --date, the revision number is
376 If you include --file, --user, or --date, the revision number is
377 suppressed unless you also include --number.
377 suppressed unless you also include --number.
378
378
379 Without the -a/--text option, annotate will avoid processing files
379 Without the -a/--text option, annotate will avoid processing files
380 it detects as binary. With -a, annotate will annotate the file
380 it detects as binary. With -a, annotate will annotate the file
381 anyway, although the results will probably be neither useful
381 anyway, although the results will probably be neither useful
382 nor desirable.
382 nor desirable.
383
383
384 Returns 0 on success.
384 Returns 0 on success.
385 """
385 """
386 if not pats:
386 if not pats:
387 raise error.Abort(_('at least one filename or pattern is required'))
387 raise error.Abort(_('at least one filename or pattern is required'))
388
388
389 if opts.get('follow'):
389 if opts.get('follow'):
390 # --follow is deprecated and now just an alias for -f/--file
390 # --follow is deprecated and now just an alias for -f/--file
391 # to mimic the behavior of Mercurial before version 1.5
391 # to mimic the behavior of Mercurial before version 1.5
392 opts['file'] = True
392 opts['file'] = True
393
393
394 ctx = scmutil.revsingle(repo, opts.get('rev'))
394 ctx = scmutil.revsingle(repo, opts.get('rev'))
395
395
396 fm = ui.formatter('annotate', opts)
396 fm = ui.formatter('annotate', opts)
397 if ui.quiet:
397 if ui.quiet:
398 datefunc = util.shortdate
398 datefunc = util.shortdate
399 else:
399 else:
400 datefunc = util.datestr
400 datefunc = util.datestr
401 if ctx.rev() is None:
401 if ctx.rev() is None:
402 def hexfn(node):
402 def hexfn(node):
403 if node is None:
403 if node is None:
404 return None
404 return None
405 else:
405 else:
406 return fm.hexfunc(node)
406 return fm.hexfunc(node)
407 if opts.get('changeset'):
407 if opts.get('changeset'):
408 # omit "+" suffix which is appended to node hex
408 # omit "+" suffix which is appended to node hex
409 def formatrev(rev):
409 def formatrev(rev):
410 if rev is None:
410 if rev is None:
411 return '%d' % ctx.p1().rev()
411 return '%d' % ctx.p1().rev()
412 else:
412 else:
413 return '%d' % rev
413 return '%d' % rev
414 else:
414 else:
415 def formatrev(rev):
415 def formatrev(rev):
416 if rev is None:
416 if rev is None:
417 return '%d+' % ctx.p1().rev()
417 return '%d+' % ctx.p1().rev()
418 else:
418 else:
419 return '%d ' % rev
419 return '%d ' % rev
420 def formathex(hex):
420 def formathex(hex):
421 if hex is None:
421 if hex is None:
422 return '%s+' % fm.hexfunc(ctx.p1().node())
422 return '%s+' % fm.hexfunc(ctx.p1().node())
423 else:
423 else:
424 return '%s ' % hex
424 return '%s ' % hex
425 else:
425 else:
426 hexfn = fm.hexfunc
426 hexfn = fm.hexfunc
427 formatrev = formathex = str
427 formatrev = formathex = str
428
428
429 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
429 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
430 ('number', ' ', lambda x: x[0].rev(), formatrev),
430 ('number', ' ', lambda x: x[0].rev(), formatrev),
431 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
431 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
432 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
432 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
433 ('file', ' ', lambda x: x[0].path(), str),
433 ('file', ' ', lambda x: x[0].path(), str),
434 ('line_number', ':', lambda x: x[1], str),
434 ('line_number', ':', lambda x: x[1], str),
435 ]
435 ]
436 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
436 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
437
437
438 if (not opts.get('user') and not opts.get('changeset')
438 if (not opts.get('user') and not opts.get('changeset')
439 and not opts.get('date') and not opts.get('file')):
439 and not opts.get('date') and not opts.get('file')):
440 opts['number'] = True
440 opts['number'] = True
441
441
442 linenumber = opts.get('line_number') is not None
442 linenumber = opts.get('line_number') is not None
443 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
443 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
444 raise error.Abort(_('at least one of -n/-c is required for -l'))
444 raise error.Abort(_('at least one of -n/-c is required for -l'))
445
445
446 if fm.isplain():
446 if fm.isplain():
447 def makefunc(get, fmt):
447 def makefunc(get, fmt):
448 return lambda x: fmt(get(x))
448 return lambda x: fmt(get(x))
449 else:
449 else:
450 def makefunc(get, fmt):
450 def makefunc(get, fmt):
451 return get
451 return get
452 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
452 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
453 if opts.get(op)]
453 if opts.get(op)]
454 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
454 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
455 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
455 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
456 if opts.get(op))
456 if opts.get(op))
457
457
458 def bad(x, y):
458 def bad(x, y):
459 raise error.Abort("%s: %s" % (x, y))
459 raise error.Abort("%s: %s" % (x, y))
460
460
461 m = scmutil.match(ctx, pats, opts, badfn=bad)
461 m = scmutil.match(ctx, pats, opts, badfn=bad)
462
462
463 follow = not opts.get('no_follow')
463 follow = not opts.get('no_follow')
464 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
464 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
465 whitespace=True)
465 whitespace=True)
466 for abs in ctx.walk(m):
466 for abs in ctx.walk(m):
467 fctx = ctx[abs]
467 fctx = ctx[abs]
468 if not opts.get('text') and util.binary(fctx.data()):
468 if not opts.get('text') and util.binary(fctx.data()):
469 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
469 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
470 continue
470 continue
471
471
472 lines = fctx.annotate(follow=follow, linenumber=linenumber,
472 lines = fctx.annotate(follow=follow, linenumber=linenumber,
473 diffopts=diffopts)
473 diffopts=diffopts)
474 if not lines:
474 if not lines:
475 continue
475 continue
476 formats = []
476 formats = []
477 pieces = []
477 pieces = []
478
478
479 for f, sep in funcmap:
479 for f, sep in funcmap:
480 l = [f(n) for n, dummy in lines]
480 l = [f(n) for n, dummy in lines]
481 if fm.isplain():
481 if fm.isplain():
482 sizes = [encoding.colwidth(x) for x in l]
482 sizes = [encoding.colwidth(x) for x in l]
483 ml = max(sizes)
483 ml = max(sizes)
484 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
484 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
485 else:
485 else:
486 formats.append(['%s' for x in l])
486 formats.append(['%s' for x in l])
487 pieces.append(l)
487 pieces.append(l)
488
488
489 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
489 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
490 fm.startitem()
490 fm.startitem()
491 fm.write(fields, "".join(f), *p)
491 fm.write(fields, "".join(f), *p)
492 fm.write('line', ": %s", l[1])
492 fm.write('line', ": %s", l[1])
493
493
494 if not lines[-1][1].endswith('\n'):
494 if not lines[-1][1].endswith('\n'):
495 fm.plain('\n')
495 fm.plain('\n')
496
496
497 fm.end()
497 fm.end()
498
498
499 @command('archive',
499 @command('archive',
500 [('', 'no-decode', None, _('do not pass files through decoders')),
500 [('', 'no-decode', None, _('do not pass files through decoders')),
501 ('p', 'prefix', '', _('directory prefix for files in archive'),
501 ('p', 'prefix', '', _('directory prefix for files in archive'),
502 _('PREFIX')),
502 _('PREFIX')),
503 ('r', 'rev', '', _('revision to distribute'), _('REV')),
503 ('r', 'rev', '', _('revision to distribute'), _('REV')),
504 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
504 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
505 ] + subrepoopts + walkopts,
505 ] + subrepoopts + walkopts,
506 _('[OPTION]... DEST'))
506 _('[OPTION]... DEST'))
507 def archive(ui, repo, dest, **opts):
507 def archive(ui, repo, dest, **opts):
508 '''create an unversioned archive of a repository revision
508 '''create an unversioned archive of a repository revision
509
509
510 By default, the revision used is the parent of the working
510 By default, the revision used is the parent of the working
511 directory; use -r/--rev to specify a different revision.
511 directory; use -r/--rev to specify a different revision.
512
512
513 The archive type is automatically detected based on file
513 The archive type is automatically detected based on file
514 extension (to override, use -t/--type).
514 extension (to override, use -t/--type).
515
515
516 .. container:: verbose
516 .. container:: verbose
517
517
518 Examples:
518 Examples:
519
519
520 - create a zip file containing the 1.0 release::
520 - create a zip file containing the 1.0 release::
521
521
522 hg archive -r 1.0 project-1.0.zip
522 hg archive -r 1.0 project-1.0.zip
523
523
524 - create a tarball excluding .hg files::
524 - create a tarball excluding .hg files::
525
525
526 hg archive project.tar.gz -X ".hg*"
526 hg archive project.tar.gz -X ".hg*"
527
527
528 Valid types are:
528 Valid types are:
529
529
530 :``files``: a directory full of files (default)
530 :``files``: a directory full of files (default)
531 :``tar``: tar archive, uncompressed
531 :``tar``: tar archive, uncompressed
532 :``tbz2``: tar archive, compressed using bzip2
532 :``tbz2``: tar archive, compressed using bzip2
533 :``tgz``: tar archive, compressed using gzip
533 :``tgz``: tar archive, compressed using gzip
534 :``uzip``: zip archive, uncompressed
534 :``uzip``: zip archive, uncompressed
535 :``zip``: zip archive, compressed using deflate
535 :``zip``: zip archive, compressed using deflate
536
536
537 The exact name of the destination archive or directory is given
537 The exact name of the destination archive or directory is given
538 using a format string; see :hg:`help export` for details.
538 using a format string; see :hg:`help export` for details.
539
539
540 Each member added to an archive file has a directory prefix
540 Each member added to an archive file has a directory prefix
541 prepended. Use -p/--prefix to specify a format string for the
541 prepended. Use -p/--prefix to specify a format string for the
542 prefix. The default is the basename of the archive, with suffixes
542 prefix. The default is the basename of the archive, with suffixes
543 removed.
543 removed.
544
544
545 Returns 0 on success.
545 Returns 0 on success.
546 '''
546 '''
547
547
548 ctx = scmutil.revsingle(repo, opts.get('rev'))
548 ctx = scmutil.revsingle(repo, opts.get('rev'))
549 if not ctx:
549 if not ctx:
550 raise error.Abort(_('no working directory: please specify a revision'))
550 raise error.Abort(_('no working directory: please specify a revision'))
551 node = ctx.node()
551 node = ctx.node()
552 dest = cmdutil.makefilename(repo, dest, node)
552 dest = cmdutil.makefilename(repo, dest, node)
553 if os.path.realpath(dest) == repo.root:
553 if os.path.realpath(dest) == repo.root:
554 raise error.Abort(_('repository root cannot be destination'))
554 raise error.Abort(_('repository root cannot be destination'))
555
555
556 kind = opts.get('type') or archival.guesskind(dest) or 'files'
556 kind = opts.get('type') or archival.guesskind(dest) or 'files'
557 prefix = opts.get('prefix')
557 prefix = opts.get('prefix')
558
558
559 if dest == '-':
559 if dest == '-':
560 if kind == 'files':
560 if kind == 'files':
561 raise error.Abort(_('cannot archive plain files to stdout'))
561 raise error.Abort(_('cannot archive plain files to stdout'))
562 dest = cmdutil.makefileobj(repo, dest)
562 dest = cmdutil.makefileobj(repo, dest)
563 if not prefix:
563 if not prefix:
564 prefix = os.path.basename(repo.root) + '-%h'
564 prefix = os.path.basename(repo.root) + '-%h'
565
565
566 prefix = cmdutil.makefilename(repo, prefix, node)
566 prefix = cmdutil.makefilename(repo, prefix, node)
567 matchfn = scmutil.match(ctx, [], opts)
567 matchfn = scmutil.match(ctx, [], opts)
568 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
568 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
569 matchfn, prefix, subrepos=opts.get('subrepos'))
569 matchfn, prefix, subrepos=opts.get('subrepos'))
570
570
571 @command('backout',
571 @command('backout',
572 [('', 'merge', None, _('merge with old dirstate parent after backout')),
572 [('', 'merge', None, _('merge with old dirstate parent after backout')),
573 ('', 'commit', None,
573 ('', 'commit', None,
574 _('commit if no conflicts were encountered (DEPRECATED)')),
574 _('commit if no conflicts were encountered (DEPRECATED)')),
575 ('', 'no-commit', None, _('do not commit')),
575 ('', 'no-commit', None, _('do not commit')),
576 ('', 'parent', '',
576 ('', 'parent', '',
577 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
577 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
578 ('r', 'rev', '', _('revision to backout'), _('REV')),
578 ('r', 'rev', '', _('revision to backout'), _('REV')),
579 ('e', 'edit', False, _('invoke editor on commit messages')),
579 ('e', 'edit', False, _('invoke editor on commit messages')),
580 ] + mergetoolopts + walkopts + commitopts + commitopts2,
580 ] + mergetoolopts + walkopts + commitopts + commitopts2,
581 _('[OPTION]... [-r] REV'))
581 _('[OPTION]... [-r] REV'))
582 def backout(ui, repo, node=None, rev=None, **opts):
582 def backout(ui, repo, node=None, rev=None, **opts):
583 '''reverse effect of earlier changeset
583 '''reverse effect of earlier changeset
584
584
585 Prepare a new changeset with the effect of REV undone in the
585 Prepare a new changeset with the effect of REV undone in the
586 current working directory. If no conflicts were encountered,
586 current working directory. If no conflicts were encountered,
587 it will be committed immediately.
587 it will be committed immediately.
588
588
589 If REV is the parent of the working directory, then this new changeset
589 If REV is the parent of the working directory, then this new changeset
590 is committed automatically (unless --no-commit is specified).
590 is committed automatically (unless --no-commit is specified).
591
591
592 .. note::
592 .. note::
593
593
594 :hg:`backout` cannot be used to fix either an unwanted or
594 :hg:`backout` cannot be used to fix either an unwanted or
595 incorrect merge.
595 incorrect merge.
596
596
597 .. container:: verbose
597 .. container:: verbose
598
598
599 Examples:
599 Examples:
600
600
601 - Reverse the effect of the parent of the working directory.
601 - Reverse the effect of the parent of the working directory.
602 This backout will be committed immediately::
602 This backout will be committed immediately::
603
603
604 hg backout -r .
604 hg backout -r .
605
605
606 - Reverse the effect of previous bad revision 23::
606 - Reverse the effect of previous bad revision 23::
607
607
608 hg backout -r 23
608 hg backout -r 23
609
609
610 - Reverse the effect of previous bad revision 23 and
610 - Reverse the effect of previous bad revision 23 and
611 leave changes uncommitted::
611 leave changes uncommitted::
612
612
613 hg backout -r 23 --no-commit
613 hg backout -r 23 --no-commit
614 hg commit -m "Backout revision 23"
614 hg commit -m "Backout revision 23"
615
615
616 By default, the pending changeset will have one parent,
616 By default, the pending changeset will have one parent,
617 maintaining a linear history. With --merge, the pending
617 maintaining a linear history. With --merge, the pending
618 changeset will instead have two parents: the old parent of the
618 changeset will instead have two parents: the old parent of the
619 working directory and a new child of REV that simply undoes REV.
619 working directory and a new child of REV that simply undoes REV.
620
620
621 Before version 1.7, the behavior without --merge was equivalent
621 Before version 1.7, the behavior without --merge was equivalent
622 to specifying --merge followed by :hg:`update --clean .` to
622 to specifying --merge followed by :hg:`update --clean .` to
623 cancel the merge and leave the child of REV as a head to be
623 cancel the merge and leave the child of REV as a head to be
624 merged separately.
624 merged separately.
625
625
626 See :hg:`help dates` for a list of formats valid for -d/--date.
626 See :hg:`help dates` for a list of formats valid for -d/--date.
627
627
628 See :hg:`help revert` for a way to restore files to the state
628 See :hg:`help revert` for a way to restore files to the state
629 of another revision.
629 of another revision.
630
630
631 Returns 0 on success, 1 if nothing to backout or there are unresolved
631 Returns 0 on success, 1 if nothing to backout or there are unresolved
632 files.
632 files.
633 '''
633 '''
634 wlock = lock = None
634 wlock = lock = None
635 try:
635 try:
636 wlock = repo.wlock()
636 wlock = repo.wlock()
637 lock = repo.lock()
637 lock = repo.lock()
638 return _dobackout(ui, repo, node, rev, **opts)
638 return _dobackout(ui, repo, node, rev, **opts)
639 finally:
639 finally:
640 release(lock, wlock)
640 release(lock, wlock)
641
641
642 def _dobackout(ui, repo, node=None, rev=None, **opts):
642 def _dobackout(ui, repo, node=None, rev=None, **opts):
643 if opts.get('commit') and opts.get('no_commit'):
643 if opts.get('commit') and opts.get('no_commit'):
644 raise error.Abort(_("cannot use --commit with --no-commit"))
644 raise error.Abort(_("cannot use --commit with --no-commit"))
645 if opts.get('merge') and opts.get('no_commit'):
645 if opts.get('merge') and opts.get('no_commit'):
646 raise error.Abort(_("cannot use --merge with --no-commit"))
646 raise error.Abort(_("cannot use --merge with --no-commit"))
647
647
648 if rev and node:
648 if rev and node:
649 raise error.Abort(_("please specify just one revision"))
649 raise error.Abort(_("please specify just one revision"))
650
650
651 if not rev:
651 if not rev:
652 rev = node
652 rev = node
653
653
654 if not rev:
654 if not rev:
655 raise error.Abort(_("please specify a revision to backout"))
655 raise error.Abort(_("please specify a revision to backout"))
656
656
657 date = opts.get('date')
657 date = opts.get('date')
658 if date:
658 if date:
659 opts['date'] = util.parsedate(date)
659 opts['date'] = util.parsedate(date)
660
660
661 cmdutil.checkunfinished(repo)
661 cmdutil.checkunfinished(repo)
662 cmdutil.bailifchanged(repo)
662 cmdutil.bailifchanged(repo)
663 node = scmutil.revsingle(repo, rev).node()
663 node = scmutil.revsingle(repo, rev).node()
664
664
665 op1, op2 = repo.dirstate.parents()
665 op1, op2 = repo.dirstate.parents()
666 if not repo.changelog.isancestor(node, op1):
666 if not repo.changelog.isancestor(node, op1):
667 raise error.Abort(_('cannot backout change that is not an ancestor'))
667 raise error.Abort(_('cannot backout change that is not an ancestor'))
668
668
669 p1, p2 = repo.changelog.parents(node)
669 p1, p2 = repo.changelog.parents(node)
670 if p1 == nullid:
670 if p1 == nullid:
671 raise error.Abort(_('cannot backout a change with no parents'))
671 raise error.Abort(_('cannot backout a change with no parents'))
672 if p2 != nullid:
672 if p2 != nullid:
673 if not opts.get('parent'):
673 if not opts.get('parent'):
674 raise error.Abort(_('cannot backout a merge changeset'))
674 raise error.Abort(_('cannot backout a merge changeset'))
675 p = repo.lookup(opts['parent'])
675 p = repo.lookup(opts['parent'])
676 if p not in (p1, p2):
676 if p not in (p1, p2):
677 raise error.Abort(_('%s is not a parent of %s') %
677 raise error.Abort(_('%s is not a parent of %s') %
678 (short(p), short(node)))
678 (short(p), short(node)))
679 parent = p
679 parent = p
680 else:
680 else:
681 if opts.get('parent'):
681 if opts.get('parent'):
682 raise error.Abort(_('cannot use --parent on non-merge changeset'))
682 raise error.Abort(_('cannot use --parent on non-merge changeset'))
683 parent = p1
683 parent = p1
684
684
685 # the backout should appear on the same branch
685 # the backout should appear on the same branch
686 branch = repo.dirstate.branch()
686 branch = repo.dirstate.branch()
687 bheads = repo.branchheads(branch)
687 bheads = repo.branchheads(branch)
688 rctx = scmutil.revsingle(repo, hex(parent))
688 rctx = scmutil.revsingle(repo, hex(parent))
689 if not opts.get('merge') and op1 != node:
689 if not opts.get('merge') and op1 != node:
690 dsguard = dirstateguard.dirstateguard(repo, 'backout')
690 dsguard = dirstateguard.dirstateguard(repo, 'backout')
691 try:
691 try:
692 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
692 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
693 'backout')
693 'backout')
694 stats = mergemod.update(repo, parent, True, True, node, False)
694 stats = mergemod.update(repo, parent, True, True, node, False)
695 repo.setparents(op1, op2)
695 repo.setparents(op1, op2)
696 dsguard.close()
696 dsguard.close()
697 hg._showstats(repo, stats)
697 hg._showstats(repo, stats)
698 if stats[3]:
698 if stats[3]:
699 repo.ui.status(_("use 'hg resolve' to retry unresolved "
699 repo.ui.status(_("use 'hg resolve' to retry unresolved "
700 "file merges\n"))
700 "file merges\n"))
701 return 1
701 return 1
702 finally:
702 finally:
703 ui.setconfig('ui', 'forcemerge', '', '')
703 ui.setconfig('ui', 'forcemerge', '', '')
704 lockmod.release(dsguard)
704 lockmod.release(dsguard)
705 else:
705 else:
706 hg.clean(repo, node, show_stats=False)
706 hg.clean(repo, node, show_stats=False)
707 repo.dirstate.setbranch(branch)
707 repo.dirstate.setbranch(branch)
708 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
708 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
709
709
710 if opts.get('no_commit'):
710 if opts.get('no_commit'):
711 msg = _("changeset %s backed out, "
711 msg = _("changeset %s backed out, "
712 "don't forget to commit.\n")
712 "don't forget to commit.\n")
713 ui.status(msg % short(node))
713 ui.status(msg % short(node))
714 return 0
714 return 0
715
715
716 def commitfunc(ui, repo, message, match, opts):
716 def commitfunc(ui, repo, message, match, opts):
717 editform = 'backout'
717 editform = 'backout'
718 e = cmdutil.getcommiteditor(editform=editform, **opts)
718 e = cmdutil.getcommiteditor(editform=editform, **opts)
719 if not message:
719 if not message:
720 # we don't translate commit messages
720 # we don't translate commit messages
721 message = "Backed out changeset %s" % short(node)
721 message = "Backed out changeset %s" % short(node)
722 e = cmdutil.getcommiteditor(edit=True, editform=editform)
722 e = cmdutil.getcommiteditor(edit=True, editform=editform)
723 return repo.commit(message, opts.get('user'), opts.get('date'),
723 return repo.commit(message, opts.get('user'), opts.get('date'),
724 match, editor=e)
724 match, editor=e)
725 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
725 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
726 if not newnode:
726 if not newnode:
727 ui.status(_("nothing changed\n"))
727 ui.status(_("nothing changed\n"))
728 return 1
728 return 1
729 cmdutil.commitstatus(repo, newnode, branch, bheads)
729 cmdutil.commitstatus(repo, newnode, branch, bheads)
730
730
731 def nice(node):
731 def nice(node):
732 return '%d:%s' % (repo.changelog.rev(node), short(node))
732 return '%d:%s' % (repo.changelog.rev(node), short(node))
733 ui.status(_('changeset %s backs out changeset %s\n') %
733 ui.status(_('changeset %s backs out changeset %s\n') %
734 (nice(repo.changelog.tip()), nice(node)))
734 (nice(repo.changelog.tip()), nice(node)))
735 if opts.get('merge') and op1 != node:
735 if opts.get('merge') and op1 != node:
736 hg.clean(repo, op1, show_stats=False)
736 hg.clean(repo, op1, show_stats=False)
737 ui.status(_('merging with changeset %s\n')
737 ui.status(_('merging with changeset %s\n')
738 % nice(repo.changelog.tip()))
738 % nice(repo.changelog.tip()))
739 try:
739 try:
740 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
740 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
741 'backout')
741 'backout')
742 return hg.merge(repo, hex(repo.changelog.tip()))
742 return hg.merge(repo, hex(repo.changelog.tip()))
743 finally:
743 finally:
744 ui.setconfig('ui', 'forcemerge', '', '')
744 ui.setconfig('ui', 'forcemerge', '', '')
745 return 0
745 return 0
746
746
747 @command('bisect',
747 @command('bisect',
748 [('r', 'reset', False, _('reset bisect state')),
748 [('r', 'reset', False, _('reset bisect state')),
749 ('g', 'good', False, _('mark changeset good')),
749 ('g', 'good', False, _('mark changeset good')),
750 ('b', 'bad', False, _('mark changeset bad')),
750 ('b', 'bad', False, _('mark changeset bad')),
751 ('s', 'skip', False, _('skip testing changeset')),
751 ('s', 'skip', False, _('skip testing changeset')),
752 ('e', 'extend', False, _('extend the bisect range')),
752 ('e', 'extend', False, _('extend the bisect range')),
753 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
753 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
754 ('U', 'noupdate', False, _('do not update to target'))],
754 ('U', 'noupdate', False, _('do not update to target'))],
755 _("[-gbsr] [-U] [-c CMD] [REV]"))
755 _("[-gbsr] [-U] [-c CMD] [REV]"))
756 def bisect(ui, repo, rev=None, extra=None, command=None,
756 def bisect(ui, repo, rev=None, extra=None, command=None,
757 reset=None, good=None, bad=None, skip=None, extend=None,
757 reset=None, good=None, bad=None, skip=None, extend=None,
758 noupdate=None):
758 noupdate=None):
759 """subdivision search of changesets
759 """subdivision search of changesets
760
760
761 This command helps to find changesets which introduce problems. To
761 This command helps to find changesets which introduce problems. To
762 use, mark the earliest changeset you know exhibits the problem as
762 use, mark the earliest changeset you know exhibits the problem as
763 bad, then mark the latest changeset which is free from the problem
763 bad, then mark the latest changeset which is free from the problem
764 as good. Bisect will update your working directory to a revision
764 as good. Bisect will update your working directory to a revision
765 for testing (unless the -U/--noupdate option is specified). Once
765 for testing (unless the -U/--noupdate option is specified). Once
766 you have performed tests, mark the working directory as good or
766 you have performed tests, mark the working directory as good or
767 bad, and bisect will either update to another candidate changeset
767 bad, and bisect will either update to another candidate changeset
768 or announce that it has found the bad revision.
768 or announce that it has found the bad revision.
769
769
770 As a shortcut, you can also use the revision argument to mark a
770 As a shortcut, you can also use the revision argument to mark a
771 revision as good or bad without checking it out first.
771 revision as good or bad without checking it out first.
772
772
773 If you supply a command, it will be used for automatic bisection.
773 If you supply a command, it will be used for automatic bisection.
774 The environment variable HG_NODE will contain the ID of the
774 The environment variable HG_NODE will contain the ID of the
775 changeset being tested. The exit status of the command will be
775 changeset being tested. The exit status of the command will be
776 used to mark revisions as good or bad: status 0 means good, 125
776 used to mark revisions as good or bad: status 0 means good, 125
777 means to skip the revision, 127 (command not found) will abort the
777 means to skip the revision, 127 (command not found) will abort the
778 bisection, and any other non-zero exit status means the revision
778 bisection, and any other non-zero exit status means the revision
779 is bad.
779 is bad.
780
780
781 .. container:: verbose
781 .. container:: verbose
782
782
783 Some examples:
783 Some examples:
784
784
785 - start a bisection with known bad revision 34, and good revision 12::
785 - start a bisection with known bad revision 34, and good revision 12::
786
786
787 hg bisect --bad 34
787 hg bisect --bad 34
788 hg bisect --good 12
788 hg bisect --good 12
789
789
790 - advance the current bisection by marking current revision as good or
790 - advance the current bisection by marking current revision as good or
791 bad::
791 bad::
792
792
793 hg bisect --good
793 hg bisect --good
794 hg bisect --bad
794 hg bisect --bad
795
795
796 - mark the current revision, or a known revision, to be skipped (e.g. if
796 - mark the current revision, or a known revision, to be skipped (e.g. if
797 that revision is not usable because of another issue)::
797 that revision is not usable because of another issue)::
798
798
799 hg bisect --skip
799 hg bisect --skip
800 hg bisect --skip 23
800 hg bisect --skip 23
801
801
802 - skip all revisions that do not touch directories ``foo`` or ``bar``::
802 - skip all revisions that do not touch directories ``foo`` or ``bar``::
803
803
804 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
804 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
805
805
806 - forget the current bisection::
806 - forget the current bisection::
807
807
808 hg bisect --reset
808 hg bisect --reset
809
809
810 - use 'make && make tests' to automatically find the first broken
810 - use 'make && make tests' to automatically find the first broken
811 revision::
811 revision::
812
812
813 hg bisect --reset
813 hg bisect --reset
814 hg bisect --bad 34
814 hg bisect --bad 34
815 hg bisect --good 12
815 hg bisect --good 12
816 hg bisect --command "make && make tests"
816 hg bisect --command "make && make tests"
817
817
818 - see all changesets whose states are already known in the current
818 - see all changesets whose states are already known in the current
819 bisection::
819 bisection::
820
820
821 hg log -r "bisect(pruned)"
821 hg log -r "bisect(pruned)"
822
822
823 - see the changeset currently being bisected (especially useful
823 - see the changeset currently being bisected (especially useful
824 if running with -U/--noupdate)::
824 if running with -U/--noupdate)::
825
825
826 hg log -r "bisect(current)"
826 hg log -r "bisect(current)"
827
827
828 - see all changesets that took part in the current bisection::
828 - see all changesets that took part in the current bisection::
829
829
830 hg log -r "bisect(range)"
830 hg log -r "bisect(range)"
831
831
832 - you can even get a nice graph::
832 - you can even get a nice graph::
833
833
834 hg log --graph -r "bisect(range)"
834 hg log --graph -r "bisect(range)"
835
835
836 See :hg:`help revsets` for more about the `bisect()` keyword.
836 See :hg:`help revsets` for more about the `bisect()` keyword.
837
837
838 Returns 0 on success.
838 Returns 0 on success.
839 """
839 """
840 # backward compatibility
840 # backward compatibility
841 if rev in "good bad reset init".split():
841 if rev in "good bad reset init".split():
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
843 cmd, rev, extra = rev, extra, None
843 cmd, rev, extra = rev, extra, None
844 if cmd == "good":
844 if cmd == "good":
845 good = True
845 good = True
846 elif cmd == "bad":
846 elif cmd == "bad":
847 bad = True
847 bad = True
848 else:
848 else:
849 reset = True
849 reset = True
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
851 raise error.Abort(_('incompatible arguments'))
851 raise error.Abort(_('incompatible arguments'))
852
852
853 cmdutil.checkunfinished(repo)
853 cmdutil.checkunfinished(repo)
854
854
855 if reset:
855 if reset:
856 hbisect.resetstate(repo)
856 hbisect.resetstate(repo)
857 return
857 return
858
858
859 state = hbisect.load_state(repo)
859 state = hbisect.load_state(repo)
860
860
861 # update state
861 # update state
862 if good or bad or skip:
862 if good or bad or skip:
863 if rev:
863 if rev:
864 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
864 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
865 else:
865 else:
866 nodes = [repo.lookup('.')]
866 nodes = [repo.lookup('.')]
867 if good:
867 if good:
868 state['good'] += nodes
868 state['good'] += nodes
869 elif bad:
869 elif bad:
870 state['bad'] += nodes
870 state['bad'] += nodes
871 elif skip:
871 elif skip:
872 state['skip'] += nodes
872 state['skip'] += nodes
873 hbisect.save_state(repo, state)
873 hbisect.save_state(repo, state)
874 if not (state['good'] and state['bad']):
874 if not (state['good'] and state['bad']):
875 return
875 return
876
876
877 def mayupdate(repo, node, show_stats=True):
877 def mayupdate(repo, node, show_stats=True):
878 """common used update sequence"""
878 """common used update sequence"""
879 if noupdate:
879 if noupdate:
880 return
880 return
881 cmdutil.bailifchanged(repo)
881 cmdutil.bailifchanged(repo)
882 return hg.clean(repo, node, show_stats=show_stats)
882 return hg.clean(repo, node, show_stats=show_stats)
883
883
884 displayer = cmdutil.show_changeset(ui, repo, {})
884 displayer = cmdutil.show_changeset(ui, repo, {})
885
885
886 if command:
886 if command:
887 changesets = 1
887 changesets = 1
888 if noupdate:
888 if noupdate:
889 try:
889 try:
890 node = state['current'][0]
890 node = state['current'][0]
891 except LookupError:
891 except LookupError:
892 raise error.Abort(_('current bisect revision is unknown - '
892 raise error.Abort(_('current bisect revision is unknown - '
893 'start a new bisect to fix'))
893 'start a new bisect to fix'))
894 else:
894 else:
895 node, p2 = repo.dirstate.parents()
895 node, p2 = repo.dirstate.parents()
896 if p2 != nullid:
896 if p2 != nullid:
897 raise error.Abort(_('current bisect revision is a merge'))
897 raise error.Abort(_('current bisect revision is a merge'))
898 if rev:
898 if rev:
899 node = repo[scmutil.revsingle(repo, rev, node)].node()
899 node = repo[scmutil.revsingle(repo, rev, node)].node()
900 try:
900 try:
901 while changesets:
901 while changesets:
902 # update state
902 # update state
903 state['current'] = [node]
903 state['current'] = [node]
904 hbisect.save_state(repo, state)
904 hbisect.save_state(repo, state)
905 status = ui.system(command, environ={'HG_NODE': hex(node)})
905 status = ui.system(command, environ={'HG_NODE': hex(node)})
906 if status == 125:
906 if status == 125:
907 transition = "skip"
907 transition = "skip"
908 elif status == 0:
908 elif status == 0:
909 transition = "good"
909 transition = "good"
910 # status < 0 means process was killed
910 # status < 0 means process was killed
911 elif status == 127:
911 elif status == 127:
912 raise error.Abort(_("failed to execute %s") % command)
912 raise error.Abort(_("failed to execute %s") % command)
913 elif status < 0:
913 elif status < 0:
914 raise error.Abort(_("%s killed") % command)
914 raise error.Abort(_("%s killed") % command)
915 else:
915 else:
916 transition = "bad"
916 transition = "bad"
917 state[transition].append(node)
917 state[transition].append(node)
918 ctx = repo[node]
918 ctx = repo[node]
919 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
919 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
920 hbisect.checkstate(state)
920 hbisect.checkstate(state)
921 # bisect
921 # bisect
922 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
922 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
923 # update to next check
923 # update to next check
924 node = nodes[0]
924 node = nodes[0]
925 mayupdate(repo, node, show_stats=False)
925 mayupdate(repo, node, show_stats=False)
926 finally:
926 finally:
927 state['current'] = [node]
927 state['current'] = [node]
928 hbisect.save_state(repo, state)
928 hbisect.save_state(repo, state)
929 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
929 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
930 return
930 return
931
931
932 hbisect.checkstate(state)
932 hbisect.checkstate(state)
933
933
934 # actually bisect
934 # actually bisect
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
936 if extend:
936 if extend:
937 if not changesets:
937 if not changesets:
938 extendnode = hbisect.extendrange(repo, state, nodes, good)
938 extendnode = hbisect.extendrange(repo, state, nodes, good)
939 if extendnode is not None:
939 if extendnode is not None:
940 ui.write(_("Extending search to changeset %d:%s\n")
940 ui.write(_("Extending search to changeset %d:%s\n")
941 % (extendnode.rev(), extendnode))
941 % (extendnode.rev(), extendnode))
942 state['current'] = [extendnode.node()]
942 state['current'] = [extendnode.node()]
943 hbisect.save_state(repo, state)
943 hbisect.save_state(repo, state)
944 return mayupdate(repo, extendnode.node())
944 return mayupdate(repo, extendnode.node())
945 raise error.Abort(_("nothing to extend"))
945 raise error.Abort(_("nothing to extend"))
946
946
947 if changesets == 0:
947 if changesets == 0:
948 hbisect.printresult(ui, repo, state, displayer, nodes, good)
948 hbisect.printresult(ui, repo, state, displayer, nodes, good)
949 else:
949 else:
950 assert len(nodes) == 1 # only a single node can be tested next
950 assert len(nodes) == 1 # only a single node can be tested next
951 node = nodes[0]
951 node = nodes[0]
952 # compute the approximate number of remaining tests
952 # compute the approximate number of remaining tests
953 tests, size = 0, 2
953 tests, size = 0, 2
954 while size <= changesets:
954 while size <= changesets:
955 tests, size = tests + 1, size * 2
955 tests, size = tests + 1, size * 2
956 rev = repo.changelog.rev(node)
956 rev = repo.changelog.rev(node)
957 ui.write(_("Testing changeset %d:%s "
957 ui.write(_("Testing changeset %d:%s "
958 "(%d changesets remaining, ~%d tests)\n")
958 "(%d changesets remaining, ~%d tests)\n")
959 % (rev, short(node), changesets, tests))
959 % (rev, short(node), changesets, tests))
960 state['current'] = [node]
960 state['current'] = [node]
961 hbisect.save_state(repo, state)
961 hbisect.save_state(repo, state)
962 return mayupdate(repo, node)
962 return mayupdate(repo, node)
963
963
964 @command('bookmarks|bookmark',
964 @command('bookmarks|bookmark',
965 [('f', 'force', False, _('force')),
965 [('f', 'force', False, _('force')),
966 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
966 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
967 ('d', 'delete', False, _('delete a given bookmark')),
967 ('d', 'delete', False, _('delete a given bookmark')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
970 ] + formatteropts,
970 ] + formatteropts,
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
972 def bookmark(ui, repo, *names, **opts):
972 def bookmark(ui, repo, *names, **opts):
973 '''create a new bookmark or list existing bookmarks
973 '''create a new bookmark or list existing bookmarks
974
974
975 Bookmarks are labels on changesets to help track lines of development.
975 Bookmarks are labels on changesets to help track lines of development.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
977 Deleting or moving a bookmark has no effect on the associated changesets.
977 Deleting or moving a bookmark has no effect on the associated changesets.
978
978
979 Creating or updating to a bookmark causes it to be marked as 'active'.
979 Creating or updating to a bookmark causes it to be marked as 'active'.
980 The active bookmark is indicated with a '*'.
980 The active bookmark is indicated with a '*'.
981 When a commit is made, the active bookmark will advance to the new commit.
981 When a commit is made, the active bookmark will advance to the new commit.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
983 Updating away from a bookmark will cause it to be deactivated.
983 Updating away from a bookmark will cause it to be deactivated.
984
984
985 Bookmarks can be pushed and pulled between repositories (see
985 Bookmarks can be pushed and pulled between repositories (see
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
988 be created. Using :hg:`merge` will resolve the divergence.
988 be created. Using :hg:`merge` will resolve the divergence.
989
989
990 A bookmark named '@' has the special property that :hg:`clone` will
990 A bookmark named '@' has the special property that :hg:`clone` will
991 check it out by default if it exists.
991 check it out by default if it exists.
992
992
993 .. container:: verbose
993 .. container:: verbose
994
994
995 Examples:
995 Examples:
996
996
997 - create an active bookmark for a new line of development::
997 - create an active bookmark for a new line of development::
998
998
999 hg book new-feature
999 hg book new-feature
1000
1000
1001 - create an inactive bookmark as a place marker::
1001 - create an inactive bookmark as a place marker::
1002
1002
1003 hg book -i reviewed
1003 hg book -i reviewed
1004
1004
1005 - create an inactive bookmark on another changeset::
1005 - create an inactive bookmark on another changeset::
1006
1006
1007 hg book -r .^ tested
1007 hg book -r .^ tested
1008
1008
1009 - rename bookmark turkey to dinner::
1009 - rename bookmark turkey to dinner::
1010
1010
1011 hg book -m turkey dinner
1011 hg book -m turkey dinner
1012
1012
1013 - move the '@' bookmark from another branch::
1013 - move the '@' bookmark from another branch::
1014
1014
1015 hg book -f @
1015 hg book -f @
1016 '''
1016 '''
1017 force = opts.get('force')
1017 force = opts.get('force')
1018 rev = opts.get('rev')
1018 rev = opts.get('rev')
1019 delete = opts.get('delete')
1019 delete = opts.get('delete')
1020 rename = opts.get('rename')
1020 rename = opts.get('rename')
1021 inactive = opts.get('inactive')
1021 inactive = opts.get('inactive')
1022
1022
1023 def checkformat(mark):
1023 def checkformat(mark):
1024 mark = mark.strip()
1024 mark = mark.strip()
1025 if not mark:
1025 if not mark:
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1027 "whitespace"))
1027 "whitespace"))
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1029 return mark
1029 return mark
1030
1030
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1032 if mark in marks and not force:
1032 if mark in marks and not force:
1033 if target:
1033 if target:
1034 if marks[mark] == target and target == cur:
1034 if marks[mark] == target and target == cur:
1035 # re-activating a bookmark
1035 # re-activating a bookmark
1036 return
1036 return
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1038 bmctx = repo[marks[mark]]
1038 bmctx = repo[marks[mark]]
1039 divs = [repo[b].node() for b in marks
1039 divs = [repo[b].node() for b in marks
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1041
1041
1042 # allow resolving a single divergent bookmark even if moving
1042 # allow resolving a single divergent bookmark even if moving
1043 # the bookmark across branches when a revision is specified
1043 # the bookmark across branches when a revision is specified
1044 # that contains a divergent bookmark
1044 # that contains a divergent bookmark
1045 if bmctx.rev() not in anc and target in divs:
1045 if bmctx.rev() not in anc and target in divs:
1046 bookmarks.deletedivergent(repo, [target], mark)
1046 bookmarks.deletedivergent(repo, [target], mark)
1047 return
1047 return
1048
1048
1049 deletefrom = [b for b in divs
1049 deletefrom = [b for b in divs
1050 if repo[b].rev() in anc or b == target]
1050 if repo[b].rev() in anc or b == target]
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1054 (mark, short(bmctx.node())))
1054 (mark, short(bmctx.node())))
1055 return
1055 return
1056 raise error.Abort(_("bookmark '%s' already exists "
1056 raise error.Abort(_("bookmark '%s' already exists "
1057 "(use -f to force)") % mark)
1057 "(use -f to force)") % mark)
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1059 and not force):
1059 and not force):
1060 raise error.Abort(
1060 raise error.Abort(
1061 _("a bookmark cannot have the name of an existing branch"))
1061 _("a bookmark cannot have the name of an existing branch"))
1062
1062
1063 if delete and rename:
1063 if delete and rename:
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1065 if delete and rev:
1065 if delete and rev:
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1067 if rename and rev:
1067 if rename and rev:
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1069 if not names and (delete or rev):
1069 if not names and (delete or rev):
1070 raise error.Abort(_("bookmark name required"))
1070 raise error.Abort(_("bookmark name required"))
1071
1071
1072 if delete or rename or names or inactive:
1072 if delete or rename or names or inactive:
1073 wlock = lock = tr = None
1073 wlock = lock = tr = None
1074 try:
1074 try:
1075 wlock = repo.wlock()
1075 wlock = repo.wlock()
1076 lock = repo.lock()
1076 lock = repo.lock()
1077 cur = repo.changectx('.').node()
1077 cur = repo.changectx('.').node()
1078 marks = repo._bookmarks
1078 marks = repo._bookmarks
1079 if delete:
1079 if delete:
1080 tr = repo.transaction('bookmark')
1080 tr = repo.transaction('bookmark')
1081 for mark in names:
1081 for mark in names:
1082 if mark not in marks:
1082 if mark not in marks:
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1084 mark)
1084 mark)
1085 if mark == repo._activebookmark:
1085 if mark == repo._activebookmark:
1086 bookmarks.deactivate(repo)
1086 bookmarks.deactivate(repo)
1087 del marks[mark]
1087 del marks[mark]
1088
1088
1089 elif rename:
1089 elif rename:
1090 tr = repo.transaction('bookmark')
1090 tr = repo.transaction('bookmark')
1091 if not names:
1091 if not names:
1092 raise error.Abort(_("new bookmark name required"))
1092 raise error.Abort(_("new bookmark name required"))
1093 elif len(names) > 1:
1093 elif len(names) > 1:
1094 raise error.Abort(_("only one new bookmark name allowed"))
1094 raise error.Abort(_("only one new bookmark name allowed"))
1095 mark = checkformat(names[0])
1095 mark = checkformat(names[0])
1096 if rename not in marks:
1096 if rename not in marks:
1097 raise error.Abort(_("bookmark '%s' does not exist")
1097 raise error.Abort(_("bookmark '%s' does not exist")
1098 % rename)
1098 % rename)
1099 checkconflict(repo, mark, cur, force)
1099 checkconflict(repo, mark, cur, force)
1100 marks[mark] = marks[rename]
1100 marks[mark] = marks[rename]
1101 if repo._activebookmark == rename and not inactive:
1101 if repo._activebookmark == rename and not inactive:
1102 bookmarks.activate(repo, mark)
1102 bookmarks.activate(repo, mark)
1103 del marks[rename]
1103 del marks[rename]
1104 elif names:
1104 elif names:
1105 tr = repo.transaction('bookmark')
1105 tr = repo.transaction('bookmark')
1106 newact = None
1106 newact = None
1107 for mark in names:
1107 for mark in names:
1108 mark = checkformat(mark)
1108 mark = checkformat(mark)
1109 if newact is None:
1109 if newact is None:
1110 newact = mark
1110 newact = mark
1111 if inactive and mark == repo._activebookmark:
1111 if inactive and mark == repo._activebookmark:
1112 bookmarks.deactivate(repo)
1112 bookmarks.deactivate(repo)
1113 return
1113 return
1114 tgt = cur
1114 tgt = cur
1115 if rev:
1115 if rev:
1116 tgt = scmutil.revsingle(repo, rev).node()
1116 tgt = scmutil.revsingle(repo, rev).node()
1117 checkconflict(repo, mark, cur, force, tgt)
1117 checkconflict(repo, mark, cur, force, tgt)
1118 marks[mark] = tgt
1118 marks[mark] = tgt
1119 if not inactive and cur == marks[newact] and not rev:
1119 if not inactive and cur == marks[newact] and not rev:
1120 bookmarks.activate(repo, newact)
1120 bookmarks.activate(repo, newact)
1121 elif cur != tgt and newact == repo._activebookmark:
1121 elif cur != tgt and newact == repo._activebookmark:
1122 bookmarks.deactivate(repo)
1122 bookmarks.deactivate(repo)
1123 elif inactive:
1123 elif inactive:
1124 if len(marks) == 0:
1124 if len(marks) == 0:
1125 ui.status(_("no bookmarks set\n"))
1125 ui.status(_("no bookmarks set\n"))
1126 elif not repo._activebookmark:
1126 elif not repo._activebookmark:
1127 ui.status(_("no active bookmark\n"))
1127 ui.status(_("no active bookmark\n"))
1128 else:
1128 else:
1129 bookmarks.deactivate(repo)
1129 bookmarks.deactivate(repo)
1130 if tr is not None:
1130 if tr is not None:
1131 marks.recordchange(tr)
1131 marks.recordchange(tr)
1132 tr.close()
1132 tr.close()
1133 finally:
1133 finally:
1134 lockmod.release(tr, lock, wlock)
1134 lockmod.release(tr, lock, wlock)
1135 else: # show bookmarks
1135 else: # show bookmarks
1136 fm = ui.formatter('bookmarks', opts)
1136 fm = ui.formatter('bookmarks', opts)
1137 hexfn = fm.hexfunc
1137 hexfn = fm.hexfunc
1138 marks = repo._bookmarks
1138 marks = repo._bookmarks
1139 if len(marks) == 0 and fm.isplain():
1139 if len(marks) == 0 and fm.isplain():
1140 ui.status(_("no bookmarks set\n"))
1140 ui.status(_("no bookmarks set\n"))
1141 for bmark, n in sorted(marks.iteritems()):
1141 for bmark, n in sorted(marks.iteritems()):
1142 active = repo._activebookmark
1142 active = repo._activebookmark
1143 if bmark == active:
1143 if bmark == active:
1144 prefix, label = '*', activebookmarklabel
1144 prefix, label = '*', activebookmarklabel
1145 else:
1145 else:
1146 prefix, label = ' ', ''
1146 prefix, label = ' ', ''
1147
1147
1148 fm.startitem()
1148 fm.startitem()
1149 if not ui.quiet:
1149 if not ui.quiet:
1150 fm.plain(' %s ' % prefix, label=label)
1150 fm.plain(' %s ' % prefix, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1152 pad = " " * (25 - encoding.colwidth(bmark))
1152 pad = " " * (25 - encoding.colwidth(bmark))
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1154 repo.changelog.rev(n), hexfn(n), label=label)
1154 repo.changelog.rev(n), hexfn(n), label=label)
1155 fm.data(active=(bmark == active))
1155 fm.data(active=(bmark == active))
1156 fm.plain('\n')
1156 fm.plain('\n')
1157 fm.end()
1157 fm.end()
1158
1158
1159 @command('branch',
1159 @command('branch',
1160 [('f', 'force', None,
1160 [('f', 'force', None,
1161 _('set branch name even if it shadows an existing branch')),
1161 _('set branch name even if it shadows an existing branch')),
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1163 _('[-fC] [NAME]'))
1163 _('[-fC] [NAME]'))
1164 def branch(ui, repo, label=None, **opts):
1164 def branch(ui, repo, label=None, **opts):
1165 """set or show the current branch name
1165 """set or show the current branch name
1166
1166
1167 .. note::
1167 .. note::
1168
1168
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1171 information about named branches and bookmarks.
1171 information about named branches and bookmarks.
1172
1172
1173 With no argument, show the current branch name. With one argument,
1173 With no argument, show the current branch name. With one argument,
1174 set the working directory branch name (the branch will not exist
1174 set the working directory branch name (the branch will not exist
1175 in the repository until the next commit). Standard practice
1175 in the repository until the next commit). Standard practice
1176 recommends that primary development take place on the 'default'
1176 recommends that primary development take place on the 'default'
1177 branch.
1177 branch.
1178
1178
1179 Unless -f/--force is specified, branch will not let you set a
1179 Unless -f/--force is specified, branch will not let you set a
1180 branch name that already exists.
1180 branch name that already exists.
1181
1181
1182 Use -C/--clean to reset the working directory branch to that of
1182 Use -C/--clean to reset the working directory branch to that of
1183 the parent of the working directory, negating a previous branch
1183 the parent of the working directory, negating a previous branch
1184 change.
1184 change.
1185
1185
1186 Use the command :hg:`update` to switch to an existing branch. Use
1186 Use the command :hg:`update` to switch to an existing branch. Use
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1188 When all heads of a branch are closed, the branch will be
1188 When all heads of a branch are closed, the branch will be
1189 considered closed.
1189 considered closed.
1190
1190
1191 Returns 0 on success.
1191 Returns 0 on success.
1192 """
1192 """
1193 if label:
1193 if label:
1194 label = label.strip()
1194 label = label.strip()
1195
1195
1196 if not opts.get('clean') and not label:
1196 if not opts.get('clean') and not label:
1197 ui.write("%s\n" % repo.dirstate.branch())
1197 ui.write("%s\n" % repo.dirstate.branch())
1198 return
1198 return
1199
1199
1200 with repo.wlock():
1200 with repo.wlock():
1201 if opts.get('clean'):
1201 if opts.get('clean'):
1202 label = repo[None].p1().branch()
1202 label = repo[None].p1().branch()
1203 repo.dirstate.setbranch(label)
1203 repo.dirstate.setbranch(label)
1204 ui.status(_('reset working directory to branch %s\n') % label)
1204 ui.status(_('reset working directory to branch %s\n') % label)
1205 elif label:
1205 elif label:
1206 if not opts.get('force') and label in repo.branchmap():
1206 if not opts.get('force') and label in repo.branchmap():
1207 if label not in [p.branch() for p in repo[None].parents()]:
1207 if label not in [p.branch() for p in repo[None].parents()]:
1208 raise error.Abort(_('a branch of the same name already'
1208 raise error.Abort(_('a branch of the same name already'
1209 ' exists'),
1209 ' exists'),
1210 # i18n: "it" refers to an existing branch
1210 # i18n: "it" refers to an existing branch
1211 hint=_("use 'hg update' to switch to it"))
1211 hint=_("use 'hg update' to switch to it"))
1212 scmutil.checknewlabel(repo, label, 'branch')
1212 scmutil.checknewlabel(repo, label, 'branch')
1213 repo.dirstate.setbranch(label)
1213 repo.dirstate.setbranch(label)
1214 ui.status(_('marked working directory as branch %s\n') % label)
1214 ui.status(_('marked working directory as branch %s\n') % label)
1215
1215
1216 # find any open named branches aside from default
1216 # find any open named branches aside from default
1217 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1217 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1218 if n != "default" and not c]
1218 if n != "default" and not c]
1219 if not others:
1219 if not others:
1220 ui.status(_('(branches are permanent and global, '
1220 ui.status(_('(branches are permanent and global, '
1221 'did you want a bookmark?)\n'))
1221 'did you want a bookmark?)\n'))
1222
1222
1223 @command('branches',
1223 @command('branches',
1224 [('a', 'active', False,
1224 [('a', 'active', False,
1225 _('show only branches that have unmerged heads (DEPRECATED)')),
1225 _('show only branches that have unmerged heads (DEPRECATED)')),
1226 ('c', 'closed', False, _('show normal and closed branches')),
1226 ('c', 'closed', False, _('show normal and closed branches')),
1227 ] + formatteropts,
1227 ] + formatteropts,
1228 _('[-c]'))
1228 _('[-c]'))
1229 def branches(ui, repo, active=False, closed=False, **opts):
1229 def branches(ui, repo, active=False, closed=False, **opts):
1230 """list repository named branches
1230 """list repository named branches
1231
1231
1232 List the repository's named branches, indicating which ones are
1232 List the repository's named branches, indicating which ones are
1233 inactive. If -c/--closed is specified, also list branches which have
1233 inactive. If -c/--closed is specified, also list branches which have
1234 been marked closed (see :hg:`commit --close-branch`).
1234 been marked closed (see :hg:`commit --close-branch`).
1235
1235
1236 Use the command :hg:`update` to switch to an existing branch.
1236 Use the command :hg:`update` to switch to an existing branch.
1237
1237
1238 Returns 0.
1238 Returns 0.
1239 """
1239 """
1240
1240
1241 fm = ui.formatter('branches', opts)
1241 fm = ui.formatter('branches', opts)
1242 hexfunc = fm.hexfunc
1242 hexfunc = fm.hexfunc
1243
1243
1244 allheads = set(repo.heads())
1244 allheads = set(repo.heads())
1245 branches = []
1245 branches = []
1246 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1246 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1247 isactive = not isclosed and bool(set(heads) & allheads)
1247 isactive = not isclosed and bool(set(heads) & allheads)
1248 branches.append((tag, repo[tip], isactive, not isclosed))
1248 branches.append((tag, repo[tip], isactive, not isclosed))
1249 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1249 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1250 reverse=True)
1250 reverse=True)
1251
1251
1252 for tag, ctx, isactive, isopen in branches:
1252 for tag, ctx, isactive, isopen in branches:
1253 if active and not isactive:
1253 if active and not isactive:
1254 continue
1254 continue
1255 if isactive:
1255 if isactive:
1256 label = 'branches.active'
1256 label = 'branches.active'
1257 notice = ''
1257 notice = ''
1258 elif not isopen:
1258 elif not isopen:
1259 if not closed:
1259 if not closed:
1260 continue
1260 continue
1261 label = 'branches.closed'
1261 label = 'branches.closed'
1262 notice = _(' (closed)')
1262 notice = _(' (closed)')
1263 else:
1263 else:
1264 label = 'branches.inactive'
1264 label = 'branches.inactive'
1265 notice = _(' (inactive)')
1265 notice = _(' (inactive)')
1266 current = (tag == repo.dirstate.branch())
1266 current = (tag == repo.dirstate.branch())
1267 if current:
1267 if current:
1268 label = 'branches.current'
1268 label = 'branches.current'
1269
1269
1270 fm.startitem()
1270 fm.startitem()
1271 fm.write('branch', '%s', tag, label=label)
1271 fm.write('branch', '%s', tag, label=label)
1272 rev = ctx.rev()
1272 rev = ctx.rev()
1273 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1273 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1274 fmt = ' ' * padsize + ' %d:%s'
1274 fmt = ' ' * padsize + ' %d:%s'
1275 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1275 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1276 label='log.changeset changeset.%s' % ctx.phasestr())
1276 label='log.changeset changeset.%s' % ctx.phasestr())
1277 fm.data(active=isactive, closed=not isopen, current=current)
1277 fm.data(active=isactive, closed=not isopen, current=current)
1278 if not ui.quiet:
1278 if not ui.quiet:
1279 fm.plain(notice)
1279 fm.plain(notice)
1280 fm.plain('\n')
1280 fm.plain('\n')
1281 fm.end()
1281 fm.end()
1282
1282
1283 @command('bundle',
1283 @command('bundle',
1284 [('f', 'force', None, _('run even when the destination is unrelated')),
1284 [('f', 'force', None, _('run even when the destination is unrelated')),
1285 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1285 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1286 _('REV')),
1286 _('REV')),
1287 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1287 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1288 _('BRANCH')),
1288 _('BRANCH')),
1289 ('', 'base', [],
1289 ('', 'base', [],
1290 _('a base changeset assumed to be available at the destination'),
1290 _('a base changeset assumed to be available at the destination'),
1291 _('REV')),
1291 _('REV')),
1292 ('a', 'all', None, _('bundle all changesets in the repository')),
1292 ('a', 'all', None, _('bundle all changesets in the repository')),
1293 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1293 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1294 ] + remoteopts,
1294 ] + remoteopts,
1295 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1295 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1296 def bundle(ui, repo, fname, dest=None, **opts):
1296 def bundle(ui, repo, fname, dest=None, **opts):
1297 """create a changegroup file
1297 """create a changegroup file
1298
1298
1299 Generate a changegroup file collecting changesets to be added
1299 Generate a changegroup file collecting changesets to be added
1300 to a repository.
1300 to a repository.
1301
1301
1302 To create a bundle containing all changesets, use -a/--all
1302 To create a bundle containing all changesets, use -a/--all
1303 (or --base null). Otherwise, hg assumes the destination will have
1303 (or --base null). Otherwise, hg assumes the destination will have
1304 all the nodes you specify with --base parameters. Otherwise, hg
1304 all the nodes you specify with --base parameters. Otherwise, hg
1305 will assume the repository has all the nodes in destination, or
1305 will assume the repository has all the nodes in destination, or
1306 default-push/default if no destination is specified.
1306 default-push/default if no destination is specified.
1307
1307
1308 You can change bundle format with the -t/--type option. You can
1308 You can change bundle format with the -t/--type option. You can
1309 specify a compression, a bundle version or both using a dash
1309 specify a compression, a bundle version or both using a dash
1310 (comp-version). The available compression methods are: none, bzip2,
1310 (comp-version). The available compression methods are: none, bzip2,
1311 and gzip (by default, bundles are compressed using bzip2). The
1311 and gzip (by default, bundles are compressed using bzip2). The
1312 available formats are: v1, v2 (default to most suitable).
1312 available formats are: v1, v2 (default to most suitable).
1313
1313
1314 The bundle file can then be transferred using conventional means
1314 The bundle file can then be transferred using conventional means
1315 and applied to another repository with the unbundle or pull
1315 and applied to another repository with the unbundle or pull
1316 command. This is useful when direct push and pull are not
1316 command. This is useful when direct push and pull are not
1317 available or when exporting an entire repository is undesirable.
1317 available or when exporting an entire repository is undesirable.
1318
1318
1319 Applying bundles preserves all changeset contents including
1319 Applying bundles preserves all changeset contents including
1320 permissions, copy/rename information, and revision history.
1320 permissions, copy/rename information, and revision history.
1321
1321
1322 Returns 0 on success, 1 if no changes found.
1322 Returns 0 on success, 1 if no changes found.
1323 """
1323 """
1324 revs = None
1324 revs = None
1325 if 'rev' in opts:
1325 if 'rev' in opts:
1326 revstrings = opts['rev']
1326 revstrings = opts['rev']
1327 revs = scmutil.revrange(repo, revstrings)
1327 revs = scmutil.revrange(repo, revstrings)
1328 if revstrings and not revs:
1328 if revstrings and not revs:
1329 raise error.Abort(_('no commits to bundle'))
1329 raise error.Abort(_('no commits to bundle'))
1330
1330
1331 bundletype = opts.get('type', 'bzip2').lower()
1331 bundletype = opts.get('type', 'bzip2').lower()
1332 try:
1332 try:
1333 bcompression, cgversion, params = exchange.parsebundlespec(
1333 bcompression, cgversion, params = exchange.parsebundlespec(
1334 repo, bundletype, strict=False)
1334 repo, bundletype, strict=False)
1335 except error.UnsupportedBundleSpecification as e:
1335 except error.UnsupportedBundleSpecification as e:
1336 raise error.Abort(str(e),
1336 raise error.Abort(str(e),
1337 hint=_("see 'hg help bundle' for supported "
1337 hint=_("see 'hg help bundle' for supported "
1338 "values for --type"))
1338 "values for --type"))
1339
1339
1340 # Packed bundles are a pseudo bundle format for now.
1340 # Packed bundles are a pseudo bundle format for now.
1341 if cgversion == 's1':
1341 if cgversion == 's1':
1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1343 hint=_("use 'hg debugcreatestreamclonebundle'"))
1343 hint=_("use 'hg debugcreatestreamclonebundle'"))
1344
1344
1345 if opts.get('all'):
1345 if opts.get('all'):
1346 if dest:
1346 if dest:
1347 raise error.Abort(_("--all is incompatible with specifying "
1347 raise error.Abort(_("--all is incompatible with specifying "
1348 "a destination"))
1348 "a destination"))
1349 if opts.get('base'):
1349 if opts.get('base'):
1350 ui.warn(_("ignoring --base because --all was specified\n"))
1350 ui.warn(_("ignoring --base because --all was specified\n"))
1351 base = ['null']
1351 base = ['null']
1352 else:
1352 else:
1353 base = scmutil.revrange(repo, opts.get('base'))
1353 base = scmutil.revrange(repo, opts.get('base'))
1354 # TODO: get desired bundlecaps from command line.
1354 # TODO: get desired bundlecaps from command line.
1355 bundlecaps = None
1355 bundlecaps = None
1356 if cgversion not in changegroup.supportedoutgoingversions(repo):
1356 if cgversion not in changegroup.supportedoutgoingversions(repo):
1357 raise error.Abort(_("repository does not support bundle version %s") %
1357 raise error.Abort(_("repository does not support bundle version %s") %
1358 cgversion)
1358 cgversion)
1359
1359
1360 if base:
1360 if base:
1361 if dest:
1361 if dest:
1362 raise error.Abort(_("--base is incompatible with specifying "
1362 raise error.Abort(_("--base is incompatible with specifying "
1363 "a destination"))
1363 "a destination"))
1364 common = [repo.lookup(rev) for rev in base]
1364 common = [repo.lookup(rev) for rev in base]
1365 heads = revs and map(repo.lookup, revs) or None
1365 heads = revs and map(repo.lookup, revs) or None
1366 outgoing = discovery.outgoing(repo, common, heads)
1366 outgoing = discovery.outgoing(repo, common, heads)
1367 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1367 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1368 bundlecaps=bundlecaps,
1368 bundlecaps=bundlecaps,
1369 version=cgversion)
1369 version=cgversion)
1370 outgoing = None
1370 outgoing = None
1371 else:
1371 else:
1372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1373 dest, branches = hg.parseurl(dest, opts.get('branch'))
1373 dest, branches = hg.parseurl(dest, opts.get('branch'))
1374 other = hg.peer(repo, opts, dest)
1374 other = hg.peer(repo, opts, dest)
1375 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1375 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1376 heads = revs and map(repo.lookup, revs) or revs
1376 heads = revs and map(repo.lookup, revs) or revs
1377 outgoing = discovery.findcommonoutgoing(repo, other,
1377 outgoing = discovery.findcommonoutgoing(repo, other,
1378 onlyheads=heads,
1378 onlyheads=heads,
1379 force=opts.get('force'),
1379 force=opts.get('force'),
1380 portable=True)
1380 portable=True)
1381 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1381 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1382 bundlecaps, version=cgversion)
1382 bundlecaps, version=cgversion)
1383 if not cg:
1383 if not cg:
1384 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1384 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1385 return 1
1385 return 1
1386
1386
1387 if cgversion == '01': #bundle1
1387 if cgversion == '01': #bundle1
1388 if bcompression is None:
1388 if bcompression is None:
1389 bcompression = 'UN'
1389 bcompression = 'UN'
1390 bversion = 'HG10' + bcompression
1390 bversion = 'HG10' + bcompression
1391 bcompression = None
1391 bcompression = None
1392 else:
1392 else:
1393 assert cgversion == '02'
1393 assert cgversion == '02'
1394 bversion = 'HG20'
1394 bversion = 'HG20'
1395
1395
1396 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1396 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1397
1397
1398 @command('cat',
1398 @command('cat',
1399 [('o', 'output', '',
1399 [('o', 'output', '',
1400 _('print output to file with formatted name'), _('FORMAT')),
1400 _('print output to file with formatted name'), _('FORMAT')),
1401 ('r', 'rev', '', _('print the given revision'), _('REV')),
1401 ('r', 'rev', '', _('print the given revision'), _('REV')),
1402 ('', 'decode', None, _('apply any matching decode filter')),
1402 ('', 'decode', None, _('apply any matching decode filter')),
1403 ] + walkopts,
1403 ] + walkopts,
1404 _('[OPTION]... FILE...'),
1404 _('[OPTION]... FILE...'),
1405 inferrepo=True)
1405 inferrepo=True)
1406 def cat(ui, repo, file1, *pats, **opts):
1406 def cat(ui, repo, file1, *pats, **opts):
1407 """output the current or given revision of files
1407 """output the current or given revision of files
1408
1408
1409 Print the specified files as they were at the given revision. If
1409 Print the specified files as they were at the given revision. If
1410 no revision is given, the parent of the working directory is used.
1410 no revision is given, the parent of the working directory is used.
1411
1411
1412 Output may be to a file, in which case the name of the file is
1412 Output may be to a file, in which case the name of the file is
1413 given using a format string. The formatting rules as follows:
1413 given using a format string. The formatting rules as follows:
1414
1414
1415 :``%%``: literal "%" character
1415 :``%%``: literal "%" character
1416 :``%s``: basename of file being printed
1416 :``%s``: basename of file being printed
1417 :``%d``: dirname of file being printed, or '.' if in repository root
1417 :``%d``: dirname of file being printed, or '.' if in repository root
1418 :``%p``: root-relative path name of file being printed
1418 :``%p``: root-relative path name of file being printed
1419 :``%H``: changeset hash (40 hexadecimal digits)
1419 :``%H``: changeset hash (40 hexadecimal digits)
1420 :``%R``: changeset revision number
1420 :``%R``: changeset revision number
1421 :``%h``: short-form changeset hash (12 hexadecimal digits)
1421 :``%h``: short-form changeset hash (12 hexadecimal digits)
1422 :``%r``: zero-padded changeset revision number
1422 :``%r``: zero-padded changeset revision number
1423 :``%b``: basename of the exporting repository
1423 :``%b``: basename of the exporting repository
1424
1424
1425 Returns 0 on success.
1425 Returns 0 on success.
1426 """
1426 """
1427 ctx = scmutil.revsingle(repo, opts.get('rev'))
1427 ctx = scmutil.revsingle(repo, opts.get('rev'))
1428 m = scmutil.match(ctx, (file1,) + pats, opts)
1428 m = scmutil.match(ctx, (file1,) + pats, opts)
1429
1429
1430 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1430 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1431
1431
1432 @command('^clone',
1432 @command('^clone',
1433 [('U', 'noupdate', None, _('the clone will include an empty working '
1433 [('U', 'noupdate', None, _('the clone will include an empty working '
1434 'directory (only a repository)')),
1434 'directory (only a repository)')),
1435 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1435 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1436 _('REV')),
1436 _('REV')),
1437 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1437 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1438 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1438 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1439 ('', 'pull', None, _('use pull protocol to copy metadata')),
1439 ('', 'pull', None, _('use pull protocol to copy metadata')),
1440 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1440 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1441 ] + remoteopts,
1441 ] + remoteopts,
1442 _('[OPTION]... SOURCE [DEST]'),
1442 _('[OPTION]... SOURCE [DEST]'),
1443 norepo=True)
1443 norepo=True)
1444 def clone(ui, source, dest=None, **opts):
1444 def clone(ui, source, dest=None, **opts):
1445 """make a copy of an existing repository
1445 """make a copy of an existing repository
1446
1446
1447 Create a copy of an existing repository in a new directory.
1447 Create a copy of an existing repository in a new directory.
1448
1448
1449 If no destination directory name is specified, it defaults to the
1449 If no destination directory name is specified, it defaults to the
1450 basename of the source.
1450 basename of the source.
1451
1451
1452 The location of the source is added to the new repository's
1452 The location of the source is added to the new repository's
1453 ``.hg/hgrc`` file, as the default to be used for future pulls.
1453 ``.hg/hgrc`` file, as the default to be used for future pulls.
1454
1454
1455 Only local paths and ``ssh://`` URLs are supported as
1455 Only local paths and ``ssh://`` URLs are supported as
1456 destinations. For ``ssh://`` destinations, no working directory or
1456 destinations. For ``ssh://`` destinations, no working directory or
1457 ``.hg/hgrc`` will be created on the remote side.
1457 ``.hg/hgrc`` will be created on the remote side.
1458
1458
1459 If the source repository has a bookmark called '@' set, that
1459 If the source repository has a bookmark called '@' set, that
1460 revision will be checked out in the new repository by default.
1460 revision will be checked out in the new repository by default.
1461
1461
1462 To check out a particular version, use -u/--update, or
1462 To check out a particular version, use -u/--update, or
1463 -U/--noupdate to create a clone with no working directory.
1463 -U/--noupdate to create a clone with no working directory.
1464
1464
1465 To pull only a subset of changesets, specify one or more revisions
1465 To pull only a subset of changesets, specify one or more revisions
1466 identifiers with -r/--rev or branches with -b/--branch. The
1466 identifiers with -r/--rev or branches with -b/--branch. The
1467 resulting clone will contain only the specified changesets and
1467 resulting clone will contain only the specified changesets and
1468 their ancestors. These options (or 'clone src#rev dest') imply
1468 their ancestors. These options (or 'clone src#rev dest') imply
1469 --pull, even for local source repositories.
1469 --pull, even for local source repositories.
1470
1470
1471 .. note::
1471 .. note::
1472
1472
1473 Specifying a tag will include the tagged changeset but not the
1473 Specifying a tag will include the tagged changeset but not the
1474 changeset containing the tag.
1474 changeset containing the tag.
1475
1475
1476 .. container:: verbose
1476 .. container:: verbose
1477
1477
1478 For efficiency, hardlinks are used for cloning whenever the
1478 For efficiency, hardlinks are used for cloning whenever the
1479 source and destination are on the same filesystem (note this
1479 source and destination are on the same filesystem (note this
1480 applies only to the repository data, not to the working
1480 applies only to the repository data, not to the working
1481 directory). Some filesystems, such as AFS, implement hardlinking
1481 directory). Some filesystems, such as AFS, implement hardlinking
1482 incorrectly, but do not report errors. In these cases, use the
1482 incorrectly, but do not report errors. In these cases, use the
1483 --pull option to avoid hardlinking.
1483 --pull option to avoid hardlinking.
1484
1484
1485 In some cases, you can clone repositories and the working
1485 In some cases, you can clone repositories and the working
1486 directory using full hardlinks with ::
1486 directory using full hardlinks with ::
1487
1487
1488 $ cp -al REPO REPOCLONE
1488 $ cp -al REPO REPOCLONE
1489
1489
1490 This is the fastest way to clone, but it is not always safe. The
1490 This is the fastest way to clone, but it is not always safe. The
1491 operation is not atomic (making sure REPO is not modified during
1491 operation is not atomic (making sure REPO is not modified during
1492 the operation is up to you) and you have to make sure your
1492 the operation is up to you) and you have to make sure your
1493 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1493 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1494 so). Also, this is not compatible with certain extensions that
1494 so). Also, this is not compatible with certain extensions that
1495 place their metadata under the .hg directory, such as mq.
1495 place their metadata under the .hg directory, such as mq.
1496
1496
1497 Mercurial will update the working directory to the first applicable
1497 Mercurial will update the working directory to the first applicable
1498 revision from this list:
1498 revision from this list:
1499
1499
1500 a) null if -U or the source repository has no changesets
1500 a) null if -U or the source repository has no changesets
1501 b) if -u . and the source repository is local, the first parent of
1501 b) if -u . and the source repository is local, the first parent of
1502 the source repository's working directory
1502 the source repository's working directory
1503 c) the changeset specified with -u (if a branch name, this means the
1503 c) the changeset specified with -u (if a branch name, this means the
1504 latest head of that branch)
1504 latest head of that branch)
1505 d) the changeset specified with -r
1505 d) the changeset specified with -r
1506 e) the tipmost head specified with -b
1506 e) the tipmost head specified with -b
1507 f) the tipmost head specified with the url#branch source syntax
1507 f) the tipmost head specified with the url#branch source syntax
1508 g) the revision marked with the '@' bookmark, if present
1508 g) the revision marked with the '@' bookmark, if present
1509 h) the tipmost head of the default branch
1509 h) the tipmost head of the default branch
1510 i) tip
1510 i) tip
1511
1511
1512 When cloning from servers that support it, Mercurial may fetch
1512 When cloning from servers that support it, Mercurial may fetch
1513 pre-generated data from a server-advertised URL. When this is done,
1513 pre-generated data from a server-advertised URL. When this is done,
1514 hooks operating on incoming changesets and changegroups may fire twice,
1514 hooks operating on incoming changesets and changegroups may fire twice,
1515 once for the bundle fetched from the URL and another for any additional
1515 once for the bundle fetched from the URL and another for any additional
1516 data not fetched from this URL. In addition, if an error occurs, the
1516 data not fetched from this URL. In addition, if an error occurs, the
1517 repository may be rolled back to a partial clone. This behavior may
1517 repository may be rolled back to a partial clone. This behavior may
1518 change in future releases. See :hg:`help -e clonebundles` for more.
1518 change in future releases. See :hg:`help -e clonebundles` for more.
1519
1519
1520 Examples:
1520 Examples:
1521
1521
1522 - clone a remote repository to a new directory named hg/::
1522 - clone a remote repository to a new directory named hg/::
1523
1523
1524 hg clone https://www.mercurial-scm.org/repo/hg/
1524 hg clone https://www.mercurial-scm.org/repo/hg/
1525
1525
1526 - create a lightweight local clone::
1526 - create a lightweight local clone::
1527
1527
1528 hg clone project/ project-feature/
1528 hg clone project/ project-feature/
1529
1529
1530 - clone from an absolute path on an ssh server (note double-slash)::
1530 - clone from an absolute path on an ssh server (note double-slash)::
1531
1531
1532 hg clone ssh://user@server//home/projects/alpha/
1532 hg clone ssh://user@server//home/projects/alpha/
1533
1533
1534 - do a high-speed clone over a LAN while checking out a
1534 - do a high-speed clone over a LAN while checking out a
1535 specified version::
1535 specified version::
1536
1536
1537 hg clone --uncompressed http://server/repo -u 1.5
1537 hg clone --uncompressed http://server/repo -u 1.5
1538
1538
1539 - create a repository without changesets after a particular revision::
1539 - create a repository without changesets after a particular revision::
1540
1540
1541 hg clone -r 04e544 experimental/ good/
1541 hg clone -r 04e544 experimental/ good/
1542
1542
1543 - clone (and track) a particular named branch::
1543 - clone (and track) a particular named branch::
1544
1544
1545 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1545 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1546
1546
1547 See :hg:`help urls` for details on specifying URLs.
1547 See :hg:`help urls` for details on specifying URLs.
1548
1548
1549 Returns 0 on success.
1549 Returns 0 on success.
1550 """
1550 """
1551 if opts.get('noupdate') and opts.get('updaterev'):
1551 if opts.get('noupdate') and opts.get('updaterev'):
1552 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1552 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1553
1553
1554 r = hg.clone(ui, opts, source, dest,
1554 r = hg.clone(ui, opts, source, dest,
1555 pull=opts.get('pull'),
1555 pull=opts.get('pull'),
1556 stream=opts.get('uncompressed'),
1556 stream=opts.get('uncompressed'),
1557 rev=opts.get('rev'),
1557 rev=opts.get('rev'),
1558 update=opts.get('updaterev') or not opts.get('noupdate'),
1558 update=opts.get('updaterev') or not opts.get('noupdate'),
1559 branch=opts.get('branch'),
1559 branch=opts.get('branch'),
1560 shareopts=opts.get('shareopts'))
1560 shareopts=opts.get('shareopts'))
1561
1561
1562 return r is None
1562 return r is None
1563
1563
1564 @command('^commit|ci',
1564 @command('^commit|ci',
1565 [('A', 'addremove', None,
1565 [('A', 'addremove', None,
1566 _('mark new/missing files as added/removed before committing')),
1566 _('mark new/missing files as added/removed before committing')),
1567 ('', 'close-branch', None,
1567 ('', 'close-branch', None,
1568 _('mark a branch head as closed')),
1568 _('mark a branch head as closed')),
1569 ('', 'amend', None, _('amend the parent of the working directory')),
1569 ('', 'amend', None, _('amend the parent of the working directory')),
1570 ('s', 'secret', None, _('use the secret phase for committing')),
1570 ('s', 'secret', None, _('use the secret phase for committing')),
1571 ('e', 'edit', None, _('invoke editor on commit messages')),
1571 ('e', 'edit', None, _('invoke editor on commit messages')),
1572 ('i', 'interactive', None, _('use interactive mode')),
1572 ('i', 'interactive', None, _('use interactive mode')),
1573 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1573 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1574 _('[OPTION]... [FILE]...'),
1574 _('[OPTION]... [FILE]...'),
1575 inferrepo=True)
1575 inferrepo=True)
1576 def commit(ui, repo, *pats, **opts):
1576 def commit(ui, repo, *pats, **opts):
1577 """commit the specified files or all outstanding changes
1577 """commit the specified files or all outstanding changes
1578
1578
1579 Commit changes to the given files into the repository. Unlike a
1579 Commit changes to the given files into the repository. Unlike a
1580 centralized SCM, this operation is a local operation. See
1580 centralized SCM, this operation is a local operation. See
1581 :hg:`push` for a way to actively distribute your changes.
1581 :hg:`push` for a way to actively distribute your changes.
1582
1582
1583 If a list of files is omitted, all changes reported by :hg:`status`
1583 If a list of files is omitted, all changes reported by :hg:`status`
1584 will be committed.
1584 will be committed.
1585
1585
1586 If you are committing the result of a merge, do not provide any
1586 If you are committing the result of a merge, do not provide any
1587 filenames or -I/-X filters.
1587 filenames or -I/-X filters.
1588
1588
1589 If no commit message is specified, Mercurial starts your
1589 If no commit message is specified, Mercurial starts your
1590 configured editor where you can enter a message. In case your
1590 configured editor where you can enter a message. In case your
1591 commit fails, you will find a backup of your message in
1591 commit fails, you will find a backup of your message in
1592 ``.hg/last-message.txt``.
1592 ``.hg/last-message.txt``.
1593
1593
1594 The --close-branch flag can be used to mark the current branch
1594 The --close-branch flag can be used to mark the current branch
1595 head closed. When all heads of a branch are closed, the branch
1595 head closed. When all heads of a branch are closed, the branch
1596 will be considered closed and no longer listed.
1596 will be considered closed and no longer listed.
1597
1597
1598 The --amend flag can be used to amend the parent of the
1598 The --amend flag can be used to amend the parent of the
1599 working directory with a new commit that contains the changes
1599 working directory with a new commit that contains the changes
1600 in the parent in addition to those currently reported by :hg:`status`,
1600 in the parent in addition to those currently reported by :hg:`status`,
1601 if there are any. The old commit is stored in a backup bundle in
1601 if there are any. The old commit is stored in a backup bundle in
1602 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1602 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1603 on how to restore it).
1603 on how to restore it).
1604
1604
1605 Message, user and date are taken from the amended commit unless
1605 Message, user and date are taken from the amended commit unless
1606 specified. When a message isn't specified on the command line,
1606 specified. When a message isn't specified on the command line,
1607 the editor will open with the message of the amended commit.
1607 the editor will open with the message of the amended commit.
1608
1608
1609 It is not possible to amend public changesets (see :hg:`help phases`)
1609 It is not possible to amend public changesets (see :hg:`help phases`)
1610 or changesets that have children.
1610 or changesets that have children.
1611
1611
1612 See :hg:`help dates` for a list of formats valid for -d/--date.
1612 See :hg:`help dates` for a list of formats valid for -d/--date.
1613
1613
1614 Returns 0 on success, 1 if nothing changed.
1614 Returns 0 on success, 1 if nothing changed.
1615
1615
1616 .. container:: verbose
1616 .. container:: verbose
1617
1617
1618 Examples:
1618 Examples:
1619
1619
1620 - commit all files ending in .py::
1620 - commit all files ending in .py::
1621
1621
1622 hg commit --include "set:**.py"
1622 hg commit --include "set:**.py"
1623
1623
1624 - commit all non-binary files::
1624 - commit all non-binary files::
1625
1625
1626 hg commit --exclude "set:binary()"
1626 hg commit --exclude "set:binary()"
1627
1627
1628 - amend the current commit and set the date to now::
1628 - amend the current commit and set the date to now::
1629
1629
1630 hg commit --amend --date now
1630 hg commit --amend --date now
1631 """
1631 """
1632 wlock = lock = None
1632 wlock = lock = None
1633 try:
1633 try:
1634 wlock = repo.wlock()
1634 wlock = repo.wlock()
1635 lock = repo.lock()
1635 lock = repo.lock()
1636 return _docommit(ui, repo, *pats, **opts)
1636 return _docommit(ui, repo, *pats, **opts)
1637 finally:
1637 finally:
1638 release(lock, wlock)
1638 release(lock, wlock)
1639
1639
1640 def _docommit(ui, repo, *pats, **opts):
1640 def _docommit(ui, repo, *pats, **opts):
1641 if opts.get('interactive'):
1641 if opts.get('interactive'):
1642 opts.pop('interactive')
1642 opts.pop('interactive')
1643 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1643 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1644 cmdutil.recordfilter, *pats, **opts)
1644 cmdutil.recordfilter, *pats, **opts)
1645 # ret can be 0 (no changes to record) or the value returned by
1645 # ret can be 0 (no changes to record) or the value returned by
1646 # commit(), 1 if nothing changed or None on success.
1646 # commit(), 1 if nothing changed or None on success.
1647 return 1 if ret == 0 else ret
1647 return 1 if ret == 0 else ret
1648
1648
1649 if opts.get('subrepos'):
1649 if opts.get('subrepos'):
1650 if opts.get('amend'):
1650 if opts.get('amend'):
1651 raise error.Abort(_('cannot amend with --subrepos'))
1651 raise error.Abort(_('cannot amend with --subrepos'))
1652 # Let --subrepos on the command line override config setting.
1652 # Let --subrepos on the command line override config setting.
1653 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1653 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1654
1654
1655 cmdutil.checkunfinished(repo, commit=True)
1655 cmdutil.checkunfinished(repo, commit=True)
1656
1656
1657 branch = repo[None].branch()
1657 branch = repo[None].branch()
1658 bheads = repo.branchheads(branch)
1658 bheads = repo.branchheads(branch)
1659
1659
1660 extra = {}
1660 extra = {}
1661 if opts.get('close_branch'):
1661 if opts.get('close_branch'):
1662 extra['close'] = 1
1662 extra['close'] = 1
1663
1663
1664 if not bheads:
1664 if not bheads:
1665 raise error.Abort(_('can only close branch heads'))
1665 raise error.Abort(_('can only close branch heads'))
1666 elif opts.get('amend'):
1666 elif opts.get('amend'):
1667 if repo[None].parents()[0].p1().branch() != branch and \
1667 if repo[None].parents()[0].p1().branch() != branch and \
1668 repo[None].parents()[0].p2().branch() != branch:
1668 repo[None].parents()[0].p2().branch() != branch:
1669 raise error.Abort(_('can only close branch heads'))
1669 raise error.Abort(_('can only close branch heads'))
1670
1670
1671 if opts.get('amend'):
1671 if opts.get('amend'):
1672 if ui.configbool('ui', 'commitsubrepos'):
1672 if ui.configbool('ui', 'commitsubrepos'):
1673 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1673 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1674
1674
1675 old = repo['.']
1675 old = repo['.']
1676 if not old.mutable():
1676 if not old.mutable():
1677 raise error.Abort(_('cannot amend public changesets'))
1677 raise error.Abort(_('cannot amend public changesets'))
1678 if len(repo[None].parents()) > 1:
1678 if len(repo[None].parents()) > 1:
1679 raise error.Abort(_('cannot amend while merging'))
1679 raise error.Abort(_('cannot amend while merging'))
1680 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1680 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1681 if not allowunstable and old.children():
1681 if not allowunstable and old.children():
1682 raise error.Abort(_('cannot amend changeset with children'))
1682 raise error.Abort(_('cannot amend changeset with children'))
1683
1683
1684 # Currently histedit gets confused if an amend happens while histedit
1684 # Currently histedit gets confused if an amend happens while histedit
1685 # is in progress. Since we have a checkunfinished command, we are
1685 # is in progress. Since we have a checkunfinished command, we are
1686 # temporarily honoring it.
1686 # temporarily honoring it.
1687 #
1687 #
1688 # Note: eventually this guard will be removed. Please do not expect
1688 # Note: eventually this guard will be removed. Please do not expect
1689 # this behavior to remain.
1689 # this behavior to remain.
1690 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1690 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1691 cmdutil.checkunfinished(repo)
1691 cmdutil.checkunfinished(repo)
1692
1692
1693 # commitfunc is used only for temporary amend commit by cmdutil.amend
1693 # commitfunc is used only for temporary amend commit by cmdutil.amend
1694 def commitfunc(ui, repo, message, match, opts):
1694 def commitfunc(ui, repo, message, match, opts):
1695 return repo.commit(message,
1695 return repo.commit(message,
1696 opts.get('user') or old.user(),
1696 opts.get('user') or old.user(),
1697 opts.get('date') or old.date(),
1697 opts.get('date') or old.date(),
1698 match,
1698 match,
1699 extra=extra)
1699 extra=extra)
1700
1700
1701 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1701 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1702 if node == old.node():
1702 if node == old.node():
1703 ui.status(_("nothing changed\n"))
1703 ui.status(_("nothing changed\n"))
1704 return 1
1704 return 1
1705 else:
1705 else:
1706 def commitfunc(ui, repo, message, match, opts):
1706 def commitfunc(ui, repo, message, match, opts):
1707 backup = ui.backupconfig('phases', 'new-commit')
1707 backup = ui.backupconfig('phases', 'new-commit')
1708 baseui = repo.baseui
1708 baseui = repo.baseui
1709 basebackup = baseui.backupconfig('phases', 'new-commit')
1709 basebackup = baseui.backupconfig('phases', 'new-commit')
1710 try:
1710 try:
1711 if opts.get('secret'):
1711 if opts.get('secret'):
1712 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1712 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1713 # Propagate to subrepos
1713 # Propagate to subrepos
1714 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1714 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1715
1715
1716 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1716 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1717 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1717 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1718 return repo.commit(message, opts.get('user'), opts.get('date'),
1718 return repo.commit(message, opts.get('user'), opts.get('date'),
1719 match,
1719 match,
1720 editor=editor,
1720 editor=editor,
1721 extra=extra)
1721 extra=extra)
1722 finally:
1722 finally:
1723 ui.restoreconfig(backup)
1723 ui.restoreconfig(backup)
1724 repo.baseui.restoreconfig(basebackup)
1724 repo.baseui.restoreconfig(basebackup)
1725
1725
1726
1726
1727 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1727 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1728
1728
1729 if not node:
1729 if not node:
1730 stat = cmdutil.postcommitstatus(repo, pats, opts)
1730 stat = cmdutil.postcommitstatus(repo, pats, opts)
1731 if stat[3]:
1731 if stat[3]:
1732 ui.status(_("nothing changed (%d missing files, see "
1732 ui.status(_("nothing changed (%d missing files, see "
1733 "'hg status')\n") % len(stat[3]))
1733 "'hg status')\n") % len(stat[3]))
1734 else:
1734 else:
1735 ui.status(_("nothing changed\n"))
1735 ui.status(_("nothing changed\n"))
1736 return 1
1736 return 1
1737
1737
1738 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1738 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1739
1739
1740 @command('config|showconfig|debugconfig',
1740 @command('config|showconfig|debugconfig',
1741 [('u', 'untrusted', None, _('show untrusted configuration options')),
1741 [('u', 'untrusted', None, _('show untrusted configuration options')),
1742 ('e', 'edit', None, _('edit user config')),
1742 ('e', 'edit', None, _('edit user config')),
1743 ('l', 'local', None, _('edit repository config')),
1743 ('l', 'local', None, _('edit repository config')),
1744 ('g', 'global', None, _('edit global config'))] + formatteropts,
1744 ('g', 'global', None, _('edit global config'))] + formatteropts,
1745 _('[-u] [NAME]...'),
1745 _('[-u] [NAME]...'),
1746 optionalrepo=True)
1746 optionalrepo=True)
1747 def config(ui, repo, *values, **opts):
1747 def config(ui, repo, *values, **opts):
1748 """show combined config settings from all hgrc files
1748 """show combined config settings from all hgrc files
1749
1749
1750 With no arguments, print names and values of all config items.
1750 With no arguments, print names and values of all config items.
1751
1751
1752 With one argument of the form section.name, print just the value
1752 With one argument of the form section.name, print just the value
1753 of that config item.
1753 of that config item.
1754
1754
1755 With multiple arguments, print names and values of all config
1755 With multiple arguments, print names and values of all config
1756 items with matching section names.
1756 items with matching section names.
1757
1757
1758 With --edit, start an editor on the user-level config file. With
1758 With --edit, start an editor on the user-level config file. With
1759 --global, edit the system-wide config file. With --local, edit the
1759 --global, edit the system-wide config file. With --local, edit the
1760 repository-level config file.
1760 repository-level config file.
1761
1761
1762 With --debug, the source (filename and line number) is printed
1762 With --debug, the source (filename and line number) is printed
1763 for each config item.
1763 for each config item.
1764
1764
1765 See :hg:`help config` for more information about config files.
1765 See :hg:`help config` for more information about config files.
1766
1766
1767 Returns 0 on success, 1 if NAME does not exist.
1767 Returns 0 on success, 1 if NAME does not exist.
1768
1768
1769 """
1769 """
1770
1770
1771 if opts.get('edit') or opts.get('local') or opts.get('global'):
1771 if opts.get('edit') or opts.get('local') or opts.get('global'):
1772 if opts.get('local') and opts.get('global'):
1772 if opts.get('local') and opts.get('global'):
1773 raise error.Abort(_("can't use --local and --global together"))
1773 raise error.Abort(_("can't use --local and --global together"))
1774
1774
1775 if opts.get('local'):
1775 if opts.get('local'):
1776 if not repo:
1776 if not repo:
1777 raise error.Abort(_("can't use --local outside a repository"))
1777 raise error.Abort(_("can't use --local outside a repository"))
1778 paths = [repo.join('hgrc')]
1778 paths = [repo.join('hgrc')]
1779 elif opts.get('global'):
1779 elif opts.get('global'):
1780 paths = scmutil.systemrcpath()
1780 paths = scmutil.systemrcpath()
1781 else:
1781 else:
1782 paths = scmutil.userrcpath()
1782 paths = scmutil.userrcpath()
1783
1783
1784 for f in paths:
1784 for f in paths:
1785 if os.path.exists(f):
1785 if os.path.exists(f):
1786 break
1786 break
1787 else:
1787 else:
1788 if opts.get('global'):
1788 if opts.get('global'):
1789 samplehgrc = uimod.samplehgrcs['global']
1789 samplehgrc = uimod.samplehgrcs['global']
1790 elif opts.get('local'):
1790 elif opts.get('local'):
1791 samplehgrc = uimod.samplehgrcs['local']
1791 samplehgrc = uimod.samplehgrcs['local']
1792 else:
1792 else:
1793 samplehgrc = uimod.samplehgrcs['user']
1793 samplehgrc = uimod.samplehgrcs['user']
1794
1794
1795 f = paths[0]
1795 f = paths[0]
1796 fp = open(f, "w")
1796 fp = open(f, "w")
1797 fp.write(samplehgrc)
1797 fp.write(samplehgrc)
1798 fp.close()
1798 fp.close()
1799
1799
1800 editor = ui.geteditor()
1800 editor = ui.geteditor()
1801 ui.system("%s \"%s\"" % (editor, f),
1801 ui.system("%s \"%s\"" % (editor, f),
1802 onerr=error.Abort, errprefix=_("edit failed"))
1802 onerr=error.Abort, errprefix=_("edit failed"))
1803 return
1803 return
1804
1804
1805 fm = ui.formatter('config', opts)
1805 fm = ui.formatter('config', opts)
1806 for f in scmutil.rcpath():
1806 for f in scmutil.rcpath():
1807 ui.debug('read config from: %s\n' % f)
1807 ui.debug('read config from: %s\n' % f)
1808 untrusted = bool(opts.get('untrusted'))
1808 untrusted = bool(opts.get('untrusted'))
1809 if values:
1809 if values:
1810 sections = [v for v in values if '.' not in v]
1810 sections = [v for v in values if '.' not in v]
1811 items = [v for v in values if '.' in v]
1811 items = [v for v in values if '.' in v]
1812 if len(items) > 1 or items and sections:
1812 if len(items) > 1 or items and sections:
1813 raise error.Abort(_('only one config item permitted'))
1813 raise error.Abort(_('only one config item permitted'))
1814 matched = False
1814 matched = False
1815 for section, name, value in ui.walkconfig(untrusted=untrusted):
1815 for section, name, value in ui.walkconfig(untrusted=untrusted):
1816 value = str(value)
1816 value = str(value)
1817 if fm.isplain():
1817 if fm.isplain():
1818 value = value.replace('\n', '\\n')
1818 value = value.replace('\n', '\\n')
1819 entryname = section + '.' + name
1819 entryname = section + '.' + name
1820 if values:
1820 if values:
1821 for v in values:
1821 for v in values:
1822 if v == section:
1822 if v == section:
1823 fm.startitem()
1823 fm.startitem()
1824 fm.condwrite(ui.debugflag, 'source', '%s: ',
1824 fm.condwrite(ui.debugflag, 'source', '%s: ',
1825 ui.configsource(section, name, untrusted))
1825 ui.configsource(section, name, untrusted))
1826 fm.write('name value', '%s=%s\n', entryname, value)
1826 fm.write('name value', '%s=%s\n', entryname, value)
1827 matched = True
1827 matched = True
1828 elif v == entryname:
1828 elif v == entryname:
1829 fm.startitem()
1829 fm.startitem()
1830 fm.condwrite(ui.debugflag, 'source', '%s: ',
1830 fm.condwrite(ui.debugflag, 'source', '%s: ',
1831 ui.configsource(section, name, untrusted))
1831 ui.configsource(section, name, untrusted))
1832 fm.write('value', '%s\n', value)
1832 fm.write('value', '%s\n', value)
1833 fm.data(name=entryname)
1833 fm.data(name=entryname)
1834 matched = True
1834 matched = True
1835 else:
1835 else:
1836 fm.startitem()
1836 fm.startitem()
1837 fm.condwrite(ui.debugflag, 'source', '%s: ',
1837 fm.condwrite(ui.debugflag, 'source', '%s: ',
1838 ui.configsource(section, name, untrusted))
1838 ui.configsource(section, name, untrusted))
1839 fm.write('name value', '%s=%s\n', entryname, value)
1839 fm.write('name value', '%s=%s\n', entryname, value)
1840 matched = True
1840 matched = True
1841 fm.end()
1841 fm.end()
1842 if matched:
1842 if matched:
1843 return 0
1843 return 0
1844 return 1
1844 return 1
1845
1845
1846 @command('copy|cp',
1846 @command('copy|cp',
1847 [('A', 'after', None, _('record a copy that has already occurred')),
1847 [('A', 'after', None, _('record a copy that has already occurred')),
1848 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1848 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1849 ] + walkopts + dryrunopts,
1849 ] + walkopts + dryrunopts,
1850 _('[OPTION]... [SOURCE]... DEST'))
1850 _('[OPTION]... [SOURCE]... DEST'))
1851 def copy(ui, repo, *pats, **opts):
1851 def copy(ui, repo, *pats, **opts):
1852 """mark files as copied for the next commit
1852 """mark files as copied for the next commit
1853
1853
1854 Mark dest as having copies of source files. If dest is a
1854 Mark dest as having copies of source files. If dest is a
1855 directory, copies are put in that directory. If dest is a file,
1855 directory, copies are put in that directory. If dest is a file,
1856 the source must be a single file.
1856 the source must be a single file.
1857
1857
1858 By default, this command copies the contents of files as they
1858 By default, this command copies the contents of files as they
1859 exist in the working directory. If invoked with -A/--after, the
1859 exist in the working directory. If invoked with -A/--after, the
1860 operation is recorded, but no copying is performed.
1860 operation is recorded, but no copying is performed.
1861
1861
1862 This command takes effect with the next commit. To undo a copy
1862 This command takes effect with the next commit. To undo a copy
1863 before that, see :hg:`revert`.
1863 before that, see :hg:`revert`.
1864
1864
1865 Returns 0 on success, 1 if errors are encountered.
1865 Returns 0 on success, 1 if errors are encountered.
1866 """
1866 """
1867 with repo.wlock(False):
1867 with repo.wlock(False):
1868 return cmdutil.copy(ui, repo, pats, opts)
1868 return cmdutil.copy(ui, repo, pats, opts)
1869
1869
1870 @command('debugbundle',
1871 [('a', 'all', None, _('show all details')),
1872 ('', 'spec', None, _('print the bundlespec of the bundle'))],
1873 _('FILE'),
1874 norepo=True)
1875 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
1876 """lists the contents of a bundle"""
1877 with hg.openpath(ui, bundlepath) as f:
1878 if spec:
1879 spec = exchange.getbundlespec(ui, f)
1880 ui.write('%s\n' % spec)
1881 return
1882
1883 gen = exchange.readbundle(ui, f, bundlepath)
1884 if isinstance(gen, bundle2.unbundle20):
1885 return _debugbundle2(ui, gen, all=all, **opts)
1886 _debugchangegroup(ui, gen, all=all, **opts)
1887
1888 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
1889 indent_string = ' ' * indent
1890 if all:
1891 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
1892 % indent_string)
1893
1894 def showchunks(named):
1895 ui.write("\n%s%s\n" % (indent_string, named))
1896 chain = None
1897 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
1898 node = chunkdata['node']
1899 p1 = chunkdata['p1']
1900 p2 = chunkdata['p2']
1901 cs = chunkdata['cs']
1902 deltabase = chunkdata['deltabase']
1903 delta = chunkdata['delta']
1904 ui.write("%s%s %s %s %s %s %s\n" %
1905 (indent_string, hex(node), hex(p1), hex(p2),
1906 hex(cs), hex(deltabase), len(delta)))
1907 chain = node
1908
1909 chunkdata = gen.changelogheader()
1910 showchunks("changelog")
1911 chunkdata = gen.manifestheader()
1912 showchunks("manifest")
1913 for chunkdata in iter(gen.filelogheader, {}):
1914 fname = chunkdata['filename']
1915 showchunks(fname)
1916 else:
1917 if isinstance(gen, bundle2.unbundle20):
1918 raise error.Abort(_('use debugbundle2 for this file'))
1919 chunkdata = gen.changelogheader()
1920 chain = None
1921 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
1922 node = chunkdata['node']
1923 ui.write("%s%s\n" % (indent_string, hex(node)))
1924 chain = node
1925
1926 def _debugbundle2(ui, gen, all=None, **opts):
1927 """lists the contents of a bundle2"""
1928 if not isinstance(gen, bundle2.unbundle20):
1929 raise error.Abort(_('not a bundle2 file'))
1930 ui.write(('Stream params: %s\n' % repr(gen.params)))
1931 for part in gen.iterparts():
1932 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1933 if part.type == 'changegroup':
1934 version = part.params.get('version', '01')
1935 cg = changegroup.getunbundler(version, part, 'UN')
1936 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
1937
1938 @command('debugcreatestreamclonebundle', [], 'FILE')
1870 @command('debugcreatestreamclonebundle', [], 'FILE')
1939 def debugcreatestreamclonebundle(ui, repo, fname):
1871 def debugcreatestreamclonebundle(ui, repo, fname):
1940 """create a stream clone bundle file
1872 """create a stream clone bundle file
1941
1873
1942 Stream bundles are special bundles that are essentially archives of
1874 Stream bundles are special bundles that are essentially archives of
1943 revlog files. They are commonly used for cloning very quickly.
1875 revlog files. They are commonly used for cloning very quickly.
1944 """
1876 """
1945 requirements, gen = streamclone.generatebundlev1(repo)
1877 requirements, gen = streamclone.generatebundlev1(repo)
1946 changegroup.writechunks(ui, gen, fname)
1878 changegroup.writechunks(ui, gen, fname)
1947
1879
1948 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
1880 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
1949
1881
1950 @command('debugapplystreamclonebundle', [], 'FILE')
1882 @command('debugapplystreamclonebundle', [], 'FILE')
1951 def debugapplystreamclonebundle(ui, repo, fname):
1883 def debugapplystreamclonebundle(ui, repo, fname):
1952 """apply a stream clone bundle file"""
1884 """apply a stream clone bundle file"""
1953 f = hg.openpath(ui, fname)
1885 f = hg.openpath(ui, fname)
1954 gen = exchange.readbundle(ui, f, fname)
1886 gen = exchange.readbundle(ui, f, fname)
1955 gen.apply(repo)
1887 gen.apply(repo)
1956
1888
1957 @command('debugcheckstate', [], '')
1889 @command('debugcheckstate', [], '')
1958 def debugcheckstate(ui, repo):
1890 def debugcheckstate(ui, repo):
1959 """validate the correctness of the current dirstate"""
1891 """validate the correctness of the current dirstate"""
1960 parent1, parent2 = repo.dirstate.parents()
1892 parent1, parent2 = repo.dirstate.parents()
1961 m1 = repo[parent1].manifest()
1893 m1 = repo[parent1].manifest()
1962 m2 = repo[parent2].manifest()
1894 m2 = repo[parent2].manifest()
1963 errors = 0
1895 errors = 0
1964 for f in repo.dirstate:
1896 for f in repo.dirstate:
1965 state = repo.dirstate[f]
1897 state = repo.dirstate[f]
1966 if state in "nr" and f not in m1:
1898 if state in "nr" and f not in m1:
1967 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1899 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1968 errors += 1
1900 errors += 1
1969 if state in "a" and f in m1:
1901 if state in "a" and f in m1:
1970 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1902 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1971 errors += 1
1903 errors += 1
1972 if state in "m" and f not in m1 and f not in m2:
1904 if state in "m" and f not in m1 and f not in m2:
1973 ui.warn(_("%s in state %s, but not in either manifest\n") %
1905 ui.warn(_("%s in state %s, but not in either manifest\n") %
1974 (f, state))
1906 (f, state))
1975 errors += 1
1907 errors += 1
1976 for f in m1:
1908 for f in m1:
1977 state = repo.dirstate[f]
1909 state = repo.dirstate[f]
1978 if state not in "nrm":
1910 if state not in "nrm":
1979 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1911 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1980 errors += 1
1912 errors += 1
1981 if errors:
1913 if errors:
1982 error = _(".hg/dirstate inconsistent with current parent's manifest")
1914 error = _(".hg/dirstate inconsistent with current parent's manifest")
1983 raise error.Abort(error)
1915 raise error.Abort(error)
1984
1916
1985 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1917 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1986 def debugcommands(ui, cmd='', *args):
1918 def debugcommands(ui, cmd='', *args):
1987 """list all available commands and options"""
1919 """list all available commands and options"""
1988 for cmd, vals in sorted(table.iteritems()):
1920 for cmd, vals in sorted(table.iteritems()):
1989 cmd = cmd.split('|')[0].strip('^')
1921 cmd = cmd.split('|')[0].strip('^')
1990 opts = ', '.join([i[1] for i in vals[1]])
1922 opts = ', '.join([i[1] for i in vals[1]])
1991 ui.write('%s: %s\n' % (cmd, opts))
1923 ui.write('%s: %s\n' % (cmd, opts))
1992
1924
1993 @command('debugcomplete',
1925 @command('debugcomplete',
1994 [('o', 'options', None, _('show the command options'))],
1926 [('o', 'options', None, _('show the command options'))],
1995 _('[-o] CMD'),
1927 _('[-o] CMD'),
1996 norepo=True)
1928 norepo=True)
1997 def debugcomplete(ui, cmd='', **opts):
1929 def debugcomplete(ui, cmd='', **opts):
1998 """returns the completion list associated with the given command"""
1930 """returns the completion list associated with the given command"""
1999
1931
2000 if opts.get('options'):
1932 if opts.get('options'):
2001 options = []
1933 options = []
2002 otables = [globalopts]
1934 otables = [globalopts]
2003 if cmd:
1935 if cmd:
2004 aliases, entry = cmdutil.findcmd(cmd, table, False)
1936 aliases, entry = cmdutil.findcmd(cmd, table, False)
2005 otables.append(entry[1])
1937 otables.append(entry[1])
2006 for t in otables:
1938 for t in otables:
2007 for o in t:
1939 for o in t:
2008 if "(DEPRECATED)" in o[3]:
1940 if "(DEPRECATED)" in o[3]:
2009 continue
1941 continue
2010 if o[0]:
1942 if o[0]:
2011 options.append('-%s' % o[0])
1943 options.append('-%s' % o[0])
2012 options.append('--%s' % o[1])
1944 options.append('--%s' % o[1])
2013 ui.write("%s\n" % "\n".join(options))
1945 ui.write("%s\n" % "\n".join(options))
2014 return
1946 return
2015
1947
2016 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1948 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2017 if ui.verbose:
1949 if ui.verbose:
2018 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1950 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2019 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1951 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2020
1952
2021 @command('debugdag',
1953 @command('debugdag',
2022 [('t', 'tags', None, _('use tags as labels')),
1954 [('t', 'tags', None, _('use tags as labels')),
2023 ('b', 'branches', None, _('annotate with branch names')),
1955 ('b', 'branches', None, _('annotate with branch names')),
2024 ('', 'dots', None, _('use dots for runs')),
1956 ('', 'dots', None, _('use dots for runs')),
2025 ('s', 'spaces', None, _('separate elements by spaces'))],
1957 ('s', 'spaces', None, _('separate elements by spaces'))],
2026 _('[OPTION]... [FILE [REV]...]'),
1958 _('[OPTION]... [FILE [REV]...]'),
2027 optionalrepo=True)
1959 optionalrepo=True)
2028 def debugdag(ui, repo, file_=None, *revs, **opts):
1960 def debugdag(ui, repo, file_=None, *revs, **opts):
2029 """format the changelog or an index DAG as a concise textual description
1961 """format the changelog or an index DAG as a concise textual description
2030
1962
2031 If you pass a revlog index, the revlog's DAG is emitted. If you list
1963 If you pass a revlog index, the revlog's DAG is emitted. If you list
2032 revision numbers, they get labeled in the output as rN.
1964 revision numbers, they get labeled in the output as rN.
2033
1965
2034 Otherwise, the changelog DAG of the current repo is emitted.
1966 Otherwise, the changelog DAG of the current repo is emitted.
2035 """
1967 """
2036 spaces = opts.get('spaces')
1968 spaces = opts.get('spaces')
2037 dots = opts.get('dots')
1969 dots = opts.get('dots')
2038 if file_:
1970 if file_:
2039 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1971 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2040 revs = set((int(r) for r in revs))
1972 revs = set((int(r) for r in revs))
2041 def events():
1973 def events():
2042 for r in rlog:
1974 for r in rlog:
2043 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1975 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2044 if p != -1))
1976 if p != -1))
2045 if r in revs:
1977 if r in revs:
2046 yield 'l', (r, "r%i" % r)
1978 yield 'l', (r, "r%i" % r)
2047 elif repo:
1979 elif repo:
2048 cl = repo.changelog
1980 cl = repo.changelog
2049 tags = opts.get('tags')
1981 tags = opts.get('tags')
2050 branches = opts.get('branches')
1982 branches = opts.get('branches')
2051 if tags:
1983 if tags:
2052 labels = {}
1984 labels = {}
2053 for l, n in repo.tags().items():
1985 for l, n in repo.tags().items():
2054 labels.setdefault(cl.rev(n), []).append(l)
1986 labels.setdefault(cl.rev(n), []).append(l)
2055 def events():
1987 def events():
2056 b = "default"
1988 b = "default"
2057 for r in cl:
1989 for r in cl:
2058 if branches:
1990 if branches:
2059 newb = cl.read(cl.node(r))[5]['branch']
1991 newb = cl.read(cl.node(r))[5]['branch']
2060 if newb != b:
1992 if newb != b:
2061 yield 'a', newb
1993 yield 'a', newb
2062 b = newb
1994 b = newb
2063 yield 'n', (r, list(p for p in cl.parentrevs(r)
1995 yield 'n', (r, list(p for p in cl.parentrevs(r)
2064 if p != -1))
1996 if p != -1))
2065 if tags:
1997 if tags:
2066 ls = labels.get(r)
1998 ls = labels.get(r)
2067 if ls:
1999 if ls:
2068 for l in ls:
2000 for l in ls:
2069 yield 'l', (r, l)
2001 yield 'l', (r, l)
2070 else:
2002 else:
2071 raise error.Abort(_('need repo for changelog dag'))
2003 raise error.Abort(_('need repo for changelog dag'))
2072
2004
2073 for line in dagparser.dagtextlines(events(),
2005 for line in dagparser.dagtextlines(events(),
2074 addspaces=spaces,
2006 addspaces=spaces,
2075 wraplabels=True,
2007 wraplabels=True,
2076 wrapannotations=True,
2008 wrapannotations=True,
2077 wrapnonlinear=dots,
2009 wrapnonlinear=dots,
2078 usedots=dots,
2010 usedots=dots,
2079 maxlinewidth=70):
2011 maxlinewidth=70):
2080 ui.write(line)
2012 ui.write(line)
2081 ui.write("\n")
2013 ui.write("\n")
2082
2014
2083 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2015 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2084 def debugdata(ui, repo, file_, rev=None, **opts):
2016 def debugdata(ui, repo, file_, rev=None, **opts):
2085 """dump the contents of a data file revision"""
2017 """dump the contents of a data file revision"""
2086 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2018 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2087 if rev is not None:
2019 if rev is not None:
2088 raise error.CommandError('debugdata', _('invalid arguments'))
2020 raise error.CommandError('debugdata', _('invalid arguments'))
2089 file_, rev = None, file_
2021 file_, rev = None, file_
2090 elif rev is None:
2022 elif rev is None:
2091 raise error.CommandError('debugdata', _('invalid arguments'))
2023 raise error.CommandError('debugdata', _('invalid arguments'))
2092 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2024 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2093 try:
2025 try:
2094 ui.write(r.revision(r.lookup(rev)))
2026 ui.write(r.revision(r.lookup(rev)))
2095 except KeyError:
2027 except KeyError:
2096 raise error.Abort(_('invalid revision identifier %s') % rev)
2028 raise error.Abort(_('invalid revision identifier %s') % rev)
2097
2029
2098 @command('debugdate',
2030 @command('debugdate',
2099 [('e', 'extended', None, _('try extended date formats'))],
2031 [('e', 'extended', None, _('try extended date formats'))],
2100 _('[-e] DATE [RANGE]'),
2032 _('[-e] DATE [RANGE]'),
2101 norepo=True, optionalrepo=True)
2033 norepo=True, optionalrepo=True)
2102 def debugdate(ui, date, range=None, **opts):
2034 def debugdate(ui, date, range=None, **opts):
2103 """parse and display a date"""
2035 """parse and display a date"""
2104 if opts["extended"]:
2036 if opts["extended"]:
2105 d = util.parsedate(date, util.extendeddateformats)
2037 d = util.parsedate(date, util.extendeddateformats)
2106 else:
2038 else:
2107 d = util.parsedate(date)
2039 d = util.parsedate(date)
2108 ui.write(("internal: %s %s\n") % d)
2040 ui.write(("internal: %s %s\n") % d)
2109 ui.write(("standard: %s\n") % util.datestr(d))
2041 ui.write(("standard: %s\n") % util.datestr(d))
2110 if range:
2042 if range:
2111 m = util.matchdate(range)
2043 m = util.matchdate(range)
2112 ui.write(("match: %s\n") % m(d[0]))
2044 ui.write(("match: %s\n") % m(d[0]))
2113
2045
2114 @command('debugdiscovery',
2046 @command('debugdiscovery',
2115 [('', 'old', None, _('use old-style discovery')),
2047 [('', 'old', None, _('use old-style discovery')),
2116 ('', 'nonheads', None,
2048 ('', 'nonheads', None,
2117 _('use old-style discovery with non-heads included')),
2049 _('use old-style discovery with non-heads included')),
2118 ] + remoteopts,
2050 ] + remoteopts,
2119 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2051 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2120 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2052 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2121 """runs the changeset discovery protocol in isolation"""
2053 """runs the changeset discovery protocol in isolation"""
2122 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2054 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2123 opts.get('branch'))
2055 opts.get('branch'))
2124 remote = hg.peer(repo, opts, remoteurl)
2056 remote = hg.peer(repo, opts, remoteurl)
2125 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2057 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2126
2058
2127 # make sure tests are repeatable
2059 # make sure tests are repeatable
2128 random.seed(12323)
2060 random.seed(12323)
2129
2061
2130 def doit(localheads, remoteheads, remote=remote):
2062 def doit(localheads, remoteheads, remote=remote):
2131 if opts.get('old'):
2063 if opts.get('old'):
2132 if localheads:
2064 if localheads:
2133 raise error.Abort('cannot use localheads with old style '
2065 raise error.Abort('cannot use localheads with old style '
2134 'discovery')
2066 'discovery')
2135 if not util.safehasattr(remote, 'branches'):
2067 if not util.safehasattr(remote, 'branches'):
2136 # enable in-client legacy support
2068 # enable in-client legacy support
2137 remote = localrepo.locallegacypeer(remote.local())
2069 remote = localrepo.locallegacypeer(remote.local())
2138 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2070 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2139 force=True)
2071 force=True)
2140 common = set(common)
2072 common = set(common)
2141 if not opts.get('nonheads'):
2073 if not opts.get('nonheads'):
2142 ui.write(("unpruned common: %s\n") %
2074 ui.write(("unpruned common: %s\n") %
2143 " ".join(sorted(short(n) for n in common)))
2075 " ".join(sorted(short(n) for n in common)))
2144 dag = dagutil.revlogdag(repo.changelog)
2076 dag = dagutil.revlogdag(repo.changelog)
2145 all = dag.ancestorset(dag.internalizeall(common))
2077 all = dag.ancestorset(dag.internalizeall(common))
2146 common = dag.externalizeall(dag.headsetofconnecteds(all))
2078 common = dag.externalizeall(dag.headsetofconnecteds(all))
2147 else:
2079 else:
2148 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2080 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2149 common = set(common)
2081 common = set(common)
2150 rheads = set(hds)
2082 rheads = set(hds)
2151 lheads = set(repo.heads())
2083 lheads = set(repo.heads())
2152 ui.write(("common heads: %s\n") %
2084 ui.write(("common heads: %s\n") %
2153 " ".join(sorted(short(n) for n in common)))
2085 " ".join(sorted(short(n) for n in common)))
2154 if lheads <= common:
2086 if lheads <= common:
2155 ui.write(("local is subset\n"))
2087 ui.write(("local is subset\n"))
2156 elif rheads <= common:
2088 elif rheads <= common:
2157 ui.write(("remote is subset\n"))
2089 ui.write(("remote is subset\n"))
2158
2090
2159 serverlogs = opts.get('serverlog')
2091 serverlogs = opts.get('serverlog')
2160 if serverlogs:
2092 if serverlogs:
2161 for filename in serverlogs:
2093 for filename in serverlogs:
2162 with open(filename, 'r') as logfile:
2094 with open(filename, 'r') as logfile:
2163 line = logfile.readline()
2095 line = logfile.readline()
2164 while line:
2096 while line:
2165 parts = line.strip().split(';')
2097 parts = line.strip().split(';')
2166 op = parts[1]
2098 op = parts[1]
2167 if op == 'cg':
2099 if op == 'cg':
2168 pass
2100 pass
2169 elif op == 'cgss':
2101 elif op == 'cgss':
2170 doit(parts[2].split(' '), parts[3].split(' '))
2102 doit(parts[2].split(' '), parts[3].split(' '))
2171 elif op == 'unb':
2103 elif op == 'unb':
2172 doit(parts[3].split(' '), parts[2].split(' '))
2104 doit(parts[3].split(' '), parts[2].split(' '))
2173 line = logfile.readline()
2105 line = logfile.readline()
2174 else:
2106 else:
2175 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2107 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2176 opts.get('remote_head'))
2108 opts.get('remote_head'))
2177 localrevs = opts.get('local_head')
2109 localrevs = opts.get('local_head')
2178 doit(localrevs, remoterevs)
2110 doit(localrevs, remoterevs)
2179
2111
2180 @command('debugextensions', formatteropts, [], norepo=True)
2112 @command('debugextensions', formatteropts, [], norepo=True)
2181 def debugextensions(ui, **opts):
2113 def debugextensions(ui, **opts):
2182 '''show information about active extensions'''
2114 '''show information about active extensions'''
2183 exts = extensions.extensions(ui)
2115 exts = extensions.extensions(ui)
2184 hgver = util.version()
2116 hgver = util.version()
2185 fm = ui.formatter('debugextensions', opts)
2117 fm = ui.formatter('debugextensions', opts)
2186 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2118 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2187 isinternal = extensions.ismoduleinternal(extmod)
2119 isinternal = extensions.ismoduleinternal(extmod)
2188 extsource = extmod.__file__
2120 extsource = extmod.__file__
2189 if isinternal:
2121 if isinternal:
2190 exttestedwith = [] # never expose magic string to users
2122 exttestedwith = [] # never expose magic string to users
2191 else:
2123 else:
2192 exttestedwith = getattr(extmod, 'testedwith', '').split()
2124 exttestedwith = getattr(extmod, 'testedwith', '').split()
2193 extbuglink = getattr(extmod, 'buglink', None)
2125 extbuglink = getattr(extmod, 'buglink', None)
2194
2126
2195 fm.startitem()
2127 fm.startitem()
2196
2128
2197 if ui.quiet or ui.verbose:
2129 if ui.quiet or ui.verbose:
2198 fm.write('name', '%s\n', extname)
2130 fm.write('name', '%s\n', extname)
2199 else:
2131 else:
2200 fm.write('name', '%s', extname)
2132 fm.write('name', '%s', extname)
2201 if isinternal or hgver in exttestedwith:
2133 if isinternal or hgver in exttestedwith:
2202 fm.plain('\n')
2134 fm.plain('\n')
2203 elif not exttestedwith:
2135 elif not exttestedwith:
2204 fm.plain(_(' (untested!)\n'))
2136 fm.plain(_(' (untested!)\n'))
2205 else:
2137 else:
2206 lasttestedversion = exttestedwith[-1]
2138 lasttestedversion = exttestedwith[-1]
2207 fm.plain(' (%s!)\n' % lasttestedversion)
2139 fm.plain(' (%s!)\n' % lasttestedversion)
2208
2140
2209 fm.condwrite(ui.verbose and extsource, 'source',
2141 fm.condwrite(ui.verbose and extsource, 'source',
2210 _(' location: %s\n'), extsource or "")
2142 _(' location: %s\n'), extsource or "")
2211
2143
2212 if ui.verbose:
2144 if ui.verbose:
2213 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2145 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2214 fm.data(bundled=isinternal)
2146 fm.data(bundled=isinternal)
2215
2147
2216 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2148 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2217 _(' tested with: %s\n'),
2149 _(' tested with: %s\n'),
2218 fm.formatlist(exttestedwith, name='ver'))
2150 fm.formatlist(exttestedwith, name='ver'))
2219
2151
2220 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2152 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2221 _(' bug reporting: %s\n'), extbuglink or "")
2153 _(' bug reporting: %s\n'), extbuglink or "")
2222
2154
2223 fm.end()
2155 fm.end()
2224
2156
2225 @command('debugfileset',
2157 @command('debugfileset',
2226 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2158 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2227 _('[-r REV] FILESPEC'))
2159 _('[-r REV] FILESPEC'))
2228 def debugfileset(ui, repo, expr, **opts):
2160 def debugfileset(ui, repo, expr, **opts):
2229 '''parse and apply a fileset specification'''
2161 '''parse and apply a fileset specification'''
2230 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2162 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2231 if ui.verbose:
2163 if ui.verbose:
2232 tree = fileset.parse(expr)
2164 tree = fileset.parse(expr)
2233 ui.note(fileset.prettyformat(tree), "\n")
2165 ui.note(fileset.prettyformat(tree), "\n")
2234
2166
2235 for f in ctx.getfileset(expr):
2167 for f in ctx.getfileset(expr):
2236 ui.write("%s\n" % f)
2168 ui.write("%s\n" % f)
2237
2169
2238 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2170 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2239 def debugfsinfo(ui, path="."):
2171 def debugfsinfo(ui, path="."):
2240 """show information detected about current filesystem"""
2172 """show information detected about current filesystem"""
2241 util.writefile('.debugfsinfo', '')
2173 util.writefile('.debugfsinfo', '')
2242 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2174 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2243 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2175 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2244 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2176 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2245 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2177 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2246 and 'yes' or 'no'))
2178 and 'yes' or 'no'))
2247 os.unlink('.debugfsinfo')
2179 os.unlink('.debugfsinfo')
2248
2180
2249 @command('debuggetbundle',
2181 @command('debuggetbundle',
2250 [('H', 'head', [], _('id of head node'), _('ID')),
2182 [('H', 'head', [], _('id of head node'), _('ID')),
2251 ('C', 'common', [], _('id of common node'), _('ID')),
2183 ('C', 'common', [], _('id of common node'), _('ID')),
2252 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2184 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2253 _('REPO FILE [-H|-C ID]...'),
2185 _('REPO FILE [-H|-C ID]...'),
2254 norepo=True)
2186 norepo=True)
2255 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2187 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2256 """retrieves a bundle from a repo
2188 """retrieves a bundle from a repo
2257
2189
2258 Every ID must be a full-length hex node id string. Saves the bundle to the
2190 Every ID must be a full-length hex node id string. Saves the bundle to the
2259 given file.
2191 given file.
2260 """
2192 """
2261 repo = hg.peer(ui, opts, repopath)
2193 repo = hg.peer(ui, opts, repopath)
2262 if not repo.capable('getbundle'):
2194 if not repo.capable('getbundle'):
2263 raise error.Abort("getbundle() not supported by target repository")
2195 raise error.Abort("getbundle() not supported by target repository")
2264 args = {}
2196 args = {}
2265 if common:
2197 if common:
2266 args['common'] = [bin(s) for s in common]
2198 args['common'] = [bin(s) for s in common]
2267 if head:
2199 if head:
2268 args['heads'] = [bin(s) for s in head]
2200 args['heads'] = [bin(s) for s in head]
2269 # TODO: get desired bundlecaps from command line.
2201 # TODO: get desired bundlecaps from command line.
2270 args['bundlecaps'] = None
2202 args['bundlecaps'] = None
2271 bundle = repo.getbundle('debug', **args)
2203 bundle = repo.getbundle('debug', **args)
2272
2204
2273 bundletype = opts.get('type', 'bzip2').lower()
2205 bundletype = opts.get('type', 'bzip2').lower()
2274 btypes = {'none': 'HG10UN',
2206 btypes = {'none': 'HG10UN',
2275 'bzip2': 'HG10BZ',
2207 'bzip2': 'HG10BZ',
2276 'gzip': 'HG10GZ',
2208 'gzip': 'HG10GZ',
2277 'bundle2': 'HG20'}
2209 'bundle2': 'HG20'}
2278 bundletype = btypes.get(bundletype)
2210 bundletype = btypes.get(bundletype)
2279 if bundletype not in bundle2.bundletypes:
2211 if bundletype not in bundle2.bundletypes:
2280 raise error.Abort(_('unknown bundle type specified with --type'))
2212 raise error.Abort(_('unknown bundle type specified with --type'))
2281 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2213 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2282
2214
2283 @command('debugignore', [], '[FILE]')
2215 @command('debugignore', [], '[FILE]')
2284 def debugignore(ui, repo, *files, **opts):
2216 def debugignore(ui, repo, *files, **opts):
2285 """display the combined ignore pattern and information about ignored files
2217 """display the combined ignore pattern and information about ignored files
2286
2218
2287 With no argument display the combined ignore pattern.
2219 With no argument display the combined ignore pattern.
2288
2220
2289 Given space separated file names, shows if the given file is ignored and
2221 Given space separated file names, shows if the given file is ignored and
2290 if so, show the ignore rule (file and line number) that matched it.
2222 if so, show the ignore rule (file and line number) that matched it.
2291 """
2223 """
2292 ignore = repo.dirstate._ignore
2224 ignore = repo.dirstate._ignore
2293 if not files:
2225 if not files:
2294 # Show all the patterns
2226 # Show all the patterns
2295 includepat = getattr(ignore, 'includepat', None)
2227 includepat = getattr(ignore, 'includepat', None)
2296 if includepat is not None:
2228 if includepat is not None:
2297 ui.write("%s\n" % includepat)
2229 ui.write("%s\n" % includepat)
2298 else:
2230 else:
2299 raise error.Abort(_("no ignore patterns found"))
2231 raise error.Abort(_("no ignore patterns found"))
2300 else:
2232 else:
2301 for f in files:
2233 for f in files:
2302 nf = util.normpath(f)
2234 nf = util.normpath(f)
2303 ignored = None
2235 ignored = None
2304 ignoredata = None
2236 ignoredata = None
2305 if nf != '.':
2237 if nf != '.':
2306 if ignore(nf):
2238 if ignore(nf):
2307 ignored = nf
2239 ignored = nf
2308 ignoredata = repo.dirstate._ignorefileandline(nf)
2240 ignoredata = repo.dirstate._ignorefileandline(nf)
2309 else:
2241 else:
2310 for p in util.finddirs(nf):
2242 for p in util.finddirs(nf):
2311 if ignore(p):
2243 if ignore(p):
2312 ignored = p
2244 ignored = p
2313 ignoredata = repo.dirstate._ignorefileandline(p)
2245 ignoredata = repo.dirstate._ignorefileandline(p)
2314 break
2246 break
2315 if ignored:
2247 if ignored:
2316 if ignored == nf:
2248 if ignored == nf:
2317 ui.write(_("%s is ignored\n") % f)
2249 ui.write(_("%s is ignored\n") % f)
2318 else:
2250 else:
2319 ui.write(_("%s is ignored because of "
2251 ui.write(_("%s is ignored because of "
2320 "containing folder %s\n")
2252 "containing folder %s\n")
2321 % (f, ignored))
2253 % (f, ignored))
2322 ignorefile, lineno, line = ignoredata
2254 ignorefile, lineno, line = ignoredata
2323 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2255 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2324 % (ignorefile, lineno, line))
2256 % (ignorefile, lineno, line))
2325 else:
2257 else:
2326 ui.write(_("%s is not ignored\n") % f)
2258 ui.write(_("%s is not ignored\n") % f)
2327
2259
2328 @command('debugindex', debugrevlogopts +
2260 @command('debugindex', debugrevlogopts +
2329 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2261 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2330 _('[-f FORMAT] -c|-m|FILE'),
2262 _('[-f FORMAT] -c|-m|FILE'),
2331 optionalrepo=True)
2263 optionalrepo=True)
2332 def debugindex(ui, repo, file_=None, **opts):
2264 def debugindex(ui, repo, file_=None, **opts):
2333 """dump the contents of an index file"""
2265 """dump the contents of an index file"""
2334 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2266 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2335 format = opts.get('format', 0)
2267 format = opts.get('format', 0)
2336 if format not in (0, 1):
2268 if format not in (0, 1):
2337 raise error.Abort(_("unknown format %d") % format)
2269 raise error.Abort(_("unknown format %d") % format)
2338
2270
2339 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2271 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2340 if generaldelta:
2272 if generaldelta:
2341 basehdr = ' delta'
2273 basehdr = ' delta'
2342 else:
2274 else:
2343 basehdr = ' base'
2275 basehdr = ' base'
2344
2276
2345 if ui.debugflag:
2277 if ui.debugflag:
2346 shortfn = hex
2278 shortfn = hex
2347 else:
2279 else:
2348 shortfn = short
2280 shortfn = short
2349
2281
2350 # There might not be anything in r, so have a sane default
2282 # There might not be anything in r, so have a sane default
2351 idlen = 12
2283 idlen = 12
2352 for i in r:
2284 for i in r:
2353 idlen = len(shortfn(r.node(i)))
2285 idlen = len(shortfn(r.node(i)))
2354 break
2286 break
2355
2287
2356 if format == 0:
2288 if format == 0:
2357 ui.write((" rev offset length " + basehdr + " linkrev"
2289 ui.write((" rev offset length " + basehdr + " linkrev"
2358 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2290 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2359 elif format == 1:
2291 elif format == 1:
2360 ui.write((" rev flag offset length"
2292 ui.write((" rev flag offset length"
2361 " size " + basehdr + " link p1 p2"
2293 " size " + basehdr + " link p1 p2"
2362 " %s\n") % "nodeid".rjust(idlen))
2294 " %s\n") % "nodeid".rjust(idlen))
2363
2295
2364 for i in r:
2296 for i in r:
2365 node = r.node(i)
2297 node = r.node(i)
2366 if generaldelta:
2298 if generaldelta:
2367 base = r.deltaparent(i)
2299 base = r.deltaparent(i)
2368 else:
2300 else:
2369 base = r.chainbase(i)
2301 base = r.chainbase(i)
2370 if format == 0:
2302 if format == 0:
2371 try:
2303 try:
2372 pp = r.parents(node)
2304 pp = r.parents(node)
2373 except Exception:
2305 except Exception:
2374 pp = [nullid, nullid]
2306 pp = [nullid, nullid]
2375 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2307 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2376 i, r.start(i), r.length(i), base, r.linkrev(i),
2308 i, r.start(i), r.length(i), base, r.linkrev(i),
2377 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2309 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2378 elif format == 1:
2310 elif format == 1:
2379 pr = r.parentrevs(i)
2311 pr = r.parentrevs(i)
2380 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2312 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2381 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2313 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2382 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2314 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2383
2315
2384 @command('debugindexdot', debugrevlogopts,
2316 @command('debugindexdot', debugrevlogopts,
2385 _('-c|-m|FILE'), optionalrepo=True)
2317 _('-c|-m|FILE'), optionalrepo=True)
2386 def debugindexdot(ui, repo, file_=None, **opts):
2318 def debugindexdot(ui, repo, file_=None, **opts):
2387 """dump an index DAG as a graphviz dot file"""
2319 """dump an index DAG as a graphviz dot file"""
2388 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2320 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2389 ui.write(("digraph G {\n"))
2321 ui.write(("digraph G {\n"))
2390 for i in r:
2322 for i in r:
2391 node = r.node(i)
2323 node = r.node(i)
2392 pp = r.parents(node)
2324 pp = r.parents(node)
2393 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2325 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2394 if pp[1] != nullid:
2326 if pp[1] != nullid:
2395 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2327 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2396 ui.write("}\n")
2328 ui.write("}\n")
2397
2329
2398 @command('debugdeltachain',
2330 @command('debugdeltachain',
2399 debugrevlogopts + formatteropts,
2331 debugrevlogopts + formatteropts,
2400 _('-c|-m|FILE'),
2332 _('-c|-m|FILE'),
2401 optionalrepo=True)
2333 optionalrepo=True)
2402 def debugdeltachain(ui, repo, file_=None, **opts):
2334 def debugdeltachain(ui, repo, file_=None, **opts):
2403 """dump information about delta chains in a revlog
2335 """dump information about delta chains in a revlog
2404
2336
2405 Output can be templatized. Available template keywords are:
2337 Output can be templatized. Available template keywords are:
2406
2338
2407 :``rev``: revision number
2339 :``rev``: revision number
2408 :``chainid``: delta chain identifier (numbered by unique base)
2340 :``chainid``: delta chain identifier (numbered by unique base)
2409 :``chainlen``: delta chain length to this revision
2341 :``chainlen``: delta chain length to this revision
2410 :``prevrev``: previous revision in delta chain
2342 :``prevrev``: previous revision in delta chain
2411 :``deltatype``: role of delta / how it was computed
2343 :``deltatype``: role of delta / how it was computed
2412 :``compsize``: compressed size of revision
2344 :``compsize``: compressed size of revision
2413 :``uncompsize``: uncompressed size of revision
2345 :``uncompsize``: uncompressed size of revision
2414 :``chainsize``: total size of compressed revisions in chain
2346 :``chainsize``: total size of compressed revisions in chain
2415 :``chainratio``: total chain size divided by uncompressed revision size
2347 :``chainratio``: total chain size divided by uncompressed revision size
2416 (new delta chains typically start at ratio 2.00)
2348 (new delta chains typically start at ratio 2.00)
2417 :``lindist``: linear distance from base revision in delta chain to end
2349 :``lindist``: linear distance from base revision in delta chain to end
2418 of this revision
2350 of this revision
2419 :``extradist``: total size of revisions not part of this delta chain from
2351 :``extradist``: total size of revisions not part of this delta chain from
2420 base of delta chain to end of this revision; a measurement
2352 base of delta chain to end of this revision; a measurement
2421 of how much extra data we need to read/seek across to read
2353 of how much extra data we need to read/seek across to read
2422 the delta chain for this revision
2354 the delta chain for this revision
2423 :``extraratio``: extradist divided by chainsize; another representation of
2355 :``extraratio``: extradist divided by chainsize; another representation of
2424 how much unrelated data is needed to load this delta chain
2356 how much unrelated data is needed to load this delta chain
2425 """
2357 """
2426 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2358 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2427 index = r.index
2359 index = r.index
2428 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2360 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2429
2361
2430 def revinfo(rev):
2362 def revinfo(rev):
2431 e = index[rev]
2363 e = index[rev]
2432 compsize = e[1]
2364 compsize = e[1]
2433 uncompsize = e[2]
2365 uncompsize = e[2]
2434 chainsize = 0
2366 chainsize = 0
2435
2367
2436 if generaldelta:
2368 if generaldelta:
2437 if e[3] == e[5]:
2369 if e[3] == e[5]:
2438 deltatype = 'p1'
2370 deltatype = 'p1'
2439 elif e[3] == e[6]:
2371 elif e[3] == e[6]:
2440 deltatype = 'p2'
2372 deltatype = 'p2'
2441 elif e[3] == rev - 1:
2373 elif e[3] == rev - 1:
2442 deltatype = 'prev'
2374 deltatype = 'prev'
2443 elif e[3] == rev:
2375 elif e[3] == rev:
2444 deltatype = 'base'
2376 deltatype = 'base'
2445 else:
2377 else:
2446 deltatype = 'other'
2378 deltatype = 'other'
2447 else:
2379 else:
2448 if e[3] == rev:
2380 if e[3] == rev:
2449 deltatype = 'base'
2381 deltatype = 'base'
2450 else:
2382 else:
2451 deltatype = 'prev'
2383 deltatype = 'prev'
2452
2384
2453 chain = r._deltachain(rev)[0]
2385 chain = r._deltachain(rev)[0]
2454 for iterrev in chain:
2386 for iterrev in chain:
2455 e = index[iterrev]
2387 e = index[iterrev]
2456 chainsize += e[1]
2388 chainsize += e[1]
2457
2389
2458 return compsize, uncompsize, deltatype, chain, chainsize
2390 return compsize, uncompsize, deltatype, chain, chainsize
2459
2391
2460 fm = ui.formatter('debugdeltachain', opts)
2392 fm = ui.formatter('debugdeltachain', opts)
2461
2393
2462 fm.plain(' rev chain# chainlen prev delta '
2394 fm.plain(' rev chain# chainlen prev delta '
2463 'size rawsize chainsize ratio lindist extradist '
2395 'size rawsize chainsize ratio lindist extradist '
2464 'extraratio\n')
2396 'extraratio\n')
2465
2397
2466 chainbases = {}
2398 chainbases = {}
2467 for rev in r:
2399 for rev in r:
2468 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2400 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2469 chainbase = chain[0]
2401 chainbase = chain[0]
2470 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2402 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2471 basestart = r.start(chainbase)
2403 basestart = r.start(chainbase)
2472 revstart = r.start(rev)
2404 revstart = r.start(rev)
2473 lineardist = revstart + comp - basestart
2405 lineardist = revstart + comp - basestart
2474 extradist = lineardist - chainsize
2406 extradist = lineardist - chainsize
2475 try:
2407 try:
2476 prevrev = chain[-2]
2408 prevrev = chain[-2]
2477 except IndexError:
2409 except IndexError:
2478 prevrev = -1
2410 prevrev = -1
2479
2411
2480 chainratio = float(chainsize) / float(uncomp)
2412 chainratio = float(chainsize) / float(uncomp)
2481 extraratio = float(extradist) / float(chainsize)
2413 extraratio = float(extradist) / float(chainsize)
2482
2414
2483 fm.startitem()
2415 fm.startitem()
2484 fm.write('rev chainid chainlen prevrev deltatype compsize '
2416 fm.write('rev chainid chainlen prevrev deltatype compsize '
2485 'uncompsize chainsize chainratio lindist extradist '
2417 'uncompsize chainsize chainratio lindist extradist '
2486 'extraratio',
2418 'extraratio',
2487 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2419 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2488 rev, chainid, len(chain), prevrev, deltatype, comp,
2420 rev, chainid, len(chain), prevrev, deltatype, comp,
2489 uncomp, chainsize, chainratio, lineardist, extradist,
2421 uncomp, chainsize, chainratio, lineardist, extradist,
2490 extraratio,
2422 extraratio,
2491 rev=rev, chainid=chainid, chainlen=len(chain),
2423 rev=rev, chainid=chainid, chainlen=len(chain),
2492 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2424 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2493 uncompsize=uncomp, chainsize=chainsize,
2425 uncompsize=uncomp, chainsize=chainsize,
2494 chainratio=chainratio, lindist=lineardist,
2426 chainratio=chainratio, lindist=lineardist,
2495 extradist=extradist, extraratio=extraratio)
2427 extradist=extradist, extraratio=extraratio)
2496
2428
2497 fm.end()
2429 fm.end()
2498
2430
2499 @command('debuginstall', [] + formatteropts, '', norepo=True)
2431 @command('debuginstall', [] + formatteropts, '', norepo=True)
2500 def debuginstall(ui, **opts):
2432 def debuginstall(ui, **opts):
2501 '''test Mercurial installation
2433 '''test Mercurial installation
2502
2434
2503 Returns 0 on success.
2435 Returns 0 on success.
2504 '''
2436 '''
2505
2437
2506 def writetemp(contents):
2438 def writetemp(contents):
2507 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2439 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2508 f = os.fdopen(fd, "wb")
2440 f = os.fdopen(fd, "wb")
2509 f.write(contents)
2441 f.write(contents)
2510 f.close()
2442 f.close()
2511 return name
2443 return name
2512
2444
2513 problems = 0
2445 problems = 0
2514
2446
2515 fm = ui.formatter('debuginstall', opts)
2447 fm = ui.formatter('debuginstall', opts)
2516 fm.startitem()
2448 fm.startitem()
2517
2449
2518 # encoding
2450 # encoding
2519 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2451 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2520 err = None
2452 err = None
2521 try:
2453 try:
2522 encoding.fromlocal("test")
2454 encoding.fromlocal("test")
2523 except error.Abort as inst:
2455 except error.Abort as inst:
2524 err = inst
2456 err = inst
2525 problems += 1
2457 problems += 1
2526 fm.condwrite(err, 'encodingerror', _(" %s\n"
2458 fm.condwrite(err, 'encodingerror', _(" %s\n"
2527 " (check that your locale is properly set)\n"), err)
2459 " (check that your locale is properly set)\n"), err)
2528
2460
2529 # Python
2461 # Python
2530 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2462 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2531 sys.executable)
2463 sys.executable)
2532 fm.write('pythonver', _("checking Python version (%s)\n"),
2464 fm.write('pythonver', _("checking Python version (%s)\n"),
2533 ("%s.%s.%s" % sys.version_info[:3]))
2465 ("%s.%s.%s" % sys.version_info[:3]))
2534 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2466 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2535 os.path.dirname(os.__file__))
2467 os.path.dirname(os.__file__))
2536
2468
2537 security = set(sslutil.supportedprotocols)
2469 security = set(sslutil.supportedprotocols)
2538 if sslutil.hassni:
2470 if sslutil.hassni:
2539 security.add('sni')
2471 security.add('sni')
2540
2472
2541 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
2473 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
2542 fm.formatlist(sorted(security), name='protocol',
2474 fm.formatlist(sorted(security), name='protocol',
2543 fmt='%s', sep=','))
2475 fmt='%s', sep=','))
2544
2476
2545 # These are warnings, not errors. So don't increment problem count. This
2477 # These are warnings, not errors. So don't increment problem count. This
2546 # may change in the future.
2478 # may change in the future.
2547 if 'tls1.2' not in security:
2479 if 'tls1.2' not in security:
2548 fm.plain(_(' TLS 1.2 not supported by Python install; '
2480 fm.plain(_(' TLS 1.2 not supported by Python install; '
2549 'network connections lack modern security\n'))
2481 'network connections lack modern security\n'))
2550 if 'sni' not in security:
2482 if 'sni' not in security:
2551 fm.plain(_(' SNI not supported by Python install; may have '
2483 fm.plain(_(' SNI not supported by Python install; may have '
2552 'connectivity issues with some servers\n'))
2484 'connectivity issues with some servers\n'))
2553
2485
2554 # TODO print CA cert info
2486 # TODO print CA cert info
2555
2487
2556 # hg version
2488 # hg version
2557 hgver = util.version()
2489 hgver = util.version()
2558 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2490 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2559 hgver.split('+')[0])
2491 hgver.split('+')[0])
2560 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2492 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2561 '+'.join(hgver.split('+')[1:]))
2493 '+'.join(hgver.split('+')[1:]))
2562
2494
2563 # compiled modules
2495 # compiled modules
2564 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2496 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2565 policy.policy)
2497 policy.policy)
2566 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2498 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2567 os.path.dirname(__file__))
2499 os.path.dirname(__file__))
2568
2500
2569 err = None
2501 err = None
2570 try:
2502 try:
2571 from . import (
2503 from . import (
2572 base85,
2504 base85,
2573 bdiff,
2505 bdiff,
2574 mpatch,
2506 mpatch,
2575 osutil,
2507 osutil,
2576 )
2508 )
2577 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2509 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2578 except Exception as inst:
2510 except Exception as inst:
2579 err = inst
2511 err = inst
2580 problems += 1
2512 problems += 1
2581 fm.condwrite(err, 'extensionserror', " %s\n", err)
2513 fm.condwrite(err, 'extensionserror', " %s\n", err)
2582
2514
2583 compengines = util.compengines._engines.values()
2515 compengines = util.compengines._engines.values()
2584 fm.write('compengines', _('checking registered compression engines (%s)\n'),
2516 fm.write('compengines', _('checking registered compression engines (%s)\n'),
2585 fm.formatlist(sorted(e.name() for e in compengines),
2517 fm.formatlist(sorted(e.name() for e in compengines),
2586 name='compengine', fmt='%s', sep=', '))
2518 name='compengine', fmt='%s', sep=', '))
2587 fm.write('compenginesavail', _('checking available compression engines '
2519 fm.write('compenginesavail', _('checking available compression engines '
2588 '(%s)\n'),
2520 '(%s)\n'),
2589 fm.formatlist(sorted(e.name() for e in compengines
2521 fm.formatlist(sorted(e.name() for e in compengines
2590 if e.available()),
2522 if e.available()),
2591 name='compengine', fmt='%s', sep=', '))
2523 name='compengine', fmt='%s', sep=', '))
2592
2524
2593 # templates
2525 # templates
2594 p = templater.templatepaths()
2526 p = templater.templatepaths()
2595 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2527 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2596 fm.condwrite(not p, '', _(" no template directories found\n"))
2528 fm.condwrite(not p, '', _(" no template directories found\n"))
2597 if p:
2529 if p:
2598 m = templater.templatepath("map-cmdline.default")
2530 m = templater.templatepath("map-cmdline.default")
2599 if m:
2531 if m:
2600 # template found, check if it is working
2532 # template found, check if it is working
2601 err = None
2533 err = None
2602 try:
2534 try:
2603 templater.templater.frommapfile(m)
2535 templater.templater.frommapfile(m)
2604 except Exception as inst:
2536 except Exception as inst:
2605 err = inst
2537 err = inst
2606 p = None
2538 p = None
2607 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2539 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2608 else:
2540 else:
2609 p = None
2541 p = None
2610 fm.condwrite(p, 'defaulttemplate',
2542 fm.condwrite(p, 'defaulttemplate',
2611 _("checking default template (%s)\n"), m)
2543 _("checking default template (%s)\n"), m)
2612 fm.condwrite(not m, 'defaulttemplatenotfound',
2544 fm.condwrite(not m, 'defaulttemplatenotfound',
2613 _(" template '%s' not found\n"), "default")
2545 _(" template '%s' not found\n"), "default")
2614 if not p:
2546 if not p:
2615 problems += 1
2547 problems += 1
2616 fm.condwrite(not p, '',
2548 fm.condwrite(not p, '',
2617 _(" (templates seem to have been installed incorrectly)\n"))
2549 _(" (templates seem to have been installed incorrectly)\n"))
2618
2550
2619 # editor
2551 # editor
2620 editor = ui.geteditor()
2552 editor = ui.geteditor()
2621 editor = util.expandpath(editor)
2553 editor = util.expandpath(editor)
2622 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2554 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2623 cmdpath = util.findexe(shlex.split(editor)[0])
2555 cmdpath = util.findexe(shlex.split(editor)[0])
2624 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2556 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2625 _(" No commit editor set and can't find %s in PATH\n"
2557 _(" No commit editor set and can't find %s in PATH\n"
2626 " (specify a commit editor in your configuration"
2558 " (specify a commit editor in your configuration"
2627 " file)\n"), not cmdpath and editor == 'vi' and editor)
2559 " file)\n"), not cmdpath and editor == 'vi' and editor)
2628 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2560 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2629 _(" Can't find editor '%s' in PATH\n"
2561 _(" Can't find editor '%s' in PATH\n"
2630 " (specify a commit editor in your configuration"
2562 " (specify a commit editor in your configuration"
2631 " file)\n"), not cmdpath and editor)
2563 " file)\n"), not cmdpath and editor)
2632 if not cmdpath and editor != 'vi':
2564 if not cmdpath and editor != 'vi':
2633 problems += 1
2565 problems += 1
2634
2566
2635 # check username
2567 # check username
2636 username = None
2568 username = None
2637 err = None
2569 err = None
2638 try:
2570 try:
2639 username = ui.username()
2571 username = ui.username()
2640 except error.Abort as e:
2572 except error.Abort as e:
2641 err = e
2573 err = e
2642 problems += 1
2574 problems += 1
2643
2575
2644 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2576 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2645 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2577 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2646 " (specify a username in your configuration file)\n"), err)
2578 " (specify a username in your configuration file)\n"), err)
2647
2579
2648 fm.condwrite(not problems, '',
2580 fm.condwrite(not problems, '',
2649 _("no problems detected\n"))
2581 _("no problems detected\n"))
2650 if not problems:
2582 if not problems:
2651 fm.data(problems=problems)
2583 fm.data(problems=problems)
2652 fm.condwrite(problems, 'problems',
2584 fm.condwrite(problems, 'problems',
2653 _("%d problems detected,"
2585 _("%d problems detected,"
2654 " please check your install!\n"), problems)
2586 " please check your install!\n"), problems)
2655 fm.end()
2587 fm.end()
2656
2588
2657 return problems
2589 return problems
2658
2590
2659 @command('debugknown', [], _('REPO ID...'), norepo=True)
2591 @command('debugknown', [], _('REPO ID...'), norepo=True)
2660 def debugknown(ui, repopath, *ids, **opts):
2592 def debugknown(ui, repopath, *ids, **opts):
2661 """test whether node ids are known to a repo
2593 """test whether node ids are known to a repo
2662
2594
2663 Every ID must be a full-length hex node id string. Returns a list of 0s
2595 Every ID must be a full-length hex node id string. Returns a list of 0s
2664 and 1s indicating unknown/known.
2596 and 1s indicating unknown/known.
2665 """
2597 """
2666 repo = hg.peer(ui, opts, repopath)
2598 repo = hg.peer(ui, opts, repopath)
2667 if not repo.capable('known'):
2599 if not repo.capable('known'):
2668 raise error.Abort("known() not supported by target repository")
2600 raise error.Abort("known() not supported by target repository")
2669 flags = repo.known([bin(s) for s in ids])
2601 flags = repo.known([bin(s) for s in ids])
2670 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2602 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2671
2603
2672 @command('debuglabelcomplete', [], _('LABEL...'))
2604 @command('debuglabelcomplete', [], _('LABEL...'))
2673 def debuglabelcomplete(ui, repo, *args):
2605 def debuglabelcomplete(ui, repo, *args):
2674 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2606 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2675 debugnamecomplete(ui, repo, *args)
2607 debugnamecomplete(ui, repo, *args)
2676
2608
2677 @command('debugmergestate', [], '')
2609 @command('debugmergestate', [], '')
2678 def debugmergestate(ui, repo, *args):
2610 def debugmergestate(ui, repo, *args):
2679 """print merge state
2611 """print merge state
2680
2612
2681 Use --verbose to print out information about whether v1 or v2 merge state
2613 Use --verbose to print out information about whether v1 or v2 merge state
2682 was chosen."""
2614 was chosen."""
2683 def _hashornull(h):
2615 def _hashornull(h):
2684 if h == nullhex:
2616 if h == nullhex:
2685 return 'null'
2617 return 'null'
2686 else:
2618 else:
2687 return h
2619 return h
2688
2620
2689 def printrecords(version):
2621 def printrecords(version):
2690 ui.write(('* version %s records\n') % version)
2622 ui.write(('* version %s records\n') % version)
2691 if version == 1:
2623 if version == 1:
2692 records = v1records
2624 records = v1records
2693 else:
2625 else:
2694 records = v2records
2626 records = v2records
2695
2627
2696 for rtype, record in records:
2628 for rtype, record in records:
2697 # pretty print some record types
2629 # pretty print some record types
2698 if rtype == 'L':
2630 if rtype == 'L':
2699 ui.write(('local: %s\n') % record)
2631 ui.write(('local: %s\n') % record)
2700 elif rtype == 'O':
2632 elif rtype == 'O':
2701 ui.write(('other: %s\n') % record)
2633 ui.write(('other: %s\n') % record)
2702 elif rtype == 'm':
2634 elif rtype == 'm':
2703 driver, mdstate = record.split('\0', 1)
2635 driver, mdstate = record.split('\0', 1)
2704 ui.write(('merge driver: %s (state "%s")\n')
2636 ui.write(('merge driver: %s (state "%s")\n')
2705 % (driver, mdstate))
2637 % (driver, mdstate))
2706 elif rtype in 'FDC':
2638 elif rtype in 'FDC':
2707 r = record.split('\0')
2639 r = record.split('\0')
2708 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2640 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2709 if version == 1:
2641 if version == 1:
2710 onode = 'not stored in v1 format'
2642 onode = 'not stored in v1 format'
2711 flags = r[7]
2643 flags = r[7]
2712 else:
2644 else:
2713 onode, flags = r[7:9]
2645 onode, flags = r[7:9]
2714 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2646 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2715 % (f, rtype, state, _hashornull(hash)))
2647 % (f, rtype, state, _hashornull(hash)))
2716 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2648 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2717 ui.write((' ancestor path: %s (node %s)\n')
2649 ui.write((' ancestor path: %s (node %s)\n')
2718 % (afile, _hashornull(anode)))
2650 % (afile, _hashornull(anode)))
2719 ui.write((' other path: %s (node %s)\n')
2651 ui.write((' other path: %s (node %s)\n')
2720 % (ofile, _hashornull(onode)))
2652 % (ofile, _hashornull(onode)))
2721 elif rtype == 'f':
2653 elif rtype == 'f':
2722 filename, rawextras = record.split('\0', 1)
2654 filename, rawextras = record.split('\0', 1)
2723 extras = rawextras.split('\0')
2655 extras = rawextras.split('\0')
2724 i = 0
2656 i = 0
2725 extrastrings = []
2657 extrastrings = []
2726 while i < len(extras):
2658 while i < len(extras):
2727 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2659 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2728 i += 2
2660 i += 2
2729
2661
2730 ui.write(('file extras: %s (%s)\n')
2662 ui.write(('file extras: %s (%s)\n')
2731 % (filename, ', '.join(extrastrings)))
2663 % (filename, ', '.join(extrastrings)))
2732 elif rtype == 'l':
2664 elif rtype == 'l':
2733 labels = record.split('\0', 2)
2665 labels = record.split('\0', 2)
2734 labels = [l for l in labels if len(l) > 0]
2666 labels = [l for l in labels if len(l) > 0]
2735 ui.write(('labels:\n'))
2667 ui.write(('labels:\n'))
2736 ui.write((' local: %s\n' % labels[0]))
2668 ui.write((' local: %s\n' % labels[0]))
2737 ui.write((' other: %s\n' % labels[1]))
2669 ui.write((' other: %s\n' % labels[1]))
2738 if len(labels) > 2:
2670 if len(labels) > 2:
2739 ui.write((' base: %s\n' % labels[2]))
2671 ui.write((' base: %s\n' % labels[2]))
2740 else:
2672 else:
2741 ui.write(('unrecognized entry: %s\t%s\n')
2673 ui.write(('unrecognized entry: %s\t%s\n')
2742 % (rtype, record.replace('\0', '\t')))
2674 % (rtype, record.replace('\0', '\t')))
2743
2675
2744 # Avoid mergestate.read() since it may raise an exception for unsupported
2676 # Avoid mergestate.read() since it may raise an exception for unsupported
2745 # merge state records. We shouldn't be doing this, but this is OK since this
2677 # merge state records. We shouldn't be doing this, but this is OK since this
2746 # command is pretty low-level.
2678 # command is pretty low-level.
2747 ms = mergemod.mergestate(repo)
2679 ms = mergemod.mergestate(repo)
2748
2680
2749 # sort so that reasonable information is on top
2681 # sort so that reasonable information is on top
2750 v1records = ms._readrecordsv1()
2682 v1records = ms._readrecordsv1()
2751 v2records = ms._readrecordsv2()
2683 v2records = ms._readrecordsv2()
2752 order = 'LOml'
2684 order = 'LOml'
2753 def key(r):
2685 def key(r):
2754 idx = order.find(r[0])
2686 idx = order.find(r[0])
2755 if idx == -1:
2687 if idx == -1:
2756 return (1, r[1])
2688 return (1, r[1])
2757 else:
2689 else:
2758 return (0, idx)
2690 return (0, idx)
2759 v1records.sort(key=key)
2691 v1records.sort(key=key)
2760 v2records.sort(key=key)
2692 v2records.sort(key=key)
2761
2693
2762 if not v1records and not v2records:
2694 if not v1records and not v2records:
2763 ui.write(('no merge state found\n'))
2695 ui.write(('no merge state found\n'))
2764 elif not v2records:
2696 elif not v2records:
2765 ui.note(('no version 2 merge state\n'))
2697 ui.note(('no version 2 merge state\n'))
2766 printrecords(1)
2698 printrecords(1)
2767 elif ms._v1v2match(v1records, v2records):
2699 elif ms._v1v2match(v1records, v2records):
2768 ui.note(('v1 and v2 states match: using v2\n'))
2700 ui.note(('v1 and v2 states match: using v2\n'))
2769 printrecords(2)
2701 printrecords(2)
2770 else:
2702 else:
2771 ui.note(('v1 and v2 states mismatch: using v1\n'))
2703 ui.note(('v1 and v2 states mismatch: using v1\n'))
2772 printrecords(1)
2704 printrecords(1)
2773 if ui.verbose:
2705 if ui.verbose:
2774 printrecords(2)
2706 printrecords(2)
2775
2707
2776 @command('debugnamecomplete', [], _('NAME...'))
2708 @command('debugnamecomplete', [], _('NAME...'))
2777 def debugnamecomplete(ui, repo, *args):
2709 def debugnamecomplete(ui, repo, *args):
2778 '''complete "names" - tags, open branch names, bookmark names'''
2710 '''complete "names" - tags, open branch names, bookmark names'''
2779
2711
2780 names = set()
2712 names = set()
2781 # since we previously only listed open branches, we will handle that
2713 # since we previously only listed open branches, we will handle that
2782 # specially (after this for loop)
2714 # specially (after this for loop)
2783 for name, ns in repo.names.iteritems():
2715 for name, ns in repo.names.iteritems():
2784 if name != 'branches':
2716 if name != 'branches':
2785 names.update(ns.listnames(repo))
2717 names.update(ns.listnames(repo))
2786 names.update(tag for (tag, heads, tip, closed)
2718 names.update(tag for (tag, heads, tip, closed)
2787 in repo.branchmap().iterbranches() if not closed)
2719 in repo.branchmap().iterbranches() if not closed)
2788 completions = set()
2720 completions = set()
2789 if not args:
2721 if not args:
2790 args = ['']
2722 args = ['']
2791 for a in args:
2723 for a in args:
2792 completions.update(n for n in names if n.startswith(a))
2724 completions.update(n for n in names if n.startswith(a))
2793 ui.write('\n'.join(sorted(completions)))
2725 ui.write('\n'.join(sorted(completions)))
2794 ui.write('\n')
2726 ui.write('\n')
2795
2727
2796 @command('debuglocks',
2728 @command('debuglocks',
2797 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2729 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2798 ('W', 'force-wlock', None,
2730 ('W', 'force-wlock', None,
2799 _('free the working state lock (DANGEROUS)'))],
2731 _('free the working state lock (DANGEROUS)'))],
2800 _('[OPTION]...'))
2732 _('[OPTION]...'))
2801 def debuglocks(ui, repo, **opts):
2733 def debuglocks(ui, repo, **opts):
2802 """show or modify state of locks
2734 """show or modify state of locks
2803
2735
2804 By default, this command will show which locks are held. This
2736 By default, this command will show which locks are held. This
2805 includes the user and process holding the lock, the amount of time
2737 includes the user and process holding the lock, the amount of time
2806 the lock has been held, and the machine name where the process is
2738 the lock has been held, and the machine name where the process is
2807 running if it's not local.
2739 running if it's not local.
2808
2740
2809 Locks protect the integrity of Mercurial's data, so should be
2741 Locks protect the integrity of Mercurial's data, so should be
2810 treated with care. System crashes or other interruptions may cause
2742 treated with care. System crashes or other interruptions may cause
2811 locks to not be properly released, though Mercurial will usually
2743 locks to not be properly released, though Mercurial will usually
2812 detect and remove such stale locks automatically.
2744 detect and remove such stale locks automatically.
2813
2745
2814 However, detecting stale locks may not always be possible (for
2746 However, detecting stale locks may not always be possible (for
2815 instance, on a shared filesystem). Removing locks may also be
2747 instance, on a shared filesystem). Removing locks may also be
2816 blocked by filesystem permissions.
2748 blocked by filesystem permissions.
2817
2749
2818 Returns 0 if no locks are held.
2750 Returns 0 if no locks are held.
2819
2751
2820 """
2752 """
2821
2753
2822 if opts.get('force_lock'):
2754 if opts.get('force_lock'):
2823 repo.svfs.unlink('lock')
2755 repo.svfs.unlink('lock')
2824 if opts.get('force_wlock'):
2756 if opts.get('force_wlock'):
2825 repo.vfs.unlink('wlock')
2757 repo.vfs.unlink('wlock')
2826 if opts.get('force_lock') or opts.get('force_lock'):
2758 if opts.get('force_lock') or opts.get('force_lock'):
2827 return 0
2759 return 0
2828
2760
2829 now = time.time()
2761 now = time.time()
2830 held = 0
2762 held = 0
2831
2763
2832 def report(vfs, name, method):
2764 def report(vfs, name, method):
2833 # this causes stale locks to get reaped for more accurate reporting
2765 # this causes stale locks to get reaped for more accurate reporting
2834 try:
2766 try:
2835 l = method(False)
2767 l = method(False)
2836 except error.LockHeld:
2768 except error.LockHeld:
2837 l = None
2769 l = None
2838
2770
2839 if l:
2771 if l:
2840 l.release()
2772 l.release()
2841 else:
2773 else:
2842 try:
2774 try:
2843 stat = vfs.lstat(name)
2775 stat = vfs.lstat(name)
2844 age = now - stat.st_mtime
2776 age = now - stat.st_mtime
2845 user = util.username(stat.st_uid)
2777 user = util.username(stat.st_uid)
2846 locker = vfs.readlock(name)
2778 locker = vfs.readlock(name)
2847 if ":" in locker:
2779 if ":" in locker:
2848 host, pid = locker.split(':')
2780 host, pid = locker.split(':')
2849 if host == socket.gethostname():
2781 if host == socket.gethostname():
2850 locker = 'user %s, process %s' % (user, pid)
2782 locker = 'user %s, process %s' % (user, pid)
2851 else:
2783 else:
2852 locker = 'user %s, process %s, host %s' \
2784 locker = 'user %s, process %s, host %s' \
2853 % (user, pid, host)
2785 % (user, pid, host)
2854 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2786 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2855 return 1
2787 return 1
2856 except OSError as e:
2788 except OSError as e:
2857 if e.errno != errno.ENOENT:
2789 if e.errno != errno.ENOENT:
2858 raise
2790 raise
2859
2791
2860 ui.write(("%-6s free\n") % (name + ":"))
2792 ui.write(("%-6s free\n") % (name + ":"))
2861 return 0
2793 return 0
2862
2794
2863 held += report(repo.svfs, "lock", repo.lock)
2795 held += report(repo.svfs, "lock", repo.lock)
2864 held += report(repo.vfs, "wlock", repo.wlock)
2796 held += report(repo.vfs, "wlock", repo.wlock)
2865
2797
2866 return held
2798 return held
2867
2799
2868 @command('debugobsolete',
2800 @command('debugobsolete',
2869 [('', 'flags', 0, _('markers flag')),
2801 [('', 'flags', 0, _('markers flag')),
2870 ('', 'record-parents', False,
2802 ('', 'record-parents', False,
2871 _('record parent information for the precursor')),
2803 _('record parent information for the precursor')),
2872 ('r', 'rev', [], _('display markers relevant to REV')),
2804 ('r', 'rev', [], _('display markers relevant to REV')),
2873 ('', 'index', False, _('display index of the marker')),
2805 ('', 'index', False, _('display index of the marker')),
2874 ('', 'delete', [], _('delete markers specified by indices')),
2806 ('', 'delete', [], _('delete markers specified by indices')),
2875 ] + commitopts2 + formatteropts,
2807 ] + commitopts2 + formatteropts,
2876 _('[OBSOLETED [REPLACEMENT ...]]'))
2808 _('[OBSOLETED [REPLACEMENT ...]]'))
2877 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2809 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2878 """create arbitrary obsolete marker
2810 """create arbitrary obsolete marker
2879
2811
2880 With no arguments, displays the list of obsolescence markers."""
2812 With no arguments, displays the list of obsolescence markers."""
2881
2813
2882 def parsenodeid(s):
2814 def parsenodeid(s):
2883 try:
2815 try:
2884 # We do not use revsingle/revrange functions here to accept
2816 # We do not use revsingle/revrange functions here to accept
2885 # arbitrary node identifiers, possibly not present in the
2817 # arbitrary node identifiers, possibly not present in the
2886 # local repository.
2818 # local repository.
2887 n = bin(s)
2819 n = bin(s)
2888 if len(n) != len(nullid):
2820 if len(n) != len(nullid):
2889 raise TypeError()
2821 raise TypeError()
2890 return n
2822 return n
2891 except TypeError:
2823 except TypeError:
2892 raise error.Abort('changeset references must be full hexadecimal '
2824 raise error.Abort('changeset references must be full hexadecimal '
2893 'node identifiers')
2825 'node identifiers')
2894
2826
2895 if opts.get('delete'):
2827 if opts.get('delete'):
2896 indices = []
2828 indices = []
2897 for v in opts.get('delete'):
2829 for v in opts.get('delete'):
2898 try:
2830 try:
2899 indices.append(int(v))
2831 indices.append(int(v))
2900 except ValueError:
2832 except ValueError:
2901 raise error.Abort(_('invalid index value: %r') % v,
2833 raise error.Abort(_('invalid index value: %r') % v,
2902 hint=_('use integers for indices'))
2834 hint=_('use integers for indices'))
2903
2835
2904 if repo.currenttransaction():
2836 if repo.currenttransaction():
2905 raise error.Abort(_('cannot delete obsmarkers in the middle '
2837 raise error.Abort(_('cannot delete obsmarkers in the middle '
2906 'of transaction.'))
2838 'of transaction.'))
2907
2839
2908 with repo.lock():
2840 with repo.lock():
2909 n = repair.deleteobsmarkers(repo.obsstore, indices)
2841 n = repair.deleteobsmarkers(repo.obsstore, indices)
2910 ui.write(_('deleted %i obsolescence markers\n') % n)
2842 ui.write(_('deleted %i obsolescence markers\n') % n)
2911
2843
2912 return
2844 return
2913
2845
2914 if precursor is not None:
2846 if precursor is not None:
2915 if opts['rev']:
2847 if opts['rev']:
2916 raise error.Abort('cannot select revision when creating marker')
2848 raise error.Abort('cannot select revision when creating marker')
2917 metadata = {}
2849 metadata = {}
2918 metadata['user'] = opts['user'] or ui.username()
2850 metadata['user'] = opts['user'] or ui.username()
2919 succs = tuple(parsenodeid(succ) for succ in successors)
2851 succs = tuple(parsenodeid(succ) for succ in successors)
2920 l = repo.lock()
2852 l = repo.lock()
2921 try:
2853 try:
2922 tr = repo.transaction('debugobsolete')
2854 tr = repo.transaction('debugobsolete')
2923 try:
2855 try:
2924 date = opts.get('date')
2856 date = opts.get('date')
2925 if date:
2857 if date:
2926 date = util.parsedate(date)
2858 date = util.parsedate(date)
2927 else:
2859 else:
2928 date = None
2860 date = None
2929 prec = parsenodeid(precursor)
2861 prec = parsenodeid(precursor)
2930 parents = None
2862 parents = None
2931 if opts['record_parents']:
2863 if opts['record_parents']:
2932 if prec not in repo.unfiltered():
2864 if prec not in repo.unfiltered():
2933 raise error.Abort('cannot used --record-parents on '
2865 raise error.Abort('cannot used --record-parents on '
2934 'unknown changesets')
2866 'unknown changesets')
2935 parents = repo.unfiltered()[prec].parents()
2867 parents = repo.unfiltered()[prec].parents()
2936 parents = tuple(p.node() for p in parents)
2868 parents = tuple(p.node() for p in parents)
2937 repo.obsstore.create(tr, prec, succs, opts['flags'],
2869 repo.obsstore.create(tr, prec, succs, opts['flags'],
2938 parents=parents, date=date,
2870 parents=parents, date=date,
2939 metadata=metadata)
2871 metadata=metadata)
2940 tr.close()
2872 tr.close()
2941 except ValueError as exc:
2873 except ValueError as exc:
2942 raise error.Abort(_('bad obsmarker input: %s') % exc)
2874 raise error.Abort(_('bad obsmarker input: %s') % exc)
2943 finally:
2875 finally:
2944 tr.release()
2876 tr.release()
2945 finally:
2877 finally:
2946 l.release()
2878 l.release()
2947 else:
2879 else:
2948 if opts['rev']:
2880 if opts['rev']:
2949 revs = scmutil.revrange(repo, opts['rev'])
2881 revs = scmutil.revrange(repo, opts['rev'])
2950 nodes = [repo[r].node() for r in revs]
2882 nodes = [repo[r].node() for r in revs]
2951 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2883 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2952 markers.sort(key=lambda x: x._data)
2884 markers.sort(key=lambda x: x._data)
2953 else:
2885 else:
2954 markers = obsolete.getmarkers(repo)
2886 markers = obsolete.getmarkers(repo)
2955
2887
2956 markerstoiter = markers
2888 markerstoiter = markers
2957 isrelevant = lambda m: True
2889 isrelevant = lambda m: True
2958 if opts.get('rev') and opts.get('index'):
2890 if opts.get('rev') and opts.get('index'):
2959 markerstoiter = obsolete.getmarkers(repo)
2891 markerstoiter = obsolete.getmarkers(repo)
2960 markerset = set(markers)
2892 markerset = set(markers)
2961 isrelevant = lambda m: m in markerset
2893 isrelevant = lambda m: m in markerset
2962
2894
2963 fm = ui.formatter('debugobsolete', opts)
2895 fm = ui.formatter('debugobsolete', opts)
2964 for i, m in enumerate(markerstoiter):
2896 for i, m in enumerate(markerstoiter):
2965 if not isrelevant(m):
2897 if not isrelevant(m):
2966 # marker can be irrelevant when we're iterating over a set
2898 # marker can be irrelevant when we're iterating over a set
2967 # of markers (markerstoiter) which is bigger than the set
2899 # of markers (markerstoiter) which is bigger than the set
2968 # of markers we want to display (markers)
2900 # of markers we want to display (markers)
2969 # this can happen if both --index and --rev options are
2901 # this can happen if both --index and --rev options are
2970 # provided and thus we need to iterate over all of the markers
2902 # provided and thus we need to iterate over all of the markers
2971 # to get the correct indices, but only display the ones that
2903 # to get the correct indices, but only display the ones that
2972 # are relevant to --rev value
2904 # are relevant to --rev value
2973 continue
2905 continue
2974 fm.startitem()
2906 fm.startitem()
2975 ind = i if opts.get('index') else None
2907 ind = i if opts.get('index') else None
2976 cmdutil.showmarker(fm, m, index=ind)
2908 cmdutil.showmarker(fm, m, index=ind)
2977 fm.end()
2909 fm.end()
2978
2910
2979 @command('debugpathcomplete',
2911 @command('debugpathcomplete',
2980 [('f', 'full', None, _('complete an entire path')),
2912 [('f', 'full', None, _('complete an entire path')),
2981 ('n', 'normal', None, _('show only normal files')),
2913 ('n', 'normal', None, _('show only normal files')),
2982 ('a', 'added', None, _('show only added files')),
2914 ('a', 'added', None, _('show only added files')),
2983 ('r', 'removed', None, _('show only removed files'))],
2915 ('r', 'removed', None, _('show only removed files'))],
2984 _('FILESPEC...'))
2916 _('FILESPEC...'))
2985 def debugpathcomplete(ui, repo, *specs, **opts):
2917 def debugpathcomplete(ui, repo, *specs, **opts):
2986 '''complete part or all of a tracked path
2918 '''complete part or all of a tracked path
2987
2919
2988 This command supports shells that offer path name completion. It
2920 This command supports shells that offer path name completion. It
2989 currently completes only files already known to the dirstate.
2921 currently completes only files already known to the dirstate.
2990
2922
2991 Completion extends only to the next path segment unless
2923 Completion extends only to the next path segment unless
2992 --full is specified, in which case entire paths are used.'''
2924 --full is specified, in which case entire paths are used.'''
2993
2925
2994 def complete(path, acceptable):
2926 def complete(path, acceptable):
2995 dirstate = repo.dirstate
2927 dirstate = repo.dirstate
2996 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2928 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2997 rootdir = repo.root + os.sep
2929 rootdir = repo.root + os.sep
2998 if spec != repo.root and not spec.startswith(rootdir):
2930 if spec != repo.root and not spec.startswith(rootdir):
2999 return [], []
2931 return [], []
3000 if os.path.isdir(spec):
2932 if os.path.isdir(spec):
3001 spec += '/'
2933 spec += '/'
3002 spec = spec[len(rootdir):]
2934 spec = spec[len(rootdir):]
3003 fixpaths = pycompat.ossep != '/'
2935 fixpaths = pycompat.ossep != '/'
3004 if fixpaths:
2936 if fixpaths:
3005 spec = spec.replace(os.sep, '/')
2937 spec = spec.replace(os.sep, '/')
3006 speclen = len(spec)
2938 speclen = len(spec)
3007 fullpaths = opts['full']
2939 fullpaths = opts['full']
3008 files, dirs = set(), set()
2940 files, dirs = set(), set()
3009 adddir, addfile = dirs.add, files.add
2941 adddir, addfile = dirs.add, files.add
3010 for f, st in dirstate.iteritems():
2942 for f, st in dirstate.iteritems():
3011 if f.startswith(spec) and st[0] in acceptable:
2943 if f.startswith(spec) and st[0] in acceptable:
3012 if fixpaths:
2944 if fixpaths:
3013 f = f.replace('/', os.sep)
2945 f = f.replace('/', os.sep)
3014 if fullpaths:
2946 if fullpaths:
3015 addfile(f)
2947 addfile(f)
3016 continue
2948 continue
3017 s = f.find(os.sep, speclen)
2949 s = f.find(os.sep, speclen)
3018 if s >= 0:
2950 if s >= 0:
3019 adddir(f[:s])
2951 adddir(f[:s])
3020 else:
2952 else:
3021 addfile(f)
2953 addfile(f)
3022 return files, dirs
2954 return files, dirs
3023
2955
3024 acceptable = ''
2956 acceptable = ''
3025 if opts['normal']:
2957 if opts['normal']:
3026 acceptable += 'nm'
2958 acceptable += 'nm'
3027 if opts['added']:
2959 if opts['added']:
3028 acceptable += 'a'
2960 acceptable += 'a'
3029 if opts['removed']:
2961 if opts['removed']:
3030 acceptable += 'r'
2962 acceptable += 'r'
3031 cwd = repo.getcwd()
2963 cwd = repo.getcwd()
3032 if not specs:
2964 if not specs:
3033 specs = ['.']
2965 specs = ['.']
3034
2966
3035 files, dirs = set(), set()
2967 files, dirs = set(), set()
3036 for spec in specs:
2968 for spec in specs:
3037 f, d = complete(spec, acceptable or 'nmar')
2969 f, d = complete(spec, acceptable or 'nmar')
3038 files.update(f)
2970 files.update(f)
3039 dirs.update(d)
2971 dirs.update(d)
3040 files.update(dirs)
2972 files.update(dirs)
3041 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2973 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3042 ui.write('\n')
2974 ui.write('\n')
3043
2975
3044 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2976 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3045 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2977 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3046 '''access the pushkey key/value protocol
2978 '''access the pushkey key/value protocol
3047
2979
3048 With two args, list the keys in the given namespace.
2980 With two args, list the keys in the given namespace.
3049
2981
3050 With five args, set a key to new if it currently is set to old.
2982 With five args, set a key to new if it currently is set to old.
3051 Reports success or failure.
2983 Reports success or failure.
3052 '''
2984 '''
3053
2985
3054 target = hg.peer(ui, {}, repopath)
2986 target = hg.peer(ui, {}, repopath)
3055 if keyinfo:
2987 if keyinfo:
3056 key, old, new = keyinfo
2988 key, old, new = keyinfo
3057 r = target.pushkey(namespace, key, old, new)
2989 r = target.pushkey(namespace, key, old, new)
3058 ui.status(str(r) + '\n')
2990 ui.status(str(r) + '\n')
3059 return not r
2991 return not r
3060 else:
2992 else:
3061 for k, v in sorted(target.listkeys(namespace).iteritems()):
2993 for k, v in sorted(target.listkeys(namespace).iteritems()):
3062 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2994 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3063 v.encode('string-escape')))
2995 v.encode('string-escape')))
3064
2996
3065 @command('debugpvec', [], _('A B'))
2997 @command('debugpvec', [], _('A B'))
3066 def debugpvec(ui, repo, a, b=None):
2998 def debugpvec(ui, repo, a, b=None):
3067 ca = scmutil.revsingle(repo, a)
2999 ca = scmutil.revsingle(repo, a)
3068 cb = scmutil.revsingle(repo, b)
3000 cb = scmutil.revsingle(repo, b)
3069 pa = pvec.ctxpvec(ca)
3001 pa = pvec.ctxpvec(ca)
3070 pb = pvec.ctxpvec(cb)
3002 pb = pvec.ctxpvec(cb)
3071 if pa == pb:
3003 if pa == pb:
3072 rel = "="
3004 rel = "="
3073 elif pa > pb:
3005 elif pa > pb:
3074 rel = ">"
3006 rel = ">"
3075 elif pa < pb:
3007 elif pa < pb:
3076 rel = "<"
3008 rel = "<"
3077 elif pa | pb:
3009 elif pa | pb:
3078 rel = "|"
3010 rel = "|"
3079 ui.write(_("a: %s\n") % pa)
3011 ui.write(_("a: %s\n") % pa)
3080 ui.write(_("b: %s\n") % pb)
3012 ui.write(_("b: %s\n") % pb)
3081 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3013 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3082 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3014 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3083 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3015 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3084 pa.distance(pb), rel))
3016 pa.distance(pb), rel))
3085
3017
3086 @command('debugrebuilddirstate|debugrebuildstate',
3018 @command('debugrebuilddirstate|debugrebuildstate',
3087 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3019 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3088 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3020 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3089 'the working copy parent')),
3021 'the working copy parent')),
3090 ],
3022 ],
3091 _('[-r REV]'))
3023 _('[-r REV]'))
3092 def debugrebuilddirstate(ui, repo, rev, **opts):
3024 def debugrebuilddirstate(ui, repo, rev, **opts):
3093 """rebuild the dirstate as it would look like for the given revision
3025 """rebuild the dirstate as it would look like for the given revision
3094
3026
3095 If no revision is specified the first current parent will be used.
3027 If no revision is specified the first current parent will be used.
3096
3028
3097 The dirstate will be set to the files of the given revision.
3029 The dirstate will be set to the files of the given revision.
3098 The actual working directory content or existing dirstate
3030 The actual working directory content or existing dirstate
3099 information such as adds or removes is not considered.
3031 information such as adds or removes is not considered.
3100
3032
3101 ``minimal`` will only rebuild the dirstate status for files that claim to be
3033 ``minimal`` will only rebuild the dirstate status for files that claim to be
3102 tracked but are not in the parent manifest, or that exist in the parent
3034 tracked but are not in the parent manifest, or that exist in the parent
3103 manifest but are not in the dirstate. It will not change adds, removes, or
3035 manifest but are not in the dirstate. It will not change adds, removes, or
3104 modified files that are in the working copy parent.
3036 modified files that are in the working copy parent.
3105
3037
3106 One use of this command is to make the next :hg:`status` invocation
3038 One use of this command is to make the next :hg:`status` invocation
3107 check the actual file content.
3039 check the actual file content.
3108 """
3040 """
3109 ctx = scmutil.revsingle(repo, rev)
3041 ctx = scmutil.revsingle(repo, rev)
3110 with repo.wlock():
3042 with repo.wlock():
3111 dirstate = repo.dirstate
3043 dirstate = repo.dirstate
3112 changedfiles = None
3044 changedfiles = None
3113 # See command doc for what minimal does.
3045 # See command doc for what minimal does.
3114 if opts.get('minimal'):
3046 if opts.get('minimal'):
3115 manifestfiles = set(ctx.manifest().keys())
3047 manifestfiles = set(ctx.manifest().keys())
3116 dirstatefiles = set(dirstate)
3048 dirstatefiles = set(dirstate)
3117 manifestonly = manifestfiles - dirstatefiles
3049 manifestonly = manifestfiles - dirstatefiles
3118 dsonly = dirstatefiles - manifestfiles
3050 dsonly = dirstatefiles - manifestfiles
3119 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3051 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3120 changedfiles = manifestonly | dsnotadded
3052 changedfiles = manifestonly | dsnotadded
3121
3053
3122 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3054 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3123
3055
3124 @command('debugrebuildfncache', [], '')
3056 @command('debugrebuildfncache', [], '')
3125 def debugrebuildfncache(ui, repo):
3057 def debugrebuildfncache(ui, repo):
3126 """rebuild the fncache file"""
3058 """rebuild the fncache file"""
3127 repair.rebuildfncache(ui, repo)
3059 repair.rebuildfncache(ui, repo)
3128
3060
3129 @command('debugrename',
3061 @command('debugrename',
3130 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3062 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3131 _('[-r REV] FILE'))
3063 _('[-r REV] FILE'))
3132 def debugrename(ui, repo, file1, *pats, **opts):
3064 def debugrename(ui, repo, file1, *pats, **opts):
3133 """dump rename information"""
3065 """dump rename information"""
3134
3066
3135 ctx = scmutil.revsingle(repo, opts.get('rev'))
3067 ctx = scmutil.revsingle(repo, opts.get('rev'))
3136 m = scmutil.match(ctx, (file1,) + pats, opts)
3068 m = scmutil.match(ctx, (file1,) + pats, opts)
3137 for abs in ctx.walk(m):
3069 for abs in ctx.walk(m):
3138 fctx = ctx[abs]
3070 fctx = ctx[abs]
3139 o = fctx.filelog().renamed(fctx.filenode())
3071 o = fctx.filelog().renamed(fctx.filenode())
3140 rel = m.rel(abs)
3072 rel = m.rel(abs)
3141 if o:
3073 if o:
3142 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3074 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3143 else:
3075 else:
3144 ui.write(_("%s not renamed\n") % rel)
3076 ui.write(_("%s not renamed\n") % rel)
3145
3077
3146 @command('debugrevlog', debugrevlogopts +
3078 @command('debugrevlog', debugrevlogopts +
3147 [('d', 'dump', False, _('dump index data'))],
3079 [('d', 'dump', False, _('dump index data'))],
3148 _('-c|-m|FILE'),
3080 _('-c|-m|FILE'),
3149 optionalrepo=True)
3081 optionalrepo=True)
3150 def debugrevlog(ui, repo, file_=None, **opts):
3082 def debugrevlog(ui, repo, file_=None, **opts):
3151 """show data and statistics about a revlog"""
3083 """show data and statistics about a revlog"""
3152 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3084 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3153
3085
3154 if opts.get("dump"):
3086 if opts.get("dump"):
3155 numrevs = len(r)
3087 numrevs = len(r)
3156 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3088 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3157 " rawsize totalsize compression heads chainlen\n"))
3089 " rawsize totalsize compression heads chainlen\n"))
3158 ts = 0
3090 ts = 0
3159 heads = set()
3091 heads = set()
3160
3092
3161 for rev in xrange(numrevs):
3093 for rev in xrange(numrevs):
3162 dbase = r.deltaparent(rev)
3094 dbase = r.deltaparent(rev)
3163 if dbase == -1:
3095 if dbase == -1:
3164 dbase = rev
3096 dbase = rev
3165 cbase = r.chainbase(rev)
3097 cbase = r.chainbase(rev)
3166 clen = r.chainlen(rev)
3098 clen = r.chainlen(rev)
3167 p1, p2 = r.parentrevs(rev)
3099 p1, p2 = r.parentrevs(rev)
3168 rs = r.rawsize(rev)
3100 rs = r.rawsize(rev)
3169 ts = ts + rs
3101 ts = ts + rs
3170 heads -= set(r.parentrevs(rev))
3102 heads -= set(r.parentrevs(rev))
3171 heads.add(rev)
3103 heads.add(rev)
3172 try:
3104 try:
3173 compression = ts / r.end(rev)
3105 compression = ts / r.end(rev)
3174 except ZeroDivisionError:
3106 except ZeroDivisionError:
3175 compression = 0
3107 compression = 0
3176 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3108 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3177 "%11d %5d %8d\n" %
3109 "%11d %5d %8d\n" %
3178 (rev, p1, p2, r.start(rev), r.end(rev),
3110 (rev, p1, p2, r.start(rev), r.end(rev),
3179 r.start(dbase), r.start(cbase),
3111 r.start(dbase), r.start(cbase),
3180 r.start(p1), r.start(p2),
3112 r.start(p1), r.start(p2),
3181 rs, ts, compression, len(heads), clen))
3113 rs, ts, compression, len(heads), clen))
3182 return 0
3114 return 0
3183
3115
3184 v = r.version
3116 v = r.version
3185 format = v & 0xFFFF
3117 format = v & 0xFFFF
3186 flags = []
3118 flags = []
3187 gdelta = False
3119 gdelta = False
3188 if v & revlog.REVLOGNGINLINEDATA:
3120 if v & revlog.REVLOGNGINLINEDATA:
3189 flags.append('inline')
3121 flags.append('inline')
3190 if v & revlog.REVLOGGENERALDELTA:
3122 if v & revlog.REVLOGGENERALDELTA:
3191 gdelta = True
3123 gdelta = True
3192 flags.append('generaldelta')
3124 flags.append('generaldelta')
3193 if not flags:
3125 if not flags:
3194 flags = ['(none)']
3126 flags = ['(none)']
3195
3127
3196 nummerges = 0
3128 nummerges = 0
3197 numfull = 0
3129 numfull = 0
3198 numprev = 0
3130 numprev = 0
3199 nump1 = 0
3131 nump1 = 0
3200 nump2 = 0
3132 nump2 = 0
3201 numother = 0
3133 numother = 0
3202 nump1prev = 0
3134 nump1prev = 0
3203 nump2prev = 0
3135 nump2prev = 0
3204 chainlengths = []
3136 chainlengths = []
3205
3137
3206 datasize = [None, 0, 0]
3138 datasize = [None, 0, 0]
3207 fullsize = [None, 0, 0]
3139 fullsize = [None, 0, 0]
3208 deltasize = [None, 0, 0]
3140 deltasize = [None, 0, 0]
3209 chunktypecounts = {}
3141 chunktypecounts = {}
3210 chunktypesizes = {}
3142 chunktypesizes = {}
3211
3143
3212 def addsize(size, l):
3144 def addsize(size, l):
3213 if l[0] is None or size < l[0]:
3145 if l[0] is None or size < l[0]:
3214 l[0] = size
3146 l[0] = size
3215 if size > l[1]:
3147 if size > l[1]:
3216 l[1] = size
3148 l[1] = size
3217 l[2] += size
3149 l[2] += size
3218
3150
3219 numrevs = len(r)
3151 numrevs = len(r)
3220 for rev in xrange(numrevs):
3152 for rev in xrange(numrevs):
3221 p1, p2 = r.parentrevs(rev)
3153 p1, p2 = r.parentrevs(rev)
3222 delta = r.deltaparent(rev)
3154 delta = r.deltaparent(rev)
3223 if format > 0:
3155 if format > 0:
3224 addsize(r.rawsize(rev), datasize)
3156 addsize(r.rawsize(rev), datasize)
3225 if p2 != nullrev:
3157 if p2 != nullrev:
3226 nummerges += 1
3158 nummerges += 1
3227 size = r.length(rev)
3159 size = r.length(rev)
3228 if delta == nullrev:
3160 if delta == nullrev:
3229 chainlengths.append(0)
3161 chainlengths.append(0)
3230 numfull += 1
3162 numfull += 1
3231 addsize(size, fullsize)
3163 addsize(size, fullsize)
3232 else:
3164 else:
3233 chainlengths.append(chainlengths[delta] + 1)
3165 chainlengths.append(chainlengths[delta] + 1)
3234 addsize(size, deltasize)
3166 addsize(size, deltasize)
3235 if delta == rev - 1:
3167 if delta == rev - 1:
3236 numprev += 1
3168 numprev += 1
3237 if delta == p1:
3169 if delta == p1:
3238 nump1prev += 1
3170 nump1prev += 1
3239 elif delta == p2:
3171 elif delta == p2:
3240 nump2prev += 1
3172 nump2prev += 1
3241 elif delta == p1:
3173 elif delta == p1:
3242 nump1 += 1
3174 nump1 += 1
3243 elif delta == p2:
3175 elif delta == p2:
3244 nump2 += 1
3176 nump2 += 1
3245 elif delta != nullrev:
3177 elif delta != nullrev:
3246 numother += 1
3178 numother += 1
3247
3179
3248 # Obtain data on the raw chunks in the revlog.
3180 # Obtain data on the raw chunks in the revlog.
3249 chunk = r._chunkraw(rev, rev)[1]
3181 chunk = r._chunkraw(rev, rev)[1]
3250 if chunk:
3182 if chunk:
3251 chunktype = chunk[0]
3183 chunktype = chunk[0]
3252 else:
3184 else:
3253 chunktype = 'empty'
3185 chunktype = 'empty'
3254
3186
3255 if chunktype not in chunktypecounts:
3187 if chunktype not in chunktypecounts:
3256 chunktypecounts[chunktype] = 0
3188 chunktypecounts[chunktype] = 0
3257 chunktypesizes[chunktype] = 0
3189 chunktypesizes[chunktype] = 0
3258
3190
3259 chunktypecounts[chunktype] += 1
3191 chunktypecounts[chunktype] += 1
3260 chunktypesizes[chunktype] += size
3192 chunktypesizes[chunktype] += size
3261
3193
3262 # Adjust size min value for empty cases
3194 # Adjust size min value for empty cases
3263 for size in (datasize, fullsize, deltasize):
3195 for size in (datasize, fullsize, deltasize):
3264 if size[0] is None:
3196 if size[0] is None:
3265 size[0] = 0
3197 size[0] = 0
3266
3198
3267 numdeltas = numrevs - numfull
3199 numdeltas = numrevs - numfull
3268 numoprev = numprev - nump1prev - nump2prev
3200 numoprev = numprev - nump1prev - nump2prev
3269 totalrawsize = datasize[2]
3201 totalrawsize = datasize[2]
3270 datasize[2] /= numrevs
3202 datasize[2] /= numrevs
3271 fulltotal = fullsize[2]
3203 fulltotal = fullsize[2]
3272 fullsize[2] /= numfull
3204 fullsize[2] /= numfull
3273 deltatotal = deltasize[2]
3205 deltatotal = deltasize[2]
3274 if numrevs - numfull > 0:
3206 if numrevs - numfull > 0:
3275 deltasize[2] /= numrevs - numfull
3207 deltasize[2] /= numrevs - numfull
3276 totalsize = fulltotal + deltatotal
3208 totalsize = fulltotal + deltatotal
3277 avgchainlen = sum(chainlengths) / numrevs
3209 avgchainlen = sum(chainlengths) / numrevs
3278 maxchainlen = max(chainlengths)
3210 maxchainlen = max(chainlengths)
3279 compratio = 1
3211 compratio = 1
3280 if totalsize:
3212 if totalsize:
3281 compratio = totalrawsize / totalsize
3213 compratio = totalrawsize / totalsize
3282
3214
3283 basedfmtstr = '%%%dd\n'
3215 basedfmtstr = '%%%dd\n'
3284 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3216 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3285
3217
3286 def dfmtstr(max):
3218 def dfmtstr(max):
3287 return basedfmtstr % len(str(max))
3219 return basedfmtstr % len(str(max))
3288 def pcfmtstr(max, padding=0):
3220 def pcfmtstr(max, padding=0):
3289 return basepcfmtstr % (len(str(max)), ' ' * padding)
3221 return basepcfmtstr % (len(str(max)), ' ' * padding)
3290
3222
3291 def pcfmt(value, total):
3223 def pcfmt(value, total):
3292 if total:
3224 if total:
3293 return (value, 100 * float(value) / total)
3225 return (value, 100 * float(value) / total)
3294 else:
3226 else:
3295 return value, 100.0
3227 return value, 100.0
3296
3228
3297 ui.write(('format : %d\n') % format)
3229 ui.write(('format : %d\n') % format)
3298 ui.write(('flags : %s\n') % ', '.join(flags))
3230 ui.write(('flags : %s\n') % ', '.join(flags))
3299
3231
3300 ui.write('\n')
3232 ui.write('\n')
3301 fmt = pcfmtstr(totalsize)
3233 fmt = pcfmtstr(totalsize)
3302 fmt2 = dfmtstr(totalsize)
3234 fmt2 = dfmtstr(totalsize)
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3235 ui.write(('revisions : ') + fmt2 % numrevs)
3304 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3236 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3305 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3237 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3306 ui.write(('revisions : ') + fmt2 % numrevs)
3238 ui.write(('revisions : ') + fmt2 % numrevs)
3307 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3239 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3308 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3240 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3309 ui.write(('revision size : ') + fmt2 % totalsize)
3241 ui.write(('revision size : ') + fmt2 % totalsize)
3310 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3242 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3311 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3243 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3312
3244
3313 def fmtchunktype(chunktype):
3245 def fmtchunktype(chunktype):
3314 if chunktype == 'empty':
3246 if chunktype == 'empty':
3315 return ' %s : ' % chunktype
3247 return ' %s : ' % chunktype
3316 elif chunktype in string.ascii_letters:
3248 elif chunktype in string.ascii_letters:
3317 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3249 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3318 else:
3250 else:
3319 return ' 0x%s : ' % hex(chunktype)
3251 return ' 0x%s : ' % hex(chunktype)
3320
3252
3321 ui.write('\n')
3253 ui.write('\n')
3322 ui.write(('chunks : ') + fmt2 % numrevs)
3254 ui.write(('chunks : ') + fmt2 % numrevs)
3323 for chunktype in sorted(chunktypecounts):
3255 for chunktype in sorted(chunktypecounts):
3324 ui.write(fmtchunktype(chunktype))
3256 ui.write(fmtchunktype(chunktype))
3325 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3257 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3326 ui.write(('chunks size : ') + fmt2 % totalsize)
3258 ui.write(('chunks size : ') + fmt2 % totalsize)
3327 for chunktype in sorted(chunktypecounts):
3259 for chunktype in sorted(chunktypecounts):
3328 ui.write(fmtchunktype(chunktype))
3260 ui.write(fmtchunktype(chunktype))
3329 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3261 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3330
3262
3331 ui.write('\n')
3263 ui.write('\n')
3332 fmt = dfmtstr(max(avgchainlen, compratio))
3264 fmt = dfmtstr(max(avgchainlen, compratio))
3333 ui.write(('avg chain length : ') + fmt % avgchainlen)
3265 ui.write(('avg chain length : ') + fmt % avgchainlen)
3334 ui.write(('max chain length : ') + fmt % maxchainlen)
3266 ui.write(('max chain length : ') + fmt % maxchainlen)
3335 ui.write(('compression ratio : ') + fmt % compratio)
3267 ui.write(('compression ratio : ') + fmt % compratio)
3336
3268
3337 if format > 0:
3269 if format > 0:
3338 ui.write('\n')
3270 ui.write('\n')
3339 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3271 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3340 % tuple(datasize))
3272 % tuple(datasize))
3341 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3273 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3342 % tuple(fullsize))
3274 % tuple(fullsize))
3343 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3275 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3344 % tuple(deltasize))
3276 % tuple(deltasize))
3345
3277
3346 if numdeltas > 0:
3278 if numdeltas > 0:
3347 ui.write('\n')
3279 ui.write('\n')
3348 fmt = pcfmtstr(numdeltas)
3280 fmt = pcfmtstr(numdeltas)
3349 fmt2 = pcfmtstr(numdeltas, 4)
3281 fmt2 = pcfmtstr(numdeltas, 4)
3350 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3282 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3351 if numprev > 0:
3283 if numprev > 0:
3352 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3284 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3353 numprev))
3285 numprev))
3354 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3286 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3355 numprev))
3287 numprev))
3356 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3288 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3357 numprev))
3289 numprev))
3358 if gdelta:
3290 if gdelta:
3359 ui.write(('deltas against p1 : ')
3291 ui.write(('deltas against p1 : ')
3360 + fmt % pcfmt(nump1, numdeltas))
3292 + fmt % pcfmt(nump1, numdeltas))
3361 ui.write(('deltas against p2 : ')
3293 ui.write(('deltas against p2 : ')
3362 + fmt % pcfmt(nump2, numdeltas))
3294 + fmt % pcfmt(nump2, numdeltas))
3363 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3295 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3364 numdeltas))
3296 numdeltas))
3365
3297
3366 @command('debugrevspec',
3298 @command('debugrevspec',
3367 [('', 'optimize', None,
3299 [('', 'optimize', None,
3368 _('print parsed tree after optimizing (DEPRECATED)')),
3300 _('print parsed tree after optimizing (DEPRECATED)')),
3369 ('p', 'show-stage', [],
3301 ('p', 'show-stage', [],
3370 _('print parsed tree at the given stage'), _('NAME')),
3302 _('print parsed tree at the given stage'), _('NAME')),
3371 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3303 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3372 ('', 'verify-optimized', False, _('verify optimized result')),
3304 ('', 'verify-optimized', False, _('verify optimized result')),
3373 ],
3305 ],
3374 ('REVSPEC'))
3306 ('REVSPEC'))
3375 def debugrevspec(ui, repo, expr, **opts):
3307 def debugrevspec(ui, repo, expr, **opts):
3376 """parse and apply a revision specification
3308 """parse and apply a revision specification
3377
3309
3378 Use -p/--show-stage option to print the parsed tree at the given stages.
3310 Use -p/--show-stage option to print the parsed tree at the given stages.
3379 Use -p all to print tree at every stage.
3311 Use -p all to print tree at every stage.
3380
3312
3381 Use --verify-optimized to compare the optimized result with the unoptimized
3313 Use --verify-optimized to compare the optimized result with the unoptimized
3382 one. Returns 1 if the optimized result differs.
3314 one. Returns 1 if the optimized result differs.
3383 """
3315 """
3384 stages = [
3316 stages = [
3385 ('parsed', lambda tree: tree),
3317 ('parsed', lambda tree: tree),
3386 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3318 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3387 ('concatenated', revset.foldconcat),
3319 ('concatenated', revset.foldconcat),
3388 ('analyzed', revset.analyze),
3320 ('analyzed', revset.analyze),
3389 ('optimized', revset.optimize),
3321 ('optimized', revset.optimize),
3390 ]
3322 ]
3391 if opts['no_optimized']:
3323 if opts['no_optimized']:
3392 stages = stages[:-1]
3324 stages = stages[:-1]
3393 if opts['verify_optimized'] and opts['no_optimized']:
3325 if opts['verify_optimized'] and opts['no_optimized']:
3394 raise error.Abort(_('cannot use --verify-optimized with '
3326 raise error.Abort(_('cannot use --verify-optimized with '
3395 '--no-optimized'))
3327 '--no-optimized'))
3396 stagenames = set(n for n, f in stages)
3328 stagenames = set(n for n, f in stages)
3397
3329
3398 showalways = set()
3330 showalways = set()
3399 showchanged = set()
3331 showchanged = set()
3400 if ui.verbose and not opts['show_stage']:
3332 if ui.verbose and not opts['show_stage']:
3401 # show parsed tree by --verbose (deprecated)
3333 # show parsed tree by --verbose (deprecated)
3402 showalways.add('parsed')
3334 showalways.add('parsed')
3403 showchanged.update(['expanded', 'concatenated'])
3335 showchanged.update(['expanded', 'concatenated'])
3404 if opts['optimize']:
3336 if opts['optimize']:
3405 showalways.add('optimized')
3337 showalways.add('optimized')
3406 if opts['show_stage'] and opts['optimize']:
3338 if opts['show_stage'] and opts['optimize']:
3407 raise error.Abort(_('cannot use --optimize with --show-stage'))
3339 raise error.Abort(_('cannot use --optimize with --show-stage'))
3408 if opts['show_stage'] == ['all']:
3340 if opts['show_stage'] == ['all']:
3409 showalways.update(stagenames)
3341 showalways.update(stagenames)
3410 else:
3342 else:
3411 for n in opts['show_stage']:
3343 for n in opts['show_stage']:
3412 if n not in stagenames:
3344 if n not in stagenames:
3413 raise error.Abort(_('invalid stage name: %s') % n)
3345 raise error.Abort(_('invalid stage name: %s') % n)
3414 showalways.update(opts['show_stage'])
3346 showalways.update(opts['show_stage'])
3415
3347
3416 treebystage = {}
3348 treebystage = {}
3417 printedtree = None
3349 printedtree = None
3418 tree = revset.parse(expr, lookup=repo.__contains__)
3350 tree = revset.parse(expr, lookup=repo.__contains__)
3419 for n, f in stages:
3351 for n, f in stages:
3420 treebystage[n] = tree = f(tree)
3352 treebystage[n] = tree = f(tree)
3421 if n in showalways or (n in showchanged and tree != printedtree):
3353 if n in showalways or (n in showchanged and tree != printedtree):
3422 if opts['show_stage'] or n != 'parsed':
3354 if opts['show_stage'] or n != 'parsed':
3423 ui.write(("* %s:\n") % n)
3355 ui.write(("* %s:\n") % n)
3424 ui.write(revset.prettyformat(tree), "\n")
3356 ui.write(revset.prettyformat(tree), "\n")
3425 printedtree = tree
3357 printedtree = tree
3426
3358
3427 if opts['verify_optimized']:
3359 if opts['verify_optimized']:
3428 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3360 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3429 brevs = revset.makematcher(treebystage['optimized'])(repo)
3361 brevs = revset.makematcher(treebystage['optimized'])(repo)
3430 if ui.verbose:
3362 if ui.verbose:
3431 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3363 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3432 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3364 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3433 arevs = list(arevs)
3365 arevs = list(arevs)
3434 brevs = list(brevs)
3366 brevs = list(brevs)
3435 if arevs == brevs:
3367 if arevs == brevs:
3436 return 0
3368 return 0
3437 ui.write(('--- analyzed\n'), label='diff.file_a')
3369 ui.write(('--- analyzed\n'), label='diff.file_a')
3438 ui.write(('+++ optimized\n'), label='diff.file_b')
3370 ui.write(('+++ optimized\n'), label='diff.file_b')
3439 sm = difflib.SequenceMatcher(None, arevs, brevs)
3371 sm = difflib.SequenceMatcher(None, arevs, brevs)
3440 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3372 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3441 if tag in ('delete', 'replace'):
3373 if tag in ('delete', 'replace'):
3442 for c in arevs[alo:ahi]:
3374 for c in arevs[alo:ahi]:
3443 ui.write('-%s\n' % c, label='diff.deleted')
3375 ui.write('-%s\n' % c, label='diff.deleted')
3444 if tag in ('insert', 'replace'):
3376 if tag in ('insert', 'replace'):
3445 for c in brevs[blo:bhi]:
3377 for c in brevs[blo:bhi]:
3446 ui.write('+%s\n' % c, label='diff.inserted')
3378 ui.write('+%s\n' % c, label='diff.inserted')
3447 if tag == 'equal':
3379 if tag == 'equal':
3448 for c in arevs[alo:ahi]:
3380 for c in arevs[alo:ahi]:
3449 ui.write(' %s\n' % c)
3381 ui.write(' %s\n' % c)
3450 return 1
3382 return 1
3451
3383
3452 func = revset.makematcher(tree)
3384 func = revset.makematcher(tree)
3453 revs = func(repo)
3385 revs = func(repo)
3454 if ui.verbose:
3386 if ui.verbose:
3455 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3387 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3456 for c in revs:
3388 for c in revs:
3457 ui.write("%s\n" % c)
3389 ui.write("%s\n" % c)
3458
3390
3459 @command('debugsetparents', [], _('REV1 [REV2]'))
3391 @command('debugsetparents', [], _('REV1 [REV2]'))
3460 def debugsetparents(ui, repo, rev1, rev2=None):
3392 def debugsetparents(ui, repo, rev1, rev2=None):
3461 """manually set the parents of the current working directory
3393 """manually set the parents of the current working directory
3462
3394
3463 This is useful for writing repository conversion tools, but should
3395 This is useful for writing repository conversion tools, but should
3464 be used with care. For example, neither the working directory nor the
3396 be used with care. For example, neither the working directory nor the
3465 dirstate is updated, so file status may be incorrect after running this
3397 dirstate is updated, so file status may be incorrect after running this
3466 command.
3398 command.
3467
3399
3468 Returns 0 on success.
3400 Returns 0 on success.
3469 """
3401 """
3470
3402
3471 r1 = scmutil.revsingle(repo, rev1).node()
3403 r1 = scmutil.revsingle(repo, rev1).node()
3472 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3404 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3473
3405
3474 with repo.wlock():
3406 with repo.wlock():
3475 repo.setparents(r1, r2)
3407 repo.setparents(r1, r2)
3476
3408
3477 @command('debugdirstate|debugstate',
3409 @command('debugdirstate|debugstate',
3478 [('', 'nodates', None, _('do not display the saved mtime')),
3410 [('', 'nodates', None, _('do not display the saved mtime')),
3479 ('', 'datesort', None, _('sort by saved mtime'))],
3411 ('', 'datesort', None, _('sort by saved mtime'))],
3480 _('[OPTION]...'))
3412 _('[OPTION]...'))
3481 def debugstate(ui, repo, **opts):
3413 def debugstate(ui, repo, **opts):
3482 """show the contents of the current dirstate"""
3414 """show the contents of the current dirstate"""
3483
3415
3484 nodates = opts.get('nodates')
3416 nodates = opts.get('nodates')
3485 datesort = opts.get('datesort')
3417 datesort = opts.get('datesort')
3486
3418
3487 timestr = ""
3419 timestr = ""
3488 if datesort:
3420 if datesort:
3489 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3421 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3490 else:
3422 else:
3491 keyfunc = None # sort by filename
3423 keyfunc = None # sort by filename
3492 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3424 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3493 if ent[3] == -1:
3425 if ent[3] == -1:
3494 timestr = 'unset '
3426 timestr = 'unset '
3495 elif nodates:
3427 elif nodates:
3496 timestr = 'set '
3428 timestr = 'set '
3497 else:
3429 else:
3498 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3430 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3499 time.localtime(ent[3]))
3431 time.localtime(ent[3]))
3500 if ent[1] & 0o20000:
3432 if ent[1] & 0o20000:
3501 mode = 'lnk'
3433 mode = 'lnk'
3502 else:
3434 else:
3503 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3435 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3504 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3436 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3505 for f in repo.dirstate.copies():
3437 for f in repo.dirstate.copies():
3506 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3438 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3507
3439
3508 @command('debugsub',
3440 @command('debugsub',
3509 [('r', 'rev', '',
3441 [('r', 'rev', '',
3510 _('revision to check'), _('REV'))],
3442 _('revision to check'), _('REV'))],
3511 _('[-r REV] [REV]'))
3443 _('[-r REV] [REV]'))
3512 def debugsub(ui, repo, rev=None):
3444 def debugsub(ui, repo, rev=None):
3513 ctx = scmutil.revsingle(repo, rev, None)
3445 ctx = scmutil.revsingle(repo, rev, None)
3514 for k, v in sorted(ctx.substate.items()):
3446 for k, v in sorted(ctx.substate.items()):
3515 ui.write(('path %s\n') % k)
3447 ui.write(('path %s\n') % k)
3516 ui.write((' source %s\n') % v[0])
3448 ui.write((' source %s\n') % v[0])
3517 ui.write((' revision %s\n') % v[1])
3449 ui.write((' revision %s\n') % v[1])
3518
3450
3519 @command('debugsuccessorssets',
3451 @command('debugsuccessorssets',
3520 [],
3452 [],
3521 _('[REV]'))
3453 _('[REV]'))
3522 def debugsuccessorssets(ui, repo, *revs):
3454 def debugsuccessorssets(ui, repo, *revs):
3523 """show set of successors for revision
3455 """show set of successors for revision
3524
3456
3525 A successors set of changeset A is a consistent group of revisions that
3457 A successors set of changeset A is a consistent group of revisions that
3526 succeed A. It contains non-obsolete changesets only.
3458 succeed A. It contains non-obsolete changesets only.
3527
3459
3528 In most cases a changeset A has a single successors set containing a single
3460 In most cases a changeset A has a single successors set containing a single
3529 successor (changeset A replaced by A').
3461 successor (changeset A replaced by A').
3530
3462
3531 A changeset that is made obsolete with no successors are called "pruned".
3463 A changeset that is made obsolete with no successors are called "pruned".
3532 Such changesets have no successors sets at all.
3464 Such changesets have no successors sets at all.
3533
3465
3534 A changeset that has been "split" will have a successors set containing
3466 A changeset that has been "split" will have a successors set containing
3535 more than one successor.
3467 more than one successor.
3536
3468
3537 A changeset that has been rewritten in multiple different ways is called
3469 A changeset that has been rewritten in multiple different ways is called
3538 "divergent". Such changesets have multiple successor sets (each of which
3470 "divergent". Such changesets have multiple successor sets (each of which
3539 may also be split, i.e. have multiple successors).
3471 may also be split, i.e. have multiple successors).
3540
3472
3541 Results are displayed as follows::
3473 Results are displayed as follows::
3542
3474
3543 <rev1>
3475 <rev1>
3544 <successors-1A>
3476 <successors-1A>
3545 <rev2>
3477 <rev2>
3546 <successors-2A>
3478 <successors-2A>
3547 <successors-2B1> <successors-2B2> <successors-2B3>
3479 <successors-2B1> <successors-2B2> <successors-2B3>
3548
3480
3549 Here rev2 has two possible (i.e. divergent) successors sets. The first
3481 Here rev2 has two possible (i.e. divergent) successors sets. The first
3550 holds one element, whereas the second holds three (i.e. the changeset has
3482 holds one element, whereas the second holds three (i.e. the changeset has
3551 been split).
3483 been split).
3552 """
3484 """
3553 # passed to successorssets caching computation from one call to another
3485 # passed to successorssets caching computation from one call to another
3554 cache = {}
3486 cache = {}
3555 ctx2str = str
3487 ctx2str = str
3556 node2str = short
3488 node2str = short
3557 if ui.debug():
3489 if ui.debug():
3558 def ctx2str(ctx):
3490 def ctx2str(ctx):
3559 return ctx.hex()
3491 return ctx.hex()
3560 node2str = hex
3492 node2str = hex
3561 for rev in scmutil.revrange(repo, revs):
3493 for rev in scmutil.revrange(repo, revs):
3562 ctx = repo[rev]
3494 ctx = repo[rev]
3563 ui.write('%s\n'% ctx2str(ctx))
3495 ui.write('%s\n'% ctx2str(ctx))
3564 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3496 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3565 if succsset:
3497 if succsset:
3566 ui.write(' ')
3498 ui.write(' ')
3567 ui.write(node2str(succsset[0]))
3499 ui.write(node2str(succsset[0]))
3568 for node in succsset[1:]:
3500 for node in succsset[1:]:
3569 ui.write(' ')
3501 ui.write(' ')
3570 ui.write(node2str(node))
3502 ui.write(node2str(node))
3571 ui.write('\n')
3503 ui.write('\n')
3572
3504
3573 @command('debugtemplate',
3505 @command('debugtemplate',
3574 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3506 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3575 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3507 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3576 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3508 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3577 optionalrepo=True)
3509 optionalrepo=True)
3578 def debugtemplate(ui, repo, tmpl, **opts):
3510 def debugtemplate(ui, repo, tmpl, **opts):
3579 """parse and apply a template
3511 """parse and apply a template
3580
3512
3581 If -r/--rev is given, the template is processed as a log template and
3513 If -r/--rev is given, the template is processed as a log template and
3582 applied to the given changesets. Otherwise, it is processed as a generic
3514 applied to the given changesets. Otherwise, it is processed as a generic
3583 template.
3515 template.
3584
3516
3585 Use --verbose to print the parsed tree.
3517 Use --verbose to print the parsed tree.
3586 """
3518 """
3587 revs = None
3519 revs = None
3588 if opts['rev']:
3520 if opts['rev']:
3589 if repo is None:
3521 if repo is None:
3590 raise error.RepoError(_('there is no Mercurial repository here '
3522 raise error.RepoError(_('there is no Mercurial repository here '
3591 '(.hg not found)'))
3523 '(.hg not found)'))
3592 revs = scmutil.revrange(repo, opts['rev'])
3524 revs = scmutil.revrange(repo, opts['rev'])
3593
3525
3594 props = {}
3526 props = {}
3595 for d in opts['define']:
3527 for d in opts['define']:
3596 try:
3528 try:
3597 k, v = (e.strip() for e in d.split('=', 1))
3529 k, v = (e.strip() for e in d.split('=', 1))
3598 if not k:
3530 if not k:
3599 raise ValueError
3531 raise ValueError
3600 props[k] = v
3532 props[k] = v
3601 except ValueError:
3533 except ValueError:
3602 raise error.Abort(_('malformed keyword definition: %s') % d)
3534 raise error.Abort(_('malformed keyword definition: %s') % d)
3603
3535
3604 if ui.verbose:
3536 if ui.verbose:
3605 aliases = ui.configitems('templatealias')
3537 aliases = ui.configitems('templatealias')
3606 tree = templater.parse(tmpl)
3538 tree = templater.parse(tmpl)
3607 ui.note(templater.prettyformat(tree), '\n')
3539 ui.note(templater.prettyformat(tree), '\n')
3608 newtree = templater.expandaliases(tree, aliases)
3540 newtree = templater.expandaliases(tree, aliases)
3609 if newtree != tree:
3541 if newtree != tree:
3610 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3542 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3611
3543
3612 mapfile = None
3544 mapfile = None
3613 if revs is None:
3545 if revs is None:
3614 k = 'debugtemplate'
3546 k = 'debugtemplate'
3615 t = formatter.maketemplater(ui, k, tmpl)
3547 t = formatter.maketemplater(ui, k, tmpl)
3616 ui.write(templater.stringify(t(k, **props)))
3548 ui.write(templater.stringify(t(k, **props)))
3617 else:
3549 else:
3618 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3550 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3619 mapfile, buffered=False)
3551 mapfile, buffered=False)
3620 for r in revs:
3552 for r in revs:
3621 displayer.show(repo[r], **props)
3553 displayer.show(repo[r], **props)
3622 displayer.close()
3554 displayer.close()
3623
3555
3624 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3556 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3625 def debugwalk(ui, repo, *pats, **opts):
3557 def debugwalk(ui, repo, *pats, **opts):
3626 """show how files match on given patterns"""
3558 """show how files match on given patterns"""
3627 m = scmutil.match(repo[None], pats, opts)
3559 m = scmutil.match(repo[None], pats, opts)
3628 items = list(repo.walk(m))
3560 items = list(repo.walk(m))
3629 if not items:
3561 if not items:
3630 return
3562 return
3631 f = lambda fn: fn
3563 f = lambda fn: fn
3632 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
3564 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
3633 f = lambda fn: util.normpath(fn)
3565 f = lambda fn: util.normpath(fn)
3634 fmt = 'f %%-%ds %%-%ds %%s' % (
3566 fmt = 'f %%-%ds %%-%ds %%s' % (
3635 max([len(abs) for abs in items]),
3567 max([len(abs) for abs in items]),
3636 max([len(m.rel(abs)) for abs in items]))
3568 max([len(m.rel(abs)) for abs in items]))
3637 for abs in items:
3569 for abs in items:
3638 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3570 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3639 ui.write("%s\n" % line.rstrip())
3571 ui.write("%s\n" % line.rstrip())
3640
3572
3641 @command('debugwireargs',
3573 @command('debugwireargs',
3642 [('', 'three', '', 'three'),
3574 [('', 'three', '', 'three'),
3643 ('', 'four', '', 'four'),
3575 ('', 'four', '', 'four'),
3644 ('', 'five', '', 'five'),
3576 ('', 'five', '', 'five'),
3645 ] + remoteopts,
3577 ] + remoteopts,
3646 _('REPO [OPTIONS]... [ONE [TWO]]'),
3578 _('REPO [OPTIONS]... [ONE [TWO]]'),
3647 norepo=True)
3579 norepo=True)
3648 def debugwireargs(ui, repopath, *vals, **opts):
3580 def debugwireargs(ui, repopath, *vals, **opts):
3649 repo = hg.peer(ui, opts, repopath)
3581 repo = hg.peer(ui, opts, repopath)
3650 for opt in remoteopts:
3582 for opt in remoteopts:
3651 del opts[opt[1]]
3583 del opts[opt[1]]
3652 args = {}
3584 args = {}
3653 for k, v in opts.iteritems():
3585 for k, v in opts.iteritems():
3654 if v:
3586 if v:
3655 args[k] = v
3587 args[k] = v
3656 # run twice to check that we don't mess up the stream for the next command
3588 # run twice to check that we don't mess up the stream for the next command
3657 res1 = repo.debugwireargs(*vals, **args)
3589 res1 = repo.debugwireargs(*vals, **args)
3658 res2 = repo.debugwireargs(*vals, **args)
3590 res2 = repo.debugwireargs(*vals, **args)
3659 ui.write("%s\n" % res1)
3591 ui.write("%s\n" % res1)
3660 if res1 != res2:
3592 if res1 != res2:
3661 ui.warn("%s\n" % res2)
3593 ui.warn("%s\n" % res2)
3662
3594
3663 @command('^diff',
3595 @command('^diff',
3664 [('r', 'rev', [], _('revision'), _('REV')),
3596 [('r', 'rev', [], _('revision'), _('REV')),
3665 ('c', 'change', '', _('change made by revision'), _('REV'))
3597 ('c', 'change', '', _('change made by revision'), _('REV'))
3666 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3598 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3667 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3599 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3668 inferrepo=True)
3600 inferrepo=True)
3669 def diff(ui, repo, *pats, **opts):
3601 def diff(ui, repo, *pats, **opts):
3670 """diff repository (or selected files)
3602 """diff repository (or selected files)
3671
3603
3672 Show differences between revisions for the specified files.
3604 Show differences between revisions for the specified files.
3673
3605
3674 Differences between files are shown using the unified diff format.
3606 Differences between files are shown using the unified diff format.
3675
3607
3676 .. note::
3608 .. note::
3677
3609
3678 :hg:`diff` may generate unexpected results for merges, as it will
3610 :hg:`diff` may generate unexpected results for merges, as it will
3679 default to comparing against the working directory's first
3611 default to comparing against the working directory's first
3680 parent changeset if no revisions are specified.
3612 parent changeset if no revisions are specified.
3681
3613
3682 When two revision arguments are given, then changes are shown
3614 When two revision arguments are given, then changes are shown
3683 between those revisions. If only one revision is specified then
3615 between those revisions. If only one revision is specified then
3684 that revision is compared to the working directory, and, when no
3616 that revision is compared to the working directory, and, when no
3685 revisions are specified, the working directory files are compared
3617 revisions are specified, the working directory files are compared
3686 to its first parent.
3618 to its first parent.
3687
3619
3688 Alternatively you can specify -c/--change with a revision to see
3620 Alternatively you can specify -c/--change with a revision to see
3689 the changes in that changeset relative to its first parent.
3621 the changes in that changeset relative to its first parent.
3690
3622
3691 Without the -a/--text option, diff will avoid generating diffs of
3623 Without the -a/--text option, diff will avoid generating diffs of
3692 files it detects as binary. With -a, diff will generate a diff
3624 files it detects as binary. With -a, diff will generate a diff
3693 anyway, probably with undesirable results.
3625 anyway, probably with undesirable results.
3694
3626
3695 Use the -g/--git option to generate diffs in the git extended diff
3627 Use the -g/--git option to generate diffs in the git extended diff
3696 format. For more information, read :hg:`help diffs`.
3628 format. For more information, read :hg:`help diffs`.
3697
3629
3698 .. container:: verbose
3630 .. container:: verbose
3699
3631
3700 Examples:
3632 Examples:
3701
3633
3702 - compare a file in the current working directory to its parent::
3634 - compare a file in the current working directory to its parent::
3703
3635
3704 hg diff foo.c
3636 hg diff foo.c
3705
3637
3706 - compare two historical versions of a directory, with rename info::
3638 - compare two historical versions of a directory, with rename info::
3707
3639
3708 hg diff --git -r 1.0:1.2 lib/
3640 hg diff --git -r 1.0:1.2 lib/
3709
3641
3710 - get change stats relative to the last change on some date::
3642 - get change stats relative to the last change on some date::
3711
3643
3712 hg diff --stat -r "date('may 2')"
3644 hg diff --stat -r "date('may 2')"
3713
3645
3714 - diff all newly-added files that contain a keyword::
3646 - diff all newly-added files that contain a keyword::
3715
3647
3716 hg diff "set:added() and grep(GNU)"
3648 hg diff "set:added() and grep(GNU)"
3717
3649
3718 - compare a revision and its parents::
3650 - compare a revision and its parents::
3719
3651
3720 hg diff -c 9353 # compare against first parent
3652 hg diff -c 9353 # compare against first parent
3721 hg diff -r 9353^:9353 # same using revset syntax
3653 hg diff -r 9353^:9353 # same using revset syntax
3722 hg diff -r 9353^2:9353 # compare against the second parent
3654 hg diff -r 9353^2:9353 # compare against the second parent
3723
3655
3724 Returns 0 on success.
3656 Returns 0 on success.
3725 """
3657 """
3726
3658
3727 revs = opts.get('rev')
3659 revs = opts.get('rev')
3728 change = opts.get('change')
3660 change = opts.get('change')
3729 stat = opts.get('stat')
3661 stat = opts.get('stat')
3730 reverse = opts.get('reverse')
3662 reverse = opts.get('reverse')
3731
3663
3732 if revs and change:
3664 if revs and change:
3733 msg = _('cannot specify --rev and --change at the same time')
3665 msg = _('cannot specify --rev and --change at the same time')
3734 raise error.Abort(msg)
3666 raise error.Abort(msg)
3735 elif change:
3667 elif change:
3736 node2 = scmutil.revsingle(repo, change, None).node()
3668 node2 = scmutil.revsingle(repo, change, None).node()
3737 node1 = repo[node2].p1().node()
3669 node1 = repo[node2].p1().node()
3738 else:
3670 else:
3739 node1, node2 = scmutil.revpair(repo, revs)
3671 node1, node2 = scmutil.revpair(repo, revs)
3740
3672
3741 if reverse:
3673 if reverse:
3742 node1, node2 = node2, node1
3674 node1, node2 = node2, node1
3743
3675
3744 diffopts = patch.diffallopts(ui, opts)
3676 diffopts = patch.diffallopts(ui, opts)
3745 m = scmutil.match(repo[node2], pats, opts)
3677 m = scmutil.match(repo[node2], pats, opts)
3746 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3678 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3747 listsubrepos=opts.get('subrepos'),
3679 listsubrepos=opts.get('subrepos'),
3748 root=opts.get('root'))
3680 root=opts.get('root'))
3749
3681
3750 @command('^export',
3682 @command('^export',
3751 [('o', 'output', '',
3683 [('o', 'output', '',
3752 _('print output to file with formatted name'), _('FORMAT')),
3684 _('print output to file with formatted name'), _('FORMAT')),
3753 ('', 'switch-parent', None, _('diff against the second parent')),
3685 ('', 'switch-parent', None, _('diff against the second parent')),
3754 ('r', 'rev', [], _('revisions to export'), _('REV')),
3686 ('r', 'rev', [], _('revisions to export'), _('REV')),
3755 ] + diffopts,
3687 ] + diffopts,
3756 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3688 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3757 def export(ui, repo, *changesets, **opts):
3689 def export(ui, repo, *changesets, **opts):
3758 """dump the header and diffs for one or more changesets
3690 """dump the header and diffs for one or more changesets
3759
3691
3760 Print the changeset header and diffs for one or more revisions.
3692 Print the changeset header and diffs for one or more revisions.
3761 If no revision is given, the parent of the working directory is used.
3693 If no revision is given, the parent of the working directory is used.
3762
3694
3763 The information shown in the changeset header is: author, date,
3695 The information shown in the changeset header is: author, date,
3764 branch name (if non-default), changeset hash, parent(s) and commit
3696 branch name (if non-default), changeset hash, parent(s) and commit
3765 comment.
3697 comment.
3766
3698
3767 .. note::
3699 .. note::
3768
3700
3769 :hg:`export` may generate unexpected diff output for merge
3701 :hg:`export` may generate unexpected diff output for merge
3770 changesets, as it will compare the merge changeset against its
3702 changesets, as it will compare the merge changeset against its
3771 first parent only.
3703 first parent only.
3772
3704
3773 Output may be to a file, in which case the name of the file is
3705 Output may be to a file, in which case the name of the file is
3774 given using a format string. The formatting rules are as follows:
3706 given using a format string. The formatting rules are as follows:
3775
3707
3776 :``%%``: literal "%" character
3708 :``%%``: literal "%" character
3777 :``%H``: changeset hash (40 hexadecimal digits)
3709 :``%H``: changeset hash (40 hexadecimal digits)
3778 :``%N``: number of patches being generated
3710 :``%N``: number of patches being generated
3779 :``%R``: changeset revision number
3711 :``%R``: changeset revision number
3780 :``%b``: basename of the exporting repository
3712 :``%b``: basename of the exporting repository
3781 :``%h``: short-form changeset hash (12 hexadecimal digits)
3713 :``%h``: short-form changeset hash (12 hexadecimal digits)
3782 :``%m``: first line of the commit message (only alphanumeric characters)
3714 :``%m``: first line of the commit message (only alphanumeric characters)
3783 :``%n``: zero-padded sequence number, starting at 1
3715 :``%n``: zero-padded sequence number, starting at 1
3784 :``%r``: zero-padded changeset revision number
3716 :``%r``: zero-padded changeset revision number
3785
3717
3786 Without the -a/--text option, export will avoid generating diffs
3718 Without the -a/--text option, export will avoid generating diffs
3787 of files it detects as binary. With -a, export will generate a
3719 of files it detects as binary. With -a, export will generate a
3788 diff anyway, probably with undesirable results.
3720 diff anyway, probably with undesirable results.
3789
3721
3790 Use the -g/--git option to generate diffs in the git extended diff
3722 Use the -g/--git option to generate diffs in the git extended diff
3791 format. See :hg:`help diffs` for more information.
3723 format. See :hg:`help diffs` for more information.
3792
3724
3793 With the --switch-parent option, the diff will be against the
3725 With the --switch-parent option, the diff will be against the
3794 second parent. It can be useful to review a merge.
3726 second parent. It can be useful to review a merge.
3795
3727
3796 .. container:: verbose
3728 .. container:: verbose
3797
3729
3798 Examples:
3730 Examples:
3799
3731
3800 - use export and import to transplant a bugfix to the current
3732 - use export and import to transplant a bugfix to the current
3801 branch::
3733 branch::
3802
3734
3803 hg export -r 9353 | hg import -
3735 hg export -r 9353 | hg import -
3804
3736
3805 - export all the changesets between two revisions to a file with
3737 - export all the changesets between two revisions to a file with
3806 rename information::
3738 rename information::
3807
3739
3808 hg export --git -r 123:150 > changes.txt
3740 hg export --git -r 123:150 > changes.txt
3809
3741
3810 - split outgoing changes into a series of patches with
3742 - split outgoing changes into a series of patches with
3811 descriptive names::
3743 descriptive names::
3812
3744
3813 hg export -r "outgoing()" -o "%n-%m.patch"
3745 hg export -r "outgoing()" -o "%n-%m.patch"
3814
3746
3815 Returns 0 on success.
3747 Returns 0 on success.
3816 """
3748 """
3817 changesets += tuple(opts.get('rev', []))
3749 changesets += tuple(opts.get('rev', []))
3818 if not changesets:
3750 if not changesets:
3819 changesets = ['.']
3751 changesets = ['.']
3820 revs = scmutil.revrange(repo, changesets)
3752 revs = scmutil.revrange(repo, changesets)
3821 if not revs:
3753 if not revs:
3822 raise error.Abort(_("export requires at least one changeset"))
3754 raise error.Abort(_("export requires at least one changeset"))
3823 if len(revs) > 1:
3755 if len(revs) > 1:
3824 ui.note(_('exporting patches:\n'))
3756 ui.note(_('exporting patches:\n'))
3825 else:
3757 else:
3826 ui.note(_('exporting patch:\n'))
3758 ui.note(_('exporting patch:\n'))
3827 cmdutil.export(repo, revs, template=opts.get('output'),
3759 cmdutil.export(repo, revs, template=opts.get('output'),
3828 switch_parent=opts.get('switch_parent'),
3760 switch_parent=opts.get('switch_parent'),
3829 opts=patch.diffallopts(ui, opts))
3761 opts=patch.diffallopts(ui, opts))
3830
3762
3831 @command('files',
3763 @command('files',
3832 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3764 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3833 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3765 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3834 ] + walkopts + formatteropts + subrepoopts,
3766 ] + walkopts + formatteropts + subrepoopts,
3835 _('[OPTION]... [FILE]...'))
3767 _('[OPTION]... [FILE]...'))
3836 def files(ui, repo, *pats, **opts):
3768 def files(ui, repo, *pats, **opts):
3837 """list tracked files
3769 """list tracked files
3838
3770
3839 Print files under Mercurial control in the working directory or
3771 Print files under Mercurial control in the working directory or
3840 specified revision for given files (excluding removed files).
3772 specified revision for given files (excluding removed files).
3841 Files can be specified as filenames or filesets.
3773 Files can be specified as filenames or filesets.
3842
3774
3843 If no files are given to match, this command prints the names
3775 If no files are given to match, this command prints the names
3844 of all files under Mercurial control.
3776 of all files under Mercurial control.
3845
3777
3846 .. container:: verbose
3778 .. container:: verbose
3847
3779
3848 Examples:
3780 Examples:
3849
3781
3850 - list all files under the current directory::
3782 - list all files under the current directory::
3851
3783
3852 hg files .
3784 hg files .
3853
3785
3854 - shows sizes and flags for current revision::
3786 - shows sizes and flags for current revision::
3855
3787
3856 hg files -vr .
3788 hg files -vr .
3857
3789
3858 - list all files named README::
3790 - list all files named README::
3859
3791
3860 hg files -I "**/README"
3792 hg files -I "**/README"
3861
3793
3862 - list all binary files::
3794 - list all binary files::
3863
3795
3864 hg files "set:binary()"
3796 hg files "set:binary()"
3865
3797
3866 - find files containing a regular expression::
3798 - find files containing a regular expression::
3867
3799
3868 hg files "set:grep('bob')"
3800 hg files "set:grep('bob')"
3869
3801
3870 - search tracked file contents with xargs and grep::
3802 - search tracked file contents with xargs and grep::
3871
3803
3872 hg files -0 | xargs -0 grep foo
3804 hg files -0 | xargs -0 grep foo
3873
3805
3874 See :hg:`help patterns` and :hg:`help filesets` for more information
3806 See :hg:`help patterns` and :hg:`help filesets` for more information
3875 on specifying file patterns.
3807 on specifying file patterns.
3876
3808
3877 Returns 0 if a match is found, 1 otherwise.
3809 Returns 0 if a match is found, 1 otherwise.
3878
3810
3879 """
3811 """
3880 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3812 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3881
3813
3882 end = '\n'
3814 end = '\n'
3883 if opts.get('print0'):
3815 if opts.get('print0'):
3884 end = '\0'
3816 end = '\0'
3885 fmt = '%s' + end
3817 fmt = '%s' + end
3886
3818
3887 m = scmutil.match(ctx, pats, opts)
3819 m = scmutil.match(ctx, pats, opts)
3888 with ui.formatter('files', opts) as fm:
3820 with ui.formatter('files', opts) as fm:
3889 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3821 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3890
3822
3891 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3823 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3892 def forget(ui, repo, *pats, **opts):
3824 def forget(ui, repo, *pats, **opts):
3893 """forget the specified files on the next commit
3825 """forget the specified files on the next commit
3894
3826
3895 Mark the specified files so they will no longer be tracked
3827 Mark the specified files so they will no longer be tracked
3896 after the next commit.
3828 after the next commit.
3897
3829
3898 This only removes files from the current branch, not from the
3830 This only removes files from the current branch, not from the
3899 entire project history, and it does not delete them from the
3831 entire project history, and it does not delete them from the
3900 working directory.
3832 working directory.
3901
3833
3902 To delete the file from the working directory, see :hg:`remove`.
3834 To delete the file from the working directory, see :hg:`remove`.
3903
3835
3904 To undo a forget before the next commit, see :hg:`add`.
3836 To undo a forget before the next commit, see :hg:`add`.
3905
3837
3906 .. container:: verbose
3838 .. container:: verbose
3907
3839
3908 Examples:
3840 Examples:
3909
3841
3910 - forget newly-added binary files::
3842 - forget newly-added binary files::
3911
3843
3912 hg forget "set:added() and binary()"
3844 hg forget "set:added() and binary()"
3913
3845
3914 - forget files that would be excluded by .hgignore::
3846 - forget files that would be excluded by .hgignore::
3915
3847
3916 hg forget "set:hgignore()"
3848 hg forget "set:hgignore()"
3917
3849
3918 Returns 0 on success.
3850 Returns 0 on success.
3919 """
3851 """
3920
3852
3921 if not pats:
3853 if not pats:
3922 raise error.Abort(_('no files specified'))
3854 raise error.Abort(_('no files specified'))
3923
3855
3924 m = scmutil.match(repo[None], pats, opts)
3856 m = scmutil.match(repo[None], pats, opts)
3925 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3857 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3926 return rejected and 1 or 0
3858 return rejected and 1 or 0
3927
3859
3928 @command(
3860 @command(
3929 'graft',
3861 'graft',
3930 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3862 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3931 ('c', 'continue', False, _('resume interrupted graft')),
3863 ('c', 'continue', False, _('resume interrupted graft')),
3932 ('e', 'edit', False, _('invoke editor on commit messages')),
3864 ('e', 'edit', False, _('invoke editor on commit messages')),
3933 ('', 'log', None, _('append graft info to log message')),
3865 ('', 'log', None, _('append graft info to log message')),
3934 ('f', 'force', False, _('force graft')),
3866 ('f', 'force', False, _('force graft')),
3935 ('D', 'currentdate', False,
3867 ('D', 'currentdate', False,
3936 _('record the current date as commit date')),
3868 _('record the current date as commit date')),
3937 ('U', 'currentuser', False,
3869 ('U', 'currentuser', False,
3938 _('record the current user as committer'), _('DATE'))]
3870 _('record the current user as committer'), _('DATE'))]
3939 + commitopts2 + mergetoolopts + dryrunopts,
3871 + commitopts2 + mergetoolopts + dryrunopts,
3940 _('[OPTION]... [-r REV]... REV...'))
3872 _('[OPTION]... [-r REV]... REV...'))
3941 def graft(ui, repo, *revs, **opts):
3873 def graft(ui, repo, *revs, **opts):
3942 '''copy changes from other branches onto the current branch
3874 '''copy changes from other branches onto the current branch
3943
3875
3944 This command uses Mercurial's merge logic to copy individual
3876 This command uses Mercurial's merge logic to copy individual
3945 changes from other branches without merging branches in the
3877 changes from other branches without merging branches in the
3946 history graph. This is sometimes known as 'backporting' or
3878 history graph. This is sometimes known as 'backporting' or
3947 'cherry-picking'. By default, graft will copy user, date, and
3879 'cherry-picking'. By default, graft will copy user, date, and
3948 description from the source changesets.
3880 description from the source changesets.
3949
3881
3950 Changesets that are ancestors of the current revision, that have
3882 Changesets that are ancestors of the current revision, that have
3951 already been grafted, or that are merges will be skipped.
3883 already been grafted, or that are merges will be skipped.
3952
3884
3953 If --log is specified, log messages will have a comment appended
3885 If --log is specified, log messages will have a comment appended
3954 of the form::
3886 of the form::
3955
3887
3956 (grafted from CHANGESETHASH)
3888 (grafted from CHANGESETHASH)
3957
3889
3958 If --force is specified, revisions will be grafted even if they
3890 If --force is specified, revisions will be grafted even if they
3959 are already ancestors of or have been grafted to the destination.
3891 are already ancestors of or have been grafted to the destination.
3960 This is useful when the revisions have since been backed out.
3892 This is useful when the revisions have since been backed out.
3961
3893
3962 If a graft merge results in conflicts, the graft process is
3894 If a graft merge results in conflicts, the graft process is
3963 interrupted so that the current merge can be manually resolved.
3895 interrupted so that the current merge can be manually resolved.
3964 Once all conflicts are addressed, the graft process can be
3896 Once all conflicts are addressed, the graft process can be
3965 continued with the -c/--continue option.
3897 continued with the -c/--continue option.
3966
3898
3967 .. note::
3899 .. note::
3968
3900
3969 The -c/--continue option does not reapply earlier options, except
3901 The -c/--continue option does not reapply earlier options, except
3970 for --force.
3902 for --force.
3971
3903
3972 .. container:: verbose
3904 .. container:: verbose
3973
3905
3974 Examples:
3906 Examples:
3975
3907
3976 - copy a single change to the stable branch and edit its description::
3908 - copy a single change to the stable branch and edit its description::
3977
3909
3978 hg update stable
3910 hg update stable
3979 hg graft --edit 9393
3911 hg graft --edit 9393
3980
3912
3981 - graft a range of changesets with one exception, updating dates::
3913 - graft a range of changesets with one exception, updating dates::
3982
3914
3983 hg graft -D "2085::2093 and not 2091"
3915 hg graft -D "2085::2093 and not 2091"
3984
3916
3985 - continue a graft after resolving conflicts::
3917 - continue a graft after resolving conflicts::
3986
3918
3987 hg graft -c
3919 hg graft -c
3988
3920
3989 - show the source of a grafted changeset::
3921 - show the source of a grafted changeset::
3990
3922
3991 hg log --debug -r .
3923 hg log --debug -r .
3992
3924
3993 - show revisions sorted by date::
3925 - show revisions sorted by date::
3994
3926
3995 hg log -r "sort(all(), date)"
3927 hg log -r "sort(all(), date)"
3996
3928
3997 See :hg:`help revisions` and :hg:`help revsets` for more about
3929 See :hg:`help revisions` and :hg:`help revsets` for more about
3998 specifying revisions.
3930 specifying revisions.
3999
3931
4000 Returns 0 on successful completion.
3932 Returns 0 on successful completion.
4001 '''
3933 '''
4002 with repo.wlock():
3934 with repo.wlock():
4003 return _dograft(ui, repo, *revs, **opts)
3935 return _dograft(ui, repo, *revs, **opts)
4004
3936
4005 def _dograft(ui, repo, *revs, **opts):
3937 def _dograft(ui, repo, *revs, **opts):
4006 if revs and opts.get('rev'):
3938 if revs and opts.get('rev'):
4007 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3939 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
4008 'revision ordering!\n'))
3940 'revision ordering!\n'))
4009
3941
4010 revs = list(revs)
3942 revs = list(revs)
4011 revs.extend(opts.get('rev'))
3943 revs.extend(opts.get('rev'))
4012
3944
4013 if not opts.get('user') and opts.get('currentuser'):
3945 if not opts.get('user') and opts.get('currentuser'):
4014 opts['user'] = ui.username()
3946 opts['user'] = ui.username()
4015 if not opts.get('date') and opts.get('currentdate'):
3947 if not opts.get('date') and opts.get('currentdate'):
4016 opts['date'] = "%d %d" % util.makedate()
3948 opts['date'] = "%d %d" % util.makedate()
4017
3949
4018 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3950 editor = cmdutil.getcommiteditor(editform='graft', **opts)
4019
3951
4020 cont = False
3952 cont = False
4021 if opts.get('continue'):
3953 if opts.get('continue'):
4022 cont = True
3954 cont = True
4023 if revs:
3955 if revs:
4024 raise error.Abort(_("can't specify --continue and revisions"))
3956 raise error.Abort(_("can't specify --continue and revisions"))
4025 # read in unfinished revisions
3957 # read in unfinished revisions
4026 try:
3958 try:
4027 nodes = repo.vfs.read('graftstate').splitlines()
3959 nodes = repo.vfs.read('graftstate').splitlines()
4028 revs = [repo[node].rev() for node in nodes]
3960 revs = [repo[node].rev() for node in nodes]
4029 except IOError as inst:
3961 except IOError as inst:
4030 if inst.errno != errno.ENOENT:
3962 if inst.errno != errno.ENOENT:
4031 raise
3963 raise
4032 cmdutil.wrongtooltocontinue(repo, _('graft'))
3964 cmdutil.wrongtooltocontinue(repo, _('graft'))
4033 else:
3965 else:
4034 cmdutil.checkunfinished(repo)
3966 cmdutil.checkunfinished(repo)
4035 cmdutil.bailifchanged(repo)
3967 cmdutil.bailifchanged(repo)
4036 if not revs:
3968 if not revs:
4037 raise error.Abort(_('no revisions specified'))
3969 raise error.Abort(_('no revisions specified'))
4038 revs = scmutil.revrange(repo, revs)
3970 revs = scmutil.revrange(repo, revs)
4039
3971
4040 skipped = set()
3972 skipped = set()
4041 # check for merges
3973 # check for merges
4042 for rev in repo.revs('%ld and merge()', revs):
3974 for rev in repo.revs('%ld and merge()', revs):
4043 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3975 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
4044 skipped.add(rev)
3976 skipped.add(rev)
4045 revs = [r for r in revs if r not in skipped]
3977 revs = [r for r in revs if r not in skipped]
4046 if not revs:
3978 if not revs:
4047 return -1
3979 return -1
4048
3980
4049 # Don't check in the --continue case, in effect retaining --force across
3981 # Don't check in the --continue case, in effect retaining --force across
4050 # --continues. That's because without --force, any revisions we decided to
3982 # --continues. That's because without --force, any revisions we decided to
4051 # skip would have been filtered out here, so they wouldn't have made their
3983 # skip would have been filtered out here, so they wouldn't have made their
4052 # way to the graftstate. With --force, any revisions we would have otherwise
3984 # way to the graftstate. With --force, any revisions we would have otherwise
4053 # skipped would not have been filtered out, and if they hadn't been applied
3985 # skipped would not have been filtered out, and if they hadn't been applied
4054 # already, they'd have been in the graftstate.
3986 # already, they'd have been in the graftstate.
4055 if not (cont or opts.get('force')):
3987 if not (cont or opts.get('force')):
4056 # check for ancestors of dest branch
3988 # check for ancestors of dest branch
4057 crev = repo['.'].rev()
3989 crev = repo['.'].rev()
4058 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3990 ancestors = repo.changelog.ancestors([crev], inclusive=True)
4059 # XXX make this lazy in the future
3991 # XXX make this lazy in the future
4060 # don't mutate while iterating, create a copy
3992 # don't mutate while iterating, create a copy
4061 for rev in list(revs):
3993 for rev in list(revs):
4062 if rev in ancestors:
3994 if rev in ancestors:
4063 ui.warn(_('skipping ancestor revision %d:%s\n') %
3995 ui.warn(_('skipping ancestor revision %d:%s\n') %
4064 (rev, repo[rev]))
3996 (rev, repo[rev]))
4065 # XXX remove on list is slow
3997 # XXX remove on list is slow
4066 revs.remove(rev)
3998 revs.remove(rev)
4067 if not revs:
3999 if not revs:
4068 return -1
4000 return -1
4069
4001
4070 # analyze revs for earlier grafts
4002 # analyze revs for earlier grafts
4071 ids = {}
4003 ids = {}
4072 for ctx in repo.set("%ld", revs):
4004 for ctx in repo.set("%ld", revs):
4073 ids[ctx.hex()] = ctx.rev()
4005 ids[ctx.hex()] = ctx.rev()
4074 n = ctx.extra().get('source')
4006 n = ctx.extra().get('source')
4075 if n:
4007 if n:
4076 ids[n] = ctx.rev()
4008 ids[n] = ctx.rev()
4077
4009
4078 # check ancestors for earlier grafts
4010 # check ancestors for earlier grafts
4079 ui.debug('scanning for duplicate grafts\n')
4011 ui.debug('scanning for duplicate grafts\n')
4080
4012
4081 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4013 for rev in repo.changelog.findmissingrevs(revs, [crev]):
4082 ctx = repo[rev]
4014 ctx = repo[rev]
4083 n = ctx.extra().get('source')
4015 n = ctx.extra().get('source')
4084 if n in ids:
4016 if n in ids:
4085 try:
4017 try:
4086 r = repo[n].rev()
4018 r = repo[n].rev()
4087 except error.RepoLookupError:
4019 except error.RepoLookupError:
4088 r = None
4020 r = None
4089 if r in revs:
4021 if r in revs:
4090 ui.warn(_('skipping revision %d:%s '
4022 ui.warn(_('skipping revision %d:%s '
4091 '(already grafted to %d:%s)\n')
4023 '(already grafted to %d:%s)\n')
4092 % (r, repo[r], rev, ctx))
4024 % (r, repo[r], rev, ctx))
4093 revs.remove(r)
4025 revs.remove(r)
4094 elif ids[n] in revs:
4026 elif ids[n] in revs:
4095 if r is None:
4027 if r is None:
4096 ui.warn(_('skipping already grafted revision %d:%s '
4028 ui.warn(_('skipping already grafted revision %d:%s '
4097 '(%d:%s also has unknown origin %s)\n')
4029 '(%d:%s also has unknown origin %s)\n')
4098 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4030 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
4099 else:
4031 else:
4100 ui.warn(_('skipping already grafted revision %d:%s '
4032 ui.warn(_('skipping already grafted revision %d:%s '
4101 '(%d:%s also has origin %d:%s)\n')
4033 '(%d:%s also has origin %d:%s)\n')
4102 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4034 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
4103 revs.remove(ids[n])
4035 revs.remove(ids[n])
4104 elif ctx.hex() in ids:
4036 elif ctx.hex() in ids:
4105 r = ids[ctx.hex()]
4037 r = ids[ctx.hex()]
4106 ui.warn(_('skipping already grafted revision %d:%s '
4038 ui.warn(_('skipping already grafted revision %d:%s '
4107 '(was grafted from %d:%s)\n') %
4039 '(was grafted from %d:%s)\n') %
4108 (r, repo[r], rev, ctx))
4040 (r, repo[r], rev, ctx))
4109 revs.remove(r)
4041 revs.remove(r)
4110 if not revs:
4042 if not revs:
4111 return -1
4043 return -1
4112
4044
4113 for pos, ctx in enumerate(repo.set("%ld", revs)):
4045 for pos, ctx in enumerate(repo.set("%ld", revs)):
4114 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4046 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4115 ctx.description().split('\n', 1)[0])
4047 ctx.description().split('\n', 1)[0])
4116 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4048 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4117 if names:
4049 if names:
4118 desc += ' (%s)' % ' '.join(names)
4050 desc += ' (%s)' % ' '.join(names)
4119 ui.status(_('grafting %s\n') % desc)
4051 ui.status(_('grafting %s\n') % desc)
4120 if opts.get('dry_run'):
4052 if opts.get('dry_run'):
4121 continue
4053 continue
4122
4054
4123 source = ctx.extra().get('source')
4055 source = ctx.extra().get('source')
4124 extra = {}
4056 extra = {}
4125 if source:
4057 if source:
4126 extra['source'] = source
4058 extra['source'] = source
4127 extra['intermediate-source'] = ctx.hex()
4059 extra['intermediate-source'] = ctx.hex()
4128 else:
4060 else:
4129 extra['source'] = ctx.hex()
4061 extra['source'] = ctx.hex()
4130 user = ctx.user()
4062 user = ctx.user()
4131 if opts.get('user'):
4063 if opts.get('user'):
4132 user = opts['user']
4064 user = opts['user']
4133 date = ctx.date()
4065 date = ctx.date()
4134 if opts.get('date'):
4066 if opts.get('date'):
4135 date = opts['date']
4067 date = opts['date']
4136 message = ctx.description()
4068 message = ctx.description()
4137 if opts.get('log'):
4069 if opts.get('log'):
4138 message += '\n(grafted from %s)' % ctx.hex()
4070 message += '\n(grafted from %s)' % ctx.hex()
4139
4071
4140 # we don't merge the first commit when continuing
4072 # we don't merge the first commit when continuing
4141 if not cont:
4073 if not cont:
4142 # perform the graft merge with p1(rev) as 'ancestor'
4074 # perform the graft merge with p1(rev) as 'ancestor'
4143 try:
4075 try:
4144 # ui.forcemerge is an internal variable, do not document
4076 # ui.forcemerge is an internal variable, do not document
4145 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4077 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4146 'graft')
4078 'graft')
4147 stats = mergemod.graft(repo, ctx, ctx.p1(),
4079 stats = mergemod.graft(repo, ctx, ctx.p1(),
4148 ['local', 'graft'])
4080 ['local', 'graft'])
4149 finally:
4081 finally:
4150 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4082 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4151 # report any conflicts
4083 # report any conflicts
4152 if stats and stats[3] > 0:
4084 if stats and stats[3] > 0:
4153 # write out state for --continue
4085 # write out state for --continue
4154 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4086 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4155 repo.vfs.write('graftstate', ''.join(nodelines))
4087 repo.vfs.write('graftstate', ''.join(nodelines))
4156 extra = ''
4088 extra = ''
4157 if opts.get('user'):
4089 if opts.get('user'):
4158 extra += ' --user %s' % util.shellquote(opts['user'])
4090 extra += ' --user %s' % util.shellquote(opts['user'])
4159 if opts.get('date'):
4091 if opts.get('date'):
4160 extra += ' --date %s' % util.shellquote(opts['date'])
4092 extra += ' --date %s' % util.shellquote(opts['date'])
4161 if opts.get('log'):
4093 if opts.get('log'):
4162 extra += ' --log'
4094 extra += ' --log'
4163 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4095 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4164 raise error.Abort(
4096 raise error.Abort(
4165 _("unresolved conflicts, can't continue"),
4097 _("unresolved conflicts, can't continue"),
4166 hint=hint)
4098 hint=hint)
4167 else:
4099 else:
4168 cont = False
4100 cont = False
4169
4101
4170 # commit
4102 # commit
4171 node = repo.commit(text=message, user=user,
4103 node = repo.commit(text=message, user=user,
4172 date=date, extra=extra, editor=editor)
4104 date=date, extra=extra, editor=editor)
4173 if node is None:
4105 if node is None:
4174 ui.warn(
4106 ui.warn(
4175 _('note: graft of %d:%s created no changes to commit\n') %
4107 _('note: graft of %d:%s created no changes to commit\n') %
4176 (ctx.rev(), ctx))
4108 (ctx.rev(), ctx))
4177
4109
4178 # remove state when we complete successfully
4110 # remove state when we complete successfully
4179 if not opts.get('dry_run'):
4111 if not opts.get('dry_run'):
4180 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4112 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4181
4113
4182 return 0
4114 return 0
4183
4115
4184 @command('grep',
4116 @command('grep',
4185 [('0', 'print0', None, _('end fields with NUL')),
4117 [('0', 'print0', None, _('end fields with NUL')),
4186 ('', 'all', None, _('print all revisions that match')),
4118 ('', 'all', None, _('print all revisions that match')),
4187 ('a', 'text', None, _('treat all files as text')),
4119 ('a', 'text', None, _('treat all files as text')),
4188 ('f', 'follow', None,
4120 ('f', 'follow', None,
4189 _('follow changeset history,'
4121 _('follow changeset history,'
4190 ' or file history across copies and renames')),
4122 ' or file history across copies and renames')),
4191 ('i', 'ignore-case', None, _('ignore case when matching')),
4123 ('i', 'ignore-case', None, _('ignore case when matching')),
4192 ('l', 'files-with-matches', None,
4124 ('l', 'files-with-matches', None,
4193 _('print only filenames and revisions that match')),
4125 _('print only filenames and revisions that match')),
4194 ('n', 'line-number', None, _('print matching line numbers')),
4126 ('n', 'line-number', None, _('print matching line numbers')),
4195 ('r', 'rev', [],
4127 ('r', 'rev', [],
4196 _('only search files changed within revision range'), _('REV')),
4128 _('only search files changed within revision range'), _('REV')),
4197 ('u', 'user', None, _('list the author (long with -v)')),
4129 ('u', 'user', None, _('list the author (long with -v)')),
4198 ('d', 'date', None, _('list the date (short with -q)')),
4130 ('d', 'date', None, _('list the date (short with -q)')),
4199 ] + formatteropts + walkopts,
4131 ] + formatteropts + walkopts,
4200 _('[OPTION]... PATTERN [FILE]...'),
4132 _('[OPTION]... PATTERN [FILE]...'),
4201 inferrepo=True)
4133 inferrepo=True)
4202 def grep(ui, repo, pattern, *pats, **opts):
4134 def grep(ui, repo, pattern, *pats, **opts):
4203 """search revision history for a pattern in specified files
4135 """search revision history for a pattern in specified files
4204
4136
4205 Search revision history for a regular expression in the specified
4137 Search revision history for a regular expression in the specified
4206 files or the entire project.
4138 files or the entire project.
4207
4139
4208 By default, grep prints the most recent revision number for each
4140 By default, grep prints the most recent revision number for each
4209 file in which it finds a match. To get it to print every revision
4141 file in which it finds a match. To get it to print every revision
4210 that contains a change in match status ("-" for a match that becomes
4142 that contains a change in match status ("-" for a match that becomes
4211 a non-match, or "+" for a non-match that becomes a match), use the
4143 a non-match, or "+" for a non-match that becomes a match), use the
4212 --all flag.
4144 --all flag.
4213
4145
4214 PATTERN can be any Python (roughly Perl-compatible) regular
4146 PATTERN can be any Python (roughly Perl-compatible) regular
4215 expression.
4147 expression.
4216
4148
4217 If no FILEs are specified (and -f/--follow isn't set), all files in
4149 If no FILEs are specified (and -f/--follow isn't set), all files in
4218 the repository are searched, including those that don't exist in the
4150 the repository are searched, including those that don't exist in the
4219 current branch or have been deleted in a prior changeset.
4151 current branch or have been deleted in a prior changeset.
4220
4152
4221 Returns 0 if a match is found, 1 otherwise.
4153 Returns 0 if a match is found, 1 otherwise.
4222 """
4154 """
4223 reflags = re.M
4155 reflags = re.M
4224 if opts.get('ignore_case'):
4156 if opts.get('ignore_case'):
4225 reflags |= re.I
4157 reflags |= re.I
4226 try:
4158 try:
4227 regexp = util.re.compile(pattern, reflags)
4159 regexp = util.re.compile(pattern, reflags)
4228 except re.error as inst:
4160 except re.error as inst:
4229 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4161 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4230 return 1
4162 return 1
4231 sep, eol = ':', '\n'
4163 sep, eol = ':', '\n'
4232 if opts.get('print0'):
4164 if opts.get('print0'):
4233 sep = eol = '\0'
4165 sep = eol = '\0'
4234
4166
4235 getfile = util.lrucachefunc(repo.file)
4167 getfile = util.lrucachefunc(repo.file)
4236
4168
4237 def matchlines(body):
4169 def matchlines(body):
4238 begin = 0
4170 begin = 0
4239 linenum = 0
4171 linenum = 0
4240 while begin < len(body):
4172 while begin < len(body):
4241 match = regexp.search(body, begin)
4173 match = regexp.search(body, begin)
4242 if not match:
4174 if not match:
4243 break
4175 break
4244 mstart, mend = match.span()
4176 mstart, mend = match.span()
4245 linenum += body.count('\n', begin, mstart) + 1
4177 linenum += body.count('\n', begin, mstart) + 1
4246 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4178 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4247 begin = body.find('\n', mend) + 1 or len(body) + 1
4179 begin = body.find('\n', mend) + 1 or len(body) + 1
4248 lend = begin - 1
4180 lend = begin - 1
4249 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4181 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4250
4182
4251 class linestate(object):
4183 class linestate(object):
4252 def __init__(self, line, linenum, colstart, colend):
4184 def __init__(self, line, linenum, colstart, colend):
4253 self.line = line
4185 self.line = line
4254 self.linenum = linenum
4186 self.linenum = linenum
4255 self.colstart = colstart
4187 self.colstart = colstart
4256 self.colend = colend
4188 self.colend = colend
4257
4189
4258 def __hash__(self):
4190 def __hash__(self):
4259 return hash((self.linenum, self.line))
4191 return hash((self.linenum, self.line))
4260
4192
4261 def __eq__(self, other):
4193 def __eq__(self, other):
4262 return self.line == other.line
4194 return self.line == other.line
4263
4195
4264 def findpos(self):
4196 def findpos(self):
4265 """Iterate all (start, end) indices of matches"""
4197 """Iterate all (start, end) indices of matches"""
4266 yield self.colstart, self.colend
4198 yield self.colstart, self.colend
4267 p = self.colend
4199 p = self.colend
4268 while p < len(self.line):
4200 while p < len(self.line):
4269 m = regexp.search(self.line, p)
4201 m = regexp.search(self.line, p)
4270 if not m:
4202 if not m:
4271 break
4203 break
4272 yield m.span()
4204 yield m.span()
4273 p = m.end()
4205 p = m.end()
4274
4206
4275 matches = {}
4207 matches = {}
4276 copies = {}
4208 copies = {}
4277 def grepbody(fn, rev, body):
4209 def grepbody(fn, rev, body):
4278 matches[rev].setdefault(fn, [])
4210 matches[rev].setdefault(fn, [])
4279 m = matches[rev][fn]
4211 m = matches[rev][fn]
4280 for lnum, cstart, cend, line in matchlines(body):
4212 for lnum, cstart, cend, line in matchlines(body):
4281 s = linestate(line, lnum, cstart, cend)
4213 s = linestate(line, lnum, cstart, cend)
4282 m.append(s)
4214 m.append(s)
4283
4215
4284 def difflinestates(a, b):
4216 def difflinestates(a, b):
4285 sm = difflib.SequenceMatcher(None, a, b)
4217 sm = difflib.SequenceMatcher(None, a, b)
4286 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4218 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4287 if tag == 'insert':
4219 if tag == 'insert':
4288 for i in xrange(blo, bhi):
4220 for i in xrange(blo, bhi):
4289 yield ('+', b[i])
4221 yield ('+', b[i])
4290 elif tag == 'delete':
4222 elif tag == 'delete':
4291 for i in xrange(alo, ahi):
4223 for i in xrange(alo, ahi):
4292 yield ('-', a[i])
4224 yield ('-', a[i])
4293 elif tag == 'replace':
4225 elif tag == 'replace':
4294 for i in xrange(alo, ahi):
4226 for i in xrange(alo, ahi):
4295 yield ('-', a[i])
4227 yield ('-', a[i])
4296 for i in xrange(blo, bhi):
4228 for i in xrange(blo, bhi):
4297 yield ('+', b[i])
4229 yield ('+', b[i])
4298
4230
4299 def display(fm, fn, ctx, pstates, states):
4231 def display(fm, fn, ctx, pstates, states):
4300 rev = ctx.rev()
4232 rev = ctx.rev()
4301 if fm.isplain():
4233 if fm.isplain():
4302 formatuser = ui.shortuser
4234 formatuser = ui.shortuser
4303 else:
4235 else:
4304 formatuser = str
4236 formatuser = str
4305 if ui.quiet:
4237 if ui.quiet:
4306 datefmt = '%Y-%m-%d'
4238 datefmt = '%Y-%m-%d'
4307 else:
4239 else:
4308 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4240 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4309 found = False
4241 found = False
4310 @util.cachefunc
4242 @util.cachefunc
4311 def binary():
4243 def binary():
4312 flog = getfile(fn)
4244 flog = getfile(fn)
4313 return util.binary(flog.read(ctx.filenode(fn)))
4245 return util.binary(flog.read(ctx.filenode(fn)))
4314
4246
4315 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4247 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4316 if opts.get('all'):
4248 if opts.get('all'):
4317 iter = difflinestates(pstates, states)
4249 iter = difflinestates(pstates, states)
4318 else:
4250 else:
4319 iter = [('', l) for l in states]
4251 iter = [('', l) for l in states]
4320 for change, l in iter:
4252 for change, l in iter:
4321 fm.startitem()
4253 fm.startitem()
4322 fm.data(node=fm.hexfunc(ctx.node()))
4254 fm.data(node=fm.hexfunc(ctx.node()))
4323 cols = [
4255 cols = [
4324 ('filename', fn, True),
4256 ('filename', fn, True),
4325 ('rev', rev, True),
4257 ('rev', rev, True),
4326 ('linenumber', l.linenum, opts.get('line_number')),
4258 ('linenumber', l.linenum, opts.get('line_number')),
4327 ]
4259 ]
4328 if opts.get('all'):
4260 if opts.get('all'):
4329 cols.append(('change', change, True))
4261 cols.append(('change', change, True))
4330 cols.extend([
4262 cols.extend([
4331 ('user', formatuser(ctx.user()), opts.get('user')),
4263 ('user', formatuser(ctx.user()), opts.get('user')),
4332 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4264 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4333 ])
4265 ])
4334 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4266 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4335 for name, data, cond in cols:
4267 for name, data, cond in cols:
4336 field = fieldnamemap.get(name, name)
4268 field = fieldnamemap.get(name, name)
4337 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4269 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4338 if cond and name != lastcol:
4270 if cond and name != lastcol:
4339 fm.plain(sep, label='grep.sep')
4271 fm.plain(sep, label='grep.sep')
4340 if not opts.get('files_with_matches'):
4272 if not opts.get('files_with_matches'):
4341 fm.plain(sep, label='grep.sep')
4273 fm.plain(sep, label='grep.sep')
4342 if not opts.get('text') and binary():
4274 if not opts.get('text') and binary():
4343 fm.plain(_(" Binary file matches"))
4275 fm.plain(_(" Binary file matches"))
4344 else:
4276 else:
4345 displaymatches(fm.nested('texts'), l)
4277 displaymatches(fm.nested('texts'), l)
4346 fm.plain(eol)
4278 fm.plain(eol)
4347 found = True
4279 found = True
4348 if opts.get('files_with_matches'):
4280 if opts.get('files_with_matches'):
4349 break
4281 break
4350 return found
4282 return found
4351
4283
4352 def displaymatches(fm, l):
4284 def displaymatches(fm, l):
4353 p = 0
4285 p = 0
4354 for s, e in l.findpos():
4286 for s, e in l.findpos():
4355 if p < s:
4287 if p < s:
4356 fm.startitem()
4288 fm.startitem()
4357 fm.write('text', '%s', l.line[p:s])
4289 fm.write('text', '%s', l.line[p:s])
4358 fm.data(matched=False)
4290 fm.data(matched=False)
4359 fm.startitem()
4291 fm.startitem()
4360 fm.write('text', '%s', l.line[s:e], label='grep.match')
4292 fm.write('text', '%s', l.line[s:e], label='grep.match')
4361 fm.data(matched=True)
4293 fm.data(matched=True)
4362 p = e
4294 p = e
4363 if p < len(l.line):
4295 if p < len(l.line):
4364 fm.startitem()
4296 fm.startitem()
4365 fm.write('text', '%s', l.line[p:])
4297 fm.write('text', '%s', l.line[p:])
4366 fm.data(matched=False)
4298 fm.data(matched=False)
4367 fm.end()
4299 fm.end()
4368
4300
4369 skip = {}
4301 skip = {}
4370 revfiles = {}
4302 revfiles = {}
4371 matchfn = scmutil.match(repo[None], pats, opts)
4303 matchfn = scmutil.match(repo[None], pats, opts)
4372 found = False
4304 found = False
4373 follow = opts.get('follow')
4305 follow = opts.get('follow')
4374
4306
4375 def prep(ctx, fns):
4307 def prep(ctx, fns):
4376 rev = ctx.rev()
4308 rev = ctx.rev()
4377 pctx = ctx.p1()
4309 pctx = ctx.p1()
4378 parent = pctx.rev()
4310 parent = pctx.rev()
4379 matches.setdefault(rev, {})
4311 matches.setdefault(rev, {})
4380 matches.setdefault(parent, {})
4312 matches.setdefault(parent, {})
4381 files = revfiles.setdefault(rev, [])
4313 files = revfiles.setdefault(rev, [])
4382 for fn in fns:
4314 for fn in fns:
4383 flog = getfile(fn)
4315 flog = getfile(fn)
4384 try:
4316 try:
4385 fnode = ctx.filenode(fn)
4317 fnode = ctx.filenode(fn)
4386 except error.LookupError:
4318 except error.LookupError:
4387 continue
4319 continue
4388
4320
4389 copied = flog.renamed(fnode)
4321 copied = flog.renamed(fnode)
4390 copy = follow and copied and copied[0]
4322 copy = follow and copied and copied[0]
4391 if copy:
4323 if copy:
4392 copies.setdefault(rev, {})[fn] = copy
4324 copies.setdefault(rev, {})[fn] = copy
4393 if fn in skip:
4325 if fn in skip:
4394 if copy:
4326 if copy:
4395 skip[copy] = True
4327 skip[copy] = True
4396 continue
4328 continue
4397 files.append(fn)
4329 files.append(fn)
4398
4330
4399 if fn not in matches[rev]:
4331 if fn not in matches[rev]:
4400 grepbody(fn, rev, flog.read(fnode))
4332 grepbody(fn, rev, flog.read(fnode))
4401
4333
4402 pfn = copy or fn
4334 pfn = copy or fn
4403 if pfn not in matches[parent]:
4335 if pfn not in matches[parent]:
4404 try:
4336 try:
4405 fnode = pctx.filenode(pfn)
4337 fnode = pctx.filenode(pfn)
4406 grepbody(pfn, parent, flog.read(fnode))
4338 grepbody(pfn, parent, flog.read(fnode))
4407 except error.LookupError:
4339 except error.LookupError:
4408 pass
4340 pass
4409
4341
4410 fm = ui.formatter('grep', opts)
4342 fm = ui.formatter('grep', opts)
4411 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4343 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4412 rev = ctx.rev()
4344 rev = ctx.rev()
4413 parent = ctx.p1().rev()
4345 parent = ctx.p1().rev()
4414 for fn in sorted(revfiles.get(rev, [])):
4346 for fn in sorted(revfiles.get(rev, [])):
4415 states = matches[rev][fn]
4347 states = matches[rev][fn]
4416 copy = copies.get(rev, {}).get(fn)
4348 copy = copies.get(rev, {}).get(fn)
4417 if fn in skip:
4349 if fn in skip:
4418 if copy:
4350 if copy:
4419 skip[copy] = True
4351 skip[copy] = True
4420 continue
4352 continue
4421 pstates = matches.get(parent, {}).get(copy or fn, [])
4353 pstates = matches.get(parent, {}).get(copy or fn, [])
4422 if pstates or states:
4354 if pstates or states:
4423 r = display(fm, fn, ctx, pstates, states)
4355 r = display(fm, fn, ctx, pstates, states)
4424 found = found or r
4356 found = found or r
4425 if r and not opts.get('all'):
4357 if r and not opts.get('all'):
4426 skip[fn] = True
4358 skip[fn] = True
4427 if copy:
4359 if copy:
4428 skip[copy] = True
4360 skip[copy] = True
4429 del matches[rev]
4361 del matches[rev]
4430 del revfiles[rev]
4362 del revfiles[rev]
4431 fm.end()
4363 fm.end()
4432
4364
4433 return not found
4365 return not found
4434
4366
4435 @command('heads',
4367 @command('heads',
4436 [('r', 'rev', '',
4368 [('r', 'rev', '',
4437 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4369 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4438 ('t', 'topo', False, _('show topological heads only')),
4370 ('t', 'topo', False, _('show topological heads only')),
4439 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4371 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4440 ('c', 'closed', False, _('show normal and closed branch heads')),
4372 ('c', 'closed', False, _('show normal and closed branch heads')),
4441 ] + templateopts,
4373 ] + templateopts,
4442 _('[-ct] [-r STARTREV] [REV]...'))
4374 _('[-ct] [-r STARTREV] [REV]...'))
4443 def heads(ui, repo, *branchrevs, **opts):
4375 def heads(ui, repo, *branchrevs, **opts):
4444 """show branch heads
4376 """show branch heads
4445
4377
4446 With no arguments, show all open branch heads in the repository.
4378 With no arguments, show all open branch heads in the repository.
4447 Branch heads are changesets that have no descendants on the
4379 Branch heads are changesets that have no descendants on the
4448 same branch. They are where development generally takes place and
4380 same branch. They are where development generally takes place and
4449 are the usual targets for update and merge operations.
4381 are the usual targets for update and merge operations.
4450
4382
4451 If one or more REVs are given, only open branch heads on the
4383 If one or more REVs are given, only open branch heads on the
4452 branches associated with the specified changesets are shown. This
4384 branches associated with the specified changesets are shown. This
4453 means that you can use :hg:`heads .` to see the heads on the
4385 means that you can use :hg:`heads .` to see the heads on the
4454 currently checked-out branch.
4386 currently checked-out branch.
4455
4387
4456 If -c/--closed is specified, also show branch heads marked closed
4388 If -c/--closed is specified, also show branch heads marked closed
4457 (see :hg:`commit --close-branch`).
4389 (see :hg:`commit --close-branch`).
4458
4390
4459 If STARTREV is specified, only those heads that are descendants of
4391 If STARTREV is specified, only those heads that are descendants of
4460 STARTREV will be displayed.
4392 STARTREV will be displayed.
4461
4393
4462 If -t/--topo is specified, named branch mechanics will be ignored and only
4394 If -t/--topo is specified, named branch mechanics will be ignored and only
4463 topological heads (changesets with no children) will be shown.
4395 topological heads (changesets with no children) will be shown.
4464
4396
4465 Returns 0 if matching heads are found, 1 if not.
4397 Returns 0 if matching heads are found, 1 if not.
4466 """
4398 """
4467
4399
4468 start = None
4400 start = None
4469 if 'rev' in opts:
4401 if 'rev' in opts:
4470 start = scmutil.revsingle(repo, opts['rev'], None).node()
4402 start = scmutil.revsingle(repo, opts['rev'], None).node()
4471
4403
4472 if opts.get('topo'):
4404 if opts.get('topo'):
4473 heads = [repo[h] for h in repo.heads(start)]
4405 heads = [repo[h] for h in repo.heads(start)]
4474 else:
4406 else:
4475 heads = []
4407 heads = []
4476 for branch in repo.branchmap():
4408 for branch in repo.branchmap():
4477 heads += repo.branchheads(branch, start, opts.get('closed'))
4409 heads += repo.branchheads(branch, start, opts.get('closed'))
4478 heads = [repo[h] for h in heads]
4410 heads = [repo[h] for h in heads]
4479
4411
4480 if branchrevs:
4412 if branchrevs:
4481 branches = set(repo[br].branch() for br in branchrevs)
4413 branches = set(repo[br].branch() for br in branchrevs)
4482 heads = [h for h in heads if h.branch() in branches]
4414 heads = [h for h in heads if h.branch() in branches]
4483
4415
4484 if opts.get('active') and branchrevs:
4416 if opts.get('active') and branchrevs:
4485 dagheads = repo.heads(start)
4417 dagheads = repo.heads(start)
4486 heads = [h for h in heads if h.node() in dagheads]
4418 heads = [h for h in heads if h.node() in dagheads]
4487
4419
4488 if branchrevs:
4420 if branchrevs:
4489 haveheads = set(h.branch() for h in heads)
4421 haveheads = set(h.branch() for h in heads)
4490 if branches - haveheads:
4422 if branches - haveheads:
4491 headless = ', '.join(b for b in branches - haveheads)
4423 headless = ', '.join(b for b in branches - haveheads)
4492 msg = _('no open branch heads found on branches %s')
4424 msg = _('no open branch heads found on branches %s')
4493 if opts.get('rev'):
4425 if opts.get('rev'):
4494 msg += _(' (started at %s)') % opts['rev']
4426 msg += _(' (started at %s)') % opts['rev']
4495 ui.warn((msg + '\n') % headless)
4427 ui.warn((msg + '\n') % headless)
4496
4428
4497 if not heads:
4429 if not heads:
4498 return 1
4430 return 1
4499
4431
4500 heads = sorted(heads, key=lambda x: -x.rev())
4432 heads = sorted(heads, key=lambda x: -x.rev())
4501 displayer = cmdutil.show_changeset(ui, repo, opts)
4433 displayer = cmdutil.show_changeset(ui, repo, opts)
4502 for ctx in heads:
4434 for ctx in heads:
4503 displayer.show(ctx)
4435 displayer.show(ctx)
4504 displayer.close()
4436 displayer.close()
4505
4437
4506 @command('help',
4438 @command('help',
4507 [('e', 'extension', None, _('show only help for extensions')),
4439 [('e', 'extension', None, _('show only help for extensions')),
4508 ('c', 'command', None, _('show only help for commands')),
4440 ('c', 'command', None, _('show only help for commands')),
4509 ('k', 'keyword', None, _('show topics matching keyword')),
4441 ('k', 'keyword', None, _('show topics matching keyword')),
4510 ('s', 'system', [], _('show help for specific platform(s)')),
4442 ('s', 'system', [], _('show help for specific platform(s)')),
4511 ],
4443 ],
4512 _('[-ecks] [TOPIC]'),
4444 _('[-ecks] [TOPIC]'),
4513 norepo=True)
4445 norepo=True)
4514 def help_(ui, name=None, **opts):
4446 def help_(ui, name=None, **opts):
4515 """show help for a given topic or a help overview
4447 """show help for a given topic or a help overview
4516
4448
4517 With no arguments, print a list of commands with short help messages.
4449 With no arguments, print a list of commands with short help messages.
4518
4450
4519 Given a topic, extension, or command name, print help for that
4451 Given a topic, extension, or command name, print help for that
4520 topic.
4452 topic.
4521
4453
4522 Returns 0 if successful.
4454 Returns 0 if successful.
4523 """
4455 """
4524
4456
4525 textwidth = ui.configint('ui', 'textwidth', 78)
4457 textwidth = ui.configint('ui', 'textwidth', 78)
4526 termwidth = ui.termwidth() - 2
4458 termwidth = ui.termwidth() - 2
4527 if textwidth <= 0 or termwidth < textwidth:
4459 if textwidth <= 0 or termwidth < textwidth:
4528 textwidth = termwidth
4460 textwidth = termwidth
4529
4461
4530 keep = opts.get('system') or []
4462 keep = opts.get('system') or []
4531 if len(keep) == 0:
4463 if len(keep) == 0:
4532 if sys.platform.startswith('win'):
4464 if sys.platform.startswith('win'):
4533 keep.append('windows')
4465 keep.append('windows')
4534 elif sys.platform == 'OpenVMS':
4466 elif sys.platform == 'OpenVMS':
4535 keep.append('vms')
4467 keep.append('vms')
4536 elif sys.platform == 'plan9':
4468 elif sys.platform == 'plan9':
4537 keep.append('plan9')
4469 keep.append('plan9')
4538 else:
4470 else:
4539 keep.append('unix')
4471 keep.append('unix')
4540 keep.append(sys.platform.lower())
4472 keep.append(sys.platform.lower())
4541 if ui.verbose:
4473 if ui.verbose:
4542 keep.append('verbose')
4474 keep.append('verbose')
4543
4475
4544 section = None
4476 section = None
4545 subtopic = None
4477 subtopic = None
4546 if name and '.' in name:
4478 if name and '.' in name:
4547 name, remaining = name.split('.', 1)
4479 name, remaining = name.split('.', 1)
4548 remaining = encoding.lower(remaining)
4480 remaining = encoding.lower(remaining)
4549 if '.' in remaining:
4481 if '.' in remaining:
4550 subtopic, section = remaining.split('.', 1)
4482 subtopic, section = remaining.split('.', 1)
4551 else:
4483 else:
4552 if name in help.subtopics:
4484 if name in help.subtopics:
4553 subtopic = remaining
4485 subtopic = remaining
4554 else:
4486 else:
4555 section = remaining
4487 section = remaining
4556
4488
4557 text = help.help_(ui, name, subtopic=subtopic, **opts)
4489 text = help.help_(ui, name, subtopic=subtopic, **opts)
4558
4490
4559 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4491 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4560 section=section)
4492 section=section)
4561
4493
4562 # We could have been given a weird ".foo" section without a name
4494 # We could have been given a weird ".foo" section without a name
4563 # to look for, or we could have simply failed to found "foo.bar"
4495 # to look for, or we could have simply failed to found "foo.bar"
4564 # because bar isn't a section of foo
4496 # because bar isn't a section of foo
4565 if section and not (formatted and name):
4497 if section and not (formatted and name):
4566 raise error.Abort(_("help section not found"))
4498 raise error.Abort(_("help section not found"))
4567
4499
4568 if 'verbose' in pruned:
4500 if 'verbose' in pruned:
4569 keep.append('omitted')
4501 keep.append('omitted')
4570 else:
4502 else:
4571 keep.append('notomitted')
4503 keep.append('notomitted')
4572 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4504 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4573 section=section)
4505 section=section)
4574 ui.write(formatted)
4506 ui.write(formatted)
4575
4507
4576
4508
4577 @command('identify|id',
4509 @command('identify|id',
4578 [('r', 'rev', '',
4510 [('r', 'rev', '',
4579 _('identify the specified revision'), _('REV')),
4511 _('identify the specified revision'), _('REV')),
4580 ('n', 'num', None, _('show local revision number')),
4512 ('n', 'num', None, _('show local revision number')),
4581 ('i', 'id', None, _('show global revision id')),
4513 ('i', 'id', None, _('show global revision id')),
4582 ('b', 'branch', None, _('show branch')),
4514 ('b', 'branch', None, _('show branch')),
4583 ('t', 'tags', None, _('show tags')),
4515 ('t', 'tags', None, _('show tags')),
4584 ('B', 'bookmarks', None, _('show bookmarks')),
4516 ('B', 'bookmarks', None, _('show bookmarks')),
4585 ] + remoteopts,
4517 ] + remoteopts,
4586 _('[-nibtB] [-r REV] [SOURCE]'),
4518 _('[-nibtB] [-r REV] [SOURCE]'),
4587 optionalrepo=True)
4519 optionalrepo=True)
4588 def identify(ui, repo, source=None, rev=None,
4520 def identify(ui, repo, source=None, rev=None,
4589 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4521 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4590 """identify the working directory or specified revision
4522 """identify the working directory or specified revision
4591
4523
4592 Print a summary identifying the repository state at REV using one or
4524 Print a summary identifying the repository state at REV using one or
4593 two parent hash identifiers, followed by a "+" if the working
4525 two parent hash identifiers, followed by a "+" if the working
4594 directory has uncommitted changes, the branch name (if not default),
4526 directory has uncommitted changes, the branch name (if not default),
4595 a list of tags, and a list of bookmarks.
4527 a list of tags, and a list of bookmarks.
4596
4528
4597 When REV is not given, print a summary of the current state of the
4529 When REV is not given, print a summary of the current state of the
4598 repository.
4530 repository.
4599
4531
4600 Specifying a path to a repository root or Mercurial bundle will
4532 Specifying a path to a repository root or Mercurial bundle will
4601 cause lookup to operate on that repository/bundle.
4533 cause lookup to operate on that repository/bundle.
4602
4534
4603 .. container:: verbose
4535 .. container:: verbose
4604
4536
4605 Examples:
4537 Examples:
4606
4538
4607 - generate a build identifier for the working directory::
4539 - generate a build identifier for the working directory::
4608
4540
4609 hg id --id > build-id.dat
4541 hg id --id > build-id.dat
4610
4542
4611 - find the revision corresponding to a tag::
4543 - find the revision corresponding to a tag::
4612
4544
4613 hg id -n -r 1.3
4545 hg id -n -r 1.3
4614
4546
4615 - check the most recent revision of a remote repository::
4547 - check the most recent revision of a remote repository::
4616
4548
4617 hg id -r tip https://www.mercurial-scm.org/repo/hg/
4549 hg id -r tip https://www.mercurial-scm.org/repo/hg/
4618
4550
4619 See :hg:`log` for generating more information about specific revisions,
4551 See :hg:`log` for generating more information about specific revisions,
4620 including full hash identifiers.
4552 including full hash identifiers.
4621
4553
4622 Returns 0 if successful.
4554 Returns 0 if successful.
4623 """
4555 """
4624
4556
4625 if not repo and not source:
4557 if not repo and not source:
4626 raise error.Abort(_("there is no Mercurial repository here "
4558 raise error.Abort(_("there is no Mercurial repository here "
4627 "(.hg not found)"))
4559 "(.hg not found)"))
4628
4560
4629 if ui.debugflag:
4561 if ui.debugflag:
4630 hexfunc = hex
4562 hexfunc = hex
4631 else:
4563 else:
4632 hexfunc = short
4564 hexfunc = short
4633 default = not (num or id or branch or tags or bookmarks)
4565 default = not (num or id or branch or tags or bookmarks)
4634 output = []
4566 output = []
4635 revs = []
4567 revs = []
4636
4568
4637 if source:
4569 if source:
4638 source, branches = hg.parseurl(ui.expandpath(source))
4570 source, branches = hg.parseurl(ui.expandpath(source))
4639 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4571 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4640 repo = peer.local()
4572 repo = peer.local()
4641 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4573 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4642
4574
4643 if not repo:
4575 if not repo:
4644 if num or branch or tags:
4576 if num or branch or tags:
4645 raise error.Abort(
4577 raise error.Abort(
4646 _("can't query remote revision number, branch, or tags"))
4578 _("can't query remote revision number, branch, or tags"))
4647 if not rev and revs:
4579 if not rev and revs:
4648 rev = revs[0]
4580 rev = revs[0]
4649 if not rev:
4581 if not rev:
4650 rev = "tip"
4582 rev = "tip"
4651
4583
4652 remoterev = peer.lookup(rev)
4584 remoterev = peer.lookup(rev)
4653 if default or id:
4585 if default or id:
4654 output = [hexfunc(remoterev)]
4586 output = [hexfunc(remoterev)]
4655
4587
4656 def getbms():
4588 def getbms():
4657 bms = []
4589 bms = []
4658
4590
4659 if 'bookmarks' in peer.listkeys('namespaces'):
4591 if 'bookmarks' in peer.listkeys('namespaces'):
4660 hexremoterev = hex(remoterev)
4592 hexremoterev = hex(remoterev)
4661 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4593 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4662 if bmr == hexremoterev]
4594 if bmr == hexremoterev]
4663
4595
4664 return sorted(bms)
4596 return sorted(bms)
4665
4597
4666 if bookmarks:
4598 if bookmarks:
4667 output.extend(getbms())
4599 output.extend(getbms())
4668 elif default and not ui.quiet:
4600 elif default and not ui.quiet:
4669 # multiple bookmarks for a single parent separated by '/'
4601 # multiple bookmarks for a single parent separated by '/'
4670 bm = '/'.join(getbms())
4602 bm = '/'.join(getbms())
4671 if bm:
4603 if bm:
4672 output.append(bm)
4604 output.append(bm)
4673 else:
4605 else:
4674 ctx = scmutil.revsingle(repo, rev, None)
4606 ctx = scmutil.revsingle(repo, rev, None)
4675
4607
4676 if ctx.rev() is None:
4608 if ctx.rev() is None:
4677 ctx = repo[None]
4609 ctx = repo[None]
4678 parents = ctx.parents()
4610 parents = ctx.parents()
4679 taglist = []
4611 taglist = []
4680 for p in parents:
4612 for p in parents:
4681 taglist.extend(p.tags())
4613 taglist.extend(p.tags())
4682
4614
4683 changed = ""
4615 changed = ""
4684 if default or id or num:
4616 if default or id or num:
4685 if (any(repo.status())
4617 if (any(repo.status())
4686 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4618 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4687 changed = '+'
4619 changed = '+'
4688 if default or id:
4620 if default or id:
4689 output = ["%s%s" %
4621 output = ["%s%s" %
4690 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4622 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4691 if num:
4623 if num:
4692 output.append("%s%s" %
4624 output.append("%s%s" %
4693 ('+'.join([str(p.rev()) for p in parents]), changed))
4625 ('+'.join([str(p.rev()) for p in parents]), changed))
4694 else:
4626 else:
4695 if default or id:
4627 if default or id:
4696 output = [hexfunc(ctx.node())]
4628 output = [hexfunc(ctx.node())]
4697 if num:
4629 if num:
4698 output.append(str(ctx.rev()))
4630 output.append(str(ctx.rev()))
4699 taglist = ctx.tags()
4631 taglist = ctx.tags()
4700
4632
4701 if default and not ui.quiet:
4633 if default and not ui.quiet:
4702 b = ctx.branch()
4634 b = ctx.branch()
4703 if b != 'default':
4635 if b != 'default':
4704 output.append("(%s)" % b)
4636 output.append("(%s)" % b)
4705
4637
4706 # multiple tags for a single parent separated by '/'
4638 # multiple tags for a single parent separated by '/'
4707 t = '/'.join(taglist)
4639 t = '/'.join(taglist)
4708 if t:
4640 if t:
4709 output.append(t)
4641 output.append(t)
4710
4642
4711 # multiple bookmarks for a single parent separated by '/'
4643 # multiple bookmarks for a single parent separated by '/'
4712 bm = '/'.join(ctx.bookmarks())
4644 bm = '/'.join(ctx.bookmarks())
4713 if bm:
4645 if bm:
4714 output.append(bm)
4646 output.append(bm)
4715 else:
4647 else:
4716 if branch:
4648 if branch:
4717 output.append(ctx.branch())
4649 output.append(ctx.branch())
4718
4650
4719 if tags:
4651 if tags:
4720 output.extend(taglist)
4652 output.extend(taglist)
4721
4653
4722 if bookmarks:
4654 if bookmarks:
4723 output.extend(ctx.bookmarks())
4655 output.extend(ctx.bookmarks())
4724
4656
4725 ui.write("%s\n" % ' '.join(output))
4657 ui.write("%s\n" % ' '.join(output))
4726
4658
4727 @command('import|patch',
4659 @command('import|patch',
4728 [('p', 'strip', 1,
4660 [('p', 'strip', 1,
4729 _('directory strip option for patch. This has the same '
4661 _('directory strip option for patch. This has the same '
4730 'meaning as the corresponding patch option'), _('NUM')),
4662 'meaning as the corresponding patch option'), _('NUM')),
4731 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4663 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4732 ('e', 'edit', False, _('invoke editor on commit messages')),
4664 ('e', 'edit', False, _('invoke editor on commit messages')),
4733 ('f', 'force', None,
4665 ('f', 'force', None,
4734 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4666 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4735 ('', 'no-commit', None,
4667 ('', 'no-commit', None,
4736 _("don't commit, just update the working directory")),
4668 _("don't commit, just update the working directory")),
4737 ('', 'bypass', None,
4669 ('', 'bypass', None,
4738 _("apply patch without touching the working directory")),
4670 _("apply patch without touching the working directory")),
4739 ('', 'partial', None,
4671 ('', 'partial', None,
4740 _('commit even if some hunks fail')),
4672 _('commit even if some hunks fail')),
4741 ('', 'exact', None,
4673 ('', 'exact', None,
4742 _('abort if patch would apply lossily')),
4674 _('abort if patch would apply lossily')),
4743 ('', 'prefix', '',
4675 ('', 'prefix', '',
4744 _('apply patch to subdirectory'), _('DIR')),
4676 _('apply patch to subdirectory'), _('DIR')),
4745 ('', 'import-branch', None,
4677 ('', 'import-branch', None,
4746 _('use any branch information in patch (implied by --exact)'))] +
4678 _('use any branch information in patch (implied by --exact)'))] +
4747 commitopts + commitopts2 + similarityopts,
4679 commitopts + commitopts2 + similarityopts,
4748 _('[OPTION]... PATCH...'))
4680 _('[OPTION]... PATCH...'))
4749 def import_(ui, repo, patch1=None, *patches, **opts):
4681 def import_(ui, repo, patch1=None, *patches, **opts):
4750 """import an ordered set of patches
4682 """import an ordered set of patches
4751
4683
4752 Import a list of patches and commit them individually (unless
4684 Import a list of patches and commit them individually (unless
4753 --no-commit is specified).
4685 --no-commit is specified).
4754
4686
4755 To read a patch from standard input, use "-" as the patch name. If
4687 To read a patch from standard input, use "-" as the patch name. If
4756 a URL is specified, the patch will be downloaded from there.
4688 a URL is specified, the patch will be downloaded from there.
4757
4689
4758 Import first applies changes to the working directory (unless
4690 Import first applies changes to the working directory (unless
4759 --bypass is specified), import will abort if there are outstanding
4691 --bypass is specified), import will abort if there are outstanding
4760 changes.
4692 changes.
4761
4693
4762 Use --bypass to apply and commit patches directly to the
4694 Use --bypass to apply and commit patches directly to the
4763 repository, without affecting the working directory. Without
4695 repository, without affecting the working directory. Without
4764 --exact, patches will be applied on top of the working directory
4696 --exact, patches will be applied on top of the working directory
4765 parent revision.
4697 parent revision.
4766
4698
4767 You can import a patch straight from a mail message. Even patches
4699 You can import a patch straight from a mail message. Even patches
4768 as attachments work (to use the body part, it must have type
4700 as attachments work (to use the body part, it must have type
4769 text/plain or text/x-patch). From and Subject headers of email
4701 text/plain or text/x-patch). From and Subject headers of email
4770 message are used as default committer and commit message. All
4702 message are used as default committer and commit message. All
4771 text/plain body parts before first diff are added to the commit
4703 text/plain body parts before first diff are added to the commit
4772 message.
4704 message.
4773
4705
4774 If the imported patch was generated by :hg:`export`, user and
4706 If the imported patch was generated by :hg:`export`, user and
4775 description from patch override values from message headers and
4707 description from patch override values from message headers and
4776 body. Values given on command line with -m/--message and -u/--user
4708 body. Values given on command line with -m/--message and -u/--user
4777 override these.
4709 override these.
4778
4710
4779 If --exact is specified, import will set the working directory to
4711 If --exact is specified, import will set the working directory to
4780 the parent of each patch before applying it, and will abort if the
4712 the parent of each patch before applying it, and will abort if the
4781 resulting changeset has a different ID than the one recorded in
4713 resulting changeset has a different ID than the one recorded in
4782 the patch. This will guard against various ways that portable
4714 the patch. This will guard against various ways that portable
4783 patch formats and mail systems might fail to transfer Mercurial
4715 patch formats and mail systems might fail to transfer Mercurial
4784 data or metadata. See :hg:`bundle` for lossless transmission.
4716 data or metadata. See :hg:`bundle` for lossless transmission.
4785
4717
4786 Use --partial to ensure a changeset will be created from the patch
4718 Use --partial to ensure a changeset will be created from the patch
4787 even if some hunks fail to apply. Hunks that fail to apply will be
4719 even if some hunks fail to apply. Hunks that fail to apply will be
4788 written to a <target-file>.rej file. Conflicts can then be resolved
4720 written to a <target-file>.rej file. Conflicts can then be resolved
4789 by hand before :hg:`commit --amend` is run to update the created
4721 by hand before :hg:`commit --amend` is run to update the created
4790 changeset. This flag exists to let people import patches that
4722 changeset. This flag exists to let people import patches that
4791 partially apply without losing the associated metadata (author,
4723 partially apply without losing the associated metadata (author,
4792 date, description, ...).
4724 date, description, ...).
4793
4725
4794 .. note::
4726 .. note::
4795
4727
4796 When no hunks apply cleanly, :hg:`import --partial` will create
4728 When no hunks apply cleanly, :hg:`import --partial` will create
4797 an empty changeset, importing only the patch metadata.
4729 an empty changeset, importing only the patch metadata.
4798
4730
4799 With -s/--similarity, hg will attempt to discover renames and
4731 With -s/--similarity, hg will attempt to discover renames and
4800 copies in the patch in the same way as :hg:`addremove`.
4732 copies in the patch in the same way as :hg:`addremove`.
4801
4733
4802 It is possible to use external patch programs to perform the patch
4734 It is possible to use external patch programs to perform the patch
4803 by setting the ``ui.patch`` configuration option. For the default
4735 by setting the ``ui.patch`` configuration option. For the default
4804 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4736 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4805 See :hg:`help config` for more information about configuration
4737 See :hg:`help config` for more information about configuration
4806 files and how to use these options.
4738 files and how to use these options.
4807
4739
4808 See :hg:`help dates` for a list of formats valid for -d/--date.
4740 See :hg:`help dates` for a list of formats valid for -d/--date.
4809
4741
4810 .. container:: verbose
4742 .. container:: verbose
4811
4743
4812 Examples:
4744 Examples:
4813
4745
4814 - import a traditional patch from a website and detect renames::
4746 - import a traditional patch from a website and detect renames::
4815
4747
4816 hg import -s 80 http://example.com/bugfix.patch
4748 hg import -s 80 http://example.com/bugfix.patch
4817
4749
4818 - import a changeset from an hgweb server::
4750 - import a changeset from an hgweb server::
4819
4751
4820 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4752 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4821
4753
4822 - import all the patches in an Unix-style mbox::
4754 - import all the patches in an Unix-style mbox::
4823
4755
4824 hg import incoming-patches.mbox
4756 hg import incoming-patches.mbox
4825
4757
4826 - attempt to exactly restore an exported changeset (not always
4758 - attempt to exactly restore an exported changeset (not always
4827 possible)::
4759 possible)::
4828
4760
4829 hg import --exact proposed-fix.patch
4761 hg import --exact proposed-fix.patch
4830
4762
4831 - use an external tool to apply a patch which is too fuzzy for
4763 - use an external tool to apply a patch which is too fuzzy for
4832 the default internal tool.
4764 the default internal tool.
4833
4765
4834 hg import --config ui.patch="patch --merge" fuzzy.patch
4766 hg import --config ui.patch="patch --merge" fuzzy.patch
4835
4767
4836 - change the default fuzzing from 2 to a less strict 7
4768 - change the default fuzzing from 2 to a less strict 7
4837
4769
4838 hg import --config ui.fuzz=7 fuzz.patch
4770 hg import --config ui.fuzz=7 fuzz.patch
4839
4771
4840 Returns 0 on success, 1 on partial success (see --partial).
4772 Returns 0 on success, 1 on partial success (see --partial).
4841 """
4773 """
4842
4774
4843 if not patch1:
4775 if not patch1:
4844 raise error.Abort(_('need at least one patch to import'))
4776 raise error.Abort(_('need at least one patch to import'))
4845
4777
4846 patches = (patch1,) + patches
4778 patches = (patch1,) + patches
4847
4779
4848 date = opts.get('date')
4780 date = opts.get('date')
4849 if date:
4781 if date:
4850 opts['date'] = util.parsedate(date)
4782 opts['date'] = util.parsedate(date)
4851
4783
4852 exact = opts.get('exact')
4784 exact = opts.get('exact')
4853 update = not opts.get('bypass')
4785 update = not opts.get('bypass')
4854 if not update and opts.get('no_commit'):
4786 if not update and opts.get('no_commit'):
4855 raise error.Abort(_('cannot use --no-commit with --bypass'))
4787 raise error.Abort(_('cannot use --no-commit with --bypass'))
4856 try:
4788 try:
4857 sim = float(opts.get('similarity') or 0)
4789 sim = float(opts.get('similarity') or 0)
4858 except ValueError:
4790 except ValueError:
4859 raise error.Abort(_('similarity must be a number'))
4791 raise error.Abort(_('similarity must be a number'))
4860 if sim < 0 or sim > 100:
4792 if sim < 0 or sim > 100:
4861 raise error.Abort(_('similarity must be between 0 and 100'))
4793 raise error.Abort(_('similarity must be between 0 and 100'))
4862 if sim and not update:
4794 if sim and not update:
4863 raise error.Abort(_('cannot use --similarity with --bypass'))
4795 raise error.Abort(_('cannot use --similarity with --bypass'))
4864 if exact:
4796 if exact:
4865 if opts.get('edit'):
4797 if opts.get('edit'):
4866 raise error.Abort(_('cannot use --exact with --edit'))
4798 raise error.Abort(_('cannot use --exact with --edit'))
4867 if opts.get('prefix'):
4799 if opts.get('prefix'):
4868 raise error.Abort(_('cannot use --exact with --prefix'))
4800 raise error.Abort(_('cannot use --exact with --prefix'))
4869
4801
4870 base = opts["base"]
4802 base = opts["base"]
4871 wlock = dsguard = lock = tr = None
4803 wlock = dsguard = lock = tr = None
4872 msgs = []
4804 msgs = []
4873 ret = 0
4805 ret = 0
4874
4806
4875
4807
4876 try:
4808 try:
4877 wlock = repo.wlock()
4809 wlock = repo.wlock()
4878
4810
4879 if update:
4811 if update:
4880 cmdutil.checkunfinished(repo)
4812 cmdutil.checkunfinished(repo)
4881 if (exact or not opts.get('force')):
4813 if (exact or not opts.get('force')):
4882 cmdutil.bailifchanged(repo)
4814 cmdutil.bailifchanged(repo)
4883
4815
4884 if not opts.get('no_commit'):
4816 if not opts.get('no_commit'):
4885 lock = repo.lock()
4817 lock = repo.lock()
4886 tr = repo.transaction('import')
4818 tr = repo.transaction('import')
4887 else:
4819 else:
4888 dsguard = dirstateguard.dirstateguard(repo, 'import')
4820 dsguard = dirstateguard.dirstateguard(repo, 'import')
4889 parents = repo[None].parents()
4821 parents = repo[None].parents()
4890 for patchurl in patches:
4822 for patchurl in patches:
4891 if patchurl == '-':
4823 if patchurl == '-':
4892 ui.status(_('applying patch from stdin\n'))
4824 ui.status(_('applying patch from stdin\n'))
4893 patchfile = ui.fin
4825 patchfile = ui.fin
4894 patchurl = 'stdin' # for error message
4826 patchurl = 'stdin' # for error message
4895 else:
4827 else:
4896 patchurl = os.path.join(base, patchurl)
4828 patchurl = os.path.join(base, patchurl)
4897 ui.status(_('applying %s\n') % patchurl)
4829 ui.status(_('applying %s\n') % patchurl)
4898 patchfile = hg.openpath(ui, patchurl)
4830 patchfile = hg.openpath(ui, patchurl)
4899
4831
4900 haspatch = False
4832 haspatch = False
4901 for hunk in patch.split(patchfile):
4833 for hunk in patch.split(patchfile):
4902 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4834 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4903 parents, opts,
4835 parents, opts,
4904 msgs, hg.clean)
4836 msgs, hg.clean)
4905 if msg:
4837 if msg:
4906 haspatch = True
4838 haspatch = True
4907 ui.note(msg + '\n')
4839 ui.note(msg + '\n')
4908 if update or exact:
4840 if update or exact:
4909 parents = repo[None].parents()
4841 parents = repo[None].parents()
4910 else:
4842 else:
4911 parents = [repo[node]]
4843 parents = [repo[node]]
4912 if rej:
4844 if rej:
4913 ui.write_err(_("patch applied partially\n"))
4845 ui.write_err(_("patch applied partially\n"))
4914 ui.write_err(_("(fix the .rej files and run "
4846 ui.write_err(_("(fix the .rej files and run "
4915 "`hg commit --amend`)\n"))
4847 "`hg commit --amend`)\n"))
4916 ret = 1
4848 ret = 1
4917 break
4849 break
4918
4850
4919 if not haspatch:
4851 if not haspatch:
4920 raise error.Abort(_('%s: no diffs found') % patchurl)
4852 raise error.Abort(_('%s: no diffs found') % patchurl)
4921
4853
4922 if tr:
4854 if tr:
4923 tr.close()
4855 tr.close()
4924 if msgs:
4856 if msgs:
4925 repo.savecommitmessage('\n* * *\n'.join(msgs))
4857 repo.savecommitmessage('\n* * *\n'.join(msgs))
4926 if dsguard:
4858 if dsguard:
4927 dsguard.close()
4859 dsguard.close()
4928 return ret
4860 return ret
4929 finally:
4861 finally:
4930 if tr:
4862 if tr:
4931 tr.release()
4863 tr.release()
4932 release(lock, dsguard, wlock)
4864 release(lock, dsguard, wlock)
4933
4865
4934 @command('incoming|in',
4866 @command('incoming|in',
4935 [('f', 'force', None,
4867 [('f', 'force', None,
4936 _('run even if remote repository is unrelated')),
4868 _('run even if remote repository is unrelated')),
4937 ('n', 'newest-first', None, _('show newest record first')),
4869 ('n', 'newest-first', None, _('show newest record first')),
4938 ('', 'bundle', '',
4870 ('', 'bundle', '',
4939 _('file to store the bundles into'), _('FILE')),
4871 _('file to store the bundles into'), _('FILE')),
4940 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4872 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4941 ('B', 'bookmarks', False, _("compare bookmarks")),
4873 ('B', 'bookmarks', False, _("compare bookmarks")),
4942 ('b', 'branch', [],
4874 ('b', 'branch', [],
4943 _('a specific branch you would like to pull'), _('BRANCH')),
4875 _('a specific branch you would like to pull'), _('BRANCH')),
4944 ] + logopts + remoteopts + subrepoopts,
4876 ] + logopts + remoteopts + subrepoopts,
4945 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4877 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4946 def incoming(ui, repo, source="default", **opts):
4878 def incoming(ui, repo, source="default", **opts):
4947 """show new changesets found in source
4879 """show new changesets found in source
4948
4880
4949 Show new changesets found in the specified path/URL or the default
4881 Show new changesets found in the specified path/URL or the default
4950 pull location. These are the changesets that would have been pulled
4882 pull location. These are the changesets that would have been pulled
4951 if a pull at the time you issued this command.
4883 if a pull at the time you issued this command.
4952
4884
4953 See pull for valid source format details.
4885 See pull for valid source format details.
4954
4886
4955 .. container:: verbose
4887 .. container:: verbose
4956
4888
4957 With -B/--bookmarks, the result of bookmark comparison between
4889 With -B/--bookmarks, the result of bookmark comparison between
4958 local and remote repositories is displayed. With -v/--verbose,
4890 local and remote repositories is displayed. With -v/--verbose,
4959 status is also displayed for each bookmark like below::
4891 status is also displayed for each bookmark like below::
4960
4892
4961 BM1 01234567890a added
4893 BM1 01234567890a added
4962 BM2 1234567890ab advanced
4894 BM2 1234567890ab advanced
4963 BM3 234567890abc diverged
4895 BM3 234567890abc diverged
4964 BM4 34567890abcd changed
4896 BM4 34567890abcd changed
4965
4897
4966 The action taken locally when pulling depends on the
4898 The action taken locally when pulling depends on the
4967 status of each bookmark:
4899 status of each bookmark:
4968
4900
4969 :``added``: pull will create it
4901 :``added``: pull will create it
4970 :``advanced``: pull will update it
4902 :``advanced``: pull will update it
4971 :``diverged``: pull will create a divergent bookmark
4903 :``diverged``: pull will create a divergent bookmark
4972 :``changed``: result depends on remote changesets
4904 :``changed``: result depends on remote changesets
4973
4905
4974 From the point of view of pulling behavior, bookmark
4906 From the point of view of pulling behavior, bookmark
4975 existing only in the remote repository are treated as ``added``,
4907 existing only in the remote repository are treated as ``added``,
4976 even if it is in fact locally deleted.
4908 even if it is in fact locally deleted.
4977
4909
4978 .. container:: verbose
4910 .. container:: verbose
4979
4911
4980 For remote repository, using --bundle avoids downloading the
4912 For remote repository, using --bundle avoids downloading the
4981 changesets twice if the incoming is followed by a pull.
4913 changesets twice if the incoming is followed by a pull.
4982
4914
4983 Examples:
4915 Examples:
4984
4916
4985 - show incoming changes with patches and full description::
4917 - show incoming changes with patches and full description::
4986
4918
4987 hg incoming -vp
4919 hg incoming -vp
4988
4920
4989 - show incoming changes excluding merges, store a bundle::
4921 - show incoming changes excluding merges, store a bundle::
4990
4922
4991 hg in -vpM --bundle incoming.hg
4923 hg in -vpM --bundle incoming.hg
4992 hg pull incoming.hg
4924 hg pull incoming.hg
4993
4925
4994 - briefly list changes inside a bundle::
4926 - briefly list changes inside a bundle::
4995
4927
4996 hg in changes.hg -T "{desc|firstline}\\n"
4928 hg in changes.hg -T "{desc|firstline}\\n"
4997
4929
4998 Returns 0 if there are incoming changes, 1 otherwise.
4930 Returns 0 if there are incoming changes, 1 otherwise.
4999 """
4931 """
5000 if opts.get('graph'):
4932 if opts.get('graph'):
5001 cmdutil.checkunsupportedgraphflags([], opts)
4933 cmdutil.checkunsupportedgraphflags([], opts)
5002 def display(other, chlist, displayer):
4934 def display(other, chlist, displayer):
5003 revdag = cmdutil.graphrevs(other, chlist, opts)
4935 revdag = cmdutil.graphrevs(other, chlist, opts)
5004 cmdutil.displaygraph(ui, repo, revdag, displayer,
4936 cmdutil.displaygraph(ui, repo, revdag, displayer,
5005 graphmod.asciiedges)
4937 graphmod.asciiedges)
5006
4938
5007 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4939 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
5008 return 0
4940 return 0
5009
4941
5010 if opts.get('bundle') and opts.get('subrepos'):
4942 if opts.get('bundle') and opts.get('subrepos'):
5011 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4943 raise error.Abort(_('cannot combine --bundle and --subrepos'))
5012
4944
5013 if opts.get('bookmarks'):
4945 if opts.get('bookmarks'):
5014 source, branches = hg.parseurl(ui.expandpath(source),
4946 source, branches = hg.parseurl(ui.expandpath(source),
5015 opts.get('branch'))
4947 opts.get('branch'))
5016 other = hg.peer(repo, opts, source)
4948 other = hg.peer(repo, opts, source)
5017 if 'bookmarks' not in other.listkeys('namespaces'):
4949 if 'bookmarks' not in other.listkeys('namespaces'):
5018 ui.warn(_("remote doesn't support bookmarks\n"))
4950 ui.warn(_("remote doesn't support bookmarks\n"))
5019 return 0
4951 return 0
5020 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4952 ui.status(_('comparing with %s\n') % util.hidepassword(source))
5021 return bookmarks.incoming(ui, repo, other)
4953 return bookmarks.incoming(ui, repo, other)
5022
4954
5023 repo._subtoppath = ui.expandpath(source)
4955 repo._subtoppath = ui.expandpath(source)
5024 try:
4956 try:
5025 return hg.incoming(ui, repo, source, opts)
4957 return hg.incoming(ui, repo, source, opts)
5026 finally:
4958 finally:
5027 del repo._subtoppath
4959 del repo._subtoppath
5028
4960
5029
4961
5030 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4962 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
5031 norepo=True)
4963 norepo=True)
5032 def init(ui, dest=".", **opts):
4964 def init(ui, dest=".", **opts):
5033 """create a new repository in the given directory
4965 """create a new repository in the given directory
5034
4966
5035 Initialize a new repository in the given directory. If the given
4967 Initialize a new repository in the given directory. If the given
5036 directory does not exist, it will be created.
4968 directory does not exist, it will be created.
5037
4969
5038 If no directory is given, the current directory is used.
4970 If no directory is given, the current directory is used.
5039
4971
5040 It is possible to specify an ``ssh://`` URL as the destination.
4972 It is possible to specify an ``ssh://`` URL as the destination.
5041 See :hg:`help urls` for more information.
4973 See :hg:`help urls` for more information.
5042
4974
5043 Returns 0 on success.
4975 Returns 0 on success.
5044 """
4976 """
5045 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4977 hg.peer(ui, opts, ui.expandpath(dest), create=True)
5046
4978
5047 @command('locate',
4979 @command('locate',
5048 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4980 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
5049 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4981 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5050 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4982 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
5051 ] + walkopts,
4983 ] + walkopts,
5052 _('[OPTION]... [PATTERN]...'))
4984 _('[OPTION]... [PATTERN]...'))
5053 def locate(ui, repo, *pats, **opts):
4985 def locate(ui, repo, *pats, **opts):
5054 """locate files matching specific patterns (DEPRECATED)
4986 """locate files matching specific patterns (DEPRECATED)
5055
4987
5056 Print files under Mercurial control in the working directory whose
4988 Print files under Mercurial control in the working directory whose
5057 names match the given patterns.
4989 names match the given patterns.
5058
4990
5059 By default, this command searches all directories in the working
4991 By default, this command searches all directories in the working
5060 directory. To search just the current directory and its
4992 directory. To search just the current directory and its
5061 subdirectories, use "--include .".
4993 subdirectories, use "--include .".
5062
4994
5063 If no patterns are given to match, this command prints the names
4995 If no patterns are given to match, this command prints the names
5064 of all files under Mercurial control in the working directory.
4996 of all files under Mercurial control in the working directory.
5065
4997
5066 If you want to feed the output of this command into the "xargs"
4998 If you want to feed the output of this command into the "xargs"
5067 command, use the -0 option to both this command and "xargs". This
4999 command, use the -0 option to both this command and "xargs". This
5068 will avoid the problem of "xargs" treating single filenames that
5000 will avoid the problem of "xargs" treating single filenames that
5069 contain whitespace as multiple filenames.
5001 contain whitespace as multiple filenames.
5070
5002
5071 See :hg:`help files` for a more versatile command.
5003 See :hg:`help files` for a more versatile command.
5072
5004
5073 Returns 0 if a match is found, 1 otherwise.
5005 Returns 0 if a match is found, 1 otherwise.
5074 """
5006 """
5075 if opts.get('print0'):
5007 if opts.get('print0'):
5076 end = '\0'
5008 end = '\0'
5077 else:
5009 else:
5078 end = '\n'
5010 end = '\n'
5079 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5011 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
5080
5012
5081 ret = 1
5013 ret = 1
5082 ctx = repo[rev]
5014 ctx = repo[rev]
5083 m = scmutil.match(ctx, pats, opts, default='relglob',
5015 m = scmutil.match(ctx, pats, opts, default='relglob',
5084 badfn=lambda x, y: False)
5016 badfn=lambda x, y: False)
5085
5017
5086 for abs in ctx.matches(m):
5018 for abs in ctx.matches(m):
5087 if opts.get('fullpath'):
5019 if opts.get('fullpath'):
5088 ui.write(repo.wjoin(abs), end)
5020 ui.write(repo.wjoin(abs), end)
5089 else:
5021 else:
5090 ui.write(((pats and m.rel(abs)) or abs), end)
5022 ui.write(((pats and m.rel(abs)) or abs), end)
5091 ret = 0
5023 ret = 0
5092
5024
5093 return ret
5025 return ret
5094
5026
5095 @command('^log|history',
5027 @command('^log|history',
5096 [('f', 'follow', None,
5028 [('f', 'follow', None,
5097 _('follow changeset history, or file history across copies and renames')),
5029 _('follow changeset history, or file history across copies and renames')),
5098 ('', 'follow-first', None,
5030 ('', 'follow-first', None,
5099 _('only follow the first parent of merge changesets (DEPRECATED)')),
5031 _('only follow the first parent of merge changesets (DEPRECATED)')),
5100 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5032 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
5101 ('C', 'copies', None, _('show copied files')),
5033 ('C', 'copies', None, _('show copied files')),
5102 ('k', 'keyword', [],
5034 ('k', 'keyword', [],
5103 _('do case-insensitive search for a given text'), _('TEXT')),
5035 _('do case-insensitive search for a given text'), _('TEXT')),
5104 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5036 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
5105 ('', 'removed', None, _('include revisions where files were removed')),
5037 ('', 'removed', None, _('include revisions where files were removed')),
5106 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5038 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
5107 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5039 ('u', 'user', [], _('revisions committed by user'), _('USER')),
5108 ('', 'only-branch', [],
5040 ('', 'only-branch', [],
5109 _('show only changesets within the given named branch (DEPRECATED)'),
5041 _('show only changesets within the given named branch (DEPRECATED)'),
5110 _('BRANCH')),
5042 _('BRANCH')),
5111 ('b', 'branch', [],
5043 ('b', 'branch', [],
5112 _('show changesets within the given named branch'), _('BRANCH')),
5044 _('show changesets within the given named branch'), _('BRANCH')),
5113 ('P', 'prune', [],
5045 ('P', 'prune', [],
5114 _('do not display revision or any of its ancestors'), _('REV')),
5046 _('do not display revision or any of its ancestors'), _('REV')),
5115 ] + logopts + walkopts,
5047 ] + logopts + walkopts,
5116 _('[OPTION]... [FILE]'),
5048 _('[OPTION]... [FILE]'),
5117 inferrepo=True)
5049 inferrepo=True)
5118 def log(ui, repo, *pats, **opts):
5050 def log(ui, repo, *pats, **opts):
5119 """show revision history of entire repository or files
5051 """show revision history of entire repository or files
5120
5052
5121 Print the revision history of the specified files or the entire
5053 Print the revision history of the specified files or the entire
5122 project.
5054 project.
5123
5055
5124 If no revision range is specified, the default is ``tip:0`` unless
5056 If no revision range is specified, the default is ``tip:0`` unless
5125 --follow is set, in which case the working directory parent is
5057 --follow is set, in which case the working directory parent is
5126 used as the starting revision.
5058 used as the starting revision.
5127
5059
5128 File history is shown without following rename or copy history of
5060 File history is shown without following rename or copy history of
5129 files. Use -f/--follow with a filename to follow history across
5061 files. Use -f/--follow with a filename to follow history across
5130 renames and copies. --follow without a filename will only show
5062 renames and copies. --follow without a filename will only show
5131 ancestors or descendants of the starting revision.
5063 ancestors or descendants of the starting revision.
5132
5064
5133 By default this command prints revision number and changeset id,
5065 By default this command prints revision number and changeset id,
5134 tags, non-trivial parents, user, date and time, and a summary for
5066 tags, non-trivial parents, user, date and time, and a summary for
5135 each commit. When the -v/--verbose switch is used, the list of
5067 each commit. When the -v/--verbose switch is used, the list of
5136 changed files and full commit message are shown.
5068 changed files and full commit message are shown.
5137
5069
5138 With --graph the revisions are shown as an ASCII art DAG with the most
5070 With --graph the revisions are shown as an ASCII art DAG with the most
5139 recent changeset at the top.
5071 recent changeset at the top.
5140 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5072 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
5141 and '+' represents a fork where the changeset from the lines below is a
5073 and '+' represents a fork where the changeset from the lines below is a
5142 parent of the 'o' merge on the same line.
5074 parent of the 'o' merge on the same line.
5143
5075
5144 .. note::
5076 .. note::
5145
5077
5146 :hg:`log --patch` may generate unexpected diff output for merge
5078 :hg:`log --patch` may generate unexpected diff output for merge
5147 changesets, as it will only compare the merge changeset against
5079 changesets, as it will only compare the merge changeset against
5148 its first parent. Also, only files different from BOTH parents
5080 its first parent. Also, only files different from BOTH parents
5149 will appear in files:.
5081 will appear in files:.
5150
5082
5151 .. note::
5083 .. note::
5152
5084
5153 For performance reasons, :hg:`log FILE` may omit duplicate changes
5085 For performance reasons, :hg:`log FILE` may omit duplicate changes
5154 made on branches and will not show removals or mode changes. To
5086 made on branches and will not show removals or mode changes. To
5155 see all such changes, use the --removed switch.
5087 see all such changes, use the --removed switch.
5156
5088
5157 .. container:: verbose
5089 .. container:: verbose
5158
5090
5159 Some examples:
5091 Some examples:
5160
5092
5161 - changesets with full descriptions and file lists::
5093 - changesets with full descriptions and file lists::
5162
5094
5163 hg log -v
5095 hg log -v
5164
5096
5165 - changesets ancestral to the working directory::
5097 - changesets ancestral to the working directory::
5166
5098
5167 hg log -f
5099 hg log -f
5168
5100
5169 - last 10 commits on the current branch::
5101 - last 10 commits on the current branch::
5170
5102
5171 hg log -l 10 -b .
5103 hg log -l 10 -b .
5172
5104
5173 - changesets showing all modifications of a file, including removals::
5105 - changesets showing all modifications of a file, including removals::
5174
5106
5175 hg log --removed file.c
5107 hg log --removed file.c
5176
5108
5177 - all changesets that touch a directory, with diffs, excluding merges::
5109 - all changesets that touch a directory, with diffs, excluding merges::
5178
5110
5179 hg log -Mp lib/
5111 hg log -Mp lib/
5180
5112
5181 - all revision numbers that match a keyword::
5113 - all revision numbers that match a keyword::
5182
5114
5183 hg log -k bug --template "{rev}\\n"
5115 hg log -k bug --template "{rev}\\n"
5184
5116
5185 - the full hash identifier of the working directory parent::
5117 - the full hash identifier of the working directory parent::
5186
5118
5187 hg log -r . --template "{node}\\n"
5119 hg log -r . --template "{node}\\n"
5188
5120
5189 - list available log templates::
5121 - list available log templates::
5190
5122
5191 hg log -T list
5123 hg log -T list
5192
5124
5193 - check if a given changeset is included in a tagged release::
5125 - check if a given changeset is included in a tagged release::
5194
5126
5195 hg log -r "a21ccf and ancestor(1.9)"
5127 hg log -r "a21ccf and ancestor(1.9)"
5196
5128
5197 - find all changesets by some user in a date range::
5129 - find all changesets by some user in a date range::
5198
5130
5199 hg log -k alice -d "may 2008 to jul 2008"
5131 hg log -k alice -d "may 2008 to jul 2008"
5200
5132
5201 - summary of all changesets after the last tag::
5133 - summary of all changesets after the last tag::
5202
5134
5203 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5135 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5204
5136
5205 See :hg:`help dates` for a list of formats valid for -d/--date.
5137 See :hg:`help dates` for a list of formats valid for -d/--date.
5206
5138
5207 See :hg:`help revisions` and :hg:`help revsets` for more about
5139 See :hg:`help revisions` and :hg:`help revsets` for more about
5208 specifying and ordering revisions.
5140 specifying and ordering revisions.
5209
5141
5210 See :hg:`help templates` for more about pre-packaged styles and
5142 See :hg:`help templates` for more about pre-packaged styles and
5211 specifying custom templates.
5143 specifying custom templates.
5212
5144
5213 Returns 0 on success.
5145 Returns 0 on success.
5214
5146
5215 """
5147 """
5216 if opts.get('follow') and opts.get('rev'):
5148 if opts.get('follow') and opts.get('rev'):
5217 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5149 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5218 del opts['follow']
5150 del opts['follow']
5219
5151
5220 if opts.get('graph'):
5152 if opts.get('graph'):
5221 return cmdutil.graphlog(ui, repo, *pats, **opts)
5153 return cmdutil.graphlog(ui, repo, *pats, **opts)
5222
5154
5223 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5155 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5224 limit = cmdutil.loglimit(opts)
5156 limit = cmdutil.loglimit(opts)
5225 count = 0
5157 count = 0
5226
5158
5227 getrenamed = None
5159 getrenamed = None
5228 if opts.get('copies'):
5160 if opts.get('copies'):
5229 endrev = None
5161 endrev = None
5230 if opts.get('rev'):
5162 if opts.get('rev'):
5231 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5163 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5232 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5164 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5233
5165
5234 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5166 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5235 for rev in revs:
5167 for rev in revs:
5236 if count == limit:
5168 if count == limit:
5237 break
5169 break
5238 ctx = repo[rev]
5170 ctx = repo[rev]
5239 copies = None
5171 copies = None
5240 if getrenamed is not None and rev:
5172 if getrenamed is not None and rev:
5241 copies = []
5173 copies = []
5242 for fn in ctx.files():
5174 for fn in ctx.files():
5243 rename = getrenamed(fn, rev)
5175 rename = getrenamed(fn, rev)
5244 if rename:
5176 if rename:
5245 copies.append((fn, rename[0]))
5177 copies.append((fn, rename[0]))
5246 if filematcher:
5178 if filematcher:
5247 revmatchfn = filematcher(ctx.rev())
5179 revmatchfn = filematcher(ctx.rev())
5248 else:
5180 else:
5249 revmatchfn = None
5181 revmatchfn = None
5250 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5182 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5251 if displayer.flush(ctx):
5183 if displayer.flush(ctx):
5252 count += 1
5184 count += 1
5253
5185
5254 displayer.close()
5186 displayer.close()
5255
5187
5256 @command('manifest',
5188 @command('manifest',
5257 [('r', 'rev', '', _('revision to display'), _('REV')),
5189 [('r', 'rev', '', _('revision to display'), _('REV')),
5258 ('', 'all', False, _("list files from all revisions"))]
5190 ('', 'all', False, _("list files from all revisions"))]
5259 + formatteropts,
5191 + formatteropts,
5260 _('[-r REV]'))
5192 _('[-r REV]'))
5261 def manifest(ui, repo, node=None, rev=None, **opts):
5193 def manifest(ui, repo, node=None, rev=None, **opts):
5262 """output the current or given revision of the project manifest
5194 """output the current or given revision of the project manifest
5263
5195
5264 Print a list of version controlled files for the given revision.
5196 Print a list of version controlled files for the given revision.
5265 If no revision is given, the first parent of the working directory
5197 If no revision is given, the first parent of the working directory
5266 is used, or the null revision if no revision is checked out.
5198 is used, or the null revision if no revision is checked out.
5267
5199
5268 With -v, print file permissions, symlink and executable bits.
5200 With -v, print file permissions, symlink and executable bits.
5269 With --debug, print file revision hashes.
5201 With --debug, print file revision hashes.
5270
5202
5271 If option --all is specified, the list of all files from all revisions
5203 If option --all is specified, the list of all files from all revisions
5272 is printed. This includes deleted and renamed files.
5204 is printed. This includes deleted and renamed files.
5273
5205
5274 Returns 0 on success.
5206 Returns 0 on success.
5275 """
5207 """
5276
5208
5277 fm = ui.formatter('manifest', opts)
5209 fm = ui.formatter('manifest', opts)
5278
5210
5279 if opts.get('all'):
5211 if opts.get('all'):
5280 if rev or node:
5212 if rev or node:
5281 raise error.Abort(_("can't specify a revision with --all"))
5213 raise error.Abort(_("can't specify a revision with --all"))
5282
5214
5283 res = []
5215 res = []
5284 prefix = "data/"
5216 prefix = "data/"
5285 suffix = ".i"
5217 suffix = ".i"
5286 plen = len(prefix)
5218 plen = len(prefix)
5287 slen = len(suffix)
5219 slen = len(suffix)
5288 with repo.lock():
5220 with repo.lock():
5289 for fn, b, size in repo.store.datafiles():
5221 for fn, b, size in repo.store.datafiles():
5290 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5222 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5291 res.append(fn[plen:-slen])
5223 res.append(fn[plen:-slen])
5292 for f in res:
5224 for f in res:
5293 fm.startitem()
5225 fm.startitem()
5294 fm.write("path", '%s\n', f)
5226 fm.write("path", '%s\n', f)
5295 fm.end()
5227 fm.end()
5296 return
5228 return
5297
5229
5298 if rev and node:
5230 if rev and node:
5299 raise error.Abort(_("please specify just one revision"))
5231 raise error.Abort(_("please specify just one revision"))
5300
5232
5301 if not node:
5233 if not node:
5302 node = rev
5234 node = rev
5303
5235
5304 char = {'l': '@', 'x': '*', '': ''}
5236 char = {'l': '@', 'x': '*', '': ''}
5305 mode = {'l': '644', 'x': '755', '': '644'}
5237 mode = {'l': '644', 'x': '755', '': '644'}
5306 ctx = scmutil.revsingle(repo, node)
5238 ctx = scmutil.revsingle(repo, node)
5307 mf = ctx.manifest()
5239 mf = ctx.manifest()
5308 for f in ctx:
5240 for f in ctx:
5309 fm.startitem()
5241 fm.startitem()
5310 fl = ctx[f].flags()
5242 fl = ctx[f].flags()
5311 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5243 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5312 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5244 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5313 fm.write('path', '%s\n', f)
5245 fm.write('path', '%s\n', f)
5314 fm.end()
5246 fm.end()
5315
5247
5316 @command('^merge',
5248 @command('^merge',
5317 [('f', 'force', None,
5249 [('f', 'force', None,
5318 _('force a merge including outstanding changes (DEPRECATED)')),
5250 _('force a merge including outstanding changes (DEPRECATED)')),
5319 ('r', 'rev', '', _('revision to merge'), _('REV')),
5251 ('r', 'rev', '', _('revision to merge'), _('REV')),
5320 ('P', 'preview', None,
5252 ('P', 'preview', None,
5321 _('review revisions to merge (no merge is performed)'))
5253 _('review revisions to merge (no merge is performed)'))
5322 ] + mergetoolopts,
5254 ] + mergetoolopts,
5323 _('[-P] [[-r] REV]'))
5255 _('[-P] [[-r] REV]'))
5324 def merge(ui, repo, node=None, **opts):
5256 def merge(ui, repo, node=None, **opts):
5325 """merge another revision into working directory
5257 """merge another revision into working directory
5326
5258
5327 The current working directory is updated with all changes made in
5259 The current working directory is updated with all changes made in
5328 the requested revision since the last common predecessor revision.
5260 the requested revision since the last common predecessor revision.
5329
5261
5330 Files that changed between either parent are marked as changed for
5262 Files that changed between either parent are marked as changed for
5331 the next commit and a commit must be performed before any further
5263 the next commit and a commit must be performed before any further
5332 updates to the repository are allowed. The next commit will have
5264 updates to the repository are allowed. The next commit will have
5333 two parents.
5265 two parents.
5334
5266
5335 ``--tool`` can be used to specify the merge tool used for file
5267 ``--tool`` can be used to specify the merge tool used for file
5336 merges. It overrides the HGMERGE environment variable and your
5268 merges. It overrides the HGMERGE environment variable and your
5337 configuration files. See :hg:`help merge-tools` for options.
5269 configuration files. See :hg:`help merge-tools` for options.
5338
5270
5339 If no revision is specified, the working directory's parent is a
5271 If no revision is specified, the working directory's parent is a
5340 head revision, and the current branch contains exactly one other
5272 head revision, and the current branch contains exactly one other
5341 head, the other head is merged with by default. Otherwise, an
5273 head, the other head is merged with by default. Otherwise, an
5342 explicit revision with which to merge with must be provided.
5274 explicit revision with which to merge with must be provided.
5343
5275
5344 See :hg:`help resolve` for information on handling file conflicts.
5276 See :hg:`help resolve` for information on handling file conflicts.
5345
5277
5346 To undo an uncommitted merge, use :hg:`update --clean .` which
5278 To undo an uncommitted merge, use :hg:`update --clean .` which
5347 will check out a clean copy of the original merge parent, losing
5279 will check out a clean copy of the original merge parent, losing
5348 all changes.
5280 all changes.
5349
5281
5350 Returns 0 on success, 1 if there are unresolved files.
5282 Returns 0 on success, 1 if there are unresolved files.
5351 """
5283 """
5352
5284
5353 if opts.get('rev') and node:
5285 if opts.get('rev') and node:
5354 raise error.Abort(_("please specify just one revision"))
5286 raise error.Abort(_("please specify just one revision"))
5355 if not node:
5287 if not node:
5356 node = opts.get('rev')
5288 node = opts.get('rev')
5357
5289
5358 if node:
5290 if node:
5359 node = scmutil.revsingle(repo, node).node()
5291 node = scmutil.revsingle(repo, node).node()
5360
5292
5361 if not node:
5293 if not node:
5362 node = repo[destutil.destmerge(repo)].node()
5294 node = repo[destutil.destmerge(repo)].node()
5363
5295
5364 if opts.get('preview'):
5296 if opts.get('preview'):
5365 # find nodes that are ancestors of p2 but not of p1
5297 # find nodes that are ancestors of p2 but not of p1
5366 p1 = repo.lookup('.')
5298 p1 = repo.lookup('.')
5367 p2 = repo.lookup(node)
5299 p2 = repo.lookup(node)
5368 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5300 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5369
5301
5370 displayer = cmdutil.show_changeset(ui, repo, opts)
5302 displayer = cmdutil.show_changeset(ui, repo, opts)
5371 for node in nodes:
5303 for node in nodes:
5372 displayer.show(repo[node])
5304 displayer.show(repo[node])
5373 displayer.close()
5305 displayer.close()
5374 return 0
5306 return 0
5375
5307
5376 try:
5308 try:
5377 # ui.forcemerge is an internal variable, do not document
5309 # ui.forcemerge is an internal variable, do not document
5378 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5310 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5379 force = opts.get('force')
5311 force = opts.get('force')
5380 labels = ['working copy', 'merge rev']
5312 labels = ['working copy', 'merge rev']
5381 return hg.merge(repo, node, force=force, mergeforce=force,
5313 return hg.merge(repo, node, force=force, mergeforce=force,
5382 labels=labels)
5314 labels=labels)
5383 finally:
5315 finally:
5384 ui.setconfig('ui', 'forcemerge', '', 'merge')
5316 ui.setconfig('ui', 'forcemerge', '', 'merge')
5385
5317
5386 @command('outgoing|out',
5318 @command('outgoing|out',
5387 [('f', 'force', None, _('run even when the destination is unrelated')),
5319 [('f', 'force', None, _('run even when the destination is unrelated')),
5388 ('r', 'rev', [],
5320 ('r', 'rev', [],
5389 _('a changeset intended to be included in the destination'), _('REV')),
5321 _('a changeset intended to be included in the destination'), _('REV')),
5390 ('n', 'newest-first', None, _('show newest record first')),
5322 ('n', 'newest-first', None, _('show newest record first')),
5391 ('B', 'bookmarks', False, _('compare bookmarks')),
5323 ('B', 'bookmarks', False, _('compare bookmarks')),
5392 ('b', 'branch', [], _('a specific branch you would like to push'),
5324 ('b', 'branch', [], _('a specific branch you would like to push'),
5393 _('BRANCH')),
5325 _('BRANCH')),
5394 ] + logopts + remoteopts + subrepoopts,
5326 ] + logopts + remoteopts + subrepoopts,
5395 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5327 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5396 def outgoing(ui, repo, dest=None, **opts):
5328 def outgoing(ui, repo, dest=None, **opts):
5397 """show changesets not found in the destination
5329 """show changesets not found in the destination
5398
5330
5399 Show changesets not found in the specified destination repository
5331 Show changesets not found in the specified destination repository
5400 or the default push location. These are the changesets that would
5332 or the default push location. These are the changesets that would
5401 be pushed if a push was requested.
5333 be pushed if a push was requested.
5402
5334
5403 See pull for details of valid destination formats.
5335 See pull for details of valid destination formats.
5404
5336
5405 .. container:: verbose
5337 .. container:: verbose
5406
5338
5407 With -B/--bookmarks, the result of bookmark comparison between
5339 With -B/--bookmarks, the result of bookmark comparison between
5408 local and remote repositories is displayed. With -v/--verbose,
5340 local and remote repositories is displayed. With -v/--verbose,
5409 status is also displayed for each bookmark like below::
5341 status is also displayed for each bookmark like below::
5410
5342
5411 BM1 01234567890a added
5343 BM1 01234567890a added
5412 BM2 deleted
5344 BM2 deleted
5413 BM3 234567890abc advanced
5345 BM3 234567890abc advanced
5414 BM4 34567890abcd diverged
5346 BM4 34567890abcd diverged
5415 BM5 4567890abcde changed
5347 BM5 4567890abcde changed
5416
5348
5417 The action taken when pushing depends on the
5349 The action taken when pushing depends on the
5418 status of each bookmark:
5350 status of each bookmark:
5419
5351
5420 :``added``: push with ``-B`` will create it
5352 :``added``: push with ``-B`` will create it
5421 :``deleted``: push with ``-B`` will delete it
5353 :``deleted``: push with ``-B`` will delete it
5422 :``advanced``: push will update it
5354 :``advanced``: push will update it
5423 :``diverged``: push with ``-B`` will update it
5355 :``diverged``: push with ``-B`` will update it
5424 :``changed``: push with ``-B`` will update it
5356 :``changed``: push with ``-B`` will update it
5425
5357
5426 From the point of view of pushing behavior, bookmarks
5358 From the point of view of pushing behavior, bookmarks
5427 existing only in the remote repository are treated as
5359 existing only in the remote repository are treated as
5428 ``deleted``, even if it is in fact added remotely.
5360 ``deleted``, even if it is in fact added remotely.
5429
5361
5430 Returns 0 if there are outgoing changes, 1 otherwise.
5362 Returns 0 if there are outgoing changes, 1 otherwise.
5431 """
5363 """
5432 if opts.get('graph'):
5364 if opts.get('graph'):
5433 cmdutil.checkunsupportedgraphflags([], opts)
5365 cmdutil.checkunsupportedgraphflags([], opts)
5434 o, other = hg._outgoing(ui, repo, dest, opts)
5366 o, other = hg._outgoing(ui, repo, dest, opts)
5435 if not o:
5367 if not o:
5436 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5368 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5437 return
5369 return
5438
5370
5439 revdag = cmdutil.graphrevs(repo, o, opts)
5371 revdag = cmdutil.graphrevs(repo, o, opts)
5440 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5372 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5441 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5373 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5442 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5374 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5443 return 0
5375 return 0
5444
5376
5445 if opts.get('bookmarks'):
5377 if opts.get('bookmarks'):
5446 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5378 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5447 dest, branches = hg.parseurl(dest, opts.get('branch'))
5379 dest, branches = hg.parseurl(dest, opts.get('branch'))
5448 other = hg.peer(repo, opts, dest)
5380 other = hg.peer(repo, opts, dest)
5449 if 'bookmarks' not in other.listkeys('namespaces'):
5381 if 'bookmarks' not in other.listkeys('namespaces'):
5450 ui.warn(_("remote doesn't support bookmarks\n"))
5382 ui.warn(_("remote doesn't support bookmarks\n"))
5451 return 0
5383 return 0
5452 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5384 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5453 return bookmarks.outgoing(ui, repo, other)
5385 return bookmarks.outgoing(ui, repo, other)
5454
5386
5455 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5387 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5456 try:
5388 try:
5457 return hg.outgoing(ui, repo, dest, opts)
5389 return hg.outgoing(ui, repo, dest, opts)
5458 finally:
5390 finally:
5459 del repo._subtoppath
5391 del repo._subtoppath
5460
5392
5461 @command('parents',
5393 @command('parents',
5462 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5394 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5463 ] + templateopts,
5395 ] + templateopts,
5464 _('[-r REV] [FILE]'),
5396 _('[-r REV] [FILE]'),
5465 inferrepo=True)
5397 inferrepo=True)
5466 def parents(ui, repo, file_=None, **opts):
5398 def parents(ui, repo, file_=None, **opts):
5467 """show the parents of the working directory or revision (DEPRECATED)
5399 """show the parents of the working directory or revision (DEPRECATED)
5468
5400
5469 Print the working directory's parent revisions. If a revision is
5401 Print the working directory's parent revisions. If a revision is
5470 given via -r/--rev, the parent of that revision will be printed.
5402 given via -r/--rev, the parent of that revision will be printed.
5471 If a file argument is given, the revision in which the file was
5403 If a file argument is given, the revision in which the file was
5472 last changed (before the working directory revision or the
5404 last changed (before the working directory revision or the
5473 argument to --rev if given) is printed.
5405 argument to --rev if given) is printed.
5474
5406
5475 This command is equivalent to::
5407 This command is equivalent to::
5476
5408
5477 hg log -r "p1()+p2()" or
5409 hg log -r "p1()+p2()" or
5478 hg log -r "p1(REV)+p2(REV)" or
5410 hg log -r "p1(REV)+p2(REV)" or
5479 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5411 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5480 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5412 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5481
5413
5482 See :hg:`summary` and :hg:`help revsets` for related information.
5414 See :hg:`summary` and :hg:`help revsets` for related information.
5483
5415
5484 Returns 0 on success.
5416 Returns 0 on success.
5485 """
5417 """
5486
5418
5487 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5419 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5488
5420
5489 if file_:
5421 if file_:
5490 m = scmutil.match(ctx, (file_,), opts)
5422 m = scmutil.match(ctx, (file_,), opts)
5491 if m.anypats() or len(m.files()) != 1:
5423 if m.anypats() or len(m.files()) != 1:
5492 raise error.Abort(_('can only specify an explicit filename'))
5424 raise error.Abort(_('can only specify an explicit filename'))
5493 file_ = m.files()[0]
5425 file_ = m.files()[0]
5494 filenodes = []
5426 filenodes = []
5495 for cp in ctx.parents():
5427 for cp in ctx.parents():
5496 if not cp:
5428 if not cp:
5497 continue
5429 continue
5498 try:
5430 try:
5499 filenodes.append(cp.filenode(file_))
5431 filenodes.append(cp.filenode(file_))
5500 except error.LookupError:
5432 except error.LookupError:
5501 pass
5433 pass
5502 if not filenodes:
5434 if not filenodes:
5503 raise error.Abort(_("'%s' not found in manifest!") % file_)
5435 raise error.Abort(_("'%s' not found in manifest!") % file_)
5504 p = []
5436 p = []
5505 for fn in filenodes:
5437 for fn in filenodes:
5506 fctx = repo.filectx(file_, fileid=fn)
5438 fctx = repo.filectx(file_, fileid=fn)
5507 p.append(fctx.node())
5439 p.append(fctx.node())
5508 else:
5440 else:
5509 p = [cp.node() for cp in ctx.parents()]
5441 p = [cp.node() for cp in ctx.parents()]
5510
5442
5511 displayer = cmdutil.show_changeset(ui, repo, opts)
5443 displayer = cmdutil.show_changeset(ui, repo, opts)
5512 for n in p:
5444 for n in p:
5513 if n != nullid:
5445 if n != nullid:
5514 displayer.show(repo[n])
5446 displayer.show(repo[n])
5515 displayer.close()
5447 displayer.close()
5516
5448
5517 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5449 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5518 def paths(ui, repo, search=None, **opts):
5450 def paths(ui, repo, search=None, **opts):
5519 """show aliases for remote repositories
5451 """show aliases for remote repositories
5520
5452
5521 Show definition of symbolic path name NAME. If no name is given,
5453 Show definition of symbolic path name NAME. If no name is given,
5522 show definition of all available names.
5454 show definition of all available names.
5523
5455
5524 Option -q/--quiet suppresses all output when searching for NAME
5456 Option -q/--quiet suppresses all output when searching for NAME
5525 and shows only the path names when listing all definitions.
5457 and shows only the path names when listing all definitions.
5526
5458
5527 Path names are defined in the [paths] section of your
5459 Path names are defined in the [paths] section of your
5528 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5460 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5529 repository, ``.hg/hgrc`` is used, too.
5461 repository, ``.hg/hgrc`` is used, too.
5530
5462
5531 The path names ``default`` and ``default-push`` have a special
5463 The path names ``default`` and ``default-push`` have a special
5532 meaning. When performing a push or pull operation, they are used
5464 meaning. When performing a push or pull operation, they are used
5533 as fallbacks if no location is specified on the command-line.
5465 as fallbacks if no location is specified on the command-line.
5534 When ``default-push`` is set, it will be used for push and
5466 When ``default-push`` is set, it will be used for push and
5535 ``default`` will be used for pull; otherwise ``default`` is used
5467 ``default`` will be used for pull; otherwise ``default`` is used
5536 as the fallback for both. When cloning a repository, the clone
5468 as the fallback for both. When cloning a repository, the clone
5537 source is written as ``default`` in ``.hg/hgrc``.
5469 source is written as ``default`` in ``.hg/hgrc``.
5538
5470
5539 .. note::
5471 .. note::
5540
5472
5541 ``default`` and ``default-push`` apply to all inbound (e.g.
5473 ``default`` and ``default-push`` apply to all inbound (e.g.
5542 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5474 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5543 and :hg:`bundle`) operations.
5475 and :hg:`bundle`) operations.
5544
5476
5545 See :hg:`help urls` for more information.
5477 See :hg:`help urls` for more information.
5546
5478
5547 Returns 0 on success.
5479 Returns 0 on success.
5548 """
5480 """
5549 if search:
5481 if search:
5550 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5482 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5551 if name == search]
5483 if name == search]
5552 else:
5484 else:
5553 pathitems = sorted(ui.paths.iteritems())
5485 pathitems = sorted(ui.paths.iteritems())
5554
5486
5555 fm = ui.formatter('paths', opts)
5487 fm = ui.formatter('paths', opts)
5556 if fm.isplain():
5488 if fm.isplain():
5557 hidepassword = util.hidepassword
5489 hidepassword = util.hidepassword
5558 else:
5490 else:
5559 hidepassword = str
5491 hidepassword = str
5560 if ui.quiet:
5492 if ui.quiet:
5561 namefmt = '%s\n'
5493 namefmt = '%s\n'
5562 else:
5494 else:
5563 namefmt = '%s = '
5495 namefmt = '%s = '
5564 showsubopts = not search and not ui.quiet
5496 showsubopts = not search and not ui.quiet
5565
5497
5566 for name, path in pathitems:
5498 for name, path in pathitems:
5567 fm.startitem()
5499 fm.startitem()
5568 fm.condwrite(not search, 'name', namefmt, name)
5500 fm.condwrite(not search, 'name', namefmt, name)
5569 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5501 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5570 for subopt, value in sorted(path.suboptions.items()):
5502 for subopt, value in sorted(path.suboptions.items()):
5571 assert subopt not in ('name', 'url')
5503 assert subopt not in ('name', 'url')
5572 if showsubopts:
5504 if showsubopts:
5573 fm.plain('%s:%s = ' % (name, subopt))
5505 fm.plain('%s:%s = ' % (name, subopt))
5574 fm.condwrite(showsubopts, subopt, '%s\n', value)
5506 fm.condwrite(showsubopts, subopt, '%s\n', value)
5575
5507
5576 fm.end()
5508 fm.end()
5577
5509
5578 if search and not pathitems:
5510 if search and not pathitems:
5579 if not ui.quiet:
5511 if not ui.quiet:
5580 ui.warn(_("not found!\n"))
5512 ui.warn(_("not found!\n"))
5581 return 1
5513 return 1
5582 else:
5514 else:
5583 return 0
5515 return 0
5584
5516
5585 @command('phase',
5517 @command('phase',
5586 [('p', 'public', False, _('set changeset phase to public')),
5518 [('p', 'public', False, _('set changeset phase to public')),
5587 ('d', 'draft', False, _('set changeset phase to draft')),
5519 ('d', 'draft', False, _('set changeset phase to draft')),
5588 ('s', 'secret', False, _('set changeset phase to secret')),
5520 ('s', 'secret', False, _('set changeset phase to secret')),
5589 ('f', 'force', False, _('allow to move boundary backward')),
5521 ('f', 'force', False, _('allow to move boundary backward')),
5590 ('r', 'rev', [], _('target revision'), _('REV')),
5522 ('r', 'rev', [], _('target revision'), _('REV')),
5591 ],
5523 ],
5592 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5524 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5593 def phase(ui, repo, *revs, **opts):
5525 def phase(ui, repo, *revs, **opts):
5594 """set or show the current phase name
5526 """set or show the current phase name
5595
5527
5596 With no argument, show the phase name of the current revision(s).
5528 With no argument, show the phase name of the current revision(s).
5597
5529
5598 With one of -p/--public, -d/--draft or -s/--secret, change the
5530 With one of -p/--public, -d/--draft or -s/--secret, change the
5599 phase value of the specified revisions.
5531 phase value of the specified revisions.
5600
5532
5601 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5533 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5602 lower phase to an higher phase. Phases are ordered as follows::
5534 lower phase to an higher phase. Phases are ordered as follows::
5603
5535
5604 public < draft < secret
5536 public < draft < secret
5605
5537
5606 Returns 0 on success, 1 if some phases could not be changed.
5538 Returns 0 on success, 1 if some phases could not be changed.
5607
5539
5608 (For more information about the phases concept, see :hg:`help phases`.)
5540 (For more information about the phases concept, see :hg:`help phases`.)
5609 """
5541 """
5610 # search for a unique phase argument
5542 # search for a unique phase argument
5611 targetphase = None
5543 targetphase = None
5612 for idx, name in enumerate(phases.phasenames):
5544 for idx, name in enumerate(phases.phasenames):
5613 if opts[name]:
5545 if opts[name]:
5614 if targetphase is not None:
5546 if targetphase is not None:
5615 raise error.Abort(_('only one phase can be specified'))
5547 raise error.Abort(_('only one phase can be specified'))
5616 targetphase = idx
5548 targetphase = idx
5617
5549
5618 # look for specified revision
5550 # look for specified revision
5619 revs = list(revs)
5551 revs = list(revs)
5620 revs.extend(opts['rev'])
5552 revs.extend(opts['rev'])
5621 if not revs:
5553 if not revs:
5622 # display both parents as the second parent phase can influence
5554 # display both parents as the second parent phase can influence
5623 # the phase of a merge commit
5555 # the phase of a merge commit
5624 revs = [c.rev() for c in repo[None].parents()]
5556 revs = [c.rev() for c in repo[None].parents()]
5625
5557
5626 revs = scmutil.revrange(repo, revs)
5558 revs = scmutil.revrange(repo, revs)
5627
5559
5628 lock = None
5560 lock = None
5629 ret = 0
5561 ret = 0
5630 if targetphase is None:
5562 if targetphase is None:
5631 # display
5563 # display
5632 for r in revs:
5564 for r in revs:
5633 ctx = repo[r]
5565 ctx = repo[r]
5634 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5566 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5635 else:
5567 else:
5636 tr = None
5568 tr = None
5637 lock = repo.lock()
5569 lock = repo.lock()
5638 try:
5570 try:
5639 tr = repo.transaction("phase")
5571 tr = repo.transaction("phase")
5640 # set phase
5572 # set phase
5641 if not revs:
5573 if not revs:
5642 raise error.Abort(_('empty revision set'))
5574 raise error.Abort(_('empty revision set'))
5643 nodes = [repo[r].node() for r in revs]
5575 nodes = [repo[r].node() for r in revs]
5644 # moving revision from public to draft may hide them
5576 # moving revision from public to draft may hide them
5645 # We have to check result on an unfiltered repository
5577 # We have to check result on an unfiltered repository
5646 unfi = repo.unfiltered()
5578 unfi = repo.unfiltered()
5647 getphase = unfi._phasecache.phase
5579 getphase = unfi._phasecache.phase
5648 olddata = [getphase(unfi, r) for r in unfi]
5580 olddata = [getphase(unfi, r) for r in unfi]
5649 phases.advanceboundary(repo, tr, targetphase, nodes)
5581 phases.advanceboundary(repo, tr, targetphase, nodes)
5650 if opts['force']:
5582 if opts['force']:
5651 phases.retractboundary(repo, tr, targetphase, nodes)
5583 phases.retractboundary(repo, tr, targetphase, nodes)
5652 tr.close()
5584 tr.close()
5653 finally:
5585 finally:
5654 if tr is not None:
5586 if tr is not None:
5655 tr.release()
5587 tr.release()
5656 lock.release()
5588 lock.release()
5657 getphase = unfi._phasecache.phase
5589 getphase = unfi._phasecache.phase
5658 newdata = [getphase(unfi, r) for r in unfi]
5590 newdata = [getphase(unfi, r) for r in unfi]
5659 changes = sum(newdata[r] != olddata[r] for r in unfi)
5591 changes = sum(newdata[r] != olddata[r] for r in unfi)
5660 cl = unfi.changelog
5592 cl = unfi.changelog
5661 rejected = [n for n in nodes
5593 rejected = [n for n in nodes
5662 if newdata[cl.rev(n)] < targetphase]
5594 if newdata[cl.rev(n)] < targetphase]
5663 if rejected:
5595 if rejected:
5664 ui.warn(_('cannot move %i changesets to a higher '
5596 ui.warn(_('cannot move %i changesets to a higher '
5665 'phase, use --force\n') % len(rejected))
5597 'phase, use --force\n') % len(rejected))
5666 ret = 1
5598 ret = 1
5667 if changes:
5599 if changes:
5668 msg = _('phase changed for %i changesets\n') % changes
5600 msg = _('phase changed for %i changesets\n') % changes
5669 if ret:
5601 if ret:
5670 ui.status(msg)
5602 ui.status(msg)
5671 else:
5603 else:
5672 ui.note(msg)
5604 ui.note(msg)
5673 else:
5605 else:
5674 ui.warn(_('no phases changed\n'))
5606 ui.warn(_('no phases changed\n'))
5675 return ret
5607 return ret
5676
5608
5677 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5609 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5678 """Run after a changegroup has been added via pull/unbundle
5610 """Run after a changegroup has been added via pull/unbundle
5679
5611
5680 This takes arguments below:
5612 This takes arguments below:
5681
5613
5682 :modheads: change of heads by pull/unbundle
5614 :modheads: change of heads by pull/unbundle
5683 :optupdate: updating working directory is needed or not
5615 :optupdate: updating working directory is needed or not
5684 :checkout: update destination revision (or None to default destination)
5616 :checkout: update destination revision (or None to default destination)
5685 :brev: a name, which might be a bookmark to be activated after updating
5617 :brev: a name, which might be a bookmark to be activated after updating
5686 """
5618 """
5687 if modheads == 0:
5619 if modheads == 0:
5688 return
5620 return
5689 if optupdate:
5621 if optupdate:
5690 try:
5622 try:
5691 return hg.updatetotally(ui, repo, checkout, brev)
5623 return hg.updatetotally(ui, repo, checkout, brev)
5692 except error.UpdateAbort as inst:
5624 except error.UpdateAbort as inst:
5693 msg = _("not updating: %s") % str(inst)
5625 msg = _("not updating: %s") % str(inst)
5694 hint = inst.hint
5626 hint = inst.hint
5695 raise error.UpdateAbort(msg, hint=hint)
5627 raise error.UpdateAbort(msg, hint=hint)
5696 if modheads > 1:
5628 if modheads > 1:
5697 currentbranchheads = len(repo.branchheads())
5629 currentbranchheads = len(repo.branchheads())
5698 if currentbranchheads == modheads:
5630 if currentbranchheads == modheads:
5699 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5631 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5700 elif currentbranchheads > 1:
5632 elif currentbranchheads > 1:
5701 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5633 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5702 "merge)\n"))
5634 "merge)\n"))
5703 else:
5635 else:
5704 ui.status(_("(run 'hg heads' to see heads)\n"))
5636 ui.status(_("(run 'hg heads' to see heads)\n"))
5705 else:
5637 else:
5706 ui.status(_("(run 'hg update' to get a working copy)\n"))
5638 ui.status(_("(run 'hg update' to get a working copy)\n"))
5707
5639
5708 @command('^pull',
5640 @command('^pull',
5709 [('u', 'update', None,
5641 [('u', 'update', None,
5710 _('update to new branch head if changesets were pulled')),
5642 _('update to new branch head if changesets were pulled')),
5711 ('f', 'force', None, _('run even when remote repository is unrelated')),
5643 ('f', 'force', None, _('run even when remote repository is unrelated')),
5712 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5644 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5713 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5645 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5714 ('b', 'branch', [], _('a specific branch you would like to pull'),
5646 ('b', 'branch', [], _('a specific branch you would like to pull'),
5715 _('BRANCH')),
5647 _('BRANCH')),
5716 ] + remoteopts,
5648 ] + remoteopts,
5717 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5649 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5718 def pull(ui, repo, source="default", **opts):
5650 def pull(ui, repo, source="default", **opts):
5719 """pull changes from the specified source
5651 """pull changes from the specified source
5720
5652
5721 Pull changes from a remote repository to a local one.
5653 Pull changes from a remote repository to a local one.
5722
5654
5723 This finds all changes from the repository at the specified path
5655 This finds all changes from the repository at the specified path
5724 or URL and adds them to a local repository (the current one unless
5656 or URL and adds them to a local repository (the current one unless
5725 -R is specified). By default, this does not update the copy of the
5657 -R is specified). By default, this does not update the copy of the
5726 project in the working directory.
5658 project in the working directory.
5727
5659
5728 Use :hg:`incoming` if you want to see what would have been added
5660 Use :hg:`incoming` if you want to see what would have been added
5729 by a pull at the time you issued this command. If you then decide
5661 by a pull at the time you issued this command. If you then decide
5730 to add those changes to the repository, you should use :hg:`pull
5662 to add those changes to the repository, you should use :hg:`pull
5731 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5663 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5732
5664
5733 If SOURCE is omitted, the 'default' path will be used.
5665 If SOURCE is omitted, the 'default' path will be used.
5734 See :hg:`help urls` for more information.
5666 See :hg:`help urls` for more information.
5735
5667
5736 Specifying bookmark as ``.`` is equivalent to specifying the active
5668 Specifying bookmark as ``.`` is equivalent to specifying the active
5737 bookmark's name.
5669 bookmark's name.
5738
5670
5739 Returns 0 on success, 1 if an update had unresolved files.
5671 Returns 0 on success, 1 if an update had unresolved files.
5740 """
5672 """
5741 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5673 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5742 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5674 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5743 other = hg.peer(repo, opts, source)
5675 other = hg.peer(repo, opts, source)
5744 try:
5676 try:
5745 revs, checkout = hg.addbranchrevs(repo, other, branches,
5677 revs, checkout = hg.addbranchrevs(repo, other, branches,
5746 opts.get('rev'))
5678 opts.get('rev'))
5747
5679
5748
5680
5749 pullopargs = {}
5681 pullopargs = {}
5750 if opts.get('bookmark'):
5682 if opts.get('bookmark'):
5751 if not revs:
5683 if not revs:
5752 revs = []
5684 revs = []
5753 # The list of bookmark used here is not the one used to actually
5685 # The list of bookmark used here is not the one used to actually
5754 # update the bookmark name. This can result in the revision pulled
5686 # update the bookmark name. This can result in the revision pulled
5755 # not ending up with the name of the bookmark because of a race
5687 # not ending up with the name of the bookmark because of a race
5756 # condition on the server. (See issue 4689 for details)
5688 # condition on the server. (See issue 4689 for details)
5757 remotebookmarks = other.listkeys('bookmarks')
5689 remotebookmarks = other.listkeys('bookmarks')
5758 pullopargs['remotebookmarks'] = remotebookmarks
5690 pullopargs['remotebookmarks'] = remotebookmarks
5759 for b in opts['bookmark']:
5691 for b in opts['bookmark']:
5760 b = repo._bookmarks.expandname(b)
5692 b = repo._bookmarks.expandname(b)
5761 if b not in remotebookmarks:
5693 if b not in remotebookmarks:
5762 raise error.Abort(_('remote bookmark %s not found!') % b)
5694 raise error.Abort(_('remote bookmark %s not found!') % b)
5763 revs.append(remotebookmarks[b])
5695 revs.append(remotebookmarks[b])
5764
5696
5765 if revs:
5697 if revs:
5766 try:
5698 try:
5767 # When 'rev' is a bookmark name, we cannot guarantee that it
5699 # When 'rev' is a bookmark name, we cannot guarantee that it
5768 # will be updated with that name because of a race condition
5700 # will be updated with that name because of a race condition
5769 # server side. (See issue 4689 for details)
5701 # server side. (See issue 4689 for details)
5770 oldrevs = revs
5702 oldrevs = revs
5771 revs = [] # actually, nodes
5703 revs = [] # actually, nodes
5772 for r in oldrevs:
5704 for r in oldrevs:
5773 node = other.lookup(r)
5705 node = other.lookup(r)
5774 revs.append(node)
5706 revs.append(node)
5775 if r == checkout:
5707 if r == checkout:
5776 checkout = node
5708 checkout = node
5777 except error.CapabilityError:
5709 except error.CapabilityError:
5778 err = _("other repository doesn't support revision lookup, "
5710 err = _("other repository doesn't support revision lookup, "
5779 "so a rev cannot be specified.")
5711 "so a rev cannot be specified.")
5780 raise error.Abort(err)
5712 raise error.Abort(err)
5781
5713
5782 pullopargs.update(opts.get('opargs', {}))
5714 pullopargs.update(opts.get('opargs', {}))
5783 modheads = exchange.pull(repo, other, heads=revs,
5715 modheads = exchange.pull(repo, other, heads=revs,
5784 force=opts.get('force'),
5716 force=opts.get('force'),
5785 bookmarks=opts.get('bookmark', ()),
5717 bookmarks=opts.get('bookmark', ()),
5786 opargs=pullopargs).cgresult
5718 opargs=pullopargs).cgresult
5787
5719
5788 # brev is a name, which might be a bookmark to be activated at
5720 # brev is a name, which might be a bookmark to be activated at
5789 # the end of the update. In other words, it is an explicit
5721 # the end of the update. In other words, it is an explicit
5790 # destination of the update
5722 # destination of the update
5791 brev = None
5723 brev = None
5792
5724
5793 if checkout:
5725 if checkout:
5794 checkout = str(repo.changelog.rev(checkout))
5726 checkout = str(repo.changelog.rev(checkout))
5795
5727
5796 # order below depends on implementation of
5728 # order below depends on implementation of
5797 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5729 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5798 # because 'checkout' is determined without it.
5730 # because 'checkout' is determined without it.
5799 if opts.get('rev'):
5731 if opts.get('rev'):
5800 brev = opts['rev'][0]
5732 brev = opts['rev'][0]
5801 elif opts.get('branch'):
5733 elif opts.get('branch'):
5802 brev = opts['branch'][0]
5734 brev = opts['branch'][0]
5803 else:
5735 else:
5804 brev = branches[0]
5736 brev = branches[0]
5805 repo._subtoppath = source
5737 repo._subtoppath = source
5806 try:
5738 try:
5807 ret = postincoming(ui, repo, modheads, opts.get('update'),
5739 ret = postincoming(ui, repo, modheads, opts.get('update'),
5808 checkout, brev)
5740 checkout, brev)
5809
5741
5810 finally:
5742 finally:
5811 del repo._subtoppath
5743 del repo._subtoppath
5812
5744
5813 finally:
5745 finally:
5814 other.close()
5746 other.close()
5815 return ret
5747 return ret
5816
5748
5817 @command('^push',
5749 @command('^push',
5818 [('f', 'force', None, _('force push')),
5750 [('f', 'force', None, _('force push')),
5819 ('r', 'rev', [],
5751 ('r', 'rev', [],
5820 _('a changeset intended to be included in the destination'),
5752 _('a changeset intended to be included in the destination'),
5821 _('REV')),
5753 _('REV')),
5822 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5754 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5823 ('b', 'branch', [],
5755 ('b', 'branch', [],
5824 _('a specific branch you would like to push'), _('BRANCH')),
5756 _('a specific branch you would like to push'), _('BRANCH')),
5825 ('', 'new-branch', False, _('allow pushing a new branch')),
5757 ('', 'new-branch', False, _('allow pushing a new branch')),
5826 ] + remoteopts,
5758 ] + remoteopts,
5827 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5759 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5828 def push(ui, repo, dest=None, **opts):
5760 def push(ui, repo, dest=None, **opts):
5829 """push changes to the specified destination
5761 """push changes to the specified destination
5830
5762
5831 Push changesets from the local repository to the specified
5763 Push changesets from the local repository to the specified
5832 destination.
5764 destination.
5833
5765
5834 This operation is symmetrical to pull: it is identical to a pull
5766 This operation is symmetrical to pull: it is identical to a pull
5835 in the destination repository from the current one.
5767 in the destination repository from the current one.
5836
5768
5837 By default, push will not allow creation of new heads at the
5769 By default, push will not allow creation of new heads at the
5838 destination, since multiple heads would make it unclear which head
5770 destination, since multiple heads would make it unclear which head
5839 to use. In this situation, it is recommended to pull and merge
5771 to use. In this situation, it is recommended to pull and merge
5840 before pushing.
5772 before pushing.
5841
5773
5842 Use --new-branch if you want to allow push to create a new named
5774 Use --new-branch if you want to allow push to create a new named
5843 branch that is not present at the destination. This allows you to
5775 branch that is not present at the destination. This allows you to
5844 only create a new branch without forcing other changes.
5776 only create a new branch without forcing other changes.
5845
5777
5846 .. note::
5778 .. note::
5847
5779
5848 Extra care should be taken with the -f/--force option,
5780 Extra care should be taken with the -f/--force option,
5849 which will push all new heads on all branches, an action which will
5781 which will push all new heads on all branches, an action which will
5850 almost always cause confusion for collaborators.
5782 almost always cause confusion for collaborators.
5851
5783
5852 If -r/--rev is used, the specified revision and all its ancestors
5784 If -r/--rev is used, the specified revision and all its ancestors
5853 will be pushed to the remote repository.
5785 will be pushed to the remote repository.
5854
5786
5855 If -B/--bookmark is used, the specified bookmarked revision, its
5787 If -B/--bookmark is used, the specified bookmarked revision, its
5856 ancestors, and the bookmark will be pushed to the remote
5788 ancestors, and the bookmark will be pushed to the remote
5857 repository. Specifying ``.`` is equivalent to specifying the active
5789 repository. Specifying ``.`` is equivalent to specifying the active
5858 bookmark's name.
5790 bookmark's name.
5859
5791
5860 Please see :hg:`help urls` for important details about ``ssh://``
5792 Please see :hg:`help urls` for important details about ``ssh://``
5861 URLs. If DESTINATION is omitted, a default path will be used.
5793 URLs. If DESTINATION is omitted, a default path will be used.
5862
5794
5863 Returns 0 if push was successful, 1 if nothing to push.
5795 Returns 0 if push was successful, 1 if nothing to push.
5864 """
5796 """
5865
5797
5866 if opts.get('bookmark'):
5798 if opts.get('bookmark'):
5867 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5799 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5868 for b in opts['bookmark']:
5800 for b in opts['bookmark']:
5869 # translate -B options to -r so changesets get pushed
5801 # translate -B options to -r so changesets get pushed
5870 b = repo._bookmarks.expandname(b)
5802 b = repo._bookmarks.expandname(b)
5871 if b in repo._bookmarks:
5803 if b in repo._bookmarks:
5872 opts.setdefault('rev', []).append(b)
5804 opts.setdefault('rev', []).append(b)
5873 else:
5805 else:
5874 # if we try to push a deleted bookmark, translate it to null
5806 # if we try to push a deleted bookmark, translate it to null
5875 # this lets simultaneous -r, -b options continue working
5807 # this lets simultaneous -r, -b options continue working
5876 opts.setdefault('rev', []).append("null")
5808 opts.setdefault('rev', []).append("null")
5877
5809
5878 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5810 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5879 if not path:
5811 if not path:
5880 raise error.Abort(_('default repository not configured!'),
5812 raise error.Abort(_('default repository not configured!'),
5881 hint=_("see 'hg help config.paths'"))
5813 hint=_("see 'hg help config.paths'"))
5882 dest = path.pushloc or path.loc
5814 dest = path.pushloc or path.loc
5883 branches = (path.branch, opts.get('branch') or [])
5815 branches = (path.branch, opts.get('branch') or [])
5884 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5816 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5885 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5817 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5886 other = hg.peer(repo, opts, dest)
5818 other = hg.peer(repo, opts, dest)
5887
5819
5888 if revs:
5820 if revs:
5889 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5821 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5890 if not revs:
5822 if not revs:
5891 raise error.Abort(_("specified revisions evaluate to an empty set"),
5823 raise error.Abort(_("specified revisions evaluate to an empty set"),
5892 hint=_("use different revision arguments"))
5824 hint=_("use different revision arguments"))
5893 elif path.pushrev:
5825 elif path.pushrev:
5894 # It doesn't make any sense to specify ancestor revisions. So limit
5826 # It doesn't make any sense to specify ancestor revisions. So limit
5895 # to DAG heads to make discovery simpler.
5827 # to DAG heads to make discovery simpler.
5896 expr = revset.formatspec('heads(%r)', path.pushrev)
5828 expr = revset.formatspec('heads(%r)', path.pushrev)
5897 revs = scmutil.revrange(repo, [expr])
5829 revs = scmutil.revrange(repo, [expr])
5898 revs = [repo[rev].node() for rev in revs]
5830 revs = [repo[rev].node() for rev in revs]
5899 if not revs:
5831 if not revs:
5900 raise error.Abort(_('default push revset for path evaluates to an '
5832 raise error.Abort(_('default push revset for path evaluates to an '
5901 'empty set'))
5833 'empty set'))
5902
5834
5903 repo._subtoppath = dest
5835 repo._subtoppath = dest
5904 try:
5836 try:
5905 # push subrepos depth-first for coherent ordering
5837 # push subrepos depth-first for coherent ordering
5906 c = repo['']
5838 c = repo['']
5907 subs = c.substate # only repos that are committed
5839 subs = c.substate # only repos that are committed
5908 for s in sorted(subs):
5840 for s in sorted(subs):
5909 result = c.sub(s).push(opts)
5841 result = c.sub(s).push(opts)
5910 if result == 0:
5842 if result == 0:
5911 return not result
5843 return not result
5912 finally:
5844 finally:
5913 del repo._subtoppath
5845 del repo._subtoppath
5914 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5846 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5915 newbranch=opts.get('new_branch'),
5847 newbranch=opts.get('new_branch'),
5916 bookmarks=opts.get('bookmark', ()),
5848 bookmarks=opts.get('bookmark', ()),
5917 opargs=opts.get('opargs'))
5849 opargs=opts.get('opargs'))
5918
5850
5919 result = not pushop.cgresult
5851 result = not pushop.cgresult
5920
5852
5921 if pushop.bkresult is not None:
5853 if pushop.bkresult is not None:
5922 if pushop.bkresult == 2:
5854 if pushop.bkresult == 2:
5923 result = 2
5855 result = 2
5924 elif not result and pushop.bkresult:
5856 elif not result and pushop.bkresult:
5925 result = 2
5857 result = 2
5926
5858
5927 return result
5859 return result
5928
5860
5929 @command('recover', [])
5861 @command('recover', [])
5930 def recover(ui, repo):
5862 def recover(ui, repo):
5931 """roll back an interrupted transaction
5863 """roll back an interrupted transaction
5932
5864
5933 Recover from an interrupted commit or pull.
5865 Recover from an interrupted commit or pull.
5934
5866
5935 This command tries to fix the repository status after an
5867 This command tries to fix the repository status after an
5936 interrupted operation. It should only be necessary when Mercurial
5868 interrupted operation. It should only be necessary when Mercurial
5937 suggests it.
5869 suggests it.
5938
5870
5939 Returns 0 if successful, 1 if nothing to recover or verify fails.
5871 Returns 0 if successful, 1 if nothing to recover or verify fails.
5940 """
5872 """
5941 if repo.recover():
5873 if repo.recover():
5942 return hg.verify(repo)
5874 return hg.verify(repo)
5943 return 1
5875 return 1
5944
5876
5945 @command('^remove|rm',
5877 @command('^remove|rm',
5946 [('A', 'after', None, _('record delete for missing files')),
5878 [('A', 'after', None, _('record delete for missing files')),
5947 ('f', 'force', None,
5879 ('f', 'force', None,
5948 _('forget added files, delete modified files')),
5880 _('forget added files, delete modified files')),
5949 ] + subrepoopts + walkopts,
5881 ] + subrepoopts + walkopts,
5950 _('[OPTION]... FILE...'),
5882 _('[OPTION]... FILE...'),
5951 inferrepo=True)
5883 inferrepo=True)
5952 def remove(ui, repo, *pats, **opts):
5884 def remove(ui, repo, *pats, **opts):
5953 """remove the specified files on the next commit
5885 """remove the specified files on the next commit
5954
5886
5955 Schedule the indicated files for removal from the current branch.
5887 Schedule the indicated files for removal from the current branch.
5956
5888
5957 This command schedules the files to be removed at the next commit.
5889 This command schedules the files to be removed at the next commit.
5958 To undo a remove before that, see :hg:`revert`. To undo added
5890 To undo a remove before that, see :hg:`revert`. To undo added
5959 files, see :hg:`forget`.
5891 files, see :hg:`forget`.
5960
5892
5961 .. container:: verbose
5893 .. container:: verbose
5962
5894
5963 -A/--after can be used to remove only files that have already
5895 -A/--after can be used to remove only files that have already
5964 been deleted, -f/--force can be used to force deletion, and -Af
5896 been deleted, -f/--force can be used to force deletion, and -Af
5965 can be used to remove files from the next revision without
5897 can be used to remove files from the next revision without
5966 deleting them from the working directory.
5898 deleting them from the working directory.
5967
5899
5968 The following table details the behavior of remove for different
5900 The following table details the behavior of remove for different
5969 file states (columns) and option combinations (rows). The file
5901 file states (columns) and option combinations (rows). The file
5970 states are Added [A], Clean [C], Modified [M] and Missing [!]
5902 states are Added [A], Clean [C], Modified [M] and Missing [!]
5971 (as reported by :hg:`status`). The actions are Warn, Remove
5903 (as reported by :hg:`status`). The actions are Warn, Remove
5972 (from branch) and Delete (from disk):
5904 (from branch) and Delete (from disk):
5973
5905
5974 ========= == == == ==
5906 ========= == == == ==
5975 opt/state A C M !
5907 opt/state A C M !
5976 ========= == == == ==
5908 ========= == == == ==
5977 none W RD W R
5909 none W RD W R
5978 -f R RD RD R
5910 -f R RD RD R
5979 -A W W W R
5911 -A W W W R
5980 -Af R R R R
5912 -Af R R R R
5981 ========= == == == ==
5913 ========= == == == ==
5982
5914
5983 .. note::
5915 .. note::
5984
5916
5985 :hg:`remove` never deletes files in Added [A] state from the
5917 :hg:`remove` never deletes files in Added [A] state from the
5986 working directory, not even if ``--force`` is specified.
5918 working directory, not even if ``--force`` is specified.
5987
5919
5988 Returns 0 on success, 1 if any warnings encountered.
5920 Returns 0 on success, 1 if any warnings encountered.
5989 """
5921 """
5990
5922
5991 after, force = opts.get('after'), opts.get('force')
5923 after, force = opts.get('after'), opts.get('force')
5992 if not pats and not after:
5924 if not pats and not after:
5993 raise error.Abort(_('no files specified'))
5925 raise error.Abort(_('no files specified'))
5994
5926
5995 m = scmutil.match(repo[None], pats, opts)
5927 m = scmutil.match(repo[None], pats, opts)
5996 subrepos = opts.get('subrepos')
5928 subrepos = opts.get('subrepos')
5997 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5929 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5998
5930
5999 @command('rename|move|mv',
5931 @command('rename|move|mv',
6000 [('A', 'after', None, _('record a rename that has already occurred')),
5932 [('A', 'after', None, _('record a rename that has already occurred')),
6001 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5933 ('f', 'force', None, _('forcibly copy over an existing managed file')),
6002 ] + walkopts + dryrunopts,
5934 ] + walkopts + dryrunopts,
6003 _('[OPTION]... SOURCE... DEST'))
5935 _('[OPTION]... SOURCE... DEST'))
6004 def rename(ui, repo, *pats, **opts):
5936 def rename(ui, repo, *pats, **opts):
6005 """rename files; equivalent of copy + remove
5937 """rename files; equivalent of copy + remove
6006
5938
6007 Mark dest as copies of sources; mark sources for deletion. If dest
5939 Mark dest as copies of sources; mark sources for deletion. If dest
6008 is a directory, copies are put in that directory. If dest is a
5940 is a directory, copies are put in that directory. If dest is a
6009 file, there can only be one source.
5941 file, there can only be one source.
6010
5942
6011 By default, this command copies the contents of files as they
5943 By default, this command copies the contents of files as they
6012 exist in the working directory. If invoked with -A/--after, the
5944 exist in the working directory. If invoked with -A/--after, the
6013 operation is recorded, but no copying is performed.
5945 operation is recorded, but no copying is performed.
6014
5946
6015 This command takes effect at the next commit. To undo a rename
5947 This command takes effect at the next commit. To undo a rename
6016 before that, see :hg:`revert`.
5948 before that, see :hg:`revert`.
6017
5949
6018 Returns 0 on success, 1 if errors are encountered.
5950 Returns 0 on success, 1 if errors are encountered.
6019 """
5951 """
6020 with repo.wlock(False):
5952 with repo.wlock(False):
6021 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5953 return cmdutil.copy(ui, repo, pats, opts, rename=True)
6022
5954
6023 @command('resolve',
5955 @command('resolve',
6024 [('a', 'all', None, _('select all unresolved files')),
5956 [('a', 'all', None, _('select all unresolved files')),
6025 ('l', 'list', None, _('list state of files needing merge')),
5957 ('l', 'list', None, _('list state of files needing merge')),
6026 ('m', 'mark', None, _('mark files as resolved')),
5958 ('m', 'mark', None, _('mark files as resolved')),
6027 ('u', 'unmark', None, _('mark files as unresolved')),
5959 ('u', 'unmark', None, _('mark files as unresolved')),
6028 ('n', 'no-status', None, _('hide status prefix'))]
5960 ('n', 'no-status', None, _('hide status prefix'))]
6029 + mergetoolopts + walkopts + formatteropts,
5961 + mergetoolopts + walkopts + formatteropts,
6030 _('[OPTION]... [FILE]...'),
5962 _('[OPTION]... [FILE]...'),
6031 inferrepo=True)
5963 inferrepo=True)
6032 def resolve(ui, repo, *pats, **opts):
5964 def resolve(ui, repo, *pats, **opts):
6033 """redo merges or set/view the merge status of files
5965 """redo merges or set/view the merge status of files
6034
5966
6035 Merges with unresolved conflicts are often the result of
5967 Merges with unresolved conflicts are often the result of
6036 non-interactive merging using the ``internal:merge`` configuration
5968 non-interactive merging using the ``internal:merge`` configuration
6037 setting, or a command-line merge tool like ``diff3``. The resolve
5969 setting, or a command-line merge tool like ``diff3``. The resolve
6038 command is used to manage the files involved in a merge, after
5970 command is used to manage the files involved in a merge, after
6039 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5971 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6040 working directory must have two parents). See :hg:`help
5972 working directory must have two parents). See :hg:`help
6041 merge-tools` for information on configuring merge tools.
5973 merge-tools` for information on configuring merge tools.
6042
5974
6043 The resolve command can be used in the following ways:
5975 The resolve command can be used in the following ways:
6044
5976
6045 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5977 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
6046 files, discarding any previous merge attempts. Re-merging is not
5978 files, discarding any previous merge attempts. Re-merging is not
6047 performed for files already marked as resolved. Use ``--all/-a``
5979 performed for files already marked as resolved. Use ``--all/-a``
6048 to select all unresolved files. ``--tool`` can be used to specify
5980 to select all unresolved files. ``--tool`` can be used to specify
6049 the merge tool used for the given files. It overrides the HGMERGE
5981 the merge tool used for the given files. It overrides the HGMERGE
6050 environment variable and your configuration files. Previous file
5982 environment variable and your configuration files. Previous file
6051 contents are saved with a ``.orig`` suffix.
5983 contents are saved with a ``.orig`` suffix.
6052
5984
6053 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5985 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6054 (e.g. after having manually fixed-up the files). The default is
5986 (e.g. after having manually fixed-up the files). The default is
6055 to mark all unresolved files.
5987 to mark all unresolved files.
6056
5988
6057 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5989 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6058 default is to mark all resolved files.
5990 default is to mark all resolved files.
6059
5991
6060 - :hg:`resolve -l`: list files which had or still have conflicts.
5992 - :hg:`resolve -l`: list files which had or still have conflicts.
6061 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5993 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6062
5994
6063 .. note::
5995 .. note::
6064
5996
6065 Mercurial will not let you commit files with unresolved merge
5997 Mercurial will not let you commit files with unresolved merge
6066 conflicts. You must use :hg:`resolve -m ...` before you can
5998 conflicts. You must use :hg:`resolve -m ...` before you can
6067 commit after a conflicting merge.
5999 commit after a conflicting merge.
6068
6000
6069 Returns 0 on success, 1 if any files fail a resolve attempt.
6001 Returns 0 on success, 1 if any files fail a resolve attempt.
6070 """
6002 """
6071
6003
6072 flaglist = 'all mark unmark list no_status'.split()
6004 flaglist = 'all mark unmark list no_status'.split()
6073 all, mark, unmark, show, nostatus = \
6005 all, mark, unmark, show, nostatus = \
6074 [opts.get(o) for o in flaglist]
6006 [opts.get(o) for o in flaglist]
6075
6007
6076 if (show and (mark or unmark)) or (mark and unmark):
6008 if (show and (mark or unmark)) or (mark and unmark):
6077 raise error.Abort(_("too many options specified"))
6009 raise error.Abort(_("too many options specified"))
6078 if pats and all:
6010 if pats and all:
6079 raise error.Abort(_("can't specify --all and patterns"))
6011 raise error.Abort(_("can't specify --all and patterns"))
6080 if not (all or pats or show or mark or unmark):
6012 if not (all or pats or show or mark or unmark):
6081 raise error.Abort(_('no files or directories specified'),
6013 raise error.Abort(_('no files or directories specified'),
6082 hint=('use --all to re-merge all unresolved files'))
6014 hint=('use --all to re-merge all unresolved files'))
6083
6015
6084 if show:
6016 if show:
6085 fm = ui.formatter('resolve', opts)
6017 fm = ui.formatter('resolve', opts)
6086 ms = mergemod.mergestate.read(repo)
6018 ms = mergemod.mergestate.read(repo)
6087 m = scmutil.match(repo[None], pats, opts)
6019 m = scmutil.match(repo[None], pats, opts)
6088 for f in ms:
6020 for f in ms:
6089 if not m(f):
6021 if not m(f):
6090 continue
6022 continue
6091 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6023 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
6092 'd': 'driverresolved'}[ms[f]]
6024 'd': 'driverresolved'}[ms[f]]
6093 fm.startitem()
6025 fm.startitem()
6094 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6026 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
6095 fm.write('path', '%s\n', f, label=l)
6027 fm.write('path', '%s\n', f, label=l)
6096 fm.end()
6028 fm.end()
6097 return 0
6029 return 0
6098
6030
6099 with repo.wlock():
6031 with repo.wlock():
6100 ms = mergemod.mergestate.read(repo)
6032 ms = mergemod.mergestate.read(repo)
6101
6033
6102 if not (ms.active() or repo.dirstate.p2() != nullid):
6034 if not (ms.active() or repo.dirstate.p2() != nullid):
6103 raise error.Abort(
6035 raise error.Abort(
6104 _('resolve command not applicable when not merging'))
6036 _('resolve command not applicable when not merging'))
6105
6037
6106 wctx = repo[None]
6038 wctx = repo[None]
6107
6039
6108 if ms.mergedriver and ms.mdstate() == 'u':
6040 if ms.mergedriver and ms.mdstate() == 'u':
6109 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6041 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6110 ms.commit()
6042 ms.commit()
6111 # allow mark and unmark to go through
6043 # allow mark and unmark to go through
6112 if not mark and not unmark and not proceed:
6044 if not mark and not unmark and not proceed:
6113 return 1
6045 return 1
6114
6046
6115 m = scmutil.match(wctx, pats, opts)
6047 m = scmutil.match(wctx, pats, opts)
6116 ret = 0
6048 ret = 0
6117 didwork = False
6049 didwork = False
6118 runconclude = False
6050 runconclude = False
6119
6051
6120 tocomplete = []
6052 tocomplete = []
6121 for f in ms:
6053 for f in ms:
6122 if not m(f):
6054 if not m(f):
6123 continue
6055 continue
6124
6056
6125 didwork = True
6057 didwork = True
6126
6058
6127 # don't let driver-resolved files be marked, and run the conclude
6059 # don't let driver-resolved files be marked, and run the conclude
6128 # step if asked to resolve
6060 # step if asked to resolve
6129 if ms[f] == "d":
6061 if ms[f] == "d":
6130 exact = m.exact(f)
6062 exact = m.exact(f)
6131 if mark:
6063 if mark:
6132 if exact:
6064 if exact:
6133 ui.warn(_('not marking %s as it is driver-resolved\n')
6065 ui.warn(_('not marking %s as it is driver-resolved\n')
6134 % f)
6066 % f)
6135 elif unmark:
6067 elif unmark:
6136 if exact:
6068 if exact:
6137 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6069 ui.warn(_('not unmarking %s as it is driver-resolved\n')
6138 % f)
6070 % f)
6139 else:
6071 else:
6140 runconclude = True
6072 runconclude = True
6141 continue
6073 continue
6142
6074
6143 if mark:
6075 if mark:
6144 ms.mark(f, "r")
6076 ms.mark(f, "r")
6145 elif unmark:
6077 elif unmark:
6146 ms.mark(f, "u")
6078 ms.mark(f, "u")
6147 else:
6079 else:
6148 # backup pre-resolve (merge uses .orig for its own purposes)
6080 # backup pre-resolve (merge uses .orig for its own purposes)
6149 a = repo.wjoin(f)
6081 a = repo.wjoin(f)
6150 try:
6082 try:
6151 util.copyfile(a, a + ".resolve")
6083 util.copyfile(a, a + ".resolve")
6152 except (IOError, OSError) as inst:
6084 except (IOError, OSError) as inst:
6153 if inst.errno != errno.ENOENT:
6085 if inst.errno != errno.ENOENT:
6154 raise
6086 raise
6155
6087
6156 try:
6088 try:
6157 # preresolve file
6089 # preresolve file
6158 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6090 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6159 'resolve')
6091 'resolve')
6160 complete, r = ms.preresolve(f, wctx)
6092 complete, r = ms.preresolve(f, wctx)
6161 if not complete:
6093 if not complete:
6162 tocomplete.append(f)
6094 tocomplete.append(f)
6163 elif r:
6095 elif r:
6164 ret = 1
6096 ret = 1
6165 finally:
6097 finally:
6166 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6098 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6167 ms.commit()
6099 ms.commit()
6168
6100
6169 # replace filemerge's .orig file with our resolve file, but only
6101 # replace filemerge's .orig file with our resolve file, but only
6170 # for merges that are complete
6102 # for merges that are complete
6171 if complete:
6103 if complete:
6172 try:
6104 try:
6173 util.rename(a + ".resolve",
6105 util.rename(a + ".resolve",
6174 scmutil.origpath(ui, repo, a))
6106 scmutil.origpath(ui, repo, a))
6175 except OSError as inst:
6107 except OSError as inst:
6176 if inst.errno != errno.ENOENT:
6108 if inst.errno != errno.ENOENT:
6177 raise
6109 raise
6178
6110
6179 for f in tocomplete:
6111 for f in tocomplete:
6180 try:
6112 try:
6181 # resolve file
6113 # resolve file
6182 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6114 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6183 'resolve')
6115 'resolve')
6184 r = ms.resolve(f, wctx)
6116 r = ms.resolve(f, wctx)
6185 if r:
6117 if r:
6186 ret = 1
6118 ret = 1
6187 finally:
6119 finally:
6188 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6120 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6189 ms.commit()
6121 ms.commit()
6190
6122
6191 # replace filemerge's .orig file with our resolve file
6123 # replace filemerge's .orig file with our resolve file
6192 a = repo.wjoin(f)
6124 a = repo.wjoin(f)
6193 try:
6125 try:
6194 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6126 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6195 except OSError as inst:
6127 except OSError as inst:
6196 if inst.errno != errno.ENOENT:
6128 if inst.errno != errno.ENOENT:
6197 raise
6129 raise
6198
6130
6199 ms.commit()
6131 ms.commit()
6200 ms.recordactions()
6132 ms.recordactions()
6201
6133
6202 if not didwork and pats:
6134 if not didwork and pats:
6203 hint = None
6135 hint = None
6204 if not any([p for p in pats if p.find(':') >= 0]):
6136 if not any([p for p in pats if p.find(':') >= 0]):
6205 pats = ['path:%s' % p for p in pats]
6137 pats = ['path:%s' % p for p in pats]
6206 m = scmutil.match(wctx, pats, opts)
6138 m = scmutil.match(wctx, pats, opts)
6207 for f in ms:
6139 for f in ms:
6208 if not m(f):
6140 if not m(f):
6209 continue
6141 continue
6210 flags = ''.join(['-%s ' % o[0] for o in flaglist
6142 flags = ''.join(['-%s ' % o[0] for o in flaglist
6211 if opts.get(o)])
6143 if opts.get(o)])
6212 hint = _("(try: hg resolve %s%s)\n") % (
6144 hint = _("(try: hg resolve %s%s)\n") % (
6213 flags,
6145 flags,
6214 ' '.join(pats))
6146 ' '.join(pats))
6215 break
6147 break
6216 ui.warn(_("arguments do not match paths that need resolving\n"))
6148 ui.warn(_("arguments do not match paths that need resolving\n"))
6217 if hint:
6149 if hint:
6218 ui.warn(hint)
6150 ui.warn(hint)
6219 elif ms.mergedriver and ms.mdstate() != 's':
6151 elif ms.mergedriver and ms.mdstate() != 's':
6220 # run conclude step when either a driver-resolved file is requested
6152 # run conclude step when either a driver-resolved file is requested
6221 # or there are no driver-resolved files
6153 # or there are no driver-resolved files
6222 # we can't use 'ret' to determine whether any files are unresolved
6154 # we can't use 'ret' to determine whether any files are unresolved
6223 # because we might not have tried to resolve some
6155 # because we might not have tried to resolve some
6224 if ((runconclude or not list(ms.driverresolved()))
6156 if ((runconclude or not list(ms.driverresolved()))
6225 and not list(ms.unresolved())):
6157 and not list(ms.unresolved())):
6226 proceed = mergemod.driverconclude(repo, ms, wctx)
6158 proceed = mergemod.driverconclude(repo, ms, wctx)
6227 ms.commit()
6159 ms.commit()
6228 if not proceed:
6160 if not proceed:
6229 return 1
6161 return 1
6230
6162
6231 # Nudge users into finishing an unfinished operation
6163 # Nudge users into finishing an unfinished operation
6232 unresolvedf = list(ms.unresolved())
6164 unresolvedf = list(ms.unresolved())
6233 driverresolvedf = list(ms.driverresolved())
6165 driverresolvedf = list(ms.driverresolved())
6234 if not unresolvedf and not driverresolvedf:
6166 if not unresolvedf and not driverresolvedf:
6235 ui.status(_('(no more unresolved files)\n'))
6167 ui.status(_('(no more unresolved files)\n'))
6236 cmdutil.checkafterresolved(repo)
6168 cmdutil.checkafterresolved(repo)
6237 elif not unresolvedf:
6169 elif not unresolvedf:
6238 ui.status(_('(no more unresolved files -- '
6170 ui.status(_('(no more unresolved files -- '
6239 'run "hg resolve --all" to conclude)\n'))
6171 'run "hg resolve --all" to conclude)\n'))
6240
6172
6241 return ret
6173 return ret
6242
6174
6243 @command('revert',
6175 @command('revert',
6244 [('a', 'all', None, _('revert all changes when no arguments given')),
6176 [('a', 'all', None, _('revert all changes when no arguments given')),
6245 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6177 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6246 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6178 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6247 ('C', 'no-backup', None, _('do not save backup copies of files')),
6179 ('C', 'no-backup', None, _('do not save backup copies of files')),
6248 ('i', 'interactive', None,
6180 ('i', 'interactive', None,
6249 _('interactively select the changes (EXPERIMENTAL)')),
6181 _('interactively select the changes (EXPERIMENTAL)')),
6250 ] + walkopts + dryrunopts,
6182 ] + walkopts + dryrunopts,
6251 _('[OPTION]... [-r REV] [NAME]...'))
6183 _('[OPTION]... [-r REV] [NAME]...'))
6252 def revert(ui, repo, *pats, **opts):
6184 def revert(ui, repo, *pats, **opts):
6253 """restore files to their checkout state
6185 """restore files to their checkout state
6254
6186
6255 .. note::
6187 .. note::
6256
6188
6257 To check out earlier revisions, you should use :hg:`update REV`.
6189 To check out earlier revisions, you should use :hg:`update REV`.
6258 To cancel an uncommitted merge (and lose your changes),
6190 To cancel an uncommitted merge (and lose your changes),
6259 use :hg:`update --clean .`.
6191 use :hg:`update --clean .`.
6260
6192
6261 With no revision specified, revert the specified files or directories
6193 With no revision specified, revert the specified files or directories
6262 to the contents they had in the parent of the working directory.
6194 to the contents they had in the parent of the working directory.
6263 This restores the contents of files to an unmodified
6195 This restores the contents of files to an unmodified
6264 state and unschedules adds, removes, copies, and renames. If the
6196 state and unschedules adds, removes, copies, and renames. If the
6265 working directory has two parents, you must explicitly specify a
6197 working directory has two parents, you must explicitly specify a
6266 revision.
6198 revision.
6267
6199
6268 Using the -r/--rev or -d/--date options, revert the given files or
6200 Using the -r/--rev or -d/--date options, revert the given files or
6269 directories to their states as of a specific revision. Because
6201 directories to their states as of a specific revision. Because
6270 revert does not change the working directory parents, this will
6202 revert does not change the working directory parents, this will
6271 cause these files to appear modified. This can be helpful to "back
6203 cause these files to appear modified. This can be helpful to "back
6272 out" some or all of an earlier change. See :hg:`backout` for a
6204 out" some or all of an earlier change. See :hg:`backout` for a
6273 related method.
6205 related method.
6274
6206
6275 Modified files are saved with a .orig suffix before reverting.
6207 Modified files are saved with a .orig suffix before reverting.
6276 To disable these backups, use --no-backup. It is possible to store
6208 To disable these backups, use --no-backup. It is possible to store
6277 the backup files in a custom directory relative to the root of the
6209 the backup files in a custom directory relative to the root of the
6278 repository by setting the ``ui.origbackuppath`` configuration
6210 repository by setting the ``ui.origbackuppath`` configuration
6279 option.
6211 option.
6280
6212
6281 See :hg:`help dates` for a list of formats valid for -d/--date.
6213 See :hg:`help dates` for a list of formats valid for -d/--date.
6282
6214
6283 See :hg:`help backout` for a way to reverse the effect of an
6215 See :hg:`help backout` for a way to reverse the effect of an
6284 earlier changeset.
6216 earlier changeset.
6285
6217
6286 Returns 0 on success.
6218 Returns 0 on success.
6287 """
6219 """
6288
6220
6289 if opts.get("date"):
6221 if opts.get("date"):
6290 if opts.get("rev"):
6222 if opts.get("rev"):
6291 raise error.Abort(_("you can't specify a revision and a date"))
6223 raise error.Abort(_("you can't specify a revision and a date"))
6292 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6224 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6293
6225
6294 parent, p2 = repo.dirstate.parents()
6226 parent, p2 = repo.dirstate.parents()
6295 if not opts.get('rev') and p2 != nullid:
6227 if not opts.get('rev') and p2 != nullid:
6296 # revert after merge is a trap for new users (issue2915)
6228 # revert after merge is a trap for new users (issue2915)
6297 raise error.Abort(_('uncommitted merge with no revision specified'),
6229 raise error.Abort(_('uncommitted merge with no revision specified'),
6298 hint=_("use 'hg update' or see 'hg help revert'"))
6230 hint=_("use 'hg update' or see 'hg help revert'"))
6299
6231
6300 ctx = scmutil.revsingle(repo, opts.get('rev'))
6232 ctx = scmutil.revsingle(repo, opts.get('rev'))
6301
6233
6302 if (not (pats or opts.get('include') or opts.get('exclude') or
6234 if (not (pats or opts.get('include') or opts.get('exclude') or
6303 opts.get('all') or opts.get('interactive'))):
6235 opts.get('all') or opts.get('interactive'))):
6304 msg = _("no files or directories specified")
6236 msg = _("no files or directories specified")
6305 if p2 != nullid:
6237 if p2 != nullid:
6306 hint = _("uncommitted merge, use --all to discard all changes,"
6238 hint = _("uncommitted merge, use --all to discard all changes,"
6307 " or 'hg update -C .' to abort the merge")
6239 " or 'hg update -C .' to abort the merge")
6308 raise error.Abort(msg, hint=hint)
6240 raise error.Abort(msg, hint=hint)
6309 dirty = any(repo.status())
6241 dirty = any(repo.status())
6310 node = ctx.node()
6242 node = ctx.node()
6311 if node != parent:
6243 if node != parent:
6312 if dirty:
6244 if dirty:
6313 hint = _("uncommitted changes, use --all to discard all"
6245 hint = _("uncommitted changes, use --all to discard all"
6314 " changes, or 'hg update %s' to update") % ctx.rev()
6246 " changes, or 'hg update %s' to update") % ctx.rev()
6315 else:
6247 else:
6316 hint = _("use --all to revert all files,"
6248 hint = _("use --all to revert all files,"
6317 " or 'hg update %s' to update") % ctx.rev()
6249 " or 'hg update %s' to update") % ctx.rev()
6318 elif dirty:
6250 elif dirty:
6319 hint = _("uncommitted changes, use --all to discard all changes")
6251 hint = _("uncommitted changes, use --all to discard all changes")
6320 else:
6252 else:
6321 hint = _("use --all to revert all files")
6253 hint = _("use --all to revert all files")
6322 raise error.Abort(msg, hint=hint)
6254 raise error.Abort(msg, hint=hint)
6323
6255
6324 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6256 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6325
6257
6326 @command('rollback', dryrunopts +
6258 @command('rollback', dryrunopts +
6327 [('f', 'force', False, _('ignore safety measures'))])
6259 [('f', 'force', False, _('ignore safety measures'))])
6328 def rollback(ui, repo, **opts):
6260 def rollback(ui, repo, **opts):
6329 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6261 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6330
6262
6331 Please use :hg:`commit --amend` instead of rollback to correct
6263 Please use :hg:`commit --amend` instead of rollback to correct
6332 mistakes in the last commit.
6264 mistakes in the last commit.
6333
6265
6334 This command should be used with care. There is only one level of
6266 This command should be used with care. There is only one level of
6335 rollback, and there is no way to undo a rollback. It will also
6267 rollback, and there is no way to undo a rollback. It will also
6336 restore the dirstate at the time of the last transaction, losing
6268 restore the dirstate at the time of the last transaction, losing
6337 any dirstate changes since that time. This command does not alter
6269 any dirstate changes since that time. This command does not alter
6338 the working directory.
6270 the working directory.
6339
6271
6340 Transactions are used to encapsulate the effects of all commands
6272 Transactions are used to encapsulate the effects of all commands
6341 that create new changesets or propagate existing changesets into a
6273 that create new changesets or propagate existing changesets into a
6342 repository.
6274 repository.
6343
6275
6344 .. container:: verbose
6276 .. container:: verbose
6345
6277
6346 For example, the following commands are transactional, and their
6278 For example, the following commands are transactional, and their
6347 effects can be rolled back:
6279 effects can be rolled back:
6348
6280
6349 - commit
6281 - commit
6350 - import
6282 - import
6351 - pull
6283 - pull
6352 - push (with this repository as the destination)
6284 - push (with this repository as the destination)
6353 - unbundle
6285 - unbundle
6354
6286
6355 To avoid permanent data loss, rollback will refuse to rollback a
6287 To avoid permanent data loss, rollback will refuse to rollback a
6356 commit transaction if it isn't checked out. Use --force to
6288 commit transaction if it isn't checked out. Use --force to
6357 override this protection.
6289 override this protection.
6358
6290
6359 The rollback command can be entirely disabled by setting the
6291 The rollback command can be entirely disabled by setting the
6360 ``ui.rollback`` configuration setting to false. If you're here
6292 ``ui.rollback`` configuration setting to false. If you're here
6361 because you want to use rollback and it's disabled, you can
6293 because you want to use rollback and it's disabled, you can
6362 re-enable the command by setting ``ui.rollback`` to true.
6294 re-enable the command by setting ``ui.rollback`` to true.
6363
6295
6364 This command is not intended for use on public repositories. Once
6296 This command is not intended for use on public repositories. Once
6365 changes are visible for pull by other users, rolling a transaction
6297 changes are visible for pull by other users, rolling a transaction
6366 back locally is ineffective (someone else may already have pulled
6298 back locally is ineffective (someone else may already have pulled
6367 the changes). Furthermore, a race is possible with readers of the
6299 the changes). Furthermore, a race is possible with readers of the
6368 repository; for example an in-progress pull from the repository
6300 repository; for example an in-progress pull from the repository
6369 may fail if a rollback is performed.
6301 may fail if a rollback is performed.
6370
6302
6371 Returns 0 on success, 1 if no rollback data is available.
6303 Returns 0 on success, 1 if no rollback data is available.
6372 """
6304 """
6373 if not ui.configbool('ui', 'rollback', True):
6305 if not ui.configbool('ui', 'rollback', True):
6374 raise error.Abort(_('rollback is disabled because it is unsafe'),
6306 raise error.Abort(_('rollback is disabled because it is unsafe'),
6375 hint=('see `hg help -v rollback` for information'))
6307 hint=('see `hg help -v rollback` for information'))
6376 return repo.rollback(dryrun=opts.get('dry_run'),
6308 return repo.rollback(dryrun=opts.get('dry_run'),
6377 force=opts.get('force'))
6309 force=opts.get('force'))
6378
6310
6379 @command('root', [])
6311 @command('root', [])
6380 def root(ui, repo):
6312 def root(ui, repo):
6381 """print the root (top) of the current working directory
6313 """print the root (top) of the current working directory
6382
6314
6383 Print the root directory of the current repository.
6315 Print the root directory of the current repository.
6384
6316
6385 Returns 0 on success.
6317 Returns 0 on success.
6386 """
6318 """
6387 ui.write(repo.root + "\n")
6319 ui.write(repo.root + "\n")
6388
6320
6389 @command('^serve',
6321 @command('^serve',
6390 [('A', 'accesslog', '', _('name of access log file to write to'),
6322 [('A', 'accesslog', '', _('name of access log file to write to'),
6391 _('FILE')),
6323 _('FILE')),
6392 ('d', 'daemon', None, _('run server in background')),
6324 ('d', 'daemon', None, _('run server in background')),
6393 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6325 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6394 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6326 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6395 # use string type, then we can check if something was passed
6327 # use string type, then we can check if something was passed
6396 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6328 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6397 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6329 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6398 _('ADDR')),
6330 _('ADDR')),
6399 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6331 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6400 _('PREFIX')),
6332 _('PREFIX')),
6401 ('n', 'name', '',
6333 ('n', 'name', '',
6402 _('name to show in web pages (default: working directory)'), _('NAME')),
6334 _('name to show in web pages (default: working directory)'), _('NAME')),
6403 ('', 'web-conf', '',
6335 ('', 'web-conf', '',
6404 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6336 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6405 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6337 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6406 _('FILE')),
6338 _('FILE')),
6407 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6339 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6408 ('', 'stdio', None, _('for remote clients')),
6340 ('', 'stdio', None, _('for remote clients')),
6409 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6341 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6410 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6342 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6411 ('', 'style', '', _('template style to use'), _('STYLE')),
6343 ('', 'style', '', _('template style to use'), _('STYLE')),
6412 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6344 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6413 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6345 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6414 _('[OPTION]...'),
6346 _('[OPTION]...'),
6415 optionalrepo=True)
6347 optionalrepo=True)
6416 def serve(ui, repo, **opts):
6348 def serve(ui, repo, **opts):
6417 """start stand-alone webserver
6349 """start stand-alone webserver
6418
6350
6419 Start a local HTTP repository browser and pull server. You can use
6351 Start a local HTTP repository browser and pull server. You can use
6420 this for ad-hoc sharing and browsing of repositories. It is
6352 this for ad-hoc sharing and browsing of repositories. It is
6421 recommended to use a real web server to serve a repository for
6353 recommended to use a real web server to serve a repository for
6422 longer periods of time.
6354 longer periods of time.
6423
6355
6424 Please note that the server does not implement access control.
6356 Please note that the server does not implement access control.
6425 This means that, by default, anybody can read from the server and
6357 This means that, by default, anybody can read from the server and
6426 nobody can write to it by default. Set the ``web.allow_push``
6358 nobody can write to it by default. Set the ``web.allow_push``
6427 option to ``*`` to allow everybody to push to the server. You
6359 option to ``*`` to allow everybody to push to the server. You
6428 should use a real web server if you need to authenticate users.
6360 should use a real web server if you need to authenticate users.
6429
6361
6430 By default, the server logs accesses to stdout and errors to
6362 By default, the server logs accesses to stdout and errors to
6431 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6363 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6432 files.
6364 files.
6433
6365
6434 To have the server choose a free port number to listen on, specify
6366 To have the server choose a free port number to listen on, specify
6435 a port number of 0; in this case, the server will print the port
6367 a port number of 0; in this case, the server will print the port
6436 number it uses.
6368 number it uses.
6437
6369
6438 Returns 0 on success.
6370 Returns 0 on success.
6439 """
6371 """
6440
6372
6441 if opts["stdio"] and opts["cmdserver"]:
6373 if opts["stdio"] and opts["cmdserver"]:
6442 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6374 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6443
6375
6444 if opts["stdio"]:
6376 if opts["stdio"]:
6445 if repo is None:
6377 if repo is None:
6446 raise error.RepoError(_("there is no Mercurial repository here"
6378 raise error.RepoError(_("there is no Mercurial repository here"
6447 " (.hg not found)"))
6379 " (.hg not found)"))
6448 s = sshserver.sshserver(ui, repo)
6380 s = sshserver.sshserver(ui, repo)
6449 s.serve_forever()
6381 s.serve_forever()
6450
6382
6451 if opts["cmdserver"]:
6383 if opts["cmdserver"]:
6452 service = commandserver.createservice(ui, repo, opts)
6384 service = commandserver.createservice(ui, repo, opts)
6453 else:
6385 else:
6454 service = hgweb.createservice(ui, repo, opts)
6386 service = hgweb.createservice(ui, repo, opts)
6455 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6387 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6456
6388
6457 @command('^status|st',
6389 @command('^status|st',
6458 [('A', 'all', None, _('show status of all files')),
6390 [('A', 'all', None, _('show status of all files')),
6459 ('m', 'modified', None, _('show only modified files')),
6391 ('m', 'modified', None, _('show only modified files')),
6460 ('a', 'added', None, _('show only added files')),
6392 ('a', 'added', None, _('show only added files')),
6461 ('r', 'removed', None, _('show only removed files')),
6393 ('r', 'removed', None, _('show only removed files')),
6462 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6394 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6463 ('c', 'clean', None, _('show only files without changes')),
6395 ('c', 'clean', None, _('show only files without changes')),
6464 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6396 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6465 ('i', 'ignored', None, _('show only ignored files')),
6397 ('i', 'ignored', None, _('show only ignored files')),
6466 ('n', 'no-status', None, _('hide status prefix')),
6398 ('n', 'no-status', None, _('hide status prefix')),
6467 ('C', 'copies', None, _('show source of copied files')),
6399 ('C', 'copies', None, _('show source of copied files')),
6468 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6400 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6469 ('', 'rev', [], _('show difference from revision'), _('REV')),
6401 ('', 'rev', [], _('show difference from revision'), _('REV')),
6470 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6402 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6471 ] + walkopts + subrepoopts + formatteropts,
6403 ] + walkopts + subrepoopts + formatteropts,
6472 _('[OPTION]... [FILE]...'),
6404 _('[OPTION]... [FILE]...'),
6473 inferrepo=True)
6405 inferrepo=True)
6474 def status(ui, repo, *pats, **opts):
6406 def status(ui, repo, *pats, **opts):
6475 """show changed files in the working directory
6407 """show changed files in the working directory
6476
6408
6477 Show status of files in the repository. If names are given, only
6409 Show status of files in the repository. If names are given, only
6478 files that match are shown. Files that are clean or ignored or
6410 files that match are shown. Files that are clean or ignored or
6479 the source of a copy/move operation, are not listed unless
6411 the source of a copy/move operation, are not listed unless
6480 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6412 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6481 Unless options described with "show only ..." are given, the
6413 Unless options described with "show only ..." are given, the
6482 options -mardu are used.
6414 options -mardu are used.
6483
6415
6484 Option -q/--quiet hides untracked (unknown and ignored) files
6416 Option -q/--quiet hides untracked (unknown and ignored) files
6485 unless explicitly requested with -u/--unknown or -i/--ignored.
6417 unless explicitly requested with -u/--unknown or -i/--ignored.
6486
6418
6487 .. note::
6419 .. note::
6488
6420
6489 :hg:`status` may appear to disagree with diff if permissions have
6421 :hg:`status` may appear to disagree with diff if permissions have
6490 changed or a merge has occurred. The standard diff format does
6422 changed or a merge has occurred. The standard diff format does
6491 not report permission changes and diff only reports changes
6423 not report permission changes and diff only reports changes
6492 relative to one merge parent.
6424 relative to one merge parent.
6493
6425
6494 If one revision is given, it is used as the base revision.
6426 If one revision is given, it is used as the base revision.
6495 If two revisions are given, the differences between them are
6427 If two revisions are given, the differences between them are
6496 shown. The --change option can also be used as a shortcut to list
6428 shown. The --change option can also be used as a shortcut to list
6497 the changed files of a revision from its first parent.
6429 the changed files of a revision from its first parent.
6498
6430
6499 The codes used to show the status of files are::
6431 The codes used to show the status of files are::
6500
6432
6501 M = modified
6433 M = modified
6502 A = added
6434 A = added
6503 R = removed
6435 R = removed
6504 C = clean
6436 C = clean
6505 ! = missing (deleted by non-hg command, but still tracked)
6437 ! = missing (deleted by non-hg command, but still tracked)
6506 ? = not tracked
6438 ? = not tracked
6507 I = ignored
6439 I = ignored
6508 = origin of the previous file (with --copies)
6440 = origin of the previous file (with --copies)
6509
6441
6510 .. container:: verbose
6442 .. container:: verbose
6511
6443
6512 Examples:
6444 Examples:
6513
6445
6514 - show changes in the working directory relative to a
6446 - show changes in the working directory relative to a
6515 changeset::
6447 changeset::
6516
6448
6517 hg status --rev 9353
6449 hg status --rev 9353
6518
6450
6519 - show changes in the working directory relative to the
6451 - show changes in the working directory relative to the
6520 current directory (see :hg:`help patterns` for more information)::
6452 current directory (see :hg:`help patterns` for more information)::
6521
6453
6522 hg status re:
6454 hg status re:
6523
6455
6524 - show all changes including copies in an existing changeset::
6456 - show all changes including copies in an existing changeset::
6525
6457
6526 hg status --copies --change 9353
6458 hg status --copies --change 9353
6527
6459
6528 - get a NUL separated list of added files, suitable for xargs::
6460 - get a NUL separated list of added files, suitable for xargs::
6529
6461
6530 hg status -an0
6462 hg status -an0
6531
6463
6532 Returns 0 on success.
6464 Returns 0 on success.
6533 """
6465 """
6534
6466
6535 revs = opts.get('rev')
6467 revs = opts.get('rev')
6536 change = opts.get('change')
6468 change = opts.get('change')
6537
6469
6538 if revs and change:
6470 if revs and change:
6539 msg = _('cannot specify --rev and --change at the same time')
6471 msg = _('cannot specify --rev and --change at the same time')
6540 raise error.Abort(msg)
6472 raise error.Abort(msg)
6541 elif change:
6473 elif change:
6542 node2 = scmutil.revsingle(repo, change, None).node()
6474 node2 = scmutil.revsingle(repo, change, None).node()
6543 node1 = repo[node2].p1().node()
6475 node1 = repo[node2].p1().node()
6544 else:
6476 else:
6545 node1, node2 = scmutil.revpair(repo, revs)
6477 node1, node2 = scmutil.revpair(repo, revs)
6546
6478
6547 if pats:
6479 if pats:
6548 cwd = repo.getcwd()
6480 cwd = repo.getcwd()
6549 else:
6481 else:
6550 cwd = ''
6482 cwd = ''
6551
6483
6552 if opts.get('print0'):
6484 if opts.get('print0'):
6553 end = '\0'
6485 end = '\0'
6554 else:
6486 else:
6555 end = '\n'
6487 end = '\n'
6556 copy = {}
6488 copy = {}
6557 states = 'modified added removed deleted unknown ignored clean'.split()
6489 states = 'modified added removed deleted unknown ignored clean'.split()
6558 show = [k for k in states if opts.get(k)]
6490 show = [k for k in states if opts.get(k)]
6559 if opts.get('all'):
6491 if opts.get('all'):
6560 show += ui.quiet and (states[:4] + ['clean']) or states
6492 show += ui.quiet and (states[:4] + ['clean']) or states
6561 if not show:
6493 if not show:
6562 if ui.quiet:
6494 if ui.quiet:
6563 show = states[:4]
6495 show = states[:4]
6564 else:
6496 else:
6565 show = states[:5]
6497 show = states[:5]
6566
6498
6567 m = scmutil.match(repo[node2], pats, opts)
6499 m = scmutil.match(repo[node2], pats, opts)
6568 stat = repo.status(node1, node2, m,
6500 stat = repo.status(node1, node2, m,
6569 'ignored' in show, 'clean' in show, 'unknown' in show,
6501 'ignored' in show, 'clean' in show, 'unknown' in show,
6570 opts.get('subrepos'))
6502 opts.get('subrepos'))
6571 changestates = zip(states, 'MAR!?IC', stat)
6503 changestates = zip(states, 'MAR!?IC', stat)
6572
6504
6573 if (opts.get('all') or opts.get('copies')
6505 if (opts.get('all') or opts.get('copies')
6574 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6506 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6575 copy = copies.pathcopies(repo[node1], repo[node2], m)
6507 copy = copies.pathcopies(repo[node1], repo[node2], m)
6576
6508
6577 fm = ui.formatter('status', opts)
6509 fm = ui.formatter('status', opts)
6578 fmt = '%s' + end
6510 fmt = '%s' + end
6579 showchar = not opts.get('no_status')
6511 showchar = not opts.get('no_status')
6580
6512
6581 for state, char, files in changestates:
6513 for state, char, files in changestates:
6582 if state in show:
6514 if state in show:
6583 label = 'status.' + state
6515 label = 'status.' + state
6584 for f in files:
6516 for f in files:
6585 fm.startitem()
6517 fm.startitem()
6586 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6518 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6587 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6519 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6588 if f in copy:
6520 if f in copy:
6589 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6521 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6590 label='status.copied')
6522 label='status.copied')
6591 fm.end()
6523 fm.end()
6592
6524
6593 @command('^summary|sum',
6525 @command('^summary|sum',
6594 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6526 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6595 def summary(ui, repo, **opts):
6527 def summary(ui, repo, **opts):
6596 """summarize working directory state
6528 """summarize working directory state
6597
6529
6598 This generates a brief summary of the working directory state,
6530 This generates a brief summary of the working directory state,
6599 including parents, branch, commit status, phase and available updates.
6531 including parents, branch, commit status, phase and available updates.
6600
6532
6601 With the --remote option, this will check the default paths for
6533 With the --remote option, this will check the default paths for
6602 incoming and outgoing changes. This can be time-consuming.
6534 incoming and outgoing changes. This can be time-consuming.
6603
6535
6604 Returns 0 on success.
6536 Returns 0 on success.
6605 """
6537 """
6606
6538
6607 ctx = repo[None]
6539 ctx = repo[None]
6608 parents = ctx.parents()
6540 parents = ctx.parents()
6609 pnode = parents[0].node()
6541 pnode = parents[0].node()
6610 marks = []
6542 marks = []
6611
6543
6612 ms = None
6544 ms = None
6613 try:
6545 try:
6614 ms = mergemod.mergestate.read(repo)
6546 ms = mergemod.mergestate.read(repo)
6615 except error.UnsupportedMergeRecords as e:
6547 except error.UnsupportedMergeRecords as e:
6616 s = ' '.join(e.recordtypes)
6548 s = ' '.join(e.recordtypes)
6617 ui.warn(
6549 ui.warn(
6618 _('warning: merge state has unsupported record types: %s\n') % s)
6550 _('warning: merge state has unsupported record types: %s\n') % s)
6619 unresolved = 0
6551 unresolved = 0
6620 else:
6552 else:
6621 unresolved = [f for f in ms if ms[f] == 'u']
6553 unresolved = [f for f in ms if ms[f] == 'u']
6622
6554
6623 for p in parents:
6555 for p in parents:
6624 # label with log.changeset (instead of log.parent) since this
6556 # label with log.changeset (instead of log.parent) since this
6625 # shows a working directory parent *changeset*:
6557 # shows a working directory parent *changeset*:
6626 # i18n: column positioning for "hg summary"
6558 # i18n: column positioning for "hg summary"
6627 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6559 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6628 label='log.changeset changeset.%s' % p.phasestr())
6560 label='log.changeset changeset.%s' % p.phasestr())
6629 ui.write(' '.join(p.tags()), label='log.tag')
6561 ui.write(' '.join(p.tags()), label='log.tag')
6630 if p.bookmarks():
6562 if p.bookmarks():
6631 marks.extend(p.bookmarks())
6563 marks.extend(p.bookmarks())
6632 if p.rev() == -1:
6564 if p.rev() == -1:
6633 if not len(repo):
6565 if not len(repo):
6634 ui.write(_(' (empty repository)'))
6566 ui.write(_(' (empty repository)'))
6635 else:
6567 else:
6636 ui.write(_(' (no revision checked out)'))
6568 ui.write(_(' (no revision checked out)'))
6637 ui.write('\n')
6569 ui.write('\n')
6638 if p.description():
6570 if p.description():
6639 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6571 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6640 label='log.summary')
6572 label='log.summary')
6641
6573
6642 branch = ctx.branch()
6574 branch = ctx.branch()
6643 bheads = repo.branchheads(branch)
6575 bheads = repo.branchheads(branch)
6644 # i18n: column positioning for "hg summary"
6576 # i18n: column positioning for "hg summary"
6645 m = _('branch: %s\n') % branch
6577 m = _('branch: %s\n') % branch
6646 if branch != 'default':
6578 if branch != 'default':
6647 ui.write(m, label='log.branch')
6579 ui.write(m, label='log.branch')
6648 else:
6580 else:
6649 ui.status(m, label='log.branch')
6581 ui.status(m, label='log.branch')
6650
6582
6651 if marks:
6583 if marks:
6652 active = repo._activebookmark
6584 active = repo._activebookmark
6653 # i18n: column positioning for "hg summary"
6585 # i18n: column positioning for "hg summary"
6654 ui.write(_('bookmarks:'), label='log.bookmark')
6586 ui.write(_('bookmarks:'), label='log.bookmark')
6655 if active is not None:
6587 if active is not None:
6656 if active in marks:
6588 if active in marks:
6657 ui.write(' *' + active, label=activebookmarklabel)
6589 ui.write(' *' + active, label=activebookmarklabel)
6658 marks.remove(active)
6590 marks.remove(active)
6659 else:
6591 else:
6660 ui.write(' [%s]' % active, label=activebookmarklabel)
6592 ui.write(' [%s]' % active, label=activebookmarklabel)
6661 for m in marks:
6593 for m in marks:
6662 ui.write(' ' + m, label='log.bookmark')
6594 ui.write(' ' + m, label='log.bookmark')
6663 ui.write('\n', label='log.bookmark')
6595 ui.write('\n', label='log.bookmark')
6664
6596
6665 status = repo.status(unknown=True)
6597 status = repo.status(unknown=True)
6666
6598
6667 c = repo.dirstate.copies()
6599 c = repo.dirstate.copies()
6668 copied, renamed = [], []
6600 copied, renamed = [], []
6669 for d, s in c.iteritems():
6601 for d, s in c.iteritems():
6670 if s in status.removed:
6602 if s in status.removed:
6671 status.removed.remove(s)
6603 status.removed.remove(s)
6672 renamed.append(d)
6604 renamed.append(d)
6673 else:
6605 else:
6674 copied.append(d)
6606 copied.append(d)
6675 if d in status.added:
6607 if d in status.added:
6676 status.added.remove(d)
6608 status.added.remove(d)
6677
6609
6678 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6610 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6679
6611
6680 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6612 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6681 (ui.label(_('%d added'), 'status.added'), status.added),
6613 (ui.label(_('%d added'), 'status.added'), status.added),
6682 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6614 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6683 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6615 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6684 (ui.label(_('%d copied'), 'status.copied'), copied),
6616 (ui.label(_('%d copied'), 'status.copied'), copied),
6685 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6617 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6686 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6618 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6687 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6619 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6688 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6620 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6689 t = []
6621 t = []
6690 for l, s in labels:
6622 for l, s in labels:
6691 if s:
6623 if s:
6692 t.append(l % len(s))
6624 t.append(l % len(s))
6693
6625
6694 t = ', '.join(t)
6626 t = ', '.join(t)
6695 cleanworkdir = False
6627 cleanworkdir = False
6696
6628
6697 if repo.vfs.exists('graftstate'):
6629 if repo.vfs.exists('graftstate'):
6698 t += _(' (graft in progress)')
6630 t += _(' (graft in progress)')
6699 if repo.vfs.exists('updatestate'):
6631 if repo.vfs.exists('updatestate'):
6700 t += _(' (interrupted update)')
6632 t += _(' (interrupted update)')
6701 elif len(parents) > 1:
6633 elif len(parents) > 1:
6702 t += _(' (merge)')
6634 t += _(' (merge)')
6703 elif branch != parents[0].branch():
6635 elif branch != parents[0].branch():
6704 t += _(' (new branch)')
6636 t += _(' (new branch)')
6705 elif (parents[0].closesbranch() and
6637 elif (parents[0].closesbranch() and
6706 pnode in repo.branchheads(branch, closed=True)):
6638 pnode in repo.branchheads(branch, closed=True)):
6707 t += _(' (head closed)')
6639 t += _(' (head closed)')
6708 elif not (status.modified or status.added or status.removed or renamed or
6640 elif not (status.modified or status.added or status.removed or renamed or
6709 copied or subs):
6641 copied or subs):
6710 t += _(' (clean)')
6642 t += _(' (clean)')
6711 cleanworkdir = True
6643 cleanworkdir = True
6712 elif pnode not in bheads:
6644 elif pnode not in bheads:
6713 t += _(' (new branch head)')
6645 t += _(' (new branch head)')
6714
6646
6715 if parents:
6647 if parents:
6716 pendingphase = max(p.phase() for p in parents)
6648 pendingphase = max(p.phase() for p in parents)
6717 else:
6649 else:
6718 pendingphase = phases.public
6650 pendingphase = phases.public
6719
6651
6720 if pendingphase > phases.newcommitphase(ui):
6652 if pendingphase > phases.newcommitphase(ui):
6721 t += ' (%s)' % phases.phasenames[pendingphase]
6653 t += ' (%s)' % phases.phasenames[pendingphase]
6722
6654
6723 if cleanworkdir:
6655 if cleanworkdir:
6724 # i18n: column positioning for "hg summary"
6656 # i18n: column positioning for "hg summary"
6725 ui.status(_('commit: %s\n') % t.strip())
6657 ui.status(_('commit: %s\n') % t.strip())
6726 else:
6658 else:
6727 # i18n: column positioning for "hg summary"
6659 # i18n: column positioning for "hg summary"
6728 ui.write(_('commit: %s\n') % t.strip())
6660 ui.write(_('commit: %s\n') % t.strip())
6729
6661
6730 # all ancestors of branch heads - all ancestors of parent = new csets
6662 # all ancestors of branch heads - all ancestors of parent = new csets
6731 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6663 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6732 bheads))
6664 bheads))
6733
6665
6734 if new == 0:
6666 if new == 0:
6735 # i18n: column positioning for "hg summary"
6667 # i18n: column positioning for "hg summary"
6736 ui.status(_('update: (current)\n'))
6668 ui.status(_('update: (current)\n'))
6737 elif pnode not in bheads:
6669 elif pnode not in bheads:
6738 # i18n: column positioning for "hg summary"
6670 # i18n: column positioning for "hg summary"
6739 ui.write(_('update: %d new changesets (update)\n') % new)
6671 ui.write(_('update: %d new changesets (update)\n') % new)
6740 else:
6672 else:
6741 # i18n: column positioning for "hg summary"
6673 # i18n: column positioning for "hg summary"
6742 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6674 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6743 (new, len(bheads)))
6675 (new, len(bheads)))
6744
6676
6745 t = []
6677 t = []
6746 draft = len(repo.revs('draft()'))
6678 draft = len(repo.revs('draft()'))
6747 if draft:
6679 if draft:
6748 t.append(_('%d draft') % draft)
6680 t.append(_('%d draft') % draft)
6749 secret = len(repo.revs('secret()'))
6681 secret = len(repo.revs('secret()'))
6750 if secret:
6682 if secret:
6751 t.append(_('%d secret') % secret)
6683 t.append(_('%d secret') % secret)
6752
6684
6753 if draft or secret:
6685 if draft or secret:
6754 ui.status(_('phases: %s\n') % ', '.join(t))
6686 ui.status(_('phases: %s\n') % ', '.join(t))
6755
6687
6756 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6688 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6757 for trouble in ("unstable", "divergent", "bumped"):
6689 for trouble in ("unstable", "divergent", "bumped"):
6758 numtrouble = len(repo.revs(trouble + "()"))
6690 numtrouble = len(repo.revs(trouble + "()"))
6759 # We write all the possibilities to ease translation
6691 # We write all the possibilities to ease translation
6760 troublemsg = {
6692 troublemsg = {
6761 "unstable": _("unstable: %d changesets"),
6693 "unstable": _("unstable: %d changesets"),
6762 "divergent": _("divergent: %d changesets"),
6694 "divergent": _("divergent: %d changesets"),
6763 "bumped": _("bumped: %d changesets"),
6695 "bumped": _("bumped: %d changesets"),
6764 }
6696 }
6765 if numtrouble > 0:
6697 if numtrouble > 0:
6766 ui.status(troublemsg[trouble] % numtrouble + "\n")
6698 ui.status(troublemsg[trouble] % numtrouble + "\n")
6767
6699
6768 cmdutil.summaryhooks(ui, repo)
6700 cmdutil.summaryhooks(ui, repo)
6769
6701
6770 if opts.get('remote'):
6702 if opts.get('remote'):
6771 needsincoming, needsoutgoing = True, True
6703 needsincoming, needsoutgoing = True, True
6772 else:
6704 else:
6773 needsincoming, needsoutgoing = False, False
6705 needsincoming, needsoutgoing = False, False
6774 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6706 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6775 if i:
6707 if i:
6776 needsincoming = True
6708 needsincoming = True
6777 if o:
6709 if o:
6778 needsoutgoing = True
6710 needsoutgoing = True
6779 if not needsincoming and not needsoutgoing:
6711 if not needsincoming and not needsoutgoing:
6780 return
6712 return
6781
6713
6782 def getincoming():
6714 def getincoming():
6783 source, branches = hg.parseurl(ui.expandpath('default'))
6715 source, branches = hg.parseurl(ui.expandpath('default'))
6784 sbranch = branches[0]
6716 sbranch = branches[0]
6785 try:
6717 try:
6786 other = hg.peer(repo, {}, source)
6718 other = hg.peer(repo, {}, source)
6787 except error.RepoError:
6719 except error.RepoError:
6788 if opts.get('remote'):
6720 if opts.get('remote'):
6789 raise
6721 raise
6790 return source, sbranch, None, None, None
6722 return source, sbranch, None, None, None
6791 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6723 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6792 if revs:
6724 if revs:
6793 revs = [other.lookup(rev) for rev in revs]
6725 revs = [other.lookup(rev) for rev in revs]
6794 ui.debug('comparing with %s\n' % util.hidepassword(source))
6726 ui.debug('comparing with %s\n' % util.hidepassword(source))
6795 repo.ui.pushbuffer()
6727 repo.ui.pushbuffer()
6796 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6728 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6797 repo.ui.popbuffer()
6729 repo.ui.popbuffer()
6798 return source, sbranch, other, commoninc, commoninc[1]
6730 return source, sbranch, other, commoninc, commoninc[1]
6799
6731
6800 if needsincoming:
6732 if needsincoming:
6801 source, sbranch, sother, commoninc, incoming = getincoming()
6733 source, sbranch, sother, commoninc, incoming = getincoming()
6802 else:
6734 else:
6803 source = sbranch = sother = commoninc = incoming = None
6735 source = sbranch = sother = commoninc = incoming = None
6804
6736
6805 def getoutgoing():
6737 def getoutgoing():
6806 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6738 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6807 dbranch = branches[0]
6739 dbranch = branches[0]
6808 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6740 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6809 if source != dest:
6741 if source != dest:
6810 try:
6742 try:
6811 dother = hg.peer(repo, {}, dest)
6743 dother = hg.peer(repo, {}, dest)
6812 except error.RepoError:
6744 except error.RepoError:
6813 if opts.get('remote'):
6745 if opts.get('remote'):
6814 raise
6746 raise
6815 return dest, dbranch, None, None
6747 return dest, dbranch, None, None
6816 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6748 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6817 elif sother is None:
6749 elif sother is None:
6818 # there is no explicit destination peer, but source one is invalid
6750 # there is no explicit destination peer, but source one is invalid
6819 return dest, dbranch, None, None
6751 return dest, dbranch, None, None
6820 else:
6752 else:
6821 dother = sother
6753 dother = sother
6822 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6754 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6823 common = None
6755 common = None
6824 else:
6756 else:
6825 common = commoninc
6757 common = commoninc
6826 if revs:
6758 if revs:
6827 revs = [repo.lookup(rev) for rev in revs]
6759 revs = [repo.lookup(rev) for rev in revs]
6828 repo.ui.pushbuffer()
6760 repo.ui.pushbuffer()
6829 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6761 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6830 commoninc=common)
6762 commoninc=common)
6831 repo.ui.popbuffer()
6763 repo.ui.popbuffer()
6832 return dest, dbranch, dother, outgoing
6764 return dest, dbranch, dother, outgoing
6833
6765
6834 if needsoutgoing:
6766 if needsoutgoing:
6835 dest, dbranch, dother, outgoing = getoutgoing()
6767 dest, dbranch, dother, outgoing = getoutgoing()
6836 else:
6768 else:
6837 dest = dbranch = dother = outgoing = None
6769 dest = dbranch = dother = outgoing = None
6838
6770
6839 if opts.get('remote'):
6771 if opts.get('remote'):
6840 t = []
6772 t = []
6841 if incoming:
6773 if incoming:
6842 t.append(_('1 or more incoming'))
6774 t.append(_('1 or more incoming'))
6843 o = outgoing.missing
6775 o = outgoing.missing
6844 if o:
6776 if o:
6845 t.append(_('%d outgoing') % len(o))
6777 t.append(_('%d outgoing') % len(o))
6846 other = dother or sother
6778 other = dother or sother
6847 if 'bookmarks' in other.listkeys('namespaces'):
6779 if 'bookmarks' in other.listkeys('namespaces'):
6848 counts = bookmarks.summary(repo, other)
6780 counts = bookmarks.summary(repo, other)
6849 if counts[0] > 0:
6781 if counts[0] > 0:
6850 t.append(_('%d incoming bookmarks') % counts[0])
6782 t.append(_('%d incoming bookmarks') % counts[0])
6851 if counts[1] > 0:
6783 if counts[1] > 0:
6852 t.append(_('%d outgoing bookmarks') % counts[1])
6784 t.append(_('%d outgoing bookmarks') % counts[1])
6853
6785
6854 if t:
6786 if t:
6855 # i18n: column positioning for "hg summary"
6787 # i18n: column positioning for "hg summary"
6856 ui.write(_('remote: %s\n') % (', '.join(t)))
6788 ui.write(_('remote: %s\n') % (', '.join(t)))
6857 else:
6789 else:
6858 # i18n: column positioning for "hg summary"
6790 # i18n: column positioning for "hg summary"
6859 ui.status(_('remote: (synced)\n'))
6791 ui.status(_('remote: (synced)\n'))
6860
6792
6861 cmdutil.summaryremotehooks(ui, repo, opts,
6793 cmdutil.summaryremotehooks(ui, repo, opts,
6862 ((source, sbranch, sother, commoninc),
6794 ((source, sbranch, sother, commoninc),
6863 (dest, dbranch, dother, outgoing)))
6795 (dest, dbranch, dother, outgoing)))
6864
6796
6865 @command('tag',
6797 @command('tag',
6866 [('f', 'force', None, _('force tag')),
6798 [('f', 'force', None, _('force tag')),
6867 ('l', 'local', None, _('make the tag local')),
6799 ('l', 'local', None, _('make the tag local')),
6868 ('r', 'rev', '', _('revision to tag'), _('REV')),
6800 ('r', 'rev', '', _('revision to tag'), _('REV')),
6869 ('', 'remove', None, _('remove a tag')),
6801 ('', 'remove', None, _('remove a tag')),
6870 # -l/--local is already there, commitopts cannot be used
6802 # -l/--local is already there, commitopts cannot be used
6871 ('e', 'edit', None, _('invoke editor on commit messages')),
6803 ('e', 'edit', None, _('invoke editor on commit messages')),
6872 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6804 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6873 ] + commitopts2,
6805 ] + commitopts2,
6874 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6806 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6875 def tag(ui, repo, name1, *names, **opts):
6807 def tag(ui, repo, name1, *names, **opts):
6876 """add one or more tags for the current or given revision
6808 """add one or more tags for the current or given revision
6877
6809
6878 Name a particular revision using <name>.
6810 Name a particular revision using <name>.
6879
6811
6880 Tags are used to name particular revisions of the repository and are
6812 Tags are used to name particular revisions of the repository and are
6881 very useful to compare different revisions, to go back to significant
6813 very useful to compare different revisions, to go back to significant
6882 earlier versions or to mark branch points as releases, etc. Changing
6814 earlier versions or to mark branch points as releases, etc. Changing
6883 an existing tag is normally disallowed; use -f/--force to override.
6815 an existing tag is normally disallowed; use -f/--force to override.
6884
6816
6885 If no revision is given, the parent of the working directory is
6817 If no revision is given, the parent of the working directory is
6886 used.
6818 used.
6887
6819
6888 To facilitate version control, distribution, and merging of tags,
6820 To facilitate version control, distribution, and merging of tags,
6889 they are stored as a file named ".hgtags" which is managed similarly
6821 they are stored as a file named ".hgtags" which is managed similarly
6890 to other project files and can be hand-edited if necessary. This
6822 to other project files and can be hand-edited if necessary. This
6891 also means that tagging creates a new commit. The file
6823 also means that tagging creates a new commit. The file
6892 ".hg/localtags" is used for local tags (not shared among
6824 ".hg/localtags" is used for local tags (not shared among
6893 repositories).
6825 repositories).
6894
6826
6895 Tag commits are usually made at the head of a branch. If the parent
6827 Tag commits are usually made at the head of a branch. If the parent
6896 of the working directory is not a branch head, :hg:`tag` aborts; use
6828 of the working directory is not a branch head, :hg:`tag` aborts; use
6897 -f/--force to force the tag commit to be based on a non-head
6829 -f/--force to force the tag commit to be based on a non-head
6898 changeset.
6830 changeset.
6899
6831
6900 See :hg:`help dates` for a list of formats valid for -d/--date.
6832 See :hg:`help dates` for a list of formats valid for -d/--date.
6901
6833
6902 Since tag names have priority over branch names during revision
6834 Since tag names have priority over branch names during revision
6903 lookup, using an existing branch name as a tag name is discouraged.
6835 lookup, using an existing branch name as a tag name is discouraged.
6904
6836
6905 Returns 0 on success.
6837 Returns 0 on success.
6906 """
6838 """
6907 wlock = lock = None
6839 wlock = lock = None
6908 try:
6840 try:
6909 wlock = repo.wlock()
6841 wlock = repo.wlock()
6910 lock = repo.lock()
6842 lock = repo.lock()
6911 rev_ = "."
6843 rev_ = "."
6912 names = [t.strip() for t in (name1,) + names]
6844 names = [t.strip() for t in (name1,) + names]
6913 if len(names) != len(set(names)):
6845 if len(names) != len(set(names)):
6914 raise error.Abort(_('tag names must be unique'))
6846 raise error.Abort(_('tag names must be unique'))
6915 for n in names:
6847 for n in names:
6916 scmutil.checknewlabel(repo, n, 'tag')
6848 scmutil.checknewlabel(repo, n, 'tag')
6917 if not n:
6849 if not n:
6918 raise error.Abort(_('tag names cannot consist entirely of '
6850 raise error.Abort(_('tag names cannot consist entirely of '
6919 'whitespace'))
6851 'whitespace'))
6920 if opts.get('rev') and opts.get('remove'):
6852 if opts.get('rev') and opts.get('remove'):
6921 raise error.Abort(_("--rev and --remove are incompatible"))
6853 raise error.Abort(_("--rev and --remove are incompatible"))
6922 if opts.get('rev'):
6854 if opts.get('rev'):
6923 rev_ = opts['rev']
6855 rev_ = opts['rev']
6924 message = opts.get('message')
6856 message = opts.get('message')
6925 if opts.get('remove'):
6857 if opts.get('remove'):
6926 if opts.get('local'):
6858 if opts.get('local'):
6927 expectedtype = 'local'
6859 expectedtype = 'local'
6928 else:
6860 else:
6929 expectedtype = 'global'
6861 expectedtype = 'global'
6930
6862
6931 for n in names:
6863 for n in names:
6932 if not repo.tagtype(n):
6864 if not repo.tagtype(n):
6933 raise error.Abort(_("tag '%s' does not exist") % n)
6865 raise error.Abort(_("tag '%s' does not exist") % n)
6934 if repo.tagtype(n) != expectedtype:
6866 if repo.tagtype(n) != expectedtype:
6935 if expectedtype == 'global':
6867 if expectedtype == 'global':
6936 raise error.Abort(_("tag '%s' is not a global tag") % n)
6868 raise error.Abort(_("tag '%s' is not a global tag") % n)
6937 else:
6869 else:
6938 raise error.Abort(_("tag '%s' is not a local tag") % n)
6870 raise error.Abort(_("tag '%s' is not a local tag") % n)
6939 rev_ = 'null'
6871 rev_ = 'null'
6940 if not message:
6872 if not message:
6941 # we don't translate commit messages
6873 # we don't translate commit messages
6942 message = 'Removed tag %s' % ', '.join(names)
6874 message = 'Removed tag %s' % ', '.join(names)
6943 elif not opts.get('force'):
6875 elif not opts.get('force'):
6944 for n in names:
6876 for n in names:
6945 if n in repo.tags():
6877 if n in repo.tags():
6946 raise error.Abort(_("tag '%s' already exists "
6878 raise error.Abort(_("tag '%s' already exists "
6947 "(use -f to force)") % n)
6879 "(use -f to force)") % n)
6948 if not opts.get('local'):
6880 if not opts.get('local'):
6949 p1, p2 = repo.dirstate.parents()
6881 p1, p2 = repo.dirstate.parents()
6950 if p2 != nullid:
6882 if p2 != nullid:
6951 raise error.Abort(_('uncommitted merge'))
6883 raise error.Abort(_('uncommitted merge'))
6952 bheads = repo.branchheads()
6884 bheads = repo.branchheads()
6953 if not opts.get('force') and bheads and p1 not in bheads:
6885 if not opts.get('force') and bheads and p1 not in bheads:
6954 raise error.Abort(_('working directory is not at a branch head '
6886 raise error.Abort(_('working directory is not at a branch head '
6955 '(use -f to force)'))
6887 '(use -f to force)'))
6956 r = scmutil.revsingle(repo, rev_).node()
6888 r = scmutil.revsingle(repo, rev_).node()
6957
6889
6958 if not message:
6890 if not message:
6959 # we don't translate commit messages
6891 # we don't translate commit messages
6960 message = ('Added tag %s for changeset %s' %
6892 message = ('Added tag %s for changeset %s' %
6961 (', '.join(names), short(r)))
6893 (', '.join(names), short(r)))
6962
6894
6963 date = opts.get('date')
6895 date = opts.get('date')
6964 if date:
6896 if date:
6965 date = util.parsedate(date)
6897 date = util.parsedate(date)
6966
6898
6967 if opts.get('remove'):
6899 if opts.get('remove'):
6968 editform = 'tag.remove'
6900 editform = 'tag.remove'
6969 else:
6901 else:
6970 editform = 'tag.add'
6902 editform = 'tag.add'
6971 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6903 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6972
6904
6973 # don't allow tagging the null rev
6905 # don't allow tagging the null rev
6974 if (not opts.get('remove') and
6906 if (not opts.get('remove') and
6975 scmutil.revsingle(repo, rev_).rev() == nullrev):
6907 scmutil.revsingle(repo, rev_).rev() == nullrev):
6976 raise error.Abort(_("cannot tag null revision"))
6908 raise error.Abort(_("cannot tag null revision"))
6977
6909
6978 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6910 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6979 editor=editor)
6911 editor=editor)
6980 finally:
6912 finally:
6981 release(lock, wlock)
6913 release(lock, wlock)
6982
6914
6983 @command('tags', formatteropts, '')
6915 @command('tags', formatteropts, '')
6984 def tags(ui, repo, **opts):
6916 def tags(ui, repo, **opts):
6985 """list repository tags
6917 """list repository tags
6986
6918
6987 This lists both regular and local tags. When the -v/--verbose
6919 This lists both regular and local tags. When the -v/--verbose
6988 switch is used, a third column "local" is printed for local tags.
6920 switch is used, a third column "local" is printed for local tags.
6989 When the -q/--quiet switch is used, only the tag name is printed.
6921 When the -q/--quiet switch is used, only the tag name is printed.
6990
6922
6991 Returns 0 on success.
6923 Returns 0 on success.
6992 """
6924 """
6993
6925
6994 fm = ui.formatter('tags', opts)
6926 fm = ui.formatter('tags', opts)
6995 hexfunc = fm.hexfunc
6927 hexfunc = fm.hexfunc
6996 tagtype = ""
6928 tagtype = ""
6997
6929
6998 for t, n in reversed(repo.tagslist()):
6930 for t, n in reversed(repo.tagslist()):
6999 hn = hexfunc(n)
6931 hn = hexfunc(n)
7000 label = 'tags.normal'
6932 label = 'tags.normal'
7001 tagtype = ''
6933 tagtype = ''
7002 if repo.tagtype(t) == 'local':
6934 if repo.tagtype(t) == 'local':
7003 label = 'tags.local'
6935 label = 'tags.local'
7004 tagtype = 'local'
6936 tagtype = 'local'
7005
6937
7006 fm.startitem()
6938 fm.startitem()
7007 fm.write('tag', '%s', t, label=label)
6939 fm.write('tag', '%s', t, label=label)
7008 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6940 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
7009 fm.condwrite(not ui.quiet, 'rev node', fmt,
6941 fm.condwrite(not ui.quiet, 'rev node', fmt,
7010 repo.changelog.rev(n), hn, label=label)
6942 repo.changelog.rev(n), hn, label=label)
7011 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6943 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
7012 tagtype, label=label)
6944 tagtype, label=label)
7013 fm.plain('\n')
6945 fm.plain('\n')
7014 fm.end()
6946 fm.end()
7015
6947
7016 @command('tip',
6948 @command('tip',
7017 [('p', 'patch', None, _('show patch')),
6949 [('p', 'patch', None, _('show patch')),
7018 ('g', 'git', None, _('use git extended diff format')),
6950 ('g', 'git', None, _('use git extended diff format')),
7019 ] + templateopts,
6951 ] + templateopts,
7020 _('[-p] [-g]'))
6952 _('[-p] [-g]'))
7021 def tip(ui, repo, **opts):
6953 def tip(ui, repo, **opts):
7022 """show the tip revision (DEPRECATED)
6954 """show the tip revision (DEPRECATED)
7023
6955
7024 The tip revision (usually just called the tip) is the changeset
6956 The tip revision (usually just called the tip) is the changeset
7025 most recently added to the repository (and therefore the most
6957 most recently added to the repository (and therefore the most
7026 recently changed head).
6958 recently changed head).
7027
6959
7028 If you have just made a commit, that commit will be the tip. If
6960 If you have just made a commit, that commit will be the tip. If
7029 you have just pulled changes from another repository, the tip of
6961 you have just pulled changes from another repository, the tip of
7030 that repository becomes the current tip. The "tip" tag is special
6962 that repository becomes the current tip. The "tip" tag is special
7031 and cannot be renamed or assigned to a different changeset.
6963 and cannot be renamed or assigned to a different changeset.
7032
6964
7033 This command is deprecated, please use :hg:`heads` instead.
6965 This command is deprecated, please use :hg:`heads` instead.
7034
6966
7035 Returns 0 on success.
6967 Returns 0 on success.
7036 """
6968 """
7037 displayer = cmdutil.show_changeset(ui, repo, opts)
6969 displayer = cmdutil.show_changeset(ui, repo, opts)
7038 displayer.show(repo['tip'])
6970 displayer.show(repo['tip'])
7039 displayer.close()
6971 displayer.close()
7040
6972
7041 @command('unbundle',
6973 @command('unbundle',
7042 [('u', 'update', None,
6974 [('u', 'update', None,
7043 _('update to new branch head if changesets were unbundled'))],
6975 _('update to new branch head if changesets were unbundled'))],
7044 _('[-u] FILE...'))
6976 _('[-u] FILE...'))
7045 def unbundle(ui, repo, fname1, *fnames, **opts):
6977 def unbundle(ui, repo, fname1, *fnames, **opts):
7046 """apply one or more changegroup files
6978 """apply one or more changegroup files
7047
6979
7048 Apply one or more compressed changegroup files generated by the
6980 Apply one or more compressed changegroup files generated by the
7049 bundle command.
6981 bundle command.
7050
6982
7051 Returns 0 on success, 1 if an update has unresolved files.
6983 Returns 0 on success, 1 if an update has unresolved files.
7052 """
6984 """
7053 fnames = (fname1,) + fnames
6985 fnames = (fname1,) + fnames
7054
6986
7055 with repo.lock():
6987 with repo.lock():
7056 for fname in fnames:
6988 for fname in fnames:
7057 f = hg.openpath(ui, fname)
6989 f = hg.openpath(ui, fname)
7058 gen = exchange.readbundle(ui, f, fname)
6990 gen = exchange.readbundle(ui, f, fname)
7059 if isinstance(gen, bundle2.unbundle20):
6991 if isinstance(gen, bundle2.unbundle20):
7060 tr = repo.transaction('unbundle')
6992 tr = repo.transaction('unbundle')
7061 try:
6993 try:
7062 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6994 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
7063 url='bundle:' + fname)
6995 url='bundle:' + fname)
7064 tr.close()
6996 tr.close()
7065 except error.BundleUnknownFeatureError as exc:
6997 except error.BundleUnknownFeatureError as exc:
7066 raise error.Abort(_('%s: unknown bundle feature, %s')
6998 raise error.Abort(_('%s: unknown bundle feature, %s')
7067 % (fname, exc),
6999 % (fname, exc),
7068 hint=_("see https://mercurial-scm.org/"
7000 hint=_("see https://mercurial-scm.org/"
7069 "wiki/BundleFeature for more "
7001 "wiki/BundleFeature for more "
7070 "information"))
7002 "information"))
7071 finally:
7003 finally:
7072 if tr:
7004 if tr:
7073 tr.release()
7005 tr.release()
7074 changes = [r.get('return', 0)
7006 changes = [r.get('return', 0)
7075 for r in op.records['changegroup']]
7007 for r in op.records['changegroup']]
7076 modheads = changegroup.combineresults(changes)
7008 modheads = changegroup.combineresults(changes)
7077 elif isinstance(gen, streamclone.streamcloneapplier):
7009 elif isinstance(gen, streamclone.streamcloneapplier):
7078 raise error.Abort(
7010 raise error.Abort(
7079 _('packed bundles cannot be applied with '
7011 _('packed bundles cannot be applied with '
7080 '"hg unbundle"'),
7012 '"hg unbundle"'),
7081 hint=_('use "hg debugapplystreamclonebundle"'))
7013 hint=_('use "hg debugapplystreamclonebundle"'))
7082 else:
7014 else:
7083 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7015 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
7084
7016
7085 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7017 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7086
7018
7087 @command('^update|up|checkout|co',
7019 @command('^update|up|checkout|co',
7088 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7020 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
7089 ('c', 'check', None, _('require clean working directory')),
7021 ('c', 'check', None, _('require clean working directory')),
7090 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7022 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
7091 ('r', 'rev', '', _('revision'), _('REV'))
7023 ('r', 'rev', '', _('revision'), _('REV'))
7092 ] + mergetoolopts,
7024 ] + mergetoolopts,
7093 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7025 _('[-c] [-C] [-d DATE] [[-r] REV]'))
7094 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7026 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
7095 tool=None):
7027 tool=None):
7096 """update working directory (or switch revisions)
7028 """update working directory (or switch revisions)
7097
7029
7098 Update the repository's working directory to the specified
7030 Update the repository's working directory to the specified
7099 changeset. If no changeset is specified, update to the tip of the
7031 changeset. If no changeset is specified, update to the tip of the
7100 current named branch and move the active bookmark (see :hg:`help
7032 current named branch and move the active bookmark (see :hg:`help
7101 bookmarks`).
7033 bookmarks`).
7102
7034
7103 Update sets the working directory's parent revision to the specified
7035 Update sets the working directory's parent revision to the specified
7104 changeset (see :hg:`help parents`).
7036 changeset (see :hg:`help parents`).
7105
7037
7106 If the changeset is not a descendant or ancestor of the working
7038 If the changeset is not a descendant or ancestor of the working
7107 directory's parent, the update is aborted. With the -c/--check
7039 directory's parent, the update is aborted. With the -c/--check
7108 option, the working directory is checked for uncommitted changes; if
7040 option, the working directory is checked for uncommitted changes; if
7109 none are found, the working directory is updated to the specified
7041 none are found, the working directory is updated to the specified
7110 changeset.
7042 changeset.
7111
7043
7112 .. container:: verbose
7044 .. container:: verbose
7113
7045
7114 The following rules apply when the working directory contains
7046 The following rules apply when the working directory contains
7115 uncommitted changes:
7047 uncommitted changes:
7116
7048
7117 1. If neither -c/--check nor -C/--clean is specified, and if
7049 1. If neither -c/--check nor -C/--clean is specified, and if
7118 the requested changeset is an ancestor or descendant of
7050 the requested changeset is an ancestor or descendant of
7119 the working directory's parent, the uncommitted changes
7051 the working directory's parent, the uncommitted changes
7120 are merged into the requested changeset and the merged
7052 are merged into the requested changeset and the merged
7121 result is left uncommitted. If the requested changeset is
7053 result is left uncommitted. If the requested changeset is
7122 not an ancestor or descendant (that is, it is on another
7054 not an ancestor or descendant (that is, it is on another
7123 branch), the update is aborted and the uncommitted changes
7055 branch), the update is aborted and the uncommitted changes
7124 are preserved.
7056 are preserved.
7125
7057
7126 2. With the -c/--check option, the update is aborted and the
7058 2. With the -c/--check option, the update is aborted and the
7127 uncommitted changes are preserved.
7059 uncommitted changes are preserved.
7128
7060
7129 3. With the -C/--clean option, uncommitted changes are discarded and
7061 3. With the -C/--clean option, uncommitted changes are discarded and
7130 the working directory is updated to the requested changeset.
7062 the working directory is updated to the requested changeset.
7131
7063
7132 To cancel an uncommitted merge (and lose your changes), use
7064 To cancel an uncommitted merge (and lose your changes), use
7133 :hg:`update --clean .`.
7065 :hg:`update --clean .`.
7134
7066
7135 Use null as the changeset to remove the working directory (like
7067 Use null as the changeset to remove the working directory (like
7136 :hg:`clone -U`).
7068 :hg:`clone -U`).
7137
7069
7138 If you want to revert just one file to an older revision, use
7070 If you want to revert just one file to an older revision, use
7139 :hg:`revert [-r REV] NAME`.
7071 :hg:`revert [-r REV] NAME`.
7140
7072
7141 See :hg:`help dates` for a list of formats valid for -d/--date.
7073 See :hg:`help dates` for a list of formats valid for -d/--date.
7142
7074
7143 Returns 0 on success, 1 if there are unresolved files.
7075 Returns 0 on success, 1 if there are unresolved files.
7144 """
7076 """
7145 if rev and node:
7077 if rev and node:
7146 raise error.Abort(_("please specify just one revision"))
7078 raise error.Abort(_("please specify just one revision"))
7147
7079
7148 if rev is None or rev == '':
7080 if rev is None or rev == '':
7149 rev = node
7081 rev = node
7150
7082
7151 if date and rev is not None:
7083 if date and rev is not None:
7152 raise error.Abort(_("you can't specify a revision and a date"))
7084 raise error.Abort(_("you can't specify a revision and a date"))
7153
7085
7154 if check and clean:
7086 if check and clean:
7155 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7087 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7156
7088
7157 with repo.wlock():
7089 with repo.wlock():
7158 cmdutil.clearunfinished(repo)
7090 cmdutil.clearunfinished(repo)
7159
7091
7160 if date:
7092 if date:
7161 rev = cmdutil.finddate(ui, repo, date)
7093 rev = cmdutil.finddate(ui, repo, date)
7162
7094
7163 # if we defined a bookmark, we have to remember the original name
7095 # if we defined a bookmark, we have to remember the original name
7164 brev = rev
7096 brev = rev
7165 rev = scmutil.revsingle(repo, rev, rev).rev()
7097 rev = scmutil.revsingle(repo, rev, rev).rev()
7166
7098
7167 if check:
7099 if check:
7168 cmdutil.bailifchanged(repo, merge=False)
7100 cmdutil.bailifchanged(repo, merge=False)
7169
7101
7170 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7102 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7171
7103
7172 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7104 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7173
7105
7174 @command('verify', [])
7106 @command('verify', [])
7175 def verify(ui, repo):
7107 def verify(ui, repo):
7176 """verify the integrity of the repository
7108 """verify the integrity of the repository
7177
7109
7178 Verify the integrity of the current repository.
7110 Verify the integrity of the current repository.
7179
7111
7180 This will perform an extensive check of the repository's
7112 This will perform an extensive check of the repository's
7181 integrity, validating the hashes and checksums of each entry in
7113 integrity, validating the hashes and checksums of each entry in
7182 the changelog, manifest, and tracked files, as well as the
7114 the changelog, manifest, and tracked files, as well as the
7183 integrity of their crosslinks and indices.
7115 integrity of their crosslinks and indices.
7184
7116
7185 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7117 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7186 for more information about recovery from corruption of the
7118 for more information about recovery from corruption of the
7187 repository.
7119 repository.
7188
7120
7189 Returns 0 on success, 1 if errors are encountered.
7121 Returns 0 on success, 1 if errors are encountered.
7190 """
7122 """
7191 return hg.verify(repo)
7123 return hg.verify(repo)
7192
7124
7193 @command('version', [] + formatteropts, norepo=True)
7125 @command('version', [] + formatteropts, norepo=True)
7194 def version_(ui, **opts):
7126 def version_(ui, **opts):
7195 """output version and copyright information"""
7127 """output version and copyright information"""
7196 fm = ui.formatter("version", opts)
7128 fm = ui.formatter("version", opts)
7197 fm.startitem()
7129 fm.startitem()
7198 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7130 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7199 util.version())
7131 util.version())
7200 license = _(
7132 license = _(
7201 "(see https://mercurial-scm.org for more information)\n"
7133 "(see https://mercurial-scm.org for more information)\n"
7202 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7134 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7203 "This is free software; see the source for copying conditions. "
7135 "This is free software; see the source for copying conditions. "
7204 "There is NO\nwarranty; "
7136 "There is NO\nwarranty; "
7205 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7137 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7206 )
7138 )
7207 if not ui.quiet:
7139 if not ui.quiet:
7208 fm.plain(license)
7140 fm.plain(license)
7209
7141
7210 if ui.verbose:
7142 if ui.verbose:
7211 fm.plain(_("\nEnabled extensions:\n\n"))
7143 fm.plain(_("\nEnabled extensions:\n\n"))
7212 # format names and versions into columns
7144 # format names and versions into columns
7213 names = []
7145 names = []
7214 vers = []
7146 vers = []
7215 isinternals = []
7147 isinternals = []
7216 for name, module in extensions.extensions():
7148 for name, module in extensions.extensions():
7217 names.append(name)
7149 names.append(name)
7218 vers.append(extensions.moduleversion(module) or None)
7150 vers.append(extensions.moduleversion(module) or None)
7219 isinternals.append(extensions.ismoduleinternal(module))
7151 isinternals.append(extensions.ismoduleinternal(module))
7220 fn = fm.nested("extensions")
7152 fn = fm.nested("extensions")
7221 if names:
7153 if names:
7222 namefmt = " %%-%ds " % max(len(n) for n in names)
7154 namefmt = " %%-%ds " % max(len(n) for n in names)
7223 places = [_("external"), _("internal")]
7155 places = [_("external"), _("internal")]
7224 for n, v, p in zip(names, vers, isinternals):
7156 for n, v, p in zip(names, vers, isinternals):
7225 fn.startitem()
7157 fn.startitem()
7226 fn.condwrite(ui.verbose, "name", namefmt, n)
7158 fn.condwrite(ui.verbose, "name", namefmt, n)
7227 if ui.verbose:
7159 if ui.verbose:
7228 fn.plain("%s " % places[p])
7160 fn.plain("%s " % places[p])
7229 fn.data(bundled=p)
7161 fn.data(bundled=p)
7230 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7162 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7231 if ui.verbose:
7163 if ui.verbose:
7232 fn.plain("\n")
7164 fn.plain("\n")
7233 fn.end()
7165 fn.end()
7234 fm.end()
7166 fm.end()
7235
7167
7236 def loadcmdtable(ui, name, cmdtable):
7168 def loadcmdtable(ui, name, cmdtable):
7237 """Load command functions from specified cmdtable
7169 """Load command functions from specified cmdtable
7238 """
7170 """
7239 overrides = [cmd for cmd in cmdtable if cmd in table]
7171 overrides = [cmd for cmd in cmdtable if cmd in table]
7240 if overrides:
7172 if overrides:
7241 ui.warn(_("extension '%s' overrides commands: %s\n")
7173 ui.warn(_("extension '%s' overrides commands: %s\n")
7242 % (name, " ".join(overrides)))
7174 % (name, " ".join(overrides)))
7243 table.update(cmdtable)
7175 table.update(cmdtable)
@@ -1,203 +1,275
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2016 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 os
10 import os
11
11
12 from .i18n import _
12 from .i18n import _
13 from .node import (
13 from .node import (
14 hex,
14 hex,
15 )
15 )
16 from . import (
16 from . import (
17 bundle2,
18 changegroup,
17 cmdutil,
19 cmdutil,
18 commands,
20 commands,
19 context,
21 context,
20 dagparser,
22 dagparser,
21 error,
23 error,
24 exchange,
25 hg,
22 lock as lockmod,
26 lock as lockmod,
23 revlog,
27 revlog,
24 scmutil,
28 scmutil,
25 simplemerge,
29 simplemerge,
26 )
30 )
27
31
28 release = lockmod.release
32 release = lockmod.release
29
33
30 # We reuse the command table from commands because it is easier than
34 # We reuse the command table from commands because it is easier than
31 # teaching dispatch about multiple tables.
35 # teaching dispatch about multiple tables.
32 command = cmdutil.command(commands.table)
36 command = cmdutil.command(commands.table)
33
37
34 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
38 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
35 def debugancestor(ui, repo, *args):
39 def debugancestor(ui, repo, *args):
36 """find the ancestor revision of two revisions in a given index"""
40 """find the ancestor revision of two revisions in a given index"""
37 if len(args) == 3:
41 if len(args) == 3:
38 index, rev1, rev2 = args
42 index, rev1, rev2 = args
39 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
43 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
40 lookup = r.lookup
44 lookup = r.lookup
41 elif len(args) == 2:
45 elif len(args) == 2:
42 if not repo:
46 if not repo:
43 raise error.Abort(_('there is no Mercurial repository here '
47 raise error.Abort(_('there is no Mercurial repository here '
44 '(.hg not found)'))
48 '(.hg not found)'))
45 rev1, rev2 = args
49 rev1, rev2 = args
46 r = repo.changelog
50 r = repo.changelog
47 lookup = repo.lookup
51 lookup = repo.lookup
48 else:
52 else:
49 raise error.Abort(_('either two or three arguments required'))
53 raise error.Abort(_('either two or three arguments required'))
50 a = r.ancestor(lookup(rev1), lookup(rev2))
54 a = r.ancestor(lookup(rev1), lookup(rev2))
51 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
55 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
52
56
53 @command('debugbuilddag',
57 @command('debugbuilddag',
54 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
58 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
55 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
59 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
56 ('n', 'new-file', None, _('add new file at each rev'))],
60 ('n', 'new-file', None, _('add new file at each rev'))],
57 _('[OPTION]... [TEXT]'))
61 _('[OPTION]... [TEXT]'))
58 def debugbuilddag(ui, repo, text=None,
62 def debugbuilddag(ui, repo, text=None,
59 mergeable_file=False,
63 mergeable_file=False,
60 overwritten_file=False,
64 overwritten_file=False,
61 new_file=False):
65 new_file=False):
62 """builds a repo with a given DAG from scratch in the current empty repo
66 """builds a repo with a given DAG from scratch in the current empty repo
63
67
64 The description of the DAG is read from stdin if not given on the
68 The description of the DAG is read from stdin if not given on the
65 command line.
69 command line.
66
70
67 Elements:
71 Elements:
68
72
69 - "+n" is a linear run of n nodes based on the current default parent
73 - "+n" is a linear run of n nodes based on the current default parent
70 - "." is a single node based on the current default parent
74 - "." is a single node based on the current default parent
71 - "$" resets the default parent to null (implied at the start);
75 - "$" resets the default parent to null (implied at the start);
72 otherwise the default parent is always the last node created
76 otherwise the default parent is always the last node created
73 - "<p" sets the default parent to the backref p
77 - "<p" sets the default parent to the backref p
74 - "*p" is a fork at parent p, which is a backref
78 - "*p" is a fork at parent p, which is a backref
75 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
79 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
76 - "/p2" is a merge of the preceding node and p2
80 - "/p2" is a merge of the preceding node and p2
77 - ":tag" defines a local tag for the preceding node
81 - ":tag" defines a local tag for the preceding node
78 - "@branch" sets the named branch for subsequent nodes
82 - "@branch" sets the named branch for subsequent nodes
79 - "#...\\n" is a comment up to the end of the line
83 - "#...\\n" is a comment up to the end of the line
80
84
81 Whitespace between the above elements is ignored.
85 Whitespace between the above elements is ignored.
82
86
83 A backref is either
87 A backref is either
84
88
85 - a number n, which references the node curr-n, where curr is the current
89 - a number n, which references the node curr-n, where curr is the current
86 node, or
90 node, or
87 - the name of a local tag you placed earlier using ":tag", or
91 - the name of a local tag you placed earlier using ":tag", or
88 - empty to denote the default parent.
92 - empty to denote the default parent.
89
93
90 All string valued-elements are either strictly alphanumeric, or must
94 All string valued-elements are either strictly alphanumeric, or must
91 be enclosed in double quotes ("..."), with "\\" as escape character.
95 be enclosed in double quotes ("..."), with "\\" as escape character.
92 """
96 """
93
97
94 if text is None:
98 if text is None:
95 ui.status(_("reading DAG from stdin\n"))
99 ui.status(_("reading DAG from stdin\n"))
96 text = ui.fin.read()
100 text = ui.fin.read()
97
101
98 cl = repo.changelog
102 cl = repo.changelog
99 if len(cl) > 0:
103 if len(cl) > 0:
100 raise error.Abort(_('repository is not empty'))
104 raise error.Abort(_('repository is not empty'))
101
105
102 # determine number of revs in DAG
106 # determine number of revs in DAG
103 total = 0
107 total = 0
104 for type, data in dagparser.parsedag(text):
108 for type, data in dagparser.parsedag(text):
105 if type == 'n':
109 if type == 'n':
106 total += 1
110 total += 1
107
111
108 if mergeable_file:
112 if mergeable_file:
109 linesperrev = 2
113 linesperrev = 2
110 # make a file with k lines per rev
114 # make a file with k lines per rev
111 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
115 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
112 initialmergedlines.append("")
116 initialmergedlines.append("")
113
117
114 tags = []
118 tags = []
115
119
116 wlock = lock = tr = None
120 wlock = lock = tr = None
117 try:
121 try:
118 wlock = repo.wlock()
122 wlock = repo.wlock()
119 lock = repo.lock()
123 lock = repo.lock()
120 tr = repo.transaction("builddag")
124 tr = repo.transaction("builddag")
121
125
122 at = -1
126 at = -1
123 atbranch = 'default'
127 atbranch = 'default'
124 nodeids = []
128 nodeids = []
125 id = 0
129 id = 0
126 ui.progress(_('building'), id, unit=_('revisions'), total=total)
130 ui.progress(_('building'), id, unit=_('revisions'), total=total)
127 for type, data in dagparser.parsedag(text):
131 for type, data in dagparser.parsedag(text):
128 if type == 'n':
132 if type == 'n':
129 ui.note(('node %s\n' % str(data)))
133 ui.note(('node %s\n' % str(data)))
130 id, ps = data
134 id, ps = data
131
135
132 files = []
136 files = []
133 fctxs = {}
137 fctxs = {}
134
138
135 p2 = None
139 p2 = None
136 if mergeable_file:
140 if mergeable_file:
137 fn = "mf"
141 fn = "mf"
138 p1 = repo[ps[0]]
142 p1 = repo[ps[0]]
139 if len(ps) > 1:
143 if len(ps) > 1:
140 p2 = repo[ps[1]]
144 p2 = repo[ps[1]]
141 pa = p1.ancestor(p2)
145 pa = p1.ancestor(p2)
142 base, local, other = [x[fn].data() for x in (pa, p1,
146 base, local, other = [x[fn].data() for x in (pa, p1,
143 p2)]
147 p2)]
144 m3 = simplemerge.Merge3Text(base, local, other)
148 m3 = simplemerge.Merge3Text(base, local, other)
145 ml = [l.strip() for l in m3.merge_lines()]
149 ml = [l.strip() for l in m3.merge_lines()]
146 ml.append("")
150 ml.append("")
147 elif at > 0:
151 elif at > 0:
148 ml = p1[fn].data().split("\n")
152 ml = p1[fn].data().split("\n")
149 else:
153 else:
150 ml = initialmergedlines
154 ml = initialmergedlines
151 ml[id * linesperrev] += " r%i" % id
155 ml[id * linesperrev] += " r%i" % id
152 mergedtext = "\n".join(ml)
156 mergedtext = "\n".join(ml)
153 files.append(fn)
157 files.append(fn)
154 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
158 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
155
159
156 if overwritten_file:
160 if overwritten_file:
157 fn = "of"
161 fn = "of"
158 files.append(fn)
162 files.append(fn)
159 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
163 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
160
164
161 if new_file:
165 if new_file:
162 fn = "nf%i" % id
166 fn = "nf%i" % id
163 files.append(fn)
167 files.append(fn)
164 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
168 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
165 if len(ps) > 1:
169 if len(ps) > 1:
166 if not p2:
170 if not p2:
167 p2 = repo[ps[1]]
171 p2 = repo[ps[1]]
168 for fn in p2:
172 for fn in p2:
169 if fn.startswith("nf"):
173 if fn.startswith("nf"):
170 files.append(fn)
174 files.append(fn)
171 fctxs[fn] = p2[fn]
175 fctxs[fn] = p2[fn]
172
176
173 def fctxfn(repo, cx, path):
177 def fctxfn(repo, cx, path):
174 return fctxs.get(path)
178 return fctxs.get(path)
175
179
176 if len(ps) == 0 or ps[0] < 0:
180 if len(ps) == 0 or ps[0] < 0:
177 pars = [None, None]
181 pars = [None, None]
178 elif len(ps) == 1:
182 elif len(ps) == 1:
179 pars = [nodeids[ps[0]], None]
183 pars = [nodeids[ps[0]], None]
180 else:
184 else:
181 pars = [nodeids[p] for p in ps]
185 pars = [nodeids[p] for p in ps]
182 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
186 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
183 date=(id, 0),
187 date=(id, 0),
184 user="debugbuilddag",
188 user="debugbuilddag",
185 extra={'branch': atbranch})
189 extra={'branch': atbranch})
186 nodeid = repo.commitctx(cx)
190 nodeid = repo.commitctx(cx)
187 nodeids.append(nodeid)
191 nodeids.append(nodeid)
188 at = id
192 at = id
189 elif type == 'l':
193 elif type == 'l':
190 id, name = data
194 id, name = data
191 ui.note(('tag %s\n' % name))
195 ui.note(('tag %s\n' % name))
192 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
196 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
193 elif type == 'a':
197 elif type == 'a':
194 ui.note(('branch %s\n' % data))
198 ui.note(('branch %s\n' % data))
195 atbranch = data
199 atbranch = data
196 ui.progress(_('building'), id, unit=_('revisions'), total=total)
200 ui.progress(_('building'), id, unit=_('revisions'), total=total)
197 tr.close()
201 tr.close()
198
202
199 if tags:
203 if tags:
200 repo.vfs.write("localtags", "".join(tags))
204 repo.vfs.write("localtags", "".join(tags))
201 finally:
205 finally:
202 ui.progress(_('building'), None)
206 ui.progress(_('building'), None)
203 release(tr, lock, wlock)
207 release(tr, lock, wlock)
208
209 @command('debugbundle',
210 [('a', 'all', None, _('show all details')),
211 ('', 'spec', None, _('print the bundlespec of the bundle'))],
212 _('FILE'),
213 norepo=True)
214 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
215 """lists the contents of a bundle"""
216 with hg.openpath(ui, bundlepath) as f:
217 if spec:
218 spec = exchange.getbundlespec(ui, f)
219 ui.write('%s\n' % spec)
220 return
221
222 gen = exchange.readbundle(ui, f, bundlepath)
223 if isinstance(gen, bundle2.unbundle20):
224 return _debugbundle2(ui, gen, all=all, **opts)
225 _debugchangegroup(ui, gen, all=all, **opts)
226
227 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
228 indent_string = ' ' * indent
229 if all:
230 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
231 % indent_string)
232
233 def showchunks(named):
234 ui.write("\n%s%s\n" % (indent_string, named))
235 chain = None
236 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
237 node = chunkdata['node']
238 p1 = chunkdata['p1']
239 p2 = chunkdata['p2']
240 cs = chunkdata['cs']
241 deltabase = chunkdata['deltabase']
242 delta = chunkdata['delta']
243 ui.write("%s%s %s %s %s %s %s\n" %
244 (indent_string, hex(node), hex(p1), hex(p2),
245 hex(cs), hex(deltabase), len(delta)))
246 chain = node
247
248 chunkdata = gen.changelogheader()
249 showchunks("changelog")
250 chunkdata = gen.manifestheader()
251 showchunks("manifest")
252 for chunkdata in iter(gen.filelogheader, {}):
253 fname = chunkdata['filename']
254 showchunks(fname)
255 else:
256 if isinstance(gen, bundle2.unbundle20):
257 raise error.Abort(_('use debugbundle2 for this file'))
258 chunkdata = gen.changelogheader()
259 chain = None
260 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
261 node = chunkdata['node']
262 ui.write("%s%s\n" % (indent_string, hex(node)))
263 chain = node
264
265 def _debugbundle2(ui, gen, all=None, **opts):
266 """lists the contents of a bundle2"""
267 if not isinstance(gen, bundle2.unbundle20):
268 raise error.Abort(_('not a bundle2 file'))
269 ui.write(('Stream params: %s\n' % repr(gen.params)))
270 for part in gen.iterparts():
271 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
272 if part.type == 'changegroup':
273 version = part.params.get('version', '01')
274 cg = changegroup.getunbundler(version, part, 'UN')
275 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
General Comments 0
You need to be logged in to leave comments. Login now