##// END OF EJS Templates
debugcommands: move 'debugdag' into the new module
Gregory Szorc -
r30514:625ccc95 default
parent child Browse files
Show More
@@ -1,7088 +1,7025 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import operator
12 import operator
13 import os
13 import os
14 import random
14 import random
15 import re
15 import re
16 import shlex
16 import shlex
17 import socket
17 import socket
18 import 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 copies,
38 copies,
39 dagparser,
40 dagutil,
39 dagutil,
41 destutil,
40 destutil,
42 dirstateguard,
41 dirstateguard,
43 discovery,
42 discovery,
44 encoding,
43 encoding,
45 error,
44 error,
46 exchange,
45 exchange,
47 extensions,
46 extensions,
48 fileset,
47 fileset,
49 formatter,
48 formatter,
50 graphmod,
49 graphmod,
51 hbisect,
50 hbisect,
52 help,
51 help,
53 hg,
52 hg,
54 localrepo,
53 localrepo,
55 lock as lockmod,
54 lock as lockmod,
56 merge as mergemod,
55 merge as mergemod,
57 minirst,
56 minirst,
58 obsolete,
57 obsolete,
59 patch,
58 patch,
60 phases,
59 phases,
61 policy,
60 policy,
62 pvec,
61 pvec,
63 pycompat,
62 pycompat,
64 repair,
63 repair,
65 revlog,
64 revlog,
66 revset,
65 revset,
67 scmutil,
66 scmutil,
68 server,
67 server,
69 setdiscovery,
68 setdiscovery,
70 sshserver,
69 sshserver,
71 sslutil,
70 sslutil,
72 streamclone,
71 streamclone,
73 templatekw,
72 templatekw,
74 templater,
73 templater,
75 treediscovery,
74 treediscovery,
76 ui as uimod,
75 ui as uimod,
77 util,
76 util,
78 )
77 )
79
78
80 release = lockmod.release
79 release = lockmod.release
81
80
82 table = {}
81 table = {}
83
82
84 command = cmdutil.command(table)
83 command = cmdutil.command(table)
85
84
86 # label constants
85 # label constants
87 # until 3.5, bookmarks.current was the advertised name, not
86 # until 3.5, bookmarks.current was the advertised name, not
88 # bookmarks.active, so we must use both to avoid breaking old
87 # bookmarks.active, so we must use both to avoid breaking old
89 # custom styles
88 # custom styles
90 activebookmarklabel = 'bookmarks.active bookmarks.current'
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
91
90
92 # common command options
91 # common command options
93
92
94 globalopts = [
93 globalopts = [
95 ('R', 'repository', '',
94 ('R', 'repository', '',
96 _('repository root directory or name of overlay bundle file'),
95 _('repository root directory or name of overlay bundle file'),
97 _('REPO')),
96 _('REPO')),
98 ('', 'cwd', '',
97 ('', 'cwd', '',
99 _('change working directory'), _('DIR')),
98 _('change working directory'), _('DIR')),
100 ('y', 'noninteractive', None,
99 ('y', 'noninteractive', None,
101 _('do not prompt, automatically pick the first choice for all prompts')),
100 _('do not prompt, automatically pick the first choice for all prompts')),
102 ('q', 'quiet', None, _('suppress output')),
101 ('q', 'quiet', None, _('suppress output')),
103 ('v', 'verbose', None, _('enable additional output')),
102 ('v', 'verbose', None, _('enable additional output')),
104 ('', 'config', [],
103 ('', 'config', [],
105 _('set/override config option (use \'section.name=value\')'),
104 _('set/override config option (use \'section.name=value\')'),
106 _('CONFIG')),
105 _('CONFIG')),
107 ('', 'debug', None, _('enable debugging output')),
106 ('', 'debug', None, _('enable debugging output')),
108 ('', 'debugger', None, _('start debugger')),
107 ('', 'debugger', None, _('start debugger')),
109 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
110 _('ENCODE')),
109 _('ENCODE')),
111 ('', 'encodingmode', encoding.encodingmode,
110 ('', 'encodingmode', encoding.encodingmode,
112 _('set the charset encoding mode'), _('MODE')),
111 _('set the charset encoding mode'), _('MODE')),
113 ('', 'traceback', None, _('always print a traceback on exception')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
114 ('', 'time', None, _('time how long the command takes')),
113 ('', 'time', None, _('time how long the command takes')),
115 ('', 'profile', None, _('print command execution profile')),
114 ('', 'profile', None, _('print command execution profile')),
116 ('', 'version', None, _('output version information and exit')),
115 ('', 'version', None, _('output version information and exit')),
117 ('h', 'help', None, _('display help and exit')),
116 ('h', 'help', None, _('display help and exit')),
118 ('', 'hidden', False, _('consider hidden changesets')),
117 ('', 'hidden', False, _('consider hidden changesets')),
119 ]
118 ]
120
119
121 dryrunopts = [('n', 'dry-run', None,
120 dryrunopts = [('n', 'dry-run', None,
122 _('do not perform actions, just print output'))]
121 _('do not perform actions, just print output'))]
123
122
124 remoteopts = [
123 remoteopts = [
125 ('e', 'ssh', '',
124 ('e', 'ssh', '',
126 _('specify ssh command to use'), _('CMD')),
125 _('specify ssh command to use'), _('CMD')),
127 ('', 'remotecmd', '',
126 ('', 'remotecmd', '',
128 _('specify hg command to run on the remote side'), _('CMD')),
127 _('specify hg command to run on the remote side'), _('CMD')),
129 ('', 'insecure', None,
128 ('', 'insecure', None,
130 _('do not verify server certificate (ignoring web.cacerts config)')),
129 _('do not verify server certificate (ignoring web.cacerts config)')),
131 ]
130 ]
132
131
133 walkopts = [
132 walkopts = [
134 ('I', 'include', [],
133 ('I', 'include', [],
135 _('include names matching the given patterns'), _('PATTERN')),
134 _('include names matching the given patterns'), _('PATTERN')),
136 ('X', 'exclude', [],
135 ('X', 'exclude', [],
137 _('exclude names matching the given patterns'), _('PATTERN')),
136 _('exclude names matching the given patterns'), _('PATTERN')),
138 ]
137 ]
139
138
140 commitopts = [
139 commitopts = [
141 ('m', 'message', '',
140 ('m', 'message', '',
142 _('use text as commit message'), _('TEXT')),
141 _('use text as commit message'), _('TEXT')),
143 ('l', 'logfile', '',
142 ('l', 'logfile', '',
144 _('read commit message from file'), _('FILE')),
143 _('read commit message from file'), _('FILE')),
145 ]
144 ]
146
145
147 commitopts2 = [
146 commitopts2 = [
148 ('d', 'date', '',
147 ('d', 'date', '',
149 _('record the specified date as commit date'), _('DATE')),
148 _('record the specified date as commit date'), _('DATE')),
150 ('u', 'user', '',
149 ('u', 'user', '',
151 _('record the specified user as committer'), _('USER')),
150 _('record the specified user as committer'), _('USER')),
152 ]
151 ]
153
152
154 # hidden for now
153 # hidden for now
155 formatteropts = [
154 formatteropts = [
156 ('T', 'template', '',
155 ('T', 'template', '',
157 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
158 ]
157 ]
159
158
160 templateopts = [
159 templateopts = [
161 ('', 'style', '',
160 ('', 'style', '',
162 _('display using template map file (DEPRECATED)'), _('STYLE')),
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
163 ('T', 'template', '',
162 ('T', 'template', '',
164 _('display with template'), _('TEMPLATE')),
163 _('display with template'), _('TEMPLATE')),
165 ]
164 ]
166
165
167 logopts = [
166 logopts = [
168 ('p', 'patch', None, _('show patch')),
167 ('p', 'patch', None, _('show patch')),
169 ('g', 'git', None, _('use git extended diff format')),
168 ('g', 'git', None, _('use git extended diff format')),
170 ('l', 'limit', '',
169 ('l', 'limit', '',
171 _('limit number of changes displayed'), _('NUM')),
170 _('limit number of changes displayed'), _('NUM')),
172 ('M', 'no-merges', None, _('do not show merges')),
171 ('M', 'no-merges', None, _('do not show merges')),
173 ('', 'stat', None, _('output diffstat-style summary of changes')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
174 ('G', 'graph', None, _("show the revision DAG")),
173 ('G', 'graph', None, _("show the revision DAG")),
175 ] + templateopts
174 ] + templateopts
176
175
177 diffopts = [
176 diffopts = [
178 ('a', 'text', None, _('treat all files as text')),
177 ('a', 'text', None, _('treat all files as text')),
179 ('g', 'git', None, _('use git extended diff format')),
178 ('g', 'git', None, _('use git extended diff format')),
180 ('', 'nodates', None, _('omit dates from diff headers'))
179 ('', 'nodates', None, _('omit dates from diff headers'))
181 ]
180 ]
182
181
183 diffwsopts = [
182 diffwsopts = [
184 ('w', 'ignore-all-space', None,
183 ('w', 'ignore-all-space', None,
185 _('ignore white space when comparing lines')),
184 _('ignore white space when comparing lines')),
186 ('b', 'ignore-space-change', None,
185 ('b', 'ignore-space-change', None,
187 _('ignore changes in the amount of white space')),
186 _('ignore changes in the amount of white space')),
188 ('B', 'ignore-blank-lines', None,
187 ('B', 'ignore-blank-lines', None,
189 _('ignore changes whose lines are all blank')),
188 _('ignore changes whose lines are all blank')),
190 ]
189 ]
191
190
192 diffopts2 = [
191 diffopts2 = [
193 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
194 ('p', 'show-function', None, _('show which function each change is in')),
193 ('p', 'show-function', None, _('show which function each change is in')),
195 ('', 'reverse', None, _('produce a diff that undoes the changes')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
196 ] + diffwsopts + [
195 ] + diffwsopts + [
197 ('U', 'unified', '',
196 ('U', 'unified', '',
198 _('number of lines of context to show'), _('NUM')),
197 _('number of lines of context to show'), _('NUM')),
199 ('', 'stat', None, _('output diffstat-style summary of changes')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
200 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
201 ]
200 ]
202
201
203 mergetoolopts = [
202 mergetoolopts = [
204 ('t', 'tool', '', _('specify merge tool')),
203 ('t', 'tool', '', _('specify merge tool')),
205 ]
204 ]
206
205
207 similarityopts = [
206 similarityopts = [
208 ('s', 'similarity', '',
207 ('s', 'similarity', '',
209 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
210 ]
209 ]
211
210
212 subrepoopts = [
211 subrepoopts = [
213 ('S', 'subrepos', None,
212 ('S', 'subrepos', None,
214 _('recurse into subrepositories'))
213 _('recurse into subrepositories'))
215 ]
214 ]
216
215
217 debugrevlogopts = [
216 debugrevlogopts = [
218 ('c', 'changelog', False, _('open changelog')),
217 ('c', 'changelog', False, _('open changelog')),
219 ('m', 'manifest', False, _('open manifest')),
218 ('m', 'manifest', False, _('open manifest')),
220 ('', 'dir', '', _('open directory manifest')),
219 ('', 'dir', '', _('open directory manifest')),
221 ]
220 ]
222
221
223 # Commands start here, listed alphabetically
222 # Commands start here, listed alphabetically
224
223
225 @command('^add',
224 @command('^add',
226 walkopts + subrepoopts + dryrunopts,
225 walkopts + subrepoopts + dryrunopts,
227 _('[OPTION]... [FILE]...'),
226 _('[OPTION]... [FILE]...'),
228 inferrepo=True)
227 inferrepo=True)
229 def add(ui, repo, *pats, **opts):
228 def add(ui, repo, *pats, **opts):
230 """add the specified files on the next commit
229 """add the specified files on the next commit
231
230
232 Schedule files to be version controlled and added to the
231 Schedule files to be version controlled and added to the
233 repository.
232 repository.
234
233
235 The files will be added to the repository at the next commit. To
234 The files will be added to the repository at the next commit. To
236 undo an add before that, see :hg:`forget`.
235 undo an add before that, see :hg:`forget`.
237
236
238 If no names are given, add all files to the repository (except
237 If no names are given, add all files to the repository (except
239 files matching ``.hgignore``).
238 files matching ``.hgignore``).
240
239
241 .. container:: verbose
240 .. container:: verbose
242
241
243 Examples:
242 Examples:
244
243
245 - New (unknown) files are added
244 - New (unknown) files are added
246 automatically by :hg:`add`::
245 automatically by :hg:`add`::
247
246
248 $ ls
247 $ ls
249 foo.c
248 foo.c
250 $ hg status
249 $ hg status
251 ? foo.c
250 ? foo.c
252 $ hg add
251 $ hg add
253 adding foo.c
252 adding foo.c
254 $ hg status
253 $ hg status
255 A foo.c
254 A foo.c
256
255
257 - Specific files to be added can be specified::
256 - Specific files to be added can be specified::
258
257
259 $ ls
258 $ ls
260 bar.c foo.c
259 bar.c foo.c
261 $ hg status
260 $ hg status
262 ? bar.c
261 ? bar.c
263 ? foo.c
262 ? foo.c
264 $ hg add bar.c
263 $ hg add bar.c
265 $ hg status
264 $ hg status
266 A bar.c
265 A bar.c
267 ? foo.c
266 ? foo.c
268
267
269 Returns 0 if all files are successfully added.
268 Returns 0 if all files are successfully added.
270 """
269 """
271
270
272 m = scmutil.match(repo[None], pats, opts)
271 m = scmutil.match(repo[None], pats, opts)
273 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
274 return rejected and 1 or 0
273 return rejected and 1 or 0
275
274
276 @command('addremove',
275 @command('addremove',
277 similarityopts + subrepoopts + walkopts + dryrunopts,
276 similarityopts + subrepoopts + walkopts + dryrunopts,
278 _('[OPTION]... [FILE]...'),
277 _('[OPTION]... [FILE]...'),
279 inferrepo=True)
278 inferrepo=True)
280 def addremove(ui, repo, *pats, **opts):
279 def addremove(ui, repo, *pats, **opts):
281 """add all new files, delete all missing files
280 """add all new files, delete all missing files
282
281
283 Add all new files and remove all missing files from the
282 Add all new files and remove all missing files from the
284 repository.
283 repository.
285
284
286 Unless names are given, new files are ignored if they match any of
285 Unless names are given, new files are ignored if they match any of
287 the patterns in ``.hgignore``. As with add, these changes take
286 the patterns in ``.hgignore``. As with add, these changes take
288 effect at the next commit.
287 effect at the next commit.
289
288
290 Use the -s/--similarity option to detect renamed files. This
289 Use the -s/--similarity option to detect renamed files. This
291 option takes a percentage between 0 (disabled) and 100 (files must
290 option takes a percentage between 0 (disabled) and 100 (files must
292 be identical) as its parameter. With a parameter greater than 0,
291 be identical) as its parameter. With a parameter greater than 0,
293 this compares every removed file with every added file and records
292 this compares every removed file with every added file and records
294 those similar enough as renames. Detecting renamed files this way
293 those similar enough as renames. Detecting renamed files this way
295 can be expensive. After using this option, :hg:`status -C` can be
294 can be expensive. After using this option, :hg:`status -C` can be
296 used to check which files were identified as moved or renamed. If
295 used to check which files were identified as moved or renamed. If
297 not specified, -s/--similarity defaults to 100 and only renames of
296 not specified, -s/--similarity defaults to 100 and only renames of
298 identical files are detected.
297 identical files are detected.
299
298
300 .. container:: verbose
299 .. container:: verbose
301
300
302 Examples:
301 Examples:
303
302
304 - A number of files (bar.c and foo.c) are new,
303 - A number of files (bar.c and foo.c) are new,
305 while foobar.c has been removed (without using :hg:`remove`)
304 while foobar.c has been removed (without using :hg:`remove`)
306 from the repository::
305 from the repository::
307
306
308 $ ls
307 $ ls
309 bar.c foo.c
308 bar.c foo.c
310 $ hg status
309 $ hg status
311 ! foobar.c
310 ! foobar.c
312 ? bar.c
311 ? bar.c
313 ? foo.c
312 ? foo.c
314 $ hg addremove
313 $ hg addremove
315 adding bar.c
314 adding bar.c
316 adding foo.c
315 adding foo.c
317 removing foobar.c
316 removing foobar.c
318 $ hg status
317 $ hg status
319 A bar.c
318 A bar.c
320 A foo.c
319 A foo.c
321 R foobar.c
320 R foobar.c
322
321
323 - A file foobar.c was moved to foo.c without using :hg:`rename`.
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
324 Afterwards, it was edited slightly::
323 Afterwards, it was edited slightly::
325
324
326 $ ls
325 $ ls
327 foo.c
326 foo.c
328 $ hg status
327 $ hg status
329 ! foobar.c
328 ! foobar.c
330 ? foo.c
329 ? foo.c
331 $ hg addremove --similarity 90
330 $ hg addremove --similarity 90
332 removing foobar.c
331 removing foobar.c
333 adding foo.c
332 adding foo.c
334 recording removal of foobar.c as rename to foo.c (94% similar)
333 recording removal of foobar.c as rename to foo.c (94% similar)
335 $ hg status -C
334 $ hg status -C
336 A foo.c
335 A foo.c
337 foobar.c
336 foobar.c
338 R foobar.c
337 R foobar.c
339
338
340 Returns 0 if all files are successfully added.
339 Returns 0 if all files are successfully added.
341 """
340 """
342 try:
341 try:
343 sim = float(opts.get('similarity') or 100)
342 sim = float(opts.get('similarity') or 100)
344 except ValueError:
343 except ValueError:
345 raise error.Abort(_('similarity must be a number'))
344 raise error.Abort(_('similarity must be a number'))
346 if sim < 0 or sim > 100:
345 if sim < 0 or sim > 100:
347 raise error.Abort(_('similarity must be between 0 and 100'))
346 raise error.Abort(_('similarity must be between 0 and 100'))
348 matcher = scmutil.match(repo[None], pats, opts)
347 matcher = scmutil.match(repo[None], pats, opts)
349 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
350
349
351 @command('^annotate|blame',
350 @command('^annotate|blame',
352 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
353 ('', 'follow', None,
352 ('', 'follow', None,
354 _('follow copies/renames and list the filename (DEPRECATED)')),
353 _('follow copies/renames and list the filename (DEPRECATED)')),
355 ('', 'no-follow', None, _("don't follow copies and renames")),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
356 ('a', 'text', None, _('treat all files as text')),
355 ('a', 'text', None, _('treat all files as text')),
357 ('u', 'user', None, _('list the author (long with -v)')),
356 ('u', 'user', None, _('list the author (long with -v)')),
358 ('f', 'file', None, _('list the filename')),
357 ('f', 'file', None, _('list the filename')),
359 ('d', 'date', None, _('list the date (short with -q)')),
358 ('d', 'date', None, _('list the date (short with -q)')),
360 ('n', 'number', None, _('list the revision number (default)')),
359 ('n', 'number', None, _('list the revision number (default)')),
361 ('c', 'changeset', None, _('list the changeset')),
360 ('c', 'changeset', None, _('list the changeset')),
362 ('l', 'line-number', None, _('show line number at the first appearance'))
361 ('l', 'line-number', None, _('show line number at the first appearance'))
363 ] + diffwsopts + walkopts + formatteropts,
362 ] + diffwsopts + walkopts + formatteropts,
364 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
365 inferrepo=True)
364 inferrepo=True)
366 def annotate(ui, repo, *pats, **opts):
365 def annotate(ui, repo, *pats, **opts):
367 """show changeset information by line for each file
366 """show changeset information by line for each file
368
367
369 List changes in files, showing the revision id responsible for
368 List changes in files, showing the revision id responsible for
370 each line.
369 each line.
371
370
372 This command is useful for discovering when a change was made and
371 This command is useful for discovering when a change was made and
373 by whom.
372 by whom.
374
373
375 If you include --file, --user, or --date, the revision number is
374 If you include --file, --user, or --date, the revision number is
376 suppressed unless you also include --number.
375 suppressed unless you also include --number.
377
376
378 Without the -a/--text option, annotate will avoid processing files
377 Without the -a/--text option, annotate will avoid processing files
379 it detects as binary. With -a, annotate will annotate the file
378 it detects as binary. With -a, annotate will annotate the file
380 anyway, although the results will probably be neither useful
379 anyway, although the results will probably be neither useful
381 nor desirable.
380 nor desirable.
382
381
383 Returns 0 on success.
382 Returns 0 on success.
384 """
383 """
385 if not pats:
384 if not pats:
386 raise error.Abort(_('at least one filename or pattern is required'))
385 raise error.Abort(_('at least one filename or pattern is required'))
387
386
388 if opts.get('follow'):
387 if opts.get('follow'):
389 # --follow is deprecated and now just an alias for -f/--file
388 # --follow is deprecated and now just an alias for -f/--file
390 # to mimic the behavior of Mercurial before version 1.5
389 # to mimic the behavior of Mercurial before version 1.5
391 opts['file'] = True
390 opts['file'] = True
392
391
393 ctx = scmutil.revsingle(repo, opts.get('rev'))
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
394
393
395 fm = ui.formatter('annotate', opts)
394 fm = ui.formatter('annotate', opts)
396 if ui.quiet:
395 if ui.quiet:
397 datefunc = util.shortdate
396 datefunc = util.shortdate
398 else:
397 else:
399 datefunc = util.datestr
398 datefunc = util.datestr
400 if ctx.rev() is None:
399 if ctx.rev() is None:
401 def hexfn(node):
400 def hexfn(node):
402 if node is None:
401 if node is None:
403 return None
402 return None
404 else:
403 else:
405 return fm.hexfunc(node)
404 return fm.hexfunc(node)
406 if opts.get('changeset'):
405 if opts.get('changeset'):
407 # omit "+" suffix which is appended to node hex
406 # omit "+" suffix which is appended to node hex
408 def formatrev(rev):
407 def formatrev(rev):
409 if rev is None:
408 if rev is None:
410 return '%d' % ctx.p1().rev()
409 return '%d' % ctx.p1().rev()
411 else:
410 else:
412 return '%d' % rev
411 return '%d' % rev
413 else:
412 else:
414 def formatrev(rev):
413 def formatrev(rev):
415 if rev is None:
414 if rev is None:
416 return '%d+' % ctx.p1().rev()
415 return '%d+' % ctx.p1().rev()
417 else:
416 else:
418 return '%d ' % rev
417 return '%d ' % rev
419 def formathex(hex):
418 def formathex(hex):
420 if hex is None:
419 if hex is None:
421 return '%s+' % fm.hexfunc(ctx.p1().node())
420 return '%s+' % fm.hexfunc(ctx.p1().node())
422 else:
421 else:
423 return '%s ' % hex
422 return '%s ' % hex
424 else:
423 else:
425 hexfn = fm.hexfunc
424 hexfn = fm.hexfunc
426 formatrev = formathex = str
425 formatrev = formathex = str
427
426
428 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
429 ('number', ' ', lambda x: x[0].rev(), formatrev),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
430 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
431 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
432 ('file', ' ', lambda x: x[0].path(), str),
431 ('file', ' ', lambda x: x[0].path(), str),
433 ('line_number', ':', lambda x: x[1], str),
432 ('line_number', ':', lambda x: x[1], str),
434 ]
433 ]
435 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
436
435
437 if (not opts.get('user') and not opts.get('changeset')
436 if (not opts.get('user') and not opts.get('changeset')
438 and not opts.get('date') and not opts.get('file')):
437 and not opts.get('date') and not opts.get('file')):
439 opts['number'] = True
438 opts['number'] = True
440
439
441 linenumber = opts.get('line_number') is not None
440 linenumber = opts.get('line_number') is not None
442 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
443 raise error.Abort(_('at least one of -n/-c is required for -l'))
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
444
443
445 if fm.isplain():
444 if fm.isplain():
446 def makefunc(get, fmt):
445 def makefunc(get, fmt):
447 return lambda x: fmt(get(x))
446 return lambda x: fmt(get(x))
448 else:
447 else:
449 def makefunc(get, fmt):
448 def makefunc(get, fmt):
450 return get
449 return get
451 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
452 if opts.get(op)]
451 if opts.get(op)]
453 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
454 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
455 if opts.get(op))
454 if opts.get(op))
456
455
457 def bad(x, y):
456 def bad(x, y):
458 raise error.Abort("%s: %s" % (x, y))
457 raise error.Abort("%s: %s" % (x, y))
459
458
460 m = scmutil.match(ctx, pats, opts, badfn=bad)
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
461
460
462 follow = not opts.get('no_follow')
461 follow = not opts.get('no_follow')
463 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
464 whitespace=True)
463 whitespace=True)
465 for abs in ctx.walk(m):
464 for abs in ctx.walk(m):
466 fctx = ctx[abs]
465 fctx = ctx[abs]
467 if not opts.get('text') and util.binary(fctx.data()):
466 if not opts.get('text') and util.binary(fctx.data()):
468 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
469 continue
468 continue
470
469
471 lines = fctx.annotate(follow=follow, linenumber=linenumber,
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
472 diffopts=diffopts)
471 diffopts=diffopts)
473 if not lines:
472 if not lines:
474 continue
473 continue
475 formats = []
474 formats = []
476 pieces = []
475 pieces = []
477
476
478 for f, sep in funcmap:
477 for f, sep in funcmap:
479 l = [f(n) for n, dummy in lines]
478 l = [f(n) for n, dummy in lines]
480 if fm.isplain():
479 if fm.isplain():
481 sizes = [encoding.colwidth(x) for x in l]
480 sizes = [encoding.colwidth(x) for x in l]
482 ml = max(sizes)
481 ml = max(sizes)
483 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
482 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
484 else:
483 else:
485 formats.append(['%s' for x in l])
484 formats.append(['%s' for x in l])
486 pieces.append(l)
485 pieces.append(l)
487
486
488 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
489 fm.startitem()
488 fm.startitem()
490 fm.write(fields, "".join(f), *p)
489 fm.write(fields, "".join(f), *p)
491 fm.write('line', ": %s", l[1])
490 fm.write('line', ": %s", l[1])
492
491
493 if not lines[-1][1].endswith('\n'):
492 if not lines[-1][1].endswith('\n'):
494 fm.plain('\n')
493 fm.plain('\n')
495
494
496 fm.end()
495 fm.end()
497
496
498 @command('archive',
497 @command('archive',
499 [('', 'no-decode', None, _('do not pass files through decoders')),
498 [('', 'no-decode', None, _('do not pass files through decoders')),
500 ('p', 'prefix', '', _('directory prefix for files in archive'),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
501 _('PREFIX')),
500 _('PREFIX')),
502 ('r', 'rev', '', _('revision to distribute'), _('REV')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
503 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
504 ] + subrepoopts + walkopts,
503 ] + subrepoopts + walkopts,
505 _('[OPTION]... DEST'))
504 _('[OPTION]... DEST'))
506 def archive(ui, repo, dest, **opts):
505 def archive(ui, repo, dest, **opts):
507 '''create an unversioned archive of a repository revision
506 '''create an unversioned archive of a repository revision
508
507
509 By default, the revision used is the parent of the working
508 By default, the revision used is the parent of the working
510 directory; use -r/--rev to specify a different revision.
509 directory; use -r/--rev to specify a different revision.
511
510
512 The archive type is automatically detected based on file
511 The archive type is automatically detected based on file
513 extension (to override, use -t/--type).
512 extension (to override, use -t/--type).
514
513
515 .. container:: verbose
514 .. container:: verbose
516
515
517 Examples:
516 Examples:
518
517
519 - create a zip file containing the 1.0 release::
518 - create a zip file containing the 1.0 release::
520
519
521 hg archive -r 1.0 project-1.0.zip
520 hg archive -r 1.0 project-1.0.zip
522
521
523 - create a tarball excluding .hg files::
522 - create a tarball excluding .hg files::
524
523
525 hg archive project.tar.gz -X ".hg*"
524 hg archive project.tar.gz -X ".hg*"
526
525
527 Valid types are:
526 Valid types are:
528
527
529 :``files``: a directory full of files (default)
528 :``files``: a directory full of files (default)
530 :``tar``: tar archive, uncompressed
529 :``tar``: tar archive, uncompressed
531 :``tbz2``: tar archive, compressed using bzip2
530 :``tbz2``: tar archive, compressed using bzip2
532 :``tgz``: tar archive, compressed using gzip
531 :``tgz``: tar archive, compressed using gzip
533 :``uzip``: zip archive, uncompressed
532 :``uzip``: zip archive, uncompressed
534 :``zip``: zip archive, compressed using deflate
533 :``zip``: zip archive, compressed using deflate
535
534
536 The exact name of the destination archive or directory is given
535 The exact name of the destination archive or directory is given
537 using a format string; see :hg:`help export` for details.
536 using a format string; see :hg:`help export` for details.
538
537
539 Each member added to an archive file has a directory prefix
538 Each member added to an archive file has a directory prefix
540 prepended. Use -p/--prefix to specify a format string for the
539 prepended. Use -p/--prefix to specify a format string for the
541 prefix. The default is the basename of the archive, with suffixes
540 prefix. The default is the basename of the archive, with suffixes
542 removed.
541 removed.
543
542
544 Returns 0 on success.
543 Returns 0 on success.
545 '''
544 '''
546
545
547 ctx = scmutil.revsingle(repo, opts.get('rev'))
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
548 if not ctx:
547 if not ctx:
549 raise error.Abort(_('no working directory: please specify a revision'))
548 raise error.Abort(_('no working directory: please specify a revision'))
550 node = ctx.node()
549 node = ctx.node()
551 dest = cmdutil.makefilename(repo, dest, node)
550 dest = cmdutil.makefilename(repo, dest, node)
552 if os.path.realpath(dest) == repo.root:
551 if os.path.realpath(dest) == repo.root:
553 raise error.Abort(_('repository root cannot be destination'))
552 raise error.Abort(_('repository root cannot be destination'))
554
553
555 kind = opts.get('type') or archival.guesskind(dest) or 'files'
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
556 prefix = opts.get('prefix')
555 prefix = opts.get('prefix')
557
556
558 if dest == '-':
557 if dest == '-':
559 if kind == 'files':
558 if kind == 'files':
560 raise error.Abort(_('cannot archive plain files to stdout'))
559 raise error.Abort(_('cannot archive plain files to stdout'))
561 dest = cmdutil.makefileobj(repo, dest)
560 dest = cmdutil.makefileobj(repo, dest)
562 if not prefix:
561 if not prefix:
563 prefix = os.path.basename(repo.root) + '-%h'
562 prefix = os.path.basename(repo.root) + '-%h'
564
563
565 prefix = cmdutil.makefilename(repo, prefix, node)
564 prefix = cmdutil.makefilename(repo, prefix, node)
566 matchfn = scmutil.match(ctx, [], opts)
565 matchfn = scmutil.match(ctx, [], opts)
567 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
568 matchfn, prefix, subrepos=opts.get('subrepos'))
567 matchfn, prefix, subrepos=opts.get('subrepos'))
569
568
570 @command('backout',
569 @command('backout',
571 [('', 'merge', None, _('merge with old dirstate parent after backout')),
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
572 ('', 'commit', None,
571 ('', 'commit', None,
573 _('commit if no conflicts were encountered (DEPRECATED)')),
572 _('commit if no conflicts were encountered (DEPRECATED)')),
574 ('', 'no-commit', None, _('do not commit')),
573 ('', 'no-commit', None, _('do not commit')),
575 ('', 'parent', '',
574 ('', 'parent', '',
576 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
577 ('r', 'rev', '', _('revision to backout'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
578 ('e', 'edit', False, _('invoke editor on commit messages')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
579 ] + mergetoolopts + walkopts + commitopts + commitopts2,
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
580 _('[OPTION]... [-r] REV'))
579 _('[OPTION]... [-r] REV'))
581 def backout(ui, repo, node=None, rev=None, **opts):
580 def backout(ui, repo, node=None, rev=None, **opts):
582 '''reverse effect of earlier changeset
581 '''reverse effect of earlier changeset
583
582
584 Prepare a new changeset with the effect of REV undone in the
583 Prepare a new changeset with the effect of REV undone in the
585 current working directory. If no conflicts were encountered,
584 current working directory. If no conflicts were encountered,
586 it will be committed immediately.
585 it will be committed immediately.
587
586
588 If REV is the parent of the working directory, then this new changeset
587 If REV is the parent of the working directory, then this new changeset
589 is committed automatically (unless --no-commit is specified).
588 is committed automatically (unless --no-commit is specified).
590
589
591 .. note::
590 .. note::
592
591
593 :hg:`backout` cannot be used to fix either an unwanted or
592 :hg:`backout` cannot be used to fix either an unwanted or
594 incorrect merge.
593 incorrect merge.
595
594
596 .. container:: verbose
595 .. container:: verbose
597
596
598 Examples:
597 Examples:
599
598
600 - Reverse the effect of the parent of the working directory.
599 - Reverse the effect of the parent of the working directory.
601 This backout will be committed immediately::
600 This backout will be committed immediately::
602
601
603 hg backout -r .
602 hg backout -r .
604
603
605 - Reverse the effect of previous bad revision 23::
604 - Reverse the effect of previous bad revision 23::
606
605
607 hg backout -r 23
606 hg backout -r 23
608
607
609 - Reverse the effect of previous bad revision 23 and
608 - Reverse the effect of previous bad revision 23 and
610 leave changes uncommitted::
609 leave changes uncommitted::
611
610
612 hg backout -r 23 --no-commit
611 hg backout -r 23 --no-commit
613 hg commit -m "Backout revision 23"
612 hg commit -m "Backout revision 23"
614
613
615 By default, the pending changeset will have one parent,
614 By default, the pending changeset will have one parent,
616 maintaining a linear history. With --merge, the pending
615 maintaining a linear history. With --merge, the pending
617 changeset will instead have two parents: the old parent of the
616 changeset will instead have two parents: the old parent of the
618 working directory and a new child of REV that simply undoes REV.
617 working directory and a new child of REV that simply undoes REV.
619
618
620 Before version 1.7, the behavior without --merge was equivalent
619 Before version 1.7, the behavior without --merge was equivalent
621 to specifying --merge followed by :hg:`update --clean .` to
620 to specifying --merge followed by :hg:`update --clean .` to
622 cancel the merge and leave the child of REV as a head to be
621 cancel the merge and leave the child of REV as a head to be
623 merged separately.
622 merged separately.
624
623
625 See :hg:`help dates` for a list of formats valid for -d/--date.
624 See :hg:`help dates` for a list of formats valid for -d/--date.
626
625
627 See :hg:`help revert` for a way to restore files to the state
626 See :hg:`help revert` for a way to restore files to the state
628 of another revision.
627 of another revision.
629
628
630 Returns 0 on success, 1 if nothing to backout or there are unresolved
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
631 files.
630 files.
632 '''
631 '''
633 wlock = lock = None
632 wlock = lock = None
634 try:
633 try:
635 wlock = repo.wlock()
634 wlock = repo.wlock()
636 lock = repo.lock()
635 lock = repo.lock()
637 return _dobackout(ui, repo, node, rev, **opts)
636 return _dobackout(ui, repo, node, rev, **opts)
638 finally:
637 finally:
639 release(lock, wlock)
638 release(lock, wlock)
640
639
641 def _dobackout(ui, repo, node=None, rev=None, **opts):
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
642 if opts.get('commit') and opts.get('no_commit'):
641 if opts.get('commit') and opts.get('no_commit'):
643 raise error.Abort(_("cannot use --commit with --no-commit"))
642 raise error.Abort(_("cannot use --commit with --no-commit"))
644 if opts.get('merge') and opts.get('no_commit'):
643 if opts.get('merge') and opts.get('no_commit'):
645 raise error.Abort(_("cannot use --merge with --no-commit"))
644 raise error.Abort(_("cannot use --merge with --no-commit"))
646
645
647 if rev and node:
646 if rev and node:
648 raise error.Abort(_("please specify just one revision"))
647 raise error.Abort(_("please specify just one revision"))
649
648
650 if not rev:
649 if not rev:
651 rev = node
650 rev = node
652
651
653 if not rev:
652 if not rev:
654 raise error.Abort(_("please specify a revision to backout"))
653 raise error.Abort(_("please specify a revision to backout"))
655
654
656 date = opts.get('date')
655 date = opts.get('date')
657 if date:
656 if date:
658 opts['date'] = util.parsedate(date)
657 opts['date'] = util.parsedate(date)
659
658
660 cmdutil.checkunfinished(repo)
659 cmdutil.checkunfinished(repo)
661 cmdutil.bailifchanged(repo)
660 cmdutil.bailifchanged(repo)
662 node = scmutil.revsingle(repo, rev).node()
661 node = scmutil.revsingle(repo, rev).node()
663
662
664 op1, op2 = repo.dirstate.parents()
663 op1, op2 = repo.dirstate.parents()
665 if not repo.changelog.isancestor(node, op1):
664 if not repo.changelog.isancestor(node, op1):
666 raise error.Abort(_('cannot backout change that is not an ancestor'))
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
667
666
668 p1, p2 = repo.changelog.parents(node)
667 p1, p2 = repo.changelog.parents(node)
669 if p1 == nullid:
668 if p1 == nullid:
670 raise error.Abort(_('cannot backout a change with no parents'))
669 raise error.Abort(_('cannot backout a change with no parents'))
671 if p2 != nullid:
670 if p2 != nullid:
672 if not opts.get('parent'):
671 if not opts.get('parent'):
673 raise error.Abort(_('cannot backout a merge changeset'))
672 raise error.Abort(_('cannot backout a merge changeset'))
674 p = repo.lookup(opts['parent'])
673 p = repo.lookup(opts['parent'])
675 if p not in (p1, p2):
674 if p not in (p1, p2):
676 raise error.Abort(_('%s is not a parent of %s') %
675 raise error.Abort(_('%s is not a parent of %s') %
677 (short(p), short(node)))
676 (short(p), short(node)))
678 parent = p
677 parent = p
679 else:
678 else:
680 if opts.get('parent'):
679 if opts.get('parent'):
681 raise error.Abort(_('cannot use --parent on non-merge changeset'))
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
682 parent = p1
681 parent = p1
683
682
684 # the backout should appear on the same branch
683 # the backout should appear on the same branch
685 branch = repo.dirstate.branch()
684 branch = repo.dirstate.branch()
686 bheads = repo.branchheads(branch)
685 bheads = repo.branchheads(branch)
687 rctx = scmutil.revsingle(repo, hex(parent))
686 rctx = scmutil.revsingle(repo, hex(parent))
688 if not opts.get('merge') and op1 != node:
687 if not opts.get('merge') and op1 != node:
689 dsguard = dirstateguard.dirstateguard(repo, 'backout')
688 dsguard = dirstateguard.dirstateguard(repo, 'backout')
690 try:
689 try:
691 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
692 'backout')
691 'backout')
693 stats = mergemod.update(repo, parent, True, True, node, False)
692 stats = mergemod.update(repo, parent, True, True, node, False)
694 repo.setparents(op1, op2)
693 repo.setparents(op1, op2)
695 dsguard.close()
694 dsguard.close()
696 hg._showstats(repo, stats)
695 hg._showstats(repo, stats)
697 if stats[3]:
696 if stats[3]:
698 repo.ui.status(_("use 'hg resolve' to retry unresolved "
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
699 "file merges\n"))
698 "file merges\n"))
700 return 1
699 return 1
701 finally:
700 finally:
702 ui.setconfig('ui', 'forcemerge', '', '')
701 ui.setconfig('ui', 'forcemerge', '', '')
703 lockmod.release(dsguard)
702 lockmod.release(dsguard)
704 else:
703 else:
705 hg.clean(repo, node, show_stats=False)
704 hg.clean(repo, node, show_stats=False)
706 repo.dirstate.setbranch(branch)
705 repo.dirstate.setbranch(branch)
707 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
708
707
709 if opts.get('no_commit'):
708 if opts.get('no_commit'):
710 msg = _("changeset %s backed out, "
709 msg = _("changeset %s backed out, "
711 "don't forget to commit.\n")
710 "don't forget to commit.\n")
712 ui.status(msg % short(node))
711 ui.status(msg % short(node))
713 return 0
712 return 0
714
713
715 def commitfunc(ui, repo, message, match, opts):
714 def commitfunc(ui, repo, message, match, opts):
716 editform = 'backout'
715 editform = 'backout'
717 e = cmdutil.getcommiteditor(editform=editform, **opts)
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
718 if not message:
717 if not message:
719 # we don't translate commit messages
718 # we don't translate commit messages
720 message = "Backed out changeset %s" % short(node)
719 message = "Backed out changeset %s" % short(node)
721 e = cmdutil.getcommiteditor(edit=True, editform=editform)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
722 return repo.commit(message, opts.get('user'), opts.get('date'),
721 return repo.commit(message, opts.get('user'), opts.get('date'),
723 match, editor=e)
722 match, editor=e)
724 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
725 if not newnode:
724 if not newnode:
726 ui.status(_("nothing changed\n"))
725 ui.status(_("nothing changed\n"))
727 return 1
726 return 1
728 cmdutil.commitstatus(repo, newnode, branch, bheads)
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
729
728
730 def nice(node):
729 def nice(node):
731 return '%d:%s' % (repo.changelog.rev(node), short(node))
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
732 ui.status(_('changeset %s backs out changeset %s\n') %
731 ui.status(_('changeset %s backs out changeset %s\n') %
733 (nice(repo.changelog.tip()), nice(node)))
732 (nice(repo.changelog.tip()), nice(node)))
734 if opts.get('merge') and op1 != node:
733 if opts.get('merge') and op1 != node:
735 hg.clean(repo, op1, show_stats=False)
734 hg.clean(repo, op1, show_stats=False)
736 ui.status(_('merging with changeset %s\n')
735 ui.status(_('merging with changeset %s\n')
737 % nice(repo.changelog.tip()))
736 % nice(repo.changelog.tip()))
738 try:
737 try:
739 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
740 'backout')
739 'backout')
741 return hg.merge(repo, hex(repo.changelog.tip()))
740 return hg.merge(repo, hex(repo.changelog.tip()))
742 finally:
741 finally:
743 ui.setconfig('ui', 'forcemerge', '', '')
742 ui.setconfig('ui', 'forcemerge', '', '')
744 return 0
743 return 0
745
744
746 @command('bisect',
745 @command('bisect',
747 [('r', 'reset', False, _('reset bisect state')),
746 [('r', 'reset', False, _('reset bisect state')),
748 ('g', 'good', False, _('mark changeset good')),
747 ('g', 'good', False, _('mark changeset good')),
749 ('b', 'bad', False, _('mark changeset bad')),
748 ('b', 'bad', False, _('mark changeset bad')),
750 ('s', 'skip', False, _('skip testing changeset')),
749 ('s', 'skip', False, _('skip testing changeset')),
751 ('e', 'extend', False, _('extend the bisect range')),
750 ('e', 'extend', False, _('extend the bisect range')),
752 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
753 ('U', 'noupdate', False, _('do not update to target'))],
752 ('U', 'noupdate', False, _('do not update to target'))],
754 _("[-gbsr] [-U] [-c CMD] [REV]"))
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
755 def bisect(ui, repo, rev=None, extra=None, command=None,
754 def bisect(ui, repo, rev=None, extra=None, command=None,
756 reset=None, good=None, bad=None, skip=None, extend=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
757 noupdate=None):
756 noupdate=None):
758 """subdivision search of changesets
757 """subdivision search of changesets
759
758
760 This command helps to find changesets which introduce problems. To
759 This command helps to find changesets which introduce problems. To
761 use, mark the earliest changeset you know exhibits the problem as
760 use, mark the earliest changeset you know exhibits the problem as
762 bad, then mark the latest changeset which is free from the problem
761 bad, then mark the latest changeset which is free from the problem
763 as good. Bisect will update your working directory to a revision
762 as good. Bisect will update your working directory to a revision
764 for testing (unless the -U/--noupdate option is specified). Once
763 for testing (unless the -U/--noupdate option is specified). Once
765 you have performed tests, mark the working directory as good or
764 you have performed tests, mark the working directory as good or
766 bad, and bisect will either update to another candidate changeset
765 bad, and bisect will either update to another candidate changeset
767 or announce that it has found the bad revision.
766 or announce that it has found the bad revision.
768
767
769 As a shortcut, you can also use the revision argument to mark a
768 As a shortcut, you can also use the revision argument to mark a
770 revision as good or bad without checking it out first.
769 revision as good or bad without checking it out first.
771
770
772 If you supply a command, it will be used for automatic bisection.
771 If you supply a command, it will be used for automatic bisection.
773 The environment variable HG_NODE will contain the ID of the
772 The environment variable HG_NODE will contain the ID of the
774 changeset being tested. The exit status of the command will be
773 changeset being tested. The exit status of the command will be
775 used to mark revisions as good or bad: status 0 means good, 125
774 used to mark revisions as good or bad: status 0 means good, 125
776 means to skip the revision, 127 (command not found) will abort the
775 means to skip the revision, 127 (command not found) will abort the
777 bisection, and any other non-zero exit status means the revision
776 bisection, and any other non-zero exit status means the revision
778 is bad.
777 is bad.
779
778
780 .. container:: verbose
779 .. container:: verbose
781
780
782 Some examples:
781 Some examples:
783
782
784 - start a bisection with known bad revision 34, and good revision 12::
783 - start a bisection with known bad revision 34, and good revision 12::
785
784
786 hg bisect --bad 34
785 hg bisect --bad 34
787 hg bisect --good 12
786 hg bisect --good 12
788
787
789 - advance the current bisection by marking current revision as good or
788 - advance the current bisection by marking current revision as good or
790 bad::
789 bad::
791
790
792 hg bisect --good
791 hg bisect --good
793 hg bisect --bad
792 hg bisect --bad
794
793
795 - mark the current revision, or a known revision, to be skipped (e.g. if
794 - mark the current revision, or a known revision, to be skipped (e.g. if
796 that revision is not usable because of another issue)::
795 that revision is not usable because of another issue)::
797
796
798 hg bisect --skip
797 hg bisect --skip
799 hg bisect --skip 23
798 hg bisect --skip 23
800
799
801 - skip all revisions that do not touch directories ``foo`` or ``bar``::
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
802
801
803 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
804
803
805 - forget the current bisection::
804 - forget the current bisection::
806
805
807 hg bisect --reset
806 hg bisect --reset
808
807
809 - use 'make && make tests' to automatically find the first broken
808 - use 'make && make tests' to automatically find the first broken
810 revision::
809 revision::
811
810
812 hg bisect --reset
811 hg bisect --reset
813 hg bisect --bad 34
812 hg bisect --bad 34
814 hg bisect --good 12
813 hg bisect --good 12
815 hg bisect --command "make && make tests"
814 hg bisect --command "make && make tests"
816
815
817 - see all changesets whose states are already known in the current
816 - see all changesets whose states are already known in the current
818 bisection::
817 bisection::
819
818
820 hg log -r "bisect(pruned)"
819 hg log -r "bisect(pruned)"
821
820
822 - see the changeset currently being bisected (especially useful
821 - see the changeset currently being bisected (especially useful
823 if running with -U/--noupdate)::
822 if running with -U/--noupdate)::
824
823
825 hg log -r "bisect(current)"
824 hg log -r "bisect(current)"
826
825
827 - see all changesets that took part in the current bisection::
826 - see all changesets that took part in the current bisection::
828
827
829 hg log -r "bisect(range)"
828 hg log -r "bisect(range)"
830
829
831 - you can even get a nice graph::
830 - you can even get a nice graph::
832
831
833 hg log --graph -r "bisect(range)"
832 hg log --graph -r "bisect(range)"
834
833
835 See :hg:`help revsets` for more about the `bisect()` keyword.
834 See :hg:`help revsets` for more about the `bisect()` keyword.
836
835
837 Returns 0 on success.
836 Returns 0 on success.
838 """
837 """
839 # backward compatibility
838 # backward compatibility
840 if rev in "good bad reset init".split():
839 if rev in "good bad reset init".split():
841 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
840 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
842 cmd, rev, extra = rev, extra, None
841 cmd, rev, extra = rev, extra, None
843 if cmd == "good":
842 if cmd == "good":
844 good = True
843 good = True
845 elif cmd == "bad":
844 elif cmd == "bad":
846 bad = True
845 bad = True
847 else:
846 else:
848 reset = True
847 reset = True
849 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
848 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
850 raise error.Abort(_('incompatible arguments'))
849 raise error.Abort(_('incompatible arguments'))
851
850
852 cmdutil.checkunfinished(repo)
851 cmdutil.checkunfinished(repo)
853
852
854 if reset:
853 if reset:
855 hbisect.resetstate(repo)
854 hbisect.resetstate(repo)
856 return
855 return
857
856
858 state = hbisect.load_state(repo)
857 state = hbisect.load_state(repo)
859
858
860 # update state
859 # update state
861 if good or bad or skip:
860 if good or bad or skip:
862 if rev:
861 if rev:
863 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
862 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
864 else:
863 else:
865 nodes = [repo.lookup('.')]
864 nodes = [repo.lookup('.')]
866 if good:
865 if good:
867 state['good'] += nodes
866 state['good'] += nodes
868 elif bad:
867 elif bad:
869 state['bad'] += nodes
868 state['bad'] += nodes
870 elif skip:
869 elif skip:
871 state['skip'] += nodes
870 state['skip'] += nodes
872 hbisect.save_state(repo, state)
871 hbisect.save_state(repo, state)
873 if not (state['good'] and state['bad']):
872 if not (state['good'] and state['bad']):
874 return
873 return
875
874
876 def mayupdate(repo, node, show_stats=True):
875 def mayupdate(repo, node, show_stats=True):
877 """common used update sequence"""
876 """common used update sequence"""
878 if noupdate:
877 if noupdate:
879 return
878 return
880 cmdutil.bailifchanged(repo)
879 cmdutil.bailifchanged(repo)
881 return hg.clean(repo, node, show_stats=show_stats)
880 return hg.clean(repo, node, show_stats=show_stats)
882
881
883 displayer = cmdutil.show_changeset(ui, repo, {})
882 displayer = cmdutil.show_changeset(ui, repo, {})
884
883
885 if command:
884 if command:
886 changesets = 1
885 changesets = 1
887 if noupdate:
886 if noupdate:
888 try:
887 try:
889 node = state['current'][0]
888 node = state['current'][0]
890 except LookupError:
889 except LookupError:
891 raise error.Abort(_('current bisect revision is unknown - '
890 raise error.Abort(_('current bisect revision is unknown - '
892 'start a new bisect to fix'))
891 'start a new bisect to fix'))
893 else:
892 else:
894 node, p2 = repo.dirstate.parents()
893 node, p2 = repo.dirstate.parents()
895 if p2 != nullid:
894 if p2 != nullid:
896 raise error.Abort(_('current bisect revision is a merge'))
895 raise error.Abort(_('current bisect revision is a merge'))
897 if rev:
896 if rev:
898 node = repo[scmutil.revsingle(repo, rev, node)].node()
897 node = repo[scmutil.revsingle(repo, rev, node)].node()
899 try:
898 try:
900 while changesets:
899 while changesets:
901 # update state
900 # update state
902 state['current'] = [node]
901 state['current'] = [node]
903 hbisect.save_state(repo, state)
902 hbisect.save_state(repo, state)
904 status = ui.system(command, environ={'HG_NODE': hex(node)})
903 status = ui.system(command, environ={'HG_NODE': hex(node)})
905 if status == 125:
904 if status == 125:
906 transition = "skip"
905 transition = "skip"
907 elif status == 0:
906 elif status == 0:
908 transition = "good"
907 transition = "good"
909 # status < 0 means process was killed
908 # status < 0 means process was killed
910 elif status == 127:
909 elif status == 127:
911 raise error.Abort(_("failed to execute %s") % command)
910 raise error.Abort(_("failed to execute %s") % command)
912 elif status < 0:
911 elif status < 0:
913 raise error.Abort(_("%s killed") % command)
912 raise error.Abort(_("%s killed") % command)
914 else:
913 else:
915 transition = "bad"
914 transition = "bad"
916 state[transition].append(node)
915 state[transition].append(node)
917 ctx = repo[node]
916 ctx = repo[node]
918 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
917 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
919 hbisect.checkstate(state)
918 hbisect.checkstate(state)
920 # bisect
919 # bisect
921 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
920 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
922 # update to next check
921 # update to next check
923 node = nodes[0]
922 node = nodes[0]
924 mayupdate(repo, node, show_stats=False)
923 mayupdate(repo, node, show_stats=False)
925 finally:
924 finally:
926 state['current'] = [node]
925 state['current'] = [node]
927 hbisect.save_state(repo, state)
926 hbisect.save_state(repo, state)
928 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
927 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
929 return
928 return
930
929
931 hbisect.checkstate(state)
930 hbisect.checkstate(state)
932
931
933 # actually bisect
932 # actually bisect
934 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
933 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
935 if extend:
934 if extend:
936 if not changesets:
935 if not changesets:
937 extendnode = hbisect.extendrange(repo, state, nodes, good)
936 extendnode = hbisect.extendrange(repo, state, nodes, good)
938 if extendnode is not None:
937 if extendnode is not None:
939 ui.write(_("Extending search to changeset %d:%s\n")
938 ui.write(_("Extending search to changeset %d:%s\n")
940 % (extendnode.rev(), extendnode))
939 % (extendnode.rev(), extendnode))
941 state['current'] = [extendnode.node()]
940 state['current'] = [extendnode.node()]
942 hbisect.save_state(repo, state)
941 hbisect.save_state(repo, state)
943 return mayupdate(repo, extendnode.node())
942 return mayupdate(repo, extendnode.node())
944 raise error.Abort(_("nothing to extend"))
943 raise error.Abort(_("nothing to extend"))
945
944
946 if changesets == 0:
945 if changesets == 0:
947 hbisect.printresult(ui, repo, state, displayer, nodes, good)
946 hbisect.printresult(ui, repo, state, displayer, nodes, good)
948 else:
947 else:
949 assert len(nodes) == 1 # only a single node can be tested next
948 assert len(nodes) == 1 # only a single node can be tested next
950 node = nodes[0]
949 node = nodes[0]
951 # compute the approximate number of remaining tests
950 # compute the approximate number of remaining tests
952 tests, size = 0, 2
951 tests, size = 0, 2
953 while size <= changesets:
952 while size <= changesets:
954 tests, size = tests + 1, size * 2
953 tests, size = tests + 1, size * 2
955 rev = repo.changelog.rev(node)
954 rev = repo.changelog.rev(node)
956 ui.write(_("Testing changeset %d:%s "
955 ui.write(_("Testing changeset %d:%s "
957 "(%d changesets remaining, ~%d tests)\n")
956 "(%d changesets remaining, ~%d tests)\n")
958 % (rev, short(node), changesets, tests))
957 % (rev, short(node), changesets, tests))
959 state['current'] = [node]
958 state['current'] = [node]
960 hbisect.save_state(repo, state)
959 hbisect.save_state(repo, state)
961 return mayupdate(repo, node)
960 return mayupdate(repo, node)
962
961
963 @command('bookmarks|bookmark',
962 @command('bookmarks|bookmark',
964 [('f', 'force', False, _('force')),
963 [('f', 'force', False, _('force')),
965 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
964 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
966 ('d', 'delete', False, _('delete a given bookmark')),
965 ('d', 'delete', False, _('delete a given bookmark')),
967 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
966 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
968 ('i', 'inactive', False, _('mark a bookmark inactive')),
967 ('i', 'inactive', False, _('mark a bookmark inactive')),
969 ] + formatteropts,
968 ] + formatteropts,
970 _('hg bookmarks [OPTIONS]... [NAME]...'))
969 _('hg bookmarks [OPTIONS]... [NAME]...'))
971 def bookmark(ui, repo, *names, **opts):
970 def bookmark(ui, repo, *names, **opts):
972 '''create a new bookmark or list existing bookmarks
971 '''create a new bookmark or list existing bookmarks
973
972
974 Bookmarks are labels on changesets to help track lines of development.
973 Bookmarks are labels on changesets to help track lines of development.
975 Bookmarks are unversioned and can be moved, renamed and deleted.
974 Bookmarks are unversioned and can be moved, renamed and deleted.
976 Deleting or moving a bookmark has no effect on the associated changesets.
975 Deleting or moving a bookmark has no effect on the associated changesets.
977
976
978 Creating or updating to a bookmark causes it to be marked as 'active'.
977 Creating or updating to a bookmark causes it to be marked as 'active'.
979 The active bookmark is indicated with a '*'.
978 The active bookmark is indicated with a '*'.
980 When a commit is made, the active bookmark will advance to the new commit.
979 When a commit is made, the active bookmark will advance to the new commit.
981 A plain :hg:`update` will also advance an active bookmark, if possible.
980 A plain :hg:`update` will also advance an active bookmark, if possible.
982 Updating away from a bookmark will cause it to be deactivated.
981 Updating away from a bookmark will cause it to be deactivated.
983
982
984 Bookmarks can be pushed and pulled between repositories (see
983 Bookmarks can be pushed and pulled between repositories (see
985 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
984 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
986 diverged, a new 'divergent bookmark' of the form 'name@path' will
985 diverged, a new 'divergent bookmark' of the form 'name@path' will
987 be created. Using :hg:`merge` will resolve the divergence.
986 be created. Using :hg:`merge` will resolve the divergence.
988
987
989 A bookmark named '@' has the special property that :hg:`clone` will
988 A bookmark named '@' has the special property that :hg:`clone` will
990 check it out by default if it exists.
989 check it out by default if it exists.
991
990
992 .. container:: verbose
991 .. container:: verbose
993
992
994 Examples:
993 Examples:
995
994
996 - create an active bookmark for a new line of development::
995 - create an active bookmark for a new line of development::
997
996
998 hg book new-feature
997 hg book new-feature
999
998
1000 - create an inactive bookmark as a place marker::
999 - create an inactive bookmark as a place marker::
1001
1000
1002 hg book -i reviewed
1001 hg book -i reviewed
1003
1002
1004 - create an inactive bookmark on another changeset::
1003 - create an inactive bookmark on another changeset::
1005
1004
1006 hg book -r .^ tested
1005 hg book -r .^ tested
1007
1006
1008 - rename bookmark turkey to dinner::
1007 - rename bookmark turkey to dinner::
1009
1008
1010 hg book -m turkey dinner
1009 hg book -m turkey dinner
1011
1010
1012 - move the '@' bookmark from another branch::
1011 - move the '@' bookmark from another branch::
1013
1012
1014 hg book -f @
1013 hg book -f @
1015 '''
1014 '''
1016 force = opts.get('force')
1015 force = opts.get('force')
1017 rev = opts.get('rev')
1016 rev = opts.get('rev')
1018 delete = opts.get('delete')
1017 delete = opts.get('delete')
1019 rename = opts.get('rename')
1018 rename = opts.get('rename')
1020 inactive = opts.get('inactive')
1019 inactive = opts.get('inactive')
1021
1020
1022 def checkformat(mark):
1021 def checkformat(mark):
1023 mark = mark.strip()
1022 mark = mark.strip()
1024 if not mark:
1023 if not mark:
1025 raise error.Abort(_("bookmark names cannot consist entirely of "
1024 raise error.Abort(_("bookmark names cannot consist entirely of "
1026 "whitespace"))
1025 "whitespace"))
1027 scmutil.checknewlabel(repo, mark, 'bookmark')
1026 scmutil.checknewlabel(repo, mark, 'bookmark')
1028 return mark
1027 return mark
1029
1028
1030 def checkconflict(repo, mark, cur, force=False, target=None):
1029 def checkconflict(repo, mark, cur, force=False, target=None):
1031 if mark in marks and not force:
1030 if mark in marks and not force:
1032 if target:
1031 if target:
1033 if marks[mark] == target and target == cur:
1032 if marks[mark] == target and target == cur:
1034 # re-activating a bookmark
1033 # re-activating a bookmark
1035 return
1034 return
1036 anc = repo.changelog.ancestors([repo[target].rev()])
1035 anc = repo.changelog.ancestors([repo[target].rev()])
1037 bmctx = repo[marks[mark]]
1036 bmctx = repo[marks[mark]]
1038 divs = [repo[b].node() for b in marks
1037 divs = [repo[b].node() for b in marks
1039 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1038 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1040
1039
1041 # allow resolving a single divergent bookmark even if moving
1040 # allow resolving a single divergent bookmark even if moving
1042 # the bookmark across branches when a revision is specified
1041 # the bookmark across branches when a revision is specified
1043 # that contains a divergent bookmark
1042 # that contains a divergent bookmark
1044 if bmctx.rev() not in anc and target in divs:
1043 if bmctx.rev() not in anc and target in divs:
1045 bookmarks.deletedivergent(repo, [target], mark)
1044 bookmarks.deletedivergent(repo, [target], mark)
1046 return
1045 return
1047
1046
1048 deletefrom = [b for b in divs
1047 deletefrom = [b for b in divs
1049 if repo[b].rev() in anc or b == target]
1048 if repo[b].rev() in anc or b == target]
1050 bookmarks.deletedivergent(repo, deletefrom, mark)
1049 bookmarks.deletedivergent(repo, deletefrom, mark)
1051 if bookmarks.validdest(repo, bmctx, repo[target]):
1050 if bookmarks.validdest(repo, bmctx, repo[target]):
1052 ui.status(_("moving bookmark '%s' forward from %s\n") %
1051 ui.status(_("moving bookmark '%s' forward from %s\n") %
1053 (mark, short(bmctx.node())))
1052 (mark, short(bmctx.node())))
1054 return
1053 return
1055 raise error.Abort(_("bookmark '%s' already exists "
1054 raise error.Abort(_("bookmark '%s' already exists "
1056 "(use -f to force)") % mark)
1055 "(use -f to force)") % mark)
1057 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1056 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1058 and not force):
1057 and not force):
1059 raise error.Abort(
1058 raise error.Abort(
1060 _("a bookmark cannot have the name of an existing branch"))
1059 _("a bookmark cannot have the name of an existing branch"))
1061
1060
1062 if delete and rename:
1061 if delete and rename:
1063 raise error.Abort(_("--delete and --rename are incompatible"))
1062 raise error.Abort(_("--delete and --rename are incompatible"))
1064 if delete and rev:
1063 if delete and rev:
1065 raise error.Abort(_("--rev is incompatible with --delete"))
1064 raise error.Abort(_("--rev is incompatible with --delete"))
1066 if rename and rev:
1065 if rename and rev:
1067 raise error.Abort(_("--rev is incompatible with --rename"))
1066 raise error.Abort(_("--rev is incompatible with --rename"))
1068 if not names and (delete or rev):
1067 if not names and (delete or rev):
1069 raise error.Abort(_("bookmark name required"))
1068 raise error.Abort(_("bookmark name required"))
1070
1069
1071 if delete or rename or names or inactive:
1070 if delete or rename or names or inactive:
1072 wlock = lock = tr = None
1071 wlock = lock = tr = None
1073 try:
1072 try:
1074 wlock = repo.wlock()
1073 wlock = repo.wlock()
1075 lock = repo.lock()
1074 lock = repo.lock()
1076 cur = repo.changectx('.').node()
1075 cur = repo.changectx('.').node()
1077 marks = repo._bookmarks
1076 marks = repo._bookmarks
1078 if delete:
1077 if delete:
1079 tr = repo.transaction('bookmark')
1078 tr = repo.transaction('bookmark')
1080 for mark in names:
1079 for mark in names:
1081 if mark not in marks:
1080 if mark not in marks:
1082 raise error.Abort(_("bookmark '%s' does not exist") %
1081 raise error.Abort(_("bookmark '%s' does not exist") %
1083 mark)
1082 mark)
1084 if mark == repo._activebookmark:
1083 if mark == repo._activebookmark:
1085 bookmarks.deactivate(repo)
1084 bookmarks.deactivate(repo)
1086 del marks[mark]
1085 del marks[mark]
1087
1086
1088 elif rename:
1087 elif rename:
1089 tr = repo.transaction('bookmark')
1088 tr = repo.transaction('bookmark')
1090 if not names:
1089 if not names:
1091 raise error.Abort(_("new bookmark name required"))
1090 raise error.Abort(_("new bookmark name required"))
1092 elif len(names) > 1:
1091 elif len(names) > 1:
1093 raise error.Abort(_("only one new bookmark name allowed"))
1092 raise error.Abort(_("only one new bookmark name allowed"))
1094 mark = checkformat(names[0])
1093 mark = checkformat(names[0])
1095 if rename not in marks:
1094 if rename not in marks:
1096 raise error.Abort(_("bookmark '%s' does not exist")
1095 raise error.Abort(_("bookmark '%s' does not exist")
1097 % rename)
1096 % rename)
1098 checkconflict(repo, mark, cur, force)
1097 checkconflict(repo, mark, cur, force)
1099 marks[mark] = marks[rename]
1098 marks[mark] = marks[rename]
1100 if repo._activebookmark == rename and not inactive:
1099 if repo._activebookmark == rename and not inactive:
1101 bookmarks.activate(repo, mark)
1100 bookmarks.activate(repo, mark)
1102 del marks[rename]
1101 del marks[rename]
1103 elif names:
1102 elif names:
1104 tr = repo.transaction('bookmark')
1103 tr = repo.transaction('bookmark')
1105 newact = None
1104 newact = None
1106 for mark in names:
1105 for mark in names:
1107 mark = checkformat(mark)
1106 mark = checkformat(mark)
1108 if newact is None:
1107 if newact is None:
1109 newact = mark
1108 newact = mark
1110 if inactive and mark == repo._activebookmark:
1109 if inactive and mark == repo._activebookmark:
1111 bookmarks.deactivate(repo)
1110 bookmarks.deactivate(repo)
1112 return
1111 return
1113 tgt = cur
1112 tgt = cur
1114 if rev:
1113 if rev:
1115 tgt = scmutil.revsingle(repo, rev).node()
1114 tgt = scmutil.revsingle(repo, rev).node()
1116 checkconflict(repo, mark, cur, force, tgt)
1115 checkconflict(repo, mark, cur, force, tgt)
1117 marks[mark] = tgt
1116 marks[mark] = tgt
1118 if not inactive and cur == marks[newact] and not rev:
1117 if not inactive and cur == marks[newact] and not rev:
1119 bookmarks.activate(repo, newact)
1118 bookmarks.activate(repo, newact)
1120 elif cur != tgt and newact == repo._activebookmark:
1119 elif cur != tgt and newact == repo._activebookmark:
1121 bookmarks.deactivate(repo)
1120 bookmarks.deactivate(repo)
1122 elif inactive:
1121 elif inactive:
1123 if len(marks) == 0:
1122 if len(marks) == 0:
1124 ui.status(_("no bookmarks set\n"))
1123 ui.status(_("no bookmarks set\n"))
1125 elif not repo._activebookmark:
1124 elif not repo._activebookmark:
1126 ui.status(_("no active bookmark\n"))
1125 ui.status(_("no active bookmark\n"))
1127 else:
1126 else:
1128 bookmarks.deactivate(repo)
1127 bookmarks.deactivate(repo)
1129 if tr is not None:
1128 if tr is not None:
1130 marks.recordchange(tr)
1129 marks.recordchange(tr)
1131 tr.close()
1130 tr.close()
1132 finally:
1131 finally:
1133 lockmod.release(tr, lock, wlock)
1132 lockmod.release(tr, lock, wlock)
1134 else: # show bookmarks
1133 else: # show bookmarks
1135 fm = ui.formatter('bookmarks', opts)
1134 fm = ui.formatter('bookmarks', opts)
1136 hexfn = fm.hexfunc
1135 hexfn = fm.hexfunc
1137 marks = repo._bookmarks
1136 marks = repo._bookmarks
1138 if len(marks) == 0 and fm.isplain():
1137 if len(marks) == 0 and fm.isplain():
1139 ui.status(_("no bookmarks set\n"))
1138 ui.status(_("no bookmarks set\n"))
1140 for bmark, n in sorted(marks.iteritems()):
1139 for bmark, n in sorted(marks.iteritems()):
1141 active = repo._activebookmark
1140 active = repo._activebookmark
1142 if bmark == active:
1141 if bmark == active:
1143 prefix, label = '*', activebookmarklabel
1142 prefix, label = '*', activebookmarklabel
1144 else:
1143 else:
1145 prefix, label = ' ', ''
1144 prefix, label = ' ', ''
1146
1145
1147 fm.startitem()
1146 fm.startitem()
1148 if not ui.quiet:
1147 if not ui.quiet:
1149 fm.plain(' %s ' % prefix, label=label)
1148 fm.plain(' %s ' % prefix, label=label)
1150 fm.write('bookmark', '%s', bmark, label=label)
1149 fm.write('bookmark', '%s', bmark, label=label)
1151 pad = " " * (25 - encoding.colwidth(bmark))
1150 pad = " " * (25 - encoding.colwidth(bmark))
1152 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1151 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1153 repo.changelog.rev(n), hexfn(n), label=label)
1152 repo.changelog.rev(n), hexfn(n), label=label)
1154 fm.data(active=(bmark == active))
1153 fm.data(active=(bmark == active))
1155 fm.plain('\n')
1154 fm.plain('\n')
1156 fm.end()
1155 fm.end()
1157
1156
1158 @command('branch',
1157 @command('branch',
1159 [('f', 'force', None,
1158 [('f', 'force', None,
1160 _('set branch name even if it shadows an existing branch')),
1159 _('set branch name even if it shadows an existing branch')),
1161 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1160 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1162 _('[-fC] [NAME]'))
1161 _('[-fC] [NAME]'))
1163 def branch(ui, repo, label=None, **opts):
1162 def branch(ui, repo, label=None, **opts):
1164 """set or show the current branch name
1163 """set or show the current branch name
1165
1164
1166 .. note::
1165 .. note::
1167
1166
1168 Branch names are permanent and global. Use :hg:`bookmark` to create a
1167 Branch names are permanent and global. Use :hg:`bookmark` to create a
1169 light-weight bookmark instead. See :hg:`help glossary` for more
1168 light-weight bookmark instead. See :hg:`help glossary` for more
1170 information about named branches and bookmarks.
1169 information about named branches and bookmarks.
1171
1170
1172 With no argument, show the current branch name. With one argument,
1171 With no argument, show the current branch name. With one argument,
1173 set the working directory branch name (the branch will not exist
1172 set the working directory branch name (the branch will not exist
1174 in the repository until the next commit). Standard practice
1173 in the repository until the next commit). Standard practice
1175 recommends that primary development take place on the 'default'
1174 recommends that primary development take place on the 'default'
1176 branch.
1175 branch.
1177
1176
1178 Unless -f/--force is specified, branch will not let you set a
1177 Unless -f/--force is specified, branch will not let you set a
1179 branch name that already exists.
1178 branch name that already exists.
1180
1179
1181 Use -C/--clean to reset the working directory branch to that of
1180 Use -C/--clean to reset the working directory branch to that of
1182 the parent of the working directory, negating a previous branch
1181 the parent of the working directory, negating a previous branch
1183 change.
1182 change.
1184
1183
1185 Use the command :hg:`update` to switch to an existing branch. Use
1184 Use the command :hg:`update` to switch to an existing branch. Use
1186 :hg:`commit --close-branch` to mark this branch head as closed.
1185 :hg:`commit --close-branch` to mark this branch head as closed.
1187 When all heads of a branch are closed, the branch will be
1186 When all heads of a branch are closed, the branch will be
1188 considered closed.
1187 considered closed.
1189
1188
1190 Returns 0 on success.
1189 Returns 0 on success.
1191 """
1190 """
1192 if label:
1191 if label:
1193 label = label.strip()
1192 label = label.strip()
1194
1193
1195 if not opts.get('clean') and not label:
1194 if not opts.get('clean') and not label:
1196 ui.write("%s\n" % repo.dirstate.branch())
1195 ui.write("%s\n" % repo.dirstate.branch())
1197 return
1196 return
1198
1197
1199 with repo.wlock():
1198 with repo.wlock():
1200 if opts.get('clean'):
1199 if opts.get('clean'):
1201 label = repo[None].p1().branch()
1200 label = repo[None].p1().branch()
1202 repo.dirstate.setbranch(label)
1201 repo.dirstate.setbranch(label)
1203 ui.status(_('reset working directory to branch %s\n') % label)
1202 ui.status(_('reset working directory to branch %s\n') % label)
1204 elif label:
1203 elif label:
1205 if not opts.get('force') and label in repo.branchmap():
1204 if not opts.get('force') and label in repo.branchmap():
1206 if label not in [p.branch() for p in repo[None].parents()]:
1205 if label not in [p.branch() for p in repo[None].parents()]:
1207 raise error.Abort(_('a branch of the same name already'
1206 raise error.Abort(_('a branch of the same name already'
1208 ' exists'),
1207 ' exists'),
1209 # i18n: "it" refers to an existing branch
1208 # i18n: "it" refers to an existing branch
1210 hint=_("use 'hg update' to switch to it"))
1209 hint=_("use 'hg update' to switch to it"))
1211 scmutil.checknewlabel(repo, label, 'branch')
1210 scmutil.checknewlabel(repo, label, 'branch')
1212 repo.dirstate.setbranch(label)
1211 repo.dirstate.setbranch(label)
1213 ui.status(_('marked working directory as branch %s\n') % label)
1212 ui.status(_('marked working directory as branch %s\n') % label)
1214
1213
1215 # find any open named branches aside from default
1214 # find any open named branches aside from default
1216 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1215 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1217 if n != "default" and not c]
1216 if n != "default" and not c]
1218 if not others:
1217 if not others:
1219 ui.status(_('(branches are permanent and global, '
1218 ui.status(_('(branches are permanent and global, '
1220 'did you want a bookmark?)\n'))
1219 'did you want a bookmark?)\n'))
1221
1220
1222 @command('branches',
1221 @command('branches',
1223 [('a', 'active', False,
1222 [('a', 'active', False,
1224 _('show only branches that have unmerged heads (DEPRECATED)')),
1223 _('show only branches that have unmerged heads (DEPRECATED)')),
1225 ('c', 'closed', False, _('show normal and closed branches')),
1224 ('c', 'closed', False, _('show normal and closed branches')),
1226 ] + formatteropts,
1225 ] + formatteropts,
1227 _('[-c]'))
1226 _('[-c]'))
1228 def branches(ui, repo, active=False, closed=False, **opts):
1227 def branches(ui, repo, active=False, closed=False, **opts):
1229 """list repository named branches
1228 """list repository named branches
1230
1229
1231 List the repository's named branches, indicating which ones are
1230 List the repository's named branches, indicating which ones are
1232 inactive. If -c/--closed is specified, also list branches which have
1231 inactive. If -c/--closed is specified, also list branches which have
1233 been marked closed (see :hg:`commit --close-branch`).
1232 been marked closed (see :hg:`commit --close-branch`).
1234
1233
1235 Use the command :hg:`update` to switch to an existing branch.
1234 Use the command :hg:`update` to switch to an existing branch.
1236
1235
1237 Returns 0.
1236 Returns 0.
1238 """
1237 """
1239
1238
1240 fm = ui.formatter('branches', opts)
1239 fm = ui.formatter('branches', opts)
1241 hexfunc = fm.hexfunc
1240 hexfunc = fm.hexfunc
1242
1241
1243 allheads = set(repo.heads())
1242 allheads = set(repo.heads())
1244 branches = []
1243 branches = []
1245 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1244 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1246 isactive = not isclosed and bool(set(heads) & allheads)
1245 isactive = not isclosed and bool(set(heads) & allheads)
1247 branches.append((tag, repo[tip], isactive, not isclosed))
1246 branches.append((tag, repo[tip], isactive, not isclosed))
1248 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1247 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1249 reverse=True)
1248 reverse=True)
1250
1249
1251 for tag, ctx, isactive, isopen in branches:
1250 for tag, ctx, isactive, isopen in branches:
1252 if active and not isactive:
1251 if active and not isactive:
1253 continue
1252 continue
1254 if isactive:
1253 if isactive:
1255 label = 'branches.active'
1254 label = 'branches.active'
1256 notice = ''
1255 notice = ''
1257 elif not isopen:
1256 elif not isopen:
1258 if not closed:
1257 if not closed:
1259 continue
1258 continue
1260 label = 'branches.closed'
1259 label = 'branches.closed'
1261 notice = _(' (closed)')
1260 notice = _(' (closed)')
1262 else:
1261 else:
1263 label = 'branches.inactive'
1262 label = 'branches.inactive'
1264 notice = _(' (inactive)')
1263 notice = _(' (inactive)')
1265 current = (tag == repo.dirstate.branch())
1264 current = (tag == repo.dirstate.branch())
1266 if current:
1265 if current:
1267 label = 'branches.current'
1266 label = 'branches.current'
1268
1267
1269 fm.startitem()
1268 fm.startitem()
1270 fm.write('branch', '%s', tag, label=label)
1269 fm.write('branch', '%s', tag, label=label)
1271 rev = ctx.rev()
1270 rev = ctx.rev()
1272 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1271 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1273 fmt = ' ' * padsize + ' %d:%s'
1272 fmt = ' ' * padsize + ' %d:%s'
1274 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1273 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1275 label='log.changeset changeset.%s' % ctx.phasestr())
1274 label='log.changeset changeset.%s' % ctx.phasestr())
1276 fm.data(active=isactive, closed=not isopen, current=current)
1275 fm.data(active=isactive, closed=not isopen, current=current)
1277 if not ui.quiet:
1276 if not ui.quiet:
1278 fm.plain(notice)
1277 fm.plain(notice)
1279 fm.plain('\n')
1278 fm.plain('\n')
1280 fm.end()
1279 fm.end()
1281
1280
1282 @command('bundle',
1281 @command('bundle',
1283 [('f', 'force', None, _('run even when the destination is unrelated')),
1282 [('f', 'force', None, _('run even when the destination is unrelated')),
1284 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1283 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1285 _('REV')),
1284 _('REV')),
1286 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1285 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1287 _('BRANCH')),
1286 _('BRANCH')),
1288 ('', 'base', [],
1287 ('', 'base', [],
1289 _('a base changeset assumed to be available at the destination'),
1288 _('a base changeset assumed to be available at the destination'),
1290 _('REV')),
1289 _('REV')),
1291 ('a', 'all', None, _('bundle all changesets in the repository')),
1290 ('a', 'all', None, _('bundle all changesets in the repository')),
1292 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1291 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1293 ] + remoteopts,
1292 ] + remoteopts,
1294 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1293 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1295 def bundle(ui, repo, fname, dest=None, **opts):
1294 def bundle(ui, repo, fname, dest=None, **opts):
1296 """create a changegroup file
1295 """create a changegroup file
1297
1296
1298 Generate a changegroup file collecting changesets to be added
1297 Generate a changegroup file collecting changesets to be added
1299 to a repository.
1298 to a repository.
1300
1299
1301 To create a bundle containing all changesets, use -a/--all
1300 To create a bundle containing all changesets, use -a/--all
1302 (or --base null). Otherwise, hg assumes the destination will have
1301 (or --base null). Otherwise, hg assumes the destination will have
1303 all the nodes you specify with --base parameters. Otherwise, hg
1302 all the nodes you specify with --base parameters. Otherwise, hg
1304 will assume the repository has all the nodes in destination, or
1303 will assume the repository has all the nodes in destination, or
1305 default-push/default if no destination is specified.
1304 default-push/default if no destination is specified.
1306
1305
1307 You can change bundle format with the -t/--type option. You can
1306 You can change bundle format with the -t/--type option. You can
1308 specify a compression, a bundle version or both using a dash
1307 specify a compression, a bundle version or both using a dash
1309 (comp-version). The available compression methods are: none, bzip2,
1308 (comp-version). The available compression methods are: none, bzip2,
1310 and gzip (by default, bundles are compressed using bzip2). The
1309 and gzip (by default, bundles are compressed using bzip2). The
1311 available formats are: v1, v2 (default to most suitable).
1310 available formats are: v1, v2 (default to most suitable).
1312
1311
1313 The bundle file can then be transferred using conventional means
1312 The bundle file can then be transferred using conventional means
1314 and applied to another repository with the unbundle or pull
1313 and applied to another repository with the unbundle or pull
1315 command. This is useful when direct push and pull are not
1314 command. This is useful when direct push and pull are not
1316 available or when exporting an entire repository is undesirable.
1315 available or when exporting an entire repository is undesirable.
1317
1316
1318 Applying bundles preserves all changeset contents including
1317 Applying bundles preserves all changeset contents including
1319 permissions, copy/rename information, and revision history.
1318 permissions, copy/rename information, and revision history.
1320
1319
1321 Returns 0 on success, 1 if no changes found.
1320 Returns 0 on success, 1 if no changes found.
1322 """
1321 """
1323 revs = None
1322 revs = None
1324 if 'rev' in opts:
1323 if 'rev' in opts:
1325 revstrings = opts['rev']
1324 revstrings = opts['rev']
1326 revs = scmutil.revrange(repo, revstrings)
1325 revs = scmutil.revrange(repo, revstrings)
1327 if revstrings and not revs:
1326 if revstrings and not revs:
1328 raise error.Abort(_('no commits to bundle'))
1327 raise error.Abort(_('no commits to bundle'))
1329
1328
1330 bundletype = opts.get('type', 'bzip2').lower()
1329 bundletype = opts.get('type', 'bzip2').lower()
1331 try:
1330 try:
1332 bcompression, cgversion, params = exchange.parsebundlespec(
1331 bcompression, cgversion, params = exchange.parsebundlespec(
1333 repo, bundletype, strict=False)
1332 repo, bundletype, strict=False)
1334 except error.UnsupportedBundleSpecification as e:
1333 except error.UnsupportedBundleSpecification as e:
1335 raise error.Abort(str(e),
1334 raise error.Abort(str(e),
1336 hint=_("see 'hg help bundle' for supported "
1335 hint=_("see 'hg help bundle' for supported "
1337 "values for --type"))
1336 "values for --type"))
1338
1337
1339 # Packed bundles are a pseudo bundle format for now.
1338 # Packed bundles are a pseudo bundle format for now.
1340 if cgversion == 's1':
1339 if cgversion == 's1':
1341 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1340 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1342 hint=_("use 'hg debugcreatestreamclonebundle'"))
1341 hint=_("use 'hg debugcreatestreamclonebundle'"))
1343
1342
1344 if opts.get('all'):
1343 if opts.get('all'):
1345 if dest:
1344 if dest:
1346 raise error.Abort(_("--all is incompatible with specifying "
1345 raise error.Abort(_("--all is incompatible with specifying "
1347 "a destination"))
1346 "a destination"))
1348 if opts.get('base'):
1347 if opts.get('base'):
1349 ui.warn(_("ignoring --base because --all was specified\n"))
1348 ui.warn(_("ignoring --base because --all was specified\n"))
1350 base = ['null']
1349 base = ['null']
1351 else:
1350 else:
1352 base = scmutil.revrange(repo, opts.get('base'))
1351 base = scmutil.revrange(repo, opts.get('base'))
1353 # TODO: get desired bundlecaps from command line.
1352 # TODO: get desired bundlecaps from command line.
1354 bundlecaps = None
1353 bundlecaps = None
1355 if cgversion not in changegroup.supportedoutgoingversions(repo):
1354 if cgversion not in changegroup.supportedoutgoingversions(repo):
1356 raise error.Abort(_("repository does not support bundle version %s") %
1355 raise error.Abort(_("repository does not support bundle version %s") %
1357 cgversion)
1356 cgversion)
1358
1357
1359 if base:
1358 if base:
1360 if dest:
1359 if dest:
1361 raise error.Abort(_("--base is incompatible with specifying "
1360 raise error.Abort(_("--base is incompatible with specifying "
1362 "a destination"))
1361 "a destination"))
1363 common = [repo.lookup(rev) for rev in base]
1362 common = [repo.lookup(rev) for rev in base]
1364 heads = revs and map(repo.lookup, revs) or None
1363 heads = revs and map(repo.lookup, revs) or None
1365 outgoing = discovery.outgoing(repo, common, heads)
1364 outgoing = discovery.outgoing(repo, common, heads)
1366 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1365 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1367 bundlecaps=bundlecaps,
1366 bundlecaps=bundlecaps,
1368 version=cgversion)
1367 version=cgversion)
1369 outgoing = None
1368 outgoing = None
1370 else:
1369 else:
1371 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1370 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1372 dest, branches = hg.parseurl(dest, opts.get('branch'))
1371 dest, branches = hg.parseurl(dest, opts.get('branch'))
1373 other = hg.peer(repo, opts, dest)
1372 other = hg.peer(repo, opts, dest)
1374 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1373 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1375 heads = revs and map(repo.lookup, revs) or revs
1374 heads = revs and map(repo.lookup, revs) or revs
1376 outgoing = discovery.findcommonoutgoing(repo, other,
1375 outgoing = discovery.findcommonoutgoing(repo, other,
1377 onlyheads=heads,
1376 onlyheads=heads,
1378 force=opts.get('force'),
1377 force=opts.get('force'),
1379 portable=True)
1378 portable=True)
1380 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1379 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1381 bundlecaps, version=cgversion)
1380 bundlecaps, version=cgversion)
1382 if not cg:
1381 if not cg:
1383 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1382 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1384 return 1
1383 return 1
1385
1384
1386 if cgversion == '01': #bundle1
1385 if cgversion == '01': #bundle1
1387 if bcompression is None:
1386 if bcompression is None:
1388 bcompression = 'UN'
1387 bcompression = 'UN'
1389 bversion = 'HG10' + bcompression
1388 bversion = 'HG10' + bcompression
1390 bcompression = None
1389 bcompression = None
1391 else:
1390 else:
1392 assert cgversion == '02'
1391 assert cgversion == '02'
1393 bversion = 'HG20'
1392 bversion = 'HG20'
1394
1393
1395 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1394 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1396
1395
1397 @command('cat',
1396 @command('cat',
1398 [('o', 'output', '',
1397 [('o', 'output', '',
1399 _('print output to file with formatted name'), _('FORMAT')),
1398 _('print output to file with formatted name'), _('FORMAT')),
1400 ('r', 'rev', '', _('print the given revision'), _('REV')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1401 ('', 'decode', None, _('apply any matching decode filter')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1402 ] + walkopts,
1401 ] + walkopts,
1403 _('[OPTION]... FILE...'),
1402 _('[OPTION]... FILE...'),
1404 inferrepo=True)
1403 inferrepo=True)
1405 def cat(ui, repo, file1, *pats, **opts):
1404 def cat(ui, repo, file1, *pats, **opts):
1406 """output the current or given revision of files
1405 """output the current or given revision of files
1407
1406
1408 Print the specified files as they were at the given revision. If
1407 Print the specified files as they were at the given revision. If
1409 no revision is given, the parent of the working directory is used.
1408 no revision is given, the parent of the working directory is used.
1410
1409
1411 Output may be to a file, in which case the name of the file is
1410 Output may be to a file, in which case the name of the file is
1412 given using a format string. The formatting rules as follows:
1411 given using a format string. The formatting rules as follows:
1413
1412
1414 :``%%``: literal "%" character
1413 :``%%``: literal "%" character
1415 :``%s``: basename of file being printed
1414 :``%s``: basename of file being printed
1416 :``%d``: dirname of file being printed, or '.' if in repository root
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1417 :``%p``: root-relative path name of file being printed
1416 :``%p``: root-relative path name of file being printed
1418 :``%H``: changeset hash (40 hexadecimal digits)
1417 :``%H``: changeset hash (40 hexadecimal digits)
1419 :``%R``: changeset revision number
1418 :``%R``: changeset revision number
1420 :``%h``: short-form changeset hash (12 hexadecimal digits)
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1421 :``%r``: zero-padded changeset revision number
1420 :``%r``: zero-padded changeset revision number
1422 :``%b``: basename of the exporting repository
1421 :``%b``: basename of the exporting repository
1423
1422
1424 Returns 0 on success.
1423 Returns 0 on success.
1425 """
1424 """
1426 ctx = scmutil.revsingle(repo, opts.get('rev'))
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1427 m = scmutil.match(ctx, (file1,) + pats, opts)
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1428
1427
1429 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1430
1429
1431 @command('^clone',
1430 @command('^clone',
1432 [('U', 'noupdate', None, _('the clone will include an empty working '
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1433 'directory (only a repository)')),
1432 'directory (only a repository)')),
1434 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1435 _('REV')),
1434 _('REV')),
1436 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1437 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1438 ('', 'pull', None, _('use pull protocol to copy metadata')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1439 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1440 ] + remoteopts,
1439 ] + remoteopts,
1441 _('[OPTION]... SOURCE [DEST]'),
1440 _('[OPTION]... SOURCE [DEST]'),
1442 norepo=True)
1441 norepo=True)
1443 def clone(ui, source, dest=None, **opts):
1442 def clone(ui, source, dest=None, **opts):
1444 """make a copy of an existing repository
1443 """make a copy of an existing repository
1445
1444
1446 Create a copy of an existing repository in a new directory.
1445 Create a copy of an existing repository in a new directory.
1447
1446
1448 If no destination directory name is specified, it defaults to the
1447 If no destination directory name is specified, it defaults to the
1449 basename of the source.
1448 basename of the source.
1450
1449
1451 The location of the source is added to the new repository's
1450 The location of the source is added to the new repository's
1452 ``.hg/hgrc`` file, as the default to be used for future pulls.
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1453
1452
1454 Only local paths and ``ssh://`` URLs are supported as
1453 Only local paths and ``ssh://`` URLs are supported as
1455 destinations. For ``ssh://`` destinations, no working directory or
1454 destinations. For ``ssh://`` destinations, no working directory or
1456 ``.hg/hgrc`` will be created on the remote side.
1455 ``.hg/hgrc`` will be created on the remote side.
1457
1456
1458 If the source repository has a bookmark called '@' set, that
1457 If the source repository has a bookmark called '@' set, that
1459 revision will be checked out in the new repository by default.
1458 revision will be checked out in the new repository by default.
1460
1459
1461 To check out a particular version, use -u/--update, or
1460 To check out a particular version, use -u/--update, or
1462 -U/--noupdate to create a clone with no working directory.
1461 -U/--noupdate to create a clone with no working directory.
1463
1462
1464 To pull only a subset of changesets, specify one or more revisions
1463 To pull only a subset of changesets, specify one or more revisions
1465 identifiers with -r/--rev or branches with -b/--branch. The
1464 identifiers with -r/--rev or branches with -b/--branch. The
1466 resulting clone will contain only the specified changesets and
1465 resulting clone will contain only the specified changesets and
1467 their ancestors. These options (or 'clone src#rev dest') imply
1466 their ancestors. These options (or 'clone src#rev dest') imply
1468 --pull, even for local source repositories.
1467 --pull, even for local source repositories.
1469
1468
1470 .. note::
1469 .. note::
1471
1470
1472 Specifying a tag will include the tagged changeset but not the
1471 Specifying a tag will include the tagged changeset but not the
1473 changeset containing the tag.
1472 changeset containing the tag.
1474
1473
1475 .. container:: verbose
1474 .. container:: verbose
1476
1475
1477 For efficiency, hardlinks are used for cloning whenever the
1476 For efficiency, hardlinks are used for cloning whenever the
1478 source and destination are on the same filesystem (note this
1477 source and destination are on the same filesystem (note this
1479 applies only to the repository data, not to the working
1478 applies only to the repository data, not to the working
1480 directory). Some filesystems, such as AFS, implement hardlinking
1479 directory). Some filesystems, such as AFS, implement hardlinking
1481 incorrectly, but do not report errors. In these cases, use the
1480 incorrectly, but do not report errors. In these cases, use the
1482 --pull option to avoid hardlinking.
1481 --pull option to avoid hardlinking.
1483
1482
1484 In some cases, you can clone repositories and the working
1483 In some cases, you can clone repositories and the working
1485 directory using full hardlinks with ::
1484 directory using full hardlinks with ::
1486
1485
1487 $ cp -al REPO REPOCLONE
1486 $ cp -al REPO REPOCLONE
1488
1487
1489 This is the fastest way to clone, but it is not always safe. The
1488 This is the fastest way to clone, but it is not always safe. The
1490 operation is not atomic (making sure REPO is not modified during
1489 operation is not atomic (making sure REPO is not modified during
1491 the operation is up to you) and you have to make sure your
1490 the operation is up to you) and you have to make sure your
1492 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1493 so). Also, this is not compatible with certain extensions that
1492 so). Also, this is not compatible with certain extensions that
1494 place their metadata under the .hg directory, such as mq.
1493 place their metadata under the .hg directory, such as mq.
1495
1494
1496 Mercurial will update the working directory to the first applicable
1495 Mercurial will update the working directory to the first applicable
1497 revision from this list:
1496 revision from this list:
1498
1497
1499 a) null if -U or the source repository has no changesets
1498 a) null if -U or the source repository has no changesets
1500 b) if -u . and the source repository is local, the first parent of
1499 b) if -u . and the source repository is local, the first parent of
1501 the source repository's working directory
1500 the source repository's working directory
1502 c) the changeset specified with -u (if a branch name, this means the
1501 c) the changeset specified with -u (if a branch name, this means the
1503 latest head of that branch)
1502 latest head of that branch)
1504 d) the changeset specified with -r
1503 d) the changeset specified with -r
1505 e) the tipmost head specified with -b
1504 e) the tipmost head specified with -b
1506 f) the tipmost head specified with the url#branch source syntax
1505 f) the tipmost head specified with the url#branch source syntax
1507 g) the revision marked with the '@' bookmark, if present
1506 g) the revision marked with the '@' bookmark, if present
1508 h) the tipmost head of the default branch
1507 h) the tipmost head of the default branch
1509 i) tip
1508 i) tip
1510
1509
1511 When cloning from servers that support it, Mercurial may fetch
1510 When cloning from servers that support it, Mercurial may fetch
1512 pre-generated data from a server-advertised URL. When this is done,
1511 pre-generated data from a server-advertised URL. When this is done,
1513 hooks operating on incoming changesets and changegroups may fire twice,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1514 once for the bundle fetched from the URL and another for any additional
1513 once for the bundle fetched from the URL and another for any additional
1515 data not fetched from this URL. In addition, if an error occurs, the
1514 data not fetched from this URL. In addition, if an error occurs, the
1516 repository may be rolled back to a partial clone. This behavior may
1515 repository may be rolled back to a partial clone. This behavior may
1517 change in future releases. See :hg:`help -e clonebundles` for more.
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1518
1517
1519 Examples:
1518 Examples:
1520
1519
1521 - clone a remote repository to a new directory named hg/::
1520 - clone a remote repository to a new directory named hg/::
1522
1521
1523 hg clone https://www.mercurial-scm.org/repo/hg/
1522 hg clone https://www.mercurial-scm.org/repo/hg/
1524
1523
1525 - create a lightweight local clone::
1524 - create a lightweight local clone::
1526
1525
1527 hg clone project/ project-feature/
1526 hg clone project/ project-feature/
1528
1527
1529 - clone from an absolute path on an ssh server (note double-slash)::
1528 - clone from an absolute path on an ssh server (note double-slash)::
1530
1529
1531 hg clone ssh://user@server//home/projects/alpha/
1530 hg clone ssh://user@server//home/projects/alpha/
1532
1531
1533 - do a high-speed clone over a LAN while checking out a
1532 - do a high-speed clone over a LAN while checking out a
1534 specified version::
1533 specified version::
1535
1534
1536 hg clone --uncompressed http://server/repo -u 1.5
1535 hg clone --uncompressed http://server/repo -u 1.5
1537
1536
1538 - create a repository without changesets after a particular revision::
1537 - create a repository without changesets after a particular revision::
1539
1538
1540 hg clone -r 04e544 experimental/ good/
1539 hg clone -r 04e544 experimental/ good/
1541
1540
1542 - clone (and track) a particular named branch::
1541 - clone (and track) a particular named branch::
1543
1542
1544 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1543 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1545
1544
1546 See :hg:`help urls` for details on specifying URLs.
1545 See :hg:`help urls` for details on specifying URLs.
1547
1546
1548 Returns 0 on success.
1547 Returns 0 on success.
1549 """
1548 """
1550 if opts.get('noupdate') and opts.get('updaterev'):
1549 if opts.get('noupdate') and opts.get('updaterev'):
1551 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1552
1551
1553 r = hg.clone(ui, opts, source, dest,
1552 r = hg.clone(ui, opts, source, dest,
1554 pull=opts.get('pull'),
1553 pull=opts.get('pull'),
1555 stream=opts.get('uncompressed'),
1554 stream=opts.get('uncompressed'),
1556 rev=opts.get('rev'),
1555 rev=opts.get('rev'),
1557 update=opts.get('updaterev') or not opts.get('noupdate'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1558 branch=opts.get('branch'),
1557 branch=opts.get('branch'),
1559 shareopts=opts.get('shareopts'))
1558 shareopts=opts.get('shareopts'))
1560
1559
1561 return r is None
1560 return r is None
1562
1561
1563 @command('^commit|ci',
1562 @command('^commit|ci',
1564 [('A', 'addremove', None,
1563 [('A', 'addremove', None,
1565 _('mark new/missing files as added/removed before committing')),
1564 _('mark new/missing files as added/removed before committing')),
1566 ('', 'close-branch', None,
1565 ('', 'close-branch', None,
1567 _('mark a branch head as closed')),
1566 _('mark a branch head as closed')),
1568 ('', 'amend', None, _('amend the parent of the working directory')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1569 ('s', 'secret', None, _('use the secret phase for committing')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1570 ('e', 'edit', None, _('invoke editor on commit messages')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1571 ('i', 'interactive', None, _('use interactive mode')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1572 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1573 _('[OPTION]... [FILE]...'),
1572 _('[OPTION]... [FILE]...'),
1574 inferrepo=True)
1573 inferrepo=True)
1575 def commit(ui, repo, *pats, **opts):
1574 def commit(ui, repo, *pats, **opts):
1576 """commit the specified files or all outstanding changes
1575 """commit the specified files or all outstanding changes
1577
1576
1578 Commit changes to the given files into the repository. Unlike a
1577 Commit changes to the given files into the repository. Unlike a
1579 centralized SCM, this operation is a local operation. See
1578 centralized SCM, this operation is a local operation. See
1580 :hg:`push` for a way to actively distribute your changes.
1579 :hg:`push` for a way to actively distribute your changes.
1581
1580
1582 If a list of files is omitted, all changes reported by :hg:`status`
1581 If a list of files is omitted, all changes reported by :hg:`status`
1583 will be committed.
1582 will be committed.
1584
1583
1585 If you are committing the result of a merge, do not provide any
1584 If you are committing the result of a merge, do not provide any
1586 filenames or -I/-X filters.
1585 filenames or -I/-X filters.
1587
1586
1588 If no commit message is specified, Mercurial starts your
1587 If no commit message is specified, Mercurial starts your
1589 configured editor where you can enter a message. In case your
1588 configured editor where you can enter a message. In case your
1590 commit fails, you will find a backup of your message in
1589 commit fails, you will find a backup of your message in
1591 ``.hg/last-message.txt``.
1590 ``.hg/last-message.txt``.
1592
1591
1593 The --close-branch flag can be used to mark the current branch
1592 The --close-branch flag can be used to mark the current branch
1594 head closed. When all heads of a branch are closed, the branch
1593 head closed. When all heads of a branch are closed, the branch
1595 will be considered closed and no longer listed.
1594 will be considered closed and no longer listed.
1596
1595
1597 The --amend flag can be used to amend the parent of the
1596 The --amend flag can be used to amend the parent of the
1598 working directory with a new commit that contains the changes
1597 working directory with a new commit that contains the changes
1599 in the parent in addition to those currently reported by :hg:`status`,
1598 in the parent in addition to those currently reported by :hg:`status`,
1600 if there are any. The old commit is stored in a backup bundle in
1599 if there are any. The old commit is stored in a backup bundle in
1601 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1602 on how to restore it).
1601 on how to restore it).
1603
1602
1604 Message, user and date are taken from the amended commit unless
1603 Message, user and date are taken from the amended commit unless
1605 specified. When a message isn't specified on the command line,
1604 specified. When a message isn't specified on the command line,
1606 the editor will open with the message of the amended commit.
1605 the editor will open with the message of the amended commit.
1607
1606
1608 It is not possible to amend public changesets (see :hg:`help phases`)
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1609 or changesets that have children.
1608 or changesets that have children.
1610
1609
1611 See :hg:`help dates` for a list of formats valid for -d/--date.
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1612
1611
1613 Returns 0 on success, 1 if nothing changed.
1612 Returns 0 on success, 1 if nothing changed.
1614
1613
1615 .. container:: verbose
1614 .. container:: verbose
1616
1615
1617 Examples:
1616 Examples:
1618
1617
1619 - commit all files ending in .py::
1618 - commit all files ending in .py::
1620
1619
1621 hg commit --include "set:**.py"
1620 hg commit --include "set:**.py"
1622
1621
1623 - commit all non-binary files::
1622 - commit all non-binary files::
1624
1623
1625 hg commit --exclude "set:binary()"
1624 hg commit --exclude "set:binary()"
1626
1625
1627 - amend the current commit and set the date to now::
1626 - amend the current commit and set the date to now::
1628
1627
1629 hg commit --amend --date now
1628 hg commit --amend --date now
1630 """
1629 """
1631 wlock = lock = None
1630 wlock = lock = None
1632 try:
1631 try:
1633 wlock = repo.wlock()
1632 wlock = repo.wlock()
1634 lock = repo.lock()
1633 lock = repo.lock()
1635 return _docommit(ui, repo, *pats, **opts)
1634 return _docommit(ui, repo, *pats, **opts)
1636 finally:
1635 finally:
1637 release(lock, wlock)
1636 release(lock, wlock)
1638
1637
1639 def _docommit(ui, repo, *pats, **opts):
1638 def _docommit(ui, repo, *pats, **opts):
1640 if opts.get('interactive'):
1639 if opts.get('interactive'):
1641 opts.pop('interactive')
1640 opts.pop('interactive')
1642 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1641 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1643 cmdutil.recordfilter, *pats, **opts)
1642 cmdutil.recordfilter, *pats, **opts)
1644 # ret can be 0 (no changes to record) or the value returned by
1643 # ret can be 0 (no changes to record) or the value returned by
1645 # commit(), 1 if nothing changed or None on success.
1644 # commit(), 1 if nothing changed or None on success.
1646 return 1 if ret == 0 else ret
1645 return 1 if ret == 0 else ret
1647
1646
1648 if opts.get('subrepos'):
1647 if opts.get('subrepos'):
1649 if opts.get('amend'):
1648 if opts.get('amend'):
1650 raise error.Abort(_('cannot amend with --subrepos'))
1649 raise error.Abort(_('cannot amend with --subrepos'))
1651 # Let --subrepos on the command line override config setting.
1650 # Let --subrepos on the command line override config setting.
1652 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1651 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1653
1652
1654 cmdutil.checkunfinished(repo, commit=True)
1653 cmdutil.checkunfinished(repo, commit=True)
1655
1654
1656 branch = repo[None].branch()
1655 branch = repo[None].branch()
1657 bheads = repo.branchheads(branch)
1656 bheads = repo.branchheads(branch)
1658
1657
1659 extra = {}
1658 extra = {}
1660 if opts.get('close_branch'):
1659 if opts.get('close_branch'):
1661 extra['close'] = 1
1660 extra['close'] = 1
1662
1661
1663 if not bheads:
1662 if not bheads:
1664 raise error.Abort(_('can only close branch heads'))
1663 raise error.Abort(_('can only close branch heads'))
1665 elif opts.get('amend'):
1664 elif opts.get('amend'):
1666 if repo[None].parents()[0].p1().branch() != branch and \
1665 if repo[None].parents()[0].p1().branch() != branch and \
1667 repo[None].parents()[0].p2().branch() != branch:
1666 repo[None].parents()[0].p2().branch() != branch:
1668 raise error.Abort(_('can only close branch heads'))
1667 raise error.Abort(_('can only close branch heads'))
1669
1668
1670 if opts.get('amend'):
1669 if opts.get('amend'):
1671 if ui.configbool('ui', 'commitsubrepos'):
1670 if ui.configbool('ui', 'commitsubrepos'):
1672 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1671 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1673
1672
1674 old = repo['.']
1673 old = repo['.']
1675 if not old.mutable():
1674 if not old.mutable():
1676 raise error.Abort(_('cannot amend public changesets'))
1675 raise error.Abort(_('cannot amend public changesets'))
1677 if len(repo[None].parents()) > 1:
1676 if len(repo[None].parents()) > 1:
1678 raise error.Abort(_('cannot amend while merging'))
1677 raise error.Abort(_('cannot amend while merging'))
1679 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1678 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1680 if not allowunstable and old.children():
1679 if not allowunstable and old.children():
1681 raise error.Abort(_('cannot amend changeset with children'))
1680 raise error.Abort(_('cannot amend changeset with children'))
1682
1681
1683 # Currently histedit gets confused if an amend happens while histedit
1682 # Currently histedit gets confused if an amend happens while histedit
1684 # is in progress. Since we have a checkunfinished command, we are
1683 # is in progress. Since we have a checkunfinished command, we are
1685 # temporarily honoring it.
1684 # temporarily honoring it.
1686 #
1685 #
1687 # Note: eventually this guard will be removed. Please do not expect
1686 # Note: eventually this guard will be removed. Please do not expect
1688 # this behavior to remain.
1687 # this behavior to remain.
1689 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1688 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1690 cmdutil.checkunfinished(repo)
1689 cmdutil.checkunfinished(repo)
1691
1690
1692 # commitfunc is used only for temporary amend commit by cmdutil.amend
1691 # commitfunc is used only for temporary amend commit by cmdutil.amend
1693 def commitfunc(ui, repo, message, match, opts):
1692 def commitfunc(ui, repo, message, match, opts):
1694 return repo.commit(message,
1693 return repo.commit(message,
1695 opts.get('user') or old.user(),
1694 opts.get('user') or old.user(),
1696 opts.get('date') or old.date(),
1695 opts.get('date') or old.date(),
1697 match,
1696 match,
1698 extra=extra)
1697 extra=extra)
1699
1698
1700 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1699 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1701 if node == old.node():
1700 if node == old.node():
1702 ui.status(_("nothing changed\n"))
1701 ui.status(_("nothing changed\n"))
1703 return 1
1702 return 1
1704 else:
1703 else:
1705 def commitfunc(ui, repo, message, match, opts):
1704 def commitfunc(ui, repo, message, match, opts):
1706 backup = ui.backupconfig('phases', 'new-commit')
1705 backup = ui.backupconfig('phases', 'new-commit')
1707 baseui = repo.baseui
1706 baseui = repo.baseui
1708 basebackup = baseui.backupconfig('phases', 'new-commit')
1707 basebackup = baseui.backupconfig('phases', 'new-commit')
1709 try:
1708 try:
1710 if opts.get('secret'):
1709 if opts.get('secret'):
1711 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1710 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1712 # Propagate to subrepos
1711 # Propagate to subrepos
1713 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1712 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1714
1713
1715 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1714 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1716 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1715 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1717 return repo.commit(message, opts.get('user'), opts.get('date'),
1716 return repo.commit(message, opts.get('user'), opts.get('date'),
1718 match,
1717 match,
1719 editor=editor,
1718 editor=editor,
1720 extra=extra)
1719 extra=extra)
1721 finally:
1720 finally:
1722 ui.restoreconfig(backup)
1721 ui.restoreconfig(backup)
1723 repo.baseui.restoreconfig(basebackup)
1722 repo.baseui.restoreconfig(basebackup)
1724
1723
1725
1724
1726 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1725 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1727
1726
1728 if not node:
1727 if not node:
1729 stat = cmdutil.postcommitstatus(repo, pats, opts)
1728 stat = cmdutil.postcommitstatus(repo, pats, opts)
1730 if stat[3]:
1729 if stat[3]:
1731 ui.status(_("nothing changed (%d missing files, see "
1730 ui.status(_("nothing changed (%d missing files, see "
1732 "'hg status')\n") % len(stat[3]))
1731 "'hg status')\n") % len(stat[3]))
1733 else:
1732 else:
1734 ui.status(_("nothing changed\n"))
1733 ui.status(_("nothing changed\n"))
1735 return 1
1734 return 1
1736
1735
1737 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1736 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1738
1737
1739 @command('config|showconfig|debugconfig',
1738 @command('config|showconfig|debugconfig',
1740 [('u', 'untrusted', None, _('show untrusted configuration options')),
1739 [('u', 'untrusted', None, _('show untrusted configuration options')),
1741 ('e', 'edit', None, _('edit user config')),
1740 ('e', 'edit', None, _('edit user config')),
1742 ('l', 'local', None, _('edit repository config')),
1741 ('l', 'local', None, _('edit repository config')),
1743 ('g', 'global', None, _('edit global config'))] + formatteropts,
1742 ('g', 'global', None, _('edit global config'))] + formatteropts,
1744 _('[-u] [NAME]...'),
1743 _('[-u] [NAME]...'),
1745 optionalrepo=True)
1744 optionalrepo=True)
1746 def config(ui, repo, *values, **opts):
1745 def config(ui, repo, *values, **opts):
1747 """show combined config settings from all hgrc files
1746 """show combined config settings from all hgrc files
1748
1747
1749 With no arguments, print names and values of all config items.
1748 With no arguments, print names and values of all config items.
1750
1749
1751 With one argument of the form section.name, print just the value
1750 With one argument of the form section.name, print just the value
1752 of that config item.
1751 of that config item.
1753
1752
1754 With multiple arguments, print names and values of all config
1753 With multiple arguments, print names and values of all config
1755 items with matching section names.
1754 items with matching section names.
1756
1755
1757 With --edit, start an editor on the user-level config file. With
1756 With --edit, start an editor on the user-level config file. With
1758 --global, edit the system-wide config file. With --local, edit the
1757 --global, edit the system-wide config file. With --local, edit the
1759 repository-level config file.
1758 repository-level config file.
1760
1759
1761 With --debug, the source (filename and line number) is printed
1760 With --debug, the source (filename and line number) is printed
1762 for each config item.
1761 for each config item.
1763
1762
1764 See :hg:`help config` for more information about config files.
1763 See :hg:`help config` for more information about config files.
1765
1764
1766 Returns 0 on success, 1 if NAME does not exist.
1765 Returns 0 on success, 1 if NAME does not exist.
1767
1766
1768 """
1767 """
1769
1768
1770 if opts.get('edit') or opts.get('local') or opts.get('global'):
1769 if opts.get('edit') or opts.get('local') or opts.get('global'):
1771 if opts.get('local') and opts.get('global'):
1770 if opts.get('local') and opts.get('global'):
1772 raise error.Abort(_("can't use --local and --global together"))
1771 raise error.Abort(_("can't use --local and --global together"))
1773
1772
1774 if opts.get('local'):
1773 if opts.get('local'):
1775 if not repo:
1774 if not repo:
1776 raise error.Abort(_("can't use --local outside a repository"))
1775 raise error.Abort(_("can't use --local outside a repository"))
1777 paths = [repo.join('hgrc')]
1776 paths = [repo.join('hgrc')]
1778 elif opts.get('global'):
1777 elif opts.get('global'):
1779 paths = scmutil.systemrcpath()
1778 paths = scmutil.systemrcpath()
1780 else:
1779 else:
1781 paths = scmutil.userrcpath()
1780 paths = scmutil.userrcpath()
1782
1781
1783 for f in paths:
1782 for f in paths:
1784 if os.path.exists(f):
1783 if os.path.exists(f):
1785 break
1784 break
1786 else:
1785 else:
1787 if opts.get('global'):
1786 if opts.get('global'):
1788 samplehgrc = uimod.samplehgrcs['global']
1787 samplehgrc = uimod.samplehgrcs['global']
1789 elif opts.get('local'):
1788 elif opts.get('local'):
1790 samplehgrc = uimod.samplehgrcs['local']
1789 samplehgrc = uimod.samplehgrcs['local']
1791 else:
1790 else:
1792 samplehgrc = uimod.samplehgrcs['user']
1791 samplehgrc = uimod.samplehgrcs['user']
1793
1792
1794 f = paths[0]
1793 f = paths[0]
1795 fp = open(f, "w")
1794 fp = open(f, "w")
1796 fp.write(samplehgrc)
1795 fp.write(samplehgrc)
1797 fp.close()
1796 fp.close()
1798
1797
1799 editor = ui.geteditor()
1798 editor = ui.geteditor()
1800 ui.system("%s \"%s\"" % (editor, f),
1799 ui.system("%s \"%s\"" % (editor, f),
1801 onerr=error.Abort, errprefix=_("edit failed"))
1800 onerr=error.Abort, errprefix=_("edit failed"))
1802 return
1801 return
1803
1802
1804 fm = ui.formatter('config', opts)
1803 fm = ui.formatter('config', opts)
1805 for f in scmutil.rcpath():
1804 for f in scmutil.rcpath():
1806 ui.debug('read config from: %s\n' % f)
1805 ui.debug('read config from: %s\n' % f)
1807 untrusted = bool(opts.get('untrusted'))
1806 untrusted = bool(opts.get('untrusted'))
1808 if values:
1807 if values:
1809 sections = [v for v in values if '.' not in v]
1808 sections = [v for v in values if '.' not in v]
1810 items = [v for v in values if '.' in v]
1809 items = [v for v in values if '.' in v]
1811 if len(items) > 1 or items and sections:
1810 if len(items) > 1 or items and sections:
1812 raise error.Abort(_('only one config item permitted'))
1811 raise error.Abort(_('only one config item permitted'))
1813 matched = False
1812 matched = False
1814 for section, name, value in ui.walkconfig(untrusted=untrusted):
1813 for section, name, value in ui.walkconfig(untrusted=untrusted):
1815 value = str(value)
1814 value = str(value)
1816 if fm.isplain():
1815 if fm.isplain():
1817 value = value.replace('\n', '\\n')
1816 value = value.replace('\n', '\\n')
1818 entryname = section + '.' + name
1817 entryname = section + '.' + name
1819 if values:
1818 if values:
1820 for v in values:
1819 for v in values:
1821 if v == section:
1820 if v == section:
1822 fm.startitem()
1821 fm.startitem()
1823 fm.condwrite(ui.debugflag, 'source', '%s: ',
1822 fm.condwrite(ui.debugflag, 'source', '%s: ',
1824 ui.configsource(section, name, untrusted))
1823 ui.configsource(section, name, untrusted))
1825 fm.write('name value', '%s=%s\n', entryname, value)
1824 fm.write('name value', '%s=%s\n', entryname, value)
1826 matched = True
1825 matched = True
1827 elif v == entryname:
1826 elif v == entryname:
1828 fm.startitem()
1827 fm.startitem()
1829 fm.condwrite(ui.debugflag, 'source', '%s: ',
1828 fm.condwrite(ui.debugflag, 'source', '%s: ',
1830 ui.configsource(section, name, untrusted))
1829 ui.configsource(section, name, untrusted))
1831 fm.write('value', '%s\n', value)
1830 fm.write('value', '%s\n', value)
1832 fm.data(name=entryname)
1831 fm.data(name=entryname)
1833 matched = True
1832 matched = True
1834 else:
1833 else:
1835 fm.startitem()
1834 fm.startitem()
1836 fm.condwrite(ui.debugflag, 'source', '%s: ',
1835 fm.condwrite(ui.debugflag, 'source', '%s: ',
1837 ui.configsource(section, name, untrusted))
1836 ui.configsource(section, name, untrusted))
1838 fm.write('name value', '%s=%s\n', entryname, value)
1837 fm.write('name value', '%s=%s\n', entryname, value)
1839 matched = True
1838 matched = True
1840 fm.end()
1839 fm.end()
1841 if matched:
1840 if matched:
1842 return 0
1841 return 0
1843 return 1
1842 return 1
1844
1843
1845 @command('copy|cp',
1844 @command('copy|cp',
1846 [('A', 'after', None, _('record a copy that has already occurred')),
1845 [('A', 'after', None, _('record a copy that has already occurred')),
1847 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1848 ] + walkopts + dryrunopts,
1847 ] + walkopts + dryrunopts,
1849 _('[OPTION]... [SOURCE]... DEST'))
1848 _('[OPTION]... [SOURCE]... DEST'))
1850 def copy(ui, repo, *pats, **opts):
1849 def copy(ui, repo, *pats, **opts):
1851 """mark files as copied for the next commit
1850 """mark files as copied for the next commit
1852
1851
1853 Mark dest as having copies of source files. If dest is a
1852 Mark dest as having copies of source files. If dest is a
1854 directory, copies are put in that directory. If dest is a file,
1853 directory, copies are put in that directory. If dest is a file,
1855 the source must be a single file.
1854 the source must be a single file.
1856
1855
1857 By default, this command copies the contents of files as they
1856 By default, this command copies the contents of files as they
1858 exist in the working directory. If invoked with -A/--after, the
1857 exist in the working directory. If invoked with -A/--after, the
1859 operation is recorded, but no copying is performed.
1858 operation is recorded, but no copying is performed.
1860
1859
1861 This command takes effect with the next commit. To undo a copy
1860 This command takes effect with the next commit. To undo a copy
1862 before that, see :hg:`revert`.
1861 before that, see :hg:`revert`.
1863
1862
1864 Returns 0 on success, 1 if errors are encountered.
1863 Returns 0 on success, 1 if errors are encountered.
1865 """
1864 """
1866 with repo.wlock(False):
1865 with repo.wlock(False):
1867 return cmdutil.copy(ui, repo, pats, opts)
1866 return cmdutil.copy(ui, repo, pats, opts)
1868
1867
1869 @command('debugdag',
1870 [('t', 'tags', None, _('use tags as labels')),
1871 ('b', 'branches', None, _('annotate with branch names')),
1872 ('', 'dots', None, _('use dots for runs')),
1873 ('s', 'spaces', None, _('separate elements by spaces'))],
1874 _('[OPTION]... [FILE [REV]...]'),
1875 optionalrepo=True)
1876 def debugdag(ui, repo, file_=None, *revs, **opts):
1877 """format the changelog or an index DAG as a concise textual description
1878
1879 If you pass a revlog index, the revlog's DAG is emitted. If you list
1880 revision numbers, they get labeled in the output as rN.
1881
1882 Otherwise, the changelog DAG of the current repo is emitted.
1883 """
1884 spaces = opts.get('spaces')
1885 dots = opts.get('dots')
1886 if file_:
1887 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1888 revs = set((int(r) for r in revs))
1889 def events():
1890 for r in rlog:
1891 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1892 if p != -1))
1893 if r in revs:
1894 yield 'l', (r, "r%i" % r)
1895 elif repo:
1896 cl = repo.changelog
1897 tags = opts.get('tags')
1898 branches = opts.get('branches')
1899 if tags:
1900 labels = {}
1901 for l, n in repo.tags().items():
1902 labels.setdefault(cl.rev(n), []).append(l)
1903 def events():
1904 b = "default"
1905 for r in cl:
1906 if branches:
1907 newb = cl.read(cl.node(r))[5]['branch']
1908 if newb != b:
1909 yield 'a', newb
1910 b = newb
1911 yield 'n', (r, list(p for p in cl.parentrevs(r)
1912 if p != -1))
1913 if tags:
1914 ls = labels.get(r)
1915 if ls:
1916 for l in ls:
1917 yield 'l', (r, l)
1918 else:
1919 raise error.Abort(_('need repo for changelog dag'))
1920
1921 for line in dagparser.dagtextlines(events(),
1922 addspaces=spaces,
1923 wraplabels=True,
1924 wrapannotations=True,
1925 wrapnonlinear=dots,
1926 usedots=dots,
1927 maxlinewidth=70):
1928 ui.write(line)
1929 ui.write("\n")
1930
1931 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
1868 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
1932 def debugdata(ui, repo, file_, rev=None, **opts):
1869 def debugdata(ui, repo, file_, rev=None, **opts):
1933 """dump the contents of a data file revision"""
1870 """dump the contents of a data file revision"""
1934 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
1871 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
1935 if rev is not None:
1872 if rev is not None:
1936 raise error.CommandError('debugdata', _('invalid arguments'))
1873 raise error.CommandError('debugdata', _('invalid arguments'))
1937 file_, rev = None, file_
1874 file_, rev = None, file_
1938 elif rev is None:
1875 elif rev is None:
1939 raise error.CommandError('debugdata', _('invalid arguments'))
1876 raise error.CommandError('debugdata', _('invalid arguments'))
1940 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1877 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1941 try:
1878 try:
1942 ui.write(r.revision(r.lookup(rev)))
1879 ui.write(r.revision(r.lookup(rev)))
1943 except KeyError:
1880 except KeyError:
1944 raise error.Abort(_('invalid revision identifier %s') % rev)
1881 raise error.Abort(_('invalid revision identifier %s') % rev)
1945
1882
1946 @command('debugdate',
1883 @command('debugdate',
1947 [('e', 'extended', None, _('try extended date formats'))],
1884 [('e', 'extended', None, _('try extended date formats'))],
1948 _('[-e] DATE [RANGE]'),
1885 _('[-e] DATE [RANGE]'),
1949 norepo=True, optionalrepo=True)
1886 norepo=True, optionalrepo=True)
1950 def debugdate(ui, date, range=None, **opts):
1887 def debugdate(ui, date, range=None, **opts):
1951 """parse and display a date"""
1888 """parse and display a date"""
1952 if opts["extended"]:
1889 if opts["extended"]:
1953 d = util.parsedate(date, util.extendeddateformats)
1890 d = util.parsedate(date, util.extendeddateformats)
1954 else:
1891 else:
1955 d = util.parsedate(date)
1892 d = util.parsedate(date)
1956 ui.write(("internal: %s %s\n") % d)
1893 ui.write(("internal: %s %s\n") % d)
1957 ui.write(("standard: %s\n") % util.datestr(d))
1894 ui.write(("standard: %s\n") % util.datestr(d))
1958 if range:
1895 if range:
1959 m = util.matchdate(range)
1896 m = util.matchdate(range)
1960 ui.write(("match: %s\n") % m(d[0]))
1897 ui.write(("match: %s\n") % m(d[0]))
1961
1898
1962 @command('debugdiscovery',
1899 @command('debugdiscovery',
1963 [('', 'old', None, _('use old-style discovery')),
1900 [('', 'old', None, _('use old-style discovery')),
1964 ('', 'nonheads', None,
1901 ('', 'nonheads', None,
1965 _('use old-style discovery with non-heads included')),
1902 _('use old-style discovery with non-heads included')),
1966 ] + remoteopts,
1903 ] + remoteopts,
1967 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1904 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1968 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1905 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1969 """runs the changeset discovery protocol in isolation"""
1906 """runs the changeset discovery protocol in isolation"""
1970 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1907 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1971 opts.get('branch'))
1908 opts.get('branch'))
1972 remote = hg.peer(repo, opts, remoteurl)
1909 remote = hg.peer(repo, opts, remoteurl)
1973 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1910 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1974
1911
1975 # make sure tests are repeatable
1912 # make sure tests are repeatable
1976 random.seed(12323)
1913 random.seed(12323)
1977
1914
1978 def doit(localheads, remoteheads, remote=remote):
1915 def doit(localheads, remoteheads, remote=remote):
1979 if opts.get('old'):
1916 if opts.get('old'):
1980 if localheads:
1917 if localheads:
1981 raise error.Abort('cannot use localheads with old style '
1918 raise error.Abort('cannot use localheads with old style '
1982 'discovery')
1919 'discovery')
1983 if not util.safehasattr(remote, 'branches'):
1920 if not util.safehasattr(remote, 'branches'):
1984 # enable in-client legacy support
1921 # enable in-client legacy support
1985 remote = localrepo.locallegacypeer(remote.local())
1922 remote = localrepo.locallegacypeer(remote.local())
1986 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1923 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1987 force=True)
1924 force=True)
1988 common = set(common)
1925 common = set(common)
1989 if not opts.get('nonheads'):
1926 if not opts.get('nonheads'):
1990 ui.write(("unpruned common: %s\n") %
1927 ui.write(("unpruned common: %s\n") %
1991 " ".join(sorted(short(n) for n in common)))
1928 " ".join(sorted(short(n) for n in common)))
1992 dag = dagutil.revlogdag(repo.changelog)
1929 dag = dagutil.revlogdag(repo.changelog)
1993 all = dag.ancestorset(dag.internalizeall(common))
1930 all = dag.ancestorset(dag.internalizeall(common))
1994 common = dag.externalizeall(dag.headsetofconnecteds(all))
1931 common = dag.externalizeall(dag.headsetofconnecteds(all))
1995 else:
1932 else:
1996 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1933 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1997 common = set(common)
1934 common = set(common)
1998 rheads = set(hds)
1935 rheads = set(hds)
1999 lheads = set(repo.heads())
1936 lheads = set(repo.heads())
2000 ui.write(("common heads: %s\n") %
1937 ui.write(("common heads: %s\n") %
2001 " ".join(sorted(short(n) for n in common)))
1938 " ".join(sorted(short(n) for n in common)))
2002 if lheads <= common:
1939 if lheads <= common:
2003 ui.write(("local is subset\n"))
1940 ui.write(("local is subset\n"))
2004 elif rheads <= common:
1941 elif rheads <= common:
2005 ui.write(("remote is subset\n"))
1942 ui.write(("remote is subset\n"))
2006
1943
2007 serverlogs = opts.get('serverlog')
1944 serverlogs = opts.get('serverlog')
2008 if serverlogs:
1945 if serverlogs:
2009 for filename in serverlogs:
1946 for filename in serverlogs:
2010 with open(filename, 'r') as logfile:
1947 with open(filename, 'r') as logfile:
2011 line = logfile.readline()
1948 line = logfile.readline()
2012 while line:
1949 while line:
2013 parts = line.strip().split(';')
1950 parts = line.strip().split(';')
2014 op = parts[1]
1951 op = parts[1]
2015 if op == 'cg':
1952 if op == 'cg':
2016 pass
1953 pass
2017 elif op == 'cgss':
1954 elif op == 'cgss':
2018 doit(parts[2].split(' '), parts[3].split(' '))
1955 doit(parts[2].split(' '), parts[3].split(' '))
2019 elif op == 'unb':
1956 elif op == 'unb':
2020 doit(parts[3].split(' '), parts[2].split(' '))
1957 doit(parts[3].split(' '), parts[2].split(' '))
2021 line = logfile.readline()
1958 line = logfile.readline()
2022 else:
1959 else:
2023 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1960 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2024 opts.get('remote_head'))
1961 opts.get('remote_head'))
2025 localrevs = opts.get('local_head')
1962 localrevs = opts.get('local_head')
2026 doit(localrevs, remoterevs)
1963 doit(localrevs, remoterevs)
2027
1964
2028 @command('debugextensions', formatteropts, [], norepo=True)
1965 @command('debugextensions', formatteropts, [], norepo=True)
2029 def debugextensions(ui, **opts):
1966 def debugextensions(ui, **opts):
2030 '''show information about active extensions'''
1967 '''show information about active extensions'''
2031 exts = extensions.extensions(ui)
1968 exts = extensions.extensions(ui)
2032 hgver = util.version()
1969 hgver = util.version()
2033 fm = ui.formatter('debugextensions', opts)
1970 fm = ui.formatter('debugextensions', opts)
2034 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1971 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2035 isinternal = extensions.ismoduleinternal(extmod)
1972 isinternal = extensions.ismoduleinternal(extmod)
2036 extsource = extmod.__file__
1973 extsource = extmod.__file__
2037 if isinternal:
1974 if isinternal:
2038 exttestedwith = [] # never expose magic string to users
1975 exttestedwith = [] # never expose magic string to users
2039 else:
1976 else:
2040 exttestedwith = getattr(extmod, 'testedwith', '').split()
1977 exttestedwith = getattr(extmod, 'testedwith', '').split()
2041 extbuglink = getattr(extmod, 'buglink', None)
1978 extbuglink = getattr(extmod, 'buglink', None)
2042
1979
2043 fm.startitem()
1980 fm.startitem()
2044
1981
2045 if ui.quiet or ui.verbose:
1982 if ui.quiet or ui.verbose:
2046 fm.write('name', '%s\n', extname)
1983 fm.write('name', '%s\n', extname)
2047 else:
1984 else:
2048 fm.write('name', '%s', extname)
1985 fm.write('name', '%s', extname)
2049 if isinternal or hgver in exttestedwith:
1986 if isinternal or hgver in exttestedwith:
2050 fm.plain('\n')
1987 fm.plain('\n')
2051 elif not exttestedwith:
1988 elif not exttestedwith:
2052 fm.plain(_(' (untested!)\n'))
1989 fm.plain(_(' (untested!)\n'))
2053 else:
1990 else:
2054 lasttestedversion = exttestedwith[-1]
1991 lasttestedversion = exttestedwith[-1]
2055 fm.plain(' (%s!)\n' % lasttestedversion)
1992 fm.plain(' (%s!)\n' % lasttestedversion)
2056
1993
2057 fm.condwrite(ui.verbose and extsource, 'source',
1994 fm.condwrite(ui.verbose and extsource, 'source',
2058 _(' location: %s\n'), extsource or "")
1995 _(' location: %s\n'), extsource or "")
2059
1996
2060 if ui.verbose:
1997 if ui.verbose:
2061 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
1998 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
2062 fm.data(bundled=isinternal)
1999 fm.data(bundled=isinternal)
2063
2000
2064 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2001 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2065 _(' tested with: %s\n'),
2002 _(' tested with: %s\n'),
2066 fm.formatlist(exttestedwith, name='ver'))
2003 fm.formatlist(exttestedwith, name='ver'))
2067
2004
2068 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2005 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2069 _(' bug reporting: %s\n'), extbuglink or "")
2006 _(' bug reporting: %s\n'), extbuglink or "")
2070
2007
2071 fm.end()
2008 fm.end()
2072
2009
2073 @command('debugfileset',
2010 @command('debugfileset',
2074 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2011 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2075 _('[-r REV] FILESPEC'))
2012 _('[-r REV] FILESPEC'))
2076 def debugfileset(ui, repo, expr, **opts):
2013 def debugfileset(ui, repo, expr, **opts):
2077 '''parse and apply a fileset specification'''
2014 '''parse and apply a fileset specification'''
2078 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2015 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2079 if ui.verbose:
2016 if ui.verbose:
2080 tree = fileset.parse(expr)
2017 tree = fileset.parse(expr)
2081 ui.note(fileset.prettyformat(tree), "\n")
2018 ui.note(fileset.prettyformat(tree), "\n")
2082
2019
2083 for f in ctx.getfileset(expr):
2020 for f in ctx.getfileset(expr):
2084 ui.write("%s\n" % f)
2021 ui.write("%s\n" % f)
2085
2022
2086 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2023 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2087 def debugfsinfo(ui, path="."):
2024 def debugfsinfo(ui, path="."):
2088 """show information detected about current filesystem"""
2025 """show information detected about current filesystem"""
2089 util.writefile('.debugfsinfo', '')
2026 util.writefile('.debugfsinfo', '')
2090 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2027 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2091 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2028 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2092 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2029 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2093 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2030 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2094 and 'yes' or 'no'))
2031 and 'yes' or 'no'))
2095 os.unlink('.debugfsinfo')
2032 os.unlink('.debugfsinfo')
2096
2033
2097 @command('debuggetbundle',
2034 @command('debuggetbundle',
2098 [('H', 'head', [], _('id of head node'), _('ID')),
2035 [('H', 'head', [], _('id of head node'), _('ID')),
2099 ('C', 'common', [], _('id of common node'), _('ID')),
2036 ('C', 'common', [], _('id of common node'), _('ID')),
2100 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2037 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2101 _('REPO FILE [-H|-C ID]...'),
2038 _('REPO FILE [-H|-C ID]...'),
2102 norepo=True)
2039 norepo=True)
2103 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2040 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2104 """retrieves a bundle from a repo
2041 """retrieves a bundle from a repo
2105
2042
2106 Every ID must be a full-length hex node id string. Saves the bundle to the
2043 Every ID must be a full-length hex node id string. Saves the bundle to the
2107 given file.
2044 given file.
2108 """
2045 """
2109 repo = hg.peer(ui, opts, repopath)
2046 repo = hg.peer(ui, opts, repopath)
2110 if not repo.capable('getbundle'):
2047 if not repo.capable('getbundle'):
2111 raise error.Abort("getbundle() not supported by target repository")
2048 raise error.Abort("getbundle() not supported by target repository")
2112 args = {}
2049 args = {}
2113 if common:
2050 if common:
2114 args['common'] = [bin(s) for s in common]
2051 args['common'] = [bin(s) for s in common]
2115 if head:
2052 if head:
2116 args['heads'] = [bin(s) for s in head]
2053 args['heads'] = [bin(s) for s in head]
2117 # TODO: get desired bundlecaps from command line.
2054 # TODO: get desired bundlecaps from command line.
2118 args['bundlecaps'] = None
2055 args['bundlecaps'] = None
2119 bundle = repo.getbundle('debug', **args)
2056 bundle = repo.getbundle('debug', **args)
2120
2057
2121 bundletype = opts.get('type', 'bzip2').lower()
2058 bundletype = opts.get('type', 'bzip2').lower()
2122 btypes = {'none': 'HG10UN',
2059 btypes = {'none': 'HG10UN',
2123 'bzip2': 'HG10BZ',
2060 'bzip2': 'HG10BZ',
2124 'gzip': 'HG10GZ',
2061 'gzip': 'HG10GZ',
2125 'bundle2': 'HG20'}
2062 'bundle2': 'HG20'}
2126 bundletype = btypes.get(bundletype)
2063 bundletype = btypes.get(bundletype)
2127 if bundletype not in bundle2.bundletypes:
2064 if bundletype not in bundle2.bundletypes:
2128 raise error.Abort(_('unknown bundle type specified with --type'))
2065 raise error.Abort(_('unknown bundle type specified with --type'))
2129 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2066 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2130
2067
2131 @command('debugignore', [], '[FILE]')
2068 @command('debugignore', [], '[FILE]')
2132 def debugignore(ui, repo, *files, **opts):
2069 def debugignore(ui, repo, *files, **opts):
2133 """display the combined ignore pattern and information about ignored files
2070 """display the combined ignore pattern and information about ignored files
2134
2071
2135 With no argument display the combined ignore pattern.
2072 With no argument display the combined ignore pattern.
2136
2073
2137 Given space separated file names, shows if the given file is ignored and
2074 Given space separated file names, shows if the given file is ignored and
2138 if so, show the ignore rule (file and line number) that matched it.
2075 if so, show the ignore rule (file and line number) that matched it.
2139 """
2076 """
2140 ignore = repo.dirstate._ignore
2077 ignore = repo.dirstate._ignore
2141 if not files:
2078 if not files:
2142 # Show all the patterns
2079 # Show all the patterns
2143 includepat = getattr(ignore, 'includepat', None)
2080 includepat = getattr(ignore, 'includepat', None)
2144 if includepat is not None:
2081 if includepat is not None:
2145 ui.write("%s\n" % includepat)
2082 ui.write("%s\n" % includepat)
2146 else:
2083 else:
2147 raise error.Abort(_("no ignore patterns found"))
2084 raise error.Abort(_("no ignore patterns found"))
2148 else:
2085 else:
2149 for f in files:
2086 for f in files:
2150 nf = util.normpath(f)
2087 nf = util.normpath(f)
2151 ignored = None
2088 ignored = None
2152 ignoredata = None
2089 ignoredata = None
2153 if nf != '.':
2090 if nf != '.':
2154 if ignore(nf):
2091 if ignore(nf):
2155 ignored = nf
2092 ignored = nf
2156 ignoredata = repo.dirstate._ignorefileandline(nf)
2093 ignoredata = repo.dirstate._ignorefileandline(nf)
2157 else:
2094 else:
2158 for p in util.finddirs(nf):
2095 for p in util.finddirs(nf):
2159 if ignore(p):
2096 if ignore(p):
2160 ignored = p
2097 ignored = p
2161 ignoredata = repo.dirstate._ignorefileandline(p)
2098 ignoredata = repo.dirstate._ignorefileandline(p)
2162 break
2099 break
2163 if ignored:
2100 if ignored:
2164 if ignored == nf:
2101 if ignored == nf:
2165 ui.write(_("%s is ignored\n") % f)
2102 ui.write(_("%s is ignored\n") % f)
2166 else:
2103 else:
2167 ui.write(_("%s is ignored because of "
2104 ui.write(_("%s is ignored because of "
2168 "containing folder %s\n")
2105 "containing folder %s\n")
2169 % (f, ignored))
2106 % (f, ignored))
2170 ignorefile, lineno, line = ignoredata
2107 ignorefile, lineno, line = ignoredata
2171 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2108 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2172 % (ignorefile, lineno, line))
2109 % (ignorefile, lineno, line))
2173 else:
2110 else:
2174 ui.write(_("%s is not ignored\n") % f)
2111 ui.write(_("%s is not ignored\n") % f)
2175
2112
2176 @command('debugindex', debugrevlogopts +
2113 @command('debugindex', debugrevlogopts +
2177 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2114 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2178 _('[-f FORMAT] -c|-m|FILE'),
2115 _('[-f FORMAT] -c|-m|FILE'),
2179 optionalrepo=True)
2116 optionalrepo=True)
2180 def debugindex(ui, repo, file_=None, **opts):
2117 def debugindex(ui, repo, file_=None, **opts):
2181 """dump the contents of an index file"""
2118 """dump the contents of an index file"""
2182 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2119 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2183 format = opts.get('format', 0)
2120 format = opts.get('format', 0)
2184 if format not in (0, 1):
2121 if format not in (0, 1):
2185 raise error.Abort(_("unknown format %d") % format)
2122 raise error.Abort(_("unknown format %d") % format)
2186
2123
2187 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2124 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2188 if generaldelta:
2125 if generaldelta:
2189 basehdr = ' delta'
2126 basehdr = ' delta'
2190 else:
2127 else:
2191 basehdr = ' base'
2128 basehdr = ' base'
2192
2129
2193 if ui.debugflag:
2130 if ui.debugflag:
2194 shortfn = hex
2131 shortfn = hex
2195 else:
2132 else:
2196 shortfn = short
2133 shortfn = short
2197
2134
2198 # There might not be anything in r, so have a sane default
2135 # There might not be anything in r, so have a sane default
2199 idlen = 12
2136 idlen = 12
2200 for i in r:
2137 for i in r:
2201 idlen = len(shortfn(r.node(i)))
2138 idlen = len(shortfn(r.node(i)))
2202 break
2139 break
2203
2140
2204 if format == 0:
2141 if format == 0:
2205 ui.write((" rev offset length " + basehdr + " linkrev"
2142 ui.write((" rev offset length " + basehdr + " linkrev"
2206 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2143 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2207 elif format == 1:
2144 elif format == 1:
2208 ui.write((" rev flag offset length"
2145 ui.write((" rev flag offset length"
2209 " size " + basehdr + " link p1 p2"
2146 " size " + basehdr + " link p1 p2"
2210 " %s\n") % "nodeid".rjust(idlen))
2147 " %s\n") % "nodeid".rjust(idlen))
2211
2148
2212 for i in r:
2149 for i in r:
2213 node = r.node(i)
2150 node = r.node(i)
2214 if generaldelta:
2151 if generaldelta:
2215 base = r.deltaparent(i)
2152 base = r.deltaparent(i)
2216 else:
2153 else:
2217 base = r.chainbase(i)
2154 base = r.chainbase(i)
2218 if format == 0:
2155 if format == 0:
2219 try:
2156 try:
2220 pp = r.parents(node)
2157 pp = r.parents(node)
2221 except Exception:
2158 except Exception:
2222 pp = [nullid, nullid]
2159 pp = [nullid, nullid]
2223 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2160 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2224 i, r.start(i), r.length(i), base, r.linkrev(i),
2161 i, r.start(i), r.length(i), base, r.linkrev(i),
2225 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2162 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2226 elif format == 1:
2163 elif format == 1:
2227 pr = r.parentrevs(i)
2164 pr = r.parentrevs(i)
2228 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2165 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2229 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2166 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2230 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2167 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2231
2168
2232 @command('debugindexdot', debugrevlogopts,
2169 @command('debugindexdot', debugrevlogopts,
2233 _('-c|-m|FILE'), optionalrepo=True)
2170 _('-c|-m|FILE'), optionalrepo=True)
2234 def debugindexdot(ui, repo, file_=None, **opts):
2171 def debugindexdot(ui, repo, file_=None, **opts):
2235 """dump an index DAG as a graphviz dot file"""
2172 """dump an index DAG as a graphviz dot file"""
2236 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2173 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2237 ui.write(("digraph G {\n"))
2174 ui.write(("digraph G {\n"))
2238 for i in r:
2175 for i in r:
2239 node = r.node(i)
2176 node = r.node(i)
2240 pp = r.parents(node)
2177 pp = r.parents(node)
2241 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2178 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2242 if pp[1] != nullid:
2179 if pp[1] != nullid:
2243 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2180 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2244 ui.write("}\n")
2181 ui.write("}\n")
2245
2182
2246 @command('debugdeltachain',
2183 @command('debugdeltachain',
2247 debugrevlogopts + formatteropts,
2184 debugrevlogopts + formatteropts,
2248 _('-c|-m|FILE'),
2185 _('-c|-m|FILE'),
2249 optionalrepo=True)
2186 optionalrepo=True)
2250 def debugdeltachain(ui, repo, file_=None, **opts):
2187 def debugdeltachain(ui, repo, file_=None, **opts):
2251 """dump information about delta chains in a revlog
2188 """dump information about delta chains in a revlog
2252
2189
2253 Output can be templatized. Available template keywords are:
2190 Output can be templatized. Available template keywords are:
2254
2191
2255 :``rev``: revision number
2192 :``rev``: revision number
2256 :``chainid``: delta chain identifier (numbered by unique base)
2193 :``chainid``: delta chain identifier (numbered by unique base)
2257 :``chainlen``: delta chain length to this revision
2194 :``chainlen``: delta chain length to this revision
2258 :``prevrev``: previous revision in delta chain
2195 :``prevrev``: previous revision in delta chain
2259 :``deltatype``: role of delta / how it was computed
2196 :``deltatype``: role of delta / how it was computed
2260 :``compsize``: compressed size of revision
2197 :``compsize``: compressed size of revision
2261 :``uncompsize``: uncompressed size of revision
2198 :``uncompsize``: uncompressed size of revision
2262 :``chainsize``: total size of compressed revisions in chain
2199 :``chainsize``: total size of compressed revisions in chain
2263 :``chainratio``: total chain size divided by uncompressed revision size
2200 :``chainratio``: total chain size divided by uncompressed revision size
2264 (new delta chains typically start at ratio 2.00)
2201 (new delta chains typically start at ratio 2.00)
2265 :``lindist``: linear distance from base revision in delta chain to end
2202 :``lindist``: linear distance from base revision in delta chain to end
2266 of this revision
2203 of this revision
2267 :``extradist``: total size of revisions not part of this delta chain from
2204 :``extradist``: total size of revisions not part of this delta chain from
2268 base of delta chain to end of this revision; a measurement
2205 base of delta chain to end of this revision; a measurement
2269 of how much extra data we need to read/seek across to read
2206 of how much extra data we need to read/seek across to read
2270 the delta chain for this revision
2207 the delta chain for this revision
2271 :``extraratio``: extradist divided by chainsize; another representation of
2208 :``extraratio``: extradist divided by chainsize; another representation of
2272 how much unrelated data is needed to load this delta chain
2209 how much unrelated data is needed to load this delta chain
2273 """
2210 """
2274 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2211 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2275 index = r.index
2212 index = r.index
2276 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2213 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2277
2214
2278 def revinfo(rev):
2215 def revinfo(rev):
2279 e = index[rev]
2216 e = index[rev]
2280 compsize = e[1]
2217 compsize = e[1]
2281 uncompsize = e[2]
2218 uncompsize = e[2]
2282 chainsize = 0
2219 chainsize = 0
2283
2220
2284 if generaldelta:
2221 if generaldelta:
2285 if e[3] == e[5]:
2222 if e[3] == e[5]:
2286 deltatype = 'p1'
2223 deltatype = 'p1'
2287 elif e[3] == e[6]:
2224 elif e[3] == e[6]:
2288 deltatype = 'p2'
2225 deltatype = 'p2'
2289 elif e[3] == rev - 1:
2226 elif e[3] == rev - 1:
2290 deltatype = 'prev'
2227 deltatype = 'prev'
2291 elif e[3] == rev:
2228 elif e[3] == rev:
2292 deltatype = 'base'
2229 deltatype = 'base'
2293 else:
2230 else:
2294 deltatype = 'other'
2231 deltatype = 'other'
2295 else:
2232 else:
2296 if e[3] == rev:
2233 if e[3] == rev:
2297 deltatype = 'base'
2234 deltatype = 'base'
2298 else:
2235 else:
2299 deltatype = 'prev'
2236 deltatype = 'prev'
2300
2237
2301 chain = r._deltachain(rev)[0]
2238 chain = r._deltachain(rev)[0]
2302 for iterrev in chain:
2239 for iterrev in chain:
2303 e = index[iterrev]
2240 e = index[iterrev]
2304 chainsize += e[1]
2241 chainsize += e[1]
2305
2242
2306 return compsize, uncompsize, deltatype, chain, chainsize
2243 return compsize, uncompsize, deltatype, chain, chainsize
2307
2244
2308 fm = ui.formatter('debugdeltachain', opts)
2245 fm = ui.formatter('debugdeltachain', opts)
2309
2246
2310 fm.plain(' rev chain# chainlen prev delta '
2247 fm.plain(' rev chain# chainlen prev delta '
2311 'size rawsize chainsize ratio lindist extradist '
2248 'size rawsize chainsize ratio lindist extradist '
2312 'extraratio\n')
2249 'extraratio\n')
2313
2250
2314 chainbases = {}
2251 chainbases = {}
2315 for rev in r:
2252 for rev in r:
2316 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2253 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2317 chainbase = chain[0]
2254 chainbase = chain[0]
2318 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2255 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2319 basestart = r.start(chainbase)
2256 basestart = r.start(chainbase)
2320 revstart = r.start(rev)
2257 revstart = r.start(rev)
2321 lineardist = revstart + comp - basestart
2258 lineardist = revstart + comp - basestart
2322 extradist = lineardist - chainsize
2259 extradist = lineardist - chainsize
2323 try:
2260 try:
2324 prevrev = chain[-2]
2261 prevrev = chain[-2]
2325 except IndexError:
2262 except IndexError:
2326 prevrev = -1
2263 prevrev = -1
2327
2264
2328 chainratio = float(chainsize) / float(uncomp)
2265 chainratio = float(chainsize) / float(uncomp)
2329 extraratio = float(extradist) / float(chainsize)
2266 extraratio = float(extradist) / float(chainsize)
2330
2267
2331 fm.startitem()
2268 fm.startitem()
2332 fm.write('rev chainid chainlen prevrev deltatype compsize '
2269 fm.write('rev chainid chainlen prevrev deltatype compsize '
2333 'uncompsize chainsize chainratio lindist extradist '
2270 'uncompsize chainsize chainratio lindist extradist '
2334 'extraratio',
2271 'extraratio',
2335 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2272 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2336 rev, chainid, len(chain), prevrev, deltatype, comp,
2273 rev, chainid, len(chain), prevrev, deltatype, comp,
2337 uncomp, chainsize, chainratio, lineardist, extradist,
2274 uncomp, chainsize, chainratio, lineardist, extradist,
2338 extraratio,
2275 extraratio,
2339 rev=rev, chainid=chainid, chainlen=len(chain),
2276 rev=rev, chainid=chainid, chainlen=len(chain),
2340 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2277 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2341 uncompsize=uncomp, chainsize=chainsize,
2278 uncompsize=uncomp, chainsize=chainsize,
2342 chainratio=chainratio, lindist=lineardist,
2279 chainratio=chainratio, lindist=lineardist,
2343 extradist=extradist, extraratio=extraratio)
2280 extradist=extradist, extraratio=extraratio)
2344
2281
2345 fm.end()
2282 fm.end()
2346
2283
2347 @command('debuginstall', [] + formatteropts, '', norepo=True)
2284 @command('debuginstall', [] + formatteropts, '', norepo=True)
2348 def debuginstall(ui, **opts):
2285 def debuginstall(ui, **opts):
2349 '''test Mercurial installation
2286 '''test Mercurial installation
2350
2287
2351 Returns 0 on success.
2288 Returns 0 on success.
2352 '''
2289 '''
2353
2290
2354 def writetemp(contents):
2291 def writetemp(contents):
2355 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2292 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2356 f = os.fdopen(fd, "wb")
2293 f = os.fdopen(fd, "wb")
2357 f.write(contents)
2294 f.write(contents)
2358 f.close()
2295 f.close()
2359 return name
2296 return name
2360
2297
2361 problems = 0
2298 problems = 0
2362
2299
2363 fm = ui.formatter('debuginstall', opts)
2300 fm = ui.formatter('debuginstall', opts)
2364 fm.startitem()
2301 fm.startitem()
2365
2302
2366 # encoding
2303 # encoding
2367 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2304 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2368 err = None
2305 err = None
2369 try:
2306 try:
2370 encoding.fromlocal("test")
2307 encoding.fromlocal("test")
2371 except error.Abort as inst:
2308 except error.Abort as inst:
2372 err = inst
2309 err = inst
2373 problems += 1
2310 problems += 1
2374 fm.condwrite(err, 'encodingerror', _(" %s\n"
2311 fm.condwrite(err, 'encodingerror', _(" %s\n"
2375 " (check that your locale is properly set)\n"), err)
2312 " (check that your locale is properly set)\n"), err)
2376
2313
2377 # Python
2314 # Python
2378 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2315 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2379 sys.executable)
2316 sys.executable)
2380 fm.write('pythonver', _("checking Python version (%s)\n"),
2317 fm.write('pythonver', _("checking Python version (%s)\n"),
2381 ("%s.%s.%s" % sys.version_info[:3]))
2318 ("%s.%s.%s" % sys.version_info[:3]))
2382 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2319 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2383 os.path.dirname(os.__file__))
2320 os.path.dirname(os.__file__))
2384
2321
2385 security = set(sslutil.supportedprotocols)
2322 security = set(sslutil.supportedprotocols)
2386 if sslutil.hassni:
2323 if sslutil.hassni:
2387 security.add('sni')
2324 security.add('sni')
2388
2325
2389 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
2326 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
2390 fm.formatlist(sorted(security), name='protocol',
2327 fm.formatlist(sorted(security), name='protocol',
2391 fmt='%s', sep=','))
2328 fmt='%s', sep=','))
2392
2329
2393 # These are warnings, not errors. So don't increment problem count. This
2330 # These are warnings, not errors. So don't increment problem count. This
2394 # may change in the future.
2331 # may change in the future.
2395 if 'tls1.2' not in security:
2332 if 'tls1.2' not in security:
2396 fm.plain(_(' TLS 1.2 not supported by Python install; '
2333 fm.plain(_(' TLS 1.2 not supported by Python install; '
2397 'network connections lack modern security\n'))
2334 'network connections lack modern security\n'))
2398 if 'sni' not in security:
2335 if 'sni' not in security:
2399 fm.plain(_(' SNI not supported by Python install; may have '
2336 fm.plain(_(' SNI not supported by Python install; may have '
2400 'connectivity issues with some servers\n'))
2337 'connectivity issues with some servers\n'))
2401
2338
2402 # TODO print CA cert info
2339 # TODO print CA cert info
2403
2340
2404 # hg version
2341 # hg version
2405 hgver = util.version()
2342 hgver = util.version()
2406 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2343 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2407 hgver.split('+')[0])
2344 hgver.split('+')[0])
2408 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2345 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2409 '+'.join(hgver.split('+')[1:]))
2346 '+'.join(hgver.split('+')[1:]))
2410
2347
2411 # compiled modules
2348 # compiled modules
2412 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2349 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2413 policy.policy)
2350 policy.policy)
2414 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2351 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2415 os.path.dirname(__file__))
2352 os.path.dirname(__file__))
2416
2353
2417 err = None
2354 err = None
2418 try:
2355 try:
2419 from . import (
2356 from . import (
2420 base85,
2357 base85,
2421 bdiff,
2358 bdiff,
2422 mpatch,
2359 mpatch,
2423 osutil,
2360 osutil,
2424 )
2361 )
2425 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2362 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2426 except Exception as inst:
2363 except Exception as inst:
2427 err = inst
2364 err = inst
2428 problems += 1
2365 problems += 1
2429 fm.condwrite(err, 'extensionserror', " %s\n", err)
2366 fm.condwrite(err, 'extensionserror', " %s\n", err)
2430
2367
2431 compengines = util.compengines._engines.values()
2368 compengines = util.compengines._engines.values()
2432 fm.write('compengines', _('checking registered compression engines (%s)\n'),
2369 fm.write('compengines', _('checking registered compression engines (%s)\n'),
2433 fm.formatlist(sorted(e.name() for e in compengines),
2370 fm.formatlist(sorted(e.name() for e in compengines),
2434 name='compengine', fmt='%s', sep=', '))
2371 name='compengine', fmt='%s', sep=', '))
2435 fm.write('compenginesavail', _('checking available compression engines '
2372 fm.write('compenginesavail', _('checking available compression engines '
2436 '(%s)\n'),
2373 '(%s)\n'),
2437 fm.formatlist(sorted(e.name() for e in compengines
2374 fm.formatlist(sorted(e.name() for e in compengines
2438 if e.available()),
2375 if e.available()),
2439 name='compengine', fmt='%s', sep=', '))
2376 name='compengine', fmt='%s', sep=', '))
2440
2377
2441 # templates
2378 # templates
2442 p = templater.templatepaths()
2379 p = templater.templatepaths()
2443 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2380 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2444 fm.condwrite(not p, '', _(" no template directories found\n"))
2381 fm.condwrite(not p, '', _(" no template directories found\n"))
2445 if p:
2382 if p:
2446 m = templater.templatepath("map-cmdline.default")
2383 m = templater.templatepath("map-cmdline.default")
2447 if m:
2384 if m:
2448 # template found, check if it is working
2385 # template found, check if it is working
2449 err = None
2386 err = None
2450 try:
2387 try:
2451 templater.templater.frommapfile(m)
2388 templater.templater.frommapfile(m)
2452 except Exception as inst:
2389 except Exception as inst:
2453 err = inst
2390 err = inst
2454 p = None
2391 p = None
2455 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2392 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2456 else:
2393 else:
2457 p = None
2394 p = None
2458 fm.condwrite(p, 'defaulttemplate',
2395 fm.condwrite(p, 'defaulttemplate',
2459 _("checking default template (%s)\n"), m)
2396 _("checking default template (%s)\n"), m)
2460 fm.condwrite(not m, 'defaulttemplatenotfound',
2397 fm.condwrite(not m, 'defaulttemplatenotfound',
2461 _(" template '%s' not found\n"), "default")
2398 _(" template '%s' not found\n"), "default")
2462 if not p:
2399 if not p:
2463 problems += 1
2400 problems += 1
2464 fm.condwrite(not p, '',
2401 fm.condwrite(not p, '',
2465 _(" (templates seem to have been installed incorrectly)\n"))
2402 _(" (templates seem to have been installed incorrectly)\n"))
2466
2403
2467 # editor
2404 # editor
2468 editor = ui.geteditor()
2405 editor = ui.geteditor()
2469 editor = util.expandpath(editor)
2406 editor = util.expandpath(editor)
2470 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2407 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2471 cmdpath = util.findexe(shlex.split(editor)[0])
2408 cmdpath = util.findexe(shlex.split(editor)[0])
2472 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2409 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2473 _(" No commit editor set and can't find %s in PATH\n"
2410 _(" No commit editor set and can't find %s in PATH\n"
2474 " (specify a commit editor in your configuration"
2411 " (specify a commit editor in your configuration"
2475 " file)\n"), not cmdpath and editor == 'vi' and editor)
2412 " file)\n"), not cmdpath and editor == 'vi' and editor)
2476 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2413 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2477 _(" Can't find editor '%s' in PATH\n"
2414 _(" Can't find editor '%s' in PATH\n"
2478 " (specify a commit editor in your configuration"
2415 " (specify a commit editor in your configuration"
2479 " file)\n"), not cmdpath and editor)
2416 " file)\n"), not cmdpath and editor)
2480 if not cmdpath and editor != 'vi':
2417 if not cmdpath and editor != 'vi':
2481 problems += 1
2418 problems += 1
2482
2419
2483 # check username
2420 # check username
2484 username = None
2421 username = None
2485 err = None
2422 err = None
2486 try:
2423 try:
2487 username = ui.username()
2424 username = ui.username()
2488 except error.Abort as e:
2425 except error.Abort as e:
2489 err = e
2426 err = e
2490 problems += 1
2427 problems += 1
2491
2428
2492 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2429 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2493 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2430 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2494 " (specify a username in your configuration file)\n"), err)
2431 " (specify a username in your configuration file)\n"), err)
2495
2432
2496 fm.condwrite(not problems, '',
2433 fm.condwrite(not problems, '',
2497 _("no problems detected\n"))
2434 _("no problems detected\n"))
2498 if not problems:
2435 if not problems:
2499 fm.data(problems=problems)
2436 fm.data(problems=problems)
2500 fm.condwrite(problems, 'problems',
2437 fm.condwrite(problems, 'problems',
2501 _("%d problems detected,"
2438 _("%d problems detected,"
2502 " please check your install!\n"), problems)
2439 " please check your install!\n"), problems)
2503 fm.end()
2440 fm.end()
2504
2441
2505 return problems
2442 return problems
2506
2443
2507 @command('debugknown', [], _('REPO ID...'), norepo=True)
2444 @command('debugknown', [], _('REPO ID...'), norepo=True)
2508 def debugknown(ui, repopath, *ids, **opts):
2445 def debugknown(ui, repopath, *ids, **opts):
2509 """test whether node ids are known to a repo
2446 """test whether node ids are known to a repo
2510
2447
2511 Every ID must be a full-length hex node id string. Returns a list of 0s
2448 Every ID must be a full-length hex node id string. Returns a list of 0s
2512 and 1s indicating unknown/known.
2449 and 1s indicating unknown/known.
2513 """
2450 """
2514 repo = hg.peer(ui, opts, repopath)
2451 repo = hg.peer(ui, opts, repopath)
2515 if not repo.capable('known'):
2452 if not repo.capable('known'):
2516 raise error.Abort("known() not supported by target repository")
2453 raise error.Abort("known() not supported by target repository")
2517 flags = repo.known([bin(s) for s in ids])
2454 flags = repo.known([bin(s) for s in ids])
2518 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2455 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2519
2456
2520 @command('debuglabelcomplete', [], _('LABEL...'))
2457 @command('debuglabelcomplete', [], _('LABEL...'))
2521 def debuglabelcomplete(ui, repo, *args):
2458 def debuglabelcomplete(ui, repo, *args):
2522 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2459 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2523 debugnamecomplete(ui, repo, *args)
2460 debugnamecomplete(ui, repo, *args)
2524
2461
2525 @command('debugmergestate', [], '')
2462 @command('debugmergestate', [], '')
2526 def debugmergestate(ui, repo, *args):
2463 def debugmergestate(ui, repo, *args):
2527 """print merge state
2464 """print merge state
2528
2465
2529 Use --verbose to print out information about whether v1 or v2 merge state
2466 Use --verbose to print out information about whether v1 or v2 merge state
2530 was chosen."""
2467 was chosen."""
2531 def _hashornull(h):
2468 def _hashornull(h):
2532 if h == nullhex:
2469 if h == nullhex:
2533 return 'null'
2470 return 'null'
2534 else:
2471 else:
2535 return h
2472 return h
2536
2473
2537 def printrecords(version):
2474 def printrecords(version):
2538 ui.write(('* version %s records\n') % version)
2475 ui.write(('* version %s records\n') % version)
2539 if version == 1:
2476 if version == 1:
2540 records = v1records
2477 records = v1records
2541 else:
2478 else:
2542 records = v2records
2479 records = v2records
2543
2480
2544 for rtype, record in records:
2481 for rtype, record in records:
2545 # pretty print some record types
2482 # pretty print some record types
2546 if rtype == 'L':
2483 if rtype == 'L':
2547 ui.write(('local: %s\n') % record)
2484 ui.write(('local: %s\n') % record)
2548 elif rtype == 'O':
2485 elif rtype == 'O':
2549 ui.write(('other: %s\n') % record)
2486 ui.write(('other: %s\n') % record)
2550 elif rtype == 'm':
2487 elif rtype == 'm':
2551 driver, mdstate = record.split('\0', 1)
2488 driver, mdstate = record.split('\0', 1)
2552 ui.write(('merge driver: %s (state "%s")\n')
2489 ui.write(('merge driver: %s (state "%s")\n')
2553 % (driver, mdstate))
2490 % (driver, mdstate))
2554 elif rtype in 'FDC':
2491 elif rtype in 'FDC':
2555 r = record.split('\0')
2492 r = record.split('\0')
2556 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2493 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2557 if version == 1:
2494 if version == 1:
2558 onode = 'not stored in v1 format'
2495 onode = 'not stored in v1 format'
2559 flags = r[7]
2496 flags = r[7]
2560 else:
2497 else:
2561 onode, flags = r[7:9]
2498 onode, flags = r[7:9]
2562 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2499 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2563 % (f, rtype, state, _hashornull(hash)))
2500 % (f, rtype, state, _hashornull(hash)))
2564 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2501 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2565 ui.write((' ancestor path: %s (node %s)\n')
2502 ui.write((' ancestor path: %s (node %s)\n')
2566 % (afile, _hashornull(anode)))
2503 % (afile, _hashornull(anode)))
2567 ui.write((' other path: %s (node %s)\n')
2504 ui.write((' other path: %s (node %s)\n')
2568 % (ofile, _hashornull(onode)))
2505 % (ofile, _hashornull(onode)))
2569 elif rtype == 'f':
2506 elif rtype == 'f':
2570 filename, rawextras = record.split('\0', 1)
2507 filename, rawextras = record.split('\0', 1)
2571 extras = rawextras.split('\0')
2508 extras = rawextras.split('\0')
2572 i = 0
2509 i = 0
2573 extrastrings = []
2510 extrastrings = []
2574 while i < len(extras):
2511 while i < len(extras):
2575 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2512 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2576 i += 2
2513 i += 2
2577
2514
2578 ui.write(('file extras: %s (%s)\n')
2515 ui.write(('file extras: %s (%s)\n')
2579 % (filename, ', '.join(extrastrings)))
2516 % (filename, ', '.join(extrastrings)))
2580 elif rtype == 'l':
2517 elif rtype == 'l':
2581 labels = record.split('\0', 2)
2518 labels = record.split('\0', 2)
2582 labels = [l for l in labels if len(l) > 0]
2519 labels = [l for l in labels if len(l) > 0]
2583 ui.write(('labels:\n'))
2520 ui.write(('labels:\n'))
2584 ui.write((' local: %s\n' % labels[0]))
2521 ui.write((' local: %s\n' % labels[0]))
2585 ui.write((' other: %s\n' % labels[1]))
2522 ui.write((' other: %s\n' % labels[1]))
2586 if len(labels) > 2:
2523 if len(labels) > 2:
2587 ui.write((' base: %s\n' % labels[2]))
2524 ui.write((' base: %s\n' % labels[2]))
2588 else:
2525 else:
2589 ui.write(('unrecognized entry: %s\t%s\n')
2526 ui.write(('unrecognized entry: %s\t%s\n')
2590 % (rtype, record.replace('\0', '\t')))
2527 % (rtype, record.replace('\0', '\t')))
2591
2528
2592 # Avoid mergestate.read() since it may raise an exception for unsupported
2529 # Avoid mergestate.read() since it may raise an exception for unsupported
2593 # merge state records. We shouldn't be doing this, but this is OK since this
2530 # merge state records. We shouldn't be doing this, but this is OK since this
2594 # command is pretty low-level.
2531 # command is pretty low-level.
2595 ms = mergemod.mergestate(repo)
2532 ms = mergemod.mergestate(repo)
2596
2533
2597 # sort so that reasonable information is on top
2534 # sort so that reasonable information is on top
2598 v1records = ms._readrecordsv1()
2535 v1records = ms._readrecordsv1()
2599 v2records = ms._readrecordsv2()
2536 v2records = ms._readrecordsv2()
2600 order = 'LOml'
2537 order = 'LOml'
2601 def key(r):
2538 def key(r):
2602 idx = order.find(r[0])
2539 idx = order.find(r[0])
2603 if idx == -1:
2540 if idx == -1:
2604 return (1, r[1])
2541 return (1, r[1])
2605 else:
2542 else:
2606 return (0, idx)
2543 return (0, idx)
2607 v1records.sort(key=key)
2544 v1records.sort(key=key)
2608 v2records.sort(key=key)
2545 v2records.sort(key=key)
2609
2546
2610 if not v1records and not v2records:
2547 if not v1records and not v2records:
2611 ui.write(('no merge state found\n'))
2548 ui.write(('no merge state found\n'))
2612 elif not v2records:
2549 elif not v2records:
2613 ui.note(('no version 2 merge state\n'))
2550 ui.note(('no version 2 merge state\n'))
2614 printrecords(1)
2551 printrecords(1)
2615 elif ms._v1v2match(v1records, v2records):
2552 elif ms._v1v2match(v1records, v2records):
2616 ui.note(('v1 and v2 states match: using v2\n'))
2553 ui.note(('v1 and v2 states match: using v2\n'))
2617 printrecords(2)
2554 printrecords(2)
2618 else:
2555 else:
2619 ui.note(('v1 and v2 states mismatch: using v1\n'))
2556 ui.note(('v1 and v2 states mismatch: using v1\n'))
2620 printrecords(1)
2557 printrecords(1)
2621 if ui.verbose:
2558 if ui.verbose:
2622 printrecords(2)
2559 printrecords(2)
2623
2560
2624 @command('debugnamecomplete', [], _('NAME...'))
2561 @command('debugnamecomplete', [], _('NAME...'))
2625 def debugnamecomplete(ui, repo, *args):
2562 def debugnamecomplete(ui, repo, *args):
2626 '''complete "names" - tags, open branch names, bookmark names'''
2563 '''complete "names" - tags, open branch names, bookmark names'''
2627
2564
2628 names = set()
2565 names = set()
2629 # since we previously only listed open branches, we will handle that
2566 # since we previously only listed open branches, we will handle that
2630 # specially (after this for loop)
2567 # specially (after this for loop)
2631 for name, ns in repo.names.iteritems():
2568 for name, ns in repo.names.iteritems():
2632 if name != 'branches':
2569 if name != 'branches':
2633 names.update(ns.listnames(repo))
2570 names.update(ns.listnames(repo))
2634 names.update(tag for (tag, heads, tip, closed)
2571 names.update(tag for (tag, heads, tip, closed)
2635 in repo.branchmap().iterbranches() if not closed)
2572 in repo.branchmap().iterbranches() if not closed)
2636 completions = set()
2573 completions = set()
2637 if not args:
2574 if not args:
2638 args = ['']
2575 args = ['']
2639 for a in args:
2576 for a in args:
2640 completions.update(n for n in names if n.startswith(a))
2577 completions.update(n for n in names if n.startswith(a))
2641 ui.write('\n'.join(sorted(completions)))
2578 ui.write('\n'.join(sorted(completions)))
2642 ui.write('\n')
2579 ui.write('\n')
2643
2580
2644 @command('debuglocks',
2581 @command('debuglocks',
2645 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2582 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2646 ('W', 'force-wlock', None,
2583 ('W', 'force-wlock', None,
2647 _('free the working state lock (DANGEROUS)'))],
2584 _('free the working state lock (DANGEROUS)'))],
2648 _('[OPTION]...'))
2585 _('[OPTION]...'))
2649 def debuglocks(ui, repo, **opts):
2586 def debuglocks(ui, repo, **opts):
2650 """show or modify state of locks
2587 """show or modify state of locks
2651
2588
2652 By default, this command will show which locks are held. This
2589 By default, this command will show which locks are held. This
2653 includes the user and process holding the lock, the amount of time
2590 includes the user and process holding the lock, the amount of time
2654 the lock has been held, and the machine name where the process is
2591 the lock has been held, and the machine name where the process is
2655 running if it's not local.
2592 running if it's not local.
2656
2593
2657 Locks protect the integrity of Mercurial's data, so should be
2594 Locks protect the integrity of Mercurial's data, so should be
2658 treated with care. System crashes or other interruptions may cause
2595 treated with care. System crashes or other interruptions may cause
2659 locks to not be properly released, though Mercurial will usually
2596 locks to not be properly released, though Mercurial will usually
2660 detect and remove such stale locks automatically.
2597 detect and remove such stale locks automatically.
2661
2598
2662 However, detecting stale locks may not always be possible (for
2599 However, detecting stale locks may not always be possible (for
2663 instance, on a shared filesystem). Removing locks may also be
2600 instance, on a shared filesystem). Removing locks may also be
2664 blocked by filesystem permissions.
2601 blocked by filesystem permissions.
2665
2602
2666 Returns 0 if no locks are held.
2603 Returns 0 if no locks are held.
2667
2604
2668 """
2605 """
2669
2606
2670 if opts.get('force_lock'):
2607 if opts.get('force_lock'):
2671 repo.svfs.unlink('lock')
2608 repo.svfs.unlink('lock')
2672 if opts.get('force_wlock'):
2609 if opts.get('force_wlock'):
2673 repo.vfs.unlink('wlock')
2610 repo.vfs.unlink('wlock')
2674 if opts.get('force_lock') or opts.get('force_lock'):
2611 if opts.get('force_lock') or opts.get('force_lock'):
2675 return 0
2612 return 0
2676
2613
2677 now = time.time()
2614 now = time.time()
2678 held = 0
2615 held = 0
2679
2616
2680 def report(vfs, name, method):
2617 def report(vfs, name, method):
2681 # this causes stale locks to get reaped for more accurate reporting
2618 # this causes stale locks to get reaped for more accurate reporting
2682 try:
2619 try:
2683 l = method(False)
2620 l = method(False)
2684 except error.LockHeld:
2621 except error.LockHeld:
2685 l = None
2622 l = None
2686
2623
2687 if l:
2624 if l:
2688 l.release()
2625 l.release()
2689 else:
2626 else:
2690 try:
2627 try:
2691 stat = vfs.lstat(name)
2628 stat = vfs.lstat(name)
2692 age = now - stat.st_mtime
2629 age = now - stat.st_mtime
2693 user = util.username(stat.st_uid)
2630 user = util.username(stat.st_uid)
2694 locker = vfs.readlock(name)
2631 locker = vfs.readlock(name)
2695 if ":" in locker:
2632 if ":" in locker:
2696 host, pid = locker.split(':')
2633 host, pid = locker.split(':')
2697 if host == socket.gethostname():
2634 if host == socket.gethostname():
2698 locker = 'user %s, process %s' % (user, pid)
2635 locker = 'user %s, process %s' % (user, pid)
2699 else:
2636 else:
2700 locker = 'user %s, process %s, host %s' \
2637 locker = 'user %s, process %s, host %s' \
2701 % (user, pid, host)
2638 % (user, pid, host)
2702 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2639 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2703 return 1
2640 return 1
2704 except OSError as e:
2641 except OSError as e:
2705 if e.errno != errno.ENOENT:
2642 if e.errno != errno.ENOENT:
2706 raise
2643 raise
2707
2644
2708 ui.write(("%-6s free\n") % (name + ":"))
2645 ui.write(("%-6s free\n") % (name + ":"))
2709 return 0
2646 return 0
2710
2647
2711 held += report(repo.svfs, "lock", repo.lock)
2648 held += report(repo.svfs, "lock", repo.lock)
2712 held += report(repo.vfs, "wlock", repo.wlock)
2649 held += report(repo.vfs, "wlock", repo.wlock)
2713
2650
2714 return held
2651 return held
2715
2652
2716 @command('debugobsolete',
2653 @command('debugobsolete',
2717 [('', 'flags', 0, _('markers flag')),
2654 [('', 'flags', 0, _('markers flag')),
2718 ('', 'record-parents', False,
2655 ('', 'record-parents', False,
2719 _('record parent information for the precursor')),
2656 _('record parent information for the precursor')),
2720 ('r', 'rev', [], _('display markers relevant to REV')),
2657 ('r', 'rev', [], _('display markers relevant to REV')),
2721 ('', 'index', False, _('display index of the marker')),
2658 ('', 'index', False, _('display index of the marker')),
2722 ('', 'delete', [], _('delete markers specified by indices')),
2659 ('', 'delete', [], _('delete markers specified by indices')),
2723 ] + commitopts2 + formatteropts,
2660 ] + commitopts2 + formatteropts,
2724 _('[OBSOLETED [REPLACEMENT ...]]'))
2661 _('[OBSOLETED [REPLACEMENT ...]]'))
2725 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2662 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2726 """create arbitrary obsolete marker
2663 """create arbitrary obsolete marker
2727
2664
2728 With no arguments, displays the list of obsolescence markers."""
2665 With no arguments, displays the list of obsolescence markers."""
2729
2666
2730 def parsenodeid(s):
2667 def parsenodeid(s):
2731 try:
2668 try:
2732 # We do not use revsingle/revrange functions here to accept
2669 # We do not use revsingle/revrange functions here to accept
2733 # arbitrary node identifiers, possibly not present in the
2670 # arbitrary node identifiers, possibly not present in the
2734 # local repository.
2671 # local repository.
2735 n = bin(s)
2672 n = bin(s)
2736 if len(n) != len(nullid):
2673 if len(n) != len(nullid):
2737 raise TypeError()
2674 raise TypeError()
2738 return n
2675 return n
2739 except TypeError:
2676 except TypeError:
2740 raise error.Abort('changeset references must be full hexadecimal '
2677 raise error.Abort('changeset references must be full hexadecimal '
2741 'node identifiers')
2678 'node identifiers')
2742
2679
2743 if opts.get('delete'):
2680 if opts.get('delete'):
2744 indices = []
2681 indices = []
2745 for v in opts.get('delete'):
2682 for v in opts.get('delete'):
2746 try:
2683 try:
2747 indices.append(int(v))
2684 indices.append(int(v))
2748 except ValueError:
2685 except ValueError:
2749 raise error.Abort(_('invalid index value: %r') % v,
2686 raise error.Abort(_('invalid index value: %r') % v,
2750 hint=_('use integers for indices'))
2687 hint=_('use integers for indices'))
2751
2688
2752 if repo.currenttransaction():
2689 if repo.currenttransaction():
2753 raise error.Abort(_('cannot delete obsmarkers in the middle '
2690 raise error.Abort(_('cannot delete obsmarkers in the middle '
2754 'of transaction.'))
2691 'of transaction.'))
2755
2692
2756 with repo.lock():
2693 with repo.lock():
2757 n = repair.deleteobsmarkers(repo.obsstore, indices)
2694 n = repair.deleteobsmarkers(repo.obsstore, indices)
2758 ui.write(_('deleted %i obsolescence markers\n') % n)
2695 ui.write(_('deleted %i obsolescence markers\n') % n)
2759
2696
2760 return
2697 return
2761
2698
2762 if precursor is not None:
2699 if precursor is not None:
2763 if opts['rev']:
2700 if opts['rev']:
2764 raise error.Abort('cannot select revision when creating marker')
2701 raise error.Abort('cannot select revision when creating marker')
2765 metadata = {}
2702 metadata = {}
2766 metadata['user'] = opts['user'] or ui.username()
2703 metadata['user'] = opts['user'] or ui.username()
2767 succs = tuple(parsenodeid(succ) for succ in successors)
2704 succs = tuple(parsenodeid(succ) for succ in successors)
2768 l = repo.lock()
2705 l = repo.lock()
2769 try:
2706 try:
2770 tr = repo.transaction('debugobsolete')
2707 tr = repo.transaction('debugobsolete')
2771 try:
2708 try:
2772 date = opts.get('date')
2709 date = opts.get('date')
2773 if date:
2710 if date:
2774 date = util.parsedate(date)
2711 date = util.parsedate(date)
2775 else:
2712 else:
2776 date = None
2713 date = None
2777 prec = parsenodeid(precursor)
2714 prec = parsenodeid(precursor)
2778 parents = None
2715 parents = None
2779 if opts['record_parents']:
2716 if opts['record_parents']:
2780 if prec not in repo.unfiltered():
2717 if prec not in repo.unfiltered():
2781 raise error.Abort('cannot used --record-parents on '
2718 raise error.Abort('cannot used --record-parents on '
2782 'unknown changesets')
2719 'unknown changesets')
2783 parents = repo.unfiltered()[prec].parents()
2720 parents = repo.unfiltered()[prec].parents()
2784 parents = tuple(p.node() for p in parents)
2721 parents = tuple(p.node() for p in parents)
2785 repo.obsstore.create(tr, prec, succs, opts['flags'],
2722 repo.obsstore.create(tr, prec, succs, opts['flags'],
2786 parents=parents, date=date,
2723 parents=parents, date=date,
2787 metadata=metadata)
2724 metadata=metadata)
2788 tr.close()
2725 tr.close()
2789 except ValueError as exc:
2726 except ValueError as exc:
2790 raise error.Abort(_('bad obsmarker input: %s') % exc)
2727 raise error.Abort(_('bad obsmarker input: %s') % exc)
2791 finally:
2728 finally:
2792 tr.release()
2729 tr.release()
2793 finally:
2730 finally:
2794 l.release()
2731 l.release()
2795 else:
2732 else:
2796 if opts['rev']:
2733 if opts['rev']:
2797 revs = scmutil.revrange(repo, opts['rev'])
2734 revs = scmutil.revrange(repo, opts['rev'])
2798 nodes = [repo[r].node() for r in revs]
2735 nodes = [repo[r].node() for r in revs]
2799 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2736 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2800 markers.sort(key=lambda x: x._data)
2737 markers.sort(key=lambda x: x._data)
2801 else:
2738 else:
2802 markers = obsolete.getmarkers(repo)
2739 markers = obsolete.getmarkers(repo)
2803
2740
2804 markerstoiter = markers
2741 markerstoiter = markers
2805 isrelevant = lambda m: True
2742 isrelevant = lambda m: True
2806 if opts.get('rev') and opts.get('index'):
2743 if opts.get('rev') and opts.get('index'):
2807 markerstoiter = obsolete.getmarkers(repo)
2744 markerstoiter = obsolete.getmarkers(repo)
2808 markerset = set(markers)
2745 markerset = set(markers)
2809 isrelevant = lambda m: m in markerset
2746 isrelevant = lambda m: m in markerset
2810
2747
2811 fm = ui.formatter('debugobsolete', opts)
2748 fm = ui.formatter('debugobsolete', opts)
2812 for i, m in enumerate(markerstoiter):
2749 for i, m in enumerate(markerstoiter):
2813 if not isrelevant(m):
2750 if not isrelevant(m):
2814 # marker can be irrelevant when we're iterating over a set
2751 # marker can be irrelevant when we're iterating over a set
2815 # of markers (markerstoiter) which is bigger than the set
2752 # of markers (markerstoiter) which is bigger than the set
2816 # of markers we want to display (markers)
2753 # of markers we want to display (markers)
2817 # this can happen if both --index and --rev options are
2754 # this can happen if both --index and --rev options are
2818 # provided and thus we need to iterate over all of the markers
2755 # provided and thus we need to iterate over all of the markers
2819 # to get the correct indices, but only display the ones that
2756 # to get the correct indices, but only display the ones that
2820 # are relevant to --rev value
2757 # are relevant to --rev value
2821 continue
2758 continue
2822 fm.startitem()
2759 fm.startitem()
2823 ind = i if opts.get('index') else None
2760 ind = i if opts.get('index') else None
2824 cmdutil.showmarker(fm, m, index=ind)
2761 cmdutil.showmarker(fm, m, index=ind)
2825 fm.end()
2762 fm.end()
2826
2763
2827 @command('debugpathcomplete',
2764 @command('debugpathcomplete',
2828 [('f', 'full', None, _('complete an entire path')),
2765 [('f', 'full', None, _('complete an entire path')),
2829 ('n', 'normal', None, _('show only normal files')),
2766 ('n', 'normal', None, _('show only normal files')),
2830 ('a', 'added', None, _('show only added files')),
2767 ('a', 'added', None, _('show only added files')),
2831 ('r', 'removed', None, _('show only removed files'))],
2768 ('r', 'removed', None, _('show only removed files'))],
2832 _('FILESPEC...'))
2769 _('FILESPEC...'))
2833 def debugpathcomplete(ui, repo, *specs, **opts):
2770 def debugpathcomplete(ui, repo, *specs, **opts):
2834 '''complete part or all of a tracked path
2771 '''complete part or all of a tracked path
2835
2772
2836 This command supports shells that offer path name completion. It
2773 This command supports shells that offer path name completion. It
2837 currently completes only files already known to the dirstate.
2774 currently completes only files already known to the dirstate.
2838
2775
2839 Completion extends only to the next path segment unless
2776 Completion extends only to the next path segment unless
2840 --full is specified, in which case entire paths are used.'''
2777 --full is specified, in which case entire paths are used.'''
2841
2778
2842 def complete(path, acceptable):
2779 def complete(path, acceptable):
2843 dirstate = repo.dirstate
2780 dirstate = repo.dirstate
2844 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2781 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2845 rootdir = repo.root + os.sep
2782 rootdir = repo.root + os.sep
2846 if spec != repo.root and not spec.startswith(rootdir):
2783 if spec != repo.root and not spec.startswith(rootdir):
2847 return [], []
2784 return [], []
2848 if os.path.isdir(spec):
2785 if os.path.isdir(spec):
2849 spec += '/'
2786 spec += '/'
2850 spec = spec[len(rootdir):]
2787 spec = spec[len(rootdir):]
2851 fixpaths = pycompat.ossep != '/'
2788 fixpaths = pycompat.ossep != '/'
2852 if fixpaths:
2789 if fixpaths:
2853 spec = spec.replace(os.sep, '/')
2790 spec = spec.replace(os.sep, '/')
2854 speclen = len(spec)
2791 speclen = len(spec)
2855 fullpaths = opts['full']
2792 fullpaths = opts['full']
2856 files, dirs = set(), set()
2793 files, dirs = set(), set()
2857 adddir, addfile = dirs.add, files.add
2794 adddir, addfile = dirs.add, files.add
2858 for f, st in dirstate.iteritems():
2795 for f, st in dirstate.iteritems():
2859 if f.startswith(spec) and st[0] in acceptable:
2796 if f.startswith(spec) and st[0] in acceptable:
2860 if fixpaths:
2797 if fixpaths:
2861 f = f.replace('/', os.sep)
2798 f = f.replace('/', os.sep)
2862 if fullpaths:
2799 if fullpaths:
2863 addfile(f)
2800 addfile(f)
2864 continue
2801 continue
2865 s = f.find(os.sep, speclen)
2802 s = f.find(os.sep, speclen)
2866 if s >= 0:
2803 if s >= 0:
2867 adddir(f[:s])
2804 adddir(f[:s])
2868 else:
2805 else:
2869 addfile(f)
2806 addfile(f)
2870 return files, dirs
2807 return files, dirs
2871
2808
2872 acceptable = ''
2809 acceptable = ''
2873 if opts['normal']:
2810 if opts['normal']:
2874 acceptable += 'nm'
2811 acceptable += 'nm'
2875 if opts['added']:
2812 if opts['added']:
2876 acceptable += 'a'
2813 acceptable += 'a'
2877 if opts['removed']:
2814 if opts['removed']:
2878 acceptable += 'r'
2815 acceptable += 'r'
2879 cwd = repo.getcwd()
2816 cwd = repo.getcwd()
2880 if not specs:
2817 if not specs:
2881 specs = ['.']
2818 specs = ['.']
2882
2819
2883 files, dirs = set(), set()
2820 files, dirs = set(), set()
2884 for spec in specs:
2821 for spec in specs:
2885 f, d = complete(spec, acceptable or 'nmar')
2822 f, d = complete(spec, acceptable or 'nmar')
2886 files.update(f)
2823 files.update(f)
2887 dirs.update(d)
2824 dirs.update(d)
2888 files.update(dirs)
2825 files.update(dirs)
2889 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2826 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2890 ui.write('\n')
2827 ui.write('\n')
2891
2828
2892 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2829 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2893 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2830 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2894 '''access the pushkey key/value protocol
2831 '''access the pushkey key/value protocol
2895
2832
2896 With two args, list the keys in the given namespace.
2833 With two args, list the keys in the given namespace.
2897
2834
2898 With five args, set a key to new if it currently is set to old.
2835 With five args, set a key to new if it currently is set to old.
2899 Reports success or failure.
2836 Reports success or failure.
2900 '''
2837 '''
2901
2838
2902 target = hg.peer(ui, {}, repopath)
2839 target = hg.peer(ui, {}, repopath)
2903 if keyinfo:
2840 if keyinfo:
2904 key, old, new = keyinfo
2841 key, old, new = keyinfo
2905 r = target.pushkey(namespace, key, old, new)
2842 r = target.pushkey(namespace, key, old, new)
2906 ui.status(str(r) + '\n')
2843 ui.status(str(r) + '\n')
2907 return not r
2844 return not r
2908 else:
2845 else:
2909 for k, v in sorted(target.listkeys(namespace).iteritems()):
2846 for k, v in sorted(target.listkeys(namespace).iteritems()):
2910 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2847 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2911 v.encode('string-escape')))
2848 v.encode('string-escape')))
2912
2849
2913 @command('debugpvec', [], _('A B'))
2850 @command('debugpvec', [], _('A B'))
2914 def debugpvec(ui, repo, a, b=None):
2851 def debugpvec(ui, repo, a, b=None):
2915 ca = scmutil.revsingle(repo, a)
2852 ca = scmutil.revsingle(repo, a)
2916 cb = scmutil.revsingle(repo, b)
2853 cb = scmutil.revsingle(repo, b)
2917 pa = pvec.ctxpvec(ca)
2854 pa = pvec.ctxpvec(ca)
2918 pb = pvec.ctxpvec(cb)
2855 pb = pvec.ctxpvec(cb)
2919 if pa == pb:
2856 if pa == pb:
2920 rel = "="
2857 rel = "="
2921 elif pa > pb:
2858 elif pa > pb:
2922 rel = ">"
2859 rel = ">"
2923 elif pa < pb:
2860 elif pa < pb:
2924 rel = "<"
2861 rel = "<"
2925 elif pa | pb:
2862 elif pa | pb:
2926 rel = "|"
2863 rel = "|"
2927 ui.write(_("a: %s\n") % pa)
2864 ui.write(_("a: %s\n") % pa)
2928 ui.write(_("b: %s\n") % pb)
2865 ui.write(_("b: %s\n") % pb)
2929 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2866 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2930 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2867 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2931 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2868 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2932 pa.distance(pb), rel))
2869 pa.distance(pb), rel))
2933
2870
2934 @command('debugrebuilddirstate|debugrebuildstate',
2871 @command('debugrebuilddirstate|debugrebuildstate',
2935 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2872 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2936 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2873 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2937 'the working copy parent')),
2874 'the working copy parent')),
2938 ],
2875 ],
2939 _('[-r REV]'))
2876 _('[-r REV]'))
2940 def debugrebuilddirstate(ui, repo, rev, **opts):
2877 def debugrebuilddirstate(ui, repo, rev, **opts):
2941 """rebuild the dirstate as it would look like for the given revision
2878 """rebuild the dirstate as it would look like for the given revision
2942
2879
2943 If no revision is specified the first current parent will be used.
2880 If no revision is specified the first current parent will be used.
2944
2881
2945 The dirstate will be set to the files of the given revision.
2882 The dirstate will be set to the files of the given revision.
2946 The actual working directory content or existing dirstate
2883 The actual working directory content or existing dirstate
2947 information such as adds or removes is not considered.
2884 information such as adds or removes is not considered.
2948
2885
2949 ``minimal`` will only rebuild the dirstate status for files that claim to be
2886 ``minimal`` will only rebuild the dirstate status for files that claim to be
2950 tracked but are not in the parent manifest, or that exist in the parent
2887 tracked but are not in the parent manifest, or that exist in the parent
2951 manifest but are not in the dirstate. It will not change adds, removes, or
2888 manifest but are not in the dirstate. It will not change adds, removes, or
2952 modified files that are in the working copy parent.
2889 modified files that are in the working copy parent.
2953
2890
2954 One use of this command is to make the next :hg:`status` invocation
2891 One use of this command is to make the next :hg:`status` invocation
2955 check the actual file content.
2892 check the actual file content.
2956 """
2893 """
2957 ctx = scmutil.revsingle(repo, rev)
2894 ctx = scmutil.revsingle(repo, rev)
2958 with repo.wlock():
2895 with repo.wlock():
2959 dirstate = repo.dirstate
2896 dirstate = repo.dirstate
2960 changedfiles = None
2897 changedfiles = None
2961 # See command doc for what minimal does.
2898 # See command doc for what minimal does.
2962 if opts.get('minimal'):
2899 if opts.get('minimal'):
2963 manifestfiles = set(ctx.manifest().keys())
2900 manifestfiles = set(ctx.manifest().keys())
2964 dirstatefiles = set(dirstate)
2901 dirstatefiles = set(dirstate)
2965 manifestonly = manifestfiles - dirstatefiles
2902 manifestonly = manifestfiles - dirstatefiles
2966 dsonly = dirstatefiles - manifestfiles
2903 dsonly = dirstatefiles - manifestfiles
2967 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2904 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2968 changedfiles = manifestonly | dsnotadded
2905 changedfiles = manifestonly | dsnotadded
2969
2906
2970 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2907 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2971
2908
2972 @command('debugrebuildfncache', [], '')
2909 @command('debugrebuildfncache', [], '')
2973 def debugrebuildfncache(ui, repo):
2910 def debugrebuildfncache(ui, repo):
2974 """rebuild the fncache file"""
2911 """rebuild the fncache file"""
2975 repair.rebuildfncache(ui, repo)
2912 repair.rebuildfncache(ui, repo)
2976
2913
2977 @command('debugrename',
2914 @command('debugrename',
2978 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2915 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2979 _('[-r REV] FILE'))
2916 _('[-r REV] FILE'))
2980 def debugrename(ui, repo, file1, *pats, **opts):
2917 def debugrename(ui, repo, file1, *pats, **opts):
2981 """dump rename information"""
2918 """dump rename information"""
2982
2919
2983 ctx = scmutil.revsingle(repo, opts.get('rev'))
2920 ctx = scmutil.revsingle(repo, opts.get('rev'))
2984 m = scmutil.match(ctx, (file1,) + pats, opts)
2921 m = scmutil.match(ctx, (file1,) + pats, opts)
2985 for abs in ctx.walk(m):
2922 for abs in ctx.walk(m):
2986 fctx = ctx[abs]
2923 fctx = ctx[abs]
2987 o = fctx.filelog().renamed(fctx.filenode())
2924 o = fctx.filelog().renamed(fctx.filenode())
2988 rel = m.rel(abs)
2925 rel = m.rel(abs)
2989 if o:
2926 if o:
2990 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2927 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2991 else:
2928 else:
2992 ui.write(_("%s not renamed\n") % rel)
2929 ui.write(_("%s not renamed\n") % rel)
2993
2930
2994 @command('debugrevlog', debugrevlogopts +
2931 @command('debugrevlog', debugrevlogopts +
2995 [('d', 'dump', False, _('dump index data'))],
2932 [('d', 'dump', False, _('dump index data'))],
2996 _('-c|-m|FILE'),
2933 _('-c|-m|FILE'),
2997 optionalrepo=True)
2934 optionalrepo=True)
2998 def debugrevlog(ui, repo, file_=None, **opts):
2935 def debugrevlog(ui, repo, file_=None, **opts):
2999 """show data and statistics about a revlog"""
2936 """show data and statistics about a revlog"""
3000 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2937 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3001
2938
3002 if opts.get("dump"):
2939 if opts.get("dump"):
3003 numrevs = len(r)
2940 numrevs = len(r)
3004 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2941 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
3005 " rawsize totalsize compression heads chainlen\n"))
2942 " rawsize totalsize compression heads chainlen\n"))
3006 ts = 0
2943 ts = 0
3007 heads = set()
2944 heads = set()
3008
2945
3009 for rev in xrange(numrevs):
2946 for rev in xrange(numrevs):
3010 dbase = r.deltaparent(rev)
2947 dbase = r.deltaparent(rev)
3011 if dbase == -1:
2948 if dbase == -1:
3012 dbase = rev
2949 dbase = rev
3013 cbase = r.chainbase(rev)
2950 cbase = r.chainbase(rev)
3014 clen = r.chainlen(rev)
2951 clen = r.chainlen(rev)
3015 p1, p2 = r.parentrevs(rev)
2952 p1, p2 = r.parentrevs(rev)
3016 rs = r.rawsize(rev)
2953 rs = r.rawsize(rev)
3017 ts = ts + rs
2954 ts = ts + rs
3018 heads -= set(r.parentrevs(rev))
2955 heads -= set(r.parentrevs(rev))
3019 heads.add(rev)
2956 heads.add(rev)
3020 try:
2957 try:
3021 compression = ts / r.end(rev)
2958 compression = ts / r.end(rev)
3022 except ZeroDivisionError:
2959 except ZeroDivisionError:
3023 compression = 0
2960 compression = 0
3024 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2961 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3025 "%11d %5d %8d\n" %
2962 "%11d %5d %8d\n" %
3026 (rev, p1, p2, r.start(rev), r.end(rev),
2963 (rev, p1, p2, r.start(rev), r.end(rev),
3027 r.start(dbase), r.start(cbase),
2964 r.start(dbase), r.start(cbase),
3028 r.start(p1), r.start(p2),
2965 r.start(p1), r.start(p2),
3029 rs, ts, compression, len(heads), clen))
2966 rs, ts, compression, len(heads), clen))
3030 return 0
2967 return 0
3031
2968
3032 v = r.version
2969 v = r.version
3033 format = v & 0xFFFF
2970 format = v & 0xFFFF
3034 flags = []
2971 flags = []
3035 gdelta = False
2972 gdelta = False
3036 if v & revlog.REVLOGNGINLINEDATA:
2973 if v & revlog.REVLOGNGINLINEDATA:
3037 flags.append('inline')
2974 flags.append('inline')
3038 if v & revlog.REVLOGGENERALDELTA:
2975 if v & revlog.REVLOGGENERALDELTA:
3039 gdelta = True
2976 gdelta = True
3040 flags.append('generaldelta')
2977 flags.append('generaldelta')
3041 if not flags:
2978 if not flags:
3042 flags = ['(none)']
2979 flags = ['(none)']
3043
2980
3044 nummerges = 0
2981 nummerges = 0
3045 numfull = 0
2982 numfull = 0
3046 numprev = 0
2983 numprev = 0
3047 nump1 = 0
2984 nump1 = 0
3048 nump2 = 0
2985 nump2 = 0
3049 numother = 0
2986 numother = 0
3050 nump1prev = 0
2987 nump1prev = 0
3051 nump2prev = 0
2988 nump2prev = 0
3052 chainlengths = []
2989 chainlengths = []
3053
2990
3054 datasize = [None, 0, 0]
2991 datasize = [None, 0, 0]
3055 fullsize = [None, 0, 0]
2992 fullsize = [None, 0, 0]
3056 deltasize = [None, 0, 0]
2993 deltasize = [None, 0, 0]
3057 chunktypecounts = {}
2994 chunktypecounts = {}
3058 chunktypesizes = {}
2995 chunktypesizes = {}
3059
2996
3060 def addsize(size, l):
2997 def addsize(size, l):
3061 if l[0] is None or size < l[0]:
2998 if l[0] is None or size < l[0]:
3062 l[0] = size
2999 l[0] = size
3063 if size > l[1]:
3000 if size > l[1]:
3064 l[1] = size
3001 l[1] = size
3065 l[2] += size
3002 l[2] += size
3066
3003
3067 numrevs = len(r)
3004 numrevs = len(r)
3068 for rev in xrange(numrevs):
3005 for rev in xrange(numrevs):
3069 p1, p2 = r.parentrevs(rev)
3006 p1, p2 = r.parentrevs(rev)
3070 delta = r.deltaparent(rev)
3007 delta = r.deltaparent(rev)
3071 if format > 0:
3008 if format > 0:
3072 addsize(r.rawsize(rev), datasize)
3009 addsize(r.rawsize(rev), datasize)
3073 if p2 != nullrev:
3010 if p2 != nullrev:
3074 nummerges += 1
3011 nummerges += 1
3075 size = r.length(rev)
3012 size = r.length(rev)
3076 if delta == nullrev:
3013 if delta == nullrev:
3077 chainlengths.append(0)
3014 chainlengths.append(0)
3078 numfull += 1
3015 numfull += 1
3079 addsize(size, fullsize)
3016 addsize(size, fullsize)
3080 else:
3017 else:
3081 chainlengths.append(chainlengths[delta] + 1)
3018 chainlengths.append(chainlengths[delta] + 1)
3082 addsize(size, deltasize)
3019 addsize(size, deltasize)
3083 if delta == rev - 1:
3020 if delta == rev - 1:
3084 numprev += 1
3021 numprev += 1
3085 if delta == p1:
3022 if delta == p1:
3086 nump1prev += 1
3023 nump1prev += 1
3087 elif delta == p2:
3024 elif delta == p2:
3088 nump2prev += 1
3025 nump2prev += 1
3089 elif delta == p1:
3026 elif delta == p1:
3090 nump1 += 1
3027 nump1 += 1
3091 elif delta == p2:
3028 elif delta == p2:
3092 nump2 += 1
3029 nump2 += 1
3093 elif delta != nullrev:
3030 elif delta != nullrev:
3094 numother += 1
3031 numother += 1
3095
3032
3096 # Obtain data on the raw chunks in the revlog.
3033 # Obtain data on the raw chunks in the revlog.
3097 chunk = r._chunkraw(rev, rev)[1]
3034 chunk = r._chunkraw(rev, rev)[1]
3098 if chunk:
3035 if chunk:
3099 chunktype = chunk[0]
3036 chunktype = chunk[0]
3100 else:
3037 else:
3101 chunktype = 'empty'
3038 chunktype = 'empty'
3102
3039
3103 if chunktype not in chunktypecounts:
3040 if chunktype not in chunktypecounts:
3104 chunktypecounts[chunktype] = 0
3041 chunktypecounts[chunktype] = 0
3105 chunktypesizes[chunktype] = 0
3042 chunktypesizes[chunktype] = 0
3106
3043
3107 chunktypecounts[chunktype] += 1
3044 chunktypecounts[chunktype] += 1
3108 chunktypesizes[chunktype] += size
3045 chunktypesizes[chunktype] += size
3109
3046
3110 # Adjust size min value for empty cases
3047 # Adjust size min value for empty cases
3111 for size in (datasize, fullsize, deltasize):
3048 for size in (datasize, fullsize, deltasize):
3112 if size[0] is None:
3049 if size[0] is None:
3113 size[0] = 0
3050 size[0] = 0
3114
3051
3115 numdeltas = numrevs - numfull
3052 numdeltas = numrevs - numfull
3116 numoprev = numprev - nump1prev - nump2prev
3053 numoprev = numprev - nump1prev - nump2prev
3117 totalrawsize = datasize[2]
3054 totalrawsize = datasize[2]
3118 datasize[2] /= numrevs
3055 datasize[2] /= numrevs
3119 fulltotal = fullsize[2]
3056 fulltotal = fullsize[2]
3120 fullsize[2] /= numfull
3057 fullsize[2] /= numfull
3121 deltatotal = deltasize[2]
3058 deltatotal = deltasize[2]
3122 if numrevs - numfull > 0:
3059 if numrevs - numfull > 0:
3123 deltasize[2] /= numrevs - numfull
3060 deltasize[2] /= numrevs - numfull
3124 totalsize = fulltotal + deltatotal
3061 totalsize = fulltotal + deltatotal
3125 avgchainlen = sum(chainlengths) / numrevs
3062 avgchainlen = sum(chainlengths) / numrevs
3126 maxchainlen = max(chainlengths)
3063 maxchainlen = max(chainlengths)
3127 compratio = 1
3064 compratio = 1
3128 if totalsize:
3065 if totalsize:
3129 compratio = totalrawsize / totalsize
3066 compratio = totalrawsize / totalsize
3130
3067
3131 basedfmtstr = '%%%dd\n'
3068 basedfmtstr = '%%%dd\n'
3132 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3069 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3133
3070
3134 def dfmtstr(max):
3071 def dfmtstr(max):
3135 return basedfmtstr % len(str(max))
3072 return basedfmtstr % len(str(max))
3136 def pcfmtstr(max, padding=0):
3073 def pcfmtstr(max, padding=0):
3137 return basepcfmtstr % (len(str(max)), ' ' * padding)
3074 return basepcfmtstr % (len(str(max)), ' ' * padding)
3138
3075
3139 def pcfmt(value, total):
3076 def pcfmt(value, total):
3140 if total:
3077 if total:
3141 return (value, 100 * float(value) / total)
3078 return (value, 100 * float(value) / total)
3142 else:
3079 else:
3143 return value, 100.0
3080 return value, 100.0
3144
3081
3145 ui.write(('format : %d\n') % format)
3082 ui.write(('format : %d\n') % format)
3146 ui.write(('flags : %s\n') % ', '.join(flags))
3083 ui.write(('flags : %s\n') % ', '.join(flags))
3147
3084
3148 ui.write('\n')
3085 ui.write('\n')
3149 fmt = pcfmtstr(totalsize)
3086 fmt = pcfmtstr(totalsize)
3150 fmt2 = dfmtstr(totalsize)
3087 fmt2 = dfmtstr(totalsize)
3151 ui.write(('revisions : ') + fmt2 % numrevs)
3088 ui.write(('revisions : ') + fmt2 % numrevs)
3152 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3089 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3153 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3090 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3154 ui.write(('revisions : ') + fmt2 % numrevs)
3091 ui.write(('revisions : ') + fmt2 % numrevs)
3155 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3092 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3156 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3093 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3157 ui.write(('revision size : ') + fmt2 % totalsize)
3094 ui.write(('revision size : ') + fmt2 % totalsize)
3158 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3095 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3159 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3096 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3160
3097
3161 def fmtchunktype(chunktype):
3098 def fmtchunktype(chunktype):
3162 if chunktype == 'empty':
3099 if chunktype == 'empty':
3163 return ' %s : ' % chunktype
3100 return ' %s : ' % chunktype
3164 elif chunktype in string.ascii_letters:
3101 elif chunktype in string.ascii_letters:
3165 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3102 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3166 else:
3103 else:
3167 return ' 0x%s : ' % hex(chunktype)
3104 return ' 0x%s : ' % hex(chunktype)
3168
3105
3169 ui.write('\n')
3106 ui.write('\n')
3170 ui.write(('chunks : ') + fmt2 % numrevs)
3107 ui.write(('chunks : ') + fmt2 % numrevs)
3171 for chunktype in sorted(chunktypecounts):
3108 for chunktype in sorted(chunktypecounts):
3172 ui.write(fmtchunktype(chunktype))
3109 ui.write(fmtchunktype(chunktype))
3173 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3110 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3174 ui.write(('chunks size : ') + fmt2 % totalsize)
3111 ui.write(('chunks size : ') + fmt2 % totalsize)
3175 for chunktype in sorted(chunktypecounts):
3112 for chunktype in sorted(chunktypecounts):
3176 ui.write(fmtchunktype(chunktype))
3113 ui.write(fmtchunktype(chunktype))
3177 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3114 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3178
3115
3179 ui.write('\n')
3116 ui.write('\n')
3180 fmt = dfmtstr(max(avgchainlen, compratio))
3117 fmt = dfmtstr(max(avgchainlen, compratio))
3181 ui.write(('avg chain length : ') + fmt % avgchainlen)
3118 ui.write(('avg chain length : ') + fmt % avgchainlen)
3182 ui.write(('max chain length : ') + fmt % maxchainlen)
3119 ui.write(('max chain length : ') + fmt % maxchainlen)
3183 ui.write(('compression ratio : ') + fmt % compratio)
3120 ui.write(('compression ratio : ') + fmt % compratio)
3184
3121
3185 if format > 0:
3122 if format > 0:
3186 ui.write('\n')
3123 ui.write('\n')
3187 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3124 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3188 % tuple(datasize))
3125 % tuple(datasize))
3189 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3126 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3190 % tuple(fullsize))
3127 % tuple(fullsize))
3191 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3128 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3192 % tuple(deltasize))
3129 % tuple(deltasize))
3193
3130
3194 if numdeltas > 0:
3131 if numdeltas > 0:
3195 ui.write('\n')
3132 ui.write('\n')
3196 fmt = pcfmtstr(numdeltas)
3133 fmt = pcfmtstr(numdeltas)
3197 fmt2 = pcfmtstr(numdeltas, 4)
3134 fmt2 = pcfmtstr(numdeltas, 4)
3198 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3135 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3199 if numprev > 0:
3136 if numprev > 0:
3200 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3137 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3201 numprev))
3138 numprev))
3202 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3139 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3203 numprev))
3140 numprev))
3204 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3141 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3205 numprev))
3142 numprev))
3206 if gdelta:
3143 if gdelta:
3207 ui.write(('deltas against p1 : ')
3144 ui.write(('deltas against p1 : ')
3208 + fmt % pcfmt(nump1, numdeltas))
3145 + fmt % pcfmt(nump1, numdeltas))
3209 ui.write(('deltas against p2 : ')
3146 ui.write(('deltas against p2 : ')
3210 + fmt % pcfmt(nump2, numdeltas))
3147 + fmt % pcfmt(nump2, numdeltas))
3211 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3148 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3212 numdeltas))
3149 numdeltas))
3213
3150
3214 @command('debugrevspec',
3151 @command('debugrevspec',
3215 [('', 'optimize', None,
3152 [('', 'optimize', None,
3216 _('print parsed tree after optimizing (DEPRECATED)')),
3153 _('print parsed tree after optimizing (DEPRECATED)')),
3217 ('p', 'show-stage', [],
3154 ('p', 'show-stage', [],
3218 _('print parsed tree at the given stage'), _('NAME')),
3155 _('print parsed tree at the given stage'), _('NAME')),
3219 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3156 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3220 ('', 'verify-optimized', False, _('verify optimized result')),
3157 ('', 'verify-optimized', False, _('verify optimized result')),
3221 ],
3158 ],
3222 ('REVSPEC'))
3159 ('REVSPEC'))
3223 def debugrevspec(ui, repo, expr, **opts):
3160 def debugrevspec(ui, repo, expr, **opts):
3224 """parse and apply a revision specification
3161 """parse and apply a revision specification
3225
3162
3226 Use -p/--show-stage option to print the parsed tree at the given stages.
3163 Use -p/--show-stage option to print the parsed tree at the given stages.
3227 Use -p all to print tree at every stage.
3164 Use -p all to print tree at every stage.
3228
3165
3229 Use --verify-optimized to compare the optimized result with the unoptimized
3166 Use --verify-optimized to compare the optimized result with the unoptimized
3230 one. Returns 1 if the optimized result differs.
3167 one. Returns 1 if the optimized result differs.
3231 """
3168 """
3232 stages = [
3169 stages = [
3233 ('parsed', lambda tree: tree),
3170 ('parsed', lambda tree: tree),
3234 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3171 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3235 ('concatenated', revset.foldconcat),
3172 ('concatenated', revset.foldconcat),
3236 ('analyzed', revset.analyze),
3173 ('analyzed', revset.analyze),
3237 ('optimized', revset.optimize),
3174 ('optimized', revset.optimize),
3238 ]
3175 ]
3239 if opts['no_optimized']:
3176 if opts['no_optimized']:
3240 stages = stages[:-1]
3177 stages = stages[:-1]
3241 if opts['verify_optimized'] and opts['no_optimized']:
3178 if opts['verify_optimized'] and opts['no_optimized']:
3242 raise error.Abort(_('cannot use --verify-optimized with '
3179 raise error.Abort(_('cannot use --verify-optimized with '
3243 '--no-optimized'))
3180 '--no-optimized'))
3244 stagenames = set(n for n, f in stages)
3181 stagenames = set(n for n, f in stages)
3245
3182
3246 showalways = set()
3183 showalways = set()
3247 showchanged = set()
3184 showchanged = set()
3248 if ui.verbose and not opts['show_stage']:
3185 if ui.verbose and not opts['show_stage']:
3249 # show parsed tree by --verbose (deprecated)
3186 # show parsed tree by --verbose (deprecated)
3250 showalways.add('parsed')
3187 showalways.add('parsed')
3251 showchanged.update(['expanded', 'concatenated'])
3188 showchanged.update(['expanded', 'concatenated'])
3252 if opts['optimize']:
3189 if opts['optimize']:
3253 showalways.add('optimized')
3190 showalways.add('optimized')
3254 if opts['show_stage'] and opts['optimize']:
3191 if opts['show_stage'] and opts['optimize']:
3255 raise error.Abort(_('cannot use --optimize with --show-stage'))
3192 raise error.Abort(_('cannot use --optimize with --show-stage'))
3256 if opts['show_stage'] == ['all']:
3193 if opts['show_stage'] == ['all']:
3257 showalways.update(stagenames)
3194 showalways.update(stagenames)
3258 else:
3195 else:
3259 for n in opts['show_stage']:
3196 for n in opts['show_stage']:
3260 if n not in stagenames:
3197 if n not in stagenames:
3261 raise error.Abort(_('invalid stage name: %s') % n)
3198 raise error.Abort(_('invalid stage name: %s') % n)
3262 showalways.update(opts['show_stage'])
3199 showalways.update(opts['show_stage'])
3263
3200
3264 treebystage = {}
3201 treebystage = {}
3265 printedtree = None
3202 printedtree = None
3266 tree = revset.parse(expr, lookup=repo.__contains__)
3203 tree = revset.parse(expr, lookup=repo.__contains__)
3267 for n, f in stages:
3204 for n, f in stages:
3268 treebystage[n] = tree = f(tree)
3205 treebystage[n] = tree = f(tree)
3269 if n in showalways or (n in showchanged and tree != printedtree):
3206 if n in showalways or (n in showchanged and tree != printedtree):
3270 if opts['show_stage'] or n != 'parsed':
3207 if opts['show_stage'] or n != 'parsed':
3271 ui.write(("* %s:\n") % n)
3208 ui.write(("* %s:\n") % n)
3272 ui.write(revset.prettyformat(tree), "\n")
3209 ui.write(revset.prettyformat(tree), "\n")
3273 printedtree = tree
3210 printedtree = tree
3274
3211
3275 if opts['verify_optimized']:
3212 if opts['verify_optimized']:
3276 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3213 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3277 brevs = revset.makematcher(treebystage['optimized'])(repo)
3214 brevs = revset.makematcher(treebystage['optimized'])(repo)
3278 if ui.verbose:
3215 if ui.verbose:
3279 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3216 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3280 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3217 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3281 arevs = list(arevs)
3218 arevs = list(arevs)
3282 brevs = list(brevs)
3219 brevs = list(brevs)
3283 if arevs == brevs:
3220 if arevs == brevs:
3284 return 0
3221 return 0
3285 ui.write(('--- analyzed\n'), label='diff.file_a')
3222 ui.write(('--- analyzed\n'), label='diff.file_a')
3286 ui.write(('+++ optimized\n'), label='diff.file_b')
3223 ui.write(('+++ optimized\n'), label='diff.file_b')
3287 sm = difflib.SequenceMatcher(None, arevs, brevs)
3224 sm = difflib.SequenceMatcher(None, arevs, brevs)
3288 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3225 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3289 if tag in ('delete', 'replace'):
3226 if tag in ('delete', 'replace'):
3290 for c in arevs[alo:ahi]:
3227 for c in arevs[alo:ahi]:
3291 ui.write('-%s\n' % c, label='diff.deleted')
3228 ui.write('-%s\n' % c, label='diff.deleted')
3292 if tag in ('insert', 'replace'):
3229 if tag in ('insert', 'replace'):
3293 for c in brevs[blo:bhi]:
3230 for c in brevs[blo:bhi]:
3294 ui.write('+%s\n' % c, label='diff.inserted')
3231 ui.write('+%s\n' % c, label='diff.inserted')
3295 if tag == 'equal':
3232 if tag == 'equal':
3296 for c in arevs[alo:ahi]:
3233 for c in arevs[alo:ahi]:
3297 ui.write(' %s\n' % c)
3234 ui.write(' %s\n' % c)
3298 return 1
3235 return 1
3299
3236
3300 func = revset.makematcher(tree)
3237 func = revset.makematcher(tree)
3301 revs = func(repo)
3238 revs = func(repo)
3302 if ui.verbose:
3239 if ui.verbose:
3303 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3240 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3304 for c in revs:
3241 for c in revs:
3305 ui.write("%s\n" % c)
3242 ui.write("%s\n" % c)
3306
3243
3307 @command('debugsetparents', [], _('REV1 [REV2]'))
3244 @command('debugsetparents', [], _('REV1 [REV2]'))
3308 def debugsetparents(ui, repo, rev1, rev2=None):
3245 def debugsetparents(ui, repo, rev1, rev2=None):
3309 """manually set the parents of the current working directory
3246 """manually set the parents of the current working directory
3310
3247
3311 This is useful for writing repository conversion tools, but should
3248 This is useful for writing repository conversion tools, but should
3312 be used with care. For example, neither the working directory nor the
3249 be used with care. For example, neither the working directory nor the
3313 dirstate is updated, so file status may be incorrect after running this
3250 dirstate is updated, so file status may be incorrect after running this
3314 command.
3251 command.
3315
3252
3316 Returns 0 on success.
3253 Returns 0 on success.
3317 """
3254 """
3318
3255
3319 r1 = scmutil.revsingle(repo, rev1).node()
3256 r1 = scmutil.revsingle(repo, rev1).node()
3320 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3257 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3321
3258
3322 with repo.wlock():
3259 with repo.wlock():
3323 repo.setparents(r1, r2)
3260 repo.setparents(r1, r2)
3324
3261
3325 @command('debugdirstate|debugstate',
3262 @command('debugdirstate|debugstate',
3326 [('', 'nodates', None, _('do not display the saved mtime')),
3263 [('', 'nodates', None, _('do not display the saved mtime')),
3327 ('', 'datesort', None, _('sort by saved mtime'))],
3264 ('', 'datesort', None, _('sort by saved mtime'))],
3328 _('[OPTION]...'))
3265 _('[OPTION]...'))
3329 def debugstate(ui, repo, **opts):
3266 def debugstate(ui, repo, **opts):
3330 """show the contents of the current dirstate"""
3267 """show the contents of the current dirstate"""
3331
3268
3332 nodates = opts.get('nodates')
3269 nodates = opts.get('nodates')
3333 datesort = opts.get('datesort')
3270 datesort = opts.get('datesort')
3334
3271
3335 timestr = ""
3272 timestr = ""
3336 if datesort:
3273 if datesort:
3337 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3274 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3338 else:
3275 else:
3339 keyfunc = None # sort by filename
3276 keyfunc = None # sort by filename
3340 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3277 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3341 if ent[3] == -1:
3278 if ent[3] == -1:
3342 timestr = 'unset '
3279 timestr = 'unset '
3343 elif nodates:
3280 elif nodates:
3344 timestr = 'set '
3281 timestr = 'set '
3345 else:
3282 else:
3346 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3283 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3347 time.localtime(ent[3]))
3284 time.localtime(ent[3]))
3348 if ent[1] & 0o20000:
3285 if ent[1] & 0o20000:
3349 mode = 'lnk'
3286 mode = 'lnk'
3350 else:
3287 else:
3351 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3288 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3352 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3289 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3353 for f in repo.dirstate.copies():
3290 for f in repo.dirstate.copies():
3354 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3291 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3355
3292
3356 @command('debugsub',
3293 @command('debugsub',
3357 [('r', 'rev', '',
3294 [('r', 'rev', '',
3358 _('revision to check'), _('REV'))],
3295 _('revision to check'), _('REV'))],
3359 _('[-r REV] [REV]'))
3296 _('[-r REV] [REV]'))
3360 def debugsub(ui, repo, rev=None):
3297 def debugsub(ui, repo, rev=None):
3361 ctx = scmutil.revsingle(repo, rev, None)
3298 ctx = scmutil.revsingle(repo, rev, None)
3362 for k, v in sorted(ctx.substate.items()):
3299 for k, v in sorted(ctx.substate.items()):
3363 ui.write(('path %s\n') % k)
3300 ui.write(('path %s\n') % k)
3364 ui.write((' source %s\n') % v[0])
3301 ui.write((' source %s\n') % v[0])
3365 ui.write((' revision %s\n') % v[1])
3302 ui.write((' revision %s\n') % v[1])
3366
3303
3367 @command('debugsuccessorssets',
3304 @command('debugsuccessorssets',
3368 [],
3305 [],
3369 _('[REV]'))
3306 _('[REV]'))
3370 def debugsuccessorssets(ui, repo, *revs):
3307 def debugsuccessorssets(ui, repo, *revs):
3371 """show set of successors for revision
3308 """show set of successors for revision
3372
3309
3373 A successors set of changeset A is a consistent group of revisions that
3310 A successors set of changeset A is a consistent group of revisions that
3374 succeed A. It contains non-obsolete changesets only.
3311 succeed A. It contains non-obsolete changesets only.
3375
3312
3376 In most cases a changeset A has a single successors set containing a single
3313 In most cases a changeset A has a single successors set containing a single
3377 successor (changeset A replaced by A').
3314 successor (changeset A replaced by A').
3378
3315
3379 A changeset that is made obsolete with no successors are called "pruned".
3316 A changeset that is made obsolete with no successors are called "pruned".
3380 Such changesets have no successors sets at all.
3317 Such changesets have no successors sets at all.
3381
3318
3382 A changeset that has been "split" will have a successors set containing
3319 A changeset that has been "split" will have a successors set containing
3383 more than one successor.
3320 more than one successor.
3384
3321
3385 A changeset that has been rewritten in multiple different ways is called
3322 A changeset that has been rewritten in multiple different ways is called
3386 "divergent". Such changesets have multiple successor sets (each of which
3323 "divergent". Such changesets have multiple successor sets (each of which
3387 may also be split, i.e. have multiple successors).
3324 may also be split, i.e. have multiple successors).
3388
3325
3389 Results are displayed as follows::
3326 Results are displayed as follows::
3390
3327
3391 <rev1>
3328 <rev1>
3392 <successors-1A>
3329 <successors-1A>
3393 <rev2>
3330 <rev2>
3394 <successors-2A>
3331 <successors-2A>
3395 <successors-2B1> <successors-2B2> <successors-2B3>
3332 <successors-2B1> <successors-2B2> <successors-2B3>
3396
3333
3397 Here rev2 has two possible (i.e. divergent) successors sets. The first
3334 Here rev2 has two possible (i.e. divergent) successors sets. The first
3398 holds one element, whereas the second holds three (i.e. the changeset has
3335 holds one element, whereas the second holds three (i.e. the changeset has
3399 been split).
3336 been split).
3400 """
3337 """
3401 # passed to successorssets caching computation from one call to another
3338 # passed to successorssets caching computation from one call to another
3402 cache = {}
3339 cache = {}
3403 ctx2str = str
3340 ctx2str = str
3404 node2str = short
3341 node2str = short
3405 if ui.debug():
3342 if ui.debug():
3406 def ctx2str(ctx):
3343 def ctx2str(ctx):
3407 return ctx.hex()
3344 return ctx.hex()
3408 node2str = hex
3345 node2str = hex
3409 for rev in scmutil.revrange(repo, revs):
3346 for rev in scmutil.revrange(repo, revs):
3410 ctx = repo[rev]
3347 ctx = repo[rev]
3411 ui.write('%s\n'% ctx2str(ctx))
3348 ui.write('%s\n'% ctx2str(ctx))
3412 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3349 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3413 if succsset:
3350 if succsset:
3414 ui.write(' ')
3351 ui.write(' ')
3415 ui.write(node2str(succsset[0]))
3352 ui.write(node2str(succsset[0]))
3416 for node in succsset[1:]:
3353 for node in succsset[1:]:
3417 ui.write(' ')
3354 ui.write(' ')
3418 ui.write(node2str(node))
3355 ui.write(node2str(node))
3419 ui.write('\n')
3356 ui.write('\n')
3420
3357
3421 @command('debugtemplate',
3358 @command('debugtemplate',
3422 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3359 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3423 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3360 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3424 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3361 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3425 optionalrepo=True)
3362 optionalrepo=True)
3426 def debugtemplate(ui, repo, tmpl, **opts):
3363 def debugtemplate(ui, repo, tmpl, **opts):
3427 """parse and apply a template
3364 """parse and apply a template
3428
3365
3429 If -r/--rev is given, the template is processed as a log template and
3366 If -r/--rev is given, the template is processed as a log template and
3430 applied to the given changesets. Otherwise, it is processed as a generic
3367 applied to the given changesets. Otherwise, it is processed as a generic
3431 template.
3368 template.
3432
3369
3433 Use --verbose to print the parsed tree.
3370 Use --verbose to print the parsed tree.
3434 """
3371 """
3435 revs = None
3372 revs = None
3436 if opts['rev']:
3373 if opts['rev']:
3437 if repo is None:
3374 if repo is None:
3438 raise error.RepoError(_('there is no Mercurial repository here '
3375 raise error.RepoError(_('there is no Mercurial repository here '
3439 '(.hg not found)'))
3376 '(.hg not found)'))
3440 revs = scmutil.revrange(repo, opts['rev'])
3377 revs = scmutil.revrange(repo, opts['rev'])
3441
3378
3442 props = {}
3379 props = {}
3443 for d in opts['define']:
3380 for d in opts['define']:
3444 try:
3381 try:
3445 k, v = (e.strip() for e in d.split('=', 1))
3382 k, v = (e.strip() for e in d.split('=', 1))
3446 if not k:
3383 if not k:
3447 raise ValueError
3384 raise ValueError
3448 props[k] = v
3385 props[k] = v
3449 except ValueError:
3386 except ValueError:
3450 raise error.Abort(_('malformed keyword definition: %s') % d)
3387 raise error.Abort(_('malformed keyword definition: %s') % d)
3451
3388
3452 if ui.verbose:
3389 if ui.verbose:
3453 aliases = ui.configitems('templatealias')
3390 aliases = ui.configitems('templatealias')
3454 tree = templater.parse(tmpl)
3391 tree = templater.parse(tmpl)
3455 ui.note(templater.prettyformat(tree), '\n')
3392 ui.note(templater.prettyformat(tree), '\n')
3456 newtree = templater.expandaliases(tree, aliases)
3393 newtree = templater.expandaliases(tree, aliases)
3457 if newtree != tree:
3394 if newtree != tree:
3458 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3395 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3459
3396
3460 mapfile = None
3397 mapfile = None
3461 if revs is None:
3398 if revs is None:
3462 k = 'debugtemplate'
3399 k = 'debugtemplate'
3463 t = formatter.maketemplater(ui, k, tmpl)
3400 t = formatter.maketemplater(ui, k, tmpl)
3464 ui.write(templater.stringify(t(k, **props)))
3401 ui.write(templater.stringify(t(k, **props)))
3465 else:
3402 else:
3466 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3403 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3467 mapfile, buffered=False)
3404 mapfile, buffered=False)
3468 for r in revs:
3405 for r in revs:
3469 displayer.show(repo[r], **props)
3406 displayer.show(repo[r], **props)
3470 displayer.close()
3407 displayer.close()
3471
3408
3472 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3409 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3473 def debugwalk(ui, repo, *pats, **opts):
3410 def debugwalk(ui, repo, *pats, **opts):
3474 """show how files match on given patterns"""
3411 """show how files match on given patterns"""
3475 m = scmutil.match(repo[None], pats, opts)
3412 m = scmutil.match(repo[None], pats, opts)
3476 items = list(repo.walk(m))
3413 items = list(repo.walk(m))
3477 if not items:
3414 if not items:
3478 return
3415 return
3479 f = lambda fn: fn
3416 f = lambda fn: fn
3480 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
3417 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
3481 f = lambda fn: util.normpath(fn)
3418 f = lambda fn: util.normpath(fn)
3482 fmt = 'f %%-%ds %%-%ds %%s' % (
3419 fmt = 'f %%-%ds %%-%ds %%s' % (
3483 max([len(abs) for abs in items]),
3420 max([len(abs) for abs in items]),
3484 max([len(m.rel(abs)) for abs in items]))
3421 max([len(m.rel(abs)) for abs in items]))
3485 for abs in items:
3422 for abs in items:
3486 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3423 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3487 ui.write("%s\n" % line.rstrip())
3424 ui.write("%s\n" % line.rstrip())
3488
3425
3489 @command('debugwireargs',
3426 @command('debugwireargs',
3490 [('', 'three', '', 'three'),
3427 [('', 'three', '', 'three'),
3491 ('', 'four', '', 'four'),
3428 ('', 'four', '', 'four'),
3492 ('', 'five', '', 'five'),
3429 ('', 'five', '', 'five'),
3493 ] + remoteopts,
3430 ] + remoteopts,
3494 _('REPO [OPTIONS]... [ONE [TWO]]'),
3431 _('REPO [OPTIONS]... [ONE [TWO]]'),
3495 norepo=True)
3432 norepo=True)
3496 def debugwireargs(ui, repopath, *vals, **opts):
3433 def debugwireargs(ui, repopath, *vals, **opts):
3497 repo = hg.peer(ui, opts, repopath)
3434 repo = hg.peer(ui, opts, repopath)
3498 for opt in remoteopts:
3435 for opt in remoteopts:
3499 del opts[opt[1]]
3436 del opts[opt[1]]
3500 args = {}
3437 args = {}
3501 for k, v in opts.iteritems():
3438 for k, v in opts.iteritems():
3502 if v:
3439 if v:
3503 args[k] = v
3440 args[k] = v
3504 # run twice to check that we don't mess up the stream for the next command
3441 # run twice to check that we don't mess up the stream for the next command
3505 res1 = repo.debugwireargs(*vals, **args)
3442 res1 = repo.debugwireargs(*vals, **args)
3506 res2 = repo.debugwireargs(*vals, **args)
3443 res2 = repo.debugwireargs(*vals, **args)
3507 ui.write("%s\n" % res1)
3444 ui.write("%s\n" % res1)
3508 if res1 != res2:
3445 if res1 != res2:
3509 ui.warn("%s\n" % res2)
3446 ui.warn("%s\n" % res2)
3510
3447
3511 @command('^diff',
3448 @command('^diff',
3512 [('r', 'rev', [], _('revision'), _('REV')),
3449 [('r', 'rev', [], _('revision'), _('REV')),
3513 ('c', 'change', '', _('change made by revision'), _('REV'))
3450 ('c', 'change', '', _('change made by revision'), _('REV'))
3514 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3451 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3515 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3452 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3516 inferrepo=True)
3453 inferrepo=True)
3517 def diff(ui, repo, *pats, **opts):
3454 def diff(ui, repo, *pats, **opts):
3518 """diff repository (or selected files)
3455 """diff repository (or selected files)
3519
3456
3520 Show differences between revisions for the specified files.
3457 Show differences between revisions for the specified files.
3521
3458
3522 Differences between files are shown using the unified diff format.
3459 Differences between files are shown using the unified diff format.
3523
3460
3524 .. note::
3461 .. note::
3525
3462
3526 :hg:`diff` may generate unexpected results for merges, as it will
3463 :hg:`diff` may generate unexpected results for merges, as it will
3527 default to comparing against the working directory's first
3464 default to comparing against the working directory's first
3528 parent changeset if no revisions are specified.
3465 parent changeset if no revisions are specified.
3529
3466
3530 When two revision arguments are given, then changes are shown
3467 When two revision arguments are given, then changes are shown
3531 between those revisions. If only one revision is specified then
3468 between those revisions. If only one revision is specified then
3532 that revision is compared to the working directory, and, when no
3469 that revision is compared to the working directory, and, when no
3533 revisions are specified, the working directory files are compared
3470 revisions are specified, the working directory files are compared
3534 to its first parent.
3471 to its first parent.
3535
3472
3536 Alternatively you can specify -c/--change with a revision to see
3473 Alternatively you can specify -c/--change with a revision to see
3537 the changes in that changeset relative to its first parent.
3474 the changes in that changeset relative to its first parent.
3538
3475
3539 Without the -a/--text option, diff will avoid generating diffs of
3476 Without the -a/--text option, diff will avoid generating diffs of
3540 files it detects as binary. With -a, diff will generate a diff
3477 files it detects as binary. With -a, diff will generate a diff
3541 anyway, probably with undesirable results.
3478 anyway, probably with undesirable results.
3542
3479
3543 Use the -g/--git option to generate diffs in the git extended diff
3480 Use the -g/--git option to generate diffs in the git extended diff
3544 format. For more information, read :hg:`help diffs`.
3481 format. For more information, read :hg:`help diffs`.
3545
3482
3546 .. container:: verbose
3483 .. container:: verbose
3547
3484
3548 Examples:
3485 Examples:
3549
3486
3550 - compare a file in the current working directory to its parent::
3487 - compare a file in the current working directory to its parent::
3551
3488
3552 hg diff foo.c
3489 hg diff foo.c
3553
3490
3554 - compare two historical versions of a directory, with rename info::
3491 - compare two historical versions of a directory, with rename info::
3555
3492
3556 hg diff --git -r 1.0:1.2 lib/
3493 hg diff --git -r 1.0:1.2 lib/
3557
3494
3558 - get change stats relative to the last change on some date::
3495 - get change stats relative to the last change on some date::
3559
3496
3560 hg diff --stat -r "date('may 2')"
3497 hg diff --stat -r "date('may 2')"
3561
3498
3562 - diff all newly-added files that contain a keyword::
3499 - diff all newly-added files that contain a keyword::
3563
3500
3564 hg diff "set:added() and grep(GNU)"
3501 hg diff "set:added() and grep(GNU)"
3565
3502
3566 - compare a revision and its parents::
3503 - compare a revision and its parents::
3567
3504
3568 hg diff -c 9353 # compare against first parent
3505 hg diff -c 9353 # compare against first parent
3569 hg diff -r 9353^:9353 # same using revset syntax
3506 hg diff -r 9353^:9353 # same using revset syntax
3570 hg diff -r 9353^2:9353 # compare against the second parent
3507 hg diff -r 9353^2:9353 # compare against the second parent
3571
3508
3572 Returns 0 on success.
3509 Returns 0 on success.
3573 """
3510 """
3574
3511
3575 revs = opts.get('rev')
3512 revs = opts.get('rev')
3576 change = opts.get('change')
3513 change = opts.get('change')
3577 stat = opts.get('stat')
3514 stat = opts.get('stat')
3578 reverse = opts.get('reverse')
3515 reverse = opts.get('reverse')
3579
3516
3580 if revs and change:
3517 if revs and change:
3581 msg = _('cannot specify --rev and --change at the same time')
3518 msg = _('cannot specify --rev and --change at the same time')
3582 raise error.Abort(msg)
3519 raise error.Abort(msg)
3583 elif change:
3520 elif change:
3584 node2 = scmutil.revsingle(repo, change, None).node()
3521 node2 = scmutil.revsingle(repo, change, None).node()
3585 node1 = repo[node2].p1().node()
3522 node1 = repo[node2].p1().node()
3586 else:
3523 else:
3587 node1, node2 = scmutil.revpair(repo, revs)
3524 node1, node2 = scmutil.revpair(repo, revs)
3588
3525
3589 if reverse:
3526 if reverse:
3590 node1, node2 = node2, node1
3527 node1, node2 = node2, node1
3591
3528
3592 diffopts = patch.diffallopts(ui, opts)
3529 diffopts = patch.diffallopts(ui, opts)
3593 m = scmutil.match(repo[node2], pats, opts)
3530 m = scmutil.match(repo[node2], pats, opts)
3594 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3531 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3595 listsubrepos=opts.get('subrepos'),
3532 listsubrepos=opts.get('subrepos'),
3596 root=opts.get('root'))
3533 root=opts.get('root'))
3597
3534
3598 @command('^export',
3535 @command('^export',
3599 [('o', 'output', '',
3536 [('o', 'output', '',
3600 _('print output to file with formatted name'), _('FORMAT')),
3537 _('print output to file with formatted name'), _('FORMAT')),
3601 ('', 'switch-parent', None, _('diff against the second parent')),
3538 ('', 'switch-parent', None, _('diff against the second parent')),
3602 ('r', 'rev', [], _('revisions to export'), _('REV')),
3539 ('r', 'rev', [], _('revisions to export'), _('REV')),
3603 ] + diffopts,
3540 ] + diffopts,
3604 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3541 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3605 def export(ui, repo, *changesets, **opts):
3542 def export(ui, repo, *changesets, **opts):
3606 """dump the header and diffs for one or more changesets
3543 """dump the header and diffs for one or more changesets
3607
3544
3608 Print the changeset header and diffs for one or more revisions.
3545 Print the changeset header and diffs for one or more revisions.
3609 If no revision is given, the parent of the working directory is used.
3546 If no revision is given, the parent of the working directory is used.
3610
3547
3611 The information shown in the changeset header is: author, date,
3548 The information shown in the changeset header is: author, date,
3612 branch name (if non-default), changeset hash, parent(s) and commit
3549 branch name (if non-default), changeset hash, parent(s) and commit
3613 comment.
3550 comment.
3614
3551
3615 .. note::
3552 .. note::
3616
3553
3617 :hg:`export` may generate unexpected diff output for merge
3554 :hg:`export` may generate unexpected diff output for merge
3618 changesets, as it will compare the merge changeset against its
3555 changesets, as it will compare the merge changeset against its
3619 first parent only.
3556 first parent only.
3620
3557
3621 Output may be to a file, in which case the name of the file is
3558 Output may be to a file, in which case the name of the file is
3622 given using a format string. The formatting rules are as follows:
3559 given using a format string. The formatting rules are as follows:
3623
3560
3624 :``%%``: literal "%" character
3561 :``%%``: literal "%" character
3625 :``%H``: changeset hash (40 hexadecimal digits)
3562 :``%H``: changeset hash (40 hexadecimal digits)
3626 :``%N``: number of patches being generated
3563 :``%N``: number of patches being generated
3627 :``%R``: changeset revision number
3564 :``%R``: changeset revision number
3628 :``%b``: basename of the exporting repository
3565 :``%b``: basename of the exporting repository
3629 :``%h``: short-form changeset hash (12 hexadecimal digits)
3566 :``%h``: short-form changeset hash (12 hexadecimal digits)
3630 :``%m``: first line of the commit message (only alphanumeric characters)
3567 :``%m``: first line of the commit message (only alphanumeric characters)
3631 :``%n``: zero-padded sequence number, starting at 1
3568 :``%n``: zero-padded sequence number, starting at 1
3632 :``%r``: zero-padded changeset revision number
3569 :``%r``: zero-padded changeset revision number
3633
3570
3634 Without the -a/--text option, export will avoid generating diffs
3571 Without the -a/--text option, export will avoid generating diffs
3635 of files it detects as binary. With -a, export will generate a
3572 of files it detects as binary. With -a, export will generate a
3636 diff anyway, probably with undesirable results.
3573 diff anyway, probably with undesirable results.
3637
3574
3638 Use the -g/--git option to generate diffs in the git extended diff
3575 Use the -g/--git option to generate diffs in the git extended diff
3639 format. See :hg:`help diffs` for more information.
3576 format. See :hg:`help diffs` for more information.
3640
3577
3641 With the --switch-parent option, the diff will be against the
3578 With the --switch-parent option, the diff will be against the
3642 second parent. It can be useful to review a merge.
3579 second parent. It can be useful to review a merge.
3643
3580
3644 .. container:: verbose
3581 .. container:: verbose
3645
3582
3646 Examples:
3583 Examples:
3647
3584
3648 - use export and import to transplant a bugfix to the current
3585 - use export and import to transplant a bugfix to the current
3649 branch::
3586 branch::
3650
3587
3651 hg export -r 9353 | hg import -
3588 hg export -r 9353 | hg import -
3652
3589
3653 - export all the changesets between two revisions to a file with
3590 - export all the changesets between two revisions to a file with
3654 rename information::
3591 rename information::
3655
3592
3656 hg export --git -r 123:150 > changes.txt
3593 hg export --git -r 123:150 > changes.txt
3657
3594
3658 - split outgoing changes into a series of patches with
3595 - split outgoing changes into a series of patches with
3659 descriptive names::
3596 descriptive names::
3660
3597
3661 hg export -r "outgoing()" -o "%n-%m.patch"
3598 hg export -r "outgoing()" -o "%n-%m.patch"
3662
3599
3663 Returns 0 on success.
3600 Returns 0 on success.
3664 """
3601 """
3665 changesets += tuple(opts.get('rev', []))
3602 changesets += tuple(opts.get('rev', []))
3666 if not changesets:
3603 if not changesets:
3667 changesets = ['.']
3604 changesets = ['.']
3668 revs = scmutil.revrange(repo, changesets)
3605 revs = scmutil.revrange(repo, changesets)
3669 if not revs:
3606 if not revs:
3670 raise error.Abort(_("export requires at least one changeset"))
3607 raise error.Abort(_("export requires at least one changeset"))
3671 if len(revs) > 1:
3608 if len(revs) > 1:
3672 ui.note(_('exporting patches:\n'))
3609 ui.note(_('exporting patches:\n'))
3673 else:
3610 else:
3674 ui.note(_('exporting patch:\n'))
3611 ui.note(_('exporting patch:\n'))
3675 cmdutil.export(repo, revs, template=opts.get('output'),
3612 cmdutil.export(repo, revs, template=opts.get('output'),
3676 switch_parent=opts.get('switch_parent'),
3613 switch_parent=opts.get('switch_parent'),
3677 opts=patch.diffallopts(ui, opts))
3614 opts=patch.diffallopts(ui, opts))
3678
3615
3679 @command('files',
3616 @command('files',
3680 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3617 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3681 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3618 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3682 ] + walkopts + formatteropts + subrepoopts,
3619 ] + walkopts + formatteropts + subrepoopts,
3683 _('[OPTION]... [FILE]...'))
3620 _('[OPTION]... [FILE]...'))
3684 def files(ui, repo, *pats, **opts):
3621 def files(ui, repo, *pats, **opts):
3685 """list tracked files
3622 """list tracked files
3686
3623
3687 Print files under Mercurial control in the working directory or
3624 Print files under Mercurial control in the working directory or
3688 specified revision for given files (excluding removed files).
3625 specified revision for given files (excluding removed files).
3689 Files can be specified as filenames or filesets.
3626 Files can be specified as filenames or filesets.
3690
3627
3691 If no files are given to match, this command prints the names
3628 If no files are given to match, this command prints the names
3692 of all files under Mercurial control.
3629 of all files under Mercurial control.
3693
3630
3694 .. container:: verbose
3631 .. container:: verbose
3695
3632
3696 Examples:
3633 Examples:
3697
3634
3698 - list all files under the current directory::
3635 - list all files under the current directory::
3699
3636
3700 hg files .
3637 hg files .
3701
3638
3702 - shows sizes and flags for current revision::
3639 - shows sizes and flags for current revision::
3703
3640
3704 hg files -vr .
3641 hg files -vr .
3705
3642
3706 - list all files named README::
3643 - list all files named README::
3707
3644
3708 hg files -I "**/README"
3645 hg files -I "**/README"
3709
3646
3710 - list all binary files::
3647 - list all binary files::
3711
3648
3712 hg files "set:binary()"
3649 hg files "set:binary()"
3713
3650
3714 - find files containing a regular expression::
3651 - find files containing a regular expression::
3715
3652
3716 hg files "set:grep('bob')"
3653 hg files "set:grep('bob')"
3717
3654
3718 - search tracked file contents with xargs and grep::
3655 - search tracked file contents with xargs and grep::
3719
3656
3720 hg files -0 | xargs -0 grep foo
3657 hg files -0 | xargs -0 grep foo
3721
3658
3722 See :hg:`help patterns` and :hg:`help filesets` for more information
3659 See :hg:`help patterns` and :hg:`help filesets` for more information
3723 on specifying file patterns.
3660 on specifying file patterns.
3724
3661
3725 Returns 0 if a match is found, 1 otherwise.
3662 Returns 0 if a match is found, 1 otherwise.
3726
3663
3727 """
3664 """
3728 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3665 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3729
3666
3730 end = '\n'
3667 end = '\n'
3731 if opts.get('print0'):
3668 if opts.get('print0'):
3732 end = '\0'
3669 end = '\0'
3733 fmt = '%s' + end
3670 fmt = '%s' + end
3734
3671
3735 m = scmutil.match(ctx, pats, opts)
3672 m = scmutil.match(ctx, pats, opts)
3736 with ui.formatter('files', opts) as fm:
3673 with ui.formatter('files', opts) as fm:
3737 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3674 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3738
3675
3739 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3676 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3740 def forget(ui, repo, *pats, **opts):
3677 def forget(ui, repo, *pats, **opts):
3741 """forget the specified files on the next commit
3678 """forget the specified files on the next commit
3742
3679
3743 Mark the specified files so they will no longer be tracked
3680 Mark the specified files so they will no longer be tracked
3744 after the next commit.
3681 after the next commit.
3745
3682
3746 This only removes files from the current branch, not from the
3683 This only removes files from the current branch, not from the
3747 entire project history, and it does not delete them from the
3684 entire project history, and it does not delete them from the
3748 working directory.
3685 working directory.
3749
3686
3750 To delete the file from the working directory, see :hg:`remove`.
3687 To delete the file from the working directory, see :hg:`remove`.
3751
3688
3752 To undo a forget before the next commit, see :hg:`add`.
3689 To undo a forget before the next commit, see :hg:`add`.
3753
3690
3754 .. container:: verbose
3691 .. container:: verbose
3755
3692
3756 Examples:
3693 Examples:
3757
3694
3758 - forget newly-added binary files::
3695 - forget newly-added binary files::
3759
3696
3760 hg forget "set:added() and binary()"
3697 hg forget "set:added() and binary()"
3761
3698
3762 - forget files that would be excluded by .hgignore::
3699 - forget files that would be excluded by .hgignore::
3763
3700
3764 hg forget "set:hgignore()"
3701 hg forget "set:hgignore()"
3765
3702
3766 Returns 0 on success.
3703 Returns 0 on success.
3767 """
3704 """
3768
3705
3769 if not pats:
3706 if not pats:
3770 raise error.Abort(_('no files specified'))
3707 raise error.Abort(_('no files specified'))
3771
3708
3772 m = scmutil.match(repo[None], pats, opts)
3709 m = scmutil.match(repo[None], pats, opts)
3773 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3710 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3774 return rejected and 1 or 0
3711 return rejected and 1 or 0
3775
3712
3776 @command(
3713 @command(
3777 'graft',
3714 'graft',
3778 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3715 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3779 ('c', 'continue', False, _('resume interrupted graft')),
3716 ('c', 'continue', False, _('resume interrupted graft')),
3780 ('e', 'edit', False, _('invoke editor on commit messages')),
3717 ('e', 'edit', False, _('invoke editor on commit messages')),
3781 ('', 'log', None, _('append graft info to log message')),
3718 ('', 'log', None, _('append graft info to log message')),
3782 ('f', 'force', False, _('force graft')),
3719 ('f', 'force', False, _('force graft')),
3783 ('D', 'currentdate', False,
3720 ('D', 'currentdate', False,
3784 _('record the current date as commit date')),
3721 _('record the current date as commit date')),
3785 ('U', 'currentuser', False,
3722 ('U', 'currentuser', False,
3786 _('record the current user as committer'), _('DATE'))]
3723 _('record the current user as committer'), _('DATE'))]
3787 + commitopts2 + mergetoolopts + dryrunopts,
3724 + commitopts2 + mergetoolopts + dryrunopts,
3788 _('[OPTION]... [-r REV]... REV...'))
3725 _('[OPTION]... [-r REV]... REV...'))
3789 def graft(ui, repo, *revs, **opts):
3726 def graft(ui, repo, *revs, **opts):
3790 '''copy changes from other branches onto the current branch
3727 '''copy changes from other branches onto the current branch
3791
3728
3792 This command uses Mercurial's merge logic to copy individual
3729 This command uses Mercurial's merge logic to copy individual
3793 changes from other branches without merging branches in the
3730 changes from other branches without merging branches in the
3794 history graph. This is sometimes known as 'backporting' or
3731 history graph. This is sometimes known as 'backporting' or
3795 'cherry-picking'. By default, graft will copy user, date, and
3732 'cherry-picking'. By default, graft will copy user, date, and
3796 description from the source changesets.
3733 description from the source changesets.
3797
3734
3798 Changesets that are ancestors of the current revision, that have
3735 Changesets that are ancestors of the current revision, that have
3799 already been grafted, or that are merges will be skipped.
3736 already been grafted, or that are merges will be skipped.
3800
3737
3801 If --log is specified, log messages will have a comment appended
3738 If --log is specified, log messages will have a comment appended
3802 of the form::
3739 of the form::
3803
3740
3804 (grafted from CHANGESETHASH)
3741 (grafted from CHANGESETHASH)
3805
3742
3806 If --force is specified, revisions will be grafted even if they
3743 If --force is specified, revisions will be grafted even if they
3807 are already ancestors of or have been grafted to the destination.
3744 are already ancestors of or have been grafted to the destination.
3808 This is useful when the revisions have since been backed out.
3745 This is useful when the revisions have since been backed out.
3809
3746
3810 If a graft merge results in conflicts, the graft process is
3747 If a graft merge results in conflicts, the graft process is
3811 interrupted so that the current merge can be manually resolved.
3748 interrupted so that the current merge can be manually resolved.
3812 Once all conflicts are addressed, the graft process can be
3749 Once all conflicts are addressed, the graft process can be
3813 continued with the -c/--continue option.
3750 continued with the -c/--continue option.
3814
3751
3815 .. note::
3752 .. note::
3816
3753
3817 The -c/--continue option does not reapply earlier options, except
3754 The -c/--continue option does not reapply earlier options, except
3818 for --force.
3755 for --force.
3819
3756
3820 .. container:: verbose
3757 .. container:: verbose
3821
3758
3822 Examples:
3759 Examples:
3823
3760
3824 - copy a single change to the stable branch and edit its description::
3761 - copy a single change to the stable branch and edit its description::
3825
3762
3826 hg update stable
3763 hg update stable
3827 hg graft --edit 9393
3764 hg graft --edit 9393
3828
3765
3829 - graft a range of changesets with one exception, updating dates::
3766 - graft a range of changesets with one exception, updating dates::
3830
3767
3831 hg graft -D "2085::2093 and not 2091"
3768 hg graft -D "2085::2093 and not 2091"
3832
3769
3833 - continue a graft after resolving conflicts::
3770 - continue a graft after resolving conflicts::
3834
3771
3835 hg graft -c
3772 hg graft -c
3836
3773
3837 - show the source of a grafted changeset::
3774 - show the source of a grafted changeset::
3838
3775
3839 hg log --debug -r .
3776 hg log --debug -r .
3840
3777
3841 - show revisions sorted by date::
3778 - show revisions sorted by date::
3842
3779
3843 hg log -r "sort(all(), date)"
3780 hg log -r "sort(all(), date)"
3844
3781
3845 See :hg:`help revisions` and :hg:`help revsets` for more about
3782 See :hg:`help revisions` and :hg:`help revsets` for more about
3846 specifying revisions.
3783 specifying revisions.
3847
3784
3848 Returns 0 on successful completion.
3785 Returns 0 on successful completion.
3849 '''
3786 '''
3850 with repo.wlock():
3787 with repo.wlock():
3851 return _dograft(ui, repo, *revs, **opts)
3788 return _dograft(ui, repo, *revs, **opts)
3852
3789
3853 def _dograft(ui, repo, *revs, **opts):
3790 def _dograft(ui, repo, *revs, **opts):
3854 if revs and opts.get('rev'):
3791 if revs and opts.get('rev'):
3855 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3792 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3856 'revision ordering!\n'))
3793 'revision ordering!\n'))
3857
3794
3858 revs = list(revs)
3795 revs = list(revs)
3859 revs.extend(opts.get('rev'))
3796 revs.extend(opts.get('rev'))
3860
3797
3861 if not opts.get('user') and opts.get('currentuser'):
3798 if not opts.get('user') and opts.get('currentuser'):
3862 opts['user'] = ui.username()
3799 opts['user'] = ui.username()
3863 if not opts.get('date') and opts.get('currentdate'):
3800 if not opts.get('date') and opts.get('currentdate'):
3864 opts['date'] = "%d %d" % util.makedate()
3801 opts['date'] = "%d %d" % util.makedate()
3865
3802
3866 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3803 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3867
3804
3868 cont = False
3805 cont = False
3869 if opts.get('continue'):
3806 if opts.get('continue'):
3870 cont = True
3807 cont = True
3871 if revs:
3808 if revs:
3872 raise error.Abort(_("can't specify --continue and revisions"))
3809 raise error.Abort(_("can't specify --continue and revisions"))
3873 # read in unfinished revisions
3810 # read in unfinished revisions
3874 try:
3811 try:
3875 nodes = repo.vfs.read('graftstate').splitlines()
3812 nodes = repo.vfs.read('graftstate').splitlines()
3876 revs = [repo[node].rev() for node in nodes]
3813 revs = [repo[node].rev() for node in nodes]
3877 except IOError as inst:
3814 except IOError as inst:
3878 if inst.errno != errno.ENOENT:
3815 if inst.errno != errno.ENOENT:
3879 raise
3816 raise
3880 cmdutil.wrongtooltocontinue(repo, _('graft'))
3817 cmdutil.wrongtooltocontinue(repo, _('graft'))
3881 else:
3818 else:
3882 cmdutil.checkunfinished(repo)
3819 cmdutil.checkunfinished(repo)
3883 cmdutil.bailifchanged(repo)
3820 cmdutil.bailifchanged(repo)
3884 if not revs:
3821 if not revs:
3885 raise error.Abort(_('no revisions specified'))
3822 raise error.Abort(_('no revisions specified'))
3886 revs = scmutil.revrange(repo, revs)
3823 revs = scmutil.revrange(repo, revs)
3887
3824
3888 skipped = set()
3825 skipped = set()
3889 # check for merges
3826 # check for merges
3890 for rev in repo.revs('%ld and merge()', revs):
3827 for rev in repo.revs('%ld and merge()', revs):
3891 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3828 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3892 skipped.add(rev)
3829 skipped.add(rev)
3893 revs = [r for r in revs if r not in skipped]
3830 revs = [r for r in revs if r not in skipped]
3894 if not revs:
3831 if not revs:
3895 return -1
3832 return -1
3896
3833
3897 # Don't check in the --continue case, in effect retaining --force across
3834 # Don't check in the --continue case, in effect retaining --force across
3898 # --continues. That's because without --force, any revisions we decided to
3835 # --continues. That's because without --force, any revisions we decided to
3899 # skip would have been filtered out here, so they wouldn't have made their
3836 # skip would have been filtered out here, so they wouldn't have made their
3900 # way to the graftstate. With --force, any revisions we would have otherwise
3837 # way to the graftstate. With --force, any revisions we would have otherwise
3901 # skipped would not have been filtered out, and if they hadn't been applied
3838 # skipped would not have been filtered out, and if they hadn't been applied
3902 # already, they'd have been in the graftstate.
3839 # already, they'd have been in the graftstate.
3903 if not (cont or opts.get('force')):
3840 if not (cont or opts.get('force')):
3904 # check for ancestors of dest branch
3841 # check for ancestors of dest branch
3905 crev = repo['.'].rev()
3842 crev = repo['.'].rev()
3906 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3843 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3907 # XXX make this lazy in the future
3844 # XXX make this lazy in the future
3908 # don't mutate while iterating, create a copy
3845 # don't mutate while iterating, create a copy
3909 for rev in list(revs):
3846 for rev in list(revs):
3910 if rev in ancestors:
3847 if rev in ancestors:
3911 ui.warn(_('skipping ancestor revision %d:%s\n') %
3848 ui.warn(_('skipping ancestor revision %d:%s\n') %
3912 (rev, repo[rev]))
3849 (rev, repo[rev]))
3913 # XXX remove on list is slow
3850 # XXX remove on list is slow
3914 revs.remove(rev)
3851 revs.remove(rev)
3915 if not revs:
3852 if not revs:
3916 return -1
3853 return -1
3917
3854
3918 # analyze revs for earlier grafts
3855 # analyze revs for earlier grafts
3919 ids = {}
3856 ids = {}
3920 for ctx in repo.set("%ld", revs):
3857 for ctx in repo.set("%ld", revs):
3921 ids[ctx.hex()] = ctx.rev()
3858 ids[ctx.hex()] = ctx.rev()
3922 n = ctx.extra().get('source')
3859 n = ctx.extra().get('source')
3923 if n:
3860 if n:
3924 ids[n] = ctx.rev()
3861 ids[n] = ctx.rev()
3925
3862
3926 # check ancestors for earlier grafts
3863 # check ancestors for earlier grafts
3927 ui.debug('scanning for duplicate grafts\n')
3864 ui.debug('scanning for duplicate grafts\n')
3928
3865
3929 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3866 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3930 ctx = repo[rev]
3867 ctx = repo[rev]
3931 n = ctx.extra().get('source')
3868 n = ctx.extra().get('source')
3932 if n in ids:
3869 if n in ids:
3933 try:
3870 try:
3934 r = repo[n].rev()
3871 r = repo[n].rev()
3935 except error.RepoLookupError:
3872 except error.RepoLookupError:
3936 r = None
3873 r = None
3937 if r in revs:
3874 if r in revs:
3938 ui.warn(_('skipping revision %d:%s '
3875 ui.warn(_('skipping revision %d:%s '
3939 '(already grafted to %d:%s)\n')
3876 '(already grafted to %d:%s)\n')
3940 % (r, repo[r], rev, ctx))
3877 % (r, repo[r], rev, ctx))
3941 revs.remove(r)
3878 revs.remove(r)
3942 elif ids[n] in revs:
3879 elif ids[n] in revs:
3943 if r is None:
3880 if r is None:
3944 ui.warn(_('skipping already grafted revision %d:%s '
3881 ui.warn(_('skipping already grafted revision %d:%s '
3945 '(%d:%s also has unknown origin %s)\n')
3882 '(%d:%s also has unknown origin %s)\n')
3946 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3883 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3947 else:
3884 else:
3948 ui.warn(_('skipping already grafted revision %d:%s '
3885 ui.warn(_('skipping already grafted revision %d:%s '
3949 '(%d:%s also has origin %d:%s)\n')
3886 '(%d:%s also has origin %d:%s)\n')
3950 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3887 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3951 revs.remove(ids[n])
3888 revs.remove(ids[n])
3952 elif ctx.hex() in ids:
3889 elif ctx.hex() in ids:
3953 r = ids[ctx.hex()]
3890 r = ids[ctx.hex()]
3954 ui.warn(_('skipping already grafted revision %d:%s '
3891 ui.warn(_('skipping already grafted revision %d:%s '
3955 '(was grafted from %d:%s)\n') %
3892 '(was grafted from %d:%s)\n') %
3956 (r, repo[r], rev, ctx))
3893 (r, repo[r], rev, ctx))
3957 revs.remove(r)
3894 revs.remove(r)
3958 if not revs:
3895 if not revs:
3959 return -1
3896 return -1
3960
3897
3961 for pos, ctx in enumerate(repo.set("%ld", revs)):
3898 for pos, ctx in enumerate(repo.set("%ld", revs)):
3962 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3899 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3963 ctx.description().split('\n', 1)[0])
3900 ctx.description().split('\n', 1)[0])
3964 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3901 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3965 if names:
3902 if names:
3966 desc += ' (%s)' % ' '.join(names)
3903 desc += ' (%s)' % ' '.join(names)
3967 ui.status(_('grafting %s\n') % desc)
3904 ui.status(_('grafting %s\n') % desc)
3968 if opts.get('dry_run'):
3905 if opts.get('dry_run'):
3969 continue
3906 continue
3970
3907
3971 source = ctx.extra().get('source')
3908 source = ctx.extra().get('source')
3972 extra = {}
3909 extra = {}
3973 if source:
3910 if source:
3974 extra['source'] = source
3911 extra['source'] = source
3975 extra['intermediate-source'] = ctx.hex()
3912 extra['intermediate-source'] = ctx.hex()
3976 else:
3913 else:
3977 extra['source'] = ctx.hex()
3914 extra['source'] = ctx.hex()
3978 user = ctx.user()
3915 user = ctx.user()
3979 if opts.get('user'):
3916 if opts.get('user'):
3980 user = opts['user']
3917 user = opts['user']
3981 date = ctx.date()
3918 date = ctx.date()
3982 if opts.get('date'):
3919 if opts.get('date'):
3983 date = opts['date']
3920 date = opts['date']
3984 message = ctx.description()
3921 message = ctx.description()
3985 if opts.get('log'):
3922 if opts.get('log'):
3986 message += '\n(grafted from %s)' % ctx.hex()
3923 message += '\n(grafted from %s)' % ctx.hex()
3987
3924
3988 # we don't merge the first commit when continuing
3925 # we don't merge the first commit when continuing
3989 if not cont:
3926 if not cont:
3990 # perform the graft merge with p1(rev) as 'ancestor'
3927 # perform the graft merge with p1(rev) as 'ancestor'
3991 try:
3928 try:
3992 # ui.forcemerge is an internal variable, do not document
3929 # ui.forcemerge is an internal variable, do not document
3993 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3930 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3994 'graft')
3931 'graft')
3995 stats = mergemod.graft(repo, ctx, ctx.p1(),
3932 stats = mergemod.graft(repo, ctx, ctx.p1(),
3996 ['local', 'graft'])
3933 ['local', 'graft'])
3997 finally:
3934 finally:
3998 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3935 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3999 # report any conflicts
3936 # report any conflicts
4000 if stats and stats[3] > 0:
3937 if stats and stats[3] > 0:
4001 # write out state for --continue
3938 # write out state for --continue
4002 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3939 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4003 repo.vfs.write('graftstate', ''.join(nodelines))
3940 repo.vfs.write('graftstate', ''.join(nodelines))
4004 extra = ''
3941 extra = ''
4005 if opts.get('user'):
3942 if opts.get('user'):
4006 extra += ' --user %s' % util.shellquote(opts['user'])
3943 extra += ' --user %s' % util.shellquote(opts['user'])
4007 if opts.get('date'):
3944 if opts.get('date'):
4008 extra += ' --date %s' % util.shellquote(opts['date'])
3945 extra += ' --date %s' % util.shellquote(opts['date'])
4009 if opts.get('log'):
3946 if opts.get('log'):
4010 extra += ' --log'
3947 extra += ' --log'
4011 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
3948 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
4012 raise error.Abort(
3949 raise error.Abort(
4013 _("unresolved conflicts, can't continue"),
3950 _("unresolved conflicts, can't continue"),
4014 hint=hint)
3951 hint=hint)
4015 else:
3952 else:
4016 cont = False
3953 cont = False
4017
3954
4018 # commit
3955 # commit
4019 node = repo.commit(text=message, user=user,
3956 node = repo.commit(text=message, user=user,
4020 date=date, extra=extra, editor=editor)
3957 date=date, extra=extra, editor=editor)
4021 if node is None:
3958 if node is None:
4022 ui.warn(
3959 ui.warn(
4023 _('note: graft of %d:%s created no changes to commit\n') %
3960 _('note: graft of %d:%s created no changes to commit\n') %
4024 (ctx.rev(), ctx))
3961 (ctx.rev(), ctx))
4025
3962
4026 # remove state when we complete successfully
3963 # remove state when we complete successfully
4027 if not opts.get('dry_run'):
3964 if not opts.get('dry_run'):
4028 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3965 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4029
3966
4030 return 0
3967 return 0
4031
3968
4032 @command('grep',
3969 @command('grep',
4033 [('0', 'print0', None, _('end fields with NUL')),
3970 [('0', 'print0', None, _('end fields with NUL')),
4034 ('', 'all', None, _('print all revisions that match')),
3971 ('', 'all', None, _('print all revisions that match')),
4035 ('a', 'text', None, _('treat all files as text')),
3972 ('a', 'text', None, _('treat all files as text')),
4036 ('f', 'follow', None,
3973 ('f', 'follow', None,
4037 _('follow changeset history,'
3974 _('follow changeset history,'
4038 ' or file history across copies and renames')),
3975 ' or file history across copies and renames')),
4039 ('i', 'ignore-case', None, _('ignore case when matching')),
3976 ('i', 'ignore-case', None, _('ignore case when matching')),
4040 ('l', 'files-with-matches', None,
3977 ('l', 'files-with-matches', None,
4041 _('print only filenames and revisions that match')),
3978 _('print only filenames and revisions that match')),
4042 ('n', 'line-number', None, _('print matching line numbers')),
3979 ('n', 'line-number', None, _('print matching line numbers')),
4043 ('r', 'rev', [],
3980 ('r', 'rev', [],
4044 _('only search files changed within revision range'), _('REV')),
3981 _('only search files changed within revision range'), _('REV')),
4045 ('u', 'user', None, _('list the author (long with -v)')),
3982 ('u', 'user', None, _('list the author (long with -v)')),
4046 ('d', 'date', None, _('list the date (short with -q)')),
3983 ('d', 'date', None, _('list the date (short with -q)')),
4047 ] + formatteropts + walkopts,
3984 ] + formatteropts + walkopts,
4048 _('[OPTION]... PATTERN [FILE]...'),
3985 _('[OPTION]... PATTERN [FILE]...'),
4049 inferrepo=True)
3986 inferrepo=True)
4050 def grep(ui, repo, pattern, *pats, **opts):
3987 def grep(ui, repo, pattern, *pats, **opts):
4051 """search revision history for a pattern in specified files
3988 """search revision history for a pattern in specified files
4052
3989
4053 Search revision history for a regular expression in the specified
3990 Search revision history for a regular expression in the specified
4054 files or the entire project.
3991 files or the entire project.
4055
3992
4056 By default, grep prints the most recent revision number for each
3993 By default, grep prints the most recent revision number for each
4057 file in which it finds a match. To get it to print every revision
3994 file in which it finds a match. To get it to print every revision
4058 that contains a change in match status ("-" for a match that becomes
3995 that contains a change in match status ("-" for a match that becomes
4059 a non-match, or "+" for a non-match that becomes a match), use the
3996 a non-match, or "+" for a non-match that becomes a match), use the
4060 --all flag.
3997 --all flag.
4061
3998
4062 PATTERN can be any Python (roughly Perl-compatible) regular
3999 PATTERN can be any Python (roughly Perl-compatible) regular
4063 expression.
4000 expression.
4064
4001
4065 If no FILEs are specified (and -f/--follow isn't set), all files in
4002 If no FILEs are specified (and -f/--follow isn't set), all files in
4066 the repository are searched, including those that don't exist in the
4003 the repository are searched, including those that don't exist in the
4067 current branch or have been deleted in a prior changeset.
4004 current branch or have been deleted in a prior changeset.
4068
4005
4069 Returns 0 if a match is found, 1 otherwise.
4006 Returns 0 if a match is found, 1 otherwise.
4070 """
4007 """
4071 reflags = re.M
4008 reflags = re.M
4072 if opts.get('ignore_case'):
4009 if opts.get('ignore_case'):
4073 reflags |= re.I
4010 reflags |= re.I
4074 try:
4011 try:
4075 regexp = util.re.compile(pattern, reflags)
4012 regexp = util.re.compile(pattern, reflags)
4076 except re.error as inst:
4013 except re.error as inst:
4077 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4014 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4078 return 1
4015 return 1
4079 sep, eol = ':', '\n'
4016 sep, eol = ':', '\n'
4080 if opts.get('print0'):
4017 if opts.get('print0'):
4081 sep = eol = '\0'
4018 sep = eol = '\0'
4082
4019
4083 getfile = util.lrucachefunc(repo.file)
4020 getfile = util.lrucachefunc(repo.file)
4084
4021
4085 def matchlines(body):
4022 def matchlines(body):
4086 begin = 0
4023 begin = 0
4087 linenum = 0
4024 linenum = 0
4088 while begin < len(body):
4025 while begin < len(body):
4089 match = regexp.search(body, begin)
4026 match = regexp.search(body, begin)
4090 if not match:
4027 if not match:
4091 break
4028 break
4092 mstart, mend = match.span()
4029 mstart, mend = match.span()
4093 linenum += body.count('\n', begin, mstart) + 1
4030 linenum += body.count('\n', begin, mstart) + 1
4094 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4031 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4095 begin = body.find('\n', mend) + 1 or len(body) + 1
4032 begin = body.find('\n', mend) + 1 or len(body) + 1
4096 lend = begin - 1
4033 lend = begin - 1
4097 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4034 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4098
4035
4099 class linestate(object):
4036 class linestate(object):
4100 def __init__(self, line, linenum, colstart, colend):
4037 def __init__(self, line, linenum, colstart, colend):
4101 self.line = line
4038 self.line = line
4102 self.linenum = linenum
4039 self.linenum = linenum
4103 self.colstart = colstart
4040 self.colstart = colstart
4104 self.colend = colend
4041 self.colend = colend
4105
4042
4106 def __hash__(self):
4043 def __hash__(self):
4107 return hash((self.linenum, self.line))
4044 return hash((self.linenum, self.line))
4108
4045
4109 def __eq__(self, other):
4046 def __eq__(self, other):
4110 return self.line == other.line
4047 return self.line == other.line
4111
4048
4112 def findpos(self):
4049 def findpos(self):
4113 """Iterate all (start, end) indices of matches"""
4050 """Iterate all (start, end) indices of matches"""
4114 yield self.colstart, self.colend
4051 yield self.colstart, self.colend
4115 p = self.colend
4052 p = self.colend
4116 while p < len(self.line):
4053 while p < len(self.line):
4117 m = regexp.search(self.line, p)
4054 m = regexp.search(self.line, p)
4118 if not m:
4055 if not m:
4119 break
4056 break
4120 yield m.span()
4057 yield m.span()
4121 p = m.end()
4058 p = m.end()
4122
4059
4123 matches = {}
4060 matches = {}
4124 copies = {}
4061 copies = {}
4125 def grepbody(fn, rev, body):
4062 def grepbody(fn, rev, body):
4126 matches[rev].setdefault(fn, [])
4063 matches[rev].setdefault(fn, [])
4127 m = matches[rev][fn]
4064 m = matches[rev][fn]
4128 for lnum, cstart, cend, line in matchlines(body):
4065 for lnum, cstart, cend, line in matchlines(body):
4129 s = linestate(line, lnum, cstart, cend)
4066 s = linestate(line, lnum, cstart, cend)
4130 m.append(s)
4067 m.append(s)
4131
4068
4132 def difflinestates(a, b):
4069 def difflinestates(a, b):
4133 sm = difflib.SequenceMatcher(None, a, b)
4070 sm = difflib.SequenceMatcher(None, a, b)
4134 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4071 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4135 if tag == 'insert':
4072 if tag == 'insert':
4136 for i in xrange(blo, bhi):
4073 for i in xrange(blo, bhi):
4137 yield ('+', b[i])
4074 yield ('+', b[i])
4138 elif tag == 'delete':
4075 elif tag == 'delete':
4139 for i in xrange(alo, ahi):
4076 for i in xrange(alo, ahi):
4140 yield ('-', a[i])
4077 yield ('-', a[i])
4141 elif tag == 'replace':
4078 elif tag == 'replace':
4142 for i in xrange(alo, ahi):
4079 for i in xrange(alo, ahi):
4143 yield ('-', a[i])
4080 yield ('-', a[i])
4144 for i in xrange(blo, bhi):
4081 for i in xrange(blo, bhi):
4145 yield ('+', b[i])
4082 yield ('+', b[i])
4146
4083
4147 def display(fm, fn, ctx, pstates, states):
4084 def display(fm, fn, ctx, pstates, states):
4148 rev = ctx.rev()
4085 rev = ctx.rev()
4149 if fm.isplain():
4086 if fm.isplain():
4150 formatuser = ui.shortuser
4087 formatuser = ui.shortuser
4151 else:
4088 else:
4152 formatuser = str
4089 formatuser = str
4153 if ui.quiet:
4090 if ui.quiet:
4154 datefmt = '%Y-%m-%d'
4091 datefmt = '%Y-%m-%d'
4155 else:
4092 else:
4156 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4093 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4157 found = False
4094 found = False
4158 @util.cachefunc
4095 @util.cachefunc
4159 def binary():
4096 def binary():
4160 flog = getfile(fn)
4097 flog = getfile(fn)
4161 return util.binary(flog.read(ctx.filenode(fn)))
4098 return util.binary(flog.read(ctx.filenode(fn)))
4162
4099
4163 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4100 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4164 if opts.get('all'):
4101 if opts.get('all'):
4165 iter = difflinestates(pstates, states)
4102 iter = difflinestates(pstates, states)
4166 else:
4103 else:
4167 iter = [('', l) for l in states]
4104 iter = [('', l) for l in states]
4168 for change, l in iter:
4105 for change, l in iter:
4169 fm.startitem()
4106 fm.startitem()
4170 fm.data(node=fm.hexfunc(ctx.node()))
4107 fm.data(node=fm.hexfunc(ctx.node()))
4171 cols = [
4108 cols = [
4172 ('filename', fn, True),
4109 ('filename', fn, True),
4173 ('rev', rev, True),
4110 ('rev', rev, True),
4174 ('linenumber', l.linenum, opts.get('line_number')),
4111 ('linenumber', l.linenum, opts.get('line_number')),
4175 ]
4112 ]
4176 if opts.get('all'):
4113 if opts.get('all'):
4177 cols.append(('change', change, True))
4114 cols.append(('change', change, True))
4178 cols.extend([
4115 cols.extend([
4179 ('user', formatuser(ctx.user()), opts.get('user')),
4116 ('user', formatuser(ctx.user()), opts.get('user')),
4180 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4117 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4181 ])
4118 ])
4182 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4119 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4183 for name, data, cond in cols:
4120 for name, data, cond in cols:
4184 field = fieldnamemap.get(name, name)
4121 field = fieldnamemap.get(name, name)
4185 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4122 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4186 if cond and name != lastcol:
4123 if cond and name != lastcol:
4187 fm.plain(sep, label='grep.sep')
4124 fm.plain(sep, label='grep.sep')
4188 if not opts.get('files_with_matches'):
4125 if not opts.get('files_with_matches'):
4189 fm.plain(sep, label='grep.sep')
4126 fm.plain(sep, label='grep.sep')
4190 if not opts.get('text') and binary():
4127 if not opts.get('text') and binary():
4191 fm.plain(_(" Binary file matches"))
4128 fm.plain(_(" Binary file matches"))
4192 else:
4129 else:
4193 displaymatches(fm.nested('texts'), l)
4130 displaymatches(fm.nested('texts'), l)
4194 fm.plain(eol)
4131 fm.plain(eol)
4195 found = True
4132 found = True
4196 if opts.get('files_with_matches'):
4133 if opts.get('files_with_matches'):
4197 break
4134 break
4198 return found
4135 return found
4199
4136
4200 def displaymatches(fm, l):
4137 def displaymatches(fm, l):
4201 p = 0
4138 p = 0
4202 for s, e in l.findpos():
4139 for s, e in l.findpos():
4203 if p < s:
4140 if p < s:
4204 fm.startitem()
4141 fm.startitem()
4205 fm.write('text', '%s', l.line[p:s])
4142 fm.write('text', '%s', l.line[p:s])
4206 fm.data(matched=False)
4143 fm.data(matched=False)
4207 fm.startitem()
4144 fm.startitem()
4208 fm.write('text', '%s', l.line[s:e], label='grep.match')
4145 fm.write('text', '%s', l.line[s:e], label='grep.match')
4209 fm.data(matched=True)
4146 fm.data(matched=True)
4210 p = e
4147 p = e
4211 if p < len(l.line):
4148 if p < len(l.line):
4212 fm.startitem()
4149 fm.startitem()
4213 fm.write('text', '%s', l.line[p:])
4150 fm.write('text', '%s', l.line[p:])
4214 fm.data(matched=False)
4151 fm.data(matched=False)
4215 fm.end()
4152 fm.end()
4216
4153
4217 skip = {}
4154 skip = {}
4218 revfiles = {}
4155 revfiles = {}
4219 matchfn = scmutil.match(repo[None], pats, opts)
4156 matchfn = scmutil.match(repo[None], pats, opts)
4220 found = False
4157 found = False
4221 follow = opts.get('follow')
4158 follow = opts.get('follow')
4222
4159
4223 def prep(ctx, fns):
4160 def prep(ctx, fns):
4224 rev = ctx.rev()
4161 rev = ctx.rev()
4225 pctx = ctx.p1()
4162 pctx = ctx.p1()
4226 parent = pctx.rev()
4163 parent = pctx.rev()
4227 matches.setdefault(rev, {})
4164 matches.setdefault(rev, {})
4228 matches.setdefault(parent, {})
4165 matches.setdefault(parent, {})
4229 files = revfiles.setdefault(rev, [])
4166 files = revfiles.setdefault(rev, [])
4230 for fn in fns:
4167 for fn in fns:
4231 flog = getfile(fn)
4168 flog = getfile(fn)
4232 try:
4169 try:
4233 fnode = ctx.filenode(fn)
4170 fnode = ctx.filenode(fn)
4234 except error.LookupError:
4171 except error.LookupError:
4235 continue
4172 continue
4236
4173
4237 copied = flog.renamed(fnode)
4174 copied = flog.renamed(fnode)
4238 copy = follow and copied and copied[0]
4175 copy = follow and copied and copied[0]
4239 if copy:
4176 if copy:
4240 copies.setdefault(rev, {})[fn] = copy
4177 copies.setdefault(rev, {})[fn] = copy
4241 if fn in skip:
4178 if fn in skip:
4242 if copy:
4179 if copy:
4243 skip[copy] = True
4180 skip[copy] = True
4244 continue
4181 continue
4245 files.append(fn)
4182 files.append(fn)
4246
4183
4247 if fn not in matches[rev]:
4184 if fn not in matches[rev]:
4248 grepbody(fn, rev, flog.read(fnode))
4185 grepbody(fn, rev, flog.read(fnode))
4249
4186
4250 pfn = copy or fn
4187 pfn = copy or fn
4251 if pfn not in matches[parent]:
4188 if pfn not in matches[parent]:
4252 try:
4189 try:
4253 fnode = pctx.filenode(pfn)
4190 fnode = pctx.filenode(pfn)
4254 grepbody(pfn, parent, flog.read(fnode))
4191 grepbody(pfn, parent, flog.read(fnode))
4255 except error.LookupError:
4192 except error.LookupError:
4256 pass
4193 pass
4257
4194
4258 fm = ui.formatter('grep', opts)
4195 fm = ui.formatter('grep', opts)
4259 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4196 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4260 rev = ctx.rev()
4197 rev = ctx.rev()
4261 parent = ctx.p1().rev()
4198 parent = ctx.p1().rev()
4262 for fn in sorted(revfiles.get(rev, [])):
4199 for fn in sorted(revfiles.get(rev, [])):
4263 states = matches[rev][fn]
4200 states = matches[rev][fn]
4264 copy = copies.get(rev, {}).get(fn)
4201 copy = copies.get(rev, {}).get(fn)
4265 if fn in skip:
4202 if fn in skip:
4266 if copy:
4203 if copy:
4267 skip[copy] = True
4204 skip[copy] = True
4268 continue
4205 continue
4269 pstates = matches.get(parent, {}).get(copy or fn, [])
4206 pstates = matches.get(parent, {}).get(copy or fn, [])
4270 if pstates or states:
4207 if pstates or states:
4271 r = display(fm, fn, ctx, pstates, states)
4208 r = display(fm, fn, ctx, pstates, states)
4272 found = found or r
4209 found = found or r
4273 if r and not opts.get('all'):
4210 if r and not opts.get('all'):
4274 skip[fn] = True
4211 skip[fn] = True
4275 if copy:
4212 if copy:
4276 skip[copy] = True
4213 skip[copy] = True
4277 del matches[rev]
4214 del matches[rev]
4278 del revfiles[rev]
4215 del revfiles[rev]
4279 fm.end()
4216 fm.end()
4280
4217
4281 return not found
4218 return not found
4282
4219
4283 @command('heads',
4220 @command('heads',
4284 [('r', 'rev', '',
4221 [('r', 'rev', '',
4285 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4222 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4286 ('t', 'topo', False, _('show topological heads only')),
4223 ('t', 'topo', False, _('show topological heads only')),
4287 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4224 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4288 ('c', 'closed', False, _('show normal and closed branch heads')),
4225 ('c', 'closed', False, _('show normal and closed branch heads')),
4289 ] + templateopts,
4226 ] + templateopts,
4290 _('[-ct] [-r STARTREV] [REV]...'))
4227 _('[-ct] [-r STARTREV] [REV]...'))
4291 def heads(ui, repo, *branchrevs, **opts):
4228 def heads(ui, repo, *branchrevs, **opts):
4292 """show branch heads
4229 """show branch heads
4293
4230
4294 With no arguments, show all open branch heads in the repository.
4231 With no arguments, show all open branch heads in the repository.
4295 Branch heads are changesets that have no descendants on the
4232 Branch heads are changesets that have no descendants on the
4296 same branch. They are where development generally takes place and
4233 same branch. They are where development generally takes place and
4297 are the usual targets for update and merge operations.
4234 are the usual targets for update and merge operations.
4298
4235
4299 If one or more REVs are given, only open branch heads on the
4236 If one or more REVs are given, only open branch heads on the
4300 branches associated with the specified changesets are shown. This
4237 branches associated with the specified changesets are shown. This
4301 means that you can use :hg:`heads .` to see the heads on the
4238 means that you can use :hg:`heads .` to see the heads on the
4302 currently checked-out branch.
4239 currently checked-out branch.
4303
4240
4304 If -c/--closed is specified, also show branch heads marked closed
4241 If -c/--closed is specified, also show branch heads marked closed
4305 (see :hg:`commit --close-branch`).
4242 (see :hg:`commit --close-branch`).
4306
4243
4307 If STARTREV is specified, only those heads that are descendants of
4244 If STARTREV is specified, only those heads that are descendants of
4308 STARTREV will be displayed.
4245 STARTREV will be displayed.
4309
4246
4310 If -t/--topo is specified, named branch mechanics will be ignored and only
4247 If -t/--topo is specified, named branch mechanics will be ignored and only
4311 topological heads (changesets with no children) will be shown.
4248 topological heads (changesets with no children) will be shown.
4312
4249
4313 Returns 0 if matching heads are found, 1 if not.
4250 Returns 0 if matching heads are found, 1 if not.
4314 """
4251 """
4315
4252
4316 start = None
4253 start = None
4317 if 'rev' in opts:
4254 if 'rev' in opts:
4318 start = scmutil.revsingle(repo, opts['rev'], None).node()
4255 start = scmutil.revsingle(repo, opts['rev'], None).node()
4319
4256
4320 if opts.get('topo'):
4257 if opts.get('topo'):
4321 heads = [repo[h] for h in repo.heads(start)]
4258 heads = [repo[h] for h in repo.heads(start)]
4322 else:
4259 else:
4323 heads = []
4260 heads = []
4324 for branch in repo.branchmap():
4261 for branch in repo.branchmap():
4325 heads += repo.branchheads(branch, start, opts.get('closed'))
4262 heads += repo.branchheads(branch, start, opts.get('closed'))
4326 heads = [repo[h] for h in heads]
4263 heads = [repo[h] for h in heads]
4327
4264
4328 if branchrevs:
4265 if branchrevs:
4329 branches = set(repo[br].branch() for br in branchrevs)
4266 branches = set(repo[br].branch() for br in branchrevs)
4330 heads = [h for h in heads if h.branch() in branches]
4267 heads = [h for h in heads if h.branch() in branches]
4331
4268
4332 if opts.get('active') and branchrevs:
4269 if opts.get('active') and branchrevs:
4333 dagheads = repo.heads(start)
4270 dagheads = repo.heads(start)
4334 heads = [h for h in heads if h.node() in dagheads]
4271 heads = [h for h in heads if h.node() in dagheads]
4335
4272
4336 if branchrevs:
4273 if branchrevs:
4337 haveheads = set(h.branch() for h in heads)
4274 haveheads = set(h.branch() for h in heads)
4338 if branches - haveheads:
4275 if branches - haveheads:
4339 headless = ', '.join(b for b in branches - haveheads)
4276 headless = ', '.join(b for b in branches - haveheads)
4340 msg = _('no open branch heads found on branches %s')
4277 msg = _('no open branch heads found on branches %s')
4341 if opts.get('rev'):
4278 if opts.get('rev'):
4342 msg += _(' (started at %s)') % opts['rev']
4279 msg += _(' (started at %s)') % opts['rev']
4343 ui.warn((msg + '\n') % headless)
4280 ui.warn((msg + '\n') % headless)
4344
4281
4345 if not heads:
4282 if not heads:
4346 return 1
4283 return 1
4347
4284
4348 heads = sorted(heads, key=lambda x: -x.rev())
4285 heads = sorted(heads, key=lambda x: -x.rev())
4349 displayer = cmdutil.show_changeset(ui, repo, opts)
4286 displayer = cmdutil.show_changeset(ui, repo, opts)
4350 for ctx in heads:
4287 for ctx in heads:
4351 displayer.show(ctx)
4288 displayer.show(ctx)
4352 displayer.close()
4289 displayer.close()
4353
4290
4354 @command('help',
4291 @command('help',
4355 [('e', 'extension', None, _('show only help for extensions')),
4292 [('e', 'extension', None, _('show only help for extensions')),
4356 ('c', 'command', None, _('show only help for commands')),
4293 ('c', 'command', None, _('show only help for commands')),
4357 ('k', 'keyword', None, _('show topics matching keyword')),
4294 ('k', 'keyword', None, _('show topics matching keyword')),
4358 ('s', 'system', [], _('show help for specific platform(s)')),
4295 ('s', 'system', [], _('show help for specific platform(s)')),
4359 ],
4296 ],
4360 _('[-ecks] [TOPIC]'),
4297 _('[-ecks] [TOPIC]'),
4361 norepo=True)
4298 norepo=True)
4362 def help_(ui, name=None, **opts):
4299 def help_(ui, name=None, **opts):
4363 """show help for a given topic or a help overview
4300 """show help for a given topic or a help overview
4364
4301
4365 With no arguments, print a list of commands with short help messages.
4302 With no arguments, print a list of commands with short help messages.
4366
4303
4367 Given a topic, extension, or command name, print help for that
4304 Given a topic, extension, or command name, print help for that
4368 topic.
4305 topic.
4369
4306
4370 Returns 0 if successful.
4307 Returns 0 if successful.
4371 """
4308 """
4372
4309
4373 textwidth = ui.configint('ui', 'textwidth', 78)
4310 textwidth = ui.configint('ui', 'textwidth', 78)
4374 termwidth = ui.termwidth() - 2
4311 termwidth = ui.termwidth() - 2
4375 if textwidth <= 0 or termwidth < textwidth:
4312 if textwidth <= 0 or termwidth < textwidth:
4376 textwidth = termwidth
4313 textwidth = termwidth
4377
4314
4378 keep = opts.get('system') or []
4315 keep = opts.get('system') or []
4379 if len(keep) == 0:
4316 if len(keep) == 0:
4380 if sys.platform.startswith('win'):
4317 if sys.platform.startswith('win'):
4381 keep.append('windows')
4318 keep.append('windows')
4382 elif sys.platform == 'OpenVMS':
4319 elif sys.platform == 'OpenVMS':
4383 keep.append('vms')
4320 keep.append('vms')
4384 elif sys.platform == 'plan9':
4321 elif sys.platform == 'plan9':
4385 keep.append('plan9')
4322 keep.append('plan9')
4386 else:
4323 else:
4387 keep.append('unix')
4324 keep.append('unix')
4388 keep.append(sys.platform.lower())
4325 keep.append(sys.platform.lower())
4389 if ui.verbose:
4326 if ui.verbose:
4390 keep.append('verbose')
4327 keep.append('verbose')
4391
4328
4392 section = None
4329 section = None
4393 subtopic = None
4330 subtopic = None
4394 if name and '.' in name:
4331 if name and '.' in name:
4395 name, remaining = name.split('.', 1)
4332 name, remaining = name.split('.', 1)
4396 remaining = encoding.lower(remaining)
4333 remaining = encoding.lower(remaining)
4397 if '.' in remaining:
4334 if '.' in remaining:
4398 subtopic, section = remaining.split('.', 1)
4335 subtopic, section = remaining.split('.', 1)
4399 else:
4336 else:
4400 if name in help.subtopics:
4337 if name in help.subtopics:
4401 subtopic = remaining
4338 subtopic = remaining
4402 else:
4339 else:
4403 section = remaining
4340 section = remaining
4404
4341
4405 text = help.help_(ui, name, subtopic=subtopic, **opts)
4342 text = help.help_(ui, name, subtopic=subtopic, **opts)
4406
4343
4407 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4344 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4408 section=section)
4345 section=section)
4409
4346
4410 # We could have been given a weird ".foo" section without a name
4347 # We could have been given a weird ".foo" section without a name
4411 # to look for, or we could have simply failed to found "foo.bar"
4348 # to look for, or we could have simply failed to found "foo.bar"
4412 # because bar isn't a section of foo
4349 # because bar isn't a section of foo
4413 if section and not (formatted and name):
4350 if section and not (formatted and name):
4414 raise error.Abort(_("help section not found"))
4351 raise error.Abort(_("help section not found"))
4415
4352
4416 if 'verbose' in pruned:
4353 if 'verbose' in pruned:
4417 keep.append('omitted')
4354 keep.append('omitted')
4418 else:
4355 else:
4419 keep.append('notomitted')
4356 keep.append('notomitted')
4420 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4357 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4421 section=section)
4358 section=section)
4422 ui.write(formatted)
4359 ui.write(formatted)
4423
4360
4424
4361
4425 @command('identify|id',
4362 @command('identify|id',
4426 [('r', 'rev', '',
4363 [('r', 'rev', '',
4427 _('identify the specified revision'), _('REV')),
4364 _('identify the specified revision'), _('REV')),
4428 ('n', 'num', None, _('show local revision number')),
4365 ('n', 'num', None, _('show local revision number')),
4429 ('i', 'id', None, _('show global revision id')),
4366 ('i', 'id', None, _('show global revision id')),
4430 ('b', 'branch', None, _('show branch')),
4367 ('b', 'branch', None, _('show branch')),
4431 ('t', 'tags', None, _('show tags')),
4368 ('t', 'tags', None, _('show tags')),
4432 ('B', 'bookmarks', None, _('show bookmarks')),
4369 ('B', 'bookmarks', None, _('show bookmarks')),
4433 ] + remoteopts,
4370 ] + remoteopts,
4434 _('[-nibtB] [-r REV] [SOURCE]'),
4371 _('[-nibtB] [-r REV] [SOURCE]'),
4435 optionalrepo=True)
4372 optionalrepo=True)
4436 def identify(ui, repo, source=None, rev=None,
4373 def identify(ui, repo, source=None, rev=None,
4437 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4374 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4438 """identify the working directory or specified revision
4375 """identify the working directory or specified revision
4439
4376
4440 Print a summary identifying the repository state at REV using one or
4377 Print a summary identifying the repository state at REV using one or
4441 two parent hash identifiers, followed by a "+" if the working
4378 two parent hash identifiers, followed by a "+" if the working
4442 directory has uncommitted changes, the branch name (if not default),
4379 directory has uncommitted changes, the branch name (if not default),
4443 a list of tags, and a list of bookmarks.
4380 a list of tags, and a list of bookmarks.
4444
4381
4445 When REV is not given, print a summary of the current state of the
4382 When REV is not given, print a summary of the current state of the
4446 repository.
4383 repository.
4447
4384
4448 Specifying a path to a repository root or Mercurial bundle will
4385 Specifying a path to a repository root or Mercurial bundle will
4449 cause lookup to operate on that repository/bundle.
4386 cause lookup to operate on that repository/bundle.
4450
4387
4451 .. container:: verbose
4388 .. container:: verbose
4452
4389
4453 Examples:
4390 Examples:
4454
4391
4455 - generate a build identifier for the working directory::
4392 - generate a build identifier for the working directory::
4456
4393
4457 hg id --id > build-id.dat
4394 hg id --id > build-id.dat
4458
4395
4459 - find the revision corresponding to a tag::
4396 - find the revision corresponding to a tag::
4460
4397
4461 hg id -n -r 1.3
4398 hg id -n -r 1.3
4462
4399
4463 - check the most recent revision of a remote repository::
4400 - check the most recent revision of a remote repository::
4464
4401
4465 hg id -r tip https://www.mercurial-scm.org/repo/hg/
4402 hg id -r tip https://www.mercurial-scm.org/repo/hg/
4466
4403
4467 See :hg:`log` for generating more information about specific revisions,
4404 See :hg:`log` for generating more information about specific revisions,
4468 including full hash identifiers.
4405 including full hash identifiers.
4469
4406
4470 Returns 0 if successful.
4407 Returns 0 if successful.
4471 """
4408 """
4472
4409
4473 if not repo and not source:
4410 if not repo and not source:
4474 raise error.Abort(_("there is no Mercurial repository here "
4411 raise error.Abort(_("there is no Mercurial repository here "
4475 "(.hg not found)"))
4412 "(.hg not found)"))
4476
4413
4477 if ui.debugflag:
4414 if ui.debugflag:
4478 hexfunc = hex
4415 hexfunc = hex
4479 else:
4416 else:
4480 hexfunc = short
4417 hexfunc = short
4481 default = not (num or id or branch or tags or bookmarks)
4418 default = not (num or id or branch or tags or bookmarks)
4482 output = []
4419 output = []
4483 revs = []
4420 revs = []
4484
4421
4485 if source:
4422 if source:
4486 source, branches = hg.parseurl(ui.expandpath(source))
4423 source, branches = hg.parseurl(ui.expandpath(source))
4487 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4424 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4488 repo = peer.local()
4425 repo = peer.local()
4489 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4426 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4490
4427
4491 if not repo:
4428 if not repo:
4492 if num or branch or tags:
4429 if num or branch or tags:
4493 raise error.Abort(
4430 raise error.Abort(
4494 _("can't query remote revision number, branch, or tags"))
4431 _("can't query remote revision number, branch, or tags"))
4495 if not rev and revs:
4432 if not rev and revs:
4496 rev = revs[0]
4433 rev = revs[0]
4497 if not rev:
4434 if not rev:
4498 rev = "tip"
4435 rev = "tip"
4499
4436
4500 remoterev = peer.lookup(rev)
4437 remoterev = peer.lookup(rev)
4501 if default or id:
4438 if default or id:
4502 output = [hexfunc(remoterev)]
4439 output = [hexfunc(remoterev)]
4503
4440
4504 def getbms():
4441 def getbms():
4505 bms = []
4442 bms = []
4506
4443
4507 if 'bookmarks' in peer.listkeys('namespaces'):
4444 if 'bookmarks' in peer.listkeys('namespaces'):
4508 hexremoterev = hex(remoterev)
4445 hexremoterev = hex(remoterev)
4509 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4446 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4510 if bmr == hexremoterev]
4447 if bmr == hexremoterev]
4511
4448
4512 return sorted(bms)
4449 return sorted(bms)
4513
4450
4514 if bookmarks:
4451 if bookmarks:
4515 output.extend(getbms())
4452 output.extend(getbms())
4516 elif default and not ui.quiet:
4453 elif default and not ui.quiet:
4517 # multiple bookmarks for a single parent separated by '/'
4454 # multiple bookmarks for a single parent separated by '/'
4518 bm = '/'.join(getbms())
4455 bm = '/'.join(getbms())
4519 if bm:
4456 if bm:
4520 output.append(bm)
4457 output.append(bm)
4521 else:
4458 else:
4522 ctx = scmutil.revsingle(repo, rev, None)
4459 ctx = scmutil.revsingle(repo, rev, None)
4523
4460
4524 if ctx.rev() is None:
4461 if ctx.rev() is None:
4525 ctx = repo[None]
4462 ctx = repo[None]
4526 parents = ctx.parents()
4463 parents = ctx.parents()
4527 taglist = []
4464 taglist = []
4528 for p in parents:
4465 for p in parents:
4529 taglist.extend(p.tags())
4466 taglist.extend(p.tags())
4530
4467
4531 changed = ""
4468 changed = ""
4532 if default or id or num:
4469 if default or id or num:
4533 if (any(repo.status())
4470 if (any(repo.status())
4534 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4471 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4535 changed = '+'
4472 changed = '+'
4536 if default or id:
4473 if default or id:
4537 output = ["%s%s" %
4474 output = ["%s%s" %
4538 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4475 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4539 if num:
4476 if num:
4540 output.append("%s%s" %
4477 output.append("%s%s" %
4541 ('+'.join([str(p.rev()) for p in parents]), changed))
4478 ('+'.join([str(p.rev()) for p in parents]), changed))
4542 else:
4479 else:
4543 if default or id:
4480 if default or id:
4544 output = [hexfunc(ctx.node())]
4481 output = [hexfunc(ctx.node())]
4545 if num:
4482 if num:
4546 output.append(str(ctx.rev()))
4483 output.append(str(ctx.rev()))
4547 taglist = ctx.tags()
4484 taglist = ctx.tags()
4548
4485
4549 if default and not ui.quiet:
4486 if default and not ui.quiet:
4550 b = ctx.branch()
4487 b = ctx.branch()
4551 if b != 'default':
4488 if b != 'default':
4552 output.append("(%s)" % b)
4489 output.append("(%s)" % b)
4553
4490
4554 # multiple tags for a single parent separated by '/'
4491 # multiple tags for a single parent separated by '/'
4555 t = '/'.join(taglist)
4492 t = '/'.join(taglist)
4556 if t:
4493 if t:
4557 output.append(t)
4494 output.append(t)
4558
4495
4559 # multiple bookmarks for a single parent separated by '/'
4496 # multiple bookmarks for a single parent separated by '/'
4560 bm = '/'.join(ctx.bookmarks())
4497 bm = '/'.join(ctx.bookmarks())
4561 if bm:
4498 if bm:
4562 output.append(bm)
4499 output.append(bm)
4563 else:
4500 else:
4564 if branch:
4501 if branch:
4565 output.append(ctx.branch())
4502 output.append(ctx.branch())
4566
4503
4567 if tags:
4504 if tags:
4568 output.extend(taglist)
4505 output.extend(taglist)
4569
4506
4570 if bookmarks:
4507 if bookmarks:
4571 output.extend(ctx.bookmarks())
4508 output.extend(ctx.bookmarks())
4572
4509
4573 ui.write("%s\n" % ' '.join(output))
4510 ui.write("%s\n" % ' '.join(output))
4574
4511
4575 @command('import|patch',
4512 @command('import|patch',
4576 [('p', 'strip', 1,
4513 [('p', 'strip', 1,
4577 _('directory strip option for patch. This has the same '
4514 _('directory strip option for patch. This has the same '
4578 'meaning as the corresponding patch option'), _('NUM')),
4515 'meaning as the corresponding patch option'), _('NUM')),
4579 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4516 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4580 ('e', 'edit', False, _('invoke editor on commit messages')),
4517 ('e', 'edit', False, _('invoke editor on commit messages')),
4581 ('f', 'force', None,
4518 ('f', 'force', None,
4582 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4519 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4583 ('', 'no-commit', None,
4520 ('', 'no-commit', None,
4584 _("don't commit, just update the working directory")),
4521 _("don't commit, just update the working directory")),
4585 ('', 'bypass', None,
4522 ('', 'bypass', None,
4586 _("apply patch without touching the working directory")),
4523 _("apply patch without touching the working directory")),
4587 ('', 'partial', None,
4524 ('', 'partial', None,
4588 _('commit even if some hunks fail')),
4525 _('commit even if some hunks fail')),
4589 ('', 'exact', None,
4526 ('', 'exact', None,
4590 _('abort if patch would apply lossily')),
4527 _('abort if patch would apply lossily')),
4591 ('', 'prefix', '',
4528 ('', 'prefix', '',
4592 _('apply patch to subdirectory'), _('DIR')),
4529 _('apply patch to subdirectory'), _('DIR')),
4593 ('', 'import-branch', None,
4530 ('', 'import-branch', None,
4594 _('use any branch information in patch (implied by --exact)'))] +
4531 _('use any branch information in patch (implied by --exact)'))] +
4595 commitopts + commitopts2 + similarityopts,
4532 commitopts + commitopts2 + similarityopts,
4596 _('[OPTION]... PATCH...'))
4533 _('[OPTION]... PATCH...'))
4597 def import_(ui, repo, patch1=None, *patches, **opts):
4534 def import_(ui, repo, patch1=None, *patches, **opts):
4598 """import an ordered set of patches
4535 """import an ordered set of patches
4599
4536
4600 Import a list of patches and commit them individually (unless
4537 Import a list of patches and commit them individually (unless
4601 --no-commit is specified).
4538 --no-commit is specified).
4602
4539
4603 To read a patch from standard input, use "-" as the patch name. If
4540 To read a patch from standard input, use "-" as the patch name. If
4604 a URL is specified, the patch will be downloaded from there.
4541 a URL is specified, the patch will be downloaded from there.
4605
4542
4606 Import first applies changes to the working directory (unless
4543 Import first applies changes to the working directory (unless
4607 --bypass is specified), import will abort if there are outstanding
4544 --bypass is specified), import will abort if there are outstanding
4608 changes.
4545 changes.
4609
4546
4610 Use --bypass to apply and commit patches directly to the
4547 Use --bypass to apply and commit patches directly to the
4611 repository, without affecting the working directory. Without
4548 repository, without affecting the working directory. Without
4612 --exact, patches will be applied on top of the working directory
4549 --exact, patches will be applied on top of the working directory
4613 parent revision.
4550 parent revision.
4614
4551
4615 You can import a patch straight from a mail message. Even patches
4552 You can import a patch straight from a mail message. Even patches
4616 as attachments work (to use the body part, it must have type
4553 as attachments work (to use the body part, it must have type
4617 text/plain or text/x-patch). From and Subject headers of email
4554 text/plain or text/x-patch). From and Subject headers of email
4618 message are used as default committer and commit message. All
4555 message are used as default committer and commit message. All
4619 text/plain body parts before first diff are added to the commit
4556 text/plain body parts before first diff are added to the commit
4620 message.
4557 message.
4621
4558
4622 If the imported patch was generated by :hg:`export`, user and
4559 If the imported patch was generated by :hg:`export`, user and
4623 description from patch override values from message headers and
4560 description from patch override values from message headers and
4624 body. Values given on command line with -m/--message and -u/--user
4561 body. Values given on command line with -m/--message and -u/--user
4625 override these.
4562 override these.
4626
4563
4627 If --exact is specified, import will set the working directory to
4564 If --exact is specified, import will set the working directory to
4628 the parent of each patch before applying it, and will abort if the
4565 the parent of each patch before applying it, and will abort if the
4629 resulting changeset has a different ID than the one recorded in
4566 resulting changeset has a different ID than the one recorded in
4630 the patch. This will guard against various ways that portable
4567 the patch. This will guard against various ways that portable
4631 patch formats and mail systems might fail to transfer Mercurial
4568 patch formats and mail systems might fail to transfer Mercurial
4632 data or metadata. See :hg:`bundle` for lossless transmission.
4569 data or metadata. See :hg:`bundle` for lossless transmission.
4633
4570
4634 Use --partial to ensure a changeset will be created from the patch
4571 Use --partial to ensure a changeset will be created from the patch
4635 even if some hunks fail to apply. Hunks that fail to apply will be
4572 even if some hunks fail to apply. Hunks that fail to apply will be
4636 written to a <target-file>.rej file. Conflicts can then be resolved
4573 written to a <target-file>.rej file. Conflicts can then be resolved
4637 by hand before :hg:`commit --amend` is run to update the created
4574 by hand before :hg:`commit --amend` is run to update the created
4638 changeset. This flag exists to let people import patches that
4575 changeset. This flag exists to let people import patches that
4639 partially apply without losing the associated metadata (author,
4576 partially apply without losing the associated metadata (author,
4640 date, description, ...).
4577 date, description, ...).
4641
4578
4642 .. note::
4579 .. note::
4643
4580
4644 When no hunks apply cleanly, :hg:`import --partial` will create
4581 When no hunks apply cleanly, :hg:`import --partial` will create
4645 an empty changeset, importing only the patch metadata.
4582 an empty changeset, importing only the patch metadata.
4646
4583
4647 With -s/--similarity, hg will attempt to discover renames and
4584 With -s/--similarity, hg will attempt to discover renames and
4648 copies in the patch in the same way as :hg:`addremove`.
4585 copies in the patch in the same way as :hg:`addremove`.
4649
4586
4650 It is possible to use external patch programs to perform the patch
4587 It is possible to use external patch programs to perform the patch
4651 by setting the ``ui.patch`` configuration option. For the default
4588 by setting the ``ui.patch`` configuration option. For the default
4652 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4589 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4653 See :hg:`help config` for more information about configuration
4590 See :hg:`help config` for more information about configuration
4654 files and how to use these options.
4591 files and how to use these options.
4655
4592
4656 See :hg:`help dates` for a list of formats valid for -d/--date.
4593 See :hg:`help dates` for a list of formats valid for -d/--date.
4657
4594
4658 .. container:: verbose
4595 .. container:: verbose
4659
4596
4660 Examples:
4597 Examples:
4661
4598
4662 - import a traditional patch from a website and detect renames::
4599 - import a traditional patch from a website and detect renames::
4663
4600
4664 hg import -s 80 http://example.com/bugfix.patch
4601 hg import -s 80 http://example.com/bugfix.patch
4665
4602
4666 - import a changeset from an hgweb server::
4603 - import a changeset from an hgweb server::
4667
4604
4668 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4605 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4669
4606
4670 - import all the patches in an Unix-style mbox::
4607 - import all the patches in an Unix-style mbox::
4671
4608
4672 hg import incoming-patches.mbox
4609 hg import incoming-patches.mbox
4673
4610
4674 - attempt to exactly restore an exported changeset (not always
4611 - attempt to exactly restore an exported changeset (not always
4675 possible)::
4612 possible)::
4676
4613
4677 hg import --exact proposed-fix.patch
4614 hg import --exact proposed-fix.patch
4678
4615
4679 - use an external tool to apply a patch which is too fuzzy for
4616 - use an external tool to apply a patch which is too fuzzy for
4680 the default internal tool.
4617 the default internal tool.
4681
4618
4682 hg import --config ui.patch="patch --merge" fuzzy.patch
4619 hg import --config ui.patch="patch --merge" fuzzy.patch
4683
4620
4684 - change the default fuzzing from 2 to a less strict 7
4621 - change the default fuzzing from 2 to a less strict 7
4685
4622
4686 hg import --config ui.fuzz=7 fuzz.patch
4623 hg import --config ui.fuzz=7 fuzz.patch
4687
4624
4688 Returns 0 on success, 1 on partial success (see --partial).
4625 Returns 0 on success, 1 on partial success (see --partial).
4689 """
4626 """
4690
4627
4691 if not patch1:
4628 if not patch1:
4692 raise error.Abort(_('need at least one patch to import'))
4629 raise error.Abort(_('need at least one patch to import'))
4693
4630
4694 patches = (patch1,) + patches
4631 patches = (patch1,) + patches
4695
4632
4696 date = opts.get('date')
4633 date = opts.get('date')
4697 if date:
4634 if date:
4698 opts['date'] = util.parsedate(date)
4635 opts['date'] = util.parsedate(date)
4699
4636
4700 exact = opts.get('exact')
4637 exact = opts.get('exact')
4701 update = not opts.get('bypass')
4638 update = not opts.get('bypass')
4702 if not update and opts.get('no_commit'):
4639 if not update and opts.get('no_commit'):
4703 raise error.Abort(_('cannot use --no-commit with --bypass'))
4640 raise error.Abort(_('cannot use --no-commit with --bypass'))
4704 try:
4641 try:
4705 sim = float(opts.get('similarity') or 0)
4642 sim = float(opts.get('similarity') or 0)
4706 except ValueError:
4643 except ValueError:
4707 raise error.Abort(_('similarity must be a number'))
4644 raise error.Abort(_('similarity must be a number'))
4708 if sim < 0 or sim > 100:
4645 if sim < 0 or sim > 100:
4709 raise error.Abort(_('similarity must be between 0 and 100'))
4646 raise error.Abort(_('similarity must be between 0 and 100'))
4710 if sim and not update:
4647 if sim and not update:
4711 raise error.Abort(_('cannot use --similarity with --bypass'))
4648 raise error.Abort(_('cannot use --similarity with --bypass'))
4712 if exact:
4649 if exact:
4713 if opts.get('edit'):
4650 if opts.get('edit'):
4714 raise error.Abort(_('cannot use --exact with --edit'))
4651 raise error.Abort(_('cannot use --exact with --edit'))
4715 if opts.get('prefix'):
4652 if opts.get('prefix'):
4716 raise error.Abort(_('cannot use --exact with --prefix'))
4653 raise error.Abort(_('cannot use --exact with --prefix'))
4717
4654
4718 base = opts["base"]
4655 base = opts["base"]
4719 wlock = dsguard = lock = tr = None
4656 wlock = dsguard = lock = tr = None
4720 msgs = []
4657 msgs = []
4721 ret = 0
4658 ret = 0
4722
4659
4723
4660
4724 try:
4661 try:
4725 wlock = repo.wlock()
4662 wlock = repo.wlock()
4726
4663
4727 if update:
4664 if update:
4728 cmdutil.checkunfinished(repo)
4665 cmdutil.checkunfinished(repo)
4729 if (exact or not opts.get('force')):
4666 if (exact or not opts.get('force')):
4730 cmdutil.bailifchanged(repo)
4667 cmdutil.bailifchanged(repo)
4731
4668
4732 if not opts.get('no_commit'):
4669 if not opts.get('no_commit'):
4733 lock = repo.lock()
4670 lock = repo.lock()
4734 tr = repo.transaction('import')
4671 tr = repo.transaction('import')
4735 else:
4672 else:
4736 dsguard = dirstateguard.dirstateguard(repo, 'import')
4673 dsguard = dirstateguard.dirstateguard(repo, 'import')
4737 parents = repo[None].parents()
4674 parents = repo[None].parents()
4738 for patchurl in patches:
4675 for patchurl in patches:
4739 if patchurl == '-':
4676 if patchurl == '-':
4740 ui.status(_('applying patch from stdin\n'))
4677 ui.status(_('applying patch from stdin\n'))
4741 patchfile = ui.fin
4678 patchfile = ui.fin
4742 patchurl = 'stdin' # for error message
4679 patchurl = 'stdin' # for error message
4743 else:
4680 else:
4744 patchurl = os.path.join(base, patchurl)
4681 patchurl = os.path.join(base, patchurl)
4745 ui.status(_('applying %s\n') % patchurl)
4682 ui.status(_('applying %s\n') % patchurl)
4746 patchfile = hg.openpath(ui, patchurl)
4683 patchfile = hg.openpath(ui, patchurl)
4747
4684
4748 haspatch = False
4685 haspatch = False
4749 for hunk in patch.split(patchfile):
4686 for hunk in patch.split(patchfile):
4750 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4687 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4751 parents, opts,
4688 parents, opts,
4752 msgs, hg.clean)
4689 msgs, hg.clean)
4753 if msg:
4690 if msg:
4754 haspatch = True
4691 haspatch = True
4755 ui.note(msg + '\n')
4692 ui.note(msg + '\n')
4756 if update or exact:
4693 if update or exact:
4757 parents = repo[None].parents()
4694 parents = repo[None].parents()
4758 else:
4695 else:
4759 parents = [repo[node]]
4696 parents = [repo[node]]
4760 if rej:
4697 if rej:
4761 ui.write_err(_("patch applied partially\n"))
4698 ui.write_err(_("patch applied partially\n"))
4762 ui.write_err(_("(fix the .rej files and run "
4699 ui.write_err(_("(fix the .rej files and run "
4763 "`hg commit --amend`)\n"))
4700 "`hg commit --amend`)\n"))
4764 ret = 1
4701 ret = 1
4765 break
4702 break
4766
4703
4767 if not haspatch:
4704 if not haspatch:
4768 raise error.Abort(_('%s: no diffs found') % patchurl)
4705 raise error.Abort(_('%s: no diffs found') % patchurl)
4769
4706
4770 if tr:
4707 if tr:
4771 tr.close()
4708 tr.close()
4772 if msgs:
4709 if msgs:
4773 repo.savecommitmessage('\n* * *\n'.join(msgs))
4710 repo.savecommitmessage('\n* * *\n'.join(msgs))
4774 if dsguard:
4711 if dsguard:
4775 dsguard.close()
4712 dsguard.close()
4776 return ret
4713 return ret
4777 finally:
4714 finally:
4778 if tr:
4715 if tr:
4779 tr.release()
4716 tr.release()
4780 release(lock, dsguard, wlock)
4717 release(lock, dsguard, wlock)
4781
4718
4782 @command('incoming|in',
4719 @command('incoming|in',
4783 [('f', 'force', None,
4720 [('f', 'force', None,
4784 _('run even if remote repository is unrelated')),
4721 _('run even if remote repository is unrelated')),
4785 ('n', 'newest-first', None, _('show newest record first')),
4722 ('n', 'newest-first', None, _('show newest record first')),
4786 ('', 'bundle', '',
4723 ('', 'bundle', '',
4787 _('file to store the bundles into'), _('FILE')),
4724 _('file to store the bundles into'), _('FILE')),
4788 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4725 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4789 ('B', 'bookmarks', False, _("compare bookmarks")),
4726 ('B', 'bookmarks', False, _("compare bookmarks")),
4790 ('b', 'branch', [],
4727 ('b', 'branch', [],
4791 _('a specific branch you would like to pull'), _('BRANCH')),
4728 _('a specific branch you would like to pull'), _('BRANCH')),
4792 ] + logopts + remoteopts + subrepoopts,
4729 ] + logopts + remoteopts + subrepoopts,
4793 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4730 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4794 def incoming(ui, repo, source="default", **opts):
4731 def incoming(ui, repo, source="default", **opts):
4795 """show new changesets found in source
4732 """show new changesets found in source
4796
4733
4797 Show new changesets found in the specified path/URL or the default
4734 Show new changesets found in the specified path/URL or the default
4798 pull location. These are the changesets that would have been pulled
4735 pull location. These are the changesets that would have been pulled
4799 if a pull at the time you issued this command.
4736 if a pull at the time you issued this command.
4800
4737
4801 See pull for valid source format details.
4738 See pull for valid source format details.
4802
4739
4803 .. container:: verbose
4740 .. container:: verbose
4804
4741
4805 With -B/--bookmarks, the result of bookmark comparison between
4742 With -B/--bookmarks, the result of bookmark comparison between
4806 local and remote repositories is displayed. With -v/--verbose,
4743 local and remote repositories is displayed. With -v/--verbose,
4807 status is also displayed for each bookmark like below::
4744 status is also displayed for each bookmark like below::
4808
4745
4809 BM1 01234567890a added
4746 BM1 01234567890a added
4810 BM2 1234567890ab advanced
4747 BM2 1234567890ab advanced
4811 BM3 234567890abc diverged
4748 BM3 234567890abc diverged
4812 BM4 34567890abcd changed
4749 BM4 34567890abcd changed
4813
4750
4814 The action taken locally when pulling depends on the
4751 The action taken locally when pulling depends on the
4815 status of each bookmark:
4752 status of each bookmark:
4816
4753
4817 :``added``: pull will create it
4754 :``added``: pull will create it
4818 :``advanced``: pull will update it
4755 :``advanced``: pull will update it
4819 :``diverged``: pull will create a divergent bookmark
4756 :``diverged``: pull will create a divergent bookmark
4820 :``changed``: result depends on remote changesets
4757 :``changed``: result depends on remote changesets
4821
4758
4822 From the point of view of pulling behavior, bookmark
4759 From the point of view of pulling behavior, bookmark
4823 existing only in the remote repository are treated as ``added``,
4760 existing only in the remote repository are treated as ``added``,
4824 even if it is in fact locally deleted.
4761 even if it is in fact locally deleted.
4825
4762
4826 .. container:: verbose
4763 .. container:: verbose
4827
4764
4828 For remote repository, using --bundle avoids downloading the
4765 For remote repository, using --bundle avoids downloading the
4829 changesets twice if the incoming is followed by a pull.
4766 changesets twice if the incoming is followed by a pull.
4830
4767
4831 Examples:
4768 Examples:
4832
4769
4833 - show incoming changes with patches and full description::
4770 - show incoming changes with patches and full description::
4834
4771
4835 hg incoming -vp
4772 hg incoming -vp
4836
4773
4837 - show incoming changes excluding merges, store a bundle::
4774 - show incoming changes excluding merges, store a bundle::
4838
4775
4839 hg in -vpM --bundle incoming.hg
4776 hg in -vpM --bundle incoming.hg
4840 hg pull incoming.hg
4777 hg pull incoming.hg
4841
4778
4842 - briefly list changes inside a bundle::
4779 - briefly list changes inside a bundle::
4843
4780
4844 hg in changes.hg -T "{desc|firstline}\\n"
4781 hg in changes.hg -T "{desc|firstline}\\n"
4845
4782
4846 Returns 0 if there are incoming changes, 1 otherwise.
4783 Returns 0 if there are incoming changes, 1 otherwise.
4847 """
4784 """
4848 if opts.get('graph'):
4785 if opts.get('graph'):
4849 cmdutil.checkunsupportedgraphflags([], opts)
4786 cmdutil.checkunsupportedgraphflags([], opts)
4850 def display(other, chlist, displayer):
4787 def display(other, chlist, displayer):
4851 revdag = cmdutil.graphrevs(other, chlist, opts)
4788 revdag = cmdutil.graphrevs(other, chlist, opts)
4852 cmdutil.displaygraph(ui, repo, revdag, displayer,
4789 cmdutil.displaygraph(ui, repo, revdag, displayer,
4853 graphmod.asciiedges)
4790 graphmod.asciiedges)
4854
4791
4855 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4792 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4856 return 0
4793 return 0
4857
4794
4858 if opts.get('bundle') and opts.get('subrepos'):
4795 if opts.get('bundle') and opts.get('subrepos'):
4859 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4796 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4860
4797
4861 if opts.get('bookmarks'):
4798 if opts.get('bookmarks'):
4862 source, branches = hg.parseurl(ui.expandpath(source),
4799 source, branches = hg.parseurl(ui.expandpath(source),
4863 opts.get('branch'))
4800 opts.get('branch'))
4864 other = hg.peer(repo, opts, source)
4801 other = hg.peer(repo, opts, source)
4865 if 'bookmarks' not in other.listkeys('namespaces'):
4802 if 'bookmarks' not in other.listkeys('namespaces'):
4866 ui.warn(_("remote doesn't support bookmarks\n"))
4803 ui.warn(_("remote doesn't support bookmarks\n"))
4867 return 0
4804 return 0
4868 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4805 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4869 return bookmarks.incoming(ui, repo, other)
4806 return bookmarks.incoming(ui, repo, other)
4870
4807
4871 repo._subtoppath = ui.expandpath(source)
4808 repo._subtoppath = ui.expandpath(source)
4872 try:
4809 try:
4873 return hg.incoming(ui, repo, source, opts)
4810 return hg.incoming(ui, repo, source, opts)
4874 finally:
4811 finally:
4875 del repo._subtoppath
4812 del repo._subtoppath
4876
4813
4877
4814
4878 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4815 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4879 norepo=True)
4816 norepo=True)
4880 def init(ui, dest=".", **opts):
4817 def init(ui, dest=".", **opts):
4881 """create a new repository in the given directory
4818 """create a new repository in the given directory
4882
4819
4883 Initialize a new repository in the given directory. If the given
4820 Initialize a new repository in the given directory. If the given
4884 directory does not exist, it will be created.
4821 directory does not exist, it will be created.
4885
4822
4886 If no directory is given, the current directory is used.
4823 If no directory is given, the current directory is used.
4887
4824
4888 It is possible to specify an ``ssh://`` URL as the destination.
4825 It is possible to specify an ``ssh://`` URL as the destination.
4889 See :hg:`help urls` for more information.
4826 See :hg:`help urls` for more information.
4890
4827
4891 Returns 0 on success.
4828 Returns 0 on success.
4892 """
4829 """
4893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4830 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4894
4831
4895 @command('locate',
4832 @command('locate',
4896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4833 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4834 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4835 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4899 ] + walkopts,
4836 ] + walkopts,
4900 _('[OPTION]... [PATTERN]...'))
4837 _('[OPTION]... [PATTERN]...'))
4901 def locate(ui, repo, *pats, **opts):
4838 def locate(ui, repo, *pats, **opts):
4902 """locate files matching specific patterns (DEPRECATED)
4839 """locate files matching specific patterns (DEPRECATED)
4903
4840
4904 Print files under Mercurial control in the working directory whose
4841 Print files under Mercurial control in the working directory whose
4905 names match the given patterns.
4842 names match the given patterns.
4906
4843
4907 By default, this command searches all directories in the working
4844 By default, this command searches all directories in the working
4908 directory. To search just the current directory and its
4845 directory. To search just the current directory and its
4909 subdirectories, use "--include .".
4846 subdirectories, use "--include .".
4910
4847
4911 If no patterns are given to match, this command prints the names
4848 If no patterns are given to match, this command prints the names
4912 of all files under Mercurial control in the working directory.
4849 of all files under Mercurial control in the working directory.
4913
4850
4914 If you want to feed the output of this command into the "xargs"
4851 If you want to feed the output of this command into the "xargs"
4915 command, use the -0 option to both this command and "xargs". This
4852 command, use the -0 option to both this command and "xargs". This
4916 will avoid the problem of "xargs" treating single filenames that
4853 will avoid the problem of "xargs" treating single filenames that
4917 contain whitespace as multiple filenames.
4854 contain whitespace as multiple filenames.
4918
4855
4919 See :hg:`help files` for a more versatile command.
4856 See :hg:`help files` for a more versatile command.
4920
4857
4921 Returns 0 if a match is found, 1 otherwise.
4858 Returns 0 if a match is found, 1 otherwise.
4922 """
4859 """
4923 if opts.get('print0'):
4860 if opts.get('print0'):
4924 end = '\0'
4861 end = '\0'
4925 else:
4862 else:
4926 end = '\n'
4863 end = '\n'
4927 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4864 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4928
4865
4929 ret = 1
4866 ret = 1
4930 ctx = repo[rev]
4867 ctx = repo[rev]
4931 m = scmutil.match(ctx, pats, opts, default='relglob',
4868 m = scmutil.match(ctx, pats, opts, default='relglob',
4932 badfn=lambda x, y: False)
4869 badfn=lambda x, y: False)
4933
4870
4934 for abs in ctx.matches(m):
4871 for abs in ctx.matches(m):
4935 if opts.get('fullpath'):
4872 if opts.get('fullpath'):
4936 ui.write(repo.wjoin(abs), end)
4873 ui.write(repo.wjoin(abs), end)
4937 else:
4874 else:
4938 ui.write(((pats and m.rel(abs)) or abs), end)
4875 ui.write(((pats and m.rel(abs)) or abs), end)
4939 ret = 0
4876 ret = 0
4940
4877
4941 return ret
4878 return ret
4942
4879
4943 @command('^log|history',
4880 @command('^log|history',
4944 [('f', 'follow', None,
4881 [('f', 'follow', None,
4945 _('follow changeset history, or file history across copies and renames')),
4882 _('follow changeset history, or file history across copies and renames')),
4946 ('', 'follow-first', None,
4883 ('', 'follow-first', None,
4947 _('only follow the first parent of merge changesets (DEPRECATED)')),
4884 _('only follow the first parent of merge changesets (DEPRECATED)')),
4948 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4885 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4949 ('C', 'copies', None, _('show copied files')),
4886 ('C', 'copies', None, _('show copied files')),
4950 ('k', 'keyword', [],
4887 ('k', 'keyword', [],
4951 _('do case-insensitive search for a given text'), _('TEXT')),
4888 _('do case-insensitive search for a given text'), _('TEXT')),
4952 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4889 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4953 ('', 'removed', None, _('include revisions where files were removed')),
4890 ('', 'removed', None, _('include revisions where files were removed')),
4954 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4891 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4955 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4892 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4956 ('', 'only-branch', [],
4893 ('', 'only-branch', [],
4957 _('show only changesets within the given named branch (DEPRECATED)'),
4894 _('show only changesets within the given named branch (DEPRECATED)'),
4958 _('BRANCH')),
4895 _('BRANCH')),
4959 ('b', 'branch', [],
4896 ('b', 'branch', [],
4960 _('show changesets within the given named branch'), _('BRANCH')),
4897 _('show changesets within the given named branch'), _('BRANCH')),
4961 ('P', 'prune', [],
4898 ('P', 'prune', [],
4962 _('do not display revision or any of its ancestors'), _('REV')),
4899 _('do not display revision or any of its ancestors'), _('REV')),
4963 ] + logopts + walkopts,
4900 ] + logopts + walkopts,
4964 _('[OPTION]... [FILE]'),
4901 _('[OPTION]... [FILE]'),
4965 inferrepo=True)
4902 inferrepo=True)
4966 def log(ui, repo, *pats, **opts):
4903 def log(ui, repo, *pats, **opts):
4967 """show revision history of entire repository or files
4904 """show revision history of entire repository or files
4968
4905
4969 Print the revision history of the specified files or the entire
4906 Print the revision history of the specified files or the entire
4970 project.
4907 project.
4971
4908
4972 If no revision range is specified, the default is ``tip:0`` unless
4909 If no revision range is specified, the default is ``tip:0`` unless
4973 --follow is set, in which case the working directory parent is
4910 --follow is set, in which case the working directory parent is
4974 used as the starting revision.
4911 used as the starting revision.
4975
4912
4976 File history is shown without following rename or copy history of
4913 File history is shown without following rename or copy history of
4977 files. Use -f/--follow with a filename to follow history across
4914 files. Use -f/--follow with a filename to follow history across
4978 renames and copies. --follow without a filename will only show
4915 renames and copies. --follow without a filename will only show
4979 ancestors or descendants of the starting revision.
4916 ancestors or descendants of the starting revision.
4980
4917
4981 By default this command prints revision number and changeset id,
4918 By default this command prints revision number and changeset id,
4982 tags, non-trivial parents, user, date and time, and a summary for
4919 tags, non-trivial parents, user, date and time, and a summary for
4983 each commit. When the -v/--verbose switch is used, the list of
4920 each commit. When the -v/--verbose switch is used, the list of
4984 changed files and full commit message are shown.
4921 changed files and full commit message are shown.
4985
4922
4986 With --graph the revisions are shown as an ASCII art DAG with the most
4923 With --graph the revisions are shown as an ASCII art DAG with the most
4987 recent changeset at the top.
4924 recent changeset at the top.
4988 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4925 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4989 and '+' represents a fork where the changeset from the lines below is a
4926 and '+' represents a fork where the changeset from the lines below is a
4990 parent of the 'o' merge on the same line.
4927 parent of the 'o' merge on the same line.
4991
4928
4992 .. note::
4929 .. note::
4993
4930
4994 :hg:`log --patch` may generate unexpected diff output for merge
4931 :hg:`log --patch` may generate unexpected diff output for merge
4995 changesets, as it will only compare the merge changeset against
4932 changesets, as it will only compare the merge changeset against
4996 its first parent. Also, only files different from BOTH parents
4933 its first parent. Also, only files different from BOTH parents
4997 will appear in files:.
4934 will appear in files:.
4998
4935
4999 .. note::
4936 .. note::
5000
4937
5001 For performance reasons, :hg:`log FILE` may omit duplicate changes
4938 For performance reasons, :hg:`log FILE` may omit duplicate changes
5002 made on branches and will not show removals or mode changes. To
4939 made on branches and will not show removals or mode changes. To
5003 see all such changes, use the --removed switch.
4940 see all such changes, use the --removed switch.
5004
4941
5005 .. container:: verbose
4942 .. container:: verbose
5006
4943
5007 Some examples:
4944 Some examples:
5008
4945
5009 - changesets with full descriptions and file lists::
4946 - changesets with full descriptions and file lists::
5010
4947
5011 hg log -v
4948 hg log -v
5012
4949
5013 - changesets ancestral to the working directory::
4950 - changesets ancestral to the working directory::
5014
4951
5015 hg log -f
4952 hg log -f
5016
4953
5017 - last 10 commits on the current branch::
4954 - last 10 commits on the current branch::
5018
4955
5019 hg log -l 10 -b .
4956 hg log -l 10 -b .
5020
4957
5021 - changesets showing all modifications of a file, including removals::
4958 - changesets showing all modifications of a file, including removals::
5022
4959
5023 hg log --removed file.c
4960 hg log --removed file.c
5024
4961
5025 - all changesets that touch a directory, with diffs, excluding merges::
4962 - all changesets that touch a directory, with diffs, excluding merges::
5026
4963
5027 hg log -Mp lib/
4964 hg log -Mp lib/
5028
4965
5029 - all revision numbers that match a keyword::
4966 - all revision numbers that match a keyword::
5030
4967
5031 hg log -k bug --template "{rev}\\n"
4968 hg log -k bug --template "{rev}\\n"
5032
4969
5033 - the full hash identifier of the working directory parent::
4970 - the full hash identifier of the working directory parent::
5034
4971
5035 hg log -r . --template "{node}\\n"
4972 hg log -r . --template "{node}\\n"
5036
4973
5037 - list available log templates::
4974 - list available log templates::
5038
4975
5039 hg log -T list
4976 hg log -T list
5040
4977
5041 - check if a given changeset is included in a tagged release::
4978 - check if a given changeset is included in a tagged release::
5042
4979
5043 hg log -r "a21ccf and ancestor(1.9)"
4980 hg log -r "a21ccf and ancestor(1.9)"
5044
4981
5045 - find all changesets by some user in a date range::
4982 - find all changesets by some user in a date range::
5046
4983
5047 hg log -k alice -d "may 2008 to jul 2008"
4984 hg log -k alice -d "may 2008 to jul 2008"
5048
4985
5049 - summary of all changesets after the last tag::
4986 - summary of all changesets after the last tag::
5050
4987
5051 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4988 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5052
4989
5053 See :hg:`help dates` for a list of formats valid for -d/--date.
4990 See :hg:`help dates` for a list of formats valid for -d/--date.
5054
4991
5055 See :hg:`help revisions` and :hg:`help revsets` for more about
4992 See :hg:`help revisions` and :hg:`help revsets` for more about
5056 specifying and ordering revisions.
4993 specifying and ordering revisions.
5057
4994
5058 See :hg:`help templates` for more about pre-packaged styles and
4995 See :hg:`help templates` for more about pre-packaged styles and
5059 specifying custom templates.
4996 specifying custom templates.
5060
4997
5061 Returns 0 on success.
4998 Returns 0 on success.
5062
4999
5063 """
5000 """
5064 if opts.get('follow') and opts.get('rev'):
5001 if opts.get('follow') and opts.get('rev'):
5065 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5002 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5066 del opts['follow']
5003 del opts['follow']
5067
5004
5068 if opts.get('graph'):
5005 if opts.get('graph'):
5069 return cmdutil.graphlog(ui, repo, *pats, **opts)
5006 return cmdutil.graphlog(ui, repo, *pats, **opts)
5070
5007
5071 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5008 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5072 limit = cmdutil.loglimit(opts)
5009 limit = cmdutil.loglimit(opts)
5073 count = 0
5010 count = 0
5074
5011
5075 getrenamed = None
5012 getrenamed = None
5076 if opts.get('copies'):
5013 if opts.get('copies'):
5077 endrev = None
5014 endrev = None
5078 if opts.get('rev'):
5015 if opts.get('rev'):
5079 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5016 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5080 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5017 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5081
5018
5082 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5019 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5083 for rev in revs:
5020 for rev in revs:
5084 if count == limit:
5021 if count == limit:
5085 break
5022 break
5086 ctx = repo[rev]
5023 ctx = repo[rev]
5087 copies = None
5024 copies = None
5088 if getrenamed is not None and rev:
5025 if getrenamed is not None and rev:
5089 copies = []
5026 copies = []
5090 for fn in ctx.files():
5027 for fn in ctx.files():
5091 rename = getrenamed(fn, rev)
5028 rename = getrenamed(fn, rev)
5092 if rename:
5029 if rename:
5093 copies.append((fn, rename[0]))
5030 copies.append((fn, rename[0]))
5094 if filematcher:
5031 if filematcher:
5095 revmatchfn = filematcher(ctx.rev())
5032 revmatchfn = filematcher(ctx.rev())
5096 else:
5033 else:
5097 revmatchfn = None
5034 revmatchfn = None
5098 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5035 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5099 if displayer.flush(ctx):
5036 if displayer.flush(ctx):
5100 count += 1
5037 count += 1
5101
5038
5102 displayer.close()
5039 displayer.close()
5103
5040
5104 @command('manifest',
5041 @command('manifest',
5105 [('r', 'rev', '', _('revision to display'), _('REV')),
5042 [('r', 'rev', '', _('revision to display'), _('REV')),
5106 ('', 'all', False, _("list files from all revisions"))]
5043 ('', 'all', False, _("list files from all revisions"))]
5107 + formatteropts,
5044 + formatteropts,
5108 _('[-r REV]'))
5045 _('[-r REV]'))
5109 def manifest(ui, repo, node=None, rev=None, **opts):
5046 def manifest(ui, repo, node=None, rev=None, **opts):
5110 """output the current or given revision of the project manifest
5047 """output the current or given revision of the project manifest
5111
5048
5112 Print a list of version controlled files for the given revision.
5049 Print a list of version controlled files for the given revision.
5113 If no revision is given, the first parent of the working directory
5050 If no revision is given, the first parent of the working directory
5114 is used, or the null revision if no revision is checked out.
5051 is used, or the null revision if no revision is checked out.
5115
5052
5116 With -v, print file permissions, symlink and executable bits.
5053 With -v, print file permissions, symlink and executable bits.
5117 With --debug, print file revision hashes.
5054 With --debug, print file revision hashes.
5118
5055
5119 If option --all is specified, the list of all files from all revisions
5056 If option --all is specified, the list of all files from all revisions
5120 is printed. This includes deleted and renamed files.
5057 is printed. This includes deleted and renamed files.
5121
5058
5122 Returns 0 on success.
5059 Returns 0 on success.
5123 """
5060 """
5124
5061
5125 fm = ui.formatter('manifest', opts)
5062 fm = ui.formatter('manifest', opts)
5126
5063
5127 if opts.get('all'):
5064 if opts.get('all'):
5128 if rev or node:
5065 if rev or node:
5129 raise error.Abort(_("can't specify a revision with --all"))
5066 raise error.Abort(_("can't specify a revision with --all"))
5130
5067
5131 res = []
5068 res = []
5132 prefix = "data/"
5069 prefix = "data/"
5133 suffix = ".i"
5070 suffix = ".i"
5134 plen = len(prefix)
5071 plen = len(prefix)
5135 slen = len(suffix)
5072 slen = len(suffix)
5136 with repo.lock():
5073 with repo.lock():
5137 for fn, b, size in repo.store.datafiles():
5074 for fn, b, size in repo.store.datafiles():
5138 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5075 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5139 res.append(fn[plen:-slen])
5076 res.append(fn[plen:-slen])
5140 for f in res:
5077 for f in res:
5141 fm.startitem()
5078 fm.startitem()
5142 fm.write("path", '%s\n', f)
5079 fm.write("path", '%s\n', f)
5143 fm.end()
5080 fm.end()
5144 return
5081 return
5145
5082
5146 if rev and node:
5083 if rev and node:
5147 raise error.Abort(_("please specify just one revision"))
5084 raise error.Abort(_("please specify just one revision"))
5148
5085
5149 if not node:
5086 if not node:
5150 node = rev
5087 node = rev
5151
5088
5152 char = {'l': '@', 'x': '*', '': ''}
5089 char = {'l': '@', 'x': '*', '': ''}
5153 mode = {'l': '644', 'x': '755', '': '644'}
5090 mode = {'l': '644', 'x': '755', '': '644'}
5154 ctx = scmutil.revsingle(repo, node)
5091 ctx = scmutil.revsingle(repo, node)
5155 mf = ctx.manifest()
5092 mf = ctx.manifest()
5156 for f in ctx:
5093 for f in ctx:
5157 fm.startitem()
5094 fm.startitem()
5158 fl = ctx[f].flags()
5095 fl = ctx[f].flags()
5159 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5096 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5160 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5097 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5161 fm.write('path', '%s\n', f)
5098 fm.write('path', '%s\n', f)
5162 fm.end()
5099 fm.end()
5163
5100
5164 @command('^merge',
5101 @command('^merge',
5165 [('f', 'force', None,
5102 [('f', 'force', None,
5166 _('force a merge including outstanding changes (DEPRECATED)')),
5103 _('force a merge including outstanding changes (DEPRECATED)')),
5167 ('r', 'rev', '', _('revision to merge'), _('REV')),
5104 ('r', 'rev', '', _('revision to merge'), _('REV')),
5168 ('P', 'preview', None,
5105 ('P', 'preview', None,
5169 _('review revisions to merge (no merge is performed)'))
5106 _('review revisions to merge (no merge is performed)'))
5170 ] + mergetoolopts,
5107 ] + mergetoolopts,
5171 _('[-P] [[-r] REV]'))
5108 _('[-P] [[-r] REV]'))
5172 def merge(ui, repo, node=None, **opts):
5109 def merge(ui, repo, node=None, **opts):
5173 """merge another revision into working directory
5110 """merge another revision into working directory
5174
5111
5175 The current working directory is updated with all changes made in
5112 The current working directory is updated with all changes made in
5176 the requested revision since the last common predecessor revision.
5113 the requested revision since the last common predecessor revision.
5177
5114
5178 Files that changed between either parent are marked as changed for
5115 Files that changed between either parent are marked as changed for
5179 the next commit and a commit must be performed before any further
5116 the next commit and a commit must be performed before any further
5180 updates to the repository are allowed. The next commit will have
5117 updates to the repository are allowed. The next commit will have
5181 two parents.
5118 two parents.
5182
5119
5183 ``--tool`` can be used to specify the merge tool used for file
5120 ``--tool`` can be used to specify the merge tool used for file
5184 merges. It overrides the HGMERGE environment variable and your
5121 merges. It overrides the HGMERGE environment variable and your
5185 configuration files. See :hg:`help merge-tools` for options.
5122 configuration files. See :hg:`help merge-tools` for options.
5186
5123
5187 If no revision is specified, the working directory's parent is a
5124 If no revision is specified, the working directory's parent is a
5188 head revision, and the current branch contains exactly one other
5125 head revision, and the current branch contains exactly one other
5189 head, the other head is merged with by default. Otherwise, an
5126 head, the other head is merged with by default. Otherwise, an
5190 explicit revision with which to merge with must be provided.
5127 explicit revision with which to merge with must be provided.
5191
5128
5192 See :hg:`help resolve` for information on handling file conflicts.
5129 See :hg:`help resolve` for information on handling file conflicts.
5193
5130
5194 To undo an uncommitted merge, use :hg:`update --clean .` which
5131 To undo an uncommitted merge, use :hg:`update --clean .` which
5195 will check out a clean copy of the original merge parent, losing
5132 will check out a clean copy of the original merge parent, losing
5196 all changes.
5133 all changes.
5197
5134
5198 Returns 0 on success, 1 if there are unresolved files.
5135 Returns 0 on success, 1 if there are unresolved files.
5199 """
5136 """
5200
5137
5201 if opts.get('rev') and node:
5138 if opts.get('rev') and node:
5202 raise error.Abort(_("please specify just one revision"))
5139 raise error.Abort(_("please specify just one revision"))
5203 if not node:
5140 if not node:
5204 node = opts.get('rev')
5141 node = opts.get('rev')
5205
5142
5206 if node:
5143 if node:
5207 node = scmutil.revsingle(repo, node).node()
5144 node = scmutil.revsingle(repo, node).node()
5208
5145
5209 if not node:
5146 if not node:
5210 node = repo[destutil.destmerge(repo)].node()
5147 node = repo[destutil.destmerge(repo)].node()
5211
5148
5212 if opts.get('preview'):
5149 if opts.get('preview'):
5213 # find nodes that are ancestors of p2 but not of p1
5150 # find nodes that are ancestors of p2 but not of p1
5214 p1 = repo.lookup('.')
5151 p1 = repo.lookup('.')
5215 p2 = repo.lookup(node)
5152 p2 = repo.lookup(node)
5216 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5153 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5217
5154
5218 displayer = cmdutil.show_changeset(ui, repo, opts)
5155 displayer = cmdutil.show_changeset(ui, repo, opts)
5219 for node in nodes:
5156 for node in nodes:
5220 displayer.show(repo[node])
5157 displayer.show(repo[node])
5221 displayer.close()
5158 displayer.close()
5222 return 0
5159 return 0
5223
5160
5224 try:
5161 try:
5225 # ui.forcemerge is an internal variable, do not document
5162 # ui.forcemerge is an internal variable, do not document
5226 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5163 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5227 force = opts.get('force')
5164 force = opts.get('force')
5228 labels = ['working copy', 'merge rev']
5165 labels = ['working copy', 'merge rev']
5229 return hg.merge(repo, node, force=force, mergeforce=force,
5166 return hg.merge(repo, node, force=force, mergeforce=force,
5230 labels=labels)
5167 labels=labels)
5231 finally:
5168 finally:
5232 ui.setconfig('ui', 'forcemerge', '', 'merge')
5169 ui.setconfig('ui', 'forcemerge', '', 'merge')
5233
5170
5234 @command('outgoing|out',
5171 @command('outgoing|out',
5235 [('f', 'force', None, _('run even when the destination is unrelated')),
5172 [('f', 'force', None, _('run even when the destination is unrelated')),
5236 ('r', 'rev', [],
5173 ('r', 'rev', [],
5237 _('a changeset intended to be included in the destination'), _('REV')),
5174 _('a changeset intended to be included in the destination'), _('REV')),
5238 ('n', 'newest-first', None, _('show newest record first')),
5175 ('n', 'newest-first', None, _('show newest record first')),
5239 ('B', 'bookmarks', False, _('compare bookmarks')),
5176 ('B', 'bookmarks', False, _('compare bookmarks')),
5240 ('b', 'branch', [], _('a specific branch you would like to push'),
5177 ('b', 'branch', [], _('a specific branch you would like to push'),
5241 _('BRANCH')),
5178 _('BRANCH')),
5242 ] + logopts + remoteopts + subrepoopts,
5179 ] + logopts + remoteopts + subrepoopts,
5243 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5180 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5244 def outgoing(ui, repo, dest=None, **opts):
5181 def outgoing(ui, repo, dest=None, **opts):
5245 """show changesets not found in the destination
5182 """show changesets not found in the destination
5246
5183
5247 Show changesets not found in the specified destination repository
5184 Show changesets not found in the specified destination repository
5248 or the default push location. These are the changesets that would
5185 or the default push location. These are the changesets that would
5249 be pushed if a push was requested.
5186 be pushed if a push was requested.
5250
5187
5251 See pull for details of valid destination formats.
5188 See pull for details of valid destination formats.
5252
5189
5253 .. container:: verbose
5190 .. container:: verbose
5254
5191
5255 With -B/--bookmarks, the result of bookmark comparison between
5192 With -B/--bookmarks, the result of bookmark comparison between
5256 local and remote repositories is displayed. With -v/--verbose,
5193 local and remote repositories is displayed. With -v/--verbose,
5257 status is also displayed for each bookmark like below::
5194 status is also displayed for each bookmark like below::
5258
5195
5259 BM1 01234567890a added
5196 BM1 01234567890a added
5260 BM2 deleted
5197 BM2 deleted
5261 BM3 234567890abc advanced
5198 BM3 234567890abc advanced
5262 BM4 34567890abcd diverged
5199 BM4 34567890abcd diverged
5263 BM5 4567890abcde changed
5200 BM5 4567890abcde changed
5264
5201
5265 The action taken when pushing depends on the
5202 The action taken when pushing depends on the
5266 status of each bookmark:
5203 status of each bookmark:
5267
5204
5268 :``added``: push with ``-B`` will create it
5205 :``added``: push with ``-B`` will create it
5269 :``deleted``: push with ``-B`` will delete it
5206 :``deleted``: push with ``-B`` will delete it
5270 :``advanced``: push will update it
5207 :``advanced``: push will update it
5271 :``diverged``: push with ``-B`` will update it
5208 :``diverged``: push with ``-B`` will update it
5272 :``changed``: push with ``-B`` will update it
5209 :``changed``: push with ``-B`` will update it
5273
5210
5274 From the point of view of pushing behavior, bookmarks
5211 From the point of view of pushing behavior, bookmarks
5275 existing only in the remote repository are treated as
5212 existing only in the remote repository are treated as
5276 ``deleted``, even if it is in fact added remotely.
5213 ``deleted``, even if it is in fact added remotely.
5277
5214
5278 Returns 0 if there are outgoing changes, 1 otherwise.
5215 Returns 0 if there are outgoing changes, 1 otherwise.
5279 """
5216 """
5280 if opts.get('graph'):
5217 if opts.get('graph'):
5281 cmdutil.checkunsupportedgraphflags([], opts)
5218 cmdutil.checkunsupportedgraphflags([], opts)
5282 o, other = hg._outgoing(ui, repo, dest, opts)
5219 o, other = hg._outgoing(ui, repo, dest, opts)
5283 if not o:
5220 if not o:
5284 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5221 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5285 return
5222 return
5286
5223
5287 revdag = cmdutil.graphrevs(repo, o, opts)
5224 revdag = cmdutil.graphrevs(repo, o, opts)
5288 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5225 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5289 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5226 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5290 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5227 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5291 return 0
5228 return 0
5292
5229
5293 if opts.get('bookmarks'):
5230 if opts.get('bookmarks'):
5294 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5231 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5295 dest, branches = hg.parseurl(dest, opts.get('branch'))
5232 dest, branches = hg.parseurl(dest, opts.get('branch'))
5296 other = hg.peer(repo, opts, dest)
5233 other = hg.peer(repo, opts, dest)
5297 if 'bookmarks' not in other.listkeys('namespaces'):
5234 if 'bookmarks' not in other.listkeys('namespaces'):
5298 ui.warn(_("remote doesn't support bookmarks\n"))
5235 ui.warn(_("remote doesn't support bookmarks\n"))
5299 return 0
5236 return 0
5300 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5237 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5301 return bookmarks.outgoing(ui, repo, other)
5238 return bookmarks.outgoing(ui, repo, other)
5302
5239
5303 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5240 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5304 try:
5241 try:
5305 return hg.outgoing(ui, repo, dest, opts)
5242 return hg.outgoing(ui, repo, dest, opts)
5306 finally:
5243 finally:
5307 del repo._subtoppath
5244 del repo._subtoppath
5308
5245
5309 @command('parents',
5246 @command('parents',
5310 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5247 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5311 ] + templateopts,
5248 ] + templateopts,
5312 _('[-r REV] [FILE]'),
5249 _('[-r REV] [FILE]'),
5313 inferrepo=True)
5250 inferrepo=True)
5314 def parents(ui, repo, file_=None, **opts):
5251 def parents(ui, repo, file_=None, **opts):
5315 """show the parents of the working directory or revision (DEPRECATED)
5252 """show the parents of the working directory or revision (DEPRECATED)
5316
5253
5317 Print the working directory's parent revisions. If a revision is
5254 Print the working directory's parent revisions. If a revision is
5318 given via -r/--rev, the parent of that revision will be printed.
5255 given via -r/--rev, the parent of that revision will be printed.
5319 If a file argument is given, the revision in which the file was
5256 If a file argument is given, the revision in which the file was
5320 last changed (before the working directory revision or the
5257 last changed (before the working directory revision or the
5321 argument to --rev if given) is printed.
5258 argument to --rev if given) is printed.
5322
5259
5323 This command is equivalent to::
5260 This command is equivalent to::
5324
5261
5325 hg log -r "p1()+p2()" or
5262 hg log -r "p1()+p2()" or
5326 hg log -r "p1(REV)+p2(REV)" or
5263 hg log -r "p1(REV)+p2(REV)" or
5327 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5264 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5328 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5265 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5329
5266
5330 See :hg:`summary` and :hg:`help revsets` for related information.
5267 See :hg:`summary` and :hg:`help revsets` for related information.
5331
5268
5332 Returns 0 on success.
5269 Returns 0 on success.
5333 """
5270 """
5334
5271
5335 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5272 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5336
5273
5337 if file_:
5274 if file_:
5338 m = scmutil.match(ctx, (file_,), opts)
5275 m = scmutil.match(ctx, (file_,), opts)
5339 if m.anypats() or len(m.files()) != 1:
5276 if m.anypats() or len(m.files()) != 1:
5340 raise error.Abort(_('can only specify an explicit filename'))
5277 raise error.Abort(_('can only specify an explicit filename'))
5341 file_ = m.files()[0]
5278 file_ = m.files()[0]
5342 filenodes = []
5279 filenodes = []
5343 for cp in ctx.parents():
5280 for cp in ctx.parents():
5344 if not cp:
5281 if not cp:
5345 continue
5282 continue
5346 try:
5283 try:
5347 filenodes.append(cp.filenode(file_))
5284 filenodes.append(cp.filenode(file_))
5348 except error.LookupError:
5285 except error.LookupError:
5349 pass
5286 pass
5350 if not filenodes:
5287 if not filenodes:
5351 raise error.Abort(_("'%s' not found in manifest!") % file_)
5288 raise error.Abort(_("'%s' not found in manifest!") % file_)
5352 p = []
5289 p = []
5353 for fn in filenodes:
5290 for fn in filenodes:
5354 fctx = repo.filectx(file_, fileid=fn)
5291 fctx = repo.filectx(file_, fileid=fn)
5355 p.append(fctx.node())
5292 p.append(fctx.node())
5356 else:
5293 else:
5357 p = [cp.node() for cp in ctx.parents()]
5294 p = [cp.node() for cp in ctx.parents()]
5358
5295
5359 displayer = cmdutil.show_changeset(ui, repo, opts)
5296 displayer = cmdutil.show_changeset(ui, repo, opts)
5360 for n in p:
5297 for n in p:
5361 if n != nullid:
5298 if n != nullid:
5362 displayer.show(repo[n])
5299 displayer.show(repo[n])
5363 displayer.close()
5300 displayer.close()
5364
5301
5365 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5302 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5366 def paths(ui, repo, search=None, **opts):
5303 def paths(ui, repo, search=None, **opts):
5367 """show aliases for remote repositories
5304 """show aliases for remote repositories
5368
5305
5369 Show definition of symbolic path name NAME. If no name is given,
5306 Show definition of symbolic path name NAME. If no name is given,
5370 show definition of all available names.
5307 show definition of all available names.
5371
5308
5372 Option -q/--quiet suppresses all output when searching for NAME
5309 Option -q/--quiet suppresses all output when searching for NAME
5373 and shows only the path names when listing all definitions.
5310 and shows only the path names when listing all definitions.
5374
5311
5375 Path names are defined in the [paths] section of your
5312 Path names are defined in the [paths] section of your
5376 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5313 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5377 repository, ``.hg/hgrc`` is used, too.
5314 repository, ``.hg/hgrc`` is used, too.
5378
5315
5379 The path names ``default`` and ``default-push`` have a special
5316 The path names ``default`` and ``default-push`` have a special
5380 meaning. When performing a push or pull operation, they are used
5317 meaning. When performing a push or pull operation, they are used
5381 as fallbacks if no location is specified on the command-line.
5318 as fallbacks if no location is specified on the command-line.
5382 When ``default-push`` is set, it will be used for push and
5319 When ``default-push`` is set, it will be used for push and
5383 ``default`` will be used for pull; otherwise ``default`` is used
5320 ``default`` will be used for pull; otherwise ``default`` is used
5384 as the fallback for both. When cloning a repository, the clone
5321 as the fallback for both. When cloning a repository, the clone
5385 source is written as ``default`` in ``.hg/hgrc``.
5322 source is written as ``default`` in ``.hg/hgrc``.
5386
5323
5387 .. note::
5324 .. note::
5388
5325
5389 ``default`` and ``default-push`` apply to all inbound (e.g.
5326 ``default`` and ``default-push`` apply to all inbound (e.g.
5390 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5327 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5391 and :hg:`bundle`) operations.
5328 and :hg:`bundle`) operations.
5392
5329
5393 See :hg:`help urls` for more information.
5330 See :hg:`help urls` for more information.
5394
5331
5395 Returns 0 on success.
5332 Returns 0 on success.
5396 """
5333 """
5397 if search:
5334 if search:
5398 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5335 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5399 if name == search]
5336 if name == search]
5400 else:
5337 else:
5401 pathitems = sorted(ui.paths.iteritems())
5338 pathitems = sorted(ui.paths.iteritems())
5402
5339
5403 fm = ui.formatter('paths', opts)
5340 fm = ui.formatter('paths', opts)
5404 if fm.isplain():
5341 if fm.isplain():
5405 hidepassword = util.hidepassword
5342 hidepassword = util.hidepassword
5406 else:
5343 else:
5407 hidepassword = str
5344 hidepassword = str
5408 if ui.quiet:
5345 if ui.quiet:
5409 namefmt = '%s\n'
5346 namefmt = '%s\n'
5410 else:
5347 else:
5411 namefmt = '%s = '
5348 namefmt = '%s = '
5412 showsubopts = not search and not ui.quiet
5349 showsubopts = not search and not ui.quiet
5413
5350
5414 for name, path in pathitems:
5351 for name, path in pathitems:
5415 fm.startitem()
5352 fm.startitem()
5416 fm.condwrite(not search, 'name', namefmt, name)
5353 fm.condwrite(not search, 'name', namefmt, name)
5417 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5354 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5418 for subopt, value in sorted(path.suboptions.items()):
5355 for subopt, value in sorted(path.suboptions.items()):
5419 assert subopt not in ('name', 'url')
5356 assert subopt not in ('name', 'url')
5420 if showsubopts:
5357 if showsubopts:
5421 fm.plain('%s:%s = ' % (name, subopt))
5358 fm.plain('%s:%s = ' % (name, subopt))
5422 fm.condwrite(showsubopts, subopt, '%s\n', value)
5359 fm.condwrite(showsubopts, subopt, '%s\n', value)
5423
5360
5424 fm.end()
5361 fm.end()
5425
5362
5426 if search and not pathitems:
5363 if search and not pathitems:
5427 if not ui.quiet:
5364 if not ui.quiet:
5428 ui.warn(_("not found!\n"))
5365 ui.warn(_("not found!\n"))
5429 return 1
5366 return 1
5430 else:
5367 else:
5431 return 0
5368 return 0
5432
5369
5433 @command('phase',
5370 @command('phase',
5434 [('p', 'public', False, _('set changeset phase to public')),
5371 [('p', 'public', False, _('set changeset phase to public')),
5435 ('d', 'draft', False, _('set changeset phase to draft')),
5372 ('d', 'draft', False, _('set changeset phase to draft')),
5436 ('s', 'secret', False, _('set changeset phase to secret')),
5373 ('s', 'secret', False, _('set changeset phase to secret')),
5437 ('f', 'force', False, _('allow to move boundary backward')),
5374 ('f', 'force', False, _('allow to move boundary backward')),
5438 ('r', 'rev', [], _('target revision'), _('REV')),
5375 ('r', 'rev', [], _('target revision'), _('REV')),
5439 ],
5376 ],
5440 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5377 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5441 def phase(ui, repo, *revs, **opts):
5378 def phase(ui, repo, *revs, **opts):
5442 """set or show the current phase name
5379 """set or show the current phase name
5443
5380
5444 With no argument, show the phase name of the current revision(s).
5381 With no argument, show the phase name of the current revision(s).
5445
5382
5446 With one of -p/--public, -d/--draft or -s/--secret, change the
5383 With one of -p/--public, -d/--draft or -s/--secret, change the
5447 phase value of the specified revisions.
5384 phase value of the specified revisions.
5448
5385
5449 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5386 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5450 lower phase to an higher phase. Phases are ordered as follows::
5387 lower phase to an higher phase. Phases are ordered as follows::
5451
5388
5452 public < draft < secret
5389 public < draft < secret
5453
5390
5454 Returns 0 on success, 1 if some phases could not be changed.
5391 Returns 0 on success, 1 if some phases could not be changed.
5455
5392
5456 (For more information about the phases concept, see :hg:`help phases`.)
5393 (For more information about the phases concept, see :hg:`help phases`.)
5457 """
5394 """
5458 # search for a unique phase argument
5395 # search for a unique phase argument
5459 targetphase = None
5396 targetphase = None
5460 for idx, name in enumerate(phases.phasenames):
5397 for idx, name in enumerate(phases.phasenames):
5461 if opts[name]:
5398 if opts[name]:
5462 if targetphase is not None:
5399 if targetphase is not None:
5463 raise error.Abort(_('only one phase can be specified'))
5400 raise error.Abort(_('only one phase can be specified'))
5464 targetphase = idx
5401 targetphase = idx
5465
5402
5466 # look for specified revision
5403 # look for specified revision
5467 revs = list(revs)
5404 revs = list(revs)
5468 revs.extend(opts['rev'])
5405 revs.extend(opts['rev'])
5469 if not revs:
5406 if not revs:
5470 # display both parents as the second parent phase can influence
5407 # display both parents as the second parent phase can influence
5471 # the phase of a merge commit
5408 # the phase of a merge commit
5472 revs = [c.rev() for c in repo[None].parents()]
5409 revs = [c.rev() for c in repo[None].parents()]
5473
5410
5474 revs = scmutil.revrange(repo, revs)
5411 revs = scmutil.revrange(repo, revs)
5475
5412
5476 lock = None
5413 lock = None
5477 ret = 0
5414 ret = 0
5478 if targetphase is None:
5415 if targetphase is None:
5479 # display
5416 # display
5480 for r in revs:
5417 for r in revs:
5481 ctx = repo[r]
5418 ctx = repo[r]
5482 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5419 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5483 else:
5420 else:
5484 tr = None
5421 tr = None
5485 lock = repo.lock()
5422 lock = repo.lock()
5486 try:
5423 try:
5487 tr = repo.transaction("phase")
5424 tr = repo.transaction("phase")
5488 # set phase
5425 # set phase
5489 if not revs:
5426 if not revs:
5490 raise error.Abort(_('empty revision set'))
5427 raise error.Abort(_('empty revision set'))
5491 nodes = [repo[r].node() for r in revs]
5428 nodes = [repo[r].node() for r in revs]
5492 # moving revision from public to draft may hide them
5429 # moving revision from public to draft may hide them
5493 # We have to check result on an unfiltered repository
5430 # We have to check result on an unfiltered repository
5494 unfi = repo.unfiltered()
5431 unfi = repo.unfiltered()
5495 getphase = unfi._phasecache.phase
5432 getphase = unfi._phasecache.phase
5496 olddata = [getphase(unfi, r) for r in unfi]
5433 olddata = [getphase(unfi, r) for r in unfi]
5497 phases.advanceboundary(repo, tr, targetphase, nodes)
5434 phases.advanceboundary(repo, tr, targetphase, nodes)
5498 if opts['force']:
5435 if opts['force']:
5499 phases.retractboundary(repo, tr, targetphase, nodes)
5436 phases.retractboundary(repo, tr, targetphase, nodes)
5500 tr.close()
5437 tr.close()
5501 finally:
5438 finally:
5502 if tr is not None:
5439 if tr is not None:
5503 tr.release()
5440 tr.release()
5504 lock.release()
5441 lock.release()
5505 getphase = unfi._phasecache.phase
5442 getphase = unfi._phasecache.phase
5506 newdata = [getphase(unfi, r) for r in unfi]
5443 newdata = [getphase(unfi, r) for r in unfi]
5507 changes = sum(newdata[r] != olddata[r] for r in unfi)
5444 changes = sum(newdata[r] != olddata[r] for r in unfi)
5508 cl = unfi.changelog
5445 cl = unfi.changelog
5509 rejected = [n for n in nodes
5446 rejected = [n for n in nodes
5510 if newdata[cl.rev(n)] < targetphase]
5447 if newdata[cl.rev(n)] < targetphase]
5511 if rejected:
5448 if rejected:
5512 ui.warn(_('cannot move %i changesets to a higher '
5449 ui.warn(_('cannot move %i changesets to a higher '
5513 'phase, use --force\n') % len(rejected))
5450 'phase, use --force\n') % len(rejected))
5514 ret = 1
5451 ret = 1
5515 if changes:
5452 if changes:
5516 msg = _('phase changed for %i changesets\n') % changes
5453 msg = _('phase changed for %i changesets\n') % changes
5517 if ret:
5454 if ret:
5518 ui.status(msg)
5455 ui.status(msg)
5519 else:
5456 else:
5520 ui.note(msg)
5457 ui.note(msg)
5521 else:
5458 else:
5522 ui.warn(_('no phases changed\n'))
5459 ui.warn(_('no phases changed\n'))
5523 return ret
5460 return ret
5524
5461
5525 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5462 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5526 """Run after a changegroup has been added via pull/unbundle
5463 """Run after a changegroup has been added via pull/unbundle
5527
5464
5528 This takes arguments below:
5465 This takes arguments below:
5529
5466
5530 :modheads: change of heads by pull/unbundle
5467 :modheads: change of heads by pull/unbundle
5531 :optupdate: updating working directory is needed or not
5468 :optupdate: updating working directory is needed or not
5532 :checkout: update destination revision (or None to default destination)
5469 :checkout: update destination revision (or None to default destination)
5533 :brev: a name, which might be a bookmark to be activated after updating
5470 :brev: a name, which might be a bookmark to be activated after updating
5534 """
5471 """
5535 if modheads == 0:
5472 if modheads == 0:
5536 return
5473 return
5537 if optupdate:
5474 if optupdate:
5538 try:
5475 try:
5539 return hg.updatetotally(ui, repo, checkout, brev)
5476 return hg.updatetotally(ui, repo, checkout, brev)
5540 except error.UpdateAbort as inst:
5477 except error.UpdateAbort as inst:
5541 msg = _("not updating: %s") % str(inst)
5478 msg = _("not updating: %s") % str(inst)
5542 hint = inst.hint
5479 hint = inst.hint
5543 raise error.UpdateAbort(msg, hint=hint)
5480 raise error.UpdateAbort(msg, hint=hint)
5544 if modheads > 1:
5481 if modheads > 1:
5545 currentbranchheads = len(repo.branchheads())
5482 currentbranchheads = len(repo.branchheads())
5546 if currentbranchheads == modheads:
5483 if currentbranchheads == modheads:
5547 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5484 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5548 elif currentbranchheads > 1:
5485 elif currentbranchheads > 1:
5549 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5486 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5550 "merge)\n"))
5487 "merge)\n"))
5551 else:
5488 else:
5552 ui.status(_("(run 'hg heads' to see heads)\n"))
5489 ui.status(_("(run 'hg heads' to see heads)\n"))
5553 else:
5490 else:
5554 ui.status(_("(run 'hg update' to get a working copy)\n"))
5491 ui.status(_("(run 'hg update' to get a working copy)\n"))
5555
5492
5556 @command('^pull',
5493 @command('^pull',
5557 [('u', 'update', None,
5494 [('u', 'update', None,
5558 _('update to new branch head if changesets were pulled')),
5495 _('update to new branch head if changesets were pulled')),
5559 ('f', 'force', None, _('run even when remote repository is unrelated')),
5496 ('f', 'force', None, _('run even when remote repository is unrelated')),
5560 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5497 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5561 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5498 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5562 ('b', 'branch', [], _('a specific branch you would like to pull'),
5499 ('b', 'branch', [], _('a specific branch you would like to pull'),
5563 _('BRANCH')),
5500 _('BRANCH')),
5564 ] + remoteopts,
5501 ] + remoteopts,
5565 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5502 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5566 def pull(ui, repo, source="default", **opts):
5503 def pull(ui, repo, source="default", **opts):
5567 """pull changes from the specified source
5504 """pull changes from the specified source
5568
5505
5569 Pull changes from a remote repository to a local one.
5506 Pull changes from a remote repository to a local one.
5570
5507
5571 This finds all changes from the repository at the specified path
5508 This finds all changes from the repository at the specified path
5572 or URL and adds them to a local repository (the current one unless
5509 or URL and adds them to a local repository (the current one unless
5573 -R is specified). By default, this does not update the copy of the
5510 -R is specified). By default, this does not update the copy of the
5574 project in the working directory.
5511 project in the working directory.
5575
5512
5576 Use :hg:`incoming` if you want to see what would have been added
5513 Use :hg:`incoming` if you want to see what would have been added
5577 by a pull at the time you issued this command. If you then decide
5514 by a pull at the time you issued this command. If you then decide
5578 to add those changes to the repository, you should use :hg:`pull
5515 to add those changes to the repository, you should use :hg:`pull
5579 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5516 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5580
5517
5581 If SOURCE is omitted, the 'default' path will be used.
5518 If SOURCE is omitted, the 'default' path will be used.
5582 See :hg:`help urls` for more information.
5519 See :hg:`help urls` for more information.
5583
5520
5584 Specifying bookmark as ``.`` is equivalent to specifying the active
5521 Specifying bookmark as ``.`` is equivalent to specifying the active
5585 bookmark's name.
5522 bookmark's name.
5586
5523
5587 Returns 0 on success, 1 if an update had unresolved files.
5524 Returns 0 on success, 1 if an update had unresolved files.
5588 """
5525 """
5589 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5526 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5590 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5527 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5591 other = hg.peer(repo, opts, source)
5528 other = hg.peer(repo, opts, source)
5592 try:
5529 try:
5593 revs, checkout = hg.addbranchrevs(repo, other, branches,
5530 revs, checkout = hg.addbranchrevs(repo, other, branches,
5594 opts.get('rev'))
5531 opts.get('rev'))
5595
5532
5596
5533
5597 pullopargs = {}
5534 pullopargs = {}
5598 if opts.get('bookmark'):
5535 if opts.get('bookmark'):
5599 if not revs:
5536 if not revs:
5600 revs = []
5537 revs = []
5601 # The list of bookmark used here is not the one used to actually
5538 # The list of bookmark used here is not the one used to actually
5602 # update the bookmark name. This can result in the revision pulled
5539 # update the bookmark name. This can result in the revision pulled
5603 # not ending up with the name of the bookmark because of a race
5540 # not ending up with the name of the bookmark because of a race
5604 # condition on the server. (See issue 4689 for details)
5541 # condition on the server. (See issue 4689 for details)
5605 remotebookmarks = other.listkeys('bookmarks')
5542 remotebookmarks = other.listkeys('bookmarks')
5606 pullopargs['remotebookmarks'] = remotebookmarks
5543 pullopargs['remotebookmarks'] = remotebookmarks
5607 for b in opts['bookmark']:
5544 for b in opts['bookmark']:
5608 b = repo._bookmarks.expandname(b)
5545 b = repo._bookmarks.expandname(b)
5609 if b not in remotebookmarks:
5546 if b not in remotebookmarks:
5610 raise error.Abort(_('remote bookmark %s not found!') % b)
5547 raise error.Abort(_('remote bookmark %s not found!') % b)
5611 revs.append(remotebookmarks[b])
5548 revs.append(remotebookmarks[b])
5612
5549
5613 if revs:
5550 if revs:
5614 try:
5551 try:
5615 # When 'rev' is a bookmark name, we cannot guarantee that it
5552 # When 'rev' is a bookmark name, we cannot guarantee that it
5616 # will be updated with that name because of a race condition
5553 # will be updated with that name because of a race condition
5617 # server side. (See issue 4689 for details)
5554 # server side. (See issue 4689 for details)
5618 oldrevs = revs
5555 oldrevs = revs
5619 revs = [] # actually, nodes
5556 revs = [] # actually, nodes
5620 for r in oldrevs:
5557 for r in oldrevs:
5621 node = other.lookup(r)
5558 node = other.lookup(r)
5622 revs.append(node)
5559 revs.append(node)
5623 if r == checkout:
5560 if r == checkout:
5624 checkout = node
5561 checkout = node
5625 except error.CapabilityError:
5562 except error.CapabilityError:
5626 err = _("other repository doesn't support revision lookup, "
5563 err = _("other repository doesn't support revision lookup, "
5627 "so a rev cannot be specified.")
5564 "so a rev cannot be specified.")
5628 raise error.Abort(err)
5565 raise error.Abort(err)
5629
5566
5630 pullopargs.update(opts.get('opargs', {}))
5567 pullopargs.update(opts.get('opargs', {}))
5631 modheads = exchange.pull(repo, other, heads=revs,
5568 modheads = exchange.pull(repo, other, heads=revs,
5632 force=opts.get('force'),
5569 force=opts.get('force'),
5633 bookmarks=opts.get('bookmark', ()),
5570 bookmarks=opts.get('bookmark', ()),
5634 opargs=pullopargs).cgresult
5571 opargs=pullopargs).cgresult
5635
5572
5636 # brev is a name, which might be a bookmark to be activated at
5573 # brev is a name, which might be a bookmark to be activated at
5637 # the end of the update. In other words, it is an explicit
5574 # the end of the update. In other words, it is an explicit
5638 # destination of the update
5575 # destination of the update
5639 brev = None
5576 brev = None
5640
5577
5641 if checkout:
5578 if checkout:
5642 checkout = str(repo.changelog.rev(checkout))
5579 checkout = str(repo.changelog.rev(checkout))
5643
5580
5644 # order below depends on implementation of
5581 # order below depends on implementation of
5645 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5582 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5646 # because 'checkout' is determined without it.
5583 # because 'checkout' is determined without it.
5647 if opts.get('rev'):
5584 if opts.get('rev'):
5648 brev = opts['rev'][0]
5585 brev = opts['rev'][0]
5649 elif opts.get('branch'):
5586 elif opts.get('branch'):
5650 brev = opts['branch'][0]
5587 brev = opts['branch'][0]
5651 else:
5588 else:
5652 brev = branches[0]
5589 brev = branches[0]
5653 repo._subtoppath = source
5590 repo._subtoppath = source
5654 try:
5591 try:
5655 ret = postincoming(ui, repo, modheads, opts.get('update'),
5592 ret = postincoming(ui, repo, modheads, opts.get('update'),
5656 checkout, brev)
5593 checkout, brev)
5657
5594
5658 finally:
5595 finally:
5659 del repo._subtoppath
5596 del repo._subtoppath
5660
5597
5661 finally:
5598 finally:
5662 other.close()
5599 other.close()
5663 return ret
5600 return ret
5664
5601
5665 @command('^push',
5602 @command('^push',
5666 [('f', 'force', None, _('force push')),
5603 [('f', 'force', None, _('force push')),
5667 ('r', 'rev', [],
5604 ('r', 'rev', [],
5668 _('a changeset intended to be included in the destination'),
5605 _('a changeset intended to be included in the destination'),
5669 _('REV')),
5606 _('REV')),
5670 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5607 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5671 ('b', 'branch', [],
5608 ('b', 'branch', [],
5672 _('a specific branch you would like to push'), _('BRANCH')),
5609 _('a specific branch you would like to push'), _('BRANCH')),
5673 ('', 'new-branch', False, _('allow pushing a new branch')),
5610 ('', 'new-branch', False, _('allow pushing a new branch')),
5674 ] + remoteopts,
5611 ] + remoteopts,
5675 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5612 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5676 def push(ui, repo, dest=None, **opts):
5613 def push(ui, repo, dest=None, **opts):
5677 """push changes to the specified destination
5614 """push changes to the specified destination
5678
5615
5679 Push changesets from the local repository to the specified
5616 Push changesets from the local repository to the specified
5680 destination.
5617 destination.
5681
5618
5682 This operation is symmetrical to pull: it is identical to a pull
5619 This operation is symmetrical to pull: it is identical to a pull
5683 in the destination repository from the current one.
5620 in the destination repository from the current one.
5684
5621
5685 By default, push will not allow creation of new heads at the
5622 By default, push will not allow creation of new heads at the
5686 destination, since multiple heads would make it unclear which head
5623 destination, since multiple heads would make it unclear which head
5687 to use. In this situation, it is recommended to pull and merge
5624 to use. In this situation, it is recommended to pull and merge
5688 before pushing.
5625 before pushing.
5689
5626
5690 Use --new-branch if you want to allow push to create a new named
5627 Use --new-branch if you want to allow push to create a new named
5691 branch that is not present at the destination. This allows you to
5628 branch that is not present at the destination. This allows you to
5692 only create a new branch without forcing other changes.
5629 only create a new branch without forcing other changes.
5693
5630
5694 .. note::
5631 .. note::
5695
5632
5696 Extra care should be taken with the -f/--force option,
5633 Extra care should be taken with the -f/--force option,
5697 which will push all new heads on all branches, an action which will
5634 which will push all new heads on all branches, an action which will
5698 almost always cause confusion for collaborators.
5635 almost always cause confusion for collaborators.
5699
5636
5700 If -r/--rev is used, the specified revision and all its ancestors
5637 If -r/--rev is used, the specified revision and all its ancestors
5701 will be pushed to the remote repository.
5638 will be pushed to the remote repository.
5702
5639
5703 If -B/--bookmark is used, the specified bookmarked revision, its
5640 If -B/--bookmark is used, the specified bookmarked revision, its
5704 ancestors, and the bookmark will be pushed to the remote
5641 ancestors, and the bookmark will be pushed to the remote
5705 repository. Specifying ``.`` is equivalent to specifying the active
5642 repository. Specifying ``.`` is equivalent to specifying the active
5706 bookmark's name.
5643 bookmark's name.
5707
5644
5708 Please see :hg:`help urls` for important details about ``ssh://``
5645 Please see :hg:`help urls` for important details about ``ssh://``
5709 URLs. If DESTINATION is omitted, a default path will be used.
5646 URLs. If DESTINATION is omitted, a default path will be used.
5710
5647
5711 Returns 0 if push was successful, 1 if nothing to push.
5648 Returns 0 if push was successful, 1 if nothing to push.
5712 """
5649 """
5713
5650
5714 if opts.get('bookmark'):
5651 if opts.get('bookmark'):
5715 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5652 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5716 for b in opts['bookmark']:
5653 for b in opts['bookmark']:
5717 # translate -B options to -r so changesets get pushed
5654 # translate -B options to -r so changesets get pushed
5718 b = repo._bookmarks.expandname(b)
5655 b = repo._bookmarks.expandname(b)
5719 if b in repo._bookmarks:
5656 if b in repo._bookmarks:
5720 opts.setdefault('rev', []).append(b)
5657 opts.setdefault('rev', []).append(b)
5721 else:
5658 else:
5722 # if we try to push a deleted bookmark, translate it to null
5659 # if we try to push a deleted bookmark, translate it to null
5723 # this lets simultaneous -r, -b options continue working
5660 # this lets simultaneous -r, -b options continue working
5724 opts.setdefault('rev', []).append("null")
5661 opts.setdefault('rev', []).append("null")
5725
5662
5726 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5663 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5727 if not path:
5664 if not path:
5728 raise error.Abort(_('default repository not configured!'),
5665 raise error.Abort(_('default repository not configured!'),
5729 hint=_("see 'hg help config.paths'"))
5666 hint=_("see 'hg help config.paths'"))
5730 dest = path.pushloc or path.loc
5667 dest = path.pushloc or path.loc
5731 branches = (path.branch, opts.get('branch') or [])
5668 branches = (path.branch, opts.get('branch') or [])
5732 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5669 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5733 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5670 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5734 other = hg.peer(repo, opts, dest)
5671 other = hg.peer(repo, opts, dest)
5735
5672
5736 if revs:
5673 if revs:
5737 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5674 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5738 if not revs:
5675 if not revs:
5739 raise error.Abort(_("specified revisions evaluate to an empty set"),
5676 raise error.Abort(_("specified revisions evaluate to an empty set"),
5740 hint=_("use different revision arguments"))
5677 hint=_("use different revision arguments"))
5741 elif path.pushrev:
5678 elif path.pushrev:
5742 # It doesn't make any sense to specify ancestor revisions. So limit
5679 # It doesn't make any sense to specify ancestor revisions. So limit
5743 # to DAG heads to make discovery simpler.
5680 # to DAG heads to make discovery simpler.
5744 expr = revset.formatspec('heads(%r)', path.pushrev)
5681 expr = revset.formatspec('heads(%r)', path.pushrev)
5745 revs = scmutil.revrange(repo, [expr])
5682 revs = scmutil.revrange(repo, [expr])
5746 revs = [repo[rev].node() for rev in revs]
5683 revs = [repo[rev].node() for rev in revs]
5747 if not revs:
5684 if not revs:
5748 raise error.Abort(_('default push revset for path evaluates to an '
5685 raise error.Abort(_('default push revset for path evaluates to an '
5749 'empty set'))
5686 'empty set'))
5750
5687
5751 repo._subtoppath = dest
5688 repo._subtoppath = dest
5752 try:
5689 try:
5753 # push subrepos depth-first for coherent ordering
5690 # push subrepos depth-first for coherent ordering
5754 c = repo['']
5691 c = repo['']
5755 subs = c.substate # only repos that are committed
5692 subs = c.substate # only repos that are committed
5756 for s in sorted(subs):
5693 for s in sorted(subs):
5757 result = c.sub(s).push(opts)
5694 result = c.sub(s).push(opts)
5758 if result == 0:
5695 if result == 0:
5759 return not result
5696 return not result
5760 finally:
5697 finally:
5761 del repo._subtoppath
5698 del repo._subtoppath
5762 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5699 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5763 newbranch=opts.get('new_branch'),
5700 newbranch=opts.get('new_branch'),
5764 bookmarks=opts.get('bookmark', ()),
5701 bookmarks=opts.get('bookmark', ()),
5765 opargs=opts.get('opargs'))
5702 opargs=opts.get('opargs'))
5766
5703
5767 result = not pushop.cgresult
5704 result = not pushop.cgresult
5768
5705
5769 if pushop.bkresult is not None:
5706 if pushop.bkresult is not None:
5770 if pushop.bkresult == 2:
5707 if pushop.bkresult == 2:
5771 result = 2
5708 result = 2
5772 elif not result and pushop.bkresult:
5709 elif not result and pushop.bkresult:
5773 result = 2
5710 result = 2
5774
5711
5775 return result
5712 return result
5776
5713
5777 @command('recover', [])
5714 @command('recover', [])
5778 def recover(ui, repo):
5715 def recover(ui, repo):
5779 """roll back an interrupted transaction
5716 """roll back an interrupted transaction
5780
5717
5781 Recover from an interrupted commit or pull.
5718 Recover from an interrupted commit or pull.
5782
5719
5783 This command tries to fix the repository status after an
5720 This command tries to fix the repository status after an
5784 interrupted operation. It should only be necessary when Mercurial
5721 interrupted operation. It should only be necessary when Mercurial
5785 suggests it.
5722 suggests it.
5786
5723
5787 Returns 0 if successful, 1 if nothing to recover or verify fails.
5724 Returns 0 if successful, 1 if nothing to recover or verify fails.
5788 """
5725 """
5789 if repo.recover():
5726 if repo.recover():
5790 return hg.verify(repo)
5727 return hg.verify(repo)
5791 return 1
5728 return 1
5792
5729
5793 @command('^remove|rm',
5730 @command('^remove|rm',
5794 [('A', 'after', None, _('record delete for missing files')),
5731 [('A', 'after', None, _('record delete for missing files')),
5795 ('f', 'force', None,
5732 ('f', 'force', None,
5796 _('forget added files, delete modified files')),
5733 _('forget added files, delete modified files')),
5797 ] + subrepoopts + walkopts,
5734 ] + subrepoopts + walkopts,
5798 _('[OPTION]... FILE...'),
5735 _('[OPTION]... FILE...'),
5799 inferrepo=True)
5736 inferrepo=True)
5800 def remove(ui, repo, *pats, **opts):
5737 def remove(ui, repo, *pats, **opts):
5801 """remove the specified files on the next commit
5738 """remove the specified files on the next commit
5802
5739
5803 Schedule the indicated files for removal from the current branch.
5740 Schedule the indicated files for removal from the current branch.
5804
5741
5805 This command schedules the files to be removed at the next commit.
5742 This command schedules the files to be removed at the next commit.
5806 To undo a remove before that, see :hg:`revert`. To undo added
5743 To undo a remove before that, see :hg:`revert`. To undo added
5807 files, see :hg:`forget`.
5744 files, see :hg:`forget`.
5808
5745
5809 .. container:: verbose
5746 .. container:: verbose
5810
5747
5811 -A/--after can be used to remove only files that have already
5748 -A/--after can be used to remove only files that have already
5812 been deleted, -f/--force can be used to force deletion, and -Af
5749 been deleted, -f/--force can be used to force deletion, and -Af
5813 can be used to remove files from the next revision without
5750 can be used to remove files from the next revision without
5814 deleting them from the working directory.
5751 deleting them from the working directory.
5815
5752
5816 The following table details the behavior of remove for different
5753 The following table details the behavior of remove for different
5817 file states (columns) and option combinations (rows). The file
5754 file states (columns) and option combinations (rows). The file
5818 states are Added [A], Clean [C], Modified [M] and Missing [!]
5755 states are Added [A], Clean [C], Modified [M] and Missing [!]
5819 (as reported by :hg:`status`). The actions are Warn, Remove
5756 (as reported by :hg:`status`). The actions are Warn, Remove
5820 (from branch) and Delete (from disk):
5757 (from branch) and Delete (from disk):
5821
5758
5822 ========= == == == ==
5759 ========= == == == ==
5823 opt/state A C M !
5760 opt/state A C M !
5824 ========= == == == ==
5761 ========= == == == ==
5825 none W RD W R
5762 none W RD W R
5826 -f R RD RD R
5763 -f R RD RD R
5827 -A W W W R
5764 -A W W W R
5828 -Af R R R R
5765 -Af R R R R
5829 ========= == == == ==
5766 ========= == == == ==
5830
5767
5831 .. note::
5768 .. note::
5832
5769
5833 :hg:`remove` never deletes files in Added [A] state from the
5770 :hg:`remove` never deletes files in Added [A] state from the
5834 working directory, not even if ``--force`` is specified.
5771 working directory, not even if ``--force`` is specified.
5835
5772
5836 Returns 0 on success, 1 if any warnings encountered.
5773 Returns 0 on success, 1 if any warnings encountered.
5837 """
5774 """
5838
5775
5839 after, force = opts.get('after'), opts.get('force')
5776 after, force = opts.get('after'), opts.get('force')
5840 if not pats and not after:
5777 if not pats and not after:
5841 raise error.Abort(_('no files specified'))
5778 raise error.Abort(_('no files specified'))
5842
5779
5843 m = scmutil.match(repo[None], pats, opts)
5780 m = scmutil.match(repo[None], pats, opts)
5844 subrepos = opts.get('subrepos')
5781 subrepos = opts.get('subrepos')
5845 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5782 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5846
5783
5847 @command('rename|move|mv',
5784 @command('rename|move|mv',
5848 [('A', 'after', None, _('record a rename that has already occurred')),
5785 [('A', 'after', None, _('record a rename that has already occurred')),
5849 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5786 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5850 ] + walkopts + dryrunopts,
5787 ] + walkopts + dryrunopts,
5851 _('[OPTION]... SOURCE... DEST'))
5788 _('[OPTION]... SOURCE... DEST'))
5852 def rename(ui, repo, *pats, **opts):
5789 def rename(ui, repo, *pats, **opts):
5853 """rename files; equivalent of copy + remove
5790 """rename files; equivalent of copy + remove
5854
5791
5855 Mark dest as copies of sources; mark sources for deletion. If dest
5792 Mark dest as copies of sources; mark sources for deletion. If dest
5856 is a directory, copies are put in that directory. If dest is a
5793 is a directory, copies are put in that directory. If dest is a
5857 file, there can only be one source.
5794 file, there can only be one source.
5858
5795
5859 By default, this command copies the contents of files as they
5796 By default, this command copies the contents of files as they
5860 exist in the working directory. If invoked with -A/--after, the
5797 exist in the working directory. If invoked with -A/--after, the
5861 operation is recorded, but no copying is performed.
5798 operation is recorded, but no copying is performed.
5862
5799
5863 This command takes effect at the next commit. To undo a rename
5800 This command takes effect at the next commit. To undo a rename
5864 before that, see :hg:`revert`.
5801 before that, see :hg:`revert`.
5865
5802
5866 Returns 0 on success, 1 if errors are encountered.
5803 Returns 0 on success, 1 if errors are encountered.
5867 """
5804 """
5868 with repo.wlock(False):
5805 with repo.wlock(False):
5869 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5806 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5870
5807
5871 @command('resolve',
5808 @command('resolve',
5872 [('a', 'all', None, _('select all unresolved files')),
5809 [('a', 'all', None, _('select all unresolved files')),
5873 ('l', 'list', None, _('list state of files needing merge')),
5810 ('l', 'list', None, _('list state of files needing merge')),
5874 ('m', 'mark', None, _('mark files as resolved')),
5811 ('m', 'mark', None, _('mark files as resolved')),
5875 ('u', 'unmark', None, _('mark files as unresolved')),
5812 ('u', 'unmark', None, _('mark files as unresolved')),
5876 ('n', 'no-status', None, _('hide status prefix'))]
5813 ('n', 'no-status', None, _('hide status prefix'))]
5877 + mergetoolopts + walkopts + formatteropts,
5814 + mergetoolopts + walkopts + formatteropts,
5878 _('[OPTION]... [FILE]...'),
5815 _('[OPTION]... [FILE]...'),
5879 inferrepo=True)
5816 inferrepo=True)
5880 def resolve(ui, repo, *pats, **opts):
5817 def resolve(ui, repo, *pats, **opts):
5881 """redo merges or set/view the merge status of files
5818 """redo merges or set/view the merge status of files
5882
5819
5883 Merges with unresolved conflicts are often the result of
5820 Merges with unresolved conflicts are often the result of
5884 non-interactive merging using the ``internal:merge`` configuration
5821 non-interactive merging using the ``internal:merge`` configuration
5885 setting, or a command-line merge tool like ``diff3``. The resolve
5822 setting, or a command-line merge tool like ``diff3``. The resolve
5886 command is used to manage the files involved in a merge, after
5823 command is used to manage the files involved in a merge, after
5887 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5824 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5888 working directory must have two parents). See :hg:`help
5825 working directory must have two parents). See :hg:`help
5889 merge-tools` for information on configuring merge tools.
5826 merge-tools` for information on configuring merge tools.
5890
5827
5891 The resolve command can be used in the following ways:
5828 The resolve command can be used in the following ways:
5892
5829
5893 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5830 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5894 files, discarding any previous merge attempts. Re-merging is not
5831 files, discarding any previous merge attempts. Re-merging is not
5895 performed for files already marked as resolved. Use ``--all/-a``
5832 performed for files already marked as resolved. Use ``--all/-a``
5896 to select all unresolved files. ``--tool`` can be used to specify
5833 to select all unresolved files. ``--tool`` can be used to specify
5897 the merge tool used for the given files. It overrides the HGMERGE
5834 the merge tool used for the given files. It overrides the HGMERGE
5898 environment variable and your configuration files. Previous file
5835 environment variable and your configuration files. Previous file
5899 contents are saved with a ``.orig`` suffix.
5836 contents are saved with a ``.orig`` suffix.
5900
5837
5901 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5838 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5902 (e.g. after having manually fixed-up the files). The default is
5839 (e.g. after having manually fixed-up the files). The default is
5903 to mark all unresolved files.
5840 to mark all unresolved files.
5904
5841
5905 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5842 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5906 default is to mark all resolved files.
5843 default is to mark all resolved files.
5907
5844
5908 - :hg:`resolve -l`: list files which had or still have conflicts.
5845 - :hg:`resolve -l`: list files which had or still have conflicts.
5909 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5846 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5910
5847
5911 .. note::
5848 .. note::
5912
5849
5913 Mercurial will not let you commit files with unresolved merge
5850 Mercurial will not let you commit files with unresolved merge
5914 conflicts. You must use :hg:`resolve -m ...` before you can
5851 conflicts. You must use :hg:`resolve -m ...` before you can
5915 commit after a conflicting merge.
5852 commit after a conflicting merge.
5916
5853
5917 Returns 0 on success, 1 if any files fail a resolve attempt.
5854 Returns 0 on success, 1 if any files fail a resolve attempt.
5918 """
5855 """
5919
5856
5920 flaglist = 'all mark unmark list no_status'.split()
5857 flaglist = 'all mark unmark list no_status'.split()
5921 all, mark, unmark, show, nostatus = \
5858 all, mark, unmark, show, nostatus = \
5922 [opts.get(o) for o in flaglist]
5859 [opts.get(o) for o in flaglist]
5923
5860
5924 if (show and (mark or unmark)) or (mark and unmark):
5861 if (show and (mark or unmark)) or (mark and unmark):
5925 raise error.Abort(_("too many options specified"))
5862 raise error.Abort(_("too many options specified"))
5926 if pats and all:
5863 if pats and all:
5927 raise error.Abort(_("can't specify --all and patterns"))
5864 raise error.Abort(_("can't specify --all and patterns"))
5928 if not (all or pats or show or mark or unmark):
5865 if not (all or pats or show or mark or unmark):
5929 raise error.Abort(_('no files or directories specified'),
5866 raise error.Abort(_('no files or directories specified'),
5930 hint=('use --all to re-merge all unresolved files'))
5867 hint=('use --all to re-merge all unresolved files'))
5931
5868
5932 if show:
5869 if show:
5933 fm = ui.formatter('resolve', opts)
5870 fm = ui.formatter('resolve', opts)
5934 ms = mergemod.mergestate.read(repo)
5871 ms = mergemod.mergestate.read(repo)
5935 m = scmutil.match(repo[None], pats, opts)
5872 m = scmutil.match(repo[None], pats, opts)
5936 for f in ms:
5873 for f in ms:
5937 if not m(f):
5874 if not m(f):
5938 continue
5875 continue
5939 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5876 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5940 'd': 'driverresolved'}[ms[f]]
5877 'd': 'driverresolved'}[ms[f]]
5941 fm.startitem()
5878 fm.startitem()
5942 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5879 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5943 fm.write('path', '%s\n', f, label=l)
5880 fm.write('path', '%s\n', f, label=l)
5944 fm.end()
5881 fm.end()
5945 return 0
5882 return 0
5946
5883
5947 with repo.wlock():
5884 with repo.wlock():
5948 ms = mergemod.mergestate.read(repo)
5885 ms = mergemod.mergestate.read(repo)
5949
5886
5950 if not (ms.active() or repo.dirstate.p2() != nullid):
5887 if not (ms.active() or repo.dirstate.p2() != nullid):
5951 raise error.Abort(
5888 raise error.Abort(
5952 _('resolve command not applicable when not merging'))
5889 _('resolve command not applicable when not merging'))
5953
5890
5954 wctx = repo[None]
5891 wctx = repo[None]
5955
5892
5956 if ms.mergedriver and ms.mdstate() == 'u':
5893 if ms.mergedriver and ms.mdstate() == 'u':
5957 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5894 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5958 ms.commit()
5895 ms.commit()
5959 # allow mark and unmark to go through
5896 # allow mark and unmark to go through
5960 if not mark and not unmark and not proceed:
5897 if not mark and not unmark and not proceed:
5961 return 1
5898 return 1
5962
5899
5963 m = scmutil.match(wctx, pats, opts)
5900 m = scmutil.match(wctx, pats, opts)
5964 ret = 0
5901 ret = 0
5965 didwork = False
5902 didwork = False
5966 runconclude = False
5903 runconclude = False
5967
5904
5968 tocomplete = []
5905 tocomplete = []
5969 for f in ms:
5906 for f in ms:
5970 if not m(f):
5907 if not m(f):
5971 continue
5908 continue
5972
5909
5973 didwork = True
5910 didwork = True
5974
5911
5975 # don't let driver-resolved files be marked, and run the conclude
5912 # don't let driver-resolved files be marked, and run the conclude
5976 # step if asked to resolve
5913 # step if asked to resolve
5977 if ms[f] == "d":
5914 if ms[f] == "d":
5978 exact = m.exact(f)
5915 exact = m.exact(f)
5979 if mark:
5916 if mark:
5980 if exact:
5917 if exact:
5981 ui.warn(_('not marking %s as it is driver-resolved\n')
5918 ui.warn(_('not marking %s as it is driver-resolved\n')
5982 % f)
5919 % f)
5983 elif unmark:
5920 elif unmark:
5984 if exact:
5921 if exact:
5985 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5922 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5986 % f)
5923 % f)
5987 else:
5924 else:
5988 runconclude = True
5925 runconclude = True
5989 continue
5926 continue
5990
5927
5991 if mark:
5928 if mark:
5992 ms.mark(f, "r")
5929 ms.mark(f, "r")
5993 elif unmark:
5930 elif unmark:
5994 ms.mark(f, "u")
5931 ms.mark(f, "u")
5995 else:
5932 else:
5996 # backup pre-resolve (merge uses .orig for its own purposes)
5933 # backup pre-resolve (merge uses .orig for its own purposes)
5997 a = repo.wjoin(f)
5934 a = repo.wjoin(f)
5998 try:
5935 try:
5999 util.copyfile(a, a + ".resolve")
5936 util.copyfile(a, a + ".resolve")
6000 except (IOError, OSError) as inst:
5937 except (IOError, OSError) as inst:
6001 if inst.errno != errno.ENOENT:
5938 if inst.errno != errno.ENOENT:
6002 raise
5939 raise
6003
5940
6004 try:
5941 try:
6005 # preresolve file
5942 # preresolve file
6006 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5943 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6007 'resolve')
5944 'resolve')
6008 complete, r = ms.preresolve(f, wctx)
5945 complete, r = ms.preresolve(f, wctx)
6009 if not complete:
5946 if not complete:
6010 tocomplete.append(f)
5947 tocomplete.append(f)
6011 elif r:
5948 elif r:
6012 ret = 1
5949 ret = 1
6013 finally:
5950 finally:
6014 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5951 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6015 ms.commit()
5952 ms.commit()
6016
5953
6017 # replace filemerge's .orig file with our resolve file, but only
5954 # replace filemerge's .orig file with our resolve file, but only
6018 # for merges that are complete
5955 # for merges that are complete
6019 if complete:
5956 if complete:
6020 try:
5957 try:
6021 util.rename(a + ".resolve",
5958 util.rename(a + ".resolve",
6022 scmutil.origpath(ui, repo, a))
5959 scmutil.origpath(ui, repo, a))
6023 except OSError as inst:
5960 except OSError as inst:
6024 if inst.errno != errno.ENOENT:
5961 if inst.errno != errno.ENOENT:
6025 raise
5962 raise
6026
5963
6027 for f in tocomplete:
5964 for f in tocomplete:
6028 try:
5965 try:
6029 # resolve file
5966 # resolve file
6030 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5967 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6031 'resolve')
5968 'resolve')
6032 r = ms.resolve(f, wctx)
5969 r = ms.resolve(f, wctx)
6033 if r:
5970 if r:
6034 ret = 1
5971 ret = 1
6035 finally:
5972 finally:
6036 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5973 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6037 ms.commit()
5974 ms.commit()
6038
5975
6039 # replace filemerge's .orig file with our resolve file
5976 # replace filemerge's .orig file with our resolve file
6040 a = repo.wjoin(f)
5977 a = repo.wjoin(f)
6041 try:
5978 try:
6042 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5979 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6043 except OSError as inst:
5980 except OSError as inst:
6044 if inst.errno != errno.ENOENT:
5981 if inst.errno != errno.ENOENT:
6045 raise
5982 raise
6046
5983
6047 ms.commit()
5984 ms.commit()
6048 ms.recordactions()
5985 ms.recordactions()
6049
5986
6050 if not didwork and pats:
5987 if not didwork and pats:
6051 hint = None
5988 hint = None
6052 if not any([p for p in pats if p.find(':') >= 0]):
5989 if not any([p for p in pats if p.find(':') >= 0]):
6053 pats = ['path:%s' % p for p in pats]
5990 pats = ['path:%s' % p for p in pats]
6054 m = scmutil.match(wctx, pats, opts)
5991 m = scmutil.match(wctx, pats, opts)
6055 for f in ms:
5992 for f in ms:
6056 if not m(f):
5993 if not m(f):
6057 continue
5994 continue
6058 flags = ''.join(['-%s ' % o[0] for o in flaglist
5995 flags = ''.join(['-%s ' % o[0] for o in flaglist
6059 if opts.get(o)])
5996 if opts.get(o)])
6060 hint = _("(try: hg resolve %s%s)\n") % (
5997 hint = _("(try: hg resolve %s%s)\n") % (
6061 flags,
5998 flags,
6062 ' '.join(pats))
5999 ' '.join(pats))
6063 break
6000 break
6064 ui.warn(_("arguments do not match paths that need resolving\n"))
6001 ui.warn(_("arguments do not match paths that need resolving\n"))
6065 if hint:
6002 if hint:
6066 ui.warn(hint)
6003 ui.warn(hint)
6067 elif ms.mergedriver and ms.mdstate() != 's':
6004 elif ms.mergedriver and ms.mdstate() != 's':
6068 # run conclude step when either a driver-resolved file is requested
6005 # run conclude step when either a driver-resolved file is requested
6069 # or there are no driver-resolved files
6006 # or there are no driver-resolved files
6070 # we can't use 'ret' to determine whether any files are unresolved
6007 # we can't use 'ret' to determine whether any files are unresolved
6071 # because we might not have tried to resolve some
6008 # because we might not have tried to resolve some
6072 if ((runconclude or not list(ms.driverresolved()))
6009 if ((runconclude or not list(ms.driverresolved()))
6073 and not list(ms.unresolved())):
6010 and not list(ms.unresolved())):
6074 proceed = mergemod.driverconclude(repo, ms, wctx)
6011 proceed = mergemod.driverconclude(repo, ms, wctx)
6075 ms.commit()
6012 ms.commit()
6076 if not proceed:
6013 if not proceed:
6077 return 1
6014 return 1
6078
6015
6079 # Nudge users into finishing an unfinished operation
6016 # Nudge users into finishing an unfinished operation
6080 unresolvedf = list(ms.unresolved())
6017 unresolvedf = list(ms.unresolved())
6081 driverresolvedf = list(ms.driverresolved())
6018 driverresolvedf = list(ms.driverresolved())
6082 if not unresolvedf and not driverresolvedf:
6019 if not unresolvedf and not driverresolvedf:
6083 ui.status(_('(no more unresolved files)\n'))
6020 ui.status(_('(no more unresolved files)\n'))
6084 cmdutil.checkafterresolved(repo)
6021 cmdutil.checkafterresolved(repo)
6085 elif not unresolvedf:
6022 elif not unresolvedf:
6086 ui.status(_('(no more unresolved files -- '
6023 ui.status(_('(no more unresolved files -- '
6087 'run "hg resolve --all" to conclude)\n'))
6024 'run "hg resolve --all" to conclude)\n'))
6088
6025
6089 return ret
6026 return ret
6090
6027
6091 @command('revert',
6028 @command('revert',
6092 [('a', 'all', None, _('revert all changes when no arguments given')),
6029 [('a', 'all', None, _('revert all changes when no arguments given')),
6093 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6030 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6094 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6031 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6095 ('C', 'no-backup', None, _('do not save backup copies of files')),
6032 ('C', 'no-backup', None, _('do not save backup copies of files')),
6096 ('i', 'interactive', None,
6033 ('i', 'interactive', None,
6097 _('interactively select the changes (EXPERIMENTAL)')),
6034 _('interactively select the changes (EXPERIMENTAL)')),
6098 ] + walkopts + dryrunopts,
6035 ] + walkopts + dryrunopts,
6099 _('[OPTION]... [-r REV] [NAME]...'))
6036 _('[OPTION]... [-r REV] [NAME]...'))
6100 def revert(ui, repo, *pats, **opts):
6037 def revert(ui, repo, *pats, **opts):
6101 """restore files to their checkout state
6038 """restore files to their checkout state
6102
6039
6103 .. note::
6040 .. note::
6104
6041
6105 To check out earlier revisions, you should use :hg:`update REV`.
6042 To check out earlier revisions, you should use :hg:`update REV`.
6106 To cancel an uncommitted merge (and lose your changes),
6043 To cancel an uncommitted merge (and lose your changes),
6107 use :hg:`update --clean .`.
6044 use :hg:`update --clean .`.
6108
6045
6109 With no revision specified, revert the specified files or directories
6046 With no revision specified, revert the specified files or directories
6110 to the contents they had in the parent of the working directory.
6047 to the contents they had in the parent of the working directory.
6111 This restores the contents of files to an unmodified
6048 This restores the contents of files to an unmodified
6112 state and unschedules adds, removes, copies, and renames. If the
6049 state and unschedules adds, removes, copies, and renames. If the
6113 working directory has two parents, you must explicitly specify a
6050 working directory has two parents, you must explicitly specify a
6114 revision.
6051 revision.
6115
6052
6116 Using the -r/--rev or -d/--date options, revert the given files or
6053 Using the -r/--rev or -d/--date options, revert the given files or
6117 directories to their states as of a specific revision. Because
6054 directories to their states as of a specific revision. Because
6118 revert does not change the working directory parents, this will
6055 revert does not change the working directory parents, this will
6119 cause these files to appear modified. This can be helpful to "back
6056 cause these files to appear modified. This can be helpful to "back
6120 out" some or all of an earlier change. See :hg:`backout` for a
6057 out" some or all of an earlier change. See :hg:`backout` for a
6121 related method.
6058 related method.
6122
6059
6123 Modified files are saved with a .orig suffix before reverting.
6060 Modified files are saved with a .orig suffix before reverting.
6124 To disable these backups, use --no-backup. It is possible to store
6061 To disable these backups, use --no-backup. It is possible to store
6125 the backup files in a custom directory relative to the root of the
6062 the backup files in a custom directory relative to the root of the
6126 repository by setting the ``ui.origbackuppath`` configuration
6063 repository by setting the ``ui.origbackuppath`` configuration
6127 option.
6064 option.
6128
6065
6129 See :hg:`help dates` for a list of formats valid for -d/--date.
6066 See :hg:`help dates` for a list of formats valid for -d/--date.
6130
6067
6131 See :hg:`help backout` for a way to reverse the effect of an
6068 See :hg:`help backout` for a way to reverse the effect of an
6132 earlier changeset.
6069 earlier changeset.
6133
6070
6134 Returns 0 on success.
6071 Returns 0 on success.
6135 """
6072 """
6136
6073
6137 if opts.get("date"):
6074 if opts.get("date"):
6138 if opts.get("rev"):
6075 if opts.get("rev"):
6139 raise error.Abort(_("you can't specify a revision and a date"))
6076 raise error.Abort(_("you can't specify a revision and a date"))
6140 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6077 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6141
6078
6142 parent, p2 = repo.dirstate.parents()
6079 parent, p2 = repo.dirstate.parents()
6143 if not opts.get('rev') and p2 != nullid:
6080 if not opts.get('rev') and p2 != nullid:
6144 # revert after merge is a trap for new users (issue2915)
6081 # revert after merge is a trap for new users (issue2915)
6145 raise error.Abort(_('uncommitted merge with no revision specified'),
6082 raise error.Abort(_('uncommitted merge with no revision specified'),
6146 hint=_("use 'hg update' or see 'hg help revert'"))
6083 hint=_("use 'hg update' or see 'hg help revert'"))
6147
6084
6148 ctx = scmutil.revsingle(repo, opts.get('rev'))
6085 ctx = scmutil.revsingle(repo, opts.get('rev'))
6149
6086
6150 if (not (pats or opts.get('include') or opts.get('exclude') or
6087 if (not (pats or opts.get('include') or opts.get('exclude') or
6151 opts.get('all') or opts.get('interactive'))):
6088 opts.get('all') or opts.get('interactive'))):
6152 msg = _("no files or directories specified")
6089 msg = _("no files or directories specified")
6153 if p2 != nullid:
6090 if p2 != nullid:
6154 hint = _("uncommitted merge, use --all to discard all changes,"
6091 hint = _("uncommitted merge, use --all to discard all changes,"
6155 " or 'hg update -C .' to abort the merge")
6092 " or 'hg update -C .' to abort the merge")
6156 raise error.Abort(msg, hint=hint)
6093 raise error.Abort(msg, hint=hint)
6157 dirty = any(repo.status())
6094 dirty = any(repo.status())
6158 node = ctx.node()
6095 node = ctx.node()
6159 if node != parent:
6096 if node != parent:
6160 if dirty:
6097 if dirty:
6161 hint = _("uncommitted changes, use --all to discard all"
6098 hint = _("uncommitted changes, use --all to discard all"
6162 " changes, or 'hg update %s' to update") % ctx.rev()
6099 " changes, or 'hg update %s' to update") % ctx.rev()
6163 else:
6100 else:
6164 hint = _("use --all to revert all files,"
6101 hint = _("use --all to revert all files,"
6165 " or 'hg update %s' to update") % ctx.rev()
6102 " or 'hg update %s' to update") % ctx.rev()
6166 elif dirty:
6103 elif dirty:
6167 hint = _("uncommitted changes, use --all to discard all changes")
6104 hint = _("uncommitted changes, use --all to discard all changes")
6168 else:
6105 else:
6169 hint = _("use --all to revert all files")
6106 hint = _("use --all to revert all files")
6170 raise error.Abort(msg, hint=hint)
6107 raise error.Abort(msg, hint=hint)
6171
6108
6172 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6109 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6173
6110
6174 @command('rollback', dryrunopts +
6111 @command('rollback', dryrunopts +
6175 [('f', 'force', False, _('ignore safety measures'))])
6112 [('f', 'force', False, _('ignore safety measures'))])
6176 def rollback(ui, repo, **opts):
6113 def rollback(ui, repo, **opts):
6177 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6114 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6178
6115
6179 Please use :hg:`commit --amend` instead of rollback to correct
6116 Please use :hg:`commit --amend` instead of rollback to correct
6180 mistakes in the last commit.
6117 mistakes in the last commit.
6181
6118
6182 This command should be used with care. There is only one level of
6119 This command should be used with care. There is only one level of
6183 rollback, and there is no way to undo a rollback. It will also
6120 rollback, and there is no way to undo a rollback. It will also
6184 restore the dirstate at the time of the last transaction, losing
6121 restore the dirstate at the time of the last transaction, losing
6185 any dirstate changes since that time. This command does not alter
6122 any dirstate changes since that time. This command does not alter
6186 the working directory.
6123 the working directory.
6187
6124
6188 Transactions are used to encapsulate the effects of all commands
6125 Transactions are used to encapsulate the effects of all commands
6189 that create new changesets or propagate existing changesets into a
6126 that create new changesets or propagate existing changesets into a
6190 repository.
6127 repository.
6191
6128
6192 .. container:: verbose
6129 .. container:: verbose
6193
6130
6194 For example, the following commands are transactional, and their
6131 For example, the following commands are transactional, and their
6195 effects can be rolled back:
6132 effects can be rolled back:
6196
6133
6197 - commit
6134 - commit
6198 - import
6135 - import
6199 - pull
6136 - pull
6200 - push (with this repository as the destination)
6137 - push (with this repository as the destination)
6201 - unbundle
6138 - unbundle
6202
6139
6203 To avoid permanent data loss, rollback will refuse to rollback a
6140 To avoid permanent data loss, rollback will refuse to rollback a
6204 commit transaction if it isn't checked out. Use --force to
6141 commit transaction if it isn't checked out. Use --force to
6205 override this protection.
6142 override this protection.
6206
6143
6207 The rollback command can be entirely disabled by setting the
6144 The rollback command can be entirely disabled by setting the
6208 ``ui.rollback`` configuration setting to false. If you're here
6145 ``ui.rollback`` configuration setting to false. If you're here
6209 because you want to use rollback and it's disabled, you can
6146 because you want to use rollback and it's disabled, you can
6210 re-enable the command by setting ``ui.rollback`` to true.
6147 re-enable the command by setting ``ui.rollback`` to true.
6211
6148
6212 This command is not intended for use on public repositories. Once
6149 This command is not intended for use on public repositories. Once
6213 changes are visible for pull by other users, rolling a transaction
6150 changes are visible for pull by other users, rolling a transaction
6214 back locally is ineffective (someone else may already have pulled
6151 back locally is ineffective (someone else may already have pulled
6215 the changes). Furthermore, a race is possible with readers of the
6152 the changes). Furthermore, a race is possible with readers of the
6216 repository; for example an in-progress pull from the repository
6153 repository; for example an in-progress pull from the repository
6217 may fail if a rollback is performed.
6154 may fail if a rollback is performed.
6218
6155
6219 Returns 0 on success, 1 if no rollback data is available.
6156 Returns 0 on success, 1 if no rollback data is available.
6220 """
6157 """
6221 if not ui.configbool('ui', 'rollback', True):
6158 if not ui.configbool('ui', 'rollback', True):
6222 raise error.Abort(_('rollback is disabled because it is unsafe'),
6159 raise error.Abort(_('rollback is disabled because it is unsafe'),
6223 hint=('see `hg help -v rollback` for information'))
6160 hint=('see `hg help -v rollback` for information'))
6224 return repo.rollback(dryrun=opts.get('dry_run'),
6161 return repo.rollback(dryrun=opts.get('dry_run'),
6225 force=opts.get('force'))
6162 force=opts.get('force'))
6226
6163
6227 @command('root', [])
6164 @command('root', [])
6228 def root(ui, repo):
6165 def root(ui, repo):
6229 """print the root (top) of the current working directory
6166 """print the root (top) of the current working directory
6230
6167
6231 Print the root directory of the current repository.
6168 Print the root directory of the current repository.
6232
6169
6233 Returns 0 on success.
6170 Returns 0 on success.
6234 """
6171 """
6235 ui.write(repo.root + "\n")
6172 ui.write(repo.root + "\n")
6236
6173
6237 @command('^serve',
6174 @command('^serve',
6238 [('A', 'accesslog', '', _('name of access log file to write to'),
6175 [('A', 'accesslog', '', _('name of access log file to write to'),
6239 _('FILE')),
6176 _('FILE')),
6240 ('d', 'daemon', None, _('run server in background')),
6177 ('d', 'daemon', None, _('run server in background')),
6241 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6178 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6242 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6179 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6243 # use string type, then we can check if something was passed
6180 # use string type, then we can check if something was passed
6244 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6181 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6245 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6182 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6246 _('ADDR')),
6183 _('ADDR')),
6247 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6184 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6248 _('PREFIX')),
6185 _('PREFIX')),
6249 ('n', 'name', '',
6186 ('n', 'name', '',
6250 _('name to show in web pages (default: working directory)'), _('NAME')),
6187 _('name to show in web pages (default: working directory)'), _('NAME')),
6251 ('', 'web-conf', '',
6188 ('', 'web-conf', '',
6252 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6189 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6253 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6190 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6254 _('FILE')),
6191 _('FILE')),
6255 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6192 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6256 ('', 'stdio', None, _('for remote clients')),
6193 ('', 'stdio', None, _('for remote clients')),
6257 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6194 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6258 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6195 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6259 ('', 'style', '', _('template style to use'), _('STYLE')),
6196 ('', 'style', '', _('template style to use'), _('STYLE')),
6260 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6197 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6261 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6198 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6262 _('[OPTION]...'),
6199 _('[OPTION]...'),
6263 optionalrepo=True)
6200 optionalrepo=True)
6264 def serve(ui, repo, **opts):
6201 def serve(ui, repo, **opts):
6265 """start stand-alone webserver
6202 """start stand-alone webserver
6266
6203
6267 Start a local HTTP repository browser and pull server. You can use
6204 Start a local HTTP repository browser and pull server. You can use
6268 this for ad-hoc sharing and browsing of repositories. It is
6205 this for ad-hoc sharing and browsing of repositories. It is
6269 recommended to use a real web server to serve a repository for
6206 recommended to use a real web server to serve a repository for
6270 longer periods of time.
6207 longer periods of time.
6271
6208
6272 Please note that the server does not implement access control.
6209 Please note that the server does not implement access control.
6273 This means that, by default, anybody can read from the server and
6210 This means that, by default, anybody can read from the server and
6274 nobody can write to it by default. Set the ``web.allow_push``
6211 nobody can write to it by default. Set the ``web.allow_push``
6275 option to ``*`` to allow everybody to push to the server. You
6212 option to ``*`` to allow everybody to push to the server. You
6276 should use a real web server if you need to authenticate users.
6213 should use a real web server if you need to authenticate users.
6277
6214
6278 By default, the server logs accesses to stdout and errors to
6215 By default, the server logs accesses to stdout and errors to
6279 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6216 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6280 files.
6217 files.
6281
6218
6282 To have the server choose a free port number to listen on, specify
6219 To have the server choose a free port number to listen on, specify
6283 a port number of 0; in this case, the server will print the port
6220 a port number of 0; in this case, the server will print the port
6284 number it uses.
6221 number it uses.
6285
6222
6286 Returns 0 on success.
6223 Returns 0 on success.
6287 """
6224 """
6288
6225
6289 if opts["stdio"] and opts["cmdserver"]:
6226 if opts["stdio"] and opts["cmdserver"]:
6290 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6227 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6291
6228
6292 if opts["stdio"]:
6229 if opts["stdio"]:
6293 if repo is None:
6230 if repo is None:
6294 raise error.RepoError(_("there is no Mercurial repository here"
6231 raise error.RepoError(_("there is no Mercurial repository here"
6295 " (.hg not found)"))
6232 " (.hg not found)"))
6296 s = sshserver.sshserver(ui, repo)
6233 s = sshserver.sshserver(ui, repo)
6297 s.serve_forever()
6234 s.serve_forever()
6298
6235
6299 service = server.createservice(ui, repo, opts)
6236 service = server.createservice(ui, repo, opts)
6300 return server.runservice(opts, initfn=service.init, runfn=service.run)
6237 return server.runservice(opts, initfn=service.init, runfn=service.run)
6301
6238
6302 @command('^status|st',
6239 @command('^status|st',
6303 [('A', 'all', None, _('show status of all files')),
6240 [('A', 'all', None, _('show status of all files')),
6304 ('m', 'modified', None, _('show only modified files')),
6241 ('m', 'modified', None, _('show only modified files')),
6305 ('a', 'added', None, _('show only added files')),
6242 ('a', 'added', None, _('show only added files')),
6306 ('r', 'removed', None, _('show only removed files')),
6243 ('r', 'removed', None, _('show only removed files')),
6307 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6244 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6308 ('c', 'clean', None, _('show only files without changes')),
6245 ('c', 'clean', None, _('show only files without changes')),
6309 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6246 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6310 ('i', 'ignored', None, _('show only ignored files')),
6247 ('i', 'ignored', None, _('show only ignored files')),
6311 ('n', 'no-status', None, _('hide status prefix')),
6248 ('n', 'no-status', None, _('hide status prefix')),
6312 ('C', 'copies', None, _('show source of copied files')),
6249 ('C', 'copies', None, _('show source of copied files')),
6313 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6250 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6314 ('', 'rev', [], _('show difference from revision'), _('REV')),
6251 ('', 'rev', [], _('show difference from revision'), _('REV')),
6315 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6252 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6316 ] + walkopts + subrepoopts + formatteropts,
6253 ] + walkopts + subrepoopts + formatteropts,
6317 _('[OPTION]... [FILE]...'),
6254 _('[OPTION]... [FILE]...'),
6318 inferrepo=True)
6255 inferrepo=True)
6319 def status(ui, repo, *pats, **opts):
6256 def status(ui, repo, *pats, **opts):
6320 """show changed files in the working directory
6257 """show changed files in the working directory
6321
6258
6322 Show status of files in the repository. If names are given, only
6259 Show status of files in the repository. If names are given, only
6323 files that match are shown. Files that are clean or ignored or
6260 files that match are shown. Files that are clean or ignored or
6324 the source of a copy/move operation, are not listed unless
6261 the source of a copy/move operation, are not listed unless
6325 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6262 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6326 Unless options described with "show only ..." are given, the
6263 Unless options described with "show only ..." are given, the
6327 options -mardu are used.
6264 options -mardu are used.
6328
6265
6329 Option -q/--quiet hides untracked (unknown and ignored) files
6266 Option -q/--quiet hides untracked (unknown and ignored) files
6330 unless explicitly requested with -u/--unknown or -i/--ignored.
6267 unless explicitly requested with -u/--unknown or -i/--ignored.
6331
6268
6332 .. note::
6269 .. note::
6333
6270
6334 :hg:`status` may appear to disagree with diff if permissions have
6271 :hg:`status` may appear to disagree with diff if permissions have
6335 changed or a merge has occurred. The standard diff format does
6272 changed or a merge has occurred. The standard diff format does
6336 not report permission changes and diff only reports changes
6273 not report permission changes and diff only reports changes
6337 relative to one merge parent.
6274 relative to one merge parent.
6338
6275
6339 If one revision is given, it is used as the base revision.
6276 If one revision is given, it is used as the base revision.
6340 If two revisions are given, the differences between them are
6277 If two revisions are given, the differences between them are
6341 shown. The --change option can also be used as a shortcut to list
6278 shown. The --change option can also be used as a shortcut to list
6342 the changed files of a revision from its first parent.
6279 the changed files of a revision from its first parent.
6343
6280
6344 The codes used to show the status of files are::
6281 The codes used to show the status of files are::
6345
6282
6346 M = modified
6283 M = modified
6347 A = added
6284 A = added
6348 R = removed
6285 R = removed
6349 C = clean
6286 C = clean
6350 ! = missing (deleted by non-hg command, but still tracked)
6287 ! = missing (deleted by non-hg command, but still tracked)
6351 ? = not tracked
6288 ? = not tracked
6352 I = ignored
6289 I = ignored
6353 = origin of the previous file (with --copies)
6290 = origin of the previous file (with --copies)
6354
6291
6355 .. container:: verbose
6292 .. container:: verbose
6356
6293
6357 Examples:
6294 Examples:
6358
6295
6359 - show changes in the working directory relative to a
6296 - show changes in the working directory relative to a
6360 changeset::
6297 changeset::
6361
6298
6362 hg status --rev 9353
6299 hg status --rev 9353
6363
6300
6364 - show changes in the working directory relative to the
6301 - show changes in the working directory relative to the
6365 current directory (see :hg:`help patterns` for more information)::
6302 current directory (see :hg:`help patterns` for more information)::
6366
6303
6367 hg status re:
6304 hg status re:
6368
6305
6369 - show all changes including copies in an existing changeset::
6306 - show all changes including copies in an existing changeset::
6370
6307
6371 hg status --copies --change 9353
6308 hg status --copies --change 9353
6372
6309
6373 - get a NUL separated list of added files, suitable for xargs::
6310 - get a NUL separated list of added files, suitable for xargs::
6374
6311
6375 hg status -an0
6312 hg status -an0
6376
6313
6377 Returns 0 on success.
6314 Returns 0 on success.
6378 """
6315 """
6379
6316
6380 revs = opts.get('rev')
6317 revs = opts.get('rev')
6381 change = opts.get('change')
6318 change = opts.get('change')
6382
6319
6383 if revs and change:
6320 if revs and change:
6384 msg = _('cannot specify --rev and --change at the same time')
6321 msg = _('cannot specify --rev and --change at the same time')
6385 raise error.Abort(msg)
6322 raise error.Abort(msg)
6386 elif change:
6323 elif change:
6387 node2 = scmutil.revsingle(repo, change, None).node()
6324 node2 = scmutil.revsingle(repo, change, None).node()
6388 node1 = repo[node2].p1().node()
6325 node1 = repo[node2].p1().node()
6389 else:
6326 else:
6390 node1, node2 = scmutil.revpair(repo, revs)
6327 node1, node2 = scmutil.revpair(repo, revs)
6391
6328
6392 if pats:
6329 if pats:
6393 cwd = repo.getcwd()
6330 cwd = repo.getcwd()
6394 else:
6331 else:
6395 cwd = ''
6332 cwd = ''
6396
6333
6397 if opts.get('print0'):
6334 if opts.get('print0'):
6398 end = '\0'
6335 end = '\0'
6399 else:
6336 else:
6400 end = '\n'
6337 end = '\n'
6401 copy = {}
6338 copy = {}
6402 states = 'modified added removed deleted unknown ignored clean'.split()
6339 states = 'modified added removed deleted unknown ignored clean'.split()
6403 show = [k for k in states if opts.get(k)]
6340 show = [k for k in states if opts.get(k)]
6404 if opts.get('all'):
6341 if opts.get('all'):
6405 show += ui.quiet and (states[:4] + ['clean']) or states
6342 show += ui.quiet and (states[:4] + ['clean']) or states
6406 if not show:
6343 if not show:
6407 if ui.quiet:
6344 if ui.quiet:
6408 show = states[:4]
6345 show = states[:4]
6409 else:
6346 else:
6410 show = states[:5]
6347 show = states[:5]
6411
6348
6412 m = scmutil.match(repo[node2], pats, opts)
6349 m = scmutil.match(repo[node2], pats, opts)
6413 stat = repo.status(node1, node2, m,
6350 stat = repo.status(node1, node2, m,
6414 'ignored' in show, 'clean' in show, 'unknown' in show,
6351 'ignored' in show, 'clean' in show, 'unknown' in show,
6415 opts.get('subrepos'))
6352 opts.get('subrepos'))
6416 changestates = zip(states, 'MAR!?IC', stat)
6353 changestates = zip(states, 'MAR!?IC', stat)
6417
6354
6418 if (opts.get('all') or opts.get('copies')
6355 if (opts.get('all') or opts.get('copies')
6419 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6356 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6420 copy = copies.pathcopies(repo[node1], repo[node2], m)
6357 copy = copies.pathcopies(repo[node1], repo[node2], m)
6421
6358
6422 fm = ui.formatter('status', opts)
6359 fm = ui.formatter('status', opts)
6423 fmt = '%s' + end
6360 fmt = '%s' + end
6424 showchar = not opts.get('no_status')
6361 showchar = not opts.get('no_status')
6425
6362
6426 for state, char, files in changestates:
6363 for state, char, files in changestates:
6427 if state in show:
6364 if state in show:
6428 label = 'status.' + state
6365 label = 'status.' + state
6429 for f in files:
6366 for f in files:
6430 fm.startitem()
6367 fm.startitem()
6431 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6368 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6432 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6369 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6433 if f in copy:
6370 if f in copy:
6434 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6371 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6435 label='status.copied')
6372 label='status.copied')
6436 fm.end()
6373 fm.end()
6437
6374
6438 @command('^summary|sum',
6375 @command('^summary|sum',
6439 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6376 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6440 def summary(ui, repo, **opts):
6377 def summary(ui, repo, **opts):
6441 """summarize working directory state
6378 """summarize working directory state
6442
6379
6443 This generates a brief summary of the working directory state,
6380 This generates a brief summary of the working directory state,
6444 including parents, branch, commit status, phase and available updates.
6381 including parents, branch, commit status, phase and available updates.
6445
6382
6446 With the --remote option, this will check the default paths for
6383 With the --remote option, this will check the default paths for
6447 incoming and outgoing changes. This can be time-consuming.
6384 incoming and outgoing changes. This can be time-consuming.
6448
6385
6449 Returns 0 on success.
6386 Returns 0 on success.
6450 """
6387 """
6451
6388
6452 ctx = repo[None]
6389 ctx = repo[None]
6453 parents = ctx.parents()
6390 parents = ctx.parents()
6454 pnode = parents[0].node()
6391 pnode = parents[0].node()
6455 marks = []
6392 marks = []
6456
6393
6457 ms = None
6394 ms = None
6458 try:
6395 try:
6459 ms = mergemod.mergestate.read(repo)
6396 ms = mergemod.mergestate.read(repo)
6460 except error.UnsupportedMergeRecords as e:
6397 except error.UnsupportedMergeRecords as e:
6461 s = ' '.join(e.recordtypes)
6398 s = ' '.join(e.recordtypes)
6462 ui.warn(
6399 ui.warn(
6463 _('warning: merge state has unsupported record types: %s\n') % s)
6400 _('warning: merge state has unsupported record types: %s\n') % s)
6464 unresolved = 0
6401 unresolved = 0
6465 else:
6402 else:
6466 unresolved = [f for f in ms if ms[f] == 'u']
6403 unresolved = [f for f in ms if ms[f] == 'u']
6467
6404
6468 for p in parents:
6405 for p in parents:
6469 # label with log.changeset (instead of log.parent) since this
6406 # label with log.changeset (instead of log.parent) since this
6470 # shows a working directory parent *changeset*:
6407 # shows a working directory parent *changeset*:
6471 # i18n: column positioning for "hg summary"
6408 # i18n: column positioning for "hg summary"
6472 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6409 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6473 label='log.changeset changeset.%s' % p.phasestr())
6410 label='log.changeset changeset.%s' % p.phasestr())
6474 ui.write(' '.join(p.tags()), label='log.tag')
6411 ui.write(' '.join(p.tags()), label='log.tag')
6475 if p.bookmarks():
6412 if p.bookmarks():
6476 marks.extend(p.bookmarks())
6413 marks.extend(p.bookmarks())
6477 if p.rev() == -1:
6414 if p.rev() == -1:
6478 if not len(repo):
6415 if not len(repo):
6479 ui.write(_(' (empty repository)'))
6416 ui.write(_(' (empty repository)'))
6480 else:
6417 else:
6481 ui.write(_(' (no revision checked out)'))
6418 ui.write(_(' (no revision checked out)'))
6482 ui.write('\n')
6419 ui.write('\n')
6483 if p.description():
6420 if p.description():
6484 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6421 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6485 label='log.summary')
6422 label='log.summary')
6486
6423
6487 branch = ctx.branch()
6424 branch = ctx.branch()
6488 bheads = repo.branchheads(branch)
6425 bheads = repo.branchheads(branch)
6489 # i18n: column positioning for "hg summary"
6426 # i18n: column positioning for "hg summary"
6490 m = _('branch: %s\n') % branch
6427 m = _('branch: %s\n') % branch
6491 if branch != 'default':
6428 if branch != 'default':
6492 ui.write(m, label='log.branch')
6429 ui.write(m, label='log.branch')
6493 else:
6430 else:
6494 ui.status(m, label='log.branch')
6431 ui.status(m, label='log.branch')
6495
6432
6496 if marks:
6433 if marks:
6497 active = repo._activebookmark
6434 active = repo._activebookmark
6498 # i18n: column positioning for "hg summary"
6435 # i18n: column positioning for "hg summary"
6499 ui.write(_('bookmarks:'), label='log.bookmark')
6436 ui.write(_('bookmarks:'), label='log.bookmark')
6500 if active is not None:
6437 if active is not None:
6501 if active in marks:
6438 if active in marks:
6502 ui.write(' *' + active, label=activebookmarklabel)
6439 ui.write(' *' + active, label=activebookmarklabel)
6503 marks.remove(active)
6440 marks.remove(active)
6504 else:
6441 else:
6505 ui.write(' [%s]' % active, label=activebookmarklabel)
6442 ui.write(' [%s]' % active, label=activebookmarklabel)
6506 for m in marks:
6443 for m in marks:
6507 ui.write(' ' + m, label='log.bookmark')
6444 ui.write(' ' + m, label='log.bookmark')
6508 ui.write('\n', label='log.bookmark')
6445 ui.write('\n', label='log.bookmark')
6509
6446
6510 status = repo.status(unknown=True)
6447 status = repo.status(unknown=True)
6511
6448
6512 c = repo.dirstate.copies()
6449 c = repo.dirstate.copies()
6513 copied, renamed = [], []
6450 copied, renamed = [], []
6514 for d, s in c.iteritems():
6451 for d, s in c.iteritems():
6515 if s in status.removed:
6452 if s in status.removed:
6516 status.removed.remove(s)
6453 status.removed.remove(s)
6517 renamed.append(d)
6454 renamed.append(d)
6518 else:
6455 else:
6519 copied.append(d)
6456 copied.append(d)
6520 if d in status.added:
6457 if d in status.added:
6521 status.added.remove(d)
6458 status.added.remove(d)
6522
6459
6523 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6460 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6524
6461
6525 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6462 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6526 (ui.label(_('%d added'), 'status.added'), status.added),
6463 (ui.label(_('%d added'), 'status.added'), status.added),
6527 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6464 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6528 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6465 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6529 (ui.label(_('%d copied'), 'status.copied'), copied),
6466 (ui.label(_('%d copied'), 'status.copied'), copied),
6530 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6467 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6531 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6468 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6532 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6469 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6533 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6470 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6534 t = []
6471 t = []
6535 for l, s in labels:
6472 for l, s in labels:
6536 if s:
6473 if s:
6537 t.append(l % len(s))
6474 t.append(l % len(s))
6538
6475
6539 t = ', '.join(t)
6476 t = ', '.join(t)
6540 cleanworkdir = False
6477 cleanworkdir = False
6541
6478
6542 if repo.vfs.exists('graftstate'):
6479 if repo.vfs.exists('graftstate'):
6543 t += _(' (graft in progress)')
6480 t += _(' (graft in progress)')
6544 if repo.vfs.exists('updatestate'):
6481 if repo.vfs.exists('updatestate'):
6545 t += _(' (interrupted update)')
6482 t += _(' (interrupted update)')
6546 elif len(parents) > 1:
6483 elif len(parents) > 1:
6547 t += _(' (merge)')
6484 t += _(' (merge)')
6548 elif branch != parents[0].branch():
6485 elif branch != parents[0].branch():
6549 t += _(' (new branch)')
6486 t += _(' (new branch)')
6550 elif (parents[0].closesbranch() and
6487 elif (parents[0].closesbranch() and
6551 pnode in repo.branchheads(branch, closed=True)):
6488 pnode in repo.branchheads(branch, closed=True)):
6552 t += _(' (head closed)')
6489 t += _(' (head closed)')
6553 elif not (status.modified or status.added or status.removed or renamed or
6490 elif not (status.modified or status.added or status.removed or renamed or
6554 copied or subs):
6491 copied or subs):
6555 t += _(' (clean)')
6492 t += _(' (clean)')
6556 cleanworkdir = True
6493 cleanworkdir = True
6557 elif pnode not in bheads:
6494 elif pnode not in bheads:
6558 t += _(' (new branch head)')
6495 t += _(' (new branch head)')
6559
6496
6560 if parents:
6497 if parents:
6561 pendingphase = max(p.phase() for p in parents)
6498 pendingphase = max(p.phase() for p in parents)
6562 else:
6499 else:
6563 pendingphase = phases.public
6500 pendingphase = phases.public
6564
6501
6565 if pendingphase > phases.newcommitphase(ui):
6502 if pendingphase > phases.newcommitphase(ui):
6566 t += ' (%s)' % phases.phasenames[pendingphase]
6503 t += ' (%s)' % phases.phasenames[pendingphase]
6567
6504
6568 if cleanworkdir:
6505 if cleanworkdir:
6569 # i18n: column positioning for "hg summary"
6506 # i18n: column positioning for "hg summary"
6570 ui.status(_('commit: %s\n') % t.strip())
6507 ui.status(_('commit: %s\n') % t.strip())
6571 else:
6508 else:
6572 # i18n: column positioning for "hg summary"
6509 # i18n: column positioning for "hg summary"
6573 ui.write(_('commit: %s\n') % t.strip())
6510 ui.write(_('commit: %s\n') % t.strip())
6574
6511
6575 # all ancestors of branch heads - all ancestors of parent = new csets
6512 # all ancestors of branch heads - all ancestors of parent = new csets
6576 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6513 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6577 bheads))
6514 bheads))
6578
6515
6579 if new == 0:
6516 if new == 0:
6580 # i18n: column positioning for "hg summary"
6517 # i18n: column positioning for "hg summary"
6581 ui.status(_('update: (current)\n'))
6518 ui.status(_('update: (current)\n'))
6582 elif pnode not in bheads:
6519 elif pnode not in bheads:
6583 # i18n: column positioning for "hg summary"
6520 # i18n: column positioning for "hg summary"
6584 ui.write(_('update: %d new changesets (update)\n') % new)
6521 ui.write(_('update: %d new changesets (update)\n') % new)
6585 else:
6522 else:
6586 # i18n: column positioning for "hg summary"
6523 # i18n: column positioning for "hg summary"
6587 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6524 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6588 (new, len(bheads)))
6525 (new, len(bheads)))
6589
6526
6590 t = []
6527 t = []
6591 draft = len(repo.revs('draft()'))
6528 draft = len(repo.revs('draft()'))
6592 if draft:
6529 if draft:
6593 t.append(_('%d draft') % draft)
6530 t.append(_('%d draft') % draft)
6594 secret = len(repo.revs('secret()'))
6531 secret = len(repo.revs('secret()'))
6595 if secret:
6532 if secret:
6596 t.append(_('%d secret') % secret)
6533 t.append(_('%d secret') % secret)
6597
6534
6598 if draft or secret:
6535 if draft or secret:
6599 ui.status(_('phases: %s\n') % ', '.join(t))
6536 ui.status(_('phases: %s\n') % ', '.join(t))
6600
6537
6601 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6538 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6602 for trouble in ("unstable", "divergent", "bumped"):
6539 for trouble in ("unstable", "divergent", "bumped"):
6603 numtrouble = len(repo.revs(trouble + "()"))
6540 numtrouble = len(repo.revs(trouble + "()"))
6604 # We write all the possibilities to ease translation
6541 # We write all the possibilities to ease translation
6605 troublemsg = {
6542 troublemsg = {
6606 "unstable": _("unstable: %d changesets"),
6543 "unstable": _("unstable: %d changesets"),
6607 "divergent": _("divergent: %d changesets"),
6544 "divergent": _("divergent: %d changesets"),
6608 "bumped": _("bumped: %d changesets"),
6545 "bumped": _("bumped: %d changesets"),
6609 }
6546 }
6610 if numtrouble > 0:
6547 if numtrouble > 0:
6611 ui.status(troublemsg[trouble] % numtrouble + "\n")
6548 ui.status(troublemsg[trouble] % numtrouble + "\n")
6612
6549
6613 cmdutil.summaryhooks(ui, repo)
6550 cmdutil.summaryhooks(ui, repo)
6614
6551
6615 if opts.get('remote'):
6552 if opts.get('remote'):
6616 needsincoming, needsoutgoing = True, True
6553 needsincoming, needsoutgoing = True, True
6617 else:
6554 else:
6618 needsincoming, needsoutgoing = False, False
6555 needsincoming, needsoutgoing = False, False
6619 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6556 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6620 if i:
6557 if i:
6621 needsincoming = True
6558 needsincoming = True
6622 if o:
6559 if o:
6623 needsoutgoing = True
6560 needsoutgoing = True
6624 if not needsincoming and not needsoutgoing:
6561 if not needsincoming and not needsoutgoing:
6625 return
6562 return
6626
6563
6627 def getincoming():
6564 def getincoming():
6628 source, branches = hg.parseurl(ui.expandpath('default'))
6565 source, branches = hg.parseurl(ui.expandpath('default'))
6629 sbranch = branches[0]
6566 sbranch = branches[0]
6630 try:
6567 try:
6631 other = hg.peer(repo, {}, source)
6568 other = hg.peer(repo, {}, source)
6632 except error.RepoError:
6569 except error.RepoError:
6633 if opts.get('remote'):
6570 if opts.get('remote'):
6634 raise
6571 raise
6635 return source, sbranch, None, None, None
6572 return source, sbranch, None, None, None
6636 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6573 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6637 if revs:
6574 if revs:
6638 revs = [other.lookup(rev) for rev in revs]
6575 revs = [other.lookup(rev) for rev in revs]
6639 ui.debug('comparing with %s\n' % util.hidepassword(source))
6576 ui.debug('comparing with %s\n' % util.hidepassword(source))
6640 repo.ui.pushbuffer()
6577 repo.ui.pushbuffer()
6641 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6578 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6642 repo.ui.popbuffer()
6579 repo.ui.popbuffer()
6643 return source, sbranch, other, commoninc, commoninc[1]
6580 return source, sbranch, other, commoninc, commoninc[1]
6644
6581
6645 if needsincoming:
6582 if needsincoming:
6646 source, sbranch, sother, commoninc, incoming = getincoming()
6583 source, sbranch, sother, commoninc, incoming = getincoming()
6647 else:
6584 else:
6648 source = sbranch = sother = commoninc = incoming = None
6585 source = sbranch = sother = commoninc = incoming = None
6649
6586
6650 def getoutgoing():
6587 def getoutgoing():
6651 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6588 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6652 dbranch = branches[0]
6589 dbranch = branches[0]
6653 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6590 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6654 if source != dest:
6591 if source != dest:
6655 try:
6592 try:
6656 dother = hg.peer(repo, {}, dest)
6593 dother = hg.peer(repo, {}, dest)
6657 except error.RepoError:
6594 except error.RepoError:
6658 if opts.get('remote'):
6595 if opts.get('remote'):
6659 raise
6596 raise
6660 return dest, dbranch, None, None
6597 return dest, dbranch, None, None
6661 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6598 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6662 elif sother is None:
6599 elif sother is None:
6663 # there is no explicit destination peer, but source one is invalid
6600 # there is no explicit destination peer, but source one is invalid
6664 return dest, dbranch, None, None
6601 return dest, dbranch, None, None
6665 else:
6602 else:
6666 dother = sother
6603 dother = sother
6667 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6604 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6668 common = None
6605 common = None
6669 else:
6606 else:
6670 common = commoninc
6607 common = commoninc
6671 if revs:
6608 if revs:
6672 revs = [repo.lookup(rev) for rev in revs]
6609 revs = [repo.lookup(rev) for rev in revs]
6673 repo.ui.pushbuffer()
6610 repo.ui.pushbuffer()
6674 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6611 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6675 commoninc=common)
6612 commoninc=common)
6676 repo.ui.popbuffer()
6613 repo.ui.popbuffer()
6677 return dest, dbranch, dother, outgoing
6614 return dest, dbranch, dother, outgoing
6678
6615
6679 if needsoutgoing:
6616 if needsoutgoing:
6680 dest, dbranch, dother, outgoing = getoutgoing()
6617 dest, dbranch, dother, outgoing = getoutgoing()
6681 else:
6618 else:
6682 dest = dbranch = dother = outgoing = None
6619 dest = dbranch = dother = outgoing = None
6683
6620
6684 if opts.get('remote'):
6621 if opts.get('remote'):
6685 t = []
6622 t = []
6686 if incoming:
6623 if incoming:
6687 t.append(_('1 or more incoming'))
6624 t.append(_('1 or more incoming'))
6688 o = outgoing.missing
6625 o = outgoing.missing
6689 if o:
6626 if o:
6690 t.append(_('%d outgoing') % len(o))
6627 t.append(_('%d outgoing') % len(o))
6691 other = dother or sother
6628 other = dother or sother
6692 if 'bookmarks' in other.listkeys('namespaces'):
6629 if 'bookmarks' in other.listkeys('namespaces'):
6693 counts = bookmarks.summary(repo, other)
6630 counts = bookmarks.summary(repo, other)
6694 if counts[0] > 0:
6631 if counts[0] > 0:
6695 t.append(_('%d incoming bookmarks') % counts[0])
6632 t.append(_('%d incoming bookmarks') % counts[0])
6696 if counts[1] > 0:
6633 if counts[1] > 0:
6697 t.append(_('%d outgoing bookmarks') % counts[1])
6634 t.append(_('%d outgoing bookmarks') % counts[1])
6698
6635
6699 if t:
6636 if t:
6700 # i18n: column positioning for "hg summary"
6637 # i18n: column positioning for "hg summary"
6701 ui.write(_('remote: %s\n') % (', '.join(t)))
6638 ui.write(_('remote: %s\n') % (', '.join(t)))
6702 else:
6639 else:
6703 # i18n: column positioning for "hg summary"
6640 # i18n: column positioning for "hg summary"
6704 ui.status(_('remote: (synced)\n'))
6641 ui.status(_('remote: (synced)\n'))
6705
6642
6706 cmdutil.summaryremotehooks(ui, repo, opts,
6643 cmdutil.summaryremotehooks(ui, repo, opts,
6707 ((source, sbranch, sother, commoninc),
6644 ((source, sbranch, sother, commoninc),
6708 (dest, dbranch, dother, outgoing)))
6645 (dest, dbranch, dother, outgoing)))
6709
6646
6710 @command('tag',
6647 @command('tag',
6711 [('f', 'force', None, _('force tag')),
6648 [('f', 'force', None, _('force tag')),
6712 ('l', 'local', None, _('make the tag local')),
6649 ('l', 'local', None, _('make the tag local')),
6713 ('r', 'rev', '', _('revision to tag'), _('REV')),
6650 ('r', 'rev', '', _('revision to tag'), _('REV')),
6714 ('', 'remove', None, _('remove a tag')),
6651 ('', 'remove', None, _('remove a tag')),
6715 # -l/--local is already there, commitopts cannot be used
6652 # -l/--local is already there, commitopts cannot be used
6716 ('e', 'edit', None, _('invoke editor on commit messages')),
6653 ('e', 'edit', None, _('invoke editor on commit messages')),
6717 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6654 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6718 ] + commitopts2,
6655 ] + commitopts2,
6719 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6656 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6720 def tag(ui, repo, name1, *names, **opts):
6657 def tag(ui, repo, name1, *names, **opts):
6721 """add one or more tags for the current or given revision
6658 """add one or more tags for the current or given revision
6722
6659
6723 Name a particular revision using <name>.
6660 Name a particular revision using <name>.
6724
6661
6725 Tags are used to name particular revisions of the repository and are
6662 Tags are used to name particular revisions of the repository and are
6726 very useful to compare different revisions, to go back to significant
6663 very useful to compare different revisions, to go back to significant
6727 earlier versions or to mark branch points as releases, etc. Changing
6664 earlier versions or to mark branch points as releases, etc. Changing
6728 an existing tag is normally disallowed; use -f/--force to override.
6665 an existing tag is normally disallowed; use -f/--force to override.
6729
6666
6730 If no revision is given, the parent of the working directory is
6667 If no revision is given, the parent of the working directory is
6731 used.
6668 used.
6732
6669
6733 To facilitate version control, distribution, and merging of tags,
6670 To facilitate version control, distribution, and merging of tags,
6734 they are stored as a file named ".hgtags" which is managed similarly
6671 they are stored as a file named ".hgtags" which is managed similarly
6735 to other project files and can be hand-edited if necessary. This
6672 to other project files and can be hand-edited if necessary. This
6736 also means that tagging creates a new commit. The file
6673 also means that tagging creates a new commit. The file
6737 ".hg/localtags" is used for local tags (not shared among
6674 ".hg/localtags" is used for local tags (not shared among
6738 repositories).
6675 repositories).
6739
6676
6740 Tag commits are usually made at the head of a branch. If the parent
6677 Tag commits are usually made at the head of a branch. If the parent
6741 of the working directory is not a branch head, :hg:`tag` aborts; use
6678 of the working directory is not a branch head, :hg:`tag` aborts; use
6742 -f/--force to force the tag commit to be based on a non-head
6679 -f/--force to force the tag commit to be based on a non-head
6743 changeset.
6680 changeset.
6744
6681
6745 See :hg:`help dates` for a list of formats valid for -d/--date.
6682 See :hg:`help dates` for a list of formats valid for -d/--date.
6746
6683
6747 Since tag names have priority over branch names during revision
6684 Since tag names have priority over branch names during revision
6748 lookup, using an existing branch name as a tag name is discouraged.
6685 lookup, using an existing branch name as a tag name is discouraged.
6749
6686
6750 Returns 0 on success.
6687 Returns 0 on success.
6751 """
6688 """
6752 wlock = lock = None
6689 wlock = lock = None
6753 try:
6690 try:
6754 wlock = repo.wlock()
6691 wlock = repo.wlock()
6755 lock = repo.lock()
6692 lock = repo.lock()
6756 rev_ = "."
6693 rev_ = "."
6757 names = [t.strip() for t in (name1,) + names]
6694 names = [t.strip() for t in (name1,) + names]
6758 if len(names) != len(set(names)):
6695 if len(names) != len(set(names)):
6759 raise error.Abort(_('tag names must be unique'))
6696 raise error.Abort(_('tag names must be unique'))
6760 for n in names:
6697 for n in names:
6761 scmutil.checknewlabel(repo, n, 'tag')
6698 scmutil.checknewlabel(repo, n, 'tag')
6762 if not n:
6699 if not n:
6763 raise error.Abort(_('tag names cannot consist entirely of '
6700 raise error.Abort(_('tag names cannot consist entirely of '
6764 'whitespace'))
6701 'whitespace'))
6765 if opts.get('rev') and opts.get('remove'):
6702 if opts.get('rev') and opts.get('remove'):
6766 raise error.Abort(_("--rev and --remove are incompatible"))
6703 raise error.Abort(_("--rev and --remove are incompatible"))
6767 if opts.get('rev'):
6704 if opts.get('rev'):
6768 rev_ = opts['rev']
6705 rev_ = opts['rev']
6769 message = opts.get('message')
6706 message = opts.get('message')
6770 if opts.get('remove'):
6707 if opts.get('remove'):
6771 if opts.get('local'):
6708 if opts.get('local'):
6772 expectedtype = 'local'
6709 expectedtype = 'local'
6773 else:
6710 else:
6774 expectedtype = 'global'
6711 expectedtype = 'global'
6775
6712
6776 for n in names:
6713 for n in names:
6777 if not repo.tagtype(n):
6714 if not repo.tagtype(n):
6778 raise error.Abort(_("tag '%s' does not exist") % n)
6715 raise error.Abort(_("tag '%s' does not exist") % n)
6779 if repo.tagtype(n) != expectedtype:
6716 if repo.tagtype(n) != expectedtype:
6780 if expectedtype == 'global':
6717 if expectedtype == 'global':
6781 raise error.Abort(_("tag '%s' is not a global tag") % n)
6718 raise error.Abort(_("tag '%s' is not a global tag") % n)
6782 else:
6719 else:
6783 raise error.Abort(_("tag '%s' is not a local tag") % n)
6720 raise error.Abort(_("tag '%s' is not a local tag") % n)
6784 rev_ = 'null'
6721 rev_ = 'null'
6785 if not message:
6722 if not message:
6786 # we don't translate commit messages
6723 # we don't translate commit messages
6787 message = 'Removed tag %s' % ', '.join(names)
6724 message = 'Removed tag %s' % ', '.join(names)
6788 elif not opts.get('force'):
6725 elif not opts.get('force'):
6789 for n in names:
6726 for n in names:
6790 if n in repo.tags():
6727 if n in repo.tags():
6791 raise error.Abort(_("tag '%s' already exists "
6728 raise error.Abort(_("tag '%s' already exists "
6792 "(use -f to force)") % n)
6729 "(use -f to force)") % n)
6793 if not opts.get('local'):
6730 if not opts.get('local'):
6794 p1, p2 = repo.dirstate.parents()
6731 p1, p2 = repo.dirstate.parents()
6795 if p2 != nullid:
6732 if p2 != nullid:
6796 raise error.Abort(_('uncommitted merge'))
6733 raise error.Abort(_('uncommitted merge'))
6797 bheads = repo.branchheads()
6734 bheads = repo.branchheads()
6798 if not opts.get('force') and bheads and p1 not in bheads:
6735 if not opts.get('force') and bheads and p1 not in bheads:
6799 raise error.Abort(_('working directory is not at a branch head '
6736 raise error.Abort(_('working directory is not at a branch head '
6800 '(use -f to force)'))
6737 '(use -f to force)'))
6801 r = scmutil.revsingle(repo, rev_).node()
6738 r = scmutil.revsingle(repo, rev_).node()
6802
6739
6803 if not message:
6740 if not message:
6804 # we don't translate commit messages
6741 # we don't translate commit messages
6805 message = ('Added tag %s for changeset %s' %
6742 message = ('Added tag %s for changeset %s' %
6806 (', '.join(names), short(r)))
6743 (', '.join(names), short(r)))
6807
6744
6808 date = opts.get('date')
6745 date = opts.get('date')
6809 if date:
6746 if date:
6810 date = util.parsedate(date)
6747 date = util.parsedate(date)
6811
6748
6812 if opts.get('remove'):
6749 if opts.get('remove'):
6813 editform = 'tag.remove'
6750 editform = 'tag.remove'
6814 else:
6751 else:
6815 editform = 'tag.add'
6752 editform = 'tag.add'
6816 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6753 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6817
6754
6818 # don't allow tagging the null rev
6755 # don't allow tagging the null rev
6819 if (not opts.get('remove') and
6756 if (not opts.get('remove') and
6820 scmutil.revsingle(repo, rev_).rev() == nullrev):
6757 scmutil.revsingle(repo, rev_).rev() == nullrev):
6821 raise error.Abort(_("cannot tag null revision"))
6758 raise error.Abort(_("cannot tag null revision"))
6822
6759
6823 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6760 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6824 editor=editor)
6761 editor=editor)
6825 finally:
6762 finally:
6826 release(lock, wlock)
6763 release(lock, wlock)
6827
6764
6828 @command('tags', formatteropts, '')
6765 @command('tags', formatteropts, '')
6829 def tags(ui, repo, **opts):
6766 def tags(ui, repo, **opts):
6830 """list repository tags
6767 """list repository tags
6831
6768
6832 This lists both regular and local tags. When the -v/--verbose
6769 This lists both regular and local tags. When the -v/--verbose
6833 switch is used, a third column "local" is printed for local tags.
6770 switch is used, a third column "local" is printed for local tags.
6834 When the -q/--quiet switch is used, only the tag name is printed.
6771 When the -q/--quiet switch is used, only the tag name is printed.
6835
6772
6836 Returns 0 on success.
6773 Returns 0 on success.
6837 """
6774 """
6838
6775
6839 fm = ui.formatter('tags', opts)
6776 fm = ui.formatter('tags', opts)
6840 hexfunc = fm.hexfunc
6777 hexfunc = fm.hexfunc
6841 tagtype = ""
6778 tagtype = ""
6842
6779
6843 for t, n in reversed(repo.tagslist()):
6780 for t, n in reversed(repo.tagslist()):
6844 hn = hexfunc(n)
6781 hn = hexfunc(n)
6845 label = 'tags.normal'
6782 label = 'tags.normal'
6846 tagtype = ''
6783 tagtype = ''
6847 if repo.tagtype(t) == 'local':
6784 if repo.tagtype(t) == 'local':
6848 label = 'tags.local'
6785 label = 'tags.local'
6849 tagtype = 'local'
6786 tagtype = 'local'
6850
6787
6851 fm.startitem()
6788 fm.startitem()
6852 fm.write('tag', '%s', t, label=label)
6789 fm.write('tag', '%s', t, label=label)
6853 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6790 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6854 fm.condwrite(not ui.quiet, 'rev node', fmt,
6791 fm.condwrite(not ui.quiet, 'rev node', fmt,
6855 repo.changelog.rev(n), hn, label=label)
6792 repo.changelog.rev(n), hn, label=label)
6856 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6793 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6857 tagtype, label=label)
6794 tagtype, label=label)
6858 fm.plain('\n')
6795 fm.plain('\n')
6859 fm.end()
6796 fm.end()
6860
6797
6861 @command('tip',
6798 @command('tip',
6862 [('p', 'patch', None, _('show patch')),
6799 [('p', 'patch', None, _('show patch')),
6863 ('g', 'git', None, _('use git extended diff format')),
6800 ('g', 'git', None, _('use git extended diff format')),
6864 ] + templateopts,
6801 ] + templateopts,
6865 _('[-p] [-g]'))
6802 _('[-p] [-g]'))
6866 def tip(ui, repo, **opts):
6803 def tip(ui, repo, **opts):
6867 """show the tip revision (DEPRECATED)
6804 """show the tip revision (DEPRECATED)
6868
6805
6869 The tip revision (usually just called the tip) is the changeset
6806 The tip revision (usually just called the tip) is the changeset
6870 most recently added to the repository (and therefore the most
6807 most recently added to the repository (and therefore the most
6871 recently changed head).
6808 recently changed head).
6872
6809
6873 If you have just made a commit, that commit will be the tip. If
6810 If you have just made a commit, that commit will be the tip. If
6874 you have just pulled changes from another repository, the tip of
6811 you have just pulled changes from another repository, the tip of
6875 that repository becomes the current tip. The "tip" tag is special
6812 that repository becomes the current tip. The "tip" tag is special
6876 and cannot be renamed or assigned to a different changeset.
6813 and cannot be renamed or assigned to a different changeset.
6877
6814
6878 This command is deprecated, please use :hg:`heads` instead.
6815 This command is deprecated, please use :hg:`heads` instead.
6879
6816
6880 Returns 0 on success.
6817 Returns 0 on success.
6881 """
6818 """
6882 displayer = cmdutil.show_changeset(ui, repo, opts)
6819 displayer = cmdutil.show_changeset(ui, repo, opts)
6883 displayer.show(repo['tip'])
6820 displayer.show(repo['tip'])
6884 displayer.close()
6821 displayer.close()
6885
6822
6886 @command('unbundle',
6823 @command('unbundle',
6887 [('u', 'update', None,
6824 [('u', 'update', None,
6888 _('update to new branch head if changesets were unbundled'))],
6825 _('update to new branch head if changesets were unbundled'))],
6889 _('[-u] FILE...'))
6826 _('[-u] FILE...'))
6890 def unbundle(ui, repo, fname1, *fnames, **opts):
6827 def unbundle(ui, repo, fname1, *fnames, **opts):
6891 """apply one or more changegroup files
6828 """apply one or more changegroup files
6892
6829
6893 Apply one or more compressed changegroup files generated by the
6830 Apply one or more compressed changegroup files generated by the
6894 bundle command.
6831 bundle command.
6895
6832
6896 Returns 0 on success, 1 if an update has unresolved files.
6833 Returns 0 on success, 1 if an update has unresolved files.
6897 """
6834 """
6898 fnames = (fname1,) + fnames
6835 fnames = (fname1,) + fnames
6899
6836
6900 with repo.lock():
6837 with repo.lock():
6901 for fname in fnames:
6838 for fname in fnames:
6902 f = hg.openpath(ui, fname)
6839 f = hg.openpath(ui, fname)
6903 gen = exchange.readbundle(ui, f, fname)
6840 gen = exchange.readbundle(ui, f, fname)
6904 if isinstance(gen, bundle2.unbundle20):
6841 if isinstance(gen, bundle2.unbundle20):
6905 tr = repo.transaction('unbundle')
6842 tr = repo.transaction('unbundle')
6906 try:
6843 try:
6907 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6844 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6908 url='bundle:' + fname)
6845 url='bundle:' + fname)
6909 tr.close()
6846 tr.close()
6910 except error.BundleUnknownFeatureError as exc:
6847 except error.BundleUnknownFeatureError as exc:
6911 raise error.Abort(_('%s: unknown bundle feature, %s')
6848 raise error.Abort(_('%s: unknown bundle feature, %s')
6912 % (fname, exc),
6849 % (fname, exc),
6913 hint=_("see https://mercurial-scm.org/"
6850 hint=_("see https://mercurial-scm.org/"
6914 "wiki/BundleFeature for more "
6851 "wiki/BundleFeature for more "
6915 "information"))
6852 "information"))
6916 finally:
6853 finally:
6917 if tr:
6854 if tr:
6918 tr.release()
6855 tr.release()
6919 changes = [r.get('return', 0)
6856 changes = [r.get('return', 0)
6920 for r in op.records['changegroup']]
6857 for r in op.records['changegroup']]
6921 modheads = changegroup.combineresults(changes)
6858 modheads = changegroup.combineresults(changes)
6922 elif isinstance(gen, streamclone.streamcloneapplier):
6859 elif isinstance(gen, streamclone.streamcloneapplier):
6923 raise error.Abort(
6860 raise error.Abort(
6924 _('packed bundles cannot be applied with '
6861 _('packed bundles cannot be applied with '
6925 '"hg unbundle"'),
6862 '"hg unbundle"'),
6926 hint=_('use "hg debugapplystreamclonebundle"'))
6863 hint=_('use "hg debugapplystreamclonebundle"'))
6927 else:
6864 else:
6928 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6865 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6929
6866
6930 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
6867 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
6931
6868
6932 @command('^update|up|checkout|co',
6869 @command('^update|up|checkout|co',
6933 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6870 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6934 ('c', 'check', None, _('require clean working directory')),
6871 ('c', 'check', None, _('require clean working directory')),
6935 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6872 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6936 ('r', 'rev', '', _('revision'), _('REV'))
6873 ('r', 'rev', '', _('revision'), _('REV'))
6937 ] + mergetoolopts,
6874 ] + mergetoolopts,
6938 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6875 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6939 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6876 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6940 tool=None):
6877 tool=None):
6941 """update working directory (or switch revisions)
6878 """update working directory (or switch revisions)
6942
6879
6943 Update the repository's working directory to the specified
6880 Update the repository's working directory to the specified
6944 changeset. If no changeset is specified, update to the tip of the
6881 changeset. If no changeset is specified, update to the tip of the
6945 current named branch and move the active bookmark (see :hg:`help
6882 current named branch and move the active bookmark (see :hg:`help
6946 bookmarks`).
6883 bookmarks`).
6947
6884
6948 Update sets the working directory's parent revision to the specified
6885 Update sets the working directory's parent revision to the specified
6949 changeset (see :hg:`help parents`).
6886 changeset (see :hg:`help parents`).
6950
6887
6951 If the changeset is not a descendant or ancestor of the working
6888 If the changeset is not a descendant or ancestor of the working
6952 directory's parent, the update is aborted. With the -c/--check
6889 directory's parent, the update is aborted. With the -c/--check
6953 option, the working directory is checked for uncommitted changes; if
6890 option, the working directory is checked for uncommitted changes; if
6954 none are found, the working directory is updated to the specified
6891 none are found, the working directory is updated to the specified
6955 changeset.
6892 changeset.
6956
6893
6957 .. container:: verbose
6894 .. container:: verbose
6958
6895
6959 The following rules apply when the working directory contains
6896 The following rules apply when the working directory contains
6960 uncommitted changes:
6897 uncommitted changes:
6961
6898
6962 1. If neither -c/--check nor -C/--clean is specified, and if
6899 1. If neither -c/--check nor -C/--clean is specified, and if
6963 the requested changeset is an ancestor or descendant of
6900 the requested changeset is an ancestor or descendant of
6964 the working directory's parent, the uncommitted changes
6901 the working directory's parent, the uncommitted changes
6965 are merged into the requested changeset and the merged
6902 are merged into the requested changeset and the merged
6966 result is left uncommitted. If the requested changeset is
6903 result is left uncommitted. If the requested changeset is
6967 not an ancestor or descendant (that is, it is on another
6904 not an ancestor or descendant (that is, it is on another
6968 branch), the update is aborted and the uncommitted changes
6905 branch), the update is aborted and the uncommitted changes
6969 are preserved.
6906 are preserved.
6970
6907
6971 2. With the -c/--check option, the update is aborted and the
6908 2. With the -c/--check option, the update is aborted and the
6972 uncommitted changes are preserved.
6909 uncommitted changes are preserved.
6973
6910
6974 3. With the -C/--clean option, uncommitted changes are discarded and
6911 3. With the -C/--clean option, uncommitted changes are discarded and
6975 the working directory is updated to the requested changeset.
6912 the working directory is updated to the requested changeset.
6976
6913
6977 To cancel an uncommitted merge (and lose your changes), use
6914 To cancel an uncommitted merge (and lose your changes), use
6978 :hg:`update --clean .`.
6915 :hg:`update --clean .`.
6979
6916
6980 Use null as the changeset to remove the working directory (like
6917 Use null as the changeset to remove the working directory (like
6981 :hg:`clone -U`).
6918 :hg:`clone -U`).
6982
6919
6983 If you want to revert just one file to an older revision, use
6920 If you want to revert just one file to an older revision, use
6984 :hg:`revert [-r REV] NAME`.
6921 :hg:`revert [-r REV] NAME`.
6985
6922
6986 See :hg:`help dates` for a list of formats valid for -d/--date.
6923 See :hg:`help dates` for a list of formats valid for -d/--date.
6987
6924
6988 Returns 0 on success, 1 if there are unresolved files.
6925 Returns 0 on success, 1 if there are unresolved files.
6989 """
6926 """
6990 if rev and node:
6927 if rev and node:
6991 raise error.Abort(_("please specify just one revision"))
6928 raise error.Abort(_("please specify just one revision"))
6992
6929
6993 if rev is None or rev == '':
6930 if rev is None or rev == '':
6994 rev = node
6931 rev = node
6995
6932
6996 if date and rev is not None:
6933 if date and rev is not None:
6997 raise error.Abort(_("you can't specify a revision and a date"))
6934 raise error.Abort(_("you can't specify a revision and a date"))
6998
6935
6999 if check and clean:
6936 if check and clean:
7000 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
6937 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
7001
6938
7002 with repo.wlock():
6939 with repo.wlock():
7003 cmdutil.clearunfinished(repo)
6940 cmdutil.clearunfinished(repo)
7004
6941
7005 if date:
6942 if date:
7006 rev = cmdutil.finddate(ui, repo, date)
6943 rev = cmdutil.finddate(ui, repo, date)
7007
6944
7008 # if we defined a bookmark, we have to remember the original name
6945 # if we defined a bookmark, we have to remember the original name
7009 brev = rev
6946 brev = rev
7010 rev = scmutil.revsingle(repo, rev, rev).rev()
6947 rev = scmutil.revsingle(repo, rev, rev).rev()
7011
6948
7012 if check:
6949 if check:
7013 cmdutil.bailifchanged(repo, merge=False)
6950 cmdutil.bailifchanged(repo, merge=False)
7014
6951
7015 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6952 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
7016
6953
7017 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
6954 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
7018
6955
7019 @command('verify', [])
6956 @command('verify', [])
7020 def verify(ui, repo):
6957 def verify(ui, repo):
7021 """verify the integrity of the repository
6958 """verify the integrity of the repository
7022
6959
7023 Verify the integrity of the current repository.
6960 Verify the integrity of the current repository.
7024
6961
7025 This will perform an extensive check of the repository's
6962 This will perform an extensive check of the repository's
7026 integrity, validating the hashes and checksums of each entry in
6963 integrity, validating the hashes and checksums of each entry in
7027 the changelog, manifest, and tracked files, as well as the
6964 the changelog, manifest, and tracked files, as well as the
7028 integrity of their crosslinks and indices.
6965 integrity of their crosslinks and indices.
7029
6966
7030 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6967 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7031 for more information about recovery from corruption of the
6968 for more information about recovery from corruption of the
7032 repository.
6969 repository.
7033
6970
7034 Returns 0 on success, 1 if errors are encountered.
6971 Returns 0 on success, 1 if errors are encountered.
7035 """
6972 """
7036 return hg.verify(repo)
6973 return hg.verify(repo)
7037
6974
7038 @command('version', [] + formatteropts, norepo=True)
6975 @command('version', [] + formatteropts, norepo=True)
7039 def version_(ui, **opts):
6976 def version_(ui, **opts):
7040 """output version and copyright information"""
6977 """output version and copyright information"""
7041 fm = ui.formatter("version", opts)
6978 fm = ui.formatter("version", opts)
7042 fm.startitem()
6979 fm.startitem()
7043 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6980 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
7044 util.version())
6981 util.version())
7045 license = _(
6982 license = _(
7046 "(see https://mercurial-scm.org for more information)\n"
6983 "(see https://mercurial-scm.org for more information)\n"
7047 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
6984 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7048 "This is free software; see the source for copying conditions. "
6985 "This is free software; see the source for copying conditions. "
7049 "There is NO\nwarranty; "
6986 "There is NO\nwarranty; "
7050 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6987 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7051 )
6988 )
7052 if not ui.quiet:
6989 if not ui.quiet:
7053 fm.plain(license)
6990 fm.plain(license)
7054
6991
7055 if ui.verbose:
6992 if ui.verbose:
7056 fm.plain(_("\nEnabled extensions:\n\n"))
6993 fm.plain(_("\nEnabled extensions:\n\n"))
7057 # format names and versions into columns
6994 # format names and versions into columns
7058 names = []
6995 names = []
7059 vers = []
6996 vers = []
7060 isinternals = []
6997 isinternals = []
7061 for name, module in extensions.extensions():
6998 for name, module in extensions.extensions():
7062 names.append(name)
6999 names.append(name)
7063 vers.append(extensions.moduleversion(module) or None)
7000 vers.append(extensions.moduleversion(module) or None)
7064 isinternals.append(extensions.ismoduleinternal(module))
7001 isinternals.append(extensions.ismoduleinternal(module))
7065 fn = fm.nested("extensions")
7002 fn = fm.nested("extensions")
7066 if names:
7003 if names:
7067 namefmt = " %%-%ds " % max(len(n) for n in names)
7004 namefmt = " %%-%ds " % max(len(n) for n in names)
7068 places = [_("external"), _("internal")]
7005 places = [_("external"), _("internal")]
7069 for n, v, p in zip(names, vers, isinternals):
7006 for n, v, p in zip(names, vers, isinternals):
7070 fn.startitem()
7007 fn.startitem()
7071 fn.condwrite(ui.verbose, "name", namefmt, n)
7008 fn.condwrite(ui.verbose, "name", namefmt, n)
7072 if ui.verbose:
7009 if ui.verbose:
7073 fn.plain("%s " % places[p])
7010 fn.plain("%s " % places[p])
7074 fn.data(bundled=p)
7011 fn.data(bundled=p)
7075 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7012 fn.condwrite(ui.verbose and v, "ver", "%s", v)
7076 if ui.verbose:
7013 if ui.verbose:
7077 fn.plain("\n")
7014 fn.plain("\n")
7078 fn.end()
7015 fn.end()
7079 fm.end()
7016 fm.end()
7080
7017
7081 def loadcmdtable(ui, name, cmdtable):
7018 def loadcmdtable(ui, name, cmdtable):
7082 """Load command functions from specified cmdtable
7019 """Load command functions from specified cmdtable
7083 """
7020 """
7084 overrides = [cmd for cmd in cmdtable if cmd in table]
7021 overrides = [cmd for cmd in cmdtable if cmd in table]
7085 if overrides:
7022 if overrides:
7086 ui.warn(_("extension '%s' overrides commands: %s\n")
7023 ui.warn(_("extension '%s' overrides commands: %s\n")
7087 % (name, " ".join(overrides)))
7024 % (name, " ".join(overrides)))
7088 table.update(cmdtable)
7025 table.update(cmdtable)
@@ -1,359 +1,421 b''
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,
17 bundle2,
18 changegroup,
18 changegroup,
19 cmdutil,
19 cmdutil,
20 commands,
20 commands,
21 context,
21 context,
22 dagparser,
22 dagparser,
23 error,
23 error,
24 exchange,
24 exchange,
25 hg,
25 hg,
26 lock as lockmod,
26 lock as lockmod,
27 revlog,
27 revlog,
28 scmutil,
28 scmutil,
29 simplemerge,
29 simplemerge,
30 streamclone,
30 streamclone,
31 )
31 )
32
32
33 release = lockmod.release
33 release = lockmod.release
34
34
35 # We reuse the command table from commands because it is easier than
35 # We reuse the command table from commands because it is easier than
36 # teaching dispatch about multiple tables.
36 # teaching dispatch about multiple tables.
37 command = cmdutil.command(commands.table)
37 command = cmdutil.command(commands.table)
38
38
39 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
39 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
40 def debugancestor(ui, repo, *args):
40 def debugancestor(ui, repo, *args):
41 """find the ancestor revision of two revisions in a given index"""
41 """find the ancestor revision of two revisions in a given index"""
42 if len(args) == 3:
42 if len(args) == 3:
43 index, rev1, rev2 = args
43 index, rev1, rev2 = args
44 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
44 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
45 lookup = r.lookup
45 lookup = r.lookup
46 elif len(args) == 2:
46 elif len(args) == 2:
47 if not repo:
47 if not repo:
48 raise error.Abort(_('there is no Mercurial repository here '
48 raise error.Abort(_('there is no Mercurial repository here '
49 '(.hg not found)'))
49 '(.hg not found)'))
50 rev1, rev2 = args
50 rev1, rev2 = args
51 r = repo.changelog
51 r = repo.changelog
52 lookup = repo.lookup
52 lookup = repo.lookup
53 else:
53 else:
54 raise error.Abort(_('either two or three arguments required'))
54 raise error.Abort(_('either two or three arguments required'))
55 a = r.ancestor(lookup(rev1), lookup(rev2))
55 a = r.ancestor(lookup(rev1), lookup(rev2))
56 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
56 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
57
57
58 @command('debugbuilddag',
58 @command('debugbuilddag',
59 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
59 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
60 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
60 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
61 ('n', 'new-file', None, _('add new file at each rev'))],
61 ('n', 'new-file', None, _('add new file at each rev'))],
62 _('[OPTION]... [TEXT]'))
62 _('[OPTION]... [TEXT]'))
63 def debugbuilddag(ui, repo, text=None,
63 def debugbuilddag(ui, repo, text=None,
64 mergeable_file=False,
64 mergeable_file=False,
65 overwritten_file=False,
65 overwritten_file=False,
66 new_file=False):
66 new_file=False):
67 """builds a repo with a given DAG from scratch in the current empty repo
67 """builds a repo with a given DAG from scratch in the current empty repo
68
68
69 The description of the DAG is read from stdin if not given on the
69 The description of the DAG is read from stdin if not given on the
70 command line.
70 command line.
71
71
72 Elements:
72 Elements:
73
73
74 - "+n" is a linear run of n nodes based on the current default parent
74 - "+n" is a linear run of n nodes based on the current default parent
75 - "." is a single node based on the current default parent
75 - "." is a single node based on the current default parent
76 - "$" resets the default parent to null (implied at the start);
76 - "$" resets the default parent to null (implied at the start);
77 otherwise the default parent is always the last node created
77 otherwise the default parent is always the last node created
78 - "<p" sets the default parent to the backref p
78 - "<p" sets the default parent to the backref p
79 - "*p" is a fork at parent p, which is a backref
79 - "*p" is a fork at parent p, which is a backref
80 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
80 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
81 - "/p2" is a merge of the preceding node and p2
81 - "/p2" is a merge of the preceding node and p2
82 - ":tag" defines a local tag for the preceding node
82 - ":tag" defines a local tag for the preceding node
83 - "@branch" sets the named branch for subsequent nodes
83 - "@branch" sets the named branch for subsequent nodes
84 - "#...\\n" is a comment up to the end of the line
84 - "#...\\n" is a comment up to the end of the line
85
85
86 Whitespace between the above elements is ignored.
86 Whitespace between the above elements is ignored.
87
87
88 A backref is either
88 A backref is either
89
89
90 - a number n, which references the node curr-n, where curr is the current
90 - a number n, which references the node curr-n, where curr is the current
91 node, or
91 node, or
92 - the name of a local tag you placed earlier using ":tag", or
92 - the name of a local tag you placed earlier using ":tag", or
93 - empty to denote the default parent.
93 - empty to denote the default parent.
94
94
95 All string valued-elements are either strictly alphanumeric, or must
95 All string valued-elements are either strictly alphanumeric, or must
96 be enclosed in double quotes ("..."), with "\\" as escape character.
96 be enclosed in double quotes ("..."), with "\\" as escape character.
97 """
97 """
98
98
99 if text is None:
99 if text is None:
100 ui.status(_("reading DAG from stdin\n"))
100 ui.status(_("reading DAG from stdin\n"))
101 text = ui.fin.read()
101 text = ui.fin.read()
102
102
103 cl = repo.changelog
103 cl = repo.changelog
104 if len(cl) > 0:
104 if len(cl) > 0:
105 raise error.Abort(_('repository is not empty'))
105 raise error.Abort(_('repository is not empty'))
106
106
107 # determine number of revs in DAG
107 # determine number of revs in DAG
108 total = 0
108 total = 0
109 for type, data in dagparser.parsedag(text):
109 for type, data in dagparser.parsedag(text):
110 if type == 'n':
110 if type == 'n':
111 total += 1
111 total += 1
112
112
113 if mergeable_file:
113 if mergeable_file:
114 linesperrev = 2
114 linesperrev = 2
115 # make a file with k lines per rev
115 # make a file with k lines per rev
116 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
116 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
117 initialmergedlines.append("")
117 initialmergedlines.append("")
118
118
119 tags = []
119 tags = []
120
120
121 wlock = lock = tr = None
121 wlock = lock = tr = None
122 try:
122 try:
123 wlock = repo.wlock()
123 wlock = repo.wlock()
124 lock = repo.lock()
124 lock = repo.lock()
125 tr = repo.transaction("builddag")
125 tr = repo.transaction("builddag")
126
126
127 at = -1
127 at = -1
128 atbranch = 'default'
128 atbranch = 'default'
129 nodeids = []
129 nodeids = []
130 id = 0
130 id = 0
131 ui.progress(_('building'), id, unit=_('revisions'), total=total)
131 ui.progress(_('building'), id, unit=_('revisions'), total=total)
132 for type, data in dagparser.parsedag(text):
132 for type, data in dagparser.parsedag(text):
133 if type == 'n':
133 if type == 'n':
134 ui.note(('node %s\n' % str(data)))
134 ui.note(('node %s\n' % str(data)))
135 id, ps = data
135 id, ps = data
136
136
137 files = []
137 files = []
138 fctxs = {}
138 fctxs = {}
139
139
140 p2 = None
140 p2 = None
141 if mergeable_file:
141 if mergeable_file:
142 fn = "mf"
142 fn = "mf"
143 p1 = repo[ps[0]]
143 p1 = repo[ps[0]]
144 if len(ps) > 1:
144 if len(ps) > 1:
145 p2 = repo[ps[1]]
145 p2 = repo[ps[1]]
146 pa = p1.ancestor(p2)
146 pa = p1.ancestor(p2)
147 base, local, other = [x[fn].data() for x in (pa, p1,
147 base, local, other = [x[fn].data() for x in (pa, p1,
148 p2)]
148 p2)]
149 m3 = simplemerge.Merge3Text(base, local, other)
149 m3 = simplemerge.Merge3Text(base, local, other)
150 ml = [l.strip() for l in m3.merge_lines()]
150 ml = [l.strip() for l in m3.merge_lines()]
151 ml.append("")
151 ml.append("")
152 elif at > 0:
152 elif at > 0:
153 ml = p1[fn].data().split("\n")
153 ml = p1[fn].data().split("\n")
154 else:
154 else:
155 ml = initialmergedlines
155 ml = initialmergedlines
156 ml[id * linesperrev] += " r%i" % id
156 ml[id * linesperrev] += " r%i" % id
157 mergedtext = "\n".join(ml)
157 mergedtext = "\n".join(ml)
158 files.append(fn)
158 files.append(fn)
159 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
159 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
160
160
161 if overwritten_file:
161 if overwritten_file:
162 fn = "of"
162 fn = "of"
163 files.append(fn)
163 files.append(fn)
164 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
164 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
165
165
166 if new_file:
166 if new_file:
167 fn = "nf%i" % id
167 fn = "nf%i" % id
168 files.append(fn)
168 files.append(fn)
169 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
169 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
170 if len(ps) > 1:
170 if len(ps) > 1:
171 if not p2:
171 if not p2:
172 p2 = repo[ps[1]]
172 p2 = repo[ps[1]]
173 for fn in p2:
173 for fn in p2:
174 if fn.startswith("nf"):
174 if fn.startswith("nf"):
175 files.append(fn)
175 files.append(fn)
176 fctxs[fn] = p2[fn]
176 fctxs[fn] = p2[fn]
177
177
178 def fctxfn(repo, cx, path):
178 def fctxfn(repo, cx, path):
179 return fctxs.get(path)
179 return fctxs.get(path)
180
180
181 if len(ps) == 0 or ps[0] < 0:
181 if len(ps) == 0 or ps[0] < 0:
182 pars = [None, None]
182 pars = [None, None]
183 elif len(ps) == 1:
183 elif len(ps) == 1:
184 pars = [nodeids[ps[0]], None]
184 pars = [nodeids[ps[0]], None]
185 else:
185 else:
186 pars = [nodeids[p] for p in ps]
186 pars = [nodeids[p] for p in ps]
187 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
187 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
188 date=(id, 0),
188 date=(id, 0),
189 user="debugbuilddag",
189 user="debugbuilddag",
190 extra={'branch': atbranch})
190 extra={'branch': atbranch})
191 nodeid = repo.commitctx(cx)
191 nodeid = repo.commitctx(cx)
192 nodeids.append(nodeid)
192 nodeids.append(nodeid)
193 at = id
193 at = id
194 elif type == 'l':
194 elif type == 'l':
195 id, name = data
195 id, name = data
196 ui.note(('tag %s\n' % name))
196 ui.note(('tag %s\n' % name))
197 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
197 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
198 elif type == 'a':
198 elif type == 'a':
199 ui.note(('branch %s\n' % data))
199 ui.note(('branch %s\n' % data))
200 atbranch = data
200 atbranch = data
201 ui.progress(_('building'), id, unit=_('revisions'), total=total)
201 ui.progress(_('building'), id, unit=_('revisions'), total=total)
202 tr.close()
202 tr.close()
203
203
204 if tags:
204 if tags:
205 repo.vfs.write("localtags", "".join(tags))
205 repo.vfs.write("localtags", "".join(tags))
206 finally:
206 finally:
207 ui.progress(_('building'), None)
207 ui.progress(_('building'), None)
208 release(tr, lock, wlock)
208 release(tr, lock, wlock)
209
209
210 @command('debugbundle',
210 @command('debugbundle',
211 [('a', 'all', None, _('show all details')),
211 [('a', 'all', None, _('show all details')),
212 ('', 'spec', None, _('print the bundlespec of the bundle'))],
212 ('', 'spec', None, _('print the bundlespec of the bundle'))],
213 _('FILE'),
213 _('FILE'),
214 norepo=True)
214 norepo=True)
215 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
215 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
216 """lists the contents of a bundle"""
216 """lists the contents of a bundle"""
217 with hg.openpath(ui, bundlepath) as f:
217 with hg.openpath(ui, bundlepath) as f:
218 if spec:
218 if spec:
219 spec = exchange.getbundlespec(ui, f)
219 spec = exchange.getbundlespec(ui, f)
220 ui.write('%s\n' % spec)
220 ui.write('%s\n' % spec)
221 return
221 return
222
222
223 gen = exchange.readbundle(ui, f, bundlepath)
223 gen = exchange.readbundle(ui, f, bundlepath)
224 if isinstance(gen, bundle2.unbundle20):
224 if isinstance(gen, bundle2.unbundle20):
225 return _debugbundle2(ui, gen, all=all, **opts)
225 return _debugbundle2(ui, gen, all=all, **opts)
226 _debugchangegroup(ui, gen, all=all, **opts)
226 _debugchangegroup(ui, gen, all=all, **opts)
227
227
228 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
228 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
229 indent_string = ' ' * indent
229 indent_string = ' ' * indent
230 if all:
230 if all:
231 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
231 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
232 % indent_string)
232 % indent_string)
233
233
234 def showchunks(named):
234 def showchunks(named):
235 ui.write("\n%s%s\n" % (indent_string, named))
235 ui.write("\n%s%s\n" % (indent_string, named))
236 chain = None
236 chain = None
237 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
237 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
238 node = chunkdata['node']
238 node = chunkdata['node']
239 p1 = chunkdata['p1']
239 p1 = chunkdata['p1']
240 p2 = chunkdata['p2']
240 p2 = chunkdata['p2']
241 cs = chunkdata['cs']
241 cs = chunkdata['cs']
242 deltabase = chunkdata['deltabase']
242 deltabase = chunkdata['deltabase']
243 delta = chunkdata['delta']
243 delta = chunkdata['delta']
244 ui.write("%s%s %s %s %s %s %s\n" %
244 ui.write("%s%s %s %s %s %s %s\n" %
245 (indent_string, hex(node), hex(p1), hex(p2),
245 (indent_string, hex(node), hex(p1), hex(p2),
246 hex(cs), hex(deltabase), len(delta)))
246 hex(cs), hex(deltabase), len(delta)))
247 chain = node
247 chain = node
248
248
249 chunkdata = gen.changelogheader()
249 chunkdata = gen.changelogheader()
250 showchunks("changelog")
250 showchunks("changelog")
251 chunkdata = gen.manifestheader()
251 chunkdata = gen.manifestheader()
252 showchunks("manifest")
252 showchunks("manifest")
253 for chunkdata in iter(gen.filelogheader, {}):
253 for chunkdata in iter(gen.filelogheader, {}):
254 fname = chunkdata['filename']
254 fname = chunkdata['filename']
255 showchunks(fname)
255 showchunks(fname)
256 else:
256 else:
257 if isinstance(gen, bundle2.unbundle20):
257 if isinstance(gen, bundle2.unbundle20):
258 raise error.Abort(_('use debugbundle2 for this file'))
258 raise error.Abort(_('use debugbundle2 for this file'))
259 chunkdata = gen.changelogheader()
259 chunkdata = gen.changelogheader()
260 chain = None
260 chain = None
261 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
261 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
262 node = chunkdata['node']
262 node = chunkdata['node']
263 ui.write("%s%s\n" % (indent_string, hex(node)))
263 ui.write("%s%s\n" % (indent_string, hex(node)))
264 chain = node
264 chain = node
265
265
266 def _debugbundle2(ui, gen, all=None, **opts):
266 def _debugbundle2(ui, gen, all=None, **opts):
267 """lists the contents of a bundle2"""
267 """lists the contents of a bundle2"""
268 if not isinstance(gen, bundle2.unbundle20):
268 if not isinstance(gen, bundle2.unbundle20):
269 raise error.Abort(_('not a bundle2 file'))
269 raise error.Abort(_('not a bundle2 file'))
270 ui.write(('Stream params: %s\n' % repr(gen.params)))
270 ui.write(('Stream params: %s\n' % repr(gen.params)))
271 for part in gen.iterparts():
271 for part in gen.iterparts():
272 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
272 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
273 if part.type == 'changegroup':
273 if part.type == 'changegroup':
274 version = part.params.get('version', '01')
274 version = part.params.get('version', '01')
275 cg = changegroup.getunbundler(version, part, 'UN')
275 cg = changegroup.getunbundler(version, part, 'UN')
276 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
276 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
277
277
278 @command('debugcreatestreamclonebundle', [], 'FILE')
278 @command('debugcreatestreamclonebundle', [], 'FILE')
279 def debugcreatestreamclonebundle(ui, repo, fname):
279 def debugcreatestreamclonebundle(ui, repo, fname):
280 """create a stream clone bundle file
280 """create a stream clone bundle file
281
281
282 Stream bundles are special bundles that are essentially archives of
282 Stream bundles are special bundles that are essentially archives of
283 revlog files. They are commonly used for cloning very quickly.
283 revlog files. They are commonly used for cloning very quickly.
284 """
284 """
285 requirements, gen = streamclone.generatebundlev1(repo)
285 requirements, gen = streamclone.generatebundlev1(repo)
286 changegroup.writechunks(ui, gen, fname)
286 changegroup.writechunks(ui, gen, fname)
287
287
288 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
288 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
289
289
290 @command('debugapplystreamclonebundle', [], 'FILE')
290 @command('debugapplystreamclonebundle', [], 'FILE')
291 def debugapplystreamclonebundle(ui, repo, fname):
291 def debugapplystreamclonebundle(ui, repo, fname):
292 """apply a stream clone bundle file"""
292 """apply a stream clone bundle file"""
293 f = hg.openpath(ui, fname)
293 f = hg.openpath(ui, fname)
294 gen = exchange.readbundle(ui, f, fname)
294 gen = exchange.readbundle(ui, f, fname)
295 gen.apply(repo)
295 gen.apply(repo)
296
296
297 @command('debugcheckstate', [], '')
297 @command('debugcheckstate', [], '')
298 def debugcheckstate(ui, repo):
298 def debugcheckstate(ui, repo):
299 """validate the correctness of the current dirstate"""
299 """validate the correctness of the current dirstate"""
300 parent1, parent2 = repo.dirstate.parents()
300 parent1, parent2 = repo.dirstate.parents()
301 m1 = repo[parent1].manifest()
301 m1 = repo[parent1].manifest()
302 m2 = repo[parent2].manifest()
302 m2 = repo[parent2].manifest()
303 errors = 0
303 errors = 0
304 for f in repo.dirstate:
304 for f in repo.dirstate:
305 state = repo.dirstate[f]
305 state = repo.dirstate[f]
306 if state in "nr" and f not in m1:
306 if state in "nr" and f not in m1:
307 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
307 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
308 errors += 1
308 errors += 1
309 if state in "a" and f in m1:
309 if state in "a" and f in m1:
310 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
310 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
311 errors += 1
311 errors += 1
312 if state in "m" and f not in m1 and f not in m2:
312 if state in "m" and f not in m1 and f not in m2:
313 ui.warn(_("%s in state %s, but not in either manifest\n") %
313 ui.warn(_("%s in state %s, but not in either manifest\n") %
314 (f, state))
314 (f, state))
315 errors += 1
315 errors += 1
316 for f in m1:
316 for f in m1:
317 state = repo.dirstate[f]
317 state = repo.dirstate[f]
318 if state not in "nrm":
318 if state not in "nrm":
319 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
319 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
320 errors += 1
320 errors += 1
321 if errors:
321 if errors:
322 error = _(".hg/dirstate inconsistent with current parent's manifest")
322 error = _(".hg/dirstate inconsistent with current parent's manifest")
323 raise error.Abort(error)
323 raise error.Abort(error)
324
324
325 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
325 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
326 def debugcommands(ui, cmd='', *args):
326 def debugcommands(ui, cmd='', *args):
327 """list all available commands and options"""
327 """list all available commands and options"""
328 for cmd, vals in sorted(commands.table.iteritems()):
328 for cmd, vals in sorted(commands.table.iteritems()):
329 cmd = cmd.split('|')[0].strip('^')
329 cmd = cmd.split('|')[0].strip('^')
330 opts = ', '.join([i[1] for i in vals[1]])
330 opts = ', '.join([i[1] for i in vals[1]])
331 ui.write('%s: %s\n' % (cmd, opts))
331 ui.write('%s: %s\n' % (cmd, opts))
332
332
333 @command('debugcomplete',
333 @command('debugcomplete',
334 [('o', 'options', None, _('show the command options'))],
334 [('o', 'options', None, _('show the command options'))],
335 _('[-o] CMD'),
335 _('[-o] CMD'),
336 norepo=True)
336 norepo=True)
337 def debugcomplete(ui, cmd='', **opts):
337 def debugcomplete(ui, cmd='', **opts):
338 """returns the completion list associated with the given command"""
338 """returns the completion list associated with the given command"""
339
339
340 if opts.get('options'):
340 if opts.get('options'):
341 options = []
341 options = []
342 otables = [commands.globalopts]
342 otables = [commands.globalopts]
343 if cmd:
343 if cmd:
344 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
344 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
345 otables.append(entry[1])
345 otables.append(entry[1])
346 for t in otables:
346 for t in otables:
347 for o in t:
347 for o in t:
348 if "(DEPRECATED)" in o[3]:
348 if "(DEPRECATED)" in o[3]:
349 continue
349 continue
350 if o[0]:
350 if o[0]:
351 options.append('-%s' % o[0])
351 options.append('-%s' % o[0])
352 options.append('--%s' % o[1])
352 options.append('--%s' % o[1])
353 ui.write("%s\n" % "\n".join(options))
353 ui.write("%s\n" % "\n".join(options))
354 return
354 return
355
355
356 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, commands.table)
356 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, commands.table)
357 if ui.verbose:
357 if ui.verbose:
358 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
358 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
359 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
359 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
360
361 @command('debugdag',
362 [('t', 'tags', None, _('use tags as labels')),
363 ('b', 'branches', None, _('annotate with branch names')),
364 ('', 'dots', None, _('use dots for runs')),
365 ('s', 'spaces', None, _('separate elements by spaces'))],
366 _('[OPTION]... [FILE [REV]...]'),
367 optionalrepo=True)
368 def debugdag(ui, repo, file_=None, *revs, **opts):
369 """format the changelog or an index DAG as a concise textual description
370
371 If you pass a revlog index, the revlog's DAG is emitted. If you list
372 revision numbers, they get labeled in the output as rN.
373
374 Otherwise, the changelog DAG of the current repo is emitted.
375 """
376 spaces = opts.get('spaces')
377 dots = opts.get('dots')
378 if file_:
379 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
380 revs = set((int(r) for r in revs))
381 def events():
382 for r in rlog:
383 yield 'n', (r, list(p for p in rlog.parentrevs(r)
384 if p != -1))
385 if r in revs:
386 yield 'l', (r, "r%i" % r)
387 elif repo:
388 cl = repo.changelog
389 tags = opts.get('tags')
390 branches = opts.get('branches')
391 if tags:
392 labels = {}
393 for l, n in repo.tags().items():
394 labels.setdefault(cl.rev(n), []).append(l)
395 def events():
396 b = "default"
397 for r in cl:
398 if branches:
399 newb = cl.read(cl.node(r))[5]['branch']
400 if newb != b:
401 yield 'a', newb
402 b = newb
403 yield 'n', (r, list(p for p in cl.parentrevs(r)
404 if p != -1))
405 if tags:
406 ls = labels.get(r)
407 if ls:
408 for l in ls:
409 yield 'l', (r, l)
410 else:
411 raise error.Abort(_('need repo for changelog dag'))
412
413 for line in dagparser.dagtextlines(events(),
414 addspaces=spaces,
415 wraplabels=True,
416 wrapannotations=True,
417 wrapnonlinear=dots,
418 usedots=dots,
419 maxlinewidth=70):
420 ui.write(line)
421 ui.write("\n")
General Comments 0
You need to be logged in to leave comments. Login now