##// END OF EJS Templates
debugcommands: move 'debugdiscovery' in the module...
Gregory Szorc -
r30517:a3ec6db3 default
parent child Browse files
Show More
@@ -1,6994 +1,6923
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
15 import re
14 import re
16 import shlex
15 import shlex
17 import socket
16 import socket
18 import string
17 import string
19 import sys
18 import sys
20 import tempfile
19 import tempfile
21 import time
20 import time
22
21
23 from .i18n import _
22 from .i18n import _
24 from .node import (
23 from .node import (
25 bin,
24 bin,
26 hex,
25 hex,
27 nullhex,
26 nullhex,
28 nullid,
27 nullid,
29 nullrev,
28 nullrev,
30 short,
29 short,
31 )
30 )
32 from . import (
31 from . import (
33 archival,
32 archival,
34 bookmarks,
33 bookmarks,
35 bundle2,
34 bundle2,
36 changegroup,
35 changegroup,
37 cmdutil,
36 cmdutil,
38 copies,
37 copies,
39 dagutil,
40 destutil,
38 destutil,
41 dirstateguard,
39 dirstateguard,
42 discovery,
40 discovery,
43 encoding,
41 encoding,
44 error,
42 error,
45 exchange,
43 exchange,
46 extensions,
44 extensions,
47 fileset,
45 fileset,
48 formatter,
46 formatter,
49 graphmod,
47 graphmod,
50 hbisect,
48 hbisect,
51 help,
49 help,
52 hg,
50 hg,
53 localrepo,
54 lock as lockmod,
51 lock as lockmod,
55 merge as mergemod,
52 merge as mergemod,
56 minirst,
53 minirst,
57 obsolete,
54 obsolete,
58 patch,
55 patch,
59 phases,
56 phases,
60 policy,
57 policy,
61 pvec,
58 pvec,
62 pycompat,
59 pycompat,
63 repair,
60 repair,
64 revlog,
61 revlog,
65 revset,
62 revset,
66 scmutil,
63 scmutil,
67 server,
64 server,
68 setdiscovery,
69 sshserver,
65 sshserver,
70 sslutil,
66 sslutil,
71 streamclone,
67 streamclone,
72 templatekw,
68 templatekw,
73 templater,
69 templater,
74 treediscovery,
75 ui as uimod,
70 ui as uimod,
76 util,
71 util,
77 )
72 )
78
73
79 release = lockmod.release
74 release = lockmod.release
80
75
81 table = {}
76 table = {}
82
77
83 command = cmdutil.command(table)
78 command = cmdutil.command(table)
84
79
85 # label constants
80 # label constants
86 # until 3.5, bookmarks.current was the advertised name, not
81 # until 3.5, bookmarks.current was the advertised name, not
87 # bookmarks.active, so we must use both to avoid breaking old
82 # bookmarks.active, so we must use both to avoid breaking old
88 # custom styles
83 # custom styles
89 activebookmarklabel = 'bookmarks.active bookmarks.current'
84 activebookmarklabel = 'bookmarks.active bookmarks.current'
90
85
91 # common command options
86 # common command options
92
87
93 globalopts = [
88 globalopts = [
94 ('R', 'repository', '',
89 ('R', 'repository', '',
95 _('repository root directory or name of overlay bundle file'),
90 _('repository root directory or name of overlay bundle file'),
96 _('REPO')),
91 _('REPO')),
97 ('', 'cwd', '',
92 ('', 'cwd', '',
98 _('change working directory'), _('DIR')),
93 _('change working directory'), _('DIR')),
99 ('y', 'noninteractive', None,
94 ('y', 'noninteractive', None,
100 _('do not prompt, automatically pick the first choice for all prompts')),
95 _('do not prompt, automatically pick the first choice for all prompts')),
101 ('q', 'quiet', None, _('suppress output')),
96 ('q', 'quiet', None, _('suppress output')),
102 ('v', 'verbose', None, _('enable additional output')),
97 ('v', 'verbose', None, _('enable additional output')),
103 ('', 'config', [],
98 ('', 'config', [],
104 _('set/override config option (use \'section.name=value\')'),
99 _('set/override config option (use \'section.name=value\')'),
105 _('CONFIG')),
100 _('CONFIG')),
106 ('', 'debug', None, _('enable debugging output')),
101 ('', 'debug', None, _('enable debugging output')),
107 ('', 'debugger', None, _('start debugger')),
102 ('', 'debugger', None, _('start debugger')),
108 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
103 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
109 _('ENCODE')),
104 _('ENCODE')),
110 ('', 'encodingmode', encoding.encodingmode,
105 ('', 'encodingmode', encoding.encodingmode,
111 _('set the charset encoding mode'), _('MODE')),
106 _('set the charset encoding mode'), _('MODE')),
112 ('', 'traceback', None, _('always print a traceback on exception')),
107 ('', 'traceback', None, _('always print a traceback on exception')),
113 ('', 'time', None, _('time how long the command takes')),
108 ('', 'time', None, _('time how long the command takes')),
114 ('', 'profile', None, _('print command execution profile')),
109 ('', 'profile', None, _('print command execution profile')),
115 ('', 'version', None, _('output version information and exit')),
110 ('', 'version', None, _('output version information and exit')),
116 ('h', 'help', None, _('display help and exit')),
111 ('h', 'help', None, _('display help and exit')),
117 ('', 'hidden', False, _('consider hidden changesets')),
112 ('', 'hidden', False, _('consider hidden changesets')),
118 ]
113 ]
119
114
120 dryrunopts = [('n', 'dry-run', None,
115 dryrunopts = [('n', 'dry-run', None,
121 _('do not perform actions, just print output'))]
116 _('do not perform actions, just print output'))]
122
117
123 remoteopts = [
118 remoteopts = [
124 ('e', 'ssh', '',
119 ('e', 'ssh', '',
125 _('specify ssh command to use'), _('CMD')),
120 _('specify ssh command to use'), _('CMD')),
126 ('', 'remotecmd', '',
121 ('', 'remotecmd', '',
127 _('specify hg command to run on the remote side'), _('CMD')),
122 _('specify hg command to run on the remote side'), _('CMD')),
128 ('', 'insecure', None,
123 ('', 'insecure', None,
129 _('do not verify server certificate (ignoring web.cacerts config)')),
124 _('do not verify server certificate (ignoring web.cacerts config)')),
130 ]
125 ]
131
126
132 walkopts = [
127 walkopts = [
133 ('I', 'include', [],
128 ('I', 'include', [],
134 _('include names matching the given patterns'), _('PATTERN')),
129 _('include names matching the given patterns'), _('PATTERN')),
135 ('X', 'exclude', [],
130 ('X', 'exclude', [],
136 _('exclude names matching the given patterns'), _('PATTERN')),
131 _('exclude names matching the given patterns'), _('PATTERN')),
137 ]
132 ]
138
133
139 commitopts = [
134 commitopts = [
140 ('m', 'message', '',
135 ('m', 'message', '',
141 _('use text as commit message'), _('TEXT')),
136 _('use text as commit message'), _('TEXT')),
142 ('l', 'logfile', '',
137 ('l', 'logfile', '',
143 _('read commit message from file'), _('FILE')),
138 _('read commit message from file'), _('FILE')),
144 ]
139 ]
145
140
146 commitopts2 = [
141 commitopts2 = [
147 ('d', 'date', '',
142 ('d', 'date', '',
148 _('record the specified date as commit date'), _('DATE')),
143 _('record the specified date as commit date'), _('DATE')),
149 ('u', 'user', '',
144 ('u', 'user', '',
150 _('record the specified user as committer'), _('USER')),
145 _('record the specified user as committer'), _('USER')),
151 ]
146 ]
152
147
153 # hidden for now
148 # hidden for now
154 formatteropts = [
149 formatteropts = [
155 ('T', 'template', '',
150 ('T', 'template', '',
156 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
151 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
157 ]
152 ]
158
153
159 templateopts = [
154 templateopts = [
160 ('', 'style', '',
155 ('', 'style', '',
161 _('display using template map file (DEPRECATED)'), _('STYLE')),
156 _('display using template map file (DEPRECATED)'), _('STYLE')),
162 ('T', 'template', '',
157 ('T', 'template', '',
163 _('display with template'), _('TEMPLATE')),
158 _('display with template'), _('TEMPLATE')),
164 ]
159 ]
165
160
166 logopts = [
161 logopts = [
167 ('p', 'patch', None, _('show patch')),
162 ('p', 'patch', None, _('show patch')),
168 ('g', 'git', None, _('use git extended diff format')),
163 ('g', 'git', None, _('use git extended diff format')),
169 ('l', 'limit', '',
164 ('l', 'limit', '',
170 _('limit number of changes displayed'), _('NUM')),
165 _('limit number of changes displayed'), _('NUM')),
171 ('M', 'no-merges', None, _('do not show merges')),
166 ('M', 'no-merges', None, _('do not show merges')),
172 ('', 'stat', None, _('output diffstat-style summary of changes')),
167 ('', 'stat', None, _('output diffstat-style summary of changes')),
173 ('G', 'graph', None, _("show the revision DAG")),
168 ('G', 'graph', None, _("show the revision DAG")),
174 ] + templateopts
169 ] + templateopts
175
170
176 diffopts = [
171 diffopts = [
177 ('a', 'text', None, _('treat all files as text')),
172 ('a', 'text', None, _('treat all files as text')),
178 ('g', 'git', None, _('use git extended diff format')),
173 ('g', 'git', None, _('use git extended diff format')),
179 ('', 'nodates', None, _('omit dates from diff headers'))
174 ('', 'nodates', None, _('omit dates from diff headers'))
180 ]
175 ]
181
176
182 diffwsopts = [
177 diffwsopts = [
183 ('w', 'ignore-all-space', None,
178 ('w', 'ignore-all-space', None,
184 _('ignore white space when comparing lines')),
179 _('ignore white space when comparing lines')),
185 ('b', 'ignore-space-change', None,
180 ('b', 'ignore-space-change', None,
186 _('ignore changes in the amount of white space')),
181 _('ignore changes in the amount of white space')),
187 ('B', 'ignore-blank-lines', None,
182 ('B', 'ignore-blank-lines', None,
188 _('ignore changes whose lines are all blank')),
183 _('ignore changes whose lines are all blank')),
189 ]
184 ]
190
185
191 diffopts2 = [
186 diffopts2 = [
192 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
187 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
193 ('p', 'show-function', None, _('show which function each change is in')),
188 ('p', 'show-function', None, _('show which function each change is in')),
194 ('', 'reverse', None, _('produce a diff that undoes the changes')),
189 ('', 'reverse', None, _('produce a diff that undoes the changes')),
195 ] + diffwsopts + [
190 ] + diffwsopts + [
196 ('U', 'unified', '',
191 ('U', 'unified', '',
197 _('number of lines of context to show'), _('NUM')),
192 _('number of lines of context to show'), _('NUM')),
198 ('', 'stat', None, _('output diffstat-style summary of changes')),
193 ('', 'stat', None, _('output diffstat-style summary of changes')),
199 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
194 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
200 ]
195 ]
201
196
202 mergetoolopts = [
197 mergetoolopts = [
203 ('t', 'tool', '', _('specify merge tool')),
198 ('t', 'tool', '', _('specify merge tool')),
204 ]
199 ]
205
200
206 similarityopts = [
201 similarityopts = [
207 ('s', 'similarity', '',
202 ('s', 'similarity', '',
208 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
203 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
209 ]
204 ]
210
205
211 subrepoopts = [
206 subrepoopts = [
212 ('S', 'subrepos', None,
207 ('S', 'subrepos', None,
213 _('recurse into subrepositories'))
208 _('recurse into subrepositories'))
214 ]
209 ]
215
210
216 debugrevlogopts = [
211 debugrevlogopts = [
217 ('c', 'changelog', False, _('open changelog')),
212 ('c', 'changelog', False, _('open changelog')),
218 ('m', 'manifest', False, _('open manifest')),
213 ('m', 'manifest', False, _('open manifest')),
219 ('', 'dir', '', _('open directory manifest')),
214 ('', 'dir', '', _('open directory manifest')),
220 ]
215 ]
221
216
222 # Commands start here, listed alphabetically
217 # Commands start here, listed alphabetically
223
218
224 @command('^add',
219 @command('^add',
225 walkopts + subrepoopts + dryrunopts,
220 walkopts + subrepoopts + dryrunopts,
226 _('[OPTION]... [FILE]...'),
221 _('[OPTION]... [FILE]...'),
227 inferrepo=True)
222 inferrepo=True)
228 def add(ui, repo, *pats, **opts):
223 def add(ui, repo, *pats, **opts):
229 """add the specified files on the next commit
224 """add the specified files on the next commit
230
225
231 Schedule files to be version controlled and added to the
226 Schedule files to be version controlled and added to the
232 repository.
227 repository.
233
228
234 The files will be added to the repository at the next commit. To
229 The files will be added to the repository at the next commit. To
235 undo an add before that, see :hg:`forget`.
230 undo an add before that, see :hg:`forget`.
236
231
237 If no names are given, add all files to the repository (except
232 If no names are given, add all files to the repository (except
238 files matching ``.hgignore``).
233 files matching ``.hgignore``).
239
234
240 .. container:: verbose
235 .. container:: verbose
241
236
242 Examples:
237 Examples:
243
238
244 - New (unknown) files are added
239 - New (unknown) files are added
245 automatically by :hg:`add`::
240 automatically by :hg:`add`::
246
241
247 $ ls
242 $ ls
248 foo.c
243 foo.c
249 $ hg status
244 $ hg status
250 ? foo.c
245 ? foo.c
251 $ hg add
246 $ hg add
252 adding foo.c
247 adding foo.c
253 $ hg status
248 $ hg status
254 A foo.c
249 A foo.c
255
250
256 - Specific files to be added can be specified::
251 - Specific files to be added can be specified::
257
252
258 $ ls
253 $ ls
259 bar.c foo.c
254 bar.c foo.c
260 $ hg status
255 $ hg status
261 ? bar.c
256 ? bar.c
262 ? foo.c
257 ? foo.c
263 $ hg add bar.c
258 $ hg add bar.c
264 $ hg status
259 $ hg status
265 A bar.c
260 A bar.c
266 ? foo.c
261 ? foo.c
267
262
268 Returns 0 if all files are successfully added.
263 Returns 0 if all files are successfully added.
269 """
264 """
270
265
271 m = scmutil.match(repo[None], pats, opts)
266 m = scmutil.match(repo[None], pats, opts)
272 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
267 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
273 return rejected and 1 or 0
268 return rejected and 1 or 0
274
269
275 @command('addremove',
270 @command('addremove',
276 similarityopts + subrepoopts + walkopts + dryrunopts,
271 similarityopts + subrepoopts + walkopts + dryrunopts,
277 _('[OPTION]... [FILE]...'),
272 _('[OPTION]... [FILE]...'),
278 inferrepo=True)
273 inferrepo=True)
279 def addremove(ui, repo, *pats, **opts):
274 def addremove(ui, repo, *pats, **opts):
280 """add all new files, delete all missing files
275 """add all new files, delete all missing files
281
276
282 Add all new files and remove all missing files from the
277 Add all new files and remove all missing files from the
283 repository.
278 repository.
284
279
285 Unless names are given, new files are ignored if they match any of
280 Unless names are given, new files are ignored if they match any of
286 the patterns in ``.hgignore``. As with add, these changes take
281 the patterns in ``.hgignore``. As with add, these changes take
287 effect at the next commit.
282 effect at the next commit.
288
283
289 Use the -s/--similarity option to detect renamed files. This
284 Use the -s/--similarity option to detect renamed files. This
290 option takes a percentage between 0 (disabled) and 100 (files must
285 option takes a percentage between 0 (disabled) and 100 (files must
291 be identical) as its parameter. With a parameter greater than 0,
286 be identical) as its parameter. With a parameter greater than 0,
292 this compares every removed file with every added file and records
287 this compares every removed file with every added file and records
293 those similar enough as renames. Detecting renamed files this way
288 those similar enough as renames. Detecting renamed files this way
294 can be expensive. After using this option, :hg:`status -C` can be
289 can be expensive. After using this option, :hg:`status -C` can be
295 used to check which files were identified as moved or renamed. If
290 used to check which files were identified as moved or renamed. If
296 not specified, -s/--similarity defaults to 100 and only renames of
291 not specified, -s/--similarity defaults to 100 and only renames of
297 identical files are detected.
292 identical files are detected.
298
293
299 .. container:: verbose
294 .. container:: verbose
300
295
301 Examples:
296 Examples:
302
297
303 - A number of files (bar.c and foo.c) are new,
298 - A number of files (bar.c and foo.c) are new,
304 while foobar.c has been removed (without using :hg:`remove`)
299 while foobar.c has been removed (without using :hg:`remove`)
305 from the repository::
300 from the repository::
306
301
307 $ ls
302 $ ls
308 bar.c foo.c
303 bar.c foo.c
309 $ hg status
304 $ hg status
310 ! foobar.c
305 ! foobar.c
311 ? bar.c
306 ? bar.c
312 ? foo.c
307 ? foo.c
313 $ hg addremove
308 $ hg addremove
314 adding bar.c
309 adding bar.c
315 adding foo.c
310 adding foo.c
316 removing foobar.c
311 removing foobar.c
317 $ hg status
312 $ hg status
318 A bar.c
313 A bar.c
319 A foo.c
314 A foo.c
320 R foobar.c
315 R foobar.c
321
316
322 - A file foobar.c was moved to foo.c without using :hg:`rename`.
317 - A file foobar.c was moved to foo.c without using :hg:`rename`.
323 Afterwards, it was edited slightly::
318 Afterwards, it was edited slightly::
324
319
325 $ ls
320 $ ls
326 foo.c
321 foo.c
327 $ hg status
322 $ hg status
328 ! foobar.c
323 ! foobar.c
329 ? foo.c
324 ? foo.c
330 $ hg addremove --similarity 90
325 $ hg addremove --similarity 90
331 removing foobar.c
326 removing foobar.c
332 adding foo.c
327 adding foo.c
333 recording removal of foobar.c as rename to foo.c (94% similar)
328 recording removal of foobar.c as rename to foo.c (94% similar)
334 $ hg status -C
329 $ hg status -C
335 A foo.c
330 A foo.c
336 foobar.c
331 foobar.c
337 R foobar.c
332 R foobar.c
338
333
339 Returns 0 if all files are successfully added.
334 Returns 0 if all files are successfully added.
340 """
335 """
341 try:
336 try:
342 sim = float(opts.get('similarity') or 100)
337 sim = float(opts.get('similarity') or 100)
343 except ValueError:
338 except ValueError:
344 raise error.Abort(_('similarity must be a number'))
339 raise error.Abort(_('similarity must be a number'))
345 if sim < 0 or sim > 100:
340 if sim < 0 or sim > 100:
346 raise error.Abort(_('similarity must be between 0 and 100'))
341 raise error.Abort(_('similarity must be between 0 and 100'))
347 matcher = scmutil.match(repo[None], pats, opts)
342 matcher = scmutil.match(repo[None], pats, opts)
348 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
343 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
349
344
350 @command('^annotate|blame',
345 @command('^annotate|blame',
351 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
346 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
352 ('', 'follow', None,
347 ('', 'follow', None,
353 _('follow copies/renames and list the filename (DEPRECATED)')),
348 _('follow copies/renames and list the filename (DEPRECATED)')),
354 ('', 'no-follow', None, _("don't follow copies and renames")),
349 ('', 'no-follow', None, _("don't follow copies and renames")),
355 ('a', 'text', None, _('treat all files as text')),
350 ('a', 'text', None, _('treat all files as text')),
356 ('u', 'user', None, _('list the author (long with -v)')),
351 ('u', 'user', None, _('list the author (long with -v)')),
357 ('f', 'file', None, _('list the filename')),
352 ('f', 'file', None, _('list the filename')),
358 ('d', 'date', None, _('list the date (short with -q)')),
353 ('d', 'date', None, _('list the date (short with -q)')),
359 ('n', 'number', None, _('list the revision number (default)')),
354 ('n', 'number', None, _('list the revision number (default)')),
360 ('c', 'changeset', None, _('list the changeset')),
355 ('c', 'changeset', None, _('list the changeset')),
361 ('l', 'line-number', None, _('show line number at the first appearance'))
356 ('l', 'line-number', None, _('show line number at the first appearance'))
362 ] + diffwsopts + walkopts + formatteropts,
357 ] + diffwsopts + walkopts + formatteropts,
363 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
358 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
364 inferrepo=True)
359 inferrepo=True)
365 def annotate(ui, repo, *pats, **opts):
360 def annotate(ui, repo, *pats, **opts):
366 """show changeset information by line for each file
361 """show changeset information by line for each file
367
362
368 List changes in files, showing the revision id responsible for
363 List changes in files, showing the revision id responsible for
369 each line.
364 each line.
370
365
371 This command is useful for discovering when a change was made and
366 This command is useful for discovering when a change was made and
372 by whom.
367 by whom.
373
368
374 If you include --file, --user, or --date, the revision number is
369 If you include --file, --user, or --date, the revision number is
375 suppressed unless you also include --number.
370 suppressed unless you also include --number.
376
371
377 Without the -a/--text option, annotate will avoid processing files
372 Without the -a/--text option, annotate will avoid processing files
378 it detects as binary. With -a, annotate will annotate the file
373 it detects as binary. With -a, annotate will annotate the file
379 anyway, although the results will probably be neither useful
374 anyway, although the results will probably be neither useful
380 nor desirable.
375 nor desirable.
381
376
382 Returns 0 on success.
377 Returns 0 on success.
383 """
378 """
384 if not pats:
379 if not pats:
385 raise error.Abort(_('at least one filename or pattern is required'))
380 raise error.Abort(_('at least one filename or pattern is required'))
386
381
387 if opts.get('follow'):
382 if opts.get('follow'):
388 # --follow is deprecated and now just an alias for -f/--file
383 # --follow is deprecated and now just an alias for -f/--file
389 # to mimic the behavior of Mercurial before version 1.5
384 # to mimic the behavior of Mercurial before version 1.5
390 opts['file'] = True
385 opts['file'] = True
391
386
392 ctx = scmutil.revsingle(repo, opts.get('rev'))
387 ctx = scmutil.revsingle(repo, opts.get('rev'))
393
388
394 fm = ui.formatter('annotate', opts)
389 fm = ui.formatter('annotate', opts)
395 if ui.quiet:
390 if ui.quiet:
396 datefunc = util.shortdate
391 datefunc = util.shortdate
397 else:
392 else:
398 datefunc = util.datestr
393 datefunc = util.datestr
399 if ctx.rev() is None:
394 if ctx.rev() is None:
400 def hexfn(node):
395 def hexfn(node):
401 if node is None:
396 if node is None:
402 return None
397 return None
403 else:
398 else:
404 return fm.hexfunc(node)
399 return fm.hexfunc(node)
405 if opts.get('changeset'):
400 if opts.get('changeset'):
406 # omit "+" suffix which is appended to node hex
401 # omit "+" suffix which is appended to node hex
407 def formatrev(rev):
402 def formatrev(rev):
408 if rev is None:
403 if rev is None:
409 return '%d' % ctx.p1().rev()
404 return '%d' % ctx.p1().rev()
410 else:
405 else:
411 return '%d' % rev
406 return '%d' % rev
412 else:
407 else:
413 def formatrev(rev):
408 def formatrev(rev):
414 if rev is None:
409 if rev is None:
415 return '%d+' % ctx.p1().rev()
410 return '%d+' % ctx.p1().rev()
416 else:
411 else:
417 return '%d ' % rev
412 return '%d ' % rev
418 def formathex(hex):
413 def formathex(hex):
419 if hex is None:
414 if hex is None:
420 return '%s+' % fm.hexfunc(ctx.p1().node())
415 return '%s+' % fm.hexfunc(ctx.p1().node())
421 else:
416 else:
422 return '%s ' % hex
417 return '%s ' % hex
423 else:
418 else:
424 hexfn = fm.hexfunc
419 hexfn = fm.hexfunc
425 formatrev = formathex = str
420 formatrev = formathex = str
426
421
427 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
422 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
428 ('number', ' ', lambda x: x[0].rev(), formatrev),
423 ('number', ' ', lambda x: x[0].rev(), formatrev),
429 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
424 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
430 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
425 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
431 ('file', ' ', lambda x: x[0].path(), str),
426 ('file', ' ', lambda x: x[0].path(), str),
432 ('line_number', ':', lambda x: x[1], str),
427 ('line_number', ':', lambda x: x[1], str),
433 ]
428 ]
434 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
429 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
435
430
436 if (not opts.get('user') and not opts.get('changeset')
431 if (not opts.get('user') and not opts.get('changeset')
437 and not opts.get('date') and not opts.get('file')):
432 and not opts.get('date') and not opts.get('file')):
438 opts['number'] = True
433 opts['number'] = True
439
434
440 linenumber = opts.get('line_number') is not None
435 linenumber = opts.get('line_number') is not None
441 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
436 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
442 raise error.Abort(_('at least one of -n/-c is required for -l'))
437 raise error.Abort(_('at least one of -n/-c is required for -l'))
443
438
444 if fm.isplain():
439 if fm.isplain():
445 def makefunc(get, fmt):
440 def makefunc(get, fmt):
446 return lambda x: fmt(get(x))
441 return lambda x: fmt(get(x))
447 else:
442 else:
448 def makefunc(get, fmt):
443 def makefunc(get, fmt):
449 return get
444 return get
450 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
445 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
451 if opts.get(op)]
446 if opts.get(op)]
452 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
447 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
453 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
448 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
454 if opts.get(op))
449 if opts.get(op))
455
450
456 def bad(x, y):
451 def bad(x, y):
457 raise error.Abort("%s: %s" % (x, y))
452 raise error.Abort("%s: %s" % (x, y))
458
453
459 m = scmutil.match(ctx, pats, opts, badfn=bad)
454 m = scmutil.match(ctx, pats, opts, badfn=bad)
460
455
461 follow = not opts.get('no_follow')
456 follow = not opts.get('no_follow')
462 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
457 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
463 whitespace=True)
458 whitespace=True)
464 for abs in ctx.walk(m):
459 for abs in ctx.walk(m):
465 fctx = ctx[abs]
460 fctx = ctx[abs]
466 if not opts.get('text') and util.binary(fctx.data()):
461 if not opts.get('text') and util.binary(fctx.data()):
467 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
462 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
468 continue
463 continue
469
464
470 lines = fctx.annotate(follow=follow, linenumber=linenumber,
465 lines = fctx.annotate(follow=follow, linenumber=linenumber,
471 diffopts=diffopts)
466 diffopts=diffopts)
472 if not lines:
467 if not lines:
473 continue
468 continue
474 formats = []
469 formats = []
475 pieces = []
470 pieces = []
476
471
477 for f, sep in funcmap:
472 for f, sep in funcmap:
478 l = [f(n) for n, dummy in lines]
473 l = [f(n) for n, dummy in lines]
479 if fm.isplain():
474 if fm.isplain():
480 sizes = [encoding.colwidth(x) for x in l]
475 sizes = [encoding.colwidth(x) for x in l]
481 ml = max(sizes)
476 ml = max(sizes)
482 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
477 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
483 else:
478 else:
484 formats.append(['%s' for x in l])
479 formats.append(['%s' for x in l])
485 pieces.append(l)
480 pieces.append(l)
486
481
487 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
482 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
488 fm.startitem()
483 fm.startitem()
489 fm.write(fields, "".join(f), *p)
484 fm.write(fields, "".join(f), *p)
490 fm.write('line', ": %s", l[1])
485 fm.write('line', ": %s", l[1])
491
486
492 if not lines[-1][1].endswith('\n'):
487 if not lines[-1][1].endswith('\n'):
493 fm.plain('\n')
488 fm.plain('\n')
494
489
495 fm.end()
490 fm.end()
496
491
497 @command('archive',
492 @command('archive',
498 [('', 'no-decode', None, _('do not pass files through decoders')),
493 [('', 'no-decode', None, _('do not pass files through decoders')),
499 ('p', 'prefix', '', _('directory prefix for files in archive'),
494 ('p', 'prefix', '', _('directory prefix for files in archive'),
500 _('PREFIX')),
495 _('PREFIX')),
501 ('r', 'rev', '', _('revision to distribute'), _('REV')),
496 ('r', 'rev', '', _('revision to distribute'), _('REV')),
502 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
497 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
503 ] + subrepoopts + walkopts,
498 ] + subrepoopts + walkopts,
504 _('[OPTION]... DEST'))
499 _('[OPTION]... DEST'))
505 def archive(ui, repo, dest, **opts):
500 def archive(ui, repo, dest, **opts):
506 '''create an unversioned archive of a repository revision
501 '''create an unversioned archive of a repository revision
507
502
508 By default, the revision used is the parent of the working
503 By default, the revision used is the parent of the working
509 directory; use -r/--rev to specify a different revision.
504 directory; use -r/--rev to specify a different revision.
510
505
511 The archive type is automatically detected based on file
506 The archive type is automatically detected based on file
512 extension (to override, use -t/--type).
507 extension (to override, use -t/--type).
513
508
514 .. container:: verbose
509 .. container:: verbose
515
510
516 Examples:
511 Examples:
517
512
518 - create a zip file containing the 1.0 release::
513 - create a zip file containing the 1.0 release::
519
514
520 hg archive -r 1.0 project-1.0.zip
515 hg archive -r 1.0 project-1.0.zip
521
516
522 - create a tarball excluding .hg files::
517 - create a tarball excluding .hg files::
523
518
524 hg archive project.tar.gz -X ".hg*"
519 hg archive project.tar.gz -X ".hg*"
525
520
526 Valid types are:
521 Valid types are:
527
522
528 :``files``: a directory full of files (default)
523 :``files``: a directory full of files (default)
529 :``tar``: tar archive, uncompressed
524 :``tar``: tar archive, uncompressed
530 :``tbz2``: tar archive, compressed using bzip2
525 :``tbz2``: tar archive, compressed using bzip2
531 :``tgz``: tar archive, compressed using gzip
526 :``tgz``: tar archive, compressed using gzip
532 :``uzip``: zip archive, uncompressed
527 :``uzip``: zip archive, uncompressed
533 :``zip``: zip archive, compressed using deflate
528 :``zip``: zip archive, compressed using deflate
534
529
535 The exact name of the destination archive or directory is given
530 The exact name of the destination archive or directory is given
536 using a format string; see :hg:`help export` for details.
531 using a format string; see :hg:`help export` for details.
537
532
538 Each member added to an archive file has a directory prefix
533 Each member added to an archive file has a directory prefix
539 prepended. Use -p/--prefix to specify a format string for the
534 prepended. Use -p/--prefix to specify a format string for the
540 prefix. The default is the basename of the archive, with suffixes
535 prefix. The default is the basename of the archive, with suffixes
541 removed.
536 removed.
542
537
543 Returns 0 on success.
538 Returns 0 on success.
544 '''
539 '''
545
540
546 ctx = scmutil.revsingle(repo, opts.get('rev'))
541 ctx = scmutil.revsingle(repo, opts.get('rev'))
547 if not ctx:
542 if not ctx:
548 raise error.Abort(_('no working directory: please specify a revision'))
543 raise error.Abort(_('no working directory: please specify a revision'))
549 node = ctx.node()
544 node = ctx.node()
550 dest = cmdutil.makefilename(repo, dest, node)
545 dest = cmdutil.makefilename(repo, dest, node)
551 if os.path.realpath(dest) == repo.root:
546 if os.path.realpath(dest) == repo.root:
552 raise error.Abort(_('repository root cannot be destination'))
547 raise error.Abort(_('repository root cannot be destination'))
553
548
554 kind = opts.get('type') or archival.guesskind(dest) or 'files'
549 kind = opts.get('type') or archival.guesskind(dest) or 'files'
555 prefix = opts.get('prefix')
550 prefix = opts.get('prefix')
556
551
557 if dest == '-':
552 if dest == '-':
558 if kind == 'files':
553 if kind == 'files':
559 raise error.Abort(_('cannot archive plain files to stdout'))
554 raise error.Abort(_('cannot archive plain files to stdout'))
560 dest = cmdutil.makefileobj(repo, dest)
555 dest = cmdutil.makefileobj(repo, dest)
561 if not prefix:
556 if not prefix:
562 prefix = os.path.basename(repo.root) + '-%h'
557 prefix = os.path.basename(repo.root) + '-%h'
563
558
564 prefix = cmdutil.makefilename(repo, prefix, node)
559 prefix = cmdutil.makefilename(repo, prefix, node)
565 matchfn = scmutil.match(ctx, [], opts)
560 matchfn = scmutil.match(ctx, [], opts)
566 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
561 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
567 matchfn, prefix, subrepos=opts.get('subrepos'))
562 matchfn, prefix, subrepos=opts.get('subrepos'))
568
563
569 @command('backout',
564 @command('backout',
570 [('', 'merge', None, _('merge with old dirstate parent after backout')),
565 [('', 'merge', None, _('merge with old dirstate parent after backout')),
571 ('', 'commit', None,
566 ('', 'commit', None,
572 _('commit if no conflicts were encountered (DEPRECATED)')),
567 _('commit if no conflicts were encountered (DEPRECATED)')),
573 ('', 'no-commit', None, _('do not commit')),
568 ('', 'no-commit', None, _('do not commit')),
574 ('', 'parent', '',
569 ('', 'parent', '',
575 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
570 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
576 ('r', 'rev', '', _('revision to backout'), _('REV')),
571 ('r', 'rev', '', _('revision to backout'), _('REV')),
577 ('e', 'edit', False, _('invoke editor on commit messages')),
572 ('e', 'edit', False, _('invoke editor on commit messages')),
578 ] + mergetoolopts + walkopts + commitopts + commitopts2,
573 ] + mergetoolopts + walkopts + commitopts + commitopts2,
579 _('[OPTION]... [-r] REV'))
574 _('[OPTION]... [-r] REV'))
580 def backout(ui, repo, node=None, rev=None, **opts):
575 def backout(ui, repo, node=None, rev=None, **opts):
581 '''reverse effect of earlier changeset
576 '''reverse effect of earlier changeset
582
577
583 Prepare a new changeset with the effect of REV undone in the
578 Prepare a new changeset with the effect of REV undone in the
584 current working directory. If no conflicts were encountered,
579 current working directory. If no conflicts were encountered,
585 it will be committed immediately.
580 it will be committed immediately.
586
581
587 If REV is the parent of the working directory, then this new changeset
582 If REV is the parent of the working directory, then this new changeset
588 is committed automatically (unless --no-commit is specified).
583 is committed automatically (unless --no-commit is specified).
589
584
590 .. note::
585 .. note::
591
586
592 :hg:`backout` cannot be used to fix either an unwanted or
587 :hg:`backout` cannot be used to fix either an unwanted or
593 incorrect merge.
588 incorrect merge.
594
589
595 .. container:: verbose
590 .. container:: verbose
596
591
597 Examples:
592 Examples:
598
593
599 - Reverse the effect of the parent of the working directory.
594 - Reverse the effect of the parent of the working directory.
600 This backout will be committed immediately::
595 This backout will be committed immediately::
601
596
602 hg backout -r .
597 hg backout -r .
603
598
604 - Reverse the effect of previous bad revision 23::
599 - Reverse the effect of previous bad revision 23::
605
600
606 hg backout -r 23
601 hg backout -r 23
607
602
608 - Reverse the effect of previous bad revision 23 and
603 - Reverse the effect of previous bad revision 23 and
609 leave changes uncommitted::
604 leave changes uncommitted::
610
605
611 hg backout -r 23 --no-commit
606 hg backout -r 23 --no-commit
612 hg commit -m "Backout revision 23"
607 hg commit -m "Backout revision 23"
613
608
614 By default, the pending changeset will have one parent,
609 By default, the pending changeset will have one parent,
615 maintaining a linear history. With --merge, the pending
610 maintaining a linear history. With --merge, the pending
616 changeset will instead have two parents: the old parent of the
611 changeset will instead have two parents: the old parent of the
617 working directory and a new child of REV that simply undoes REV.
612 working directory and a new child of REV that simply undoes REV.
618
613
619 Before version 1.7, the behavior without --merge was equivalent
614 Before version 1.7, the behavior without --merge was equivalent
620 to specifying --merge followed by :hg:`update --clean .` to
615 to specifying --merge followed by :hg:`update --clean .` to
621 cancel the merge and leave the child of REV as a head to be
616 cancel the merge and leave the child of REV as a head to be
622 merged separately.
617 merged separately.
623
618
624 See :hg:`help dates` for a list of formats valid for -d/--date.
619 See :hg:`help dates` for a list of formats valid for -d/--date.
625
620
626 See :hg:`help revert` for a way to restore files to the state
621 See :hg:`help revert` for a way to restore files to the state
627 of another revision.
622 of another revision.
628
623
629 Returns 0 on success, 1 if nothing to backout or there are unresolved
624 Returns 0 on success, 1 if nothing to backout or there are unresolved
630 files.
625 files.
631 '''
626 '''
632 wlock = lock = None
627 wlock = lock = None
633 try:
628 try:
634 wlock = repo.wlock()
629 wlock = repo.wlock()
635 lock = repo.lock()
630 lock = repo.lock()
636 return _dobackout(ui, repo, node, rev, **opts)
631 return _dobackout(ui, repo, node, rev, **opts)
637 finally:
632 finally:
638 release(lock, wlock)
633 release(lock, wlock)
639
634
640 def _dobackout(ui, repo, node=None, rev=None, **opts):
635 def _dobackout(ui, repo, node=None, rev=None, **opts):
641 if opts.get('commit') and opts.get('no_commit'):
636 if opts.get('commit') and opts.get('no_commit'):
642 raise error.Abort(_("cannot use --commit with --no-commit"))
637 raise error.Abort(_("cannot use --commit with --no-commit"))
643 if opts.get('merge') and opts.get('no_commit'):
638 if opts.get('merge') and opts.get('no_commit'):
644 raise error.Abort(_("cannot use --merge with --no-commit"))
639 raise error.Abort(_("cannot use --merge with --no-commit"))
645
640
646 if rev and node:
641 if rev and node:
647 raise error.Abort(_("please specify just one revision"))
642 raise error.Abort(_("please specify just one revision"))
648
643
649 if not rev:
644 if not rev:
650 rev = node
645 rev = node
651
646
652 if not rev:
647 if not rev:
653 raise error.Abort(_("please specify a revision to backout"))
648 raise error.Abort(_("please specify a revision to backout"))
654
649
655 date = opts.get('date')
650 date = opts.get('date')
656 if date:
651 if date:
657 opts['date'] = util.parsedate(date)
652 opts['date'] = util.parsedate(date)
658
653
659 cmdutil.checkunfinished(repo)
654 cmdutil.checkunfinished(repo)
660 cmdutil.bailifchanged(repo)
655 cmdutil.bailifchanged(repo)
661 node = scmutil.revsingle(repo, rev).node()
656 node = scmutil.revsingle(repo, rev).node()
662
657
663 op1, op2 = repo.dirstate.parents()
658 op1, op2 = repo.dirstate.parents()
664 if not repo.changelog.isancestor(node, op1):
659 if not repo.changelog.isancestor(node, op1):
665 raise error.Abort(_('cannot backout change that is not an ancestor'))
660 raise error.Abort(_('cannot backout change that is not an ancestor'))
666
661
667 p1, p2 = repo.changelog.parents(node)
662 p1, p2 = repo.changelog.parents(node)
668 if p1 == nullid:
663 if p1 == nullid:
669 raise error.Abort(_('cannot backout a change with no parents'))
664 raise error.Abort(_('cannot backout a change with no parents'))
670 if p2 != nullid:
665 if p2 != nullid:
671 if not opts.get('parent'):
666 if not opts.get('parent'):
672 raise error.Abort(_('cannot backout a merge changeset'))
667 raise error.Abort(_('cannot backout a merge changeset'))
673 p = repo.lookup(opts['parent'])
668 p = repo.lookup(opts['parent'])
674 if p not in (p1, p2):
669 if p not in (p1, p2):
675 raise error.Abort(_('%s is not a parent of %s') %
670 raise error.Abort(_('%s is not a parent of %s') %
676 (short(p), short(node)))
671 (short(p), short(node)))
677 parent = p
672 parent = p
678 else:
673 else:
679 if opts.get('parent'):
674 if opts.get('parent'):
680 raise error.Abort(_('cannot use --parent on non-merge changeset'))
675 raise error.Abort(_('cannot use --parent on non-merge changeset'))
681 parent = p1
676 parent = p1
682
677
683 # the backout should appear on the same branch
678 # the backout should appear on the same branch
684 branch = repo.dirstate.branch()
679 branch = repo.dirstate.branch()
685 bheads = repo.branchheads(branch)
680 bheads = repo.branchheads(branch)
686 rctx = scmutil.revsingle(repo, hex(parent))
681 rctx = scmutil.revsingle(repo, hex(parent))
687 if not opts.get('merge') and op1 != node:
682 if not opts.get('merge') and op1 != node:
688 dsguard = dirstateguard.dirstateguard(repo, 'backout')
683 dsguard = dirstateguard.dirstateguard(repo, 'backout')
689 try:
684 try:
690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
685 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 'backout')
686 'backout')
692 stats = mergemod.update(repo, parent, True, True, node, False)
687 stats = mergemod.update(repo, parent, True, True, node, False)
693 repo.setparents(op1, op2)
688 repo.setparents(op1, op2)
694 dsguard.close()
689 dsguard.close()
695 hg._showstats(repo, stats)
690 hg._showstats(repo, stats)
696 if stats[3]:
691 if stats[3]:
697 repo.ui.status(_("use 'hg resolve' to retry unresolved "
692 repo.ui.status(_("use 'hg resolve' to retry unresolved "
698 "file merges\n"))
693 "file merges\n"))
699 return 1
694 return 1
700 finally:
695 finally:
701 ui.setconfig('ui', 'forcemerge', '', '')
696 ui.setconfig('ui', 'forcemerge', '', '')
702 lockmod.release(dsguard)
697 lockmod.release(dsguard)
703 else:
698 else:
704 hg.clean(repo, node, show_stats=False)
699 hg.clean(repo, node, show_stats=False)
705 repo.dirstate.setbranch(branch)
700 repo.dirstate.setbranch(branch)
706 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
701 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
707
702
708 if opts.get('no_commit'):
703 if opts.get('no_commit'):
709 msg = _("changeset %s backed out, "
704 msg = _("changeset %s backed out, "
710 "don't forget to commit.\n")
705 "don't forget to commit.\n")
711 ui.status(msg % short(node))
706 ui.status(msg % short(node))
712 return 0
707 return 0
713
708
714 def commitfunc(ui, repo, message, match, opts):
709 def commitfunc(ui, repo, message, match, opts):
715 editform = 'backout'
710 editform = 'backout'
716 e = cmdutil.getcommiteditor(editform=editform, **opts)
711 e = cmdutil.getcommiteditor(editform=editform, **opts)
717 if not message:
712 if not message:
718 # we don't translate commit messages
713 # we don't translate commit messages
719 message = "Backed out changeset %s" % short(node)
714 message = "Backed out changeset %s" % short(node)
720 e = cmdutil.getcommiteditor(edit=True, editform=editform)
715 e = cmdutil.getcommiteditor(edit=True, editform=editform)
721 return repo.commit(message, opts.get('user'), opts.get('date'),
716 return repo.commit(message, opts.get('user'), opts.get('date'),
722 match, editor=e)
717 match, editor=e)
723 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
718 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
724 if not newnode:
719 if not newnode:
725 ui.status(_("nothing changed\n"))
720 ui.status(_("nothing changed\n"))
726 return 1
721 return 1
727 cmdutil.commitstatus(repo, newnode, branch, bheads)
722 cmdutil.commitstatus(repo, newnode, branch, bheads)
728
723
729 def nice(node):
724 def nice(node):
730 return '%d:%s' % (repo.changelog.rev(node), short(node))
725 return '%d:%s' % (repo.changelog.rev(node), short(node))
731 ui.status(_('changeset %s backs out changeset %s\n') %
726 ui.status(_('changeset %s backs out changeset %s\n') %
732 (nice(repo.changelog.tip()), nice(node)))
727 (nice(repo.changelog.tip()), nice(node)))
733 if opts.get('merge') and op1 != node:
728 if opts.get('merge') and op1 != node:
734 hg.clean(repo, op1, show_stats=False)
729 hg.clean(repo, op1, show_stats=False)
735 ui.status(_('merging with changeset %s\n')
730 ui.status(_('merging with changeset %s\n')
736 % nice(repo.changelog.tip()))
731 % nice(repo.changelog.tip()))
737 try:
732 try:
738 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
733 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
739 'backout')
734 'backout')
740 return hg.merge(repo, hex(repo.changelog.tip()))
735 return hg.merge(repo, hex(repo.changelog.tip()))
741 finally:
736 finally:
742 ui.setconfig('ui', 'forcemerge', '', '')
737 ui.setconfig('ui', 'forcemerge', '', '')
743 return 0
738 return 0
744
739
745 @command('bisect',
740 @command('bisect',
746 [('r', 'reset', False, _('reset bisect state')),
741 [('r', 'reset', False, _('reset bisect state')),
747 ('g', 'good', False, _('mark changeset good')),
742 ('g', 'good', False, _('mark changeset good')),
748 ('b', 'bad', False, _('mark changeset bad')),
743 ('b', 'bad', False, _('mark changeset bad')),
749 ('s', 'skip', False, _('skip testing changeset')),
744 ('s', 'skip', False, _('skip testing changeset')),
750 ('e', 'extend', False, _('extend the bisect range')),
745 ('e', 'extend', False, _('extend the bisect range')),
751 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
746 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
752 ('U', 'noupdate', False, _('do not update to target'))],
747 ('U', 'noupdate', False, _('do not update to target'))],
753 _("[-gbsr] [-U] [-c CMD] [REV]"))
748 _("[-gbsr] [-U] [-c CMD] [REV]"))
754 def bisect(ui, repo, rev=None, extra=None, command=None,
749 def bisect(ui, repo, rev=None, extra=None, command=None,
755 reset=None, good=None, bad=None, skip=None, extend=None,
750 reset=None, good=None, bad=None, skip=None, extend=None,
756 noupdate=None):
751 noupdate=None):
757 """subdivision search of changesets
752 """subdivision search of changesets
758
753
759 This command helps to find changesets which introduce problems. To
754 This command helps to find changesets which introduce problems. To
760 use, mark the earliest changeset you know exhibits the problem as
755 use, mark the earliest changeset you know exhibits the problem as
761 bad, then mark the latest changeset which is free from the problem
756 bad, then mark the latest changeset which is free from the problem
762 as good. Bisect will update your working directory to a revision
757 as good. Bisect will update your working directory to a revision
763 for testing (unless the -U/--noupdate option is specified). Once
758 for testing (unless the -U/--noupdate option is specified). Once
764 you have performed tests, mark the working directory as good or
759 you have performed tests, mark the working directory as good or
765 bad, and bisect will either update to another candidate changeset
760 bad, and bisect will either update to another candidate changeset
766 or announce that it has found the bad revision.
761 or announce that it has found the bad revision.
767
762
768 As a shortcut, you can also use the revision argument to mark a
763 As a shortcut, you can also use the revision argument to mark a
769 revision as good or bad without checking it out first.
764 revision as good or bad without checking it out first.
770
765
771 If you supply a command, it will be used for automatic bisection.
766 If you supply a command, it will be used for automatic bisection.
772 The environment variable HG_NODE will contain the ID of the
767 The environment variable HG_NODE will contain the ID of the
773 changeset being tested. The exit status of the command will be
768 changeset being tested. The exit status of the command will be
774 used to mark revisions as good or bad: status 0 means good, 125
769 used to mark revisions as good or bad: status 0 means good, 125
775 means to skip the revision, 127 (command not found) will abort the
770 means to skip the revision, 127 (command not found) will abort the
776 bisection, and any other non-zero exit status means the revision
771 bisection, and any other non-zero exit status means the revision
777 is bad.
772 is bad.
778
773
779 .. container:: verbose
774 .. container:: verbose
780
775
781 Some examples:
776 Some examples:
782
777
783 - start a bisection with known bad revision 34, and good revision 12::
778 - start a bisection with known bad revision 34, and good revision 12::
784
779
785 hg bisect --bad 34
780 hg bisect --bad 34
786 hg bisect --good 12
781 hg bisect --good 12
787
782
788 - advance the current bisection by marking current revision as good or
783 - advance the current bisection by marking current revision as good or
789 bad::
784 bad::
790
785
791 hg bisect --good
786 hg bisect --good
792 hg bisect --bad
787 hg bisect --bad
793
788
794 - mark the current revision, or a known revision, to be skipped (e.g. if
789 - mark the current revision, or a known revision, to be skipped (e.g. if
795 that revision is not usable because of another issue)::
790 that revision is not usable because of another issue)::
796
791
797 hg bisect --skip
792 hg bisect --skip
798 hg bisect --skip 23
793 hg bisect --skip 23
799
794
800 - skip all revisions that do not touch directories ``foo`` or ``bar``::
795 - skip all revisions that do not touch directories ``foo`` or ``bar``::
801
796
802 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
797 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
803
798
804 - forget the current bisection::
799 - forget the current bisection::
805
800
806 hg bisect --reset
801 hg bisect --reset
807
802
808 - use 'make && make tests' to automatically find the first broken
803 - use 'make && make tests' to automatically find the first broken
809 revision::
804 revision::
810
805
811 hg bisect --reset
806 hg bisect --reset
812 hg bisect --bad 34
807 hg bisect --bad 34
813 hg bisect --good 12
808 hg bisect --good 12
814 hg bisect --command "make && make tests"
809 hg bisect --command "make && make tests"
815
810
816 - see all changesets whose states are already known in the current
811 - see all changesets whose states are already known in the current
817 bisection::
812 bisection::
818
813
819 hg log -r "bisect(pruned)"
814 hg log -r "bisect(pruned)"
820
815
821 - see the changeset currently being bisected (especially useful
816 - see the changeset currently being bisected (especially useful
822 if running with -U/--noupdate)::
817 if running with -U/--noupdate)::
823
818
824 hg log -r "bisect(current)"
819 hg log -r "bisect(current)"
825
820
826 - see all changesets that took part in the current bisection::
821 - see all changesets that took part in the current bisection::
827
822
828 hg log -r "bisect(range)"
823 hg log -r "bisect(range)"
829
824
830 - you can even get a nice graph::
825 - you can even get a nice graph::
831
826
832 hg log --graph -r "bisect(range)"
827 hg log --graph -r "bisect(range)"
833
828
834 See :hg:`help revsets` for more about the `bisect()` keyword.
829 See :hg:`help revsets` for more about the `bisect()` keyword.
835
830
836 Returns 0 on success.
831 Returns 0 on success.
837 """
832 """
838 # backward compatibility
833 # backward compatibility
839 if rev in "good bad reset init".split():
834 if rev in "good bad reset init".split():
840 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
835 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
841 cmd, rev, extra = rev, extra, None
836 cmd, rev, extra = rev, extra, None
842 if cmd == "good":
837 if cmd == "good":
843 good = True
838 good = True
844 elif cmd == "bad":
839 elif cmd == "bad":
845 bad = True
840 bad = True
846 else:
841 else:
847 reset = True
842 reset = True
848 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
843 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
849 raise error.Abort(_('incompatible arguments'))
844 raise error.Abort(_('incompatible arguments'))
850
845
851 cmdutil.checkunfinished(repo)
846 cmdutil.checkunfinished(repo)
852
847
853 if reset:
848 if reset:
854 hbisect.resetstate(repo)
849 hbisect.resetstate(repo)
855 return
850 return
856
851
857 state = hbisect.load_state(repo)
852 state = hbisect.load_state(repo)
858
853
859 # update state
854 # update state
860 if good or bad or skip:
855 if good or bad or skip:
861 if rev:
856 if rev:
862 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
857 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
863 else:
858 else:
864 nodes = [repo.lookup('.')]
859 nodes = [repo.lookup('.')]
865 if good:
860 if good:
866 state['good'] += nodes
861 state['good'] += nodes
867 elif bad:
862 elif bad:
868 state['bad'] += nodes
863 state['bad'] += nodes
869 elif skip:
864 elif skip:
870 state['skip'] += nodes
865 state['skip'] += nodes
871 hbisect.save_state(repo, state)
866 hbisect.save_state(repo, state)
872 if not (state['good'] and state['bad']):
867 if not (state['good'] and state['bad']):
873 return
868 return
874
869
875 def mayupdate(repo, node, show_stats=True):
870 def mayupdate(repo, node, show_stats=True):
876 """common used update sequence"""
871 """common used update sequence"""
877 if noupdate:
872 if noupdate:
878 return
873 return
879 cmdutil.bailifchanged(repo)
874 cmdutil.bailifchanged(repo)
880 return hg.clean(repo, node, show_stats=show_stats)
875 return hg.clean(repo, node, show_stats=show_stats)
881
876
882 displayer = cmdutil.show_changeset(ui, repo, {})
877 displayer = cmdutil.show_changeset(ui, repo, {})
883
878
884 if command:
879 if command:
885 changesets = 1
880 changesets = 1
886 if noupdate:
881 if noupdate:
887 try:
882 try:
888 node = state['current'][0]
883 node = state['current'][0]
889 except LookupError:
884 except LookupError:
890 raise error.Abort(_('current bisect revision is unknown - '
885 raise error.Abort(_('current bisect revision is unknown - '
891 'start a new bisect to fix'))
886 'start a new bisect to fix'))
892 else:
887 else:
893 node, p2 = repo.dirstate.parents()
888 node, p2 = repo.dirstate.parents()
894 if p2 != nullid:
889 if p2 != nullid:
895 raise error.Abort(_('current bisect revision is a merge'))
890 raise error.Abort(_('current bisect revision is a merge'))
896 if rev:
891 if rev:
897 node = repo[scmutil.revsingle(repo, rev, node)].node()
892 node = repo[scmutil.revsingle(repo, rev, node)].node()
898 try:
893 try:
899 while changesets:
894 while changesets:
900 # update state
895 # update state
901 state['current'] = [node]
896 state['current'] = [node]
902 hbisect.save_state(repo, state)
897 hbisect.save_state(repo, state)
903 status = ui.system(command, environ={'HG_NODE': hex(node)})
898 status = ui.system(command, environ={'HG_NODE': hex(node)})
904 if status == 125:
899 if status == 125:
905 transition = "skip"
900 transition = "skip"
906 elif status == 0:
901 elif status == 0:
907 transition = "good"
902 transition = "good"
908 # status < 0 means process was killed
903 # status < 0 means process was killed
909 elif status == 127:
904 elif status == 127:
910 raise error.Abort(_("failed to execute %s") % command)
905 raise error.Abort(_("failed to execute %s") % command)
911 elif status < 0:
906 elif status < 0:
912 raise error.Abort(_("%s killed") % command)
907 raise error.Abort(_("%s killed") % command)
913 else:
908 else:
914 transition = "bad"
909 transition = "bad"
915 state[transition].append(node)
910 state[transition].append(node)
916 ctx = repo[node]
911 ctx = repo[node]
917 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
912 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
918 hbisect.checkstate(state)
913 hbisect.checkstate(state)
919 # bisect
914 # bisect
920 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
915 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
921 # update to next check
916 # update to next check
922 node = nodes[0]
917 node = nodes[0]
923 mayupdate(repo, node, show_stats=False)
918 mayupdate(repo, node, show_stats=False)
924 finally:
919 finally:
925 state['current'] = [node]
920 state['current'] = [node]
926 hbisect.save_state(repo, state)
921 hbisect.save_state(repo, state)
927 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
922 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
928 return
923 return
929
924
930 hbisect.checkstate(state)
925 hbisect.checkstate(state)
931
926
932 # actually bisect
927 # actually bisect
933 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
928 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
934 if extend:
929 if extend:
935 if not changesets:
930 if not changesets:
936 extendnode = hbisect.extendrange(repo, state, nodes, good)
931 extendnode = hbisect.extendrange(repo, state, nodes, good)
937 if extendnode is not None:
932 if extendnode is not None:
938 ui.write(_("Extending search to changeset %d:%s\n")
933 ui.write(_("Extending search to changeset %d:%s\n")
939 % (extendnode.rev(), extendnode))
934 % (extendnode.rev(), extendnode))
940 state['current'] = [extendnode.node()]
935 state['current'] = [extendnode.node()]
941 hbisect.save_state(repo, state)
936 hbisect.save_state(repo, state)
942 return mayupdate(repo, extendnode.node())
937 return mayupdate(repo, extendnode.node())
943 raise error.Abort(_("nothing to extend"))
938 raise error.Abort(_("nothing to extend"))
944
939
945 if changesets == 0:
940 if changesets == 0:
946 hbisect.printresult(ui, repo, state, displayer, nodes, good)
941 hbisect.printresult(ui, repo, state, displayer, nodes, good)
947 else:
942 else:
948 assert len(nodes) == 1 # only a single node can be tested next
943 assert len(nodes) == 1 # only a single node can be tested next
949 node = nodes[0]
944 node = nodes[0]
950 # compute the approximate number of remaining tests
945 # compute the approximate number of remaining tests
951 tests, size = 0, 2
946 tests, size = 0, 2
952 while size <= changesets:
947 while size <= changesets:
953 tests, size = tests + 1, size * 2
948 tests, size = tests + 1, size * 2
954 rev = repo.changelog.rev(node)
949 rev = repo.changelog.rev(node)
955 ui.write(_("Testing changeset %d:%s "
950 ui.write(_("Testing changeset %d:%s "
956 "(%d changesets remaining, ~%d tests)\n")
951 "(%d changesets remaining, ~%d tests)\n")
957 % (rev, short(node), changesets, tests))
952 % (rev, short(node), changesets, tests))
958 state['current'] = [node]
953 state['current'] = [node]
959 hbisect.save_state(repo, state)
954 hbisect.save_state(repo, state)
960 return mayupdate(repo, node)
955 return mayupdate(repo, node)
961
956
962 @command('bookmarks|bookmark',
957 @command('bookmarks|bookmark',
963 [('f', 'force', False, _('force')),
958 [('f', 'force', False, _('force')),
964 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
959 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
965 ('d', 'delete', False, _('delete a given bookmark')),
960 ('d', 'delete', False, _('delete a given bookmark')),
966 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
961 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
967 ('i', 'inactive', False, _('mark a bookmark inactive')),
962 ('i', 'inactive', False, _('mark a bookmark inactive')),
968 ] + formatteropts,
963 ] + formatteropts,
969 _('hg bookmarks [OPTIONS]... [NAME]...'))
964 _('hg bookmarks [OPTIONS]... [NAME]...'))
970 def bookmark(ui, repo, *names, **opts):
965 def bookmark(ui, repo, *names, **opts):
971 '''create a new bookmark or list existing bookmarks
966 '''create a new bookmark or list existing bookmarks
972
967
973 Bookmarks are labels on changesets to help track lines of development.
968 Bookmarks are labels on changesets to help track lines of development.
974 Bookmarks are unversioned and can be moved, renamed and deleted.
969 Bookmarks are unversioned and can be moved, renamed and deleted.
975 Deleting or moving a bookmark has no effect on the associated changesets.
970 Deleting or moving a bookmark has no effect on the associated changesets.
976
971
977 Creating or updating to a bookmark causes it to be marked as 'active'.
972 Creating or updating to a bookmark causes it to be marked as 'active'.
978 The active bookmark is indicated with a '*'.
973 The active bookmark is indicated with a '*'.
979 When a commit is made, the active bookmark will advance to the new commit.
974 When a commit is made, the active bookmark will advance to the new commit.
980 A plain :hg:`update` will also advance an active bookmark, if possible.
975 A plain :hg:`update` will also advance an active bookmark, if possible.
981 Updating away from a bookmark will cause it to be deactivated.
976 Updating away from a bookmark will cause it to be deactivated.
982
977
983 Bookmarks can be pushed and pulled between repositories (see
978 Bookmarks can be pushed and pulled between repositories (see
984 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
979 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
985 diverged, a new 'divergent bookmark' of the form 'name@path' will
980 diverged, a new 'divergent bookmark' of the form 'name@path' will
986 be created. Using :hg:`merge` will resolve the divergence.
981 be created. Using :hg:`merge` will resolve the divergence.
987
982
988 A bookmark named '@' has the special property that :hg:`clone` will
983 A bookmark named '@' has the special property that :hg:`clone` will
989 check it out by default if it exists.
984 check it out by default if it exists.
990
985
991 .. container:: verbose
986 .. container:: verbose
992
987
993 Examples:
988 Examples:
994
989
995 - create an active bookmark for a new line of development::
990 - create an active bookmark for a new line of development::
996
991
997 hg book new-feature
992 hg book new-feature
998
993
999 - create an inactive bookmark as a place marker::
994 - create an inactive bookmark as a place marker::
1000
995
1001 hg book -i reviewed
996 hg book -i reviewed
1002
997
1003 - create an inactive bookmark on another changeset::
998 - create an inactive bookmark on another changeset::
1004
999
1005 hg book -r .^ tested
1000 hg book -r .^ tested
1006
1001
1007 - rename bookmark turkey to dinner::
1002 - rename bookmark turkey to dinner::
1008
1003
1009 hg book -m turkey dinner
1004 hg book -m turkey dinner
1010
1005
1011 - move the '@' bookmark from another branch::
1006 - move the '@' bookmark from another branch::
1012
1007
1013 hg book -f @
1008 hg book -f @
1014 '''
1009 '''
1015 force = opts.get('force')
1010 force = opts.get('force')
1016 rev = opts.get('rev')
1011 rev = opts.get('rev')
1017 delete = opts.get('delete')
1012 delete = opts.get('delete')
1018 rename = opts.get('rename')
1013 rename = opts.get('rename')
1019 inactive = opts.get('inactive')
1014 inactive = opts.get('inactive')
1020
1015
1021 def checkformat(mark):
1016 def checkformat(mark):
1022 mark = mark.strip()
1017 mark = mark.strip()
1023 if not mark:
1018 if not mark:
1024 raise error.Abort(_("bookmark names cannot consist entirely of "
1019 raise error.Abort(_("bookmark names cannot consist entirely of "
1025 "whitespace"))
1020 "whitespace"))
1026 scmutil.checknewlabel(repo, mark, 'bookmark')
1021 scmutil.checknewlabel(repo, mark, 'bookmark')
1027 return mark
1022 return mark
1028
1023
1029 def checkconflict(repo, mark, cur, force=False, target=None):
1024 def checkconflict(repo, mark, cur, force=False, target=None):
1030 if mark in marks and not force:
1025 if mark in marks and not force:
1031 if target:
1026 if target:
1032 if marks[mark] == target and target == cur:
1027 if marks[mark] == target and target == cur:
1033 # re-activating a bookmark
1028 # re-activating a bookmark
1034 return
1029 return
1035 anc = repo.changelog.ancestors([repo[target].rev()])
1030 anc = repo.changelog.ancestors([repo[target].rev()])
1036 bmctx = repo[marks[mark]]
1031 bmctx = repo[marks[mark]]
1037 divs = [repo[b].node() for b in marks
1032 divs = [repo[b].node() for b in marks
1038 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1033 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1039
1034
1040 # allow resolving a single divergent bookmark even if moving
1035 # allow resolving a single divergent bookmark even if moving
1041 # the bookmark across branches when a revision is specified
1036 # the bookmark across branches when a revision is specified
1042 # that contains a divergent bookmark
1037 # that contains a divergent bookmark
1043 if bmctx.rev() not in anc and target in divs:
1038 if bmctx.rev() not in anc and target in divs:
1044 bookmarks.deletedivergent(repo, [target], mark)
1039 bookmarks.deletedivergent(repo, [target], mark)
1045 return
1040 return
1046
1041
1047 deletefrom = [b for b in divs
1042 deletefrom = [b for b in divs
1048 if repo[b].rev() in anc or b == target]
1043 if repo[b].rev() in anc or b == target]
1049 bookmarks.deletedivergent(repo, deletefrom, mark)
1044 bookmarks.deletedivergent(repo, deletefrom, mark)
1050 if bookmarks.validdest(repo, bmctx, repo[target]):
1045 if bookmarks.validdest(repo, bmctx, repo[target]):
1051 ui.status(_("moving bookmark '%s' forward from %s\n") %
1046 ui.status(_("moving bookmark '%s' forward from %s\n") %
1052 (mark, short(bmctx.node())))
1047 (mark, short(bmctx.node())))
1053 return
1048 return
1054 raise error.Abort(_("bookmark '%s' already exists "
1049 raise error.Abort(_("bookmark '%s' already exists "
1055 "(use -f to force)") % mark)
1050 "(use -f to force)") % mark)
1056 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1051 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1057 and not force):
1052 and not force):
1058 raise error.Abort(
1053 raise error.Abort(
1059 _("a bookmark cannot have the name of an existing branch"))
1054 _("a bookmark cannot have the name of an existing branch"))
1060
1055
1061 if delete and rename:
1056 if delete and rename:
1062 raise error.Abort(_("--delete and --rename are incompatible"))
1057 raise error.Abort(_("--delete and --rename are incompatible"))
1063 if delete and rev:
1058 if delete and rev:
1064 raise error.Abort(_("--rev is incompatible with --delete"))
1059 raise error.Abort(_("--rev is incompatible with --delete"))
1065 if rename and rev:
1060 if rename and rev:
1066 raise error.Abort(_("--rev is incompatible with --rename"))
1061 raise error.Abort(_("--rev is incompatible with --rename"))
1067 if not names and (delete or rev):
1062 if not names and (delete or rev):
1068 raise error.Abort(_("bookmark name required"))
1063 raise error.Abort(_("bookmark name required"))
1069
1064
1070 if delete or rename or names or inactive:
1065 if delete or rename or names or inactive:
1071 wlock = lock = tr = None
1066 wlock = lock = tr = None
1072 try:
1067 try:
1073 wlock = repo.wlock()
1068 wlock = repo.wlock()
1074 lock = repo.lock()
1069 lock = repo.lock()
1075 cur = repo.changectx('.').node()
1070 cur = repo.changectx('.').node()
1076 marks = repo._bookmarks
1071 marks = repo._bookmarks
1077 if delete:
1072 if delete:
1078 tr = repo.transaction('bookmark')
1073 tr = repo.transaction('bookmark')
1079 for mark in names:
1074 for mark in names:
1080 if mark not in marks:
1075 if mark not in marks:
1081 raise error.Abort(_("bookmark '%s' does not exist") %
1076 raise error.Abort(_("bookmark '%s' does not exist") %
1082 mark)
1077 mark)
1083 if mark == repo._activebookmark:
1078 if mark == repo._activebookmark:
1084 bookmarks.deactivate(repo)
1079 bookmarks.deactivate(repo)
1085 del marks[mark]
1080 del marks[mark]
1086
1081
1087 elif rename:
1082 elif rename:
1088 tr = repo.transaction('bookmark')
1083 tr = repo.transaction('bookmark')
1089 if not names:
1084 if not names:
1090 raise error.Abort(_("new bookmark name required"))
1085 raise error.Abort(_("new bookmark name required"))
1091 elif len(names) > 1:
1086 elif len(names) > 1:
1092 raise error.Abort(_("only one new bookmark name allowed"))
1087 raise error.Abort(_("only one new bookmark name allowed"))
1093 mark = checkformat(names[0])
1088 mark = checkformat(names[0])
1094 if rename not in marks:
1089 if rename not in marks:
1095 raise error.Abort(_("bookmark '%s' does not exist")
1090 raise error.Abort(_("bookmark '%s' does not exist")
1096 % rename)
1091 % rename)
1097 checkconflict(repo, mark, cur, force)
1092 checkconflict(repo, mark, cur, force)
1098 marks[mark] = marks[rename]
1093 marks[mark] = marks[rename]
1099 if repo._activebookmark == rename and not inactive:
1094 if repo._activebookmark == rename and not inactive:
1100 bookmarks.activate(repo, mark)
1095 bookmarks.activate(repo, mark)
1101 del marks[rename]
1096 del marks[rename]
1102 elif names:
1097 elif names:
1103 tr = repo.transaction('bookmark')
1098 tr = repo.transaction('bookmark')
1104 newact = None
1099 newact = None
1105 for mark in names:
1100 for mark in names:
1106 mark = checkformat(mark)
1101 mark = checkformat(mark)
1107 if newact is None:
1102 if newact is None:
1108 newact = mark
1103 newact = mark
1109 if inactive and mark == repo._activebookmark:
1104 if inactive and mark == repo._activebookmark:
1110 bookmarks.deactivate(repo)
1105 bookmarks.deactivate(repo)
1111 return
1106 return
1112 tgt = cur
1107 tgt = cur
1113 if rev:
1108 if rev:
1114 tgt = scmutil.revsingle(repo, rev).node()
1109 tgt = scmutil.revsingle(repo, rev).node()
1115 checkconflict(repo, mark, cur, force, tgt)
1110 checkconflict(repo, mark, cur, force, tgt)
1116 marks[mark] = tgt
1111 marks[mark] = tgt
1117 if not inactive and cur == marks[newact] and not rev:
1112 if not inactive and cur == marks[newact] and not rev:
1118 bookmarks.activate(repo, newact)
1113 bookmarks.activate(repo, newact)
1119 elif cur != tgt and newact == repo._activebookmark:
1114 elif cur != tgt and newact == repo._activebookmark:
1120 bookmarks.deactivate(repo)
1115 bookmarks.deactivate(repo)
1121 elif inactive:
1116 elif inactive:
1122 if len(marks) == 0:
1117 if len(marks) == 0:
1123 ui.status(_("no bookmarks set\n"))
1118 ui.status(_("no bookmarks set\n"))
1124 elif not repo._activebookmark:
1119 elif not repo._activebookmark:
1125 ui.status(_("no active bookmark\n"))
1120 ui.status(_("no active bookmark\n"))
1126 else:
1121 else:
1127 bookmarks.deactivate(repo)
1122 bookmarks.deactivate(repo)
1128 if tr is not None:
1123 if tr is not None:
1129 marks.recordchange(tr)
1124 marks.recordchange(tr)
1130 tr.close()
1125 tr.close()
1131 finally:
1126 finally:
1132 lockmod.release(tr, lock, wlock)
1127 lockmod.release(tr, lock, wlock)
1133 else: # show bookmarks
1128 else: # show bookmarks
1134 fm = ui.formatter('bookmarks', opts)
1129 fm = ui.formatter('bookmarks', opts)
1135 hexfn = fm.hexfunc
1130 hexfn = fm.hexfunc
1136 marks = repo._bookmarks
1131 marks = repo._bookmarks
1137 if len(marks) == 0 and fm.isplain():
1132 if len(marks) == 0 and fm.isplain():
1138 ui.status(_("no bookmarks set\n"))
1133 ui.status(_("no bookmarks set\n"))
1139 for bmark, n in sorted(marks.iteritems()):
1134 for bmark, n in sorted(marks.iteritems()):
1140 active = repo._activebookmark
1135 active = repo._activebookmark
1141 if bmark == active:
1136 if bmark == active:
1142 prefix, label = '*', activebookmarklabel
1137 prefix, label = '*', activebookmarklabel
1143 else:
1138 else:
1144 prefix, label = ' ', ''
1139 prefix, label = ' ', ''
1145
1140
1146 fm.startitem()
1141 fm.startitem()
1147 if not ui.quiet:
1142 if not ui.quiet:
1148 fm.plain(' %s ' % prefix, label=label)
1143 fm.plain(' %s ' % prefix, label=label)
1149 fm.write('bookmark', '%s', bmark, label=label)
1144 fm.write('bookmark', '%s', bmark, label=label)
1150 pad = " " * (25 - encoding.colwidth(bmark))
1145 pad = " " * (25 - encoding.colwidth(bmark))
1151 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1146 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1152 repo.changelog.rev(n), hexfn(n), label=label)
1147 repo.changelog.rev(n), hexfn(n), label=label)
1153 fm.data(active=(bmark == active))
1148 fm.data(active=(bmark == active))
1154 fm.plain('\n')
1149 fm.plain('\n')
1155 fm.end()
1150 fm.end()
1156
1151
1157 @command('branch',
1152 @command('branch',
1158 [('f', 'force', None,
1153 [('f', 'force', None,
1159 _('set branch name even if it shadows an existing branch')),
1154 _('set branch name even if it shadows an existing branch')),
1160 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1155 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1161 _('[-fC] [NAME]'))
1156 _('[-fC] [NAME]'))
1162 def branch(ui, repo, label=None, **opts):
1157 def branch(ui, repo, label=None, **opts):
1163 """set or show the current branch name
1158 """set or show the current branch name
1164
1159
1165 .. note::
1160 .. note::
1166
1161
1167 Branch names are permanent and global. Use :hg:`bookmark` to create a
1162 Branch names are permanent and global. Use :hg:`bookmark` to create a
1168 light-weight bookmark instead. See :hg:`help glossary` for more
1163 light-weight bookmark instead. See :hg:`help glossary` for more
1169 information about named branches and bookmarks.
1164 information about named branches and bookmarks.
1170
1165
1171 With no argument, show the current branch name. With one argument,
1166 With no argument, show the current branch name. With one argument,
1172 set the working directory branch name (the branch will not exist
1167 set the working directory branch name (the branch will not exist
1173 in the repository until the next commit). Standard practice
1168 in the repository until the next commit). Standard practice
1174 recommends that primary development take place on the 'default'
1169 recommends that primary development take place on the 'default'
1175 branch.
1170 branch.
1176
1171
1177 Unless -f/--force is specified, branch will not let you set a
1172 Unless -f/--force is specified, branch will not let you set a
1178 branch name that already exists.
1173 branch name that already exists.
1179
1174
1180 Use -C/--clean to reset the working directory branch to that of
1175 Use -C/--clean to reset the working directory branch to that of
1181 the parent of the working directory, negating a previous branch
1176 the parent of the working directory, negating a previous branch
1182 change.
1177 change.
1183
1178
1184 Use the command :hg:`update` to switch to an existing branch. Use
1179 Use the command :hg:`update` to switch to an existing branch. Use
1185 :hg:`commit --close-branch` to mark this branch head as closed.
1180 :hg:`commit --close-branch` to mark this branch head as closed.
1186 When all heads of a branch are closed, the branch will be
1181 When all heads of a branch are closed, the branch will be
1187 considered closed.
1182 considered closed.
1188
1183
1189 Returns 0 on success.
1184 Returns 0 on success.
1190 """
1185 """
1191 if label:
1186 if label:
1192 label = label.strip()
1187 label = label.strip()
1193
1188
1194 if not opts.get('clean') and not label:
1189 if not opts.get('clean') and not label:
1195 ui.write("%s\n" % repo.dirstate.branch())
1190 ui.write("%s\n" % repo.dirstate.branch())
1196 return
1191 return
1197
1192
1198 with repo.wlock():
1193 with repo.wlock():
1199 if opts.get('clean'):
1194 if opts.get('clean'):
1200 label = repo[None].p1().branch()
1195 label = repo[None].p1().branch()
1201 repo.dirstate.setbranch(label)
1196 repo.dirstate.setbranch(label)
1202 ui.status(_('reset working directory to branch %s\n') % label)
1197 ui.status(_('reset working directory to branch %s\n') % label)
1203 elif label:
1198 elif label:
1204 if not opts.get('force') and label in repo.branchmap():
1199 if not opts.get('force') and label in repo.branchmap():
1205 if label not in [p.branch() for p in repo[None].parents()]:
1200 if label not in [p.branch() for p in repo[None].parents()]:
1206 raise error.Abort(_('a branch of the same name already'
1201 raise error.Abort(_('a branch of the same name already'
1207 ' exists'),
1202 ' exists'),
1208 # i18n: "it" refers to an existing branch
1203 # i18n: "it" refers to an existing branch
1209 hint=_("use 'hg update' to switch to it"))
1204 hint=_("use 'hg update' to switch to it"))
1210 scmutil.checknewlabel(repo, label, 'branch')
1205 scmutil.checknewlabel(repo, label, 'branch')
1211 repo.dirstate.setbranch(label)
1206 repo.dirstate.setbranch(label)
1212 ui.status(_('marked working directory as branch %s\n') % label)
1207 ui.status(_('marked working directory as branch %s\n') % label)
1213
1208
1214 # find any open named branches aside from default
1209 # find any open named branches aside from default
1215 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1210 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1216 if n != "default" and not c]
1211 if n != "default" and not c]
1217 if not others:
1212 if not others:
1218 ui.status(_('(branches are permanent and global, '
1213 ui.status(_('(branches are permanent and global, '
1219 'did you want a bookmark?)\n'))
1214 'did you want a bookmark?)\n'))
1220
1215
1221 @command('branches',
1216 @command('branches',
1222 [('a', 'active', False,
1217 [('a', 'active', False,
1223 _('show only branches that have unmerged heads (DEPRECATED)')),
1218 _('show only branches that have unmerged heads (DEPRECATED)')),
1224 ('c', 'closed', False, _('show normal and closed branches')),
1219 ('c', 'closed', False, _('show normal and closed branches')),
1225 ] + formatteropts,
1220 ] + formatteropts,
1226 _('[-c]'))
1221 _('[-c]'))
1227 def branches(ui, repo, active=False, closed=False, **opts):
1222 def branches(ui, repo, active=False, closed=False, **opts):
1228 """list repository named branches
1223 """list repository named branches
1229
1224
1230 List the repository's named branches, indicating which ones are
1225 List the repository's named branches, indicating which ones are
1231 inactive. If -c/--closed is specified, also list branches which have
1226 inactive. If -c/--closed is specified, also list branches which have
1232 been marked closed (see :hg:`commit --close-branch`).
1227 been marked closed (see :hg:`commit --close-branch`).
1233
1228
1234 Use the command :hg:`update` to switch to an existing branch.
1229 Use the command :hg:`update` to switch to an existing branch.
1235
1230
1236 Returns 0.
1231 Returns 0.
1237 """
1232 """
1238
1233
1239 fm = ui.formatter('branches', opts)
1234 fm = ui.formatter('branches', opts)
1240 hexfunc = fm.hexfunc
1235 hexfunc = fm.hexfunc
1241
1236
1242 allheads = set(repo.heads())
1237 allheads = set(repo.heads())
1243 branches = []
1238 branches = []
1244 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1239 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1245 isactive = not isclosed and bool(set(heads) & allheads)
1240 isactive = not isclosed and bool(set(heads) & allheads)
1246 branches.append((tag, repo[tip], isactive, not isclosed))
1241 branches.append((tag, repo[tip], isactive, not isclosed))
1247 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1242 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1248 reverse=True)
1243 reverse=True)
1249
1244
1250 for tag, ctx, isactive, isopen in branches:
1245 for tag, ctx, isactive, isopen in branches:
1251 if active and not isactive:
1246 if active and not isactive:
1252 continue
1247 continue
1253 if isactive:
1248 if isactive:
1254 label = 'branches.active'
1249 label = 'branches.active'
1255 notice = ''
1250 notice = ''
1256 elif not isopen:
1251 elif not isopen:
1257 if not closed:
1252 if not closed:
1258 continue
1253 continue
1259 label = 'branches.closed'
1254 label = 'branches.closed'
1260 notice = _(' (closed)')
1255 notice = _(' (closed)')
1261 else:
1256 else:
1262 label = 'branches.inactive'
1257 label = 'branches.inactive'
1263 notice = _(' (inactive)')
1258 notice = _(' (inactive)')
1264 current = (tag == repo.dirstate.branch())
1259 current = (tag == repo.dirstate.branch())
1265 if current:
1260 if current:
1266 label = 'branches.current'
1261 label = 'branches.current'
1267
1262
1268 fm.startitem()
1263 fm.startitem()
1269 fm.write('branch', '%s', tag, label=label)
1264 fm.write('branch', '%s', tag, label=label)
1270 rev = ctx.rev()
1265 rev = ctx.rev()
1271 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1266 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1272 fmt = ' ' * padsize + ' %d:%s'
1267 fmt = ' ' * padsize + ' %d:%s'
1273 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1268 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1274 label='log.changeset changeset.%s' % ctx.phasestr())
1269 label='log.changeset changeset.%s' % ctx.phasestr())
1275 fm.data(active=isactive, closed=not isopen, current=current)
1270 fm.data(active=isactive, closed=not isopen, current=current)
1276 if not ui.quiet:
1271 if not ui.quiet:
1277 fm.plain(notice)
1272 fm.plain(notice)
1278 fm.plain('\n')
1273 fm.plain('\n')
1279 fm.end()
1274 fm.end()
1280
1275
1281 @command('bundle',
1276 @command('bundle',
1282 [('f', 'force', None, _('run even when the destination is unrelated')),
1277 [('f', 'force', None, _('run even when the destination is unrelated')),
1283 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1278 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1284 _('REV')),
1279 _('REV')),
1285 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1280 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1286 _('BRANCH')),
1281 _('BRANCH')),
1287 ('', 'base', [],
1282 ('', 'base', [],
1288 _('a base changeset assumed to be available at the destination'),
1283 _('a base changeset assumed to be available at the destination'),
1289 _('REV')),
1284 _('REV')),
1290 ('a', 'all', None, _('bundle all changesets in the repository')),
1285 ('a', 'all', None, _('bundle all changesets in the repository')),
1291 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1286 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1292 ] + remoteopts,
1287 ] + remoteopts,
1293 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1288 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1294 def bundle(ui, repo, fname, dest=None, **opts):
1289 def bundle(ui, repo, fname, dest=None, **opts):
1295 """create a changegroup file
1290 """create a changegroup file
1296
1291
1297 Generate a changegroup file collecting changesets to be added
1292 Generate a changegroup file collecting changesets to be added
1298 to a repository.
1293 to a repository.
1299
1294
1300 To create a bundle containing all changesets, use -a/--all
1295 To create a bundle containing all changesets, use -a/--all
1301 (or --base null). Otherwise, hg assumes the destination will have
1296 (or --base null). Otherwise, hg assumes the destination will have
1302 all the nodes you specify with --base parameters. Otherwise, hg
1297 all the nodes you specify with --base parameters. Otherwise, hg
1303 will assume the repository has all the nodes in destination, or
1298 will assume the repository has all the nodes in destination, or
1304 default-push/default if no destination is specified.
1299 default-push/default if no destination is specified.
1305
1300
1306 You can change bundle format with the -t/--type option. You can
1301 You can change bundle format with the -t/--type option. You can
1307 specify a compression, a bundle version or both using a dash
1302 specify a compression, a bundle version or both using a dash
1308 (comp-version). The available compression methods are: none, bzip2,
1303 (comp-version). The available compression methods are: none, bzip2,
1309 and gzip (by default, bundles are compressed using bzip2). The
1304 and gzip (by default, bundles are compressed using bzip2). The
1310 available formats are: v1, v2 (default to most suitable).
1305 available formats are: v1, v2 (default to most suitable).
1311
1306
1312 The bundle file can then be transferred using conventional means
1307 The bundle file can then be transferred using conventional means
1313 and applied to another repository with the unbundle or pull
1308 and applied to another repository with the unbundle or pull
1314 command. This is useful when direct push and pull are not
1309 command. This is useful when direct push and pull are not
1315 available or when exporting an entire repository is undesirable.
1310 available or when exporting an entire repository is undesirable.
1316
1311
1317 Applying bundles preserves all changeset contents including
1312 Applying bundles preserves all changeset contents including
1318 permissions, copy/rename information, and revision history.
1313 permissions, copy/rename information, and revision history.
1319
1314
1320 Returns 0 on success, 1 if no changes found.
1315 Returns 0 on success, 1 if no changes found.
1321 """
1316 """
1322 revs = None
1317 revs = None
1323 if 'rev' in opts:
1318 if 'rev' in opts:
1324 revstrings = opts['rev']
1319 revstrings = opts['rev']
1325 revs = scmutil.revrange(repo, revstrings)
1320 revs = scmutil.revrange(repo, revstrings)
1326 if revstrings and not revs:
1321 if revstrings and not revs:
1327 raise error.Abort(_('no commits to bundle'))
1322 raise error.Abort(_('no commits to bundle'))
1328
1323
1329 bundletype = opts.get('type', 'bzip2').lower()
1324 bundletype = opts.get('type', 'bzip2').lower()
1330 try:
1325 try:
1331 bcompression, cgversion, params = exchange.parsebundlespec(
1326 bcompression, cgversion, params = exchange.parsebundlespec(
1332 repo, bundletype, strict=False)
1327 repo, bundletype, strict=False)
1333 except error.UnsupportedBundleSpecification as e:
1328 except error.UnsupportedBundleSpecification as e:
1334 raise error.Abort(str(e),
1329 raise error.Abort(str(e),
1335 hint=_("see 'hg help bundle' for supported "
1330 hint=_("see 'hg help bundle' for supported "
1336 "values for --type"))
1331 "values for --type"))
1337
1332
1338 # Packed bundles are a pseudo bundle format for now.
1333 # Packed bundles are a pseudo bundle format for now.
1339 if cgversion == 's1':
1334 if cgversion == 's1':
1340 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1335 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1341 hint=_("use 'hg debugcreatestreamclonebundle'"))
1336 hint=_("use 'hg debugcreatestreamclonebundle'"))
1342
1337
1343 if opts.get('all'):
1338 if opts.get('all'):
1344 if dest:
1339 if dest:
1345 raise error.Abort(_("--all is incompatible with specifying "
1340 raise error.Abort(_("--all is incompatible with specifying "
1346 "a destination"))
1341 "a destination"))
1347 if opts.get('base'):
1342 if opts.get('base'):
1348 ui.warn(_("ignoring --base because --all was specified\n"))
1343 ui.warn(_("ignoring --base because --all was specified\n"))
1349 base = ['null']
1344 base = ['null']
1350 else:
1345 else:
1351 base = scmutil.revrange(repo, opts.get('base'))
1346 base = scmutil.revrange(repo, opts.get('base'))
1352 # TODO: get desired bundlecaps from command line.
1347 # TODO: get desired bundlecaps from command line.
1353 bundlecaps = None
1348 bundlecaps = None
1354 if cgversion not in changegroup.supportedoutgoingversions(repo):
1349 if cgversion not in changegroup.supportedoutgoingversions(repo):
1355 raise error.Abort(_("repository does not support bundle version %s") %
1350 raise error.Abort(_("repository does not support bundle version %s") %
1356 cgversion)
1351 cgversion)
1357
1352
1358 if base:
1353 if base:
1359 if dest:
1354 if dest:
1360 raise error.Abort(_("--base is incompatible with specifying "
1355 raise error.Abort(_("--base is incompatible with specifying "
1361 "a destination"))
1356 "a destination"))
1362 common = [repo.lookup(rev) for rev in base]
1357 common = [repo.lookup(rev) for rev in base]
1363 heads = revs and map(repo.lookup, revs) or None
1358 heads = revs and map(repo.lookup, revs) or None
1364 outgoing = discovery.outgoing(repo, common, heads)
1359 outgoing = discovery.outgoing(repo, common, heads)
1365 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1360 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1366 bundlecaps=bundlecaps,
1361 bundlecaps=bundlecaps,
1367 version=cgversion)
1362 version=cgversion)
1368 outgoing = None
1363 outgoing = None
1369 else:
1364 else:
1370 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1365 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1371 dest, branches = hg.parseurl(dest, opts.get('branch'))
1366 dest, branches = hg.parseurl(dest, opts.get('branch'))
1372 other = hg.peer(repo, opts, dest)
1367 other = hg.peer(repo, opts, dest)
1373 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1368 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1374 heads = revs and map(repo.lookup, revs) or revs
1369 heads = revs and map(repo.lookup, revs) or revs
1375 outgoing = discovery.findcommonoutgoing(repo, other,
1370 outgoing = discovery.findcommonoutgoing(repo, other,
1376 onlyheads=heads,
1371 onlyheads=heads,
1377 force=opts.get('force'),
1372 force=opts.get('force'),
1378 portable=True)
1373 portable=True)
1379 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1374 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1380 bundlecaps, version=cgversion)
1375 bundlecaps, version=cgversion)
1381 if not cg:
1376 if not cg:
1382 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1377 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1383 return 1
1378 return 1
1384
1379
1385 if cgversion == '01': #bundle1
1380 if cgversion == '01': #bundle1
1386 if bcompression is None:
1381 if bcompression is None:
1387 bcompression = 'UN'
1382 bcompression = 'UN'
1388 bversion = 'HG10' + bcompression
1383 bversion = 'HG10' + bcompression
1389 bcompression = None
1384 bcompression = None
1390 else:
1385 else:
1391 assert cgversion == '02'
1386 assert cgversion == '02'
1392 bversion = 'HG20'
1387 bversion = 'HG20'
1393
1388
1394 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1389 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression)
1395
1390
1396 @command('cat',
1391 @command('cat',
1397 [('o', 'output', '',
1392 [('o', 'output', '',
1398 _('print output to file with formatted name'), _('FORMAT')),
1393 _('print output to file with formatted name'), _('FORMAT')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1394 ('r', 'rev', '', _('print the given revision'), _('REV')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1395 ('', 'decode', None, _('apply any matching decode filter')),
1401 ] + walkopts,
1396 ] + walkopts,
1402 _('[OPTION]... FILE...'),
1397 _('[OPTION]... FILE...'),
1403 inferrepo=True)
1398 inferrepo=True)
1404 def cat(ui, repo, file1, *pats, **opts):
1399 def cat(ui, repo, file1, *pats, **opts):
1405 """output the current or given revision of files
1400 """output the current or given revision of files
1406
1401
1407 Print the specified files as they were at the given revision. If
1402 Print the specified files as they were at the given revision. If
1408 no revision is given, the parent of the working directory is used.
1403 no revision is given, the parent of the working directory is used.
1409
1404
1410 Output may be to a file, in which case the name of the file is
1405 Output may be to a file, in which case the name of the file is
1411 given using a format string. The formatting rules as follows:
1406 given using a format string. The formatting rules as follows:
1412
1407
1413 :``%%``: literal "%" character
1408 :``%%``: literal "%" character
1414 :``%s``: basename of file being printed
1409 :``%s``: basename of file being printed
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1410 :``%d``: dirname of file being printed, or '.' if in repository root
1416 :``%p``: root-relative path name of file being printed
1411 :``%p``: root-relative path name of file being printed
1417 :``%H``: changeset hash (40 hexadecimal digits)
1412 :``%H``: changeset hash (40 hexadecimal digits)
1418 :``%R``: changeset revision number
1413 :``%R``: changeset revision number
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1414 :``%h``: short-form changeset hash (12 hexadecimal digits)
1420 :``%r``: zero-padded changeset revision number
1415 :``%r``: zero-padded changeset revision number
1421 :``%b``: basename of the exporting repository
1416 :``%b``: basename of the exporting repository
1422
1417
1423 Returns 0 on success.
1418 Returns 0 on success.
1424 """
1419 """
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1420 ctx = scmutil.revsingle(repo, opts.get('rev'))
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1421 m = scmutil.match(ctx, (file1,) + pats, opts)
1427
1422
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1423 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1429
1424
1430 @command('^clone',
1425 @command('^clone',
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1426 [('U', 'noupdate', None, _('the clone will include an empty working '
1432 'directory (only a repository)')),
1427 'directory (only a repository)')),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1428 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1434 _('REV')),
1429 _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1430 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1431 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1432 ('', 'pull', None, _('use pull protocol to copy metadata')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1433 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1439 ] + remoteopts,
1434 ] + remoteopts,
1440 _('[OPTION]... SOURCE [DEST]'),
1435 _('[OPTION]... SOURCE [DEST]'),
1441 norepo=True)
1436 norepo=True)
1442 def clone(ui, source, dest=None, **opts):
1437 def clone(ui, source, dest=None, **opts):
1443 """make a copy of an existing repository
1438 """make a copy of an existing repository
1444
1439
1445 Create a copy of an existing repository in a new directory.
1440 Create a copy of an existing repository in a new directory.
1446
1441
1447 If no destination directory name is specified, it defaults to the
1442 If no destination directory name is specified, it defaults to the
1448 basename of the source.
1443 basename of the source.
1449
1444
1450 The location of the source is added to the new repository's
1445 The location of the source is added to the new repository's
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1446 ``.hg/hgrc`` file, as the default to be used for future pulls.
1452
1447
1453 Only local paths and ``ssh://`` URLs are supported as
1448 Only local paths and ``ssh://`` URLs are supported as
1454 destinations. For ``ssh://`` destinations, no working directory or
1449 destinations. For ``ssh://`` destinations, no working directory or
1455 ``.hg/hgrc`` will be created on the remote side.
1450 ``.hg/hgrc`` will be created on the remote side.
1456
1451
1457 If the source repository has a bookmark called '@' set, that
1452 If the source repository has a bookmark called '@' set, that
1458 revision will be checked out in the new repository by default.
1453 revision will be checked out in the new repository by default.
1459
1454
1460 To check out a particular version, use -u/--update, or
1455 To check out a particular version, use -u/--update, or
1461 -U/--noupdate to create a clone with no working directory.
1456 -U/--noupdate to create a clone with no working directory.
1462
1457
1463 To pull only a subset of changesets, specify one or more revisions
1458 To pull only a subset of changesets, specify one or more revisions
1464 identifiers with -r/--rev or branches with -b/--branch. The
1459 identifiers with -r/--rev or branches with -b/--branch. The
1465 resulting clone will contain only the specified changesets and
1460 resulting clone will contain only the specified changesets and
1466 their ancestors. These options (or 'clone src#rev dest') imply
1461 their ancestors. These options (or 'clone src#rev dest') imply
1467 --pull, even for local source repositories.
1462 --pull, even for local source repositories.
1468
1463
1469 .. note::
1464 .. note::
1470
1465
1471 Specifying a tag will include the tagged changeset but not the
1466 Specifying a tag will include the tagged changeset but not the
1472 changeset containing the tag.
1467 changeset containing the tag.
1473
1468
1474 .. container:: verbose
1469 .. container:: verbose
1475
1470
1476 For efficiency, hardlinks are used for cloning whenever the
1471 For efficiency, hardlinks are used for cloning whenever the
1477 source and destination are on the same filesystem (note this
1472 source and destination are on the same filesystem (note this
1478 applies only to the repository data, not to the working
1473 applies only to the repository data, not to the working
1479 directory). Some filesystems, such as AFS, implement hardlinking
1474 directory). Some filesystems, such as AFS, implement hardlinking
1480 incorrectly, but do not report errors. In these cases, use the
1475 incorrectly, but do not report errors. In these cases, use the
1481 --pull option to avoid hardlinking.
1476 --pull option to avoid hardlinking.
1482
1477
1483 In some cases, you can clone repositories and the working
1478 In some cases, you can clone repositories and the working
1484 directory using full hardlinks with ::
1479 directory using full hardlinks with ::
1485
1480
1486 $ cp -al REPO REPOCLONE
1481 $ cp -al REPO REPOCLONE
1487
1482
1488 This is the fastest way to clone, but it is not always safe. The
1483 This is the fastest way to clone, but it is not always safe. The
1489 operation is not atomic (making sure REPO is not modified during
1484 operation is not atomic (making sure REPO is not modified during
1490 the operation is up to you) and you have to make sure your
1485 the operation is up to you) and you have to make sure your
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1486 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1492 so). Also, this is not compatible with certain extensions that
1487 so). Also, this is not compatible with certain extensions that
1493 place their metadata under the .hg directory, such as mq.
1488 place their metadata under the .hg directory, such as mq.
1494
1489
1495 Mercurial will update the working directory to the first applicable
1490 Mercurial will update the working directory to the first applicable
1496 revision from this list:
1491 revision from this list:
1497
1492
1498 a) null if -U or the source repository has no changesets
1493 a) null if -U or the source repository has no changesets
1499 b) if -u . and the source repository is local, the first parent of
1494 b) if -u . and the source repository is local, the first parent of
1500 the source repository's working directory
1495 the source repository's working directory
1501 c) the changeset specified with -u (if a branch name, this means the
1496 c) the changeset specified with -u (if a branch name, this means the
1502 latest head of that branch)
1497 latest head of that branch)
1503 d) the changeset specified with -r
1498 d) the changeset specified with -r
1504 e) the tipmost head specified with -b
1499 e) the tipmost head specified with -b
1505 f) the tipmost head specified with the url#branch source syntax
1500 f) the tipmost head specified with the url#branch source syntax
1506 g) the revision marked with the '@' bookmark, if present
1501 g) the revision marked with the '@' bookmark, if present
1507 h) the tipmost head of the default branch
1502 h) the tipmost head of the default branch
1508 i) tip
1503 i) tip
1509
1504
1510 When cloning from servers that support it, Mercurial may fetch
1505 When cloning from servers that support it, Mercurial may fetch
1511 pre-generated data from a server-advertised URL. When this is done,
1506 pre-generated data from a server-advertised URL. When this is done,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1507 hooks operating on incoming changesets and changegroups may fire twice,
1513 once for the bundle fetched from the URL and another for any additional
1508 once for the bundle fetched from the URL and another for any additional
1514 data not fetched from this URL. In addition, if an error occurs, the
1509 data not fetched from this URL. In addition, if an error occurs, the
1515 repository may be rolled back to a partial clone. This behavior may
1510 repository may be rolled back to a partial clone. This behavior may
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1511 change in future releases. See :hg:`help -e clonebundles` for more.
1517
1512
1518 Examples:
1513 Examples:
1519
1514
1520 - clone a remote repository to a new directory named hg/::
1515 - clone a remote repository to a new directory named hg/::
1521
1516
1522 hg clone https://www.mercurial-scm.org/repo/hg/
1517 hg clone https://www.mercurial-scm.org/repo/hg/
1523
1518
1524 - create a lightweight local clone::
1519 - create a lightweight local clone::
1525
1520
1526 hg clone project/ project-feature/
1521 hg clone project/ project-feature/
1527
1522
1528 - clone from an absolute path on an ssh server (note double-slash)::
1523 - clone from an absolute path on an ssh server (note double-slash)::
1529
1524
1530 hg clone ssh://user@server//home/projects/alpha/
1525 hg clone ssh://user@server//home/projects/alpha/
1531
1526
1532 - do a high-speed clone over a LAN while checking out a
1527 - do a high-speed clone over a LAN while checking out a
1533 specified version::
1528 specified version::
1534
1529
1535 hg clone --uncompressed http://server/repo -u 1.5
1530 hg clone --uncompressed http://server/repo -u 1.5
1536
1531
1537 - create a repository without changesets after a particular revision::
1532 - create a repository without changesets after a particular revision::
1538
1533
1539 hg clone -r 04e544 experimental/ good/
1534 hg clone -r 04e544 experimental/ good/
1540
1535
1541 - clone (and track) a particular named branch::
1536 - clone (and track) a particular named branch::
1542
1537
1543 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1538 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1544
1539
1545 See :hg:`help urls` for details on specifying URLs.
1540 See :hg:`help urls` for details on specifying URLs.
1546
1541
1547 Returns 0 on success.
1542 Returns 0 on success.
1548 """
1543 """
1549 if opts.get('noupdate') and opts.get('updaterev'):
1544 if opts.get('noupdate') and opts.get('updaterev'):
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1545 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1551
1546
1552 r = hg.clone(ui, opts, source, dest,
1547 r = hg.clone(ui, opts, source, dest,
1553 pull=opts.get('pull'),
1548 pull=opts.get('pull'),
1554 stream=opts.get('uncompressed'),
1549 stream=opts.get('uncompressed'),
1555 rev=opts.get('rev'),
1550 rev=opts.get('rev'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1551 update=opts.get('updaterev') or not opts.get('noupdate'),
1557 branch=opts.get('branch'),
1552 branch=opts.get('branch'),
1558 shareopts=opts.get('shareopts'))
1553 shareopts=opts.get('shareopts'))
1559
1554
1560 return r is None
1555 return r is None
1561
1556
1562 @command('^commit|ci',
1557 @command('^commit|ci',
1563 [('A', 'addremove', None,
1558 [('A', 'addremove', None,
1564 _('mark new/missing files as added/removed before committing')),
1559 _('mark new/missing files as added/removed before committing')),
1565 ('', 'close-branch', None,
1560 ('', 'close-branch', None,
1566 _('mark a branch head as closed')),
1561 _('mark a branch head as closed')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1562 ('', 'amend', None, _('amend the parent of the working directory')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1563 ('s', 'secret', None, _('use the secret phase for committing')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1564 ('e', 'edit', None, _('invoke editor on commit messages')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1565 ('i', 'interactive', None, _('use interactive mode')),
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1566 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1572 _('[OPTION]... [FILE]...'),
1567 _('[OPTION]... [FILE]...'),
1573 inferrepo=True)
1568 inferrepo=True)
1574 def commit(ui, repo, *pats, **opts):
1569 def commit(ui, repo, *pats, **opts):
1575 """commit the specified files or all outstanding changes
1570 """commit the specified files or all outstanding changes
1576
1571
1577 Commit changes to the given files into the repository. Unlike a
1572 Commit changes to the given files into the repository. Unlike a
1578 centralized SCM, this operation is a local operation. See
1573 centralized SCM, this operation is a local operation. See
1579 :hg:`push` for a way to actively distribute your changes.
1574 :hg:`push` for a way to actively distribute your changes.
1580
1575
1581 If a list of files is omitted, all changes reported by :hg:`status`
1576 If a list of files is omitted, all changes reported by :hg:`status`
1582 will be committed.
1577 will be committed.
1583
1578
1584 If you are committing the result of a merge, do not provide any
1579 If you are committing the result of a merge, do not provide any
1585 filenames or -I/-X filters.
1580 filenames or -I/-X filters.
1586
1581
1587 If no commit message is specified, Mercurial starts your
1582 If no commit message is specified, Mercurial starts your
1588 configured editor where you can enter a message. In case your
1583 configured editor where you can enter a message. In case your
1589 commit fails, you will find a backup of your message in
1584 commit fails, you will find a backup of your message in
1590 ``.hg/last-message.txt``.
1585 ``.hg/last-message.txt``.
1591
1586
1592 The --close-branch flag can be used to mark the current branch
1587 The --close-branch flag can be used to mark the current branch
1593 head closed. When all heads of a branch are closed, the branch
1588 head closed. When all heads of a branch are closed, the branch
1594 will be considered closed and no longer listed.
1589 will be considered closed and no longer listed.
1595
1590
1596 The --amend flag can be used to amend the parent of the
1591 The --amend flag can be used to amend the parent of the
1597 working directory with a new commit that contains the changes
1592 working directory with a new commit that contains the changes
1598 in the parent in addition to those currently reported by :hg:`status`,
1593 in the parent in addition to those currently reported by :hg:`status`,
1599 if there are any. The old commit is stored in a backup bundle in
1594 if there are any. The old commit is stored in a backup bundle in
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1595 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1601 on how to restore it).
1596 on how to restore it).
1602
1597
1603 Message, user and date are taken from the amended commit unless
1598 Message, user and date are taken from the amended commit unless
1604 specified. When a message isn't specified on the command line,
1599 specified. When a message isn't specified on the command line,
1605 the editor will open with the message of the amended commit.
1600 the editor will open with the message of the amended commit.
1606
1601
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1602 It is not possible to amend public changesets (see :hg:`help phases`)
1608 or changesets that have children.
1603 or changesets that have children.
1609
1604
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1605 See :hg:`help dates` for a list of formats valid for -d/--date.
1611
1606
1612 Returns 0 on success, 1 if nothing changed.
1607 Returns 0 on success, 1 if nothing changed.
1613
1608
1614 .. container:: verbose
1609 .. container:: verbose
1615
1610
1616 Examples:
1611 Examples:
1617
1612
1618 - commit all files ending in .py::
1613 - commit all files ending in .py::
1619
1614
1620 hg commit --include "set:**.py"
1615 hg commit --include "set:**.py"
1621
1616
1622 - commit all non-binary files::
1617 - commit all non-binary files::
1623
1618
1624 hg commit --exclude "set:binary()"
1619 hg commit --exclude "set:binary()"
1625
1620
1626 - amend the current commit and set the date to now::
1621 - amend the current commit and set the date to now::
1627
1622
1628 hg commit --amend --date now
1623 hg commit --amend --date now
1629 """
1624 """
1630 wlock = lock = None
1625 wlock = lock = None
1631 try:
1626 try:
1632 wlock = repo.wlock()
1627 wlock = repo.wlock()
1633 lock = repo.lock()
1628 lock = repo.lock()
1634 return _docommit(ui, repo, *pats, **opts)
1629 return _docommit(ui, repo, *pats, **opts)
1635 finally:
1630 finally:
1636 release(lock, wlock)
1631 release(lock, wlock)
1637
1632
1638 def _docommit(ui, repo, *pats, **opts):
1633 def _docommit(ui, repo, *pats, **opts):
1639 if opts.get('interactive'):
1634 if opts.get('interactive'):
1640 opts.pop('interactive')
1635 opts.pop('interactive')
1641 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1636 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1642 cmdutil.recordfilter, *pats, **opts)
1637 cmdutil.recordfilter, *pats, **opts)
1643 # ret can be 0 (no changes to record) or the value returned by
1638 # ret can be 0 (no changes to record) or the value returned by
1644 # commit(), 1 if nothing changed or None on success.
1639 # commit(), 1 if nothing changed or None on success.
1645 return 1 if ret == 0 else ret
1640 return 1 if ret == 0 else ret
1646
1641
1647 if opts.get('subrepos'):
1642 if opts.get('subrepos'):
1648 if opts.get('amend'):
1643 if opts.get('amend'):
1649 raise error.Abort(_('cannot amend with --subrepos'))
1644 raise error.Abort(_('cannot amend with --subrepos'))
1650 # Let --subrepos on the command line override config setting.
1645 # Let --subrepos on the command line override config setting.
1651 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1646 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1652
1647
1653 cmdutil.checkunfinished(repo, commit=True)
1648 cmdutil.checkunfinished(repo, commit=True)
1654
1649
1655 branch = repo[None].branch()
1650 branch = repo[None].branch()
1656 bheads = repo.branchheads(branch)
1651 bheads = repo.branchheads(branch)
1657
1652
1658 extra = {}
1653 extra = {}
1659 if opts.get('close_branch'):
1654 if opts.get('close_branch'):
1660 extra['close'] = 1
1655 extra['close'] = 1
1661
1656
1662 if not bheads:
1657 if not bheads:
1663 raise error.Abort(_('can only close branch heads'))
1658 raise error.Abort(_('can only close branch heads'))
1664 elif opts.get('amend'):
1659 elif opts.get('amend'):
1665 if repo[None].parents()[0].p1().branch() != branch and \
1660 if repo[None].parents()[0].p1().branch() != branch and \
1666 repo[None].parents()[0].p2().branch() != branch:
1661 repo[None].parents()[0].p2().branch() != branch:
1667 raise error.Abort(_('can only close branch heads'))
1662 raise error.Abort(_('can only close branch heads'))
1668
1663
1669 if opts.get('amend'):
1664 if opts.get('amend'):
1670 if ui.configbool('ui', 'commitsubrepos'):
1665 if ui.configbool('ui', 'commitsubrepos'):
1671 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1666 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1672
1667
1673 old = repo['.']
1668 old = repo['.']
1674 if not old.mutable():
1669 if not old.mutable():
1675 raise error.Abort(_('cannot amend public changesets'))
1670 raise error.Abort(_('cannot amend public changesets'))
1676 if len(repo[None].parents()) > 1:
1671 if len(repo[None].parents()) > 1:
1677 raise error.Abort(_('cannot amend while merging'))
1672 raise error.Abort(_('cannot amend while merging'))
1678 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1673 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1679 if not allowunstable and old.children():
1674 if not allowunstable and old.children():
1680 raise error.Abort(_('cannot amend changeset with children'))
1675 raise error.Abort(_('cannot amend changeset with children'))
1681
1676
1682 # Currently histedit gets confused if an amend happens while histedit
1677 # Currently histedit gets confused if an amend happens while histedit
1683 # is in progress. Since we have a checkunfinished command, we are
1678 # is in progress. Since we have a checkunfinished command, we are
1684 # temporarily honoring it.
1679 # temporarily honoring it.
1685 #
1680 #
1686 # Note: eventually this guard will be removed. Please do not expect
1681 # Note: eventually this guard will be removed. Please do not expect
1687 # this behavior to remain.
1682 # this behavior to remain.
1688 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1683 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1689 cmdutil.checkunfinished(repo)
1684 cmdutil.checkunfinished(repo)
1690
1685
1691 # commitfunc is used only for temporary amend commit by cmdutil.amend
1686 # commitfunc is used only for temporary amend commit by cmdutil.amend
1692 def commitfunc(ui, repo, message, match, opts):
1687 def commitfunc(ui, repo, message, match, opts):
1693 return repo.commit(message,
1688 return repo.commit(message,
1694 opts.get('user') or old.user(),
1689 opts.get('user') or old.user(),
1695 opts.get('date') or old.date(),
1690 opts.get('date') or old.date(),
1696 match,
1691 match,
1697 extra=extra)
1692 extra=extra)
1698
1693
1699 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1694 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1700 if node == old.node():
1695 if node == old.node():
1701 ui.status(_("nothing changed\n"))
1696 ui.status(_("nothing changed\n"))
1702 return 1
1697 return 1
1703 else:
1698 else:
1704 def commitfunc(ui, repo, message, match, opts):
1699 def commitfunc(ui, repo, message, match, opts):
1705 backup = ui.backupconfig('phases', 'new-commit')
1700 backup = ui.backupconfig('phases', 'new-commit')
1706 baseui = repo.baseui
1701 baseui = repo.baseui
1707 basebackup = baseui.backupconfig('phases', 'new-commit')
1702 basebackup = baseui.backupconfig('phases', 'new-commit')
1708 try:
1703 try:
1709 if opts.get('secret'):
1704 if opts.get('secret'):
1710 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1705 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1711 # Propagate to subrepos
1706 # Propagate to subrepos
1712 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1707 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1713
1708
1714 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1709 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1715 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1710 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1716 return repo.commit(message, opts.get('user'), opts.get('date'),
1711 return repo.commit(message, opts.get('user'), opts.get('date'),
1717 match,
1712 match,
1718 editor=editor,
1713 editor=editor,
1719 extra=extra)
1714 extra=extra)
1720 finally:
1715 finally:
1721 ui.restoreconfig(backup)
1716 ui.restoreconfig(backup)
1722 repo.baseui.restoreconfig(basebackup)
1717 repo.baseui.restoreconfig(basebackup)
1723
1718
1724
1719
1725 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1720 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1726
1721
1727 if not node:
1722 if not node:
1728 stat = cmdutil.postcommitstatus(repo, pats, opts)
1723 stat = cmdutil.postcommitstatus(repo, pats, opts)
1729 if stat[3]:
1724 if stat[3]:
1730 ui.status(_("nothing changed (%d missing files, see "
1725 ui.status(_("nothing changed (%d missing files, see "
1731 "'hg status')\n") % len(stat[3]))
1726 "'hg status')\n") % len(stat[3]))
1732 else:
1727 else:
1733 ui.status(_("nothing changed\n"))
1728 ui.status(_("nothing changed\n"))
1734 return 1
1729 return 1
1735
1730
1736 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1731 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1737
1732
1738 @command('config|showconfig|debugconfig',
1733 @command('config|showconfig|debugconfig',
1739 [('u', 'untrusted', None, _('show untrusted configuration options')),
1734 [('u', 'untrusted', None, _('show untrusted configuration options')),
1740 ('e', 'edit', None, _('edit user config')),
1735 ('e', 'edit', None, _('edit user config')),
1741 ('l', 'local', None, _('edit repository config')),
1736 ('l', 'local', None, _('edit repository config')),
1742 ('g', 'global', None, _('edit global config'))] + formatteropts,
1737 ('g', 'global', None, _('edit global config'))] + formatteropts,
1743 _('[-u] [NAME]...'),
1738 _('[-u] [NAME]...'),
1744 optionalrepo=True)
1739 optionalrepo=True)
1745 def config(ui, repo, *values, **opts):
1740 def config(ui, repo, *values, **opts):
1746 """show combined config settings from all hgrc files
1741 """show combined config settings from all hgrc files
1747
1742
1748 With no arguments, print names and values of all config items.
1743 With no arguments, print names and values of all config items.
1749
1744
1750 With one argument of the form section.name, print just the value
1745 With one argument of the form section.name, print just the value
1751 of that config item.
1746 of that config item.
1752
1747
1753 With multiple arguments, print names and values of all config
1748 With multiple arguments, print names and values of all config
1754 items with matching section names.
1749 items with matching section names.
1755
1750
1756 With --edit, start an editor on the user-level config file. With
1751 With --edit, start an editor on the user-level config file. With
1757 --global, edit the system-wide config file. With --local, edit the
1752 --global, edit the system-wide config file. With --local, edit the
1758 repository-level config file.
1753 repository-level config file.
1759
1754
1760 With --debug, the source (filename and line number) is printed
1755 With --debug, the source (filename and line number) is printed
1761 for each config item.
1756 for each config item.
1762
1757
1763 See :hg:`help config` for more information about config files.
1758 See :hg:`help config` for more information about config files.
1764
1759
1765 Returns 0 on success, 1 if NAME does not exist.
1760 Returns 0 on success, 1 if NAME does not exist.
1766
1761
1767 """
1762 """
1768
1763
1769 if opts.get('edit') or opts.get('local') or opts.get('global'):
1764 if opts.get('edit') or opts.get('local') or opts.get('global'):
1770 if opts.get('local') and opts.get('global'):
1765 if opts.get('local') and opts.get('global'):
1771 raise error.Abort(_("can't use --local and --global together"))
1766 raise error.Abort(_("can't use --local and --global together"))
1772
1767
1773 if opts.get('local'):
1768 if opts.get('local'):
1774 if not repo:
1769 if not repo:
1775 raise error.Abort(_("can't use --local outside a repository"))
1770 raise error.Abort(_("can't use --local outside a repository"))
1776 paths = [repo.join('hgrc')]
1771 paths = [repo.join('hgrc')]
1777 elif opts.get('global'):
1772 elif opts.get('global'):
1778 paths = scmutil.systemrcpath()
1773 paths = scmutil.systemrcpath()
1779 else:
1774 else:
1780 paths = scmutil.userrcpath()
1775 paths = scmutil.userrcpath()
1781
1776
1782 for f in paths:
1777 for f in paths:
1783 if os.path.exists(f):
1778 if os.path.exists(f):
1784 break
1779 break
1785 else:
1780 else:
1786 if opts.get('global'):
1781 if opts.get('global'):
1787 samplehgrc = uimod.samplehgrcs['global']
1782 samplehgrc = uimod.samplehgrcs['global']
1788 elif opts.get('local'):
1783 elif opts.get('local'):
1789 samplehgrc = uimod.samplehgrcs['local']
1784 samplehgrc = uimod.samplehgrcs['local']
1790 else:
1785 else:
1791 samplehgrc = uimod.samplehgrcs['user']
1786 samplehgrc = uimod.samplehgrcs['user']
1792
1787
1793 f = paths[0]
1788 f = paths[0]
1794 fp = open(f, "w")
1789 fp = open(f, "w")
1795 fp.write(samplehgrc)
1790 fp.write(samplehgrc)
1796 fp.close()
1791 fp.close()
1797
1792
1798 editor = ui.geteditor()
1793 editor = ui.geteditor()
1799 ui.system("%s \"%s\"" % (editor, f),
1794 ui.system("%s \"%s\"" % (editor, f),
1800 onerr=error.Abort, errprefix=_("edit failed"))
1795 onerr=error.Abort, errprefix=_("edit failed"))
1801 return
1796 return
1802
1797
1803 fm = ui.formatter('config', opts)
1798 fm = ui.formatter('config', opts)
1804 for f in scmutil.rcpath():
1799 for f in scmutil.rcpath():
1805 ui.debug('read config from: %s\n' % f)
1800 ui.debug('read config from: %s\n' % f)
1806 untrusted = bool(opts.get('untrusted'))
1801 untrusted = bool(opts.get('untrusted'))
1807 if values:
1802 if values:
1808 sections = [v for v in values if '.' not in v]
1803 sections = [v for v in values if '.' not in v]
1809 items = [v for v in values if '.' in v]
1804 items = [v for v in values if '.' in v]
1810 if len(items) > 1 or items and sections:
1805 if len(items) > 1 or items and sections:
1811 raise error.Abort(_('only one config item permitted'))
1806 raise error.Abort(_('only one config item permitted'))
1812 matched = False
1807 matched = False
1813 for section, name, value in ui.walkconfig(untrusted=untrusted):
1808 for section, name, value in ui.walkconfig(untrusted=untrusted):
1814 value = str(value)
1809 value = str(value)
1815 if fm.isplain():
1810 if fm.isplain():
1816 value = value.replace('\n', '\\n')
1811 value = value.replace('\n', '\\n')
1817 entryname = section + '.' + name
1812 entryname = section + '.' + name
1818 if values:
1813 if values:
1819 for v in values:
1814 for v in values:
1820 if v == section:
1815 if v == section:
1821 fm.startitem()
1816 fm.startitem()
1822 fm.condwrite(ui.debugflag, 'source', '%s: ',
1817 fm.condwrite(ui.debugflag, 'source', '%s: ',
1823 ui.configsource(section, name, untrusted))
1818 ui.configsource(section, name, untrusted))
1824 fm.write('name value', '%s=%s\n', entryname, value)
1819 fm.write('name value', '%s=%s\n', entryname, value)
1825 matched = True
1820 matched = True
1826 elif v == entryname:
1821 elif v == entryname:
1827 fm.startitem()
1822 fm.startitem()
1828 fm.condwrite(ui.debugflag, 'source', '%s: ',
1823 fm.condwrite(ui.debugflag, 'source', '%s: ',
1829 ui.configsource(section, name, untrusted))
1824 ui.configsource(section, name, untrusted))
1830 fm.write('value', '%s\n', value)
1825 fm.write('value', '%s\n', value)
1831 fm.data(name=entryname)
1826 fm.data(name=entryname)
1832 matched = True
1827 matched = True
1833 else:
1828 else:
1834 fm.startitem()
1829 fm.startitem()
1835 fm.condwrite(ui.debugflag, 'source', '%s: ',
1830 fm.condwrite(ui.debugflag, 'source', '%s: ',
1836 ui.configsource(section, name, untrusted))
1831 ui.configsource(section, name, untrusted))
1837 fm.write('name value', '%s=%s\n', entryname, value)
1832 fm.write('name value', '%s=%s\n', entryname, value)
1838 matched = True
1833 matched = True
1839 fm.end()
1834 fm.end()
1840 if matched:
1835 if matched:
1841 return 0
1836 return 0
1842 return 1
1837 return 1
1843
1838
1844 @command('copy|cp',
1839 @command('copy|cp',
1845 [('A', 'after', None, _('record a copy that has already occurred')),
1840 [('A', 'after', None, _('record a copy that has already occurred')),
1846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1841 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1847 ] + walkopts + dryrunopts,
1842 ] + walkopts + dryrunopts,
1848 _('[OPTION]... [SOURCE]... DEST'))
1843 _('[OPTION]... [SOURCE]... DEST'))
1849 def copy(ui, repo, *pats, **opts):
1844 def copy(ui, repo, *pats, **opts):
1850 """mark files as copied for the next commit
1845 """mark files as copied for the next commit
1851
1846
1852 Mark dest as having copies of source files. If dest is a
1847 Mark dest as having copies of source files. If dest is a
1853 directory, copies are put in that directory. If dest is a file,
1848 directory, copies are put in that directory. If dest is a file,
1854 the source must be a single file.
1849 the source must be a single file.
1855
1850
1856 By default, this command copies the contents of files as they
1851 By default, this command copies the contents of files as they
1857 exist in the working directory. If invoked with -A/--after, the
1852 exist in the working directory. If invoked with -A/--after, the
1858 operation is recorded, but no copying is performed.
1853 operation is recorded, but no copying is performed.
1859
1854
1860 This command takes effect with the next commit. To undo a copy
1855 This command takes effect with the next commit. To undo a copy
1861 before that, see :hg:`revert`.
1856 before that, see :hg:`revert`.
1862
1857
1863 Returns 0 on success, 1 if errors are encountered.
1858 Returns 0 on success, 1 if errors are encountered.
1864 """
1859 """
1865 with repo.wlock(False):
1860 with repo.wlock(False):
1866 return cmdutil.copy(ui, repo, pats, opts)
1861 return cmdutil.copy(ui, repo, pats, opts)
1867
1862
1868 @command('debugdiscovery',
1869 [('', 'old', None, _('use old-style discovery')),
1870 ('', 'nonheads', None,
1871 _('use old-style discovery with non-heads included')),
1872 ] + remoteopts,
1873 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1874 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1875 """runs the changeset discovery protocol in isolation"""
1876 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1877 opts.get('branch'))
1878 remote = hg.peer(repo, opts, remoteurl)
1879 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1880
1881 # make sure tests are repeatable
1882 random.seed(12323)
1883
1884 def doit(localheads, remoteheads, remote=remote):
1885 if opts.get('old'):
1886 if localheads:
1887 raise error.Abort('cannot use localheads with old style '
1888 'discovery')
1889 if not util.safehasattr(remote, 'branches'):
1890 # enable in-client legacy support
1891 remote = localrepo.locallegacypeer(remote.local())
1892 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1893 force=True)
1894 common = set(common)
1895 if not opts.get('nonheads'):
1896 ui.write(("unpruned common: %s\n") %
1897 " ".join(sorted(short(n) for n in common)))
1898 dag = dagutil.revlogdag(repo.changelog)
1899 all = dag.ancestorset(dag.internalizeall(common))
1900 common = dag.externalizeall(dag.headsetofconnecteds(all))
1901 else:
1902 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1903 common = set(common)
1904 rheads = set(hds)
1905 lheads = set(repo.heads())
1906 ui.write(("common heads: %s\n") %
1907 " ".join(sorted(short(n) for n in common)))
1908 if lheads <= common:
1909 ui.write(("local is subset\n"))
1910 elif rheads <= common:
1911 ui.write(("remote is subset\n"))
1912
1913 serverlogs = opts.get('serverlog')
1914 if serverlogs:
1915 for filename in serverlogs:
1916 with open(filename, 'r') as logfile:
1917 line = logfile.readline()
1918 while line:
1919 parts = line.strip().split(';')
1920 op = parts[1]
1921 if op == 'cg':
1922 pass
1923 elif op == 'cgss':
1924 doit(parts[2].split(' '), parts[3].split(' '))
1925 elif op == 'unb':
1926 doit(parts[3].split(' '), parts[2].split(' '))
1927 line = logfile.readline()
1928 else:
1929 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1930 opts.get('remote_head'))
1931 localrevs = opts.get('local_head')
1932 doit(localrevs, remoterevs)
1933
1934 @command('debugextensions', formatteropts, [], norepo=True)
1863 @command('debugextensions', formatteropts, [], norepo=True)
1935 def debugextensions(ui, **opts):
1864 def debugextensions(ui, **opts):
1936 '''show information about active extensions'''
1865 '''show information about active extensions'''
1937 exts = extensions.extensions(ui)
1866 exts = extensions.extensions(ui)
1938 hgver = util.version()
1867 hgver = util.version()
1939 fm = ui.formatter('debugextensions', opts)
1868 fm = ui.formatter('debugextensions', opts)
1940 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1869 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1941 isinternal = extensions.ismoduleinternal(extmod)
1870 isinternal = extensions.ismoduleinternal(extmod)
1942 extsource = extmod.__file__
1871 extsource = extmod.__file__
1943 if isinternal:
1872 if isinternal:
1944 exttestedwith = [] # never expose magic string to users
1873 exttestedwith = [] # never expose magic string to users
1945 else:
1874 else:
1946 exttestedwith = getattr(extmod, 'testedwith', '').split()
1875 exttestedwith = getattr(extmod, 'testedwith', '').split()
1947 extbuglink = getattr(extmod, 'buglink', None)
1876 extbuglink = getattr(extmod, 'buglink', None)
1948
1877
1949 fm.startitem()
1878 fm.startitem()
1950
1879
1951 if ui.quiet or ui.verbose:
1880 if ui.quiet or ui.verbose:
1952 fm.write('name', '%s\n', extname)
1881 fm.write('name', '%s\n', extname)
1953 else:
1882 else:
1954 fm.write('name', '%s', extname)
1883 fm.write('name', '%s', extname)
1955 if isinternal or hgver in exttestedwith:
1884 if isinternal or hgver in exttestedwith:
1956 fm.plain('\n')
1885 fm.plain('\n')
1957 elif not exttestedwith:
1886 elif not exttestedwith:
1958 fm.plain(_(' (untested!)\n'))
1887 fm.plain(_(' (untested!)\n'))
1959 else:
1888 else:
1960 lasttestedversion = exttestedwith[-1]
1889 lasttestedversion = exttestedwith[-1]
1961 fm.plain(' (%s!)\n' % lasttestedversion)
1890 fm.plain(' (%s!)\n' % lasttestedversion)
1962
1891
1963 fm.condwrite(ui.verbose and extsource, 'source',
1892 fm.condwrite(ui.verbose and extsource, 'source',
1964 _(' location: %s\n'), extsource or "")
1893 _(' location: %s\n'), extsource or "")
1965
1894
1966 if ui.verbose:
1895 if ui.verbose:
1967 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
1896 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
1968 fm.data(bundled=isinternal)
1897 fm.data(bundled=isinternal)
1969
1898
1970 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
1899 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
1971 _(' tested with: %s\n'),
1900 _(' tested with: %s\n'),
1972 fm.formatlist(exttestedwith, name='ver'))
1901 fm.formatlist(exttestedwith, name='ver'))
1973
1902
1974 fm.condwrite(ui.verbose and extbuglink, 'buglink',
1903 fm.condwrite(ui.verbose and extbuglink, 'buglink',
1975 _(' bug reporting: %s\n'), extbuglink or "")
1904 _(' bug reporting: %s\n'), extbuglink or "")
1976
1905
1977 fm.end()
1906 fm.end()
1978
1907
1979 @command('debugfileset',
1908 @command('debugfileset',
1980 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1909 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1981 _('[-r REV] FILESPEC'))
1910 _('[-r REV] FILESPEC'))
1982 def debugfileset(ui, repo, expr, **opts):
1911 def debugfileset(ui, repo, expr, **opts):
1983 '''parse and apply a fileset specification'''
1912 '''parse and apply a fileset specification'''
1984 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1913 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1985 if ui.verbose:
1914 if ui.verbose:
1986 tree = fileset.parse(expr)
1915 tree = fileset.parse(expr)
1987 ui.note(fileset.prettyformat(tree), "\n")
1916 ui.note(fileset.prettyformat(tree), "\n")
1988
1917
1989 for f in ctx.getfileset(expr):
1918 for f in ctx.getfileset(expr):
1990 ui.write("%s\n" % f)
1919 ui.write("%s\n" % f)
1991
1920
1992 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1921 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1993 def debugfsinfo(ui, path="."):
1922 def debugfsinfo(ui, path="."):
1994 """show information detected about current filesystem"""
1923 """show information detected about current filesystem"""
1995 util.writefile('.debugfsinfo', '')
1924 util.writefile('.debugfsinfo', '')
1996 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1925 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1997 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1926 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1998 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1927 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1999 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
1928 ui.write(('case-sensitive: %s\n') % (util.fscasesensitive('.debugfsinfo')
2000 and 'yes' or 'no'))
1929 and 'yes' or 'no'))
2001 os.unlink('.debugfsinfo')
1930 os.unlink('.debugfsinfo')
2002
1931
2003 @command('debuggetbundle',
1932 @command('debuggetbundle',
2004 [('H', 'head', [], _('id of head node'), _('ID')),
1933 [('H', 'head', [], _('id of head node'), _('ID')),
2005 ('C', 'common', [], _('id of common node'), _('ID')),
1934 ('C', 'common', [], _('id of common node'), _('ID')),
2006 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1935 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2007 _('REPO FILE [-H|-C ID]...'),
1936 _('REPO FILE [-H|-C ID]...'),
2008 norepo=True)
1937 norepo=True)
2009 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1938 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2010 """retrieves a bundle from a repo
1939 """retrieves a bundle from a repo
2011
1940
2012 Every ID must be a full-length hex node id string. Saves the bundle to the
1941 Every ID must be a full-length hex node id string. Saves the bundle to the
2013 given file.
1942 given file.
2014 """
1943 """
2015 repo = hg.peer(ui, opts, repopath)
1944 repo = hg.peer(ui, opts, repopath)
2016 if not repo.capable('getbundle'):
1945 if not repo.capable('getbundle'):
2017 raise error.Abort("getbundle() not supported by target repository")
1946 raise error.Abort("getbundle() not supported by target repository")
2018 args = {}
1947 args = {}
2019 if common:
1948 if common:
2020 args['common'] = [bin(s) for s in common]
1949 args['common'] = [bin(s) for s in common]
2021 if head:
1950 if head:
2022 args['heads'] = [bin(s) for s in head]
1951 args['heads'] = [bin(s) for s in head]
2023 # TODO: get desired bundlecaps from command line.
1952 # TODO: get desired bundlecaps from command line.
2024 args['bundlecaps'] = None
1953 args['bundlecaps'] = None
2025 bundle = repo.getbundle('debug', **args)
1954 bundle = repo.getbundle('debug', **args)
2026
1955
2027 bundletype = opts.get('type', 'bzip2').lower()
1956 bundletype = opts.get('type', 'bzip2').lower()
2028 btypes = {'none': 'HG10UN',
1957 btypes = {'none': 'HG10UN',
2029 'bzip2': 'HG10BZ',
1958 'bzip2': 'HG10BZ',
2030 'gzip': 'HG10GZ',
1959 'gzip': 'HG10GZ',
2031 'bundle2': 'HG20'}
1960 'bundle2': 'HG20'}
2032 bundletype = btypes.get(bundletype)
1961 bundletype = btypes.get(bundletype)
2033 if bundletype not in bundle2.bundletypes:
1962 if bundletype not in bundle2.bundletypes:
2034 raise error.Abort(_('unknown bundle type specified with --type'))
1963 raise error.Abort(_('unknown bundle type specified with --type'))
2035 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1964 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
2036
1965
2037 @command('debugignore', [], '[FILE]')
1966 @command('debugignore', [], '[FILE]')
2038 def debugignore(ui, repo, *files, **opts):
1967 def debugignore(ui, repo, *files, **opts):
2039 """display the combined ignore pattern and information about ignored files
1968 """display the combined ignore pattern and information about ignored files
2040
1969
2041 With no argument display the combined ignore pattern.
1970 With no argument display the combined ignore pattern.
2042
1971
2043 Given space separated file names, shows if the given file is ignored and
1972 Given space separated file names, shows if the given file is ignored and
2044 if so, show the ignore rule (file and line number) that matched it.
1973 if so, show the ignore rule (file and line number) that matched it.
2045 """
1974 """
2046 ignore = repo.dirstate._ignore
1975 ignore = repo.dirstate._ignore
2047 if not files:
1976 if not files:
2048 # Show all the patterns
1977 # Show all the patterns
2049 includepat = getattr(ignore, 'includepat', None)
1978 includepat = getattr(ignore, 'includepat', None)
2050 if includepat is not None:
1979 if includepat is not None:
2051 ui.write("%s\n" % includepat)
1980 ui.write("%s\n" % includepat)
2052 else:
1981 else:
2053 raise error.Abort(_("no ignore patterns found"))
1982 raise error.Abort(_("no ignore patterns found"))
2054 else:
1983 else:
2055 for f in files:
1984 for f in files:
2056 nf = util.normpath(f)
1985 nf = util.normpath(f)
2057 ignored = None
1986 ignored = None
2058 ignoredata = None
1987 ignoredata = None
2059 if nf != '.':
1988 if nf != '.':
2060 if ignore(nf):
1989 if ignore(nf):
2061 ignored = nf
1990 ignored = nf
2062 ignoredata = repo.dirstate._ignorefileandline(nf)
1991 ignoredata = repo.dirstate._ignorefileandline(nf)
2063 else:
1992 else:
2064 for p in util.finddirs(nf):
1993 for p in util.finddirs(nf):
2065 if ignore(p):
1994 if ignore(p):
2066 ignored = p
1995 ignored = p
2067 ignoredata = repo.dirstate._ignorefileandline(p)
1996 ignoredata = repo.dirstate._ignorefileandline(p)
2068 break
1997 break
2069 if ignored:
1998 if ignored:
2070 if ignored == nf:
1999 if ignored == nf:
2071 ui.write(_("%s is ignored\n") % f)
2000 ui.write(_("%s is ignored\n") % f)
2072 else:
2001 else:
2073 ui.write(_("%s is ignored because of "
2002 ui.write(_("%s is ignored because of "
2074 "containing folder %s\n")
2003 "containing folder %s\n")
2075 % (f, ignored))
2004 % (f, ignored))
2076 ignorefile, lineno, line = ignoredata
2005 ignorefile, lineno, line = ignoredata
2077 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2006 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
2078 % (ignorefile, lineno, line))
2007 % (ignorefile, lineno, line))
2079 else:
2008 else:
2080 ui.write(_("%s is not ignored\n") % f)
2009 ui.write(_("%s is not ignored\n") % f)
2081
2010
2082 @command('debugindex', debugrevlogopts +
2011 @command('debugindex', debugrevlogopts +
2083 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2012 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2084 _('[-f FORMAT] -c|-m|FILE'),
2013 _('[-f FORMAT] -c|-m|FILE'),
2085 optionalrepo=True)
2014 optionalrepo=True)
2086 def debugindex(ui, repo, file_=None, **opts):
2015 def debugindex(ui, repo, file_=None, **opts):
2087 """dump the contents of an index file"""
2016 """dump the contents of an index file"""
2088 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2017 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2089 format = opts.get('format', 0)
2018 format = opts.get('format', 0)
2090 if format not in (0, 1):
2019 if format not in (0, 1):
2091 raise error.Abort(_("unknown format %d") % format)
2020 raise error.Abort(_("unknown format %d") % format)
2092
2021
2093 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2022 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2094 if generaldelta:
2023 if generaldelta:
2095 basehdr = ' delta'
2024 basehdr = ' delta'
2096 else:
2025 else:
2097 basehdr = ' base'
2026 basehdr = ' base'
2098
2027
2099 if ui.debugflag:
2028 if ui.debugflag:
2100 shortfn = hex
2029 shortfn = hex
2101 else:
2030 else:
2102 shortfn = short
2031 shortfn = short
2103
2032
2104 # There might not be anything in r, so have a sane default
2033 # There might not be anything in r, so have a sane default
2105 idlen = 12
2034 idlen = 12
2106 for i in r:
2035 for i in r:
2107 idlen = len(shortfn(r.node(i)))
2036 idlen = len(shortfn(r.node(i)))
2108 break
2037 break
2109
2038
2110 if format == 0:
2039 if format == 0:
2111 ui.write((" rev offset length " + basehdr + " linkrev"
2040 ui.write((" rev offset length " + basehdr + " linkrev"
2112 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2041 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2113 elif format == 1:
2042 elif format == 1:
2114 ui.write((" rev flag offset length"
2043 ui.write((" rev flag offset length"
2115 " size " + basehdr + " link p1 p2"
2044 " size " + basehdr + " link p1 p2"
2116 " %s\n") % "nodeid".rjust(idlen))
2045 " %s\n") % "nodeid".rjust(idlen))
2117
2046
2118 for i in r:
2047 for i in r:
2119 node = r.node(i)
2048 node = r.node(i)
2120 if generaldelta:
2049 if generaldelta:
2121 base = r.deltaparent(i)
2050 base = r.deltaparent(i)
2122 else:
2051 else:
2123 base = r.chainbase(i)
2052 base = r.chainbase(i)
2124 if format == 0:
2053 if format == 0:
2125 try:
2054 try:
2126 pp = r.parents(node)
2055 pp = r.parents(node)
2127 except Exception:
2056 except Exception:
2128 pp = [nullid, nullid]
2057 pp = [nullid, nullid]
2129 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2058 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2130 i, r.start(i), r.length(i), base, r.linkrev(i),
2059 i, r.start(i), r.length(i), base, r.linkrev(i),
2131 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2060 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2132 elif format == 1:
2061 elif format == 1:
2133 pr = r.parentrevs(i)
2062 pr = r.parentrevs(i)
2134 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2063 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2135 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2064 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2136 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2065 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2137
2066
2138 @command('debugindexdot', debugrevlogopts,
2067 @command('debugindexdot', debugrevlogopts,
2139 _('-c|-m|FILE'), optionalrepo=True)
2068 _('-c|-m|FILE'), optionalrepo=True)
2140 def debugindexdot(ui, repo, file_=None, **opts):
2069 def debugindexdot(ui, repo, file_=None, **opts):
2141 """dump an index DAG as a graphviz dot file"""
2070 """dump an index DAG as a graphviz dot file"""
2142 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2071 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2143 ui.write(("digraph G {\n"))
2072 ui.write(("digraph G {\n"))
2144 for i in r:
2073 for i in r:
2145 node = r.node(i)
2074 node = r.node(i)
2146 pp = r.parents(node)
2075 pp = r.parents(node)
2147 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2076 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2148 if pp[1] != nullid:
2077 if pp[1] != nullid:
2149 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2078 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2150 ui.write("}\n")
2079 ui.write("}\n")
2151
2080
2152 @command('debugdeltachain',
2081 @command('debugdeltachain',
2153 debugrevlogopts + formatteropts,
2082 debugrevlogopts + formatteropts,
2154 _('-c|-m|FILE'),
2083 _('-c|-m|FILE'),
2155 optionalrepo=True)
2084 optionalrepo=True)
2156 def debugdeltachain(ui, repo, file_=None, **opts):
2085 def debugdeltachain(ui, repo, file_=None, **opts):
2157 """dump information about delta chains in a revlog
2086 """dump information about delta chains in a revlog
2158
2087
2159 Output can be templatized. Available template keywords are:
2088 Output can be templatized. Available template keywords are:
2160
2089
2161 :``rev``: revision number
2090 :``rev``: revision number
2162 :``chainid``: delta chain identifier (numbered by unique base)
2091 :``chainid``: delta chain identifier (numbered by unique base)
2163 :``chainlen``: delta chain length to this revision
2092 :``chainlen``: delta chain length to this revision
2164 :``prevrev``: previous revision in delta chain
2093 :``prevrev``: previous revision in delta chain
2165 :``deltatype``: role of delta / how it was computed
2094 :``deltatype``: role of delta / how it was computed
2166 :``compsize``: compressed size of revision
2095 :``compsize``: compressed size of revision
2167 :``uncompsize``: uncompressed size of revision
2096 :``uncompsize``: uncompressed size of revision
2168 :``chainsize``: total size of compressed revisions in chain
2097 :``chainsize``: total size of compressed revisions in chain
2169 :``chainratio``: total chain size divided by uncompressed revision size
2098 :``chainratio``: total chain size divided by uncompressed revision size
2170 (new delta chains typically start at ratio 2.00)
2099 (new delta chains typically start at ratio 2.00)
2171 :``lindist``: linear distance from base revision in delta chain to end
2100 :``lindist``: linear distance from base revision in delta chain to end
2172 of this revision
2101 of this revision
2173 :``extradist``: total size of revisions not part of this delta chain from
2102 :``extradist``: total size of revisions not part of this delta chain from
2174 base of delta chain to end of this revision; a measurement
2103 base of delta chain to end of this revision; a measurement
2175 of how much extra data we need to read/seek across to read
2104 of how much extra data we need to read/seek across to read
2176 the delta chain for this revision
2105 the delta chain for this revision
2177 :``extraratio``: extradist divided by chainsize; another representation of
2106 :``extraratio``: extradist divided by chainsize; another representation of
2178 how much unrelated data is needed to load this delta chain
2107 how much unrelated data is needed to load this delta chain
2179 """
2108 """
2180 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2109 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2181 index = r.index
2110 index = r.index
2182 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2111 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2183
2112
2184 def revinfo(rev):
2113 def revinfo(rev):
2185 e = index[rev]
2114 e = index[rev]
2186 compsize = e[1]
2115 compsize = e[1]
2187 uncompsize = e[2]
2116 uncompsize = e[2]
2188 chainsize = 0
2117 chainsize = 0
2189
2118
2190 if generaldelta:
2119 if generaldelta:
2191 if e[3] == e[5]:
2120 if e[3] == e[5]:
2192 deltatype = 'p1'
2121 deltatype = 'p1'
2193 elif e[3] == e[6]:
2122 elif e[3] == e[6]:
2194 deltatype = 'p2'
2123 deltatype = 'p2'
2195 elif e[3] == rev - 1:
2124 elif e[3] == rev - 1:
2196 deltatype = 'prev'
2125 deltatype = 'prev'
2197 elif e[3] == rev:
2126 elif e[3] == rev:
2198 deltatype = 'base'
2127 deltatype = 'base'
2199 else:
2128 else:
2200 deltatype = 'other'
2129 deltatype = 'other'
2201 else:
2130 else:
2202 if e[3] == rev:
2131 if e[3] == rev:
2203 deltatype = 'base'
2132 deltatype = 'base'
2204 else:
2133 else:
2205 deltatype = 'prev'
2134 deltatype = 'prev'
2206
2135
2207 chain = r._deltachain(rev)[0]
2136 chain = r._deltachain(rev)[0]
2208 for iterrev in chain:
2137 for iterrev in chain:
2209 e = index[iterrev]
2138 e = index[iterrev]
2210 chainsize += e[1]
2139 chainsize += e[1]
2211
2140
2212 return compsize, uncompsize, deltatype, chain, chainsize
2141 return compsize, uncompsize, deltatype, chain, chainsize
2213
2142
2214 fm = ui.formatter('debugdeltachain', opts)
2143 fm = ui.formatter('debugdeltachain', opts)
2215
2144
2216 fm.plain(' rev chain# chainlen prev delta '
2145 fm.plain(' rev chain# chainlen prev delta '
2217 'size rawsize chainsize ratio lindist extradist '
2146 'size rawsize chainsize ratio lindist extradist '
2218 'extraratio\n')
2147 'extraratio\n')
2219
2148
2220 chainbases = {}
2149 chainbases = {}
2221 for rev in r:
2150 for rev in r:
2222 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2151 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2223 chainbase = chain[0]
2152 chainbase = chain[0]
2224 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2153 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2225 basestart = r.start(chainbase)
2154 basestart = r.start(chainbase)
2226 revstart = r.start(rev)
2155 revstart = r.start(rev)
2227 lineardist = revstart + comp - basestart
2156 lineardist = revstart + comp - basestart
2228 extradist = lineardist - chainsize
2157 extradist = lineardist - chainsize
2229 try:
2158 try:
2230 prevrev = chain[-2]
2159 prevrev = chain[-2]
2231 except IndexError:
2160 except IndexError:
2232 prevrev = -1
2161 prevrev = -1
2233
2162
2234 chainratio = float(chainsize) / float(uncomp)
2163 chainratio = float(chainsize) / float(uncomp)
2235 extraratio = float(extradist) / float(chainsize)
2164 extraratio = float(extradist) / float(chainsize)
2236
2165
2237 fm.startitem()
2166 fm.startitem()
2238 fm.write('rev chainid chainlen prevrev deltatype compsize '
2167 fm.write('rev chainid chainlen prevrev deltatype compsize '
2239 'uncompsize chainsize chainratio lindist extradist '
2168 'uncompsize chainsize chainratio lindist extradist '
2240 'extraratio',
2169 'extraratio',
2241 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2170 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2242 rev, chainid, len(chain), prevrev, deltatype, comp,
2171 rev, chainid, len(chain), prevrev, deltatype, comp,
2243 uncomp, chainsize, chainratio, lineardist, extradist,
2172 uncomp, chainsize, chainratio, lineardist, extradist,
2244 extraratio,
2173 extraratio,
2245 rev=rev, chainid=chainid, chainlen=len(chain),
2174 rev=rev, chainid=chainid, chainlen=len(chain),
2246 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2175 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2247 uncompsize=uncomp, chainsize=chainsize,
2176 uncompsize=uncomp, chainsize=chainsize,
2248 chainratio=chainratio, lindist=lineardist,
2177 chainratio=chainratio, lindist=lineardist,
2249 extradist=extradist, extraratio=extraratio)
2178 extradist=extradist, extraratio=extraratio)
2250
2179
2251 fm.end()
2180 fm.end()
2252
2181
2253 @command('debuginstall', [] + formatteropts, '', norepo=True)
2182 @command('debuginstall', [] + formatteropts, '', norepo=True)
2254 def debuginstall(ui, **opts):
2183 def debuginstall(ui, **opts):
2255 '''test Mercurial installation
2184 '''test Mercurial installation
2256
2185
2257 Returns 0 on success.
2186 Returns 0 on success.
2258 '''
2187 '''
2259
2188
2260 def writetemp(contents):
2189 def writetemp(contents):
2261 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2190 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2262 f = os.fdopen(fd, "wb")
2191 f = os.fdopen(fd, "wb")
2263 f.write(contents)
2192 f.write(contents)
2264 f.close()
2193 f.close()
2265 return name
2194 return name
2266
2195
2267 problems = 0
2196 problems = 0
2268
2197
2269 fm = ui.formatter('debuginstall', opts)
2198 fm = ui.formatter('debuginstall', opts)
2270 fm.startitem()
2199 fm.startitem()
2271
2200
2272 # encoding
2201 # encoding
2273 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2202 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
2274 err = None
2203 err = None
2275 try:
2204 try:
2276 encoding.fromlocal("test")
2205 encoding.fromlocal("test")
2277 except error.Abort as inst:
2206 except error.Abort as inst:
2278 err = inst
2207 err = inst
2279 problems += 1
2208 problems += 1
2280 fm.condwrite(err, 'encodingerror', _(" %s\n"
2209 fm.condwrite(err, 'encodingerror', _(" %s\n"
2281 " (check that your locale is properly set)\n"), err)
2210 " (check that your locale is properly set)\n"), err)
2282
2211
2283 # Python
2212 # Python
2284 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2213 fm.write('pythonexe', _("checking Python executable (%s)\n"),
2285 sys.executable)
2214 sys.executable)
2286 fm.write('pythonver', _("checking Python version (%s)\n"),
2215 fm.write('pythonver', _("checking Python version (%s)\n"),
2287 ("%s.%s.%s" % sys.version_info[:3]))
2216 ("%s.%s.%s" % sys.version_info[:3]))
2288 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2217 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
2289 os.path.dirname(os.__file__))
2218 os.path.dirname(os.__file__))
2290
2219
2291 security = set(sslutil.supportedprotocols)
2220 security = set(sslutil.supportedprotocols)
2292 if sslutil.hassni:
2221 if sslutil.hassni:
2293 security.add('sni')
2222 security.add('sni')
2294
2223
2295 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
2224 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
2296 fm.formatlist(sorted(security), name='protocol',
2225 fm.formatlist(sorted(security), name='protocol',
2297 fmt='%s', sep=','))
2226 fmt='%s', sep=','))
2298
2227
2299 # These are warnings, not errors. So don't increment problem count. This
2228 # These are warnings, not errors. So don't increment problem count. This
2300 # may change in the future.
2229 # may change in the future.
2301 if 'tls1.2' not in security:
2230 if 'tls1.2' not in security:
2302 fm.plain(_(' TLS 1.2 not supported by Python install; '
2231 fm.plain(_(' TLS 1.2 not supported by Python install; '
2303 'network connections lack modern security\n'))
2232 'network connections lack modern security\n'))
2304 if 'sni' not in security:
2233 if 'sni' not in security:
2305 fm.plain(_(' SNI not supported by Python install; may have '
2234 fm.plain(_(' SNI not supported by Python install; may have '
2306 'connectivity issues with some servers\n'))
2235 'connectivity issues with some servers\n'))
2307
2236
2308 # TODO print CA cert info
2237 # TODO print CA cert info
2309
2238
2310 # hg version
2239 # hg version
2311 hgver = util.version()
2240 hgver = util.version()
2312 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2241 fm.write('hgver', _("checking Mercurial version (%s)\n"),
2313 hgver.split('+')[0])
2242 hgver.split('+')[0])
2314 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2243 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
2315 '+'.join(hgver.split('+')[1:]))
2244 '+'.join(hgver.split('+')[1:]))
2316
2245
2317 # compiled modules
2246 # compiled modules
2318 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2247 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
2319 policy.policy)
2248 policy.policy)
2320 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2249 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
2321 os.path.dirname(__file__))
2250 os.path.dirname(__file__))
2322
2251
2323 err = None
2252 err = None
2324 try:
2253 try:
2325 from . import (
2254 from . import (
2326 base85,
2255 base85,
2327 bdiff,
2256 bdiff,
2328 mpatch,
2257 mpatch,
2329 osutil,
2258 osutil,
2330 )
2259 )
2331 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2260 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2332 except Exception as inst:
2261 except Exception as inst:
2333 err = inst
2262 err = inst
2334 problems += 1
2263 problems += 1
2335 fm.condwrite(err, 'extensionserror', " %s\n", err)
2264 fm.condwrite(err, 'extensionserror', " %s\n", err)
2336
2265
2337 compengines = util.compengines._engines.values()
2266 compengines = util.compengines._engines.values()
2338 fm.write('compengines', _('checking registered compression engines (%s)\n'),
2267 fm.write('compengines', _('checking registered compression engines (%s)\n'),
2339 fm.formatlist(sorted(e.name() for e in compengines),
2268 fm.formatlist(sorted(e.name() for e in compengines),
2340 name='compengine', fmt='%s', sep=', '))
2269 name='compengine', fmt='%s', sep=', '))
2341 fm.write('compenginesavail', _('checking available compression engines '
2270 fm.write('compenginesavail', _('checking available compression engines '
2342 '(%s)\n'),
2271 '(%s)\n'),
2343 fm.formatlist(sorted(e.name() for e in compengines
2272 fm.formatlist(sorted(e.name() for e in compengines
2344 if e.available()),
2273 if e.available()),
2345 name='compengine', fmt='%s', sep=', '))
2274 name='compengine', fmt='%s', sep=', '))
2346
2275
2347 # templates
2276 # templates
2348 p = templater.templatepaths()
2277 p = templater.templatepaths()
2349 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2278 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
2350 fm.condwrite(not p, '', _(" no template directories found\n"))
2279 fm.condwrite(not p, '', _(" no template directories found\n"))
2351 if p:
2280 if p:
2352 m = templater.templatepath("map-cmdline.default")
2281 m = templater.templatepath("map-cmdline.default")
2353 if m:
2282 if m:
2354 # template found, check if it is working
2283 # template found, check if it is working
2355 err = None
2284 err = None
2356 try:
2285 try:
2357 templater.templater.frommapfile(m)
2286 templater.templater.frommapfile(m)
2358 except Exception as inst:
2287 except Exception as inst:
2359 err = inst
2288 err = inst
2360 p = None
2289 p = None
2361 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2290 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
2362 else:
2291 else:
2363 p = None
2292 p = None
2364 fm.condwrite(p, 'defaulttemplate',
2293 fm.condwrite(p, 'defaulttemplate',
2365 _("checking default template (%s)\n"), m)
2294 _("checking default template (%s)\n"), m)
2366 fm.condwrite(not m, 'defaulttemplatenotfound',
2295 fm.condwrite(not m, 'defaulttemplatenotfound',
2367 _(" template '%s' not found\n"), "default")
2296 _(" template '%s' not found\n"), "default")
2368 if not p:
2297 if not p:
2369 problems += 1
2298 problems += 1
2370 fm.condwrite(not p, '',
2299 fm.condwrite(not p, '',
2371 _(" (templates seem to have been installed incorrectly)\n"))
2300 _(" (templates seem to have been installed incorrectly)\n"))
2372
2301
2373 # editor
2302 # editor
2374 editor = ui.geteditor()
2303 editor = ui.geteditor()
2375 editor = util.expandpath(editor)
2304 editor = util.expandpath(editor)
2376 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2305 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
2377 cmdpath = util.findexe(shlex.split(editor)[0])
2306 cmdpath = util.findexe(shlex.split(editor)[0])
2378 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2307 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
2379 _(" No commit editor set and can't find %s in PATH\n"
2308 _(" No commit editor set and can't find %s in PATH\n"
2380 " (specify a commit editor in your configuration"
2309 " (specify a commit editor in your configuration"
2381 " file)\n"), not cmdpath and editor == 'vi' and editor)
2310 " file)\n"), not cmdpath and editor == 'vi' and editor)
2382 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2311 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
2383 _(" Can't find editor '%s' in PATH\n"
2312 _(" Can't find editor '%s' in PATH\n"
2384 " (specify a commit editor in your configuration"
2313 " (specify a commit editor in your configuration"
2385 " file)\n"), not cmdpath and editor)
2314 " file)\n"), not cmdpath and editor)
2386 if not cmdpath and editor != 'vi':
2315 if not cmdpath and editor != 'vi':
2387 problems += 1
2316 problems += 1
2388
2317
2389 # check username
2318 # check username
2390 username = None
2319 username = None
2391 err = None
2320 err = None
2392 try:
2321 try:
2393 username = ui.username()
2322 username = ui.username()
2394 except error.Abort as e:
2323 except error.Abort as e:
2395 err = e
2324 err = e
2396 problems += 1
2325 problems += 1
2397
2326
2398 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2327 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
2399 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2328 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
2400 " (specify a username in your configuration file)\n"), err)
2329 " (specify a username in your configuration file)\n"), err)
2401
2330
2402 fm.condwrite(not problems, '',
2331 fm.condwrite(not problems, '',
2403 _("no problems detected\n"))
2332 _("no problems detected\n"))
2404 if not problems:
2333 if not problems:
2405 fm.data(problems=problems)
2334 fm.data(problems=problems)
2406 fm.condwrite(problems, 'problems',
2335 fm.condwrite(problems, 'problems',
2407 _("%d problems detected,"
2336 _("%d problems detected,"
2408 " please check your install!\n"), problems)
2337 " please check your install!\n"), problems)
2409 fm.end()
2338 fm.end()
2410
2339
2411 return problems
2340 return problems
2412
2341
2413 @command('debugknown', [], _('REPO ID...'), norepo=True)
2342 @command('debugknown', [], _('REPO ID...'), norepo=True)
2414 def debugknown(ui, repopath, *ids, **opts):
2343 def debugknown(ui, repopath, *ids, **opts):
2415 """test whether node ids are known to a repo
2344 """test whether node ids are known to a repo
2416
2345
2417 Every ID must be a full-length hex node id string. Returns a list of 0s
2346 Every ID must be a full-length hex node id string. Returns a list of 0s
2418 and 1s indicating unknown/known.
2347 and 1s indicating unknown/known.
2419 """
2348 """
2420 repo = hg.peer(ui, opts, repopath)
2349 repo = hg.peer(ui, opts, repopath)
2421 if not repo.capable('known'):
2350 if not repo.capable('known'):
2422 raise error.Abort("known() not supported by target repository")
2351 raise error.Abort("known() not supported by target repository")
2423 flags = repo.known([bin(s) for s in ids])
2352 flags = repo.known([bin(s) for s in ids])
2424 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2353 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2425
2354
2426 @command('debuglabelcomplete', [], _('LABEL...'))
2355 @command('debuglabelcomplete', [], _('LABEL...'))
2427 def debuglabelcomplete(ui, repo, *args):
2356 def debuglabelcomplete(ui, repo, *args):
2428 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2357 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2429 debugnamecomplete(ui, repo, *args)
2358 debugnamecomplete(ui, repo, *args)
2430
2359
2431 @command('debugmergestate', [], '')
2360 @command('debugmergestate', [], '')
2432 def debugmergestate(ui, repo, *args):
2361 def debugmergestate(ui, repo, *args):
2433 """print merge state
2362 """print merge state
2434
2363
2435 Use --verbose to print out information about whether v1 or v2 merge state
2364 Use --verbose to print out information about whether v1 or v2 merge state
2436 was chosen."""
2365 was chosen."""
2437 def _hashornull(h):
2366 def _hashornull(h):
2438 if h == nullhex:
2367 if h == nullhex:
2439 return 'null'
2368 return 'null'
2440 else:
2369 else:
2441 return h
2370 return h
2442
2371
2443 def printrecords(version):
2372 def printrecords(version):
2444 ui.write(('* version %s records\n') % version)
2373 ui.write(('* version %s records\n') % version)
2445 if version == 1:
2374 if version == 1:
2446 records = v1records
2375 records = v1records
2447 else:
2376 else:
2448 records = v2records
2377 records = v2records
2449
2378
2450 for rtype, record in records:
2379 for rtype, record in records:
2451 # pretty print some record types
2380 # pretty print some record types
2452 if rtype == 'L':
2381 if rtype == 'L':
2453 ui.write(('local: %s\n') % record)
2382 ui.write(('local: %s\n') % record)
2454 elif rtype == 'O':
2383 elif rtype == 'O':
2455 ui.write(('other: %s\n') % record)
2384 ui.write(('other: %s\n') % record)
2456 elif rtype == 'm':
2385 elif rtype == 'm':
2457 driver, mdstate = record.split('\0', 1)
2386 driver, mdstate = record.split('\0', 1)
2458 ui.write(('merge driver: %s (state "%s")\n')
2387 ui.write(('merge driver: %s (state "%s")\n')
2459 % (driver, mdstate))
2388 % (driver, mdstate))
2460 elif rtype in 'FDC':
2389 elif rtype in 'FDC':
2461 r = record.split('\0')
2390 r = record.split('\0')
2462 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2391 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2463 if version == 1:
2392 if version == 1:
2464 onode = 'not stored in v1 format'
2393 onode = 'not stored in v1 format'
2465 flags = r[7]
2394 flags = r[7]
2466 else:
2395 else:
2467 onode, flags = r[7:9]
2396 onode, flags = r[7:9]
2468 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2397 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2469 % (f, rtype, state, _hashornull(hash)))
2398 % (f, rtype, state, _hashornull(hash)))
2470 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2399 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2471 ui.write((' ancestor path: %s (node %s)\n')
2400 ui.write((' ancestor path: %s (node %s)\n')
2472 % (afile, _hashornull(anode)))
2401 % (afile, _hashornull(anode)))
2473 ui.write((' other path: %s (node %s)\n')
2402 ui.write((' other path: %s (node %s)\n')
2474 % (ofile, _hashornull(onode)))
2403 % (ofile, _hashornull(onode)))
2475 elif rtype == 'f':
2404 elif rtype == 'f':
2476 filename, rawextras = record.split('\0', 1)
2405 filename, rawextras = record.split('\0', 1)
2477 extras = rawextras.split('\0')
2406 extras = rawextras.split('\0')
2478 i = 0
2407 i = 0
2479 extrastrings = []
2408 extrastrings = []
2480 while i < len(extras):
2409 while i < len(extras):
2481 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2410 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
2482 i += 2
2411 i += 2
2483
2412
2484 ui.write(('file extras: %s (%s)\n')
2413 ui.write(('file extras: %s (%s)\n')
2485 % (filename, ', '.join(extrastrings)))
2414 % (filename, ', '.join(extrastrings)))
2486 elif rtype == 'l':
2415 elif rtype == 'l':
2487 labels = record.split('\0', 2)
2416 labels = record.split('\0', 2)
2488 labels = [l for l in labels if len(l) > 0]
2417 labels = [l for l in labels if len(l) > 0]
2489 ui.write(('labels:\n'))
2418 ui.write(('labels:\n'))
2490 ui.write((' local: %s\n' % labels[0]))
2419 ui.write((' local: %s\n' % labels[0]))
2491 ui.write((' other: %s\n' % labels[1]))
2420 ui.write((' other: %s\n' % labels[1]))
2492 if len(labels) > 2:
2421 if len(labels) > 2:
2493 ui.write((' base: %s\n' % labels[2]))
2422 ui.write((' base: %s\n' % labels[2]))
2494 else:
2423 else:
2495 ui.write(('unrecognized entry: %s\t%s\n')
2424 ui.write(('unrecognized entry: %s\t%s\n')
2496 % (rtype, record.replace('\0', '\t')))
2425 % (rtype, record.replace('\0', '\t')))
2497
2426
2498 # Avoid mergestate.read() since it may raise an exception for unsupported
2427 # Avoid mergestate.read() since it may raise an exception for unsupported
2499 # merge state records. We shouldn't be doing this, but this is OK since this
2428 # merge state records. We shouldn't be doing this, but this is OK since this
2500 # command is pretty low-level.
2429 # command is pretty low-level.
2501 ms = mergemod.mergestate(repo)
2430 ms = mergemod.mergestate(repo)
2502
2431
2503 # sort so that reasonable information is on top
2432 # sort so that reasonable information is on top
2504 v1records = ms._readrecordsv1()
2433 v1records = ms._readrecordsv1()
2505 v2records = ms._readrecordsv2()
2434 v2records = ms._readrecordsv2()
2506 order = 'LOml'
2435 order = 'LOml'
2507 def key(r):
2436 def key(r):
2508 idx = order.find(r[0])
2437 idx = order.find(r[0])
2509 if idx == -1:
2438 if idx == -1:
2510 return (1, r[1])
2439 return (1, r[1])
2511 else:
2440 else:
2512 return (0, idx)
2441 return (0, idx)
2513 v1records.sort(key=key)
2442 v1records.sort(key=key)
2514 v2records.sort(key=key)
2443 v2records.sort(key=key)
2515
2444
2516 if not v1records and not v2records:
2445 if not v1records and not v2records:
2517 ui.write(('no merge state found\n'))
2446 ui.write(('no merge state found\n'))
2518 elif not v2records:
2447 elif not v2records:
2519 ui.note(('no version 2 merge state\n'))
2448 ui.note(('no version 2 merge state\n'))
2520 printrecords(1)
2449 printrecords(1)
2521 elif ms._v1v2match(v1records, v2records):
2450 elif ms._v1v2match(v1records, v2records):
2522 ui.note(('v1 and v2 states match: using v2\n'))
2451 ui.note(('v1 and v2 states match: using v2\n'))
2523 printrecords(2)
2452 printrecords(2)
2524 else:
2453 else:
2525 ui.note(('v1 and v2 states mismatch: using v1\n'))
2454 ui.note(('v1 and v2 states mismatch: using v1\n'))
2526 printrecords(1)
2455 printrecords(1)
2527 if ui.verbose:
2456 if ui.verbose:
2528 printrecords(2)
2457 printrecords(2)
2529
2458
2530 @command('debugnamecomplete', [], _('NAME...'))
2459 @command('debugnamecomplete', [], _('NAME...'))
2531 def debugnamecomplete(ui, repo, *args):
2460 def debugnamecomplete(ui, repo, *args):
2532 '''complete "names" - tags, open branch names, bookmark names'''
2461 '''complete "names" - tags, open branch names, bookmark names'''
2533
2462
2534 names = set()
2463 names = set()
2535 # since we previously only listed open branches, we will handle that
2464 # since we previously only listed open branches, we will handle that
2536 # specially (after this for loop)
2465 # specially (after this for loop)
2537 for name, ns in repo.names.iteritems():
2466 for name, ns in repo.names.iteritems():
2538 if name != 'branches':
2467 if name != 'branches':
2539 names.update(ns.listnames(repo))
2468 names.update(ns.listnames(repo))
2540 names.update(tag for (tag, heads, tip, closed)
2469 names.update(tag for (tag, heads, tip, closed)
2541 in repo.branchmap().iterbranches() if not closed)
2470 in repo.branchmap().iterbranches() if not closed)
2542 completions = set()
2471 completions = set()
2543 if not args:
2472 if not args:
2544 args = ['']
2473 args = ['']
2545 for a in args:
2474 for a in args:
2546 completions.update(n for n in names if n.startswith(a))
2475 completions.update(n for n in names if n.startswith(a))
2547 ui.write('\n'.join(sorted(completions)))
2476 ui.write('\n'.join(sorted(completions)))
2548 ui.write('\n')
2477 ui.write('\n')
2549
2478
2550 @command('debuglocks',
2479 @command('debuglocks',
2551 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2480 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2552 ('W', 'force-wlock', None,
2481 ('W', 'force-wlock', None,
2553 _('free the working state lock (DANGEROUS)'))],
2482 _('free the working state lock (DANGEROUS)'))],
2554 _('[OPTION]...'))
2483 _('[OPTION]...'))
2555 def debuglocks(ui, repo, **opts):
2484 def debuglocks(ui, repo, **opts):
2556 """show or modify state of locks
2485 """show or modify state of locks
2557
2486
2558 By default, this command will show which locks are held. This
2487 By default, this command will show which locks are held. This
2559 includes the user and process holding the lock, the amount of time
2488 includes the user and process holding the lock, the amount of time
2560 the lock has been held, and the machine name where the process is
2489 the lock has been held, and the machine name where the process is
2561 running if it's not local.
2490 running if it's not local.
2562
2491
2563 Locks protect the integrity of Mercurial's data, so should be
2492 Locks protect the integrity of Mercurial's data, so should be
2564 treated with care. System crashes or other interruptions may cause
2493 treated with care. System crashes or other interruptions may cause
2565 locks to not be properly released, though Mercurial will usually
2494 locks to not be properly released, though Mercurial will usually
2566 detect and remove such stale locks automatically.
2495 detect and remove such stale locks automatically.
2567
2496
2568 However, detecting stale locks may not always be possible (for
2497 However, detecting stale locks may not always be possible (for
2569 instance, on a shared filesystem). Removing locks may also be
2498 instance, on a shared filesystem). Removing locks may also be
2570 blocked by filesystem permissions.
2499 blocked by filesystem permissions.
2571
2500
2572 Returns 0 if no locks are held.
2501 Returns 0 if no locks are held.
2573
2502
2574 """
2503 """
2575
2504
2576 if opts.get('force_lock'):
2505 if opts.get('force_lock'):
2577 repo.svfs.unlink('lock')
2506 repo.svfs.unlink('lock')
2578 if opts.get('force_wlock'):
2507 if opts.get('force_wlock'):
2579 repo.vfs.unlink('wlock')
2508 repo.vfs.unlink('wlock')
2580 if opts.get('force_lock') or opts.get('force_lock'):
2509 if opts.get('force_lock') or opts.get('force_lock'):
2581 return 0
2510 return 0
2582
2511
2583 now = time.time()
2512 now = time.time()
2584 held = 0
2513 held = 0
2585
2514
2586 def report(vfs, name, method):
2515 def report(vfs, name, method):
2587 # this causes stale locks to get reaped for more accurate reporting
2516 # this causes stale locks to get reaped for more accurate reporting
2588 try:
2517 try:
2589 l = method(False)
2518 l = method(False)
2590 except error.LockHeld:
2519 except error.LockHeld:
2591 l = None
2520 l = None
2592
2521
2593 if l:
2522 if l:
2594 l.release()
2523 l.release()
2595 else:
2524 else:
2596 try:
2525 try:
2597 stat = vfs.lstat(name)
2526 stat = vfs.lstat(name)
2598 age = now - stat.st_mtime
2527 age = now - stat.st_mtime
2599 user = util.username(stat.st_uid)
2528 user = util.username(stat.st_uid)
2600 locker = vfs.readlock(name)
2529 locker = vfs.readlock(name)
2601 if ":" in locker:
2530 if ":" in locker:
2602 host, pid = locker.split(':')
2531 host, pid = locker.split(':')
2603 if host == socket.gethostname():
2532 if host == socket.gethostname():
2604 locker = 'user %s, process %s' % (user, pid)
2533 locker = 'user %s, process %s' % (user, pid)
2605 else:
2534 else:
2606 locker = 'user %s, process %s, host %s' \
2535 locker = 'user %s, process %s, host %s' \
2607 % (user, pid, host)
2536 % (user, pid, host)
2608 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2537 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
2609 return 1
2538 return 1
2610 except OSError as e:
2539 except OSError as e:
2611 if e.errno != errno.ENOENT:
2540 if e.errno != errno.ENOENT:
2612 raise
2541 raise
2613
2542
2614 ui.write(("%-6s free\n") % (name + ":"))
2543 ui.write(("%-6s free\n") % (name + ":"))
2615 return 0
2544 return 0
2616
2545
2617 held += report(repo.svfs, "lock", repo.lock)
2546 held += report(repo.svfs, "lock", repo.lock)
2618 held += report(repo.vfs, "wlock", repo.wlock)
2547 held += report(repo.vfs, "wlock", repo.wlock)
2619
2548
2620 return held
2549 return held
2621
2550
2622 @command('debugobsolete',
2551 @command('debugobsolete',
2623 [('', 'flags', 0, _('markers flag')),
2552 [('', 'flags', 0, _('markers flag')),
2624 ('', 'record-parents', False,
2553 ('', 'record-parents', False,
2625 _('record parent information for the precursor')),
2554 _('record parent information for the precursor')),
2626 ('r', 'rev', [], _('display markers relevant to REV')),
2555 ('r', 'rev', [], _('display markers relevant to REV')),
2627 ('', 'index', False, _('display index of the marker')),
2556 ('', 'index', False, _('display index of the marker')),
2628 ('', 'delete', [], _('delete markers specified by indices')),
2557 ('', 'delete', [], _('delete markers specified by indices')),
2629 ] + commitopts2 + formatteropts,
2558 ] + commitopts2 + formatteropts,
2630 _('[OBSOLETED [REPLACEMENT ...]]'))
2559 _('[OBSOLETED [REPLACEMENT ...]]'))
2631 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2560 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2632 """create arbitrary obsolete marker
2561 """create arbitrary obsolete marker
2633
2562
2634 With no arguments, displays the list of obsolescence markers."""
2563 With no arguments, displays the list of obsolescence markers."""
2635
2564
2636 def parsenodeid(s):
2565 def parsenodeid(s):
2637 try:
2566 try:
2638 # We do not use revsingle/revrange functions here to accept
2567 # We do not use revsingle/revrange functions here to accept
2639 # arbitrary node identifiers, possibly not present in the
2568 # arbitrary node identifiers, possibly not present in the
2640 # local repository.
2569 # local repository.
2641 n = bin(s)
2570 n = bin(s)
2642 if len(n) != len(nullid):
2571 if len(n) != len(nullid):
2643 raise TypeError()
2572 raise TypeError()
2644 return n
2573 return n
2645 except TypeError:
2574 except TypeError:
2646 raise error.Abort('changeset references must be full hexadecimal '
2575 raise error.Abort('changeset references must be full hexadecimal '
2647 'node identifiers')
2576 'node identifiers')
2648
2577
2649 if opts.get('delete'):
2578 if opts.get('delete'):
2650 indices = []
2579 indices = []
2651 for v in opts.get('delete'):
2580 for v in opts.get('delete'):
2652 try:
2581 try:
2653 indices.append(int(v))
2582 indices.append(int(v))
2654 except ValueError:
2583 except ValueError:
2655 raise error.Abort(_('invalid index value: %r') % v,
2584 raise error.Abort(_('invalid index value: %r') % v,
2656 hint=_('use integers for indices'))
2585 hint=_('use integers for indices'))
2657
2586
2658 if repo.currenttransaction():
2587 if repo.currenttransaction():
2659 raise error.Abort(_('cannot delete obsmarkers in the middle '
2588 raise error.Abort(_('cannot delete obsmarkers in the middle '
2660 'of transaction.'))
2589 'of transaction.'))
2661
2590
2662 with repo.lock():
2591 with repo.lock():
2663 n = repair.deleteobsmarkers(repo.obsstore, indices)
2592 n = repair.deleteobsmarkers(repo.obsstore, indices)
2664 ui.write(_('deleted %i obsolescence markers\n') % n)
2593 ui.write(_('deleted %i obsolescence markers\n') % n)
2665
2594
2666 return
2595 return
2667
2596
2668 if precursor is not None:
2597 if precursor is not None:
2669 if opts['rev']:
2598 if opts['rev']:
2670 raise error.Abort('cannot select revision when creating marker')
2599 raise error.Abort('cannot select revision when creating marker')
2671 metadata = {}
2600 metadata = {}
2672 metadata['user'] = opts['user'] or ui.username()
2601 metadata['user'] = opts['user'] or ui.username()
2673 succs = tuple(parsenodeid(succ) for succ in successors)
2602 succs = tuple(parsenodeid(succ) for succ in successors)
2674 l = repo.lock()
2603 l = repo.lock()
2675 try:
2604 try:
2676 tr = repo.transaction('debugobsolete')
2605 tr = repo.transaction('debugobsolete')
2677 try:
2606 try:
2678 date = opts.get('date')
2607 date = opts.get('date')
2679 if date:
2608 if date:
2680 date = util.parsedate(date)
2609 date = util.parsedate(date)
2681 else:
2610 else:
2682 date = None
2611 date = None
2683 prec = parsenodeid(precursor)
2612 prec = parsenodeid(precursor)
2684 parents = None
2613 parents = None
2685 if opts['record_parents']:
2614 if opts['record_parents']:
2686 if prec not in repo.unfiltered():
2615 if prec not in repo.unfiltered():
2687 raise error.Abort('cannot used --record-parents on '
2616 raise error.Abort('cannot used --record-parents on '
2688 'unknown changesets')
2617 'unknown changesets')
2689 parents = repo.unfiltered()[prec].parents()
2618 parents = repo.unfiltered()[prec].parents()
2690 parents = tuple(p.node() for p in parents)
2619 parents = tuple(p.node() for p in parents)
2691 repo.obsstore.create(tr, prec, succs, opts['flags'],
2620 repo.obsstore.create(tr, prec, succs, opts['flags'],
2692 parents=parents, date=date,
2621 parents=parents, date=date,
2693 metadata=metadata)
2622 metadata=metadata)
2694 tr.close()
2623 tr.close()
2695 except ValueError as exc:
2624 except ValueError as exc:
2696 raise error.Abort(_('bad obsmarker input: %s') % exc)
2625 raise error.Abort(_('bad obsmarker input: %s') % exc)
2697 finally:
2626 finally:
2698 tr.release()
2627 tr.release()
2699 finally:
2628 finally:
2700 l.release()
2629 l.release()
2701 else:
2630 else:
2702 if opts['rev']:
2631 if opts['rev']:
2703 revs = scmutil.revrange(repo, opts['rev'])
2632 revs = scmutil.revrange(repo, opts['rev'])
2704 nodes = [repo[r].node() for r in revs]
2633 nodes = [repo[r].node() for r in revs]
2705 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2634 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2706 markers.sort(key=lambda x: x._data)
2635 markers.sort(key=lambda x: x._data)
2707 else:
2636 else:
2708 markers = obsolete.getmarkers(repo)
2637 markers = obsolete.getmarkers(repo)
2709
2638
2710 markerstoiter = markers
2639 markerstoiter = markers
2711 isrelevant = lambda m: True
2640 isrelevant = lambda m: True
2712 if opts.get('rev') and opts.get('index'):
2641 if opts.get('rev') and opts.get('index'):
2713 markerstoiter = obsolete.getmarkers(repo)
2642 markerstoiter = obsolete.getmarkers(repo)
2714 markerset = set(markers)
2643 markerset = set(markers)
2715 isrelevant = lambda m: m in markerset
2644 isrelevant = lambda m: m in markerset
2716
2645
2717 fm = ui.formatter('debugobsolete', opts)
2646 fm = ui.formatter('debugobsolete', opts)
2718 for i, m in enumerate(markerstoiter):
2647 for i, m in enumerate(markerstoiter):
2719 if not isrelevant(m):
2648 if not isrelevant(m):
2720 # marker can be irrelevant when we're iterating over a set
2649 # marker can be irrelevant when we're iterating over a set
2721 # of markers (markerstoiter) which is bigger than the set
2650 # of markers (markerstoiter) which is bigger than the set
2722 # of markers we want to display (markers)
2651 # of markers we want to display (markers)
2723 # this can happen if both --index and --rev options are
2652 # this can happen if both --index and --rev options are
2724 # provided and thus we need to iterate over all of the markers
2653 # provided and thus we need to iterate over all of the markers
2725 # to get the correct indices, but only display the ones that
2654 # to get the correct indices, but only display the ones that
2726 # are relevant to --rev value
2655 # are relevant to --rev value
2727 continue
2656 continue
2728 fm.startitem()
2657 fm.startitem()
2729 ind = i if opts.get('index') else None
2658 ind = i if opts.get('index') else None
2730 cmdutil.showmarker(fm, m, index=ind)
2659 cmdutil.showmarker(fm, m, index=ind)
2731 fm.end()
2660 fm.end()
2732
2661
2733 @command('debugpathcomplete',
2662 @command('debugpathcomplete',
2734 [('f', 'full', None, _('complete an entire path')),
2663 [('f', 'full', None, _('complete an entire path')),
2735 ('n', 'normal', None, _('show only normal files')),
2664 ('n', 'normal', None, _('show only normal files')),
2736 ('a', 'added', None, _('show only added files')),
2665 ('a', 'added', None, _('show only added files')),
2737 ('r', 'removed', None, _('show only removed files'))],
2666 ('r', 'removed', None, _('show only removed files'))],
2738 _('FILESPEC...'))
2667 _('FILESPEC...'))
2739 def debugpathcomplete(ui, repo, *specs, **opts):
2668 def debugpathcomplete(ui, repo, *specs, **opts):
2740 '''complete part or all of a tracked path
2669 '''complete part or all of a tracked path
2741
2670
2742 This command supports shells that offer path name completion. It
2671 This command supports shells that offer path name completion. It
2743 currently completes only files already known to the dirstate.
2672 currently completes only files already known to the dirstate.
2744
2673
2745 Completion extends only to the next path segment unless
2674 Completion extends only to the next path segment unless
2746 --full is specified, in which case entire paths are used.'''
2675 --full is specified, in which case entire paths are used.'''
2747
2676
2748 def complete(path, acceptable):
2677 def complete(path, acceptable):
2749 dirstate = repo.dirstate
2678 dirstate = repo.dirstate
2750 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2679 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2751 rootdir = repo.root + os.sep
2680 rootdir = repo.root + os.sep
2752 if spec != repo.root and not spec.startswith(rootdir):
2681 if spec != repo.root and not spec.startswith(rootdir):
2753 return [], []
2682 return [], []
2754 if os.path.isdir(spec):
2683 if os.path.isdir(spec):
2755 spec += '/'
2684 spec += '/'
2756 spec = spec[len(rootdir):]
2685 spec = spec[len(rootdir):]
2757 fixpaths = pycompat.ossep != '/'
2686 fixpaths = pycompat.ossep != '/'
2758 if fixpaths:
2687 if fixpaths:
2759 spec = spec.replace(os.sep, '/')
2688 spec = spec.replace(os.sep, '/')
2760 speclen = len(spec)
2689 speclen = len(spec)
2761 fullpaths = opts['full']
2690 fullpaths = opts['full']
2762 files, dirs = set(), set()
2691 files, dirs = set(), set()
2763 adddir, addfile = dirs.add, files.add
2692 adddir, addfile = dirs.add, files.add
2764 for f, st in dirstate.iteritems():
2693 for f, st in dirstate.iteritems():
2765 if f.startswith(spec) and st[0] in acceptable:
2694 if f.startswith(spec) and st[0] in acceptable:
2766 if fixpaths:
2695 if fixpaths:
2767 f = f.replace('/', os.sep)
2696 f = f.replace('/', os.sep)
2768 if fullpaths:
2697 if fullpaths:
2769 addfile(f)
2698 addfile(f)
2770 continue
2699 continue
2771 s = f.find(os.sep, speclen)
2700 s = f.find(os.sep, speclen)
2772 if s >= 0:
2701 if s >= 0:
2773 adddir(f[:s])
2702 adddir(f[:s])
2774 else:
2703 else:
2775 addfile(f)
2704 addfile(f)
2776 return files, dirs
2705 return files, dirs
2777
2706
2778 acceptable = ''
2707 acceptable = ''
2779 if opts['normal']:
2708 if opts['normal']:
2780 acceptable += 'nm'
2709 acceptable += 'nm'
2781 if opts['added']:
2710 if opts['added']:
2782 acceptable += 'a'
2711 acceptable += 'a'
2783 if opts['removed']:
2712 if opts['removed']:
2784 acceptable += 'r'
2713 acceptable += 'r'
2785 cwd = repo.getcwd()
2714 cwd = repo.getcwd()
2786 if not specs:
2715 if not specs:
2787 specs = ['.']
2716 specs = ['.']
2788
2717
2789 files, dirs = set(), set()
2718 files, dirs = set(), set()
2790 for spec in specs:
2719 for spec in specs:
2791 f, d = complete(spec, acceptable or 'nmar')
2720 f, d = complete(spec, acceptable or 'nmar')
2792 files.update(f)
2721 files.update(f)
2793 dirs.update(d)
2722 dirs.update(d)
2794 files.update(dirs)
2723 files.update(dirs)
2795 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2724 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2796 ui.write('\n')
2725 ui.write('\n')
2797
2726
2798 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2727 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2799 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2728 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2800 '''access the pushkey key/value protocol
2729 '''access the pushkey key/value protocol
2801
2730
2802 With two args, list the keys in the given namespace.
2731 With two args, list the keys in the given namespace.
2803
2732
2804 With five args, set a key to new if it currently is set to old.
2733 With five args, set a key to new if it currently is set to old.
2805 Reports success or failure.
2734 Reports success or failure.
2806 '''
2735 '''
2807
2736
2808 target = hg.peer(ui, {}, repopath)
2737 target = hg.peer(ui, {}, repopath)
2809 if keyinfo:
2738 if keyinfo:
2810 key, old, new = keyinfo
2739 key, old, new = keyinfo
2811 r = target.pushkey(namespace, key, old, new)
2740 r = target.pushkey(namespace, key, old, new)
2812 ui.status(str(r) + '\n')
2741 ui.status(str(r) + '\n')
2813 return not r
2742 return not r
2814 else:
2743 else:
2815 for k, v in sorted(target.listkeys(namespace).iteritems()):
2744 for k, v in sorted(target.listkeys(namespace).iteritems()):
2816 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2745 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2817 v.encode('string-escape')))
2746 v.encode('string-escape')))
2818
2747
2819 @command('debugpvec', [], _('A B'))
2748 @command('debugpvec', [], _('A B'))
2820 def debugpvec(ui, repo, a, b=None):
2749 def debugpvec(ui, repo, a, b=None):
2821 ca = scmutil.revsingle(repo, a)
2750 ca = scmutil.revsingle(repo, a)
2822 cb = scmutil.revsingle(repo, b)
2751 cb = scmutil.revsingle(repo, b)
2823 pa = pvec.ctxpvec(ca)
2752 pa = pvec.ctxpvec(ca)
2824 pb = pvec.ctxpvec(cb)
2753 pb = pvec.ctxpvec(cb)
2825 if pa == pb:
2754 if pa == pb:
2826 rel = "="
2755 rel = "="
2827 elif pa > pb:
2756 elif pa > pb:
2828 rel = ">"
2757 rel = ">"
2829 elif pa < pb:
2758 elif pa < pb:
2830 rel = "<"
2759 rel = "<"
2831 elif pa | pb:
2760 elif pa | pb:
2832 rel = "|"
2761 rel = "|"
2833 ui.write(_("a: %s\n") % pa)
2762 ui.write(_("a: %s\n") % pa)
2834 ui.write(_("b: %s\n") % pb)
2763 ui.write(_("b: %s\n") % pb)
2835 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2764 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2836 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2765 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2837 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2766 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2838 pa.distance(pb), rel))
2767 pa.distance(pb), rel))
2839
2768
2840 @command('debugrebuilddirstate|debugrebuildstate',
2769 @command('debugrebuilddirstate|debugrebuildstate',
2841 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2770 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2842 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2771 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2843 'the working copy parent')),
2772 'the working copy parent')),
2844 ],
2773 ],
2845 _('[-r REV]'))
2774 _('[-r REV]'))
2846 def debugrebuilddirstate(ui, repo, rev, **opts):
2775 def debugrebuilddirstate(ui, repo, rev, **opts):
2847 """rebuild the dirstate as it would look like for the given revision
2776 """rebuild the dirstate as it would look like for the given revision
2848
2777
2849 If no revision is specified the first current parent will be used.
2778 If no revision is specified the first current parent will be used.
2850
2779
2851 The dirstate will be set to the files of the given revision.
2780 The dirstate will be set to the files of the given revision.
2852 The actual working directory content or existing dirstate
2781 The actual working directory content or existing dirstate
2853 information such as adds or removes is not considered.
2782 information such as adds or removes is not considered.
2854
2783
2855 ``minimal`` will only rebuild the dirstate status for files that claim to be
2784 ``minimal`` will only rebuild the dirstate status for files that claim to be
2856 tracked but are not in the parent manifest, or that exist in the parent
2785 tracked but are not in the parent manifest, or that exist in the parent
2857 manifest but are not in the dirstate. It will not change adds, removes, or
2786 manifest but are not in the dirstate. It will not change adds, removes, or
2858 modified files that are in the working copy parent.
2787 modified files that are in the working copy parent.
2859
2788
2860 One use of this command is to make the next :hg:`status` invocation
2789 One use of this command is to make the next :hg:`status` invocation
2861 check the actual file content.
2790 check the actual file content.
2862 """
2791 """
2863 ctx = scmutil.revsingle(repo, rev)
2792 ctx = scmutil.revsingle(repo, rev)
2864 with repo.wlock():
2793 with repo.wlock():
2865 dirstate = repo.dirstate
2794 dirstate = repo.dirstate
2866 changedfiles = None
2795 changedfiles = None
2867 # See command doc for what minimal does.
2796 # See command doc for what minimal does.
2868 if opts.get('minimal'):
2797 if opts.get('minimal'):
2869 manifestfiles = set(ctx.manifest().keys())
2798 manifestfiles = set(ctx.manifest().keys())
2870 dirstatefiles = set(dirstate)
2799 dirstatefiles = set(dirstate)
2871 manifestonly = manifestfiles - dirstatefiles
2800 manifestonly = manifestfiles - dirstatefiles
2872 dsonly = dirstatefiles - manifestfiles
2801 dsonly = dirstatefiles - manifestfiles
2873 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2802 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2874 changedfiles = manifestonly | dsnotadded
2803 changedfiles = manifestonly | dsnotadded
2875
2804
2876 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2805 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2877
2806
2878 @command('debugrebuildfncache', [], '')
2807 @command('debugrebuildfncache', [], '')
2879 def debugrebuildfncache(ui, repo):
2808 def debugrebuildfncache(ui, repo):
2880 """rebuild the fncache file"""
2809 """rebuild the fncache file"""
2881 repair.rebuildfncache(ui, repo)
2810 repair.rebuildfncache(ui, repo)
2882
2811
2883 @command('debugrename',
2812 @command('debugrename',
2884 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2813 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2885 _('[-r REV] FILE'))
2814 _('[-r REV] FILE'))
2886 def debugrename(ui, repo, file1, *pats, **opts):
2815 def debugrename(ui, repo, file1, *pats, **opts):
2887 """dump rename information"""
2816 """dump rename information"""
2888
2817
2889 ctx = scmutil.revsingle(repo, opts.get('rev'))
2818 ctx = scmutil.revsingle(repo, opts.get('rev'))
2890 m = scmutil.match(ctx, (file1,) + pats, opts)
2819 m = scmutil.match(ctx, (file1,) + pats, opts)
2891 for abs in ctx.walk(m):
2820 for abs in ctx.walk(m):
2892 fctx = ctx[abs]
2821 fctx = ctx[abs]
2893 o = fctx.filelog().renamed(fctx.filenode())
2822 o = fctx.filelog().renamed(fctx.filenode())
2894 rel = m.rel(abs)
2823 rel = m.rel(abs)
2895 if o:
2824 if o:
2896 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2825 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2897 else:
2826 else:
2898 ui.write(_("%s not renamed\n") % rel)
2827 ui.write(_("%s not renamed\n") % rel)
2899
2828
2900 @command('debugrevlog', debugrevlogopts +
2829 @command('debugrevlog', debugrevlogopts +
2901 [('d', 'dump', False, _('dump index data'))],
2830 [('d', 'dump', False, _('dump index data'))],
2902 _('-c|-m|FILE'),
2831 _('-c|-m|FILE'),
2903 optionalrepo=True)
2832 optionalrepo=True)
2904 def debugrevlog(ui, repo, file_=None, **opts):
2833 def debugrevlog(ui, repo, file_=None, **opts):
2905 """show data and statistics about a revlog"""
2834 """show data and statistics about a revlog"""
2906 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2835 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2907
2836
2908 if opts.get("dump"):
2837 if opts.get("dump"):
2909 numrevs = len(r)
2838 numrevs = len(r)
2910 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2839 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2911 " rawsize totalsize compression heads chainlen\n"))
2840 " rawsize totalsize compression heads chainlen\n"))
2912 ts = 0
2841 ts = 0
2913 heads = set()
2842 heads = set()
2914
2843
2915 for rev in xrange(numrevs):
2844 for rev in xrange(numrevs):
2916 dbase = r.deltaparent(rev)
2845 dbase = r.deltaparent(rev)
2917 if dbase == -1:
2846 if dbase == -1:
2918 dbase = rev
2847 dbase = rev
2919 cbase = r.chainbase(rev)
2848 cbase = r.chainbase(rev)
2920 clen = r.chainlen(rev)
2849 clen = r.chainlen(rev)
2921 p1, p2 = r.parentrevs(rev)
2850 p1, p2 = r.parentrevs(rev)
2922 rs = r.rawsize(rev)
2851 rs = r.rawsize(rev)
2923 ts = ts + rs
2852 ts = ts + rs
2924 heads -= set(r.parentrevs(rev))
2853 heads -= set(r.parentrevs(rev))
2925 heads.add(rev)
2854 heads.add(rev)
2926 try:
2855 try:
2927 compression = ts / r.end(rev)
2856 compression = ts / r.end(rev)
2928 except ZeroDivisionError:
2857 except ZeroDivisionError:
2929 compression = 0
2858 compression = 0
2930 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2859 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2931 "%11d %5d %8d\n" %
2860 "%11d %5d %8d\n" %
2932 (rev, p1, p2, r.start(rev), r.end(rev),
2861 (rev, p1, p2, r.start(rev), r.end(rev),
2933 r.start(dbase), r.start(cbase),
2862 r.start(dbase), r.start(cbase),
2934 r.start(p1), r.start(p2),
2863 r.start(p1), r.start(p2),
2935 rs, ts, compression, len(heads), clen))
2864 rs, ts, compression, len(heads), clen))
2936 return 0
2865 return 0
2937
2866
2938 v = r.version
2867 v = r.version
2939 format = v & 0xFFFF
2868 format = v & 0xFFFF
2940 flags = []
2869 flags = []
2941 gdelta = False
2870 gdelta = False
2942 if v & revlog.REVLOGNGINLINEDATA:
2871 if v & revlog.REVLOGNGINLINEDATA:
2943 flags.append('inline')
2872 flags.append('inline')
2944 if v & revlog.REVLOGGENERALDELTA:
2873 if v & revlog.REVLOGGENERALDELTA:
2945 gdelta = True
2874 gdelta = True
2946 flags.append('generaldelta')
2875 flags.append('generaldelta')
2947 if not flags:
2876 if not flags:
2948 flags = ['(none)']
2877 flags = ['(none)']
2949
2878
2950 nummerges = 0
2879 nummerges = 0
2951 numfull = 0
2880 numfull = 0
2952 numprev = 0
2881 numprev = 0
2953 nump1 = 0
2882 nump1 = 0
2954 nump2 = 0
2883 nump2 = 0
2955 numother = 0
2884 numother = 0
2956 nump1prev = 0
2885 nump1prev = 0
2957 nump2prev = 0
2886 nump2prev = 0
2958 chainlengths = []
2887 chainlengths = []
2959
2888
2960 datasize = [None, 0, 0]
2889 datasize = [None, 0, 0]
2961 fullsize = [None, 0, 0]
2890 fullsize = [None, 0, 0]
2962 deltasize = [None, 0, 0]
2891 deltasize = [None, 0, 0]
2963 chunktypecounts = {}
2892 chunktypecounts = {}
2964 chunktypesizes = {}
2893 chunktypesizes = {}
2965
2894
2966 def addsize(size, l):
2895 def addsize(size, l):
2967 if l[0] is None or size < l[0]:
2896 if l[0] is None or size < l[0]:
2968 l[0] = size
2897 l[0] = size
2969 if size > l[1]:
2898 if size > l[1]:
2970 l[1] = size
2899 l[1] = size
2971 l[2] += size
2900 l[2] += size
2972
2901
2973 numrevs = len(r)
2902 numrevs = len(r)
2974 for rev in xrange(numrevs):
2903 for rev in xrange(numrevs):
2975 p1, p2 = r.parentrevs(rev)
2904 p1, p2 = r.parentrevs(rev)
2976 delta = r.deltaparent(rev)
2905 delta = r.deltaparent(rev)
2977 if format > 0:
2906 if format > 0:
2978 addsize(r.rawsize(rev), datasize)
2907 addsize(r.rawsize(rev), datasize)
2979 if p2 != nullrev:
2908 if p2 != nullrev:
2980 nummerges += 1
2909 nummerges += 1
2981 size = r.length(rev)
2910 size = r.length(rev)
2982 if delta == nullrev:
2911 if delta == nullrev:
2983 chainlengths.append(0)
2912 chainlengths.append(0)
2984 numfull += 1
2913 numfull += 1
2985 addsize(size, fullsize)
2914 addsize(size, fullsize)
2986 else:
2915 else:
2987 chainlengths.append(chainlengths[delta] + 1)
2916 chainlengths.append(chainlengths[delta] + 1)
2988 addsize(size, deltasize)
2917 addsize(size, deltasize)
2989 if delta == rev - 1:
2918 if delta == rev - 1:
2990 numprev += 1
2919 numprev += 1
2991 if delta == p1:
2920 if delta == p1:
2992 nump1prev += 1
2921 nump1prev += 1
2993 elif delta == p2:
2922 elif delta == p2:
2994 nump2prev += 1
2923 nump2prev += 1
2995 elif delta == p1:
2924 elif delta == p1:
2996 nump1 += 1
2925 nump1 += 1
2997 elif delta == p2:
2926 elif delta == p2:
2998 nump2 += 1
2927 nump2 += 1
2999 elif delta != nullrev:
2928 elif delta != nullrev:
3000 numother += 1
2929 numother += 1
3001
2930
3002 # Obtain data on the raw chunks in the revlog.
2931 # Obtain data on the raw chunks in the revlog.
3003 chunk = r._chunkraw(rev, rev)[1]
2932 chunk = r._chunkraw(rev, rev)[1]
3004 if chunk:
2933 if chunk:
3005 chunktype = chunk[0]
2934 chunktype = chunk[0]
3006 else:
2935 else:
3007 chunktype = 'empty'
2936 chunktype = 'empty'
3008
2937
3009 if chunktype not in chunktypecounts:
2938 if chunktype not in chunktypecounts:
3010 chunktypecounts[chunktype] = 0
2939 chunktypecounts[chunktype] = 0
3011 chunktypesizes[chunktype] = 0
2940 chunktypesizes[chunktype] = 0
3012
2941
3013 chunktypecounts[chunktype] += 1
2942 chunktypecounts[chunktype] += 1
3014 chunktypesizes[chunktype] += size
2943 chunktypesizes[chunktype] += size
3015
2944
3016 # Adjust size min value for empty cases
2945 # Adjust size min value for empty cases
3017 for size in (datasize, fullsize, deltasize):
2946 for size in (datasize, fullsize, deltasize):
3018 if size[0] is None:
2947 if size[0] is None:
3019 size[0] = 0
2948 size[0] = 0
3020
2949
3021 numdeltas = numrevs - numfull
2950 numdeltas = numrevs - numfull
3022 numoprev = numprev - nump1prev - nump2prev
2951 numoprev = numprev - nump1prev - nump2prev
3023 totalrawsize = datasize[2]
2952 totalrawsize = datasize[2]
3024 datasize[2] /= numrevs
2953 datasize[2] /= numrevs
3025 fulltotal = fullsize[2]
2954 fulltotal = fullsize[2]
3026 fullsize[2] /= numfull
2955 fullsize[2] /= numfull
3027 deltatotal = deltasize[2]
2956 deltatotal = deltasize[2]
3028 if numrevs - numfull > 0:
2957 if numrevs - numfull > 0:
3029 deltasize[2] /= numrevs - numfull
2958 deltasize[2] /= numrevs - numfull
3030 totalsize = fulltotal + deltatotal
2959 totalsize = fulltotal + deltatotal
3031 avgchainlen = sum(chainlengths) / numrevs
2960 avgchainlen = sum(chainlengths) / numrevs
3032 maxchainlen = max(chainlengths)
2961 maxchainlen = max(chainlengths)
3033 compratio = 1
2962 compratio = 1
3034 if totalsize:
2963 if totalsize:
3035 compratio = totalrawsize / totalsize
2964 compratio = totalrawsize / totalsize
3036
2965
3037 basedfmtstr = '%%%dd\n'
2966 basedfmtstr = '%%%dd\n'
3038 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2967 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3039
2968
3040 def dfmtstr(max):
2969 def dfmtstr(max):
3041 return basedfmtstr % len(str(max))
2970 return basedfmtstr % len(str(max))
3042 def pcfmtstr(max, padding=0):
2971 def pcfmtstr(max, padding=0):
3043 return basepcfmtstr % (len(str(max)), ' ' * padding)
2972 return basepcfmtstr % (len(str(max)), ' ' * padding)
3044
2973
3045 def pcfmt(value, total):
2974 def pcfmt(value, total):
3046 if total:
2975 if total:
3047 return (value, 100 * float(value) / total)
2976 return (value, 100 * float(value) / total)
3048 else:
2977 else:
3049 return value, 100.0
2978 return value, 100.0
3050
2979
3051 ui.write(('format : %d\n') % format)
2980 ui.write(('format : %d\n') % format)
3052 ui.write(('flags : %s\n') % ', '.join(flags))
2981 ui.write(('flags : %s\n') % ', '.join(flags))
3053
2982
3054 ui.write('\n')
2983 ui.write('\n')
3055 fmt = pcfmtstr(totalsize)
2984 fmt = pcfmtstr(totalsize)
3056 fmt2 = dfmtstr(totalsize)
2985 fmt2 = dfmtstr(totalsize)
3057 ui.write(('revisions : ') + fmt2 % numrevs)
2986 ui.write(('revisions : ') + fmt2 % numrevs)
3058 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2987 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3059 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2988 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3060 ui.write(('revisions : ') + fmt2 % numrevs)
2989 ui.write(('revisions : ') + fmt2 % numrevs)
3061 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2990 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3062 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2991 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3063 ui.write(('revision size : ') + fmt2 % totalsize)
2992 ui.write(('revision size : ') + fmt2 % totalsize)
3064 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2993 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3065 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2994 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3066
2995
3067 def fmtchunktype(chunktype):
2996 def fmtchunktype(chunktype):
3068 if chunktype == 'empty':
2997 if chunktype == 'empty':
3069 return ' %s : ' % chunktype
2998 return ' %s : ' % chunktype
3070 elif chunktype in string.ascii_letters:
2999 elif chunktype in string.ascii_letters:
3071 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3000 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3072 else:
3001 else:
3073 return ' 0x%s : ' % hex(chunktype)
3002 return ' 0x%s : ' % hex(chunktype)
3074
3003
3075 ui.write('\n')
3004 ui.write('\n')
3076 ui.write(('chunks : ') + fmt2 % numrevs)
3005 ui.write(('chunks : ') + fmt2 % numrevs)
3077 for chunktype in sorted(chunktypecounts):
3006 for chunktype in sorted(chunktypecounts):
3078 ui.write(fmtchunktype(chunktype))
3007 ui.write(fmtchunktype(chunktype))
3079 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3008 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3080 ui.write(('chunks size : ') + fmt2 % totalsize)
3009 ui.write(('chunks size : ') + fmt2 % totalsize)
3081 for chunktype in sorted(chunktypecounts):
3010 for chunktype in sorted(chunktypecounts):
3082 ui.write(fmtchunktype(chunktype))
3011 ui.write(fmtchunktype(chunktype))
3083 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3012 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3084
3013
3085 ui.write('\n')
3014 ui.write('\n')
3086 fmt = dfmtstr(max(avgchainlen, compratio))
3015 fmt = dfmtstr(max(avgchainlen, compratio))
3087 ui.write(('avg chain length : ') + fmt % avgchainlen)
3016 ui.write(('avg chain length : ') + fmt % avgchainlen)
3088 ui.write(('max chain length : ') + fmt % maxchainlen)
3017 ui.write(('max chain length : ') + fmt % maxchainlen)
3089 ui.write(('compression ratio : ') + fmt % compratio)
3018 ui.write(('compression ratio : ') + fmt % compratio)
3090
3019
3091 if format > 0:
3020 if format > 0:
3092 ui.write('\n')
3021 ui.write('\n')
3093 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3022 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3094 % tuple(datasize))
3023 % tuple(datasize))
3095 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3024 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3096 % tuple(fullsize))
3025 % tuple(fullsize))
3097 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3026 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3098 % tuple(deltasize))
3027 % tuple(deltasize))
3099
3028
3100 if numdeltas > 0:
3029 if numdeltas > 0:
3101 ui.write('\n')
3030 ui.write('\n')
3102 fmt = pcfmtstr(numdeltas)
3031 fmt = pcfmtstr(numdeltas)
3103 fmt2 = pcfmtstr(numdeltas, 4)
3032 fmt2 = pcfmtstr(numdeltas, 4)
3104 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3033 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3105 if numprev > 0:
3034 if numprev > 0:
3106 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3035 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3107 numprev))
3036 numprev))
3108 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3037 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3109 numprev))
3038 numprev))
3110 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3039 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3111 numprev))
3040 numprev))
3112 if gdelta:
3041 if gdelta:
3113 ui.write(('deltas against p1 : ')
3042 ui.write(('deltas against p1 : ')
3114 + fmt % pcfmt(nump1, numdeltas))
3043 + fmt % pcfmt(nump1, numdeltas))
3115 ui.write(('deltas against p2 : ')
3044 ui.write(('deltas against p2 : ')
3116 + fmt % pcfmt(nump2, numdeltas))
3045 + fmt % pcfmt(nump2, numdeltas))
3117 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3046 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3118 numdeltas))
3047 numdeltas))
3119
3048
3120 @command('debugrevspec',
3049 @command('debugrevspec',
3121 [('', 'optimize', None,
3050 [('', 'optimize', None,
3122 _('print parsed tree after optimizing (DEPRECATED)')),
3051 _('print parsed tree after optimizing (DEPRECATED)')),
3123 ('p', 'show-stage', [],
3052 ('p', 'show-stage', [],
3124 _('print parsed tree at the given stage'), _('NAME')),
3053 _('print parsed tree at the given stage'), _('NAME')),
3125 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3054 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3126 ('', 'verify-optimized', False, _('verify optimized result')),
3055 ('', 'verify-optimized', False, _('verify optimized result')),
3127 ],
3056 ],
3128 ('REVSPEC'))
3057 ('REVSPEC'))
3129 def debugrevspec(ui, repo, expr, **opts):
3058 def debugrevspec(ui, repo, expr, **opts):
3130 """parse and apply a revision specification
3059 """parse and apply a revision specification
3131
3060
3132 Use -p/--show-stage option to print the parsed tree at the given stages.
3061 Use -p/--show-stage option to print the parsed tree at the given stages.
3133 Use -p all to print tree at every stage.
3062 Use -p all to print tree at every stage.
3134
3063
3135 Use --verify-optimized to compare the optimized result with the unoptimized
3064 Use --verify-optimized to compare the optimized result with the unoptimized
3136 one. Returns 1 if the optimized result differs.
3065 one. Returns 1 if the optimized result differs.
3137 """
3066 """
3138 stages = [
3067 stages = [
3139 ('parsed', lambda tree: tree),
3068 ('parsed', lambda tree: tree),
3140 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3069 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3141 ('concatenated', revset.foldconcat),
3070 ('concatenated', revset.foldconcat),
3142 ('analyzed', revset.analyze),
3071 ('analyzed', revset.analyze),
3143 ('optimized', revset.optimize),
3072 ('optimized', revset.optimize),
3144 ]
3073 ]
3145 if opts['no_optimized']:
3074 if opts['no_optimized']:
3146 stages = stages[:-1]
3075 stages = stages[:-1]
3147 if opts['verify_optimized'] and opts['no_optimized']:
3076 if opts['verify_optimized'] and opts['no_optimized']:
3148 raise error.Abort(_('cannot use --verify-optimized with '
3077 raise error.Abort(_('cannot use --verify-optimized with '
3149 '--no-optimized'))
3078 '--no-optimized'))
3150 stagenames = set(n for n, f in stages)
3079 stagenames = set(n for n, f in stages)
3151
3080
3152 showalways = set()
3081 showalways = set()
3153 showchanged = set()
3082 showchanged = set()
3154 if ui.verbose and not opts['show_stage']:
3083 if ui.verbose and not opts['show_stage']:
3155 # show parsed tree by --verbose (deprecated)
3084 # show parsed tree by --verbose (deprecated)
3156 showalways.add('parsed')
3085 showalways.add('parsed')
3157 showchanged.update(['expanded', 'concatenated'])
3086 showchanged.update(['expanded', 'concatenated'])
3158 if opts['optimize']:
3087 if opts['optimize']:
3159 showalways.add('optimized')
3088 showalways.add('optimized')
3160 if opts['show_stage'] and opts['optimize']:
3089 if opts['show_stage'] and opts['optimize']:
3161 raise error.Abort(_('cannot use --optimize with --show-stage'))
3090 raise error.Abort(_('cannot use --optimize with --show-stage'))
3162 if opts['show_stage'] == ['all']:
3091 if opts['show_stage'] == ['all']:
3163 showalways.update(stagenames)
3092 showalways.update(stagenames)
3164 else:
3093 else:
3165 for n in opts['show_stage']:
3094 for n in opts['show_stage']:
3166 if n not in stagenames:
3095 if n not in stagenames:
3167 raise error.Abort(_('invalid stage name: %s') % n)
3096 raise error.Abort(_('invalid stage name: %s') % n)
3168 showalways.update(opts['show_stage'])
3097 showalways.update(opts['show_stage'])
3169
3098
3170 treebystage = {}
3099 treebystage = {}
3171 printedtree = None
3100 printedtree = None
3172 tree = revset.parse(expr, lookup=repo.__contains__)
3101 tree = revset.parse(expr, lookup=repo.__contains__)
3173 for n, f in stages:
3102 for n, f in stages:
3174 treebystage[n] = tree = f(tree)
3103 treebystage[n] = tree = f(tree)
3175 if n in showalways or (n in showchanged and tree != printedtree):
3104 if n in showalways or (n in showchanged and tree != printedtree):
3176 if opts['show_stage'] or n != 'parsed':
3105 if opts['show_stage'] or n != 'parsed':
3177 ui.write(("* %s:\n") % n)
3106 ui.write(("* %s:\n") % n)
3178 ui.write(revset.prettyformat(tree), "\n")
3107 ui.write(revset.prettyformat(tree), "\n")
3179 printedtree = tree
3108 printedtree = tree
3180
3109
3181 if opts['verify_optimized']:
3110 if opts['verify_optimized']:
3182 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3111 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3183 brevs = revset.makematcher(treebystage['optimized'])(repo)
3112 brevs = revset.makematcher(treebystage['optimized'])(repo)
3184 if ui.verbose:
3113 if ui.verbose:
3185 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3114 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3186 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3115 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3187 arevs = list(arevs)
3116 arevs = list(arevs)
3188 brevs = list(brevs)
3117 brevs = list(brevs)
3189 if arevs == brevs:
3118 if arevs == brevs:
3190 return 0
3119 return 0
3191 ui.write(('--- analyzed\n'), label='diff.file_a')
3120 ui.write(('--- analyzed\n'), label='diff.file_a')
3192 ui.write(('+++ optimized\n'), label='diff.file_b')
3121 ui.write(('+++ optimized\n'), label='diff.file_b')
3193 sm = difflib.SequenceMatcher(None, arevs, brevs)
3122 sm = difflib.SequenceMatcher(None, arevs, brevs)
3194 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3123 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3195 if tag in ('delete', 'replace'):
3124 if tag in ('delete', 'replace'):
3196 for c in arevs[alo:ahi]:
3125 for c in arevs[alo:ahi]:
3197 ui.write('-%s\n' % c, label='diff.deleted')
3126 ui.write('-%s\n' % c, label='diff.deleted')
3198 if tag in ('insert', 'replace'):
3127 if tag in ('insert', 'replace'):
3199 for c in brevs[blo:bhi]:
3128 for c in brevs[blo:bhi]:
3200 ui.write('+%s\n' % c, label='diff.inserted')
3129 ui.write('+%s\n' % c, label='diff.inserted')
3201 if tag == 'equal':
3130 if tag == 'equal':
3202 for c in arevs[alo:ahi]:
3131 for c in arevs[alo:ahi]:
3203 ui.write(' %s\n' % c)
3132 ui.write(' %s\n' % c)
3204 return 1
3133 return 1
3205
3134
3206 func = revset.makematcher(tree)
3135 func = revset.makematcher(tree)
3207 revs = func(repo)
3136 revs = func(repo)
3208 if ui.verbose:
3137 if ui.verbose:
3209 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3138 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")
3210 for c in revs:
3139 for c in revs:
3211 ui.write("%s\n" % c)
3140 ui.write("%s\n" % c)
3212
3141
3213 @command('debugsetparents', [], _('REV1 [REV2]'))
3142 @command('debugsetparents', [], _('REV1 [REV2]'))
3214 def debugsetparents(ui, repo, rev1, rev2=None):
3143 def debugsetparents(ui, repo, rev1, rev2=None):
3215 """manually set the parents of the current working directory
3144 """manually set the parents of the current working directory
3216
3145
3217 This is useful for writing repository conversion tools, but should
3146 This is useful for writing repository conversion tools, but should
3218 be used with care. For example, neither the working directory nor the
3147 be used with care. For example, neither the working directory nor the
3219 dirstate is updated, so file status may be incorrect after running this
3148 dirstate is updated, so file status may be incorrect after running this
3220 command.
3149 command.
3221
3150
3222 Returns 0 on success.
3151 Returns 0 on success.
3223 """
3152 """
3224
3153
3225 r1 = scmutil.revsingle(repo, rev1).node()
3154 r1 = scmutil.revsingle(repo, rev1).node()
3226 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3155 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3227
3156
3228 with repo.wlock():
3157 with repo.wlock():
3229 repo.setparents(r1, r2)
3158 repo.setparents(r1, r2)
3230
3159
3231 @command('debugdirstate|debugstate',
3160 @command('debugdirstate|debugstate',
3232 [('', 'nodates', None, _('do not display the saved mtime')),
3161 [('', 'nodates', None, _('do not display the saved mtime')),
3233 ('', 'datesort', None, _('sort by saved mtime'))],
3162 ('', 'datesort', None, _('sort by saved mtime'))],
3234 _('[OPTION]...'))
3163 _('[OPTION]...'))
3235 def debugstate(ui, repo, **opts):
3164 def debugstate(ui, repo, **opts):
3236 """show the contents of the current dirstate"""
3165 """show the contents of the current dirstate"""
3237
3166
3238 nodates = opts.get('nodates')
3167 nodates = opts.get('nodates')
3239 datesort = opts.get('datesort')
3168 datesort = opts.get('datesort')
3240
3169
3241 timestr = ""
3170 timestr = ""
3242 if datesort:
3171 if datesort:
3243 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3172 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3244 else:
3173 else:
3245 keyfunc = None # sort by filename
3174 keyfunc = None # sort by filename
3246 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3175 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3247 if ent[3] == -1:
3176 if ent[3] == -1:
3248 timestr = 'unset '
3177 timestr = 'unset '
3249 elif nodates:
3178 elif nodates:
3250 timestr = 'set '
3179 timestr = 'set '
3251 else:
3180 else:
3252 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3181 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3253 time.localtime(ent[3]))
3182 time.localtime(ent[3]))
3254 if ent[1] & 0o20000:
3183 if ent[1] & 0o20000:
3255 mode = 'lnk'
3184 mode = 'lnk'
3256 else:
3185 else:
3257 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3186 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3258 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3187 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3259 for f in repo.dirstate.copies():
3188 for f in repo.dirstate.copies():
3260 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3189 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3261
3190
3262 @command('debugsub',
3191 @command('debugsub',
3263 [('r', 'rev', '',
3192 [('r', 'rev', '',
3264 _('revision to check'), _('REV'))],
3193 _('revision to check'), _('REV'))],
3265 _('[-r REV] [REV]'))
3194 _('[-r REV] [REV]'))
3266 def debugsub(ui, repo, rev=None):
3195 def debugsub(ui, repo, rev=None):
3267 ctx = scmutil.revsingle(repo, rev, None)
3196 ctx = scmutil.revsingle(repo, rev, None)
3268 for k, v in sorted(ctx.substate.items()):
3197 for k, v in sorted(ctx.substate.items()):
3269 ui.write(('path %s\n') % k)
3198 ui.write(('path %s\n') % k)
3270 ui.write((' source %s\n') % v[0])
3199 ui.write((' source %s\n') % v[0])
3271 ui.write((' revision %s\n') % v[1])
3200 ui.write((' revision %s\n') % v[1])
3272
3201
3273 @command('debugsuccessorssets',
3202 @command('debugsuccessorssets',
3274 [],
3203 [],
3275 _('[REV]'))
3204 _('[REV]'))
3276 def debugsuccessorssets(ui, repo, *revs):
3205 def debugsuccessorssets(ui, repo, *revs):
3277 """show set of successors for revision
3206 """show set of successors for revision
3278
3207
3279 A successors set of changeset A is a consistent group of revisions that
3208 A successors set of changeset A is a consistent group of revisions that
3280 succeed A. It contains non-obsolete changesets only.
3209 succeed A. It contains non-obsolete changesets only.
3281
3210
3282 In most cases a changeset A has a single successors set containing a single
3211 In most cases a changeset A has a single successors set containing a single
3283 successor (changeset A replaced by A').
3212 successor (changeset A replaced by A').
3284
3213
3285 A changeset that is made obsolete with no successors are called "pruned".
3214 A changeset that is made obsolete with no successors are called "pruned".
3286 Such changesets have no successors sets at all.
3215 Such changesets have no successors sets at all.
3287
3216
3288 A changeset that has been "split" will have a successors set containing
3217 A changeset that has been "split" will have a successors set containing
3289 more than one successor.
3218 more than one successor.
3290
3219
3291 A changeset that has been rewritten in multiple different ways is called
3220 A changeset that has been rewritten in multiple different ways is called
3292 "divergent". Such changesets have multiple successor sets (each of which
3221 "divergent". Such changesets have multiple successor sets (each of which
3293 may also be split, i.e. have multiple successors).
3222 may also be split, i.e. have multiple successors).
3294
3223
3295 Results are displayed as follows::
3224 Results are displayed as follows::
3296
3225
3297 <rev1>
3226 <rev1>
3298 <successors-1A>
3227 <successors-1A>
3299 <rev2>
3228 <rev2>
3300 <successors-2A>
3229 <successors-2A>
3301 <successors-2B1> <successors-2B2> <successors-2B3>
3230 <successors-2B1> <successors-2B2> <successors-2B3>
3302
3231
3303 Here rev2 has two possible (i.e. divergent) successors sets. The first
3232 Here rev2 has two possible (i.e. divergent) successors sets. The first
3304 holds one element, whereas the second holds three (i.e. the changeset has
3233 holds one element, whereas the second holds three (i.e. the changeset has
3305 been split).
3234 been split).
3306 """
3235 """
3307 # passed to successorssets caching computation from one call to another
3236 # passed to successorssets caching computation from one call to another
3308 cache = {}
3237 cache = {}
3309 ctx2str = str
3238 ctx2str = str
3310 node2str = short
3239 node2str = short
3311 if ui.debug():
3240 if ui.debug():
3312 def ctx2str(ctx):
3241 def ctx2str(ctx):
3313 return ctx.hex()
3242 return ctx.hex()
3314 node2str = hex
3243 node2str = hex
3315 for rev in scmutil.revrange(repo, revs):
3244 for rev in scmutil.revrange(repo, revs):
3316 ctx = repo[rev]
3245 ctx = repo[rev]
3317 ui.write('%s\n'% ctx2str(ctx))
3246 ui.write('%s\n'% ctx2str(ctx))
3318 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3247 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3319 if succsset:
3248 if succsset:
3320 ui.write(' ')
3249 ui.write(' ')
3321 ui.write(node2str(succsset[0]))
3250 ui.write(node2str(succsset[0]))
3322 for node in succsset[1:]:
3251 for node in succsset[1:]:
3323 ui.write(' ')
3252 ui.write(' ')
3324 ui.write(node2str(node))
3253 ui.write(node2str(node))
3325 ui.write('\n')
3254 ui.write('\n')
3326
3255
3327 @command('debugtemplate',
3256 @command('debugtemplate',
3328 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3257 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
3329 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3258 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
3330 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3259 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3331 optionalrepo=True)
3260 optionalrepo=True)
3332 def debugtemplate(ui, repo, tmpl, **opts):
3261 def debugtemplate(ui, repo, tmpl, **opts):
3333 """parse and apply a template
3262 """parse and apply a template
3334
3263
3335 If -r/--rev is given, the template is processed as a log template and
3264 If -r/--rev is given, the template is processed as a log template and
3336 applied to the given changesets. Otherwise, it is processed as a generic
3265 applied to the given changesets. Otherwise, it is processed as a generic
3337 template.
3266 template.
3338
3267
3339 Use --verbose to print the parsed tree.
3268 Use --verbose to print the parsed tree.
3340 """
3269 """
3341 revs = None
3270 revs = None
3342 if opts['rev']:
3271 if opts['rev']:
3343 if repo is None:
3272 if repo is None:
3344 raise error.RepoError(_('there is no Mercurial repository here '
3273 raise error.RepoError(_('there is no Mercurial repository here '
3345 '(.hg not found)'))
3274 '(.hg not found)'))
3346 revs = scmutil.revrange(repo, opts['rev'])
3275 revs = scmutil.revrange(repo, opts['rev'])
3347
3276
3348 props = {}
3277 props = {}
3349 for d in opts['define']:
3278 for d in opts['define']:
3350 try:
3279 try:
3351 k, v = (e.strip() for e in d.split('=', 1))
3280 k, v = (e.strip() for e in d.split('=', 1))
3352 if not k:
3281 if not k:
3353 raise ValueError
3282 raise ValueError
3354 props[k] = v
3283 props[k] = v
3355 except ValueError:
3284 except ValueError:
3356 raise error.Abort(_('malformed keyword definition: %s') % d)
3285 raise error.Abort(_('malformed keyword definition: %s') % d)
3357
3286
3358 if ui.verbose:
3287 if ui.verbose:
3359 aliases = ui.configitems('templatealias')
3288 aliases = ui.configitems('templatealias')
3360 tree = templater.parse(tmpl)
3289 tree = templater.parse(tmpl)
3361 ui.note(templater.prettyformat(tree), '\n')
3290 ui.note(templater.prettyformat(tree), '\n')
3362 newtree = templater.expandaliases(tree, aliases)
3291 newtree = templater.expandaliases(tree, aliases)
3363 if newtree != tree:
3292 if newtree != tree:
3364 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3293 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
3365
3294
3366 mapfile = None
3295 mapfile = None
3367 if revs is None:
3296 if revs is None:
3368 k = 'debugtemplate'
3297 k = 'debugtemplate'
3369 t = formatter.maketemplater(ui, k, tmpl)
3298 t = formatter.maketemplater(ui, k, tmpl)
3370 ui.write(templater.stringify(t(k, **props)))
3299 ui.write(templater.stringify(t(k, **props)))
3371 else:
3300 else:
3372 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3301 displayer = cmdutil.changeset_templater(ui, repo, None, opts, tmpl,
3373 mapfile, buffered=False)
3302 mapfile, buffered=False)
3374 for r in revs:
3303 for r in revs:
3375 displayer.show(repo[r], **props)
3304 displayer.show(repo[r], **props)
3376 displayer.close()
3305 displayer.close()
3377
3306
3378 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3307 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3379 def debugwalk(ui, repo, *pats, **opts):
3308 def debugwalk(ui, repo, *pats, **opts):
3380 """show how files match on given patterns"""
3309 """show how files match on given patterns"""
3381 m = scmutil.match(repo[None], pats, opts)
3310 m = scmutil.match(repo[None], pats, opts)
3382 items = list(repo.walk(m))
3311 items = list(repo.walk(m))
3383 if not items:
3312 if not items:
3384 return
3313 return
3385 f = lambda fn: fn
3314 f = lambda fn: fn
3386 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
3315 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
3387 f = lambda fn: util.normpath(fn)
3316 f = lambda fn: util.normpath(fn)
3388 fmt = 'f %%-%ds %%-%ds %%s' % (
3317 fmt = 'f %%-%ds %%-%ds %%s' % (
3389 max([len(abs) for abs in items]),
3318 max([len(abs) for abs in items]),
3390 max([len(m.rel(abs)) for abs in items]))
3319 max([len(m.rel(abs)) for abs in items]))
3391 for abs in items:
3320 for abs in items:
3392 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3321 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3393 ui.write("%s\n" % line.rstrip())
3322 ui.write("%s\n" % line.rstrip())
3394
3323
3395 @command('debugwireargs',
3324 @command('debugwireargs',
3396 [('', 'three', '', 'three'),
3325 [('', 'three', '', 'three'),
3397 ('', 'four', '', 'four'),
3326 ('', 'four', '', 'four'),
3398 ('', 'five', '', 'five'),
3327 ('', 'five', '', 'five'),
3399 ] + remoteopts,
3328 ] + remoteopts,
3400 _('REPO [OPTIONS]... [ONE [TWO]]'),
3329 _('REPO [OPTIONS]... [ONE [TWO]]'),
3401 norepo=True)
3330 norepo=True)
3402 def debugwireargs(ui, repopath, *vals, **opts):
3331 def debugwireargs(ui, repopath, *vals, **opts):
3403 repo = hg.peer(ui, opts, repopath)
3332 repo = hg.peer(ui, opts, repopath)
3404 for opt in remoteopts:
3333 for opt in remoteopts:
3405 del opts[opt[1]]
3334 del opts[opt[1]]
3406 args = {}
3335 args = {}
3407 for k, v in opts.iteritems():
3336 for k, v in opts.iteritems():
3408 if v:
3337 if v:
3409 args[k] = v
3338 args[k] = v
3410 # run twice to check that we don't mess up the stream for the next command
3339 # run twice to check that we don't mess up the stream for the next command
3411 res1 = repo.debugwireargs(*vals, **args)
3340 res1 = repo.debugwireargs(*vals, **args)
3412 res2 = repo.debugwireargs(*vals, **args)
3341 res2 = repo.debugwireargs(*vals, **args)
3413 ui.write("%s\n" % res1)
3342 ui.write("%s\n" % res1)
3414 if res1 != res2:
3343 if res1 != res2:
3415 ui.warn("%s\n" % res2)
3344 ui.warn("%s\n" % res2)
3416
3345
3417 @command('^diff',
3346 @command('^diff',
3418 [('r', 'rev', [], _('revision'), _('REV')),
3347 [('r', 'rev', [], _('revision'), _('REV')),
3419 ('c', 'change', '', _('change made by revision'), _('REV'))
3348 ('c', 'change', '', _('change made by revision'), _('REV'))
3420 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3349 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3421 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3350 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3422 inferrepo=True)
3351 inferrepo=True)
3423 def diff(ui, repo, *pats, **opts):
3352 def diff(ui, repo, *pats, **opts):
3424 """diff repository (or selected files)
3353 """diff repository (or selected files)
3425
3354
3426 Show differences between revisions for the specified files.
3355 Show differences between revisions for the specified files.
3427
3356
3428 Differences between files are shown using the unified diff format.
3357 Differences between files are shown using the unified diff format.
3429
3358
3430 .. note::
3359 .. note::
3431
3360
3432 :hg:`diff` may generate unexpected results for merges, as it will
3361 :hg:`diff` may generate unexpected results for merges, as it will
3433 default to comparing against the working directory's first
3362 default to comparing against the working directory's first
3434 parent changeset if no revisions are specified.
3363 parent changeset if no revisions are specified.
3435
3364
3436 When two revision arguments are given, then changes are shown
3365 When two revision arguments are given, then changes are shown
3437 between those revisions. If only one revision is specified then
3366 between those revisions. If only one revision is specified then
3438 that revision is compared to the working directory, and, when no
3367 that revision is compared to the working directory, and, when no
3439 revisions are specified, the working directory files are compared
3368 revisions are specified, the working directory files are compared
3440 to its first parent.
3369 to its first parent.
3441
3370
3442 Alternatively you can specify -c/--change with a revision to see
3371 Alternatively you can specify -c/--change with a revision to see
3443 the changes in that changeset relative to its first parent.
3372 the changes in that changeset relative to its first parent.
3444
3373
3445 Without the -a/--text option, diff will avoid generating diffs of
3374 Without the -a/--text option, diff will avoid generating diffs of
3446 files it detects as binary. With -a, diff will generate a diff
3375 files it detects as binary. With -a, diff will generate a diff
3447 anyway, probably with undesirable results.
3376 anyway, probably with undesirable results.
3448
3377
3449 Use the -g/--git option to generate diffs in the git extended diff
3378 Use the -g/--git option to generate diffs in the git extended diff
3450 format. For more information, read :hg:`help diffs`.
3379 format. For more information, read :hg:`help diffs`.
3451
3380
3452 .. container:: verbose
3381 .. container:: verbose
3453
3382
3454 Examples:
3383 Examples:
3455
3384
3456 - compare a file in the current working directory to its parent::
3385 - compare a file in the current working directory to its parent::
3457
3386
3458 hg diff foo.c
3387 hg diff foo.c
3459
3388
3460 - compare two historical versions of a directory, with rename info::
3389 - compare two historical versions of a directory, with rename info::
3461
3390
3462 hg diff --git -r 1.0:1.2 lib/
3391 hg diff --git -r 1.0:1.2 lib/
3463
3392
3464 - get change stats relative to the last change on some date::
3393 - get change stats relative to the last change on some date::
3465
3394
3466 hg diff --stat -r "date('may 2')"
3395 hg diff --stat -r "date('may 2')"
3467
3396
3468 - diff all newly-added files that contain a keyword::
3397 - diff all newly-added files that contain a keyword::
3469
3398
3470 hg diff "set:added() and grep(GNU)"
3399 hg diff "set:added() and grep(GNU)"
3471
3400
3472 - compare a revision and its parents::
3401 - compare a revision and its parents::
3473
3402
3474 hg diff -c 9353 # compare against first parent
3403 hg diff -c 9353 # compare against first parent
3475 hg diff -r 9353^:9353 # same using revset syntax
3404 hg diff -r 9353^:9353 # same using revset syntax
3476 hg diff -r 9353^2:9353 # compare against the second parent
3405 hg diff -r 9353^2:9353 # compare against the second parent
3477
3406
3478 Returns 0 on success.
3407 Returns 0 on success.
3479 """
3408 """
3480
3409
3481 revs = opts.get('rev')
3410 revs = opts.get('rev')
3482 change = opts.get('change')
3411 change = opts.get('change')
3483 stat = opts.get('stat')
3412 stat = opts.get('stat')
3484 reverse = opts.get('reverse')
3413 reverse = opts.get('reverse')
3485
3414
3486 if revs and change:
3415 if revs and change:
3487 msg = _('cannot specify --rev and --change at the same time')
3416 msg = _('cannot specify --rev and --change at the same time')
3488 raise error.Abort(msg)
3417 raise error.Abort(msg)
3489 elif change:
3418 elif change:
3490 node2 = scmutil.revsingle(repo, change, None).node()
3419 node2 = scmutil.revsingle(repo, change, None).node()
3491 node1 = repo[node2].p1().node()
3420 node1 = repo[node2].p1().node()
3492 else:
3421 else:
3493 node1, node2 = scmutil.revpair(repo, revs)
3422 node1, node2 = scmutil.revpair(repo, revs)
3494
3423
3495 if reverse:
3424 if reverse:
3496 node1, node2 = node2, node1
3425 node1, node2 = node2, node1
3497
3426
3498 diffopts = patch.diffallopts(ui, opts)
3427 diffopts = patch.diffallopts(ui, opts)
3499 m = scmutil.match(repo[node2], pats, opts)
3428 m = scmutil.match(repo[node2], pats, opts)
3500 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3429 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3501 listsubrepos=opts.get('subrepos'),
3430 listsubrepos=opts.get('subrepos'),
3502 root=opts.get('root'))
3431 root=opts.get('root'))
3503
3432
3504 @command('^export',
3433 @command('^export',
3505 [('o', 'output', '',
3434 [('o', 'output', '',
3506 _('print output to file with formatted name'), _('FORMAT')),
3435 _('print output to file with formatted name'), _('FORMAT')),
3507 ('', 'switch-parent', None, _('diff against the second parent')),
3436 ('', 'switch-parent', None, _('diff against the second parent')),
3508 ('r', 'rev', [], _('revisions to export'), _('REV')),
3437 ('r', 'rev', [], _('revisions to export'), _('REV')),
3509 ] + diffopts,
3438 ] + diffopts,
3510 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3439 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3511 def export(ui, repo, *changesets, **opts):
3440 def export(ui, repo, *changesets, **opts):
3512 """dump the header and diffs for one or more changesets
3441 """dump the header and diffs for one or more changesets
3513
3442
3514 Print the changeset header and diffs for one or more revisions.
3443 Print the changeset header and diffs for one or more revisions.
3515 If no revision is given, the parent of the working directory is used.
3444 If no revision is given, the parent of the working directory is used.
3516
3445
3517 The information shown in the changeset header is: author, date,
3446 The information shown in the changeset header is: author, date,
3518 branch name (if non-default), changeset hash, parent(s) and commit
3447 branch name (if non-default), changeset hash, parent(s) and commit
3519 comment.
3448 comment.
3520
3449
3521 .. note::
3450 .. note::
3522
3451
3523 :hg:`export` may generate unexpected diff output for merge
3452 :hg:`export` may generate unexpected diff output for merge
3524 changesets, as it will compare the merge changeset against its
3453 changesets, as it will compare the merge changeset against its
3525 first parent only.
3454 first parent only.
3526
3455
3527 Output may be to a file, in which case the name of the file is
3456 Output may be to a file, in which case the name of the file is
3528 given using a format string. The formatting rules are as follows:
3457 given using a format string. The formatting rules are as follows:
3529
3458
3530 :``%%``: literal "%" character
3459 :``%%``: literal "%" character
3531 :``%H``: changeset hash (40 hexadecimal digits)
3460 :``%H``: changeset hash (40 hexadecimal digits)
3532 :``%N``: number of patches being generated
3461 :``%N``: number of patches being generated
3533 :``%R``: changeset revision number
3462 :``%R``: changeset revision number
3534 :``%b``: basename of the exporting repository
3463 :``%b``: basename of the exporting repository
3535 :``%h``: short-form changeset hash (12 hexadecimal digits)
3464 :``%h``: short-form changeset hash (12 hexadecimal digits)
3536 :``%m``: first line of the commit message (only alphanumeric characters)
3465 :``%m``: first line of the commit message (only alphanumeric characters)
3537 :``%n``: zero-padded sequence number, starting at 1
3466 :``%n``: zero-padded sequence number, starting at 1
3538 :``%r``: zero-padded changeset revision number
3467 :``%r``: zero-padded changeset revision number
3539
3468
3540 Without the -a/--text option, export will avoid generating diffs
3469 Without the -a/--text option, export will avoid generating diffs
3541 of files it detects as binary. With -a, export will generate a
3470 of files it detects as binary. With -a, export will generate a
3542 diff anyway, probably with undesirable results.
3471 diff anyway, probably with undesirable results.
3543
3472
3544 Use the -g/--git option to generate diffs in the git extended diff
3473 Use the -g/--git option to generate diffs in the git extended diff
3545 format. See :hg:`help diffs` for more information.
3474 format. See :hg:`help diffs` for more information.
3546
3475
3547 With the --switch-parent option, the diff will be against the
3476 With the --switch-parent option, the diff will be against the
3548 second parent. It can be useful to review a merge.
3477 second parent. It can be useful to review a merge.
3549
3478
3550 .. container:: verbose
3479 .. container:: verbose
3551
3480
3552 Examples:
3481 Examples:
3553
3482
3554 - use export and import to transplant a bugfix to the current
3483 - use export and import to transplant a bugfix to the current
3555 branch::
3484 branch::
3556
3485
3557 hg export -r 9353 | hg import -
3486 hg export -r 9353 | hg import -
3558
3487
3559 - export all the changesets between two revisions to a file with
3488 - export all the changesets between two revisions to a file with
3560 rename information::
3489 rename information::
3561
3490
3562 hg export --git -r 123:150 > changes.txt
3491 hg export --git -r 123:150 > changes.txt
3563
3492
3564 - split outgoing changes into a series of patches with
3493 - split outgoing changes into a series of patches with
3565 descriptive names::
3494 descriptive names::
3566
3495
3567 hg export -r "outgoing()" -o "%n-%m.patch"
3496 hg export -r "outgoing()" -o "%n-%m.patch"
3568
3497
3569 Returns 0 on success.
3498 Returns 0 on success.
3570 """
3499 """
3571 changesets += tuple(opts.get('rev', []))
3500 changesets += tuple(opts.get('rev', []))
3572 if not changesets:
3501 if not changesets:
3573 changesets = ['.']
3502 changesets = ['.']
3574 revs = scmutil.revrange(repo, changesets)
3503 revs = scmutil.revrange(repo, changesets)
3575 if not revs:
3504 if not revs:
3576 raise error.Abort(_("export requires at least one changeset"))
3505 raise error.Abort(_("export requires at least one changeset"))
3577 if len(revs) > 1:
3506 if len(revs) > 1:
3578 ui.note(_('exporting patches:\n'))
3507 ui.note(_('exporting patches:\n'))
3579 else:
3508 else:
3580 ui.note(_('exporting patch:\n'))
3509 ui.note(_('exporting patch:\n'))
3581 cmdutil.export(repo, revs, template=opts.get('output'),
3510 cmdutil.export(repo, revs, template=opts.get('output'),
3582 switch_parent=opts.get('switch_parent'),
3511 switch_parent=opts.get('switch_parent'),
3583 opts=patch.diffallopts(ui, opts))
3512 opts=patch.diffallopts(ui, opts))
3584
3513
3585 @command('files',
3514 @command('files',
3586 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3515 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3587 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3516 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3588 ] + walkopts + formatteropts + subrepoopts,
3517 ] + walkopts + formatteropts + subrepoopts,
3589 _('[OPTION]... [FILE]...'))
3518 _('[OPTION]... [FILE]...'))
3590 def files(ui, repo, *pats, **opts):
3519 def files(ui, repo, *pats, **opts):
3591 """list tracked files
3520 """list tracked files
3592
3521
3593 Print files under Mercurial control in the working directory or
3522 Print files under Mercurial control in the working directory or
3594 specified revision for given files (excluding removed files).
3523 specified revision for given files (excluding removed files).
3595 Files can be specified as filenames or filesets.
3524 Files can be specified as filenames or filesets.
3596
3525
3597 If no files are given to match, this command prints the names
3526 If no files are given to match, this command prints the names
3598 of all files under Mercurial control.
3527 of all files under Mercurial control.
3599
3528
3600 .. container:: verbose
3529 .. container:: verbose
3601
3530
3602 Examples:
3531 Examples:
3603
3532
3604 - list all files under the current directory::
3533 - list all files under the current directory::
3605
3534
3606 hg files .
3535 hg files .
3607
3536
3608 - shows sizes and flags for current revision::
3537 - shows sizes and flags for current revision::
3609
3538
3610 hg files -vr .
3539 hg files -vr .
3611
3540
3612 - list all files named README::
3541 - list all files named README::
3613
3542
3614 hg files -I "**/README"
3543 hg files -I "**/README"
3615
3544
3616 - list all binary files::
3545 - list all binary files::
3617
3546
3618 hg files "set:binary()"
3547 hg files "set:binary()"
3619
3548
3620 - find files containing a regular expression::
3549 - find files containing a regular expression::
3621
3550
3622 hg files "set:grep('bob')"
3551 hg files "set:grep('bob')"
3623
3552
3624 - search tracked file contents with xargs and grep::
3553 - search tracked file contents with xargs and grep::
3625
3554
3626 hg files -0 | xargs -0 grep foo
3555 hg files -0 | xargs -0 grep foo
3627
3556
3628 See :hg:`help patterns` and :hg:`help filesets` for more information
3557 See :hg:`help patterns` and :hg:`help filesets` for more information
3629 on specifying file patterns.
3558 on specifying file patterns.
3630
3559
3631 Returns 0 if a match is found, 1 otherwise.
3560 Returns 0 if a match is found, 1 otherwise.
3632
3561
3633 """
3562 """
3634 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3563 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3635
3564
3636 end = '\n'
3565 end = '\n'
3637 if opts.get('print0'):
3566 if opts.get('print0'):
3638 end = '\0'
3567 end = '\0'
3639 fmt = '%s' + end
3568 fmt = '%s' + end
3640
3569
3641 m = scmutil.match(ctx, pats, opts)
3570 m = scmutil.match(ctx, pats, opts)
3642 with ui.formatter('files', opts) as fm:
3571 with ui.formatter('files', opts) as fm:
3643 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3572 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3644
3573
3645 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3574 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3646 def forget(ui, repo, *pats, **opts):
3575 def forget(ui, repo, *pats, **opts):
3647 """forget the specified files on the next commit
3576 """forget the specified files on the next commit
3648
3577
3649 Mark the specified files so they will no longer be tracked
3578 Mark the specified files so they will no longer be tracked
3650 after the next commit.
3579 after the next commit.
3651
3580
3652 This only removes files from the current branch, not from the
3581 This only removes files from the current branch, not from the
3653 entire project history, and it does not delete them from the
3582 entire project history, and it does not delete them from the
3654 working directory.
3583 working directory.
3655
3584
3656 To delete the file from the working directory, see :hg:`remove`.
3585 To delete the file from the working directory, see :hg:`remove`.
3657
3586
3658 To undo a forget before the next commit, see :hg:`add`.
3587 To undo a forget before the next commit, see :hg:`add`.
3659
3588
3660 .. container:: verbose
3589 .. container:: verbose
3661
3590
3662 Examples:
3591 Examples:
3663
3592
3664 - forget newly-added binary files::
3593 - forget newly-added binary files::
3665
3594
3666 hg forget "set:added() and binary()"
3595 hg forget "set:added() and binary()"
3667
3596
3668 - forget files that would be excluded by .hgignore::
3597 - forget files that would be excluded by .hgignore::
3669
3598
3670 hg forget "set:hgignore()"
3599 hg forget "set:hgignore()"
3671
3600
3672 Returns 0 on success.
3601 Returns 0 on success.
3673 """
3602 """
3674
3603
3675 if not pats:
3604 if not pats:
3676 raise error.Abort(_('no files specified'))
3605 raise error.Abort(_('no files specified'))
3677
3606
3678 m = scmutil.match(repo[None], pats, opts)
3607 m = scmutil.match(repo[None], pats, opts)
3679 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3608 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3680 return rejected and 1 or 0
3609 return rejected and 1 or 0
3681
3610
3682 @command(
3611 @command(
3683 'graft',
3612 'graft',
3684 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3613 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3685 ('c', 'continue', False, _('resume interrupted graft')),
3614 ('c', 'continue', False, _('resume interrupted graft')),
3686 ('e', 'edit', False, _('invoke editor on commit messages')),
3615 ('e', 'edit', False, _('invoke editor on commit messages')),
3687 ('', 'log', None, _('append graft info to log message')),
3616 ('', 'log', None, _('append graft info to log message')),
3688 ('f', 'force', False, _('force graft')),
3617 ('f', 'force', False, _('force graft')),
3689 ('D', 'currentdate', False,
3618 ('D', 'currentdate', False,
3690 _('record the current date as commit date')),
3619 _('record the current date as commit date')),
3691 ('U', 'currentuser', False,
3620 ('U', 'currentuser', False,
3692 _('record the current user as committer'), _('DATE'))]
3621 _('record the current user as committer'), _('DATE'))]
3693 + commitopts2 + mergetoolopts + dryrunopts,
3622 + commitopts2 + mergetoolopts + dryrunopts,
3694 _('[OPTION]... [-r REV]... REV...'))
3623 _('[OPTION]... [-r REV]... REV...'))
3695 def graft(ui, repo, *revs, **opts):
3624 def graft(ui, repo, *revs, **opts):
3696 '''copy changes from other branches onto the current branch
3625 '''copy changes from other branches onto the current branch
3697
3626
3698 This command uses Mercurial's merge logic to copy individual
3627 This command uses Mercurial's merge logic to copy individual
3699 changes from other branches without merging branches in the
3628 changes from other branches without merging branches in the
3700 history graph. This is sometimes known as 'backporting' or
3629 history graph. This is sometimes known as 'backporting' or
3701 'cherry-picking'. By default, graft will copy user, date, and
3630 'cherry-picking'. By default, graft will copy user, date, and
3702 description from the source changesets.
3631 description from the source changesets.
3703
3632
3704 Changesets that are ancestors of the current revision, that have
3633 Changesets that are ancestors of the current revision, that have
3705 already been grafted, or that are merges will be skipped.
3634 already been grafted, or that are merges will be skipped.
3706
3635
3707 If --log is specified, log messages will have a comment appended
3636 If --log is specified, log messages will have a comment appended
3708 of the form::
3637 of the form::
3709
3638
3710 (grafted from CHANGESETHASH)
3639 (grafted from CHANGESETHASH)
3711
3640
3712 If --force is specified, revisions will be grafted even if they
3641 If --force is specified, revisions will be grafted even if they
3713 are already ancestors of or have been grafted to the destination.
3642 are already ancestors of or have been grafted to the destination.
3714 This is useful when the revisions have since been backed out.
3643 This is useful when the revisions have since been backed out.
3715
3644
3716 If a graft merge results in conflicts, the graft process is
3645 If a graft merge results in conflicts, the graft process is
3717 interrupted so that the current merge can be manually resolved.
3646 interrupted so that the current merge can be manually resolved.
3718 Once all conflicts are addressed, the graft process can be
3647 Once all conflicts are addressed, the graft process can be
3719 continued with the -c/--continue option.
3648 continued with the -c/--continue option.
3720
3649
3721 .. note::
3650 .. note::
3722
3651
3723 The -c/--continue option does not reapply earlier options, except
3652 The -c/--continue option does not reapply earlier options, except
3724 for --force.
3653 for --force.
3725
3654
3726 .. container:: verbose
3655 .. container:: verbose
3727
3656
3728 Examples:
3657 Examples:
3729
3658
3730 - copy a single change to the stable branch and edit its description::
3659 - copy a single change to the stable branch and edit its description::
3731
3660
3732 hg update stable
3661 hg update stable
3733 hg graft --edit 9393
3662 hg graft --edit 9393
3734
3663
3735 - graft a range of changesets with one exception, updating dates::
3664 - graft a range of changesets with one exception, updating dates::
3736
3665
3737 hg graft -D "2085::2093 and not 2091"
3666 hg graft -D "2085::2093 and not 2091"
3738
3667
3739 - continue a graft after resolving conflicts::
3668 - continue a graft after resolving conflicts::
3740
3669
3741 hg graft -c
3670 hg graft -c
3742
3671
3743 - show the source of a grafted changeset::
3672 - show the source of a grafted changeset::
3744
3673
3745 hg log --debug -r .
3674 hg log --debug -r .
3746
3675
3747 - show revisions sorted by date::
3676 - show revisions sorted by date::
3748
3677
3749 hg log -r "sort(all(), date)"
3678 hg log -r "sort(all(), date)"
3750
3679
3751 See :hg:`help revisions` and :hg:`help revsets` for more about
3680 See :hg:`help revisions` and :hg:`help revsets` for more about
3752 specifying revisions.
3681 specifying revisions.
3753
3682
3754 Returns 0 on successful completion.
3683 Returns 0 on successful completion.
3755 '''
3684 '''
3756 with repo.wlock():
3685 with repo.wlock():
3757 return _dograft(ui, repo, *revs, **opts)
3686 return _dograft(ui, repo, *revs, **opts)
3758
3687
3759 def _dograft(ui, repo, *revs, **opts):
3688 def _dograft(ui, repo, *revs, **opts):
3760 if revs and opts.get('rev'):
3689 if revs and opts.get('rev'):
3761 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3690 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3762 'revision ordering!\n'))
3691 'revision ordering!\n'))
3763
3692
3764 revs = list(revs)
3693 revs = list(revs)
3765 revs.extend(opts.get('rev'))
3694 revs.extend(opts.get('rev'))
3766
3695
3767 if not opts.get('user') and opts.get('currentuser'):
3696 if not opts.get('user') and opts.get('currentuser'):
3768 opts['user'] = ui.username()
3697 opts['user'] = ui.username()
3769 if not opts.get('date') and opts.get('currentdate'):
3698 if not opts.get('date') and opts.get('currentdate'):
3770 opts['date'] = "%d %d" % util.makedate()
3699 opts['date'] = "%d %d" % util.makedate()
3771
3700
3772 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3701 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3773
3702
3774 cont = False
3703 cont = False
3775 if opts.get('continue'):
3704 if opts.get('continue'):
3776 cont = True
3705 cont = True
3777 if revs:
3706 if revs:
3778 raise error.Abort(_("can't specify --continue and revisions"))
3707 raise error.Abort(_("can't specify --continue and revisions"))
3779 # read in unfinished revisions
3708 # read in unfinished revisions
3780 try:
3709 try:
3781 nodes = repo.vfs.read('graftstate').splitlines()
3710 nodes = repo.vfs.read('graftstate').splitlines()
3782 revs = [repo[node].rev() for node in nodes]
3711 revs = [repo[node].rev() for node in nodes]
3783 except IOError as inst:
3712 except IOError as inst:
3784 if inst.errno != errno.ENOENT:
3713 if inst.errno != errno.ENOENT:
3785 raise
3714 raise
3786 cmdutil.wrongtooltocontinue(repo, _('graft'))
3715 cmdutil.wrongtooltocontinue(repo, _('graft'))
3787 else:
3716 else:
3788 cmdutil.checkunfinished(repo)
3717 cmdutil.checkunfinished(repo)
3789 cmdutil.bailifchanged(repo)
3718 cmdutil.bailifchanged(repo)
3790 if not revs:
3719 if not revs:
3791 raise error.Abort(_('no revisions specified'))
3720 raise error.Abort(_('no revisions specified'))
3792 revs = scmutil.revrange(repo, revs)
3721 revs = scmutil.revrange(repo, revs)
3793
3722
3794 skipped = set()
3723 skipped = set()
3795 # check for merges
3724 # check for merges
3796 for rev in repo.revs('%ld and merge()', revs):
3725 for rev in repo.revs('%ld and merge()', revs):
3797 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3726 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3798 skipped.add(rev)
3727 skipped.add(rev)
3799 revs = [r for r in revs if r not in skipped]
3728 revs = [r for r in revs if r not in skipped]
3800 if not revs:
3729 if not revs:
3801 return -1
3730 return -1
3802
3731
3803 # Don't check in the --continue case, in effect retaining --force across
3732 # Don't check in the --continue case, in effect retaining --force across
3804 # --continues. That's because without --force, any revisions we decided to
3733 # --continues. That's because without --force, any revisions we decided to
3805 # skip would have been filtered out here, so they wouldn't have made their
3734 # skip would have been filtered out here, so they wouldn't have made their
3806 # way to the graftstate. With --force, any revisions we would have otherwise
3735 # way to the graftstate. With --force, any revisions we would have otherwise
3807 # skipped would not have been filtered out, and if they hadn't been applied
3736 # skipped would not have been filtered out, and if they hadn't been applied
3808 # already, they'd have been in the graftstate.
3737 # already, they'd have been in the graftstate.
3809 if not (cont or opts.get('force')):
3738 if not (cont or opts.get('force')):
3810 # check for ancestors of dest branch
3739 # check for ancestors of dest branch
3811 crev = repo['.'].rev()
3740 crev = repo['.'].rev()
3812 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3741 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3813 # XXX make this lazy in the future
3742 # XXX make this lazy in the future
3814 # don't mutate while iterating, create a copy
3743 # don't mutate while iterating, create a copy
3815 for rev in list(revs):
3744 for rev in list(revs):
3816 if rev in ancestors:
3745 if rev in ancestors:
3817 ui.warn(_('skipping ancestor revision %d:%s\n') %
3746 ui.warn(_('skipping ancestor revision %d:%s\n') %
3818 (rev, repo[rev]))
3747 (rev, repo[rev]))
3819 # XXX remove on list is slow
3748 # XXX remove on list is slow
3820 revs.remove(rev)
3749 revs.remove(rev)
3821 if not revs:
3750 if not revs:
3822 return -1
3751 return -1
3823
3752
3824 # analyze revs for earlier grafts
3753 # analyze revs for earlier grafts
3825 ids = {}
3754 ids = {}
3826 for ctx in repo.set("%ld", revs):
3755 for ctx in repo.set("%ld", revs):
3827 ids[ctx.hex()] = ctx.rev()
3756 ids[ctx.hex()] = ctx.rev()
3828 n = ctx.extra().get('source')
3757 n = ctx.extra().get('source')
3829 if n:
3758 if n:
3830 ids[n] = ctx.rev()
3759 ids[n] = ctx.rev()
3831
3760
3832 # check ancestors for earlier grafts
3761 # check ancestors for earlier grafts
3833 ui.debug('scanning for duplicate grafts\n')
3762 ui.debug('scanning for duplicate grafts\n')
3834
3763
3835 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3764 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3836 ctx = repo[rev]
3765 ctx = repo[rev]
3837 n = ctx.extra().get('source')
3766 n = ctx.extra().get('source')
3838 if n in ids:
3767 if n in ids:
3839 try:
3768 try:
3840 r = repo[n].rev()
3769 r = repo[n].rev()
3841 except error.RepoLookupError:
3770 except error.RepoLookupError:
3842 r = None
3771 r = None
3843 if r in revs:
3772 if r in revs:
3844 ui.warn(_('skipping revision %d:%s '
3773 ui.warn(_('skipping revision %d:%s '
3845 '(already grafted to %d:%s)\n')
3774 '(already grafted to %d:%s)\n')
3846 % (r, repo[r], rev, ctx))
3775 % (r, repo[r], rev, ctx))
3847 revs.remove(r)
3776 revs.remove(r)
3848 elif ids[n] in revs:
3777 elif ids[n] in revs:
3849 if r is None:
3778 if r is None:
3850 ui.warn(_('skipping already grafted revision %d:%s '
3779 ui.warn(_('skipping already grafted revision %d:%s '
3851 '(%d:%s also has unknown origin %s)\n')
3780 '(%d:%s also has unknown origin %s)\n')
3852 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3781 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3853 else:
3782 else:
3854 ui.warn(_('skipping already grafted revision %d:%s '
3783 ui.warn(_('skipping already grafted revision %d:%s '
3855 '(%d:%s also has origin %d:%s)\n')
3784 '(%d:%s also has origin %d:%s)\n')
3856 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3785 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3857 revs.remove(ids[n])
3786 revs.remove(ids[n])
3858 elif ctx.hex() in ids:
3787 elif ctx.hex() in ids:
3859 r = ids[ctx.hex()]
3788 r = ids[ctx.hex()]
3860 ui.warn(_('skipping already grafted revision %d:%s '
3789 ui.warn(_('skipping already grafted revision %d:%s '
3861 '(was grafted from %d:%s)\n') %
3790 '(was grafted from %d:%s)\n') %
3862 (r, repo[r], rev, ctx))
3791 (r, repo[r], rev, ctx))
3863 revs.remove(r)
3792 revs.remove(r)
3864 if not revs:
3793 if not revs:
3865 return -1
3794 return -1
3866
3795
3867 for pos, ctx in enumerate(repo.set("%ld", revs)):
3796 for pos, ctx in enumerate(repo.set("%ld", revs)):
3868 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3797 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3869 ctx.description().split('\n', 1)[0])
3798 ctx.description().split('\n', 1)[0])
3870 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3799 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3871 if names:
3800 if names:
3872 desc += ' (%s)' % ' '.join(names)
3801 desc += ' (%s)' % ' '.join(names)
3873 ui.status(_('grafting %s\n') % desc)
3802 ui.status(_('grafting %s\n') % desc)
3874 if opts.get('dry_run'):
3803 if opts.get('dry_run'):
3875 continue
3804 continue
3876
3805
3877 source = ctx.extra().get('source')
3806 source = ctx.extra().get('source')
3878 extra = {}
3807 extra = {}
3879 if source:
3808 if source:
3880 extra['source'] = source
3809 extra['source'] = source
3881 extra['intermediate-source'] = ctx.hex()
3810 extra['intermediate-source'] = ctx.hex()
3882 else:
3811 else:
3883 extra['source'] = ctx.hex()
3812 extra['source'] = ctx.hex()
3884 user = ctx.user()
3813 user = ctx.user()
3885 if opts.get('user'):
3814 if opts.get('user'):
3886 user = opts['user']
3815 user = opts['user']
3887 date = ctx.date()
3816 date = ctx.date()
3888 if opts.get('date'):
3817 if opts.get('date'):
3889 date = opts['date']
3818 date = opts['date']
3890 message = ctx.description()
3819 message = ctx.description()
3891 if opts.get('log'):
3820 if opts.get('log'):
3892 message += '\n(grafted from %s)' % ctx.hex()
3821 message += '\n(grafted from %s)' % ctx.hex()
3893
3822
3894 # we don't merge the first commit when continuing
3823 # we don't merge the first commit when continuing
3895 if not cont:
3824 if not cont:
3896 # perform the graft merge with p1(rev) as 'ancestor'
3825 # perform the graft merge with p1(rev) as 'ancestor'
3897 try:
3826 try:
3898 # ui.forcemerge is an internal variable, do not document
3827 # ui.forcemerge is an internal variable, do not document
3899 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3828 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3900 'graft')
3829 'graft')
3901 stats = mergemod.graft(repo, ctx, ctx.p1(),
3830 stats = mergemod.graft(repo, ctx, ctx.p1(),
3902 ['local', 'graft'])
3831 ['local', 'graft'])
3903 finally:
3832 finally:
3904 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3833 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3905 # report any conflicts
3834 # report any conflicts
3906 if stats and stats[3] > 0:
3835 if stats and stats[3] > 0:
3907 # write out state for --continue
3836 # write out state for --continue
3908 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3837 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3909 repo.vfs.write('graftstate', ''.join(nodelines))
3838 repo.vfs.write('graftstate', ''.join(nodelines))
3910 extra = ''
3839 extra = ''
3911 if opts.get('user'):
3840 if opts.get('user'):
3912 extra += ' --user %s' % util.shellquote(opts['user'])
3841 extra += ' --user %s' % util.shellquote(opts['user'])
3913 if opts.get('date'):
3842 if opts.get('date'):
3914 extra += ' --date %s' % util.shellquote(opts['date'])
3843 extra += ' --date %s' % util.shellquote(opts['date'])
3915 if opts.get('log'):
3844 if opts.get('log'):
3916 extra += ' --log'
3845 extra += ' --log'
3917 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
3846 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
3918 raise error.Abort(
3847 raise error.Abort(
3919 _("unresolved conflicts, can't continue"),
3848 _("unresolved conflicts, can't continue"),
3920 hint=hint)
3849 hint=hint)
3921 else:
3850 else:
3922 cont = False
3851 cont = False
3923
3852
3924 # commit
3853 # commit
3925 node = repo.commit(text=message, user=user,
3854 node = repo.commit(text=message, user=user,
3926 date=date, extra=extra, editor=editor)
3855 date=date, extra=extra, editor=editor)
3927 if node is None:
3856 if node is None:
3928 ui.warn(
3857 ui.warn(
3929 _('note: graft of %d:%s created no changes to commit\n') %
3858 _('note: graft of %d:%s created no changes to commit\n') %
3930 (ctx.rev(), ctx))
3859 (ctx.rev(), ctx))
3931
3860
3932 # remove state when we complete successfully
3861 # remove state when we complete successfully
3933 if not opts.get('dry_run'):
3862 if not opts.get('dry_run'):
3934 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3863 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3935
3864
3936 return 0
3865 return 0
3937
3866
3938 @command('grep',
3867 @command('grep',
3939 [('0', 'print0', None, _('end fields with NUL')),
3868 [('0', 'print0', None, _('end fields with NUL')),
3940 ('', 'all', None, _('print all revisions that match')),
3869 ('', 'all', None, _('print all revisions that match')),
3941 ('a', 'text', None, _('treat all files as text')),
3870 ('a', 'text', None, _('treat all files as text')),
3942 ('f', 'follow', None,
3871 ('f', 'follow', None,
3943 _('follow changeset history,'
3872 _('follow changeset history,'
3944 ' or file history across copies and renames')),
3873 ' or file history across copies and renames')),
3945 ('i', 'ignore-case', None, _('ignore case when matching')),
3874 ('i', 'ignore-case', None, _('ignore case when matching')),
3946 ('l', 'files-with-matches', None,
3875 ('l', 'files-with-matches', None,
3947 _('print only filenames and revisions that match')),
3876 _('print only filenames and revisions that match')),
3948 ('n', 'line-number', None, _('print matching line numbers')),
3877 ('n', 'line-number', None, _('print matching line numbers')),
3949 ('r', 'rev', [],
3878 ('r', 'rev', [],
3950 _('only search files changed within revision range'), _('REV')),
3879 _('only search files changed within revision range'), _('REV')),
3951 ('u', 'user', None, _('list the author (long with -v)')),
3880 ('u', 'user', None, _('list the author (long with -v)')),
3952 ('d', 'date', None, _('list the date (short with -q)')),
3881 ('d', 'date', None, _('list the date (short with -q)')),
3953 ] + formatteropts + walkopts,
3882 ] + formatteropts + walkopts,
3954 _('[OPTION]... PATTERN [FILE]...'),
3883 _('[OPTION]... PATTERN [FILE]...'),
3955 inferrepo=True)
3884 inferrepo=True)
3956 def grep(ui, repo, pattern, *pats, **opts):
3885 def grep(ui, repo, pattern, *pats, **opts):
3957 """search revision history for a pattern in specified files
3886 """search revision history for a pattern in specified files
3958
3887
3959 Search revision history for a regular expression in the specified
3888 Search revision history for a regular expression in the specified
3960 files or the entire project.
3889 files or the entire project.
3961
3890
3962 By default, grep prints the most recent revision number for each
3891 By default, grep prints the most recent revision number for each
3963 file in which it finds a match. To get it to print every revision
3892 file in which it finds a match. To get it to print every revision
3964 that contains a change in match status ("-" for a match that becomes
3893 that contains a change in match status ("-" for a match that becomes
3965 a non-match, or "+" for a non-match that becomes a match), use the
3894 a non-match, or "+" for a non-match that becomes a match), use the
3966 --all flag.
3895 --all flag.
3967
3896
3968 PATTERN can be any Python (roughly Perl-compatible) regular
3897 PATTERN can be any Python (roughly Perl-compatible) regular
3969 expression.
3898 expression.
3970
3899
3971 If no FILEs are specified (and -f/--follow isn't set), all files in
3900 If no FILEs are specified (and -f/--follow isn't set), all files in
3972 the repository are searched, including those that don't exist in the
3901 the repository are searched, including those that don't exist in the
3973 current branch or have been deleted in a prior changeset.
3902 current branch or have been deleted in a prior changeset.
3974
3903
3975 Returns 0 if a match is found, 1 otherwise.
3904 Returns 0 if a match is found, 1 otherwise.
3976 """
3905 """
3977 reflags = re.M
3906 reflags = re.M
3978 if opts.get('ignore_case'):
3907 if opts.get('ignore_case'):
3979 reflags |= re.I
3908 reflags |= re.I
3980 try:
3909 try:
3981 regexp = util.re.compile(pattern, reflags)
3910 regexp = util.re.compile(pattern, reflags)
3982 except re.error as inst:
3911 except re.error as inst:
3983 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3912 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3984 return 1
3913 return 1
3985 sep, eol = ':', '\n'
3914 sep, eol = ':', '\n'
3986 if opts.get('print0'):
3915 if opts.get('print0'):
3987 sep = eol = '\0'
3916 sep = eol = '\0'
3988
3917
3989 getfile = util.lrucachefunc(repo.file)
3918 getfile = util.lrucachefunc(repo.file)
3990
3919
3991 def matchlines(body):
3920 def matchlines(body):
3992 begin = 0
3921 begin = 0
3993 linenum = 0
3922 linenum = 0
3994 while begin < len(body):
3923 while begin < len(body):
3995 match = regexp.search(body, begin)
3924 match = regexp.search(body, begin)
3996 if not match:
3925 if not match:
3997 break
3926 break
3998 mstart, mend = match.span()
3927 mstart, mend = match.span()
3999 linenum += body.count('\n', begin, mstart) + 1
3928 linenum += body.count('\n', begin, mstart) + 1
4000 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3929 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4001 begin = body.find('\n', mend) + 1 or len(body) + 1
3930 begin = body.find('\n', mend) + 1 or len(body) + 1
4002 lend = begin - 1
3931 lend = begin - 1
4003 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3932 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4004
3933
4005 class linestate(object):
3934 class linestate(object):
4006 def __init__(self, line, linenum, colstart, colend):
3935 def __init__(self, line, linenum, colstart, colend):
4007 self.line = line
3936 self.line = line
4008 self.linenum = linenum
3937 self.linenum = linenum
4009 self.colstart = colstart
3938 self.colstart = colstart
4010 self.colend = colend
3939 self.colend = colend
4011
3940
4012 def __hash__(self):
3941 def __hash__(self):
4013 return hash((self.linenum, self.line))
3942 return hash((self.linenum, self.line))
4014
3943
4015 def __eq__(self, other):
3944 def __eq__(self, other):
4016 return self.line == other.line
3945 return self.line == other.line
4017
3946
4018 def findpos(self):
3947 def findpos(self):
4019 """Iterate all (start, end) indices of matches"""
3948 """Iterate all (start, end) indices of matches"""
4020 yield self.colstart, self.colend
3949 yield self.colstart, self.colend
4021 p = self.colend
3950 p = self.colend
4022 while p < len(self.line):
3951 while p < len(self.line):
4023 m = regexp.search(self.line, p)
3952 m = regexp.search(self.line, p)
4024 if not m:
3953 if not m:
4025 break
3954 break
4026 yield m.span()
3955 yield m.span()
4027 p = m.end()
3956 p = m.end()
4028
3957
4029 matches = {}
3958 matches = {}
4030 copies = {}
3959 copies = {}
4031 def grepbody(fn, rev, body):
3960 def grepbody(fn, rev, body):
4032 matches[rev].setdefault(fn, [])
3961 matches[rev].setdefault(fn, [])
4033 m = matches[rev][fn]
3962 m = matches[rev][fn]
4034 for lnum, cstart, cend, line in matchlines(body):
3963 for lnum, cstart, cend, line in matchlines(body):
4035 s = linestate(line, lnum, cstart, cend)
3964 s = linestate(line, lnum, cstart, cend)
4036 m.append(s)
3965 m.append(s)
4037
3966
4038 def difflinestates(a, b):
3967 def difflinestates(a, b):
4039 sm = difflib.SequenceMatcher(None, a, b)
3968 sm = difflib.SequenceMatcher(None, a, b)
4040 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3969 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4041 if tag == 'insert':
3970 if tag == 'insert':
4042 for i in xrange(blo, bhi):
3971 for i in xrange(blo, bhi):
4043 yield ('+', b[i])
3972 yield ('+', b[i])
4044 elif tag == 'delete':
3973 elif tag == 'delete':
4045 for i in xrange(alo, ahi):
3974 for i in xrange(alo, ahi):
4046 yield ('-', a[i])
3975 yield ('-', a[i])
4047 elif tag == 'replace':
3976 elif tag == 'replace':
4048 for i in xrange(alo, ahi):
3977 for i in xrange(alo, ahi):
4049 yield ('-', a[i])
3978 yield ('-', a[i])
4050 for i in xrange(blo, bhi):
3979 for i in xrange(blo, bhi):
4051 yield ('+', b[i])
3980 yield ('+', b[i])
4052
3981
4053 def display(fm, fn, ctx, pstates, states):
3982 def display(fm, fn, ctx, pstates, states):
4054 rev = ctx.rev()
3983 rev = ctx.rev()
4055 if fm.isplain():
3984 if fm.isplain():
4056 formatuser = ui.shortuser
3985 formatuser = ui.shortuser
4057 else:
3986 else:
4058 formatuser = str
3987 formatuser = str
4059 if ui.quiet:
3988 if ui.quiet:
4060 datefmt = '%Y-%m-%d'
3989 datefmt = '%Y-%m-%d'
4061 else:
3990 else:
4062 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
3991 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4063 found = False
3992 found = False
4064 @util.cachefunc
3993 @util.cachefunc
4065 def binary():
3994 def binary():
4066 flog = getfile(fn)
3995 flog = getfile(fn)
4067 return util.binary(flog.read(ctx.filenode(fn)))
3996 return util.binary(flog.read(ctx.filenode(fn)))
4068
3997
4069 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
3998 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4070 if opts.get('all'):
3999 if opts.get('all'):
4071 iter = difflinestates(pstates, states)
4000 iter = difflinestates(pstates, states)
4072 else:
4001 else:
4073 iter = [('', l) for l in states]
4002 iter = [('', l) for l in states]
4074 for change, l in iter:
4003 for change, l in iter:
4075 fm.startitem()
4004 fm.startitem()
4076 fm.data(node=fm.hexfunc(ctx.node()))
4005 fm.data(node=fm.hexfunc(ctx.node()))
4077 cols = [
4006 cols = [
4078 ('filename', fn, True),
4007 ('filename', fn, True),
4079 ('rev', rev, True),
4008 ('rev', rev, True),
4080 ('linenumber', l.linenum, opts.get('line_number')),
4009 ('linenumber', l.linenum, opts.get('line_number')),
4081 ]
4010 ]
4082 if opts.get('all'):
4011 if opts.get('all'):
4083 cols.append(('change', change, True))
4012 cols.append(('change', change, True))
4084 cols.extend([
4013 cols.extend([
4085 ('user', formatuser(ctx.user()), opts.get('user')),
4014 ('user', formatuser(ctx.user()), opts.get('user')),
4086 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4015 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4087 ])
4016 ])
4088 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4017 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4089 for name, data, cond in cols:
4018 for name, data, cond in cols:
4090 field = fieldnamemap.get(name, name)
4019 field = fieldnamemap.get(name, name)
4091 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4020 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4092 if cond and name != lastcol:
4021 if cond and name != lastcol:
4093 fm.plain(sep, label='grep.sep')
4022 fm.plain(sep, label='grep.sep')
4094 if not opts.get('files_with_matches'):
4023 if not opts.get('files_with_matches'):
4095 fm.plain(sep, label='grep.sep')
4024 fm.plain(sep, label='grep.sep')
4096 if not opts.get('text') and binary():
4025 if not opts.get('text') and binary():
4097 fm.plain(_(" Binary file matches"))
4026 fm.plain(_(" Binary file matches"))
4098 else:
4027 else:
4099 displaymatches(fm.nested('texts'), l)
4028 displaymatches(fm.nested('texts'), l)
4100 fm.plain(eol)
4029 fm.plain(eol)
4101 found = True
4030 found = True
4102 if opts.get('files_with_matches'):
4031 if opts.get('files_with_matches'):
4103 break
4032 break
4104 return found
4033 return found
4105
4034
4106 def displaymatches(fm, l):
4035 def displaymatches(fm, l):
4107 p = 0
4036 p = 0
4108 for s, e in l.findpos():
4037 for s, e in l.findpos():
4109 if p < s:
4038 if p < s:
4110 fm.startitem()
4039 fm.startitem()
4111 fm.write('text', '%s', l.line[p:s])
4040 fm.write('text', '%s', l.line[p:s])
4112 fm.data(matched=False)
4041 fm.data(matched=False)
4113 fm.startitem()
4042 fm.startitem()
4114 fm.write('text', '%s', l.line[s:e], label='grep.match')
4043 fm.write('text', '%s', l.line[s:e], label='grep.match')
4115 fm.data(matched=True)
4044 fm.data(matched=True)
4116 p = e
4045 p = e
4117 if p < len(l.line):
4046 if p < len(l.line):
4118 fm.startitem()
4047 fm.startitem()
4119 fm.write('text', '%s', l.line[p:])
4048 fm.write('text', '%s', l.line[p:])
4120 fm.data(matched=False)
4049 fm.data(matched=False)
4121 fm.end()
4050 fm.end()
4122
4051
4123 skip = {}
4052 skip = {}
4124 revfiles = {}
4053 revfiles = {}
4125 matchfn = scmutil.match(repo[None], pats, opts)
4054 matchfn = scmutil.match(repo[None], pats, opts)
4126 found = False
4055 found = False
4127 follow = opts.get('follow')
4056 follow = opts.get('follow')
4128
4057
4129 def prep(ctx, fns):
4058 def prep(ctx, fns):
4130 rev = ctx.rev()
4059 rev = ctx.rev()
4131 pctx = ctx.p1()
4060 pctx = ctx.p1()
4132 parent = pctx.rev()
4061 parent = pctx.rev()
4133 matches.setdefault(rev, {})
4062 matches.setdefault(rev, {})
4134 matches.setdefault(parent, {})
4063 matches.setdefault(parent, {})
4135 files = revfiles.setdefault(rev, [])
4064 files = revfiles.setdefault(rev, [])
4136 for fn in fns:
4065 for fn in fns:
4137 flog = getfile(fn)
4066 flog = getfile(fn)
4138 try:
4067 try:
4139 fnode = ctx.filenode(fn)
4068 fnode = ctx.filenode(fn)
4140 except error.LookupError:
4069 except error.LookupError:
4141 continue
4070 continue
4142
4071
4143 copied = flog.renamed(fnode)
4072 copied = flog.renamed(fnode)
4144 copy = follow and copied and copied[0]
4073 copy = follow and copied and copied[0]
4145 if copy:
4074 if copy:
4146 copies.setdefault(rev, {})[fn] = copy
4075 copies.setdefault(rev, {})[fn] = copy
4147 if fn in skip:
4076 if fn in skip:
4148 if copy:
4077 if copy:
4149 skip[copy] = True
4078 skip[copy] = True
4150 continue
4079 continue
4151 files.append(fn)
4080 files.append(fn)
4152
4081
4153 if fn not in matches[rev]:
4082 if fn not in matches[rev]:
4154 grepbody(fn, rev, flog.read(fnode))
4083 grepbody(fn, rev, flog.read(fnode))
4155
4084
4156 pfn = copy or fn
4085 pfn = copy or fn
4157 if pfn not in matches[parent]:
4086 if pfn not in matches[parent]:
4158 try:
4087 try:
4159 fnode = pctx.filenode(pfn)
4088 fnode = pctx.filenode(pfn)
4160 grepbody(pfn, parent, flog.read(fnode))
4089 grepbody(pfn, parent, flog.read(fnode))
4161 except error.LookupError:
4090 except error.LookupError:
4162 pass
4091 pass
4163
4092
4164 fm = ui.formatter('grep', opts)
4093 fm = ui.formatter('grep', opts)
4165 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4094 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4166 rev = ctx.rev()
4095 rev = ctx.rev()
4167 parent = ctx.p1().rev()
4096 parent = ctx.p1().rev()
4168 for fn in sorted(revfiles.get(rev, [])):
4097 for fn in sorted(revfiles.get(rev, [])):
4169 states = matches[rev][fn]
4098 states = matches[rev][fn]
4170 copy = copies.get(rev, {}).get(fn)
4099 copy = copies.get(rev, {}).get(fn)
4171 if fn in skip:
4100 if fn in skip:
4172 if copy:
4101 if copy:
4173 skip[copy] = True
4102 skip[copy] = True
4174 continue
4103 continue
4175 pstates = matches.get(parent, {}).get(copy or fn, [])
4104 pstates = matches.get(parent, {}).get(copy or fn, [])
4176 if pstates or states:
4105 if pstates or states:
4177 r = display(fm, fn, ctx, pstates, states)
4106 r = display(fm, fn, ctx, pstates, states)
4178 found = found or r
4107 found = found or r
4179 if r and not opts.get('all'):
4108 if r and not opts.get('all'):
4180 skip[fn] = True
4109 skip[fn] = True
4181 if copy:
4110 if copy:
4182 skip[copy] = True
4111 skip[copy] = True
4183 del matches[rev]
4112 del matches[rev]
4184 del revfiles[rev]
4113 del revfiles[rev]
4185 fm.end()
4114 fm.end()
4186
4115
4187 return not found
4116 return not found
4188
4117
4189 @command('heads',
4118 @command('heads',
4190 [('r', 'rev', '',
4119 [('r', 'rev', '',
4191 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4120 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4192 ('t', 'topo', False, _('show topological heads only')),
4121 ('t', 'topo', False, _('show topological heads only')),
4193 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4122 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4194 ('c', 'closed', False, _('show normal and closed branch heads')),
4123 ('c', 'closed', False, _('show normal and closed branch heads')),
4195 ] + templateopts,
4124 ] + templateopts,
4196 _('[-ct] [-r STARTREV] [REV]...'))
4125 _('[-ct] [-r STARTREV] [REV]...'))
4197 def heads(ui, repo, *branchrevs, **opts):
4126 def heads(ui, repo, *branchrevs, **opts):
4198 """show branch heads
4127 """show branch heads
4199
4128
4200 With no arguments, show all open branch heads in the repository.
4129 With no arguments, show all open branch heads in the repository.
4201 Branch heads are changesets that have no descendants on the
4130 Branch heads are changesets that have no descendants on the
4202 same branch. They are where development generally takes place and
4131 same branch. They are where development generally takes place and
4203 are the usual targets for update and merge operations.
4132 are the usual targets for update and merge operations.
4204
4133
4205 If one or more REVs are given, only open branch heads on the
4134 If one or more REVs are given, only open branch heads on the
4206 branches associated with the specified changesets are shown. This
4135 branches associated with the specified changesets are shown. This
4207 means that you can use :hg:`heads .` to see the heads on the
4136 means that you can use :hg:`heads .` to see the heads on the
4208 currently checked-out branch.
4137 currently checked-out branch.
4209
4138
4210 If -c/--closed is specified, also show branch heads marked closed
4139 If -c/--closed is specified, also show branch heads marked closed
4211 (see :hg:`commit --close-branch`).
4140 (see :hg:`commit --close-branch`).
4212
4141
4213 If STARTREV is specified, only those heads that are descendants of
4142 If STARTREV is specified, only those heads that are descendants of
4214 STARTREV will be displayed.
4143 STARTREV will be displayed.
4215
4144
4216 If -t/--topo is specified, named branch mechanics will be ignored and only
4145 If -t/--topo is specified, named branch mechanics will be ignored and only
4217 topological heads (changesets with no children) will be shown.
4146 topological heads (changesets with no children) will be shown.
4218
4147
4219 Returns 0 if matching heads are found, 1 if not.
4148 Returns 0 if matching heads are found, 1 if not.
4220 """
4149 """
4221
4150
4222 start = None
4151 start = None
4223 if 'rev' in opts:
4152 if 'rev' in opts:
4224 start = scmutil.revsingle(repo, opts['rev'], None).node()
4153 start = scmutil.revsingle(repo, opts['rev'], None).node()
4225
4154
4226 if opts.get('topo'):
4155 if opts.get('topo'):
4227 heads = [repo[h] for h in repo.heads(start)]
4156 heads = [repo[h] for h in repo.heads(start)]
4228 else:
4157 else:
4229 heads = []
4158 heads = []
4230 for branch in repo.branchmap():
4159 for branch in repo.branchmap():
4231 heads += repo.branchheads(branch, start, opts.get('closed'))
4160 heads += repo.branchheads(branch, start, opts.get('closed'))
4232 heads = [repo[h] for h in heads]
4161 heads = [repo[h] for h in heads]
4233
4162
4234 if branchrevs:
4163 if branchrevs:
4235 branches = set(repo[br].branch() for br in branchrevs)
4164 branches = set(repo[br].branch() for br in branchrevs)
4236 heads = [h for h in heads if h.branch() in branches]
4165 heads = [h for h in heads if h.branch() in branches]
4237
4166
4238 if opts.get('active') and branchrevs:
4167 if opts.get('active') and branchrevs:
4239 dagheads = repo.heads(start)
4168 dagheads = repo.heads(start)
4240 heads = [h for h in heads if h.node() in dagheads]
4169 heads = [h for h in heads if h.node() in dagheads]
4241
4170
4242 if branchrevs:
4171 if branchrevs:
4243 haveheads = set(h.branch() for h in heads)
4172 haveheads = set(h.branch() for h in heads)
4244 if branches - haveheads:
4173 if branches - haveheads:
4245 headless = ', '.join(b for b in branches - haveheads)
4174 headless = ', '.join(b for b in branches - haveheads)
4246 msg = _('no open branch heads found on branches %s')
4175 msg = _('no open branch heads found on branches %s')
4247 if opts.get('rev'):
4176 if opts.get('rev'):
4248 msg += _(' (started at %s)') % opts['rev']
4177 msg += _(' (started at %s)') % opts['rev']
4249 ui.warn((msg + '\n') % headless)
4178 ui.warn((msg + '\n') % headless)
4250
4179
4251 if not heads:
4180 if not heads:
4252 return 1
4181 return 1
4253
4182
4254 heads = sorted(heads, key=lambda x: -x.rev())
4183 heads = sorted(heads, key=lambda x: -x.rev())
4255 displayer = cmdutil.show_changeset(ui, repo, opts)
4184 displayer = cmdutil.show_changeset(ui, repo, opts)
4256 for ctx in heads:
4185 for ctx in heads:
4257 displayer.show(ctx)
4186 displayer.show(ctx)
4258 displayer.close()
4187 displayer.close()
4259
4188
4260 @command('help',
4189 @command('help',
4261 [('e', 'extension', None, _('show only help for extensions')),
4190 [('e', 'extension', None, _('show only help for extensions')),
4262 ('c', 'command', None, _('show only help for commands')),
4191 ('c', 'command', None, _('show only help for commands')),
4263 ('k', 'keyword', None, _('show topics matching keyword')),
4192 ('k', 'keyword', None, _('show topics matching keyword')),
4264 ('s', 'system', [], _('show help for specific platform(s)')),
4193 ('s', 'system', [], _('show help for specific platform(s)')),
4265 ],
4194 ],
4266 _('[-ecks] [TOPIC]'),
4195 _('[-ecks] [TOPIC]'),
4267 norepo=True)
4196 norepo=True)
4268 def help_(ui, name=None, **opts):
4197 def help_(ui, name=None, **opts):
4269 """show help for a given topic or a help overview
4198 """show help for a given topic or a help overview
4270
4199
4271 With no arguments, print a list of commands with short help messages.
4200 With no arguments, print a list of commands with short help messages.
4272
4201
4273 Given a topic, extension, or command name, print help for that
4202 Given a topic, extension, or command name, print help for that
4274 topic.
4203 topic.
4275
4204
4276 Returns 0 if successful.
4205 Returns 0 if successful.
4277 """
4206 """
4278
4207
4279 textwidth = ui.configint('ui', 'textwidth', 78)
4208 textwidth = ui.configint('ui', 'textwidth', 78)
4280 termwidth = ui.termwidth() - 2
4209 termwidth = ui.termwidth() - 2
4281 if textwidth <= 0 or termwidth < textwidth:
4210 if textwidth <= 0 or termwidth < textwidth:
4282 textwidth = termwidth
4211 textwidth = termwidth
4283
4212
4284 keep = opts.get('system') or []
4213 keep = opts.get('system') or []
4285 if len(keep) == 0:
4214 if len(keep) == 0:
4286 if sys.platform.startswith('win'):
4215 if sys.platform.startswith('win'):
4287 keep.append('windows')
4216 keep.append('windows')
4288 elif sys.platform == 'OpenVMS':
4217 elif sys.platform == 'OpenVMS':
4289 keep.append('vms')
4218 keep.append('vms')
4290 elif sys.platform == 'plan9':
4219 elif sys.platform == 'plan9':
4291 keep.append('plan9')
4220 keep.append('plan9')
4292 else:
4221 else:
4293 keep.append('unix')
4222 keep.append('unix')
4294 keep.append(sys.platform.lower())
4223 keep.append(sys.platform.lower())
4295 if ui.verbose:
4224 if ui.verbose:
4296 keep.append('verbose')
4225 keep.append('verbose')
4297
4226
4298 section = None
4227 section = None
4299 subtopic = None
4228 subtopic = None
4300 if name and '.' in name:
4229 if name and '.' in name:
4301 name, remaining = name.split('.', 1)
4230 name, remaining = name.split('.', 1)
4302 remaining = encoding.lower(remaining)
4231 remaining = encoding.lower(remaining)
4303 if '.' in remaining:
4232 if '.' in remaining:
4304 subtopic, section = remaining.split('.', 1)
4233 subtopic, section = remaining.split('.', 1)
4305 else:
4234 else:
4306 if name in help.subtopics:
4235 if name in help.subtopics:
4307 subtopic = remaining
4236 subtopic = remaining
4308 else:
4237 else:
4309 section = remaining
4238 section = remaining
4310
4239
4311 text = help.help_(ui, name, subtopic=subtopic, **opts)
4240 text = help.help_(ui, name, subtopic=subtopic, **opts)
4312
4241
4313 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4242 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4314 section=section)
4243 section=section)
4315
4244
4316 # We could have been given a weird ".foo" section without a name
4245 # We could have been given a weird ".foo" section without a name
4317 # to look for, or we could have simply failed to found "foo.bar"
4246 # to look for, or we could have simply failed to found "foo.bar"
4318 # because bar isn't a section of foo
4247 # because bar isn't a section of foo
4319 if section and not (formatted and name):
4248 if section and not (formatted and name):
4320 raise error.Abort(_("help section not found"))
4249 raise error.Abort(_("help section not found"))
4321
4250
4322 if 'verbose' in pruned:
4251 if 'verbose' in pruned:
4323 keep.append('omitted')
4252 keep.append('omitted')
4324 else:
4253 else:
4325 keep.append('notomitted')
4254 keep.append('notomitted')
4326 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4255 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4327 section=section)
4256 section=section)
4328 ui.write(formatted)
4257 ui.write(formatted)
4329
4258
4330
4259
4331 @command('identify|id',
4260 @command('identify|id',
4332 [('r', 'rev', '',
4261 [('r', 'rev', '',
4333 _('identify the specified revision'), _('REV')),
4262 _('identify the specified revision'), _('REV')),
4334 ('n', 'num', None, _('show local revision number')),
4263 ('n', 'num', None, _('show local revision number')),
4335 ('i', 'id', None, _('show global revision id')),
4264 ('i', 'id', None, _('show global revision id')),
4336 ('b', 'branch', None, _('show branch')),
4265 ('b', 'branch', None, _('show branch')),
4337 ('t', 'tags', None, _('show tags')),
4266 ('t', 'tags', None, _('show tags')),
4338 ('B', 'bookmarks', None, _('show bookmarks')),
4267 ('B', 'bookmarks', None, _('show bookmarks')),
4339 ] + remoteopts,
4268 ] + remoteopts,
4340 _('[-nibtB] [-r REV] [SOURCE]'),
4269 _('[-nibtB] [-r REV] [SOURCE]'),
4341 optionalrepo=True)
4270 optionalrepo=True)
4342 def identify(ui, repo, source=None, rev=None,
4271 def identify(ui, repo, source=None, rev=None,
4343 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4272 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4344 """identify the working directory or specified revision
4273 """identify the working directory or specified revision
4345
4274
4346 Print a summary identifying the repository state at REV using one or
4275 Print a summary identifying the repository state at REV using one or
4347 two parent hash identifiers, followed by a "+" if the working
4276 two parent hash identifiers, followed by a "+" if the working
4348 directory has uncommitted changes, the branch name (if not default),
4277 directory has uncommitted changes, the branch name (if not default),
4349 a list of tags, and a list of bookmarks.
4278 a list of tags, and a list of bookmarks.
4350
4279
4351 When REV is not given, print a summary of the current state of the
4280 When REV is not given, print a summary of the current state of the
4352 repository.
4281 repository.
4353
4282
4354 Specifying a path to a repository root or Mercurial bundle will
4283 Specifying a path to a repository root or Mercurial bundle will
4355 cause lookup to operate on that repository/bundle.
4284 cause lookup to operate on that repository/bundle.
4356
4285
4357 .. container:: verbose
4286 .. container:: verbose
4358
4287
4359 Examples:
4288 Examples:
4360
4289
4361 - generate a build identifier for the working directory::
4290 - generate a build identifier for the working directory::
4362
4291
4363 hg id --id > build-id.dat
4292 hg id --id > build-id.dat
4364
4293
4365 - find the revision corresponding to a tag::
4294 - find the revision corresponding to a tag::
4366
4295
4367 hg id -n -r 1.3
4296 hg id -n -r 1.3
4368
4297
4369 - check the most recent revision of a remote repository::
4298 - check the most recent revision of a remote repository::
4370
4299
4371 hg id -r tip https://www.mercurial-scm.org/repo/hg/
4300 hg id -r tip https://www.mercurial-scm.org/repo/hg/
4372
4301
4373 See :hg:`log` for generating more information about specific revisions,
4302 See :hg:`log` for generating more information about specific revisions,
4374 including full hash identifiers.
4303 including full hash identifiers.
4375
4304
4376 Returns 0 if successful.
4305 Returns 0 if successful.
4377 """
4306 """
4378
4307
4379 if not repo and not source:
4308 if not repo and not source:
4380 raise error.Abort(_("there is no Mercurial repository here "
4309 raise error.Abort(_("there is no Mercurial repository here "
4381 "(.hg not found)"))
4310 "(.hg not found)"))
4382
4311
4383 if ui.debugflag:
4312 if ui.debugflag:
4384 hexfunc = hex
4313 hexfunc = hex
4385 else:
4314 else:
4386 hexfunc = short
4315 hexfunc = short
4387 default = not (num or id or branch or tags or bookmarks)
4316 default = not (num or id or branch or tags or bookmarks)
4388 output = []
4317 output = []
4389 revs = []
4318 revs = []
4390
4319
4391 if source:
4320 if source:
4392 source, branches = hg.parseurl(ui.expandpath(source))
4321 source, branches = hg.parseurl(ui.expandpath(source))
4393 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4322 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4394 repo = peer.local()
4323 repo = peer.local()
4395 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4324 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4396
4325
4397 if not repo:
4326 if not repo:
4398 if num or branch or tags:
4327 if num or branch or tags:
4399 raise error.Abort(
4328 raise error.Abort(
4400 _("can't query remote revision number, branch, or tags"))
4329 _("can't query remote revision number, branch, or tags"))
4401 if not rev and revs:
4330 if not rev and revs:
4402 rev = revs[0]
4331 rev = revs[0]
4403 if not rev:
4332 if not rev:
4404 rev = "tip"
4333 rev = "tip"
4405
4334
4406 remoterev = peer.lookup(rev)
4335 remoterev = peer.lookup(rev)
4407 if default or id:
4336 if default or id:
4408 output = [hexfunc(remoterev)]
4337 output = [hexfunc(remoterev)]
4409
4338
4410 def getbms():
4339 def getbms():
4411 bms = []
4340 bms = []
4412
4341
4413 if 'bookmarks' in peer.listkeys('namespaces'):
4342 if 'bookmarks' in peer.listkeys('namespaces'):
4414 hexremoterev = hex(remoterev)
4343 hexremoterev = hex(remoterev)
4415 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4344 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4416 if bmr == hexremoterev]
4345 if bmr == hexremoterev]
4417
4346
4418 return sorted(bms)
4347 return sorted(bms)
4419
4348
4420 if bookmarks:
4349 if bookmarks:
4421 output.extend(getbms())
4350 output.extend(getbms())
4422 elif default and not ui.quiet:
4351 elif default and not ui.quiet:
4423 # multiple bookmarks for a single parent separated by '/'
4352 # multiple bookmarks for a single parent separated by '/'
4424 bm = '/'.join(getbms())
4353 bm = '/'.join(getbms())
4425 if bm:
4354 if bm:
4426 output.append(bm)
4355 output.append(bm)
4427 else:
4356 else:
4428 ctx = scmutil.revsingle(repo, rev, None)
4357 ctx = scmutil.revsingle(repo, rev, None)
4429
4358
4430 if ctx.rev() is None:
4359 if ctx.rev() is None:
4431 ctx = repo[None]
4360 ctx = repo[None]
4432 parents = ctx.parents()
4361 parents = ctx.parents()
4433 taglist = []
4362 taglist = []
4434 for p in parents:
4363 for p in parents:
4435 taglist.extend(p.tags())
4364 taglist.extend(p.tags())
4436
4365
4437 changed = ""
4366 changed = ""
4438 if default or id or num:
4367 if default or id or num:
4439 if (any(repo.status())
4368 if (any(repo.status())
4440 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4369 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4441 changed = '+'
4370 changed = '+'
4442 if default or id:
4371 if default or id:
4443 output = ["%s%s" %
4372 output = ["%s%s" %
4444 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4373 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4445 if num:
4374 if num:
4446 output.append("%s%s" %
4375 output.append("%s%s" %
4447 ('+'.join([str(p.rev()) for p in parents]), changed))
4376 ('+'.join([str(p.rev()) for p in parents]), changed))
4448 else:
4377 else:
4449 if default or id:
4378 if default or id:
4450 output = [hexfunc(ctx.node())]
4379 output = [hexfunc(ctx.node())]
4451 if num:
4380 if num:
4452 output.append(str(ctx.rev()))
4381 output.append(str(ctx.rev()))
4453 taglist = ctx.tags()
4382 taglist = ctx.tags()
4454
4383
4455 if default and not ui.quiet:
4384 if default and not ui.quiet:
4456 b = ctx.branch()
4385 b = ctx.branch()
4457 if b != 'default':
4386 if b != 'default':
4458 output.append("(%s)" % b)
4387 output.append("(%s)" % b)
4459
4388
4460 # multiple tags for a single parent separated by '/'
4389 # multiple tags for a single parent separated by '/'
4461 t = '/'.join(taglist)
4390 t = '/'.join(taglist)
4462 if t:
4391 if t:
4463 output.append(t)
4392 output.append(t)
4464
4393
4465 # multiple bookmarks for a single parent separated by '/'
4394 # multiple bookmarks for a single parent separated by '/'
4466 bm = '/'.join(ctx.bookmarks())
4395 bm = '/'.join(ctx.bookmarks())
4467 if bm:
4396 if bm:
4468 output.append(bm)
4397 output.append(bm)
4469 else:
4398 else:
4470 if branch:
4399 if branch:
4471 output.append(ctx.branch())
4400 output.append(ctx.branch())
4472
4401
4473 if tags:
4402 if tags:
4474 output.extend(taglist)
4403 output.extend(taglist)
4475
4404
4476 if bookmarks:
4405 if bookmarks:
4477 output.extend(ctx.bookmarks())
4406 output.extend(ctx.bookmarks())
4478
4407
4479 ui.write("%s\n" % ' '.join(output))
4408 ui.write("%s\n" % ' '.join(output))
4480
4409
4481 @command('import|patch',
4410 @command('import|patch',
4482 [('p', 'strip', 1,
4411 [('p', 'strip', 1,
4483 _('directory strip option for patch. This has the same '
4412 _('directory strip option for patch. This has the same '
4484 'meaning as the corresponding patch option'), _('NUM')),
4413 'meaning as the corresponding patch option'), _('NUM')),
4485 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4414 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4486 ('e', 'edit', False, _('invoke editor on commit messages')),
4415 ('e', 'edit', False, _('invoke editor on commit messages')),
4487 ('f', 'force', None,
4416 ('f', 'force', None,
4488 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4417 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4489 ('', 'no-commit', None,
4418 ('', 'no-commit', None,
4490 _("don't commit, just update the working directory")),
4419 _("don't commit, just update the working directory")),
4491 ('', 'bypass', None,
4420 ('', 'bypass', None,
4492 _("apply patch without touching the working directory")),
4421 _("apply patch without touching the working directory")),
4493 ('', 'partial', None,
4422 ('', 'partial', None,
4494 _('commit even if some hunks fail')),
4423 _('commit even if some hunks fail')),
4495 ('', 'exact', None,
4424 ('', 'exact', None,
4496 _('abort if patch would apply lossily')),
4425 _('abort if patch would apply lossily')),
4497 ('', 'prefix', '',
4426 ('', 'prefix', '',
4498 _('apply patch to subdirectory'), _('DIR')),
4427 _('apply patch to subdirectory'), _('DIR')),
4499 ('', 'import-branch', None,
4428 ('', 'import-branch', None,
4500 _('use any branch information in patch (implied by --exact)'))] +
4429 _('use any branch information in patch (implied by --exact)'))] +
4501 commitopts + commitopts2 + similarityopts,
4430 commitopts + commitopts2 + similarityopts,
4502 _('[OPTION]... PATCH...'))
4431 _('[OPTION]... PATCH...'))
4503 def import_(ui, repo, patch1=None, *patches, **opts):
4432 def import_(ui, repo, patch1=None, *patches, **opts):
4504 """import an ordered set of patches
4433 """import an ordered set of patches
4505
4434
4506 Import a list of patches and commit them individually (unless
4435 Import a list of patches and commit them individually (unless
4507 --no-commit is specified).
4436 --no-commit is specified).
4508
4437
4509 To read a patch from standard input, use "-" as the patch name. If
4438 To read a patch from standard input, use "-" as the patch name. If
4510 a URL is specified, the patch will be downloaded from there.
4439 a URL is specified, the patch will be downloaded from there.
4511
4440
4512 Import first applies changes to the working directory (unless
4441 Import first applies changes to the working directory (unless
4513 --bypass is specified), import will abort if there are outstanding
4442 --bypass is specified), import will abort if there are outstanding
4514 changes.
4443 changes.
4515
4444
4516 Use --bypass to apply and commit patches directly to the
4445 Use --bypass to apply and commit patches directly to the
4517 repository, without affecting the working directory. Without
4446 repository, without affecting the working directory. Without
4518 --exact, patches will be applied on top of the working directory
4447 --exact, patches will be applied on top of the working directory
4519 parent revision.
4448 parent revision.
4520
4449
4521 You can import a patch straight from a mail message. Even patches
4450 You can import a patch straight from a mail message. Even patches
4522 as attachments work (to use the body part, it must have type
4451 as attachments work (to use the body part, it must have type
4523 text/plain or text/x-patch). From and Subject headers of email
4452 text/plain or text/x-patch). From and Subject headers of email
4524 message are used as default committer and commit message. All
4453 message are used as default committer and commit message. All
4525 text/plain body parts before first diff are added to the commit
4454 text/plain body parts before first diff are added to the commit
4526 message.
4455 message.
4527
4456
4528 If the imported patch was generated by :hg:`export`, user and
4457 If the imported patch was generated by :hg:`export`, user and
4529 description from patch override values from message headers and
4458 description from patch override values from message headers and
4530 body. Values given on command line with -m/--message and -u/--user
4459 body. Values given on command line with -m/--message and -u/--user
4531 override these.
4460 override these.
4532
4461
4533 If --exact is specified, import will set the working directory to
4462 If --exact is specified, import will set the working directory to
4534 the parent of each patch before applying it, and will abort if the
4463 the parent of each patch before applying it, and will abort if the
4535 resulting changeset has a different ID than the one recorded in
4464 resulting changeset has a different ID than the one recorded in
4536 the patch. This will guard against various ways that portable
4465 the patch. This will guard against various ways that portable
4537 patch formats and mail systems might fail to transfer Mercurial
4466 patch formats and mail systems might fail to transfer Mercurial
4538 data or metadata. See :hg:`bundle` for lossless transmission.
4467 data or metadata. See :hg:`bundle` for lossless transmission.
4539
4468
4540 Use --partial to ensure a changeset will be created from the patch
4469 Use --partial to ensure a changeset will be created from the patch
4541 even if some hunks fail to apply. Hunks that fail to apply will be
4470 even if some hunks fail to apply. Hunks that fail to apply will be
4542 written to a <target-file>.rej file. Conflicts can then be resolved
4471 written to a <target-file>.rej file. Conflicts can then be resolved
4543 by hand before :hg:`commit --amend` is run to update the created
4472 by hand before :hg:`commit --amend` is run to update the created
4544 changeset. This flag exists to let people import patches that
4473 changeset. This flag exists to let people import patches that
4545 partially apply without losing the associated metadata (author,
4474 partially apply without losing the associated metadata (author,
4546 date, description, ...).
4475 date, description, ...).
4547
4476
4548 .. note::
4477 .. note::
4549
4478
4550 When no hunks apply cleanly, :hg:`import --partial` will create
4479 When no hunks apply cleanly, :hg:`import --partial` will create
4551 an empty changeset, importing only the patch metadata.
4480 an empty changeset, importing only the patch metadata.
4552
4481
4553 With -s/--similarity, hg will attempt to discover renames and
4482 With -s/--similarity, hg will attempt to discover renames and
4554 copies in the patch in the same way as :hg:`addremove`.
4483 copies in the patch in the same way as :hg:`addremove`.
4555
4484
4556 It is possible to use external patch programs to perform the patch
4485 It is possible to use external patch programs to perform the patch
4557 by setting the ``ui.patch`` configuration option. For the default
4486 by setting the ``ui.patch`` configuration option. For the default
4558 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4487 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4559 See :hg:`help config` for more information about configuration
4488 See :hg:`help config` for more information about configuration
4560 files and how to use these options.
4489 files and how to use these options.
4561
4490
4562 See :hg:`help dates` for a list of formats valid for -d/--date.
4491 See :hg:`help dates` for a list of formats valid for -d/--date.
4563
4492
4564 .. container:: verbose
4493 .. container:: verbose
4565
4494
4566 Examples:
4495 Examples:
4567
4496
4568 - import a traditional patch from a website and detect renames::
4497 - import a traditional patch from a website and detect renames::
4569
4498
4570 hg import -s 80 http://example.com/bugfix.patch
4499 hg import -s 80 http://example.com/bugfix.patch
4571
4500
4572 - import a changeset from an hgweb server::
4501 - import a changeset from an hgweb server::
4573
4502
4574 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4503 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4575
4504
4576 - import all the patches in an Unix-style mbox::
4505 - import all the patches in an Unix-style mbox::
4577
4506
4578 hg import incoming-patches.mbox
4507 hg import incoming-patches.mbox
4579
4508
4580 - attempt to exactly restore an exported changeset (not always
4509 - attempt to exactly restore an exported changeset (not always
4581 possible)::
4510 possible)::
4582
4511
4583 hg import --exact proposed-fix.patch
4512 hg import --exact proposed-fix.patch
4584
4513
4585 - use an external tool to apply a patch which is too fuzzy for
4514 - use an external tool to apply a patch which is too fuzzy for
4586 the default internal tool.
4515 the default internal tool.
4587
4516
4588 hg import --config ui.patch="patch --merge" fuzzy.patch
4517 hg import --config ui.patch="patch --merge" fuzzy.patch
4589
4518
4590 - change the default fuzzing from 2 to a less strict 7
4519 - change the default fuzzing from 2 to a less strict 7
4591
4520
4592 hg import --config ui.fuzz=7 fuzz.patch
4521 hg import --config ui.fuzz=7 fuzz.patch
4593
4522
4594 Returns 0 on success, 1 on partial success (see --partial).
4523 Returns 0 on success, 1 on partial success (see --partial).
4595 """
4524 """
4596
4525
4597 if not patch1:
4526 if not patch1:
4598 raise error.Abort(_('need at least one patch to import'))
4527 raise error.Abort(_('need at least one patch to import'))
4599
4528
4600 patches = (patch1,) + patches
4529 patches = (patch1,) + patches
4601
4530
4602 date = opts.get('date')
4531 date = opts.get('date')
4603 if date:
4532 if date:
4604 opts['date'] = util.parsedate(date)
4533 opts['date'] = util.parsedate(date)
4605
4534
4606 exact = opts.get('exact')
4535 exact = opts.get('exact')
4607 update = not opts.get('bypass')
4536 update = not opts.get('bypass')
4608 if not update and opts.get('no_commit'):
4537 if not update and opts.get('no_commit'):
4609 raise error.Abort(_('cannot use --no-commit with --bypass'))
4538 raise error.Abort(_('cannot use --no-commit with --bypass'))
4610 try:
4539 try:
4611 sim = float(opts.get('similarity') or 0)
4540 sim = float(opts.get('similarity') or 0)
4612 except ValueError:
4541 except ValueError:
4613 raise error.Abort(_('similarity must be a number'))
4542 raise error.Abort(_('similarity must be a number'))
4614 if sim < 0 or sim > 100:
4543 if sim < 0 or sim > 100:
4615 raise error.Abort(_('similarity must be between 0 and 100'))
4544 raise error.Abort(_('similarity must be between 0 and 100'))
4616 if sim and not update:
4545 if sim and not update:
4617 raise error.Abort(_('cannot use --similarity with --bypass'))
4546 raise error.Abort(_('cannot use --similarity with --bypass'))
4618 if exact:
4547 if exact:
4619 if opts.get('edit'):
4548 if opts.get('edit'):
4620 raise error.Abort(_('cannot use --exact with --edit'))
4549 raise error.Abort(_('cannot use --exact with --edit'))
4621 if opts.get('prefix'):
4550 if opts.get('prefix'):
4622 raise error.Abort(_('cannot use --exact with --prefix'))
4551 raise error.Abort(_('cannot use --exact with --prefix'))
4623
4552
4624 base = opts["base"]
4553 base = opts["base"]
4625 wlock = dsguard = lock = tr = None
4554 wlock = dsguard = lock = tr = None
4626 msgs = []
4555 msgs = []
4627 ret = 0
4556 ret = 0
4628
4557
4629
4558
4630 try:
4559 try:
4631 wlock = repo.wlock()
4560 wlock = repo.wlock()
4632
4561
4633 if update:
4562 if update:
4634 cmdutil.checkunfinished(repo)
4563 cmdutil.checkunfinished(repo)
4635 if (exact or not opts.get('force')):
4564 if (exact or not opts.get('force')):
4636 cmdutil.bailifchanged(repo)
4565 cmdutil.bailifchanged(repo)
4637
4566
4638 if not opts.get('no_commit'):
4567 if not opts.get('no_commit'):
4639 lock = repo.lock()
4568 lock = repo.lock()
4640 tr = repo.transaction('import')
4569 tr = repo.transaction('import')
4641 else:
4570 else:
4642 dsguard = dirstateguard.dirstateguard(repo, 'import')
4571 dsguard = dirstateguard.dirstateguard(repo, 'import')
4643 parents = repo[None].parents()
4572 parents = repo[None].parents()
4644 for patchurl in patches:
4573 for patchurl in patches:
4645 if patchurl == '-':
4574 if patchurl == '-':
4646 ui.status(_('applying patch from stdin\n'))
4575 ui.status(_('applying patch from stdin\n'))
4647 patchfile = ui.fin
4576 patchfile = ui.fin
4648 patchurl = 'stdin' # for error message
4577 patchurl = 'stdin' # for error message
4649 else:
4578 else:
4650 patchurl = os.path.join(base, patchurl)
4579 patchurl = os.path.join(base, patchurl)
4651 ui.status(_('applying %s\n') % patchurl)
4580 ui.status(_('applying %s\n') % patchurl)
4652 patchfile = hg.openpath(ui, patchurl)
4581 patchfile = hg.openpath(ui, patchurl)
4653
4582
4654 haspatch = False
4583 haspatch = False
4655 for hunk in patch.split(patchfile):
4584 for hunk in patch.split(patchfile):
4656 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4585 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4657 parents, opts,
4586 parents, opts,
4658 msgs, hg.clean)
4587 msgs, hg.clean)
4659 if msg:
4588 if msg:
4660 haspatch = True
4589 haspatch = True
4661 ui.note(msg + '\n')
4590 ui.note(msg + '\n')
4662 if update or exact:
4591 if update or exact:
4663 parents = repo[None].parents()
4592 parents = repo[None].parents()
4664 else:
4593 else:
4665 parents = [repo[node]]
4594 parents = [repo[node]]
4666 if rej:
4595 if rej:
4667 ui.write_err(_("patch applied partially\n"))
4596 ui.write_err(_("patch applied partially\n"))
4668 ui.write_err(_("(fix the .rej files and run "
4597 ui.write_err(_("(fix the .rej files and run "
4669 "`hg commit --amend`)\n"))
4598 "`hg commit --amend`)\n"))
4670 ret = 1
4599 ret = 1
4671 break
4600 break
4672
4601
4673 if not haspatch:
4602 if not haspatch:
4674 raise error.Abort(_('%s: no diffs found') % patchurl)
4603 raise error.Abort(_('%s: no diffs found') % patchurl)
4675
4604
4676 if tr:
4605 if tr:
4677 tr.close()
4606 tr.close()
4678 if msgs:
4607 if msgs:
4679 repo.savecommitmessage('\n* * *\n'.join(msgs))
4608 repo.savecommitmessage('\n* * *\n'.join(msgs))
4680 if dsguard:
4609 if dsguard:
4681 dsguard.close()
4610 dsguard.close()
4682 return ret
4611 return ret
4683 finally:
4612 finally:
4684 if tr:
4613 if tr:
4685 tr.release()
4614 tr.release()
4686 release(lock, dsguard, wlock)
4615 release(lock, dsguard, wlock)
4687
4616
4688 @command('incoming|in',
4617 @command('incoming|in',
4689 [('f', 'force', None,
4618 [('f', 'force', None,
4690 _('run even if remote repository is unrelated')),
4619 _('run even if remote repository is unrelated')),
4691 ('n', 'newest-first', None, _('show newest record first')),
4620 ('n', 'newest-first', None, _('show newest record first')),
4692 ('', 'bundle', '',
4621 ('', 'bundle', '',
4693 _('file to store the bundles into'), _('FILE')),
4622 _('file to store the bundles into'), _('FILE')),
4694 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4623 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4695 ('B', 'bookmarks', False, _("compare bookmarks")),
4624 ('B', 'bookmarks', False, _("compare bookmarks")),
4696 ('b', 'branch', [],
4625 ('b', 'branch', [],
4697 _('a specific branch you would like to pull'), _('BRANCH')),
4626 _('a specific branch you would like to pull'), _('BRANCH')),
4698 ] + logopts + remoteopts + subrepoopts,
4627 ] + logopts + remoteopts + subrepoopts,
4699 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4628 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4700 def incoming(ui, repo, source="default", **opts):
4629 def incoming(ui, repo, source="default", **opts):
4701 """show new changesets found in source
4630 """show new changesets found in source
4702
4631
4703 Show new changesets found in the specified path/URL or the default
4632 Show new changesets found in the specified path/URL or the default
4704 pull location. These are the changesets that would have been pulled
4633 pull location. These are the changesets that would have been pulled
4705 if a pull at the time you issued this command.
4634 if a pull at the time you issued this command.
4706
4635
4707 See pull for valid source format details.
4636 See pull for valid source format details.
4708
4637
4709 .. container:: verbose
4638 .. container:: verbose
4710
4639
4711 With -B/--bookmarks, the result of bookmark comparison between
4640 With -B/--bookmarks, the result of bookmark comparison between
4712 local and remote repositories is displayed. With -v/--verbose,
4641 local and remote repositories is displayed. With -v/--verbose,
4713 status is also displayed for each bookmark like below::
4642 status is also displayed for each bookmark like below::
4714
4643
4715 BM1 01234567890a added
4644 BM1 01234567890a added
4716 BM2 1234567890ab advanced
4645 BM2 1234567890ab advanced
4717 BM3 234567890abc diverged
4646 BM3 234567890abc diverged
4718 BM4 34567890abcd changed
4647 BM4 34567890abcd changed
4719
4648
4720 The action taken locally when pulling depends on the
4649 The action taken locally when pulling depends on the
4721 status of each bookmark:
4650 status of each bookmark:
4722
4651
4723 :``added``: pull will create it
4652 :``added``: pull will create it
4724 :``advanced``: pull will update it
4653 :``advanced``: pull will update it
4725 :``diverged``: pull will create a divergent bookmark
4654 :``diverged``: pull will create a divergent bookmark
4726 :``changed``: result depends on remote changesets
4655 :``changed``: result depends on remote changesets
4727
4656
4728 From the point of view of pulling behavior, bookmark
4657 From the point of view of pulling behavior, bookmark
4729 existing only in the remote repository are treated as ``added``,
4658 existing only in the remote repository are treated as ``added``,
4730 even if it is in fact locally deleted.
4659 even if it is in fact locally deleted.
4731
4660
4732 .. container:: verbose
4661 .. container:: verbose
4733
4662
4734 For remote repository, using --bundle avoids downloading the
4663 For remote repository, using --bundle avoids downloading the
4735 changesets twice if the incoming is followed by a pull.
4664 changesets twice if the incoming is followed by a pull.
4736
4665
4737 Examples:
4666 Examples:
4738
4667
4739 - show incoming changes with patches and full description::
4668 - show incoming changes with patches and full description::
4740
4669
4741 hg incoming -vp
4670 hg incoming -vp
4742
4671
4743 - show incoming changes excluding merges, store a bundle::
4672 - show incoming changes excluding merges, store a bundle::
4744
4673
4745 hg in -vpM --bundle incoming.hg
4674 hg in -vpM --bundle incoming.hg
4746 hg pull incoming.hg
4675 hg pull incoming.hg
4747
4676
4748 - briefly list changes inside a bundle::
4677 - briefly list changes inside a bundle::
4749
4678
4750 hg in changes.hg -T "{desc|firstline}\\n"
4679 hg in changes.hg -T "{desc|firstline}\\n"
4751
4680
4752 Returns 0 if there are incoming changes, 1 otherwise.
4681 Returns 0 if there are incoming changes, 1 otherwise.
4753 """
4682 """
4754 if opts.get('graph'):
4683 if opts.get('graph'):
4755 cmdutil.checkunsupportedgraphflags([], opts)
4684 cmdutil.checkunsupportedgraphflags([], opts)
4756 def display(other, chlist, displayer):
4685 def display(other, chlist, displayer):
4757 revdag = cmdutil.graphrevs(other, chlist, opts)
4686 revdag = cmdutil.graphrevs(other, chlist, opts)
4758 cmdutil.displaygraph(ui, repo, revdag, displayer,
4687 cmdutil.displaygraph(ui, repo, revdag, displayer,
4759 graphmod.asciiedges)
4688 graphmod.asciiedges)
4760
4689
4761 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4690 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4762 return 0
4691 return 0
4763
4692
4764 if opts.get('bundle') and opts.get('subrepos'):
4693 if opts.get('bundle') and opts.get('subrepos'):
4765 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4694 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4766
4695
4767 if opts.get('bookmarks'):
4696 if opts.get('bookmarks'):
4768 source, branches = hg.parseurl(ui.expandpath(source),
4697 source, branches = hg.parseurl(ui.expandpath(source),
4769 opts.get('branch'))
4698 opts.get('branch'))
4770 other = hg.peer(repo, opts, source)
4699 other = hg.peer(repo, opts, source)
4771 if 'bookmarks' not in other.listkeys('namespaces'):
4700 if 'bookmarks' not in other.listkeys('namespaces'):
4772 ui.warn(_("remote doesn't support bookmarks\n"))
4701 ui.warn(_("remote doesn't support bookmarks\n"))
4773 return 0
4702 return 0
4774 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4703 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4775 return bookmarks.incoming(ui, repo, other)
4704 return bookmarks.incoming(ui, repo, other)
4776
4705
4777 repo._subtoppath = ui.expandpath(source)
4706 repo._subtoppath = ui.expandpath(source)
4778 try:
4707 try:
4779 return hg.incoming(ui, repo, source, opts)
4708 return hg.incoming(ui, repo, source, opts)
4780 finally:
4709 finally:
4781 del repo._subtoppath
4710 del repo._subtoppath
4782
4711
4783
4712
4784 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4713 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4785 norepo=True)
4714 norepo=True)
4786 def init(ui, dest=".", **opts):
4715 def init(ui, dest=".", **opts):
4787 """create a new repository in the given directory
4716 """create a new repository in the given directory
4788
4717
4789 Initialize a new repository in the given directory. If the given
4718 Initialize a new repository in the given directory. If the given
4790 directory does not exist, it will be created.
4719 directory does not exist, it will be created.
4791
4720
4792 If no directory is given, the current directory is used.
4721 If no directory is given, the current directory is used.
4793
4722
4794 It is possible to specify an ``ssh://`` URL as the destination.
4723 It is possible to specify an ``ssh://`` URL as the destination.
4795 See :hg:`help urls` for more information.
4724 See :hg:`help urls` for more information.
4796
4725
4797 Returns 0 on success.
4726 Returns 0 on success.
4798 """
4727 """
4799 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4728 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4800
4729
4801 @command('locate',
4730 @command('locate',
4802 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4731 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4803 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4732 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4804 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4733 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4805 ] + walkopts,
4734 ] + walkopts,
4806 _('[OPTION]... [PATTERN]...'))
4735 _('[OPTION]... [PATTERN]...'))
4807 def locate(ui, repo, *pats, **opts):
4736 def locate(ui, repo, *pats, **opts):
4808 """locate files matching specific patterns (DEPRECATED)
4737 """locate files matching specific patterns (DEPRECATED)
4809
4738
4810 Print files under Mercurial control in the working directory whose
4739 Print files under Mercurial control in the working directory whose
4811 names match the given patterns.
4740 names match the given patterns.
4812
4741
4813 By default, this command searches all directories in the working
4742 By default, this command searches all directories in the working
4814 directory. To search just the current directory and its
4743 directory. To search just the current directory and its
4815 subdirectories, use "--include .".
4744 subdirectories, use "--include .".
4816
4745
4817 If no patterns are given to match, this command prints the names
4746 If no patterns are given to match, this command prints the names
4818 of all files under Mercurial control in the working directory.
4747 of all files under Mercurial control in the working directory.
4819
4748
4820 If you want to feed the output of this command into the "xargs"
4749 If you want to feed the output of this command into the "xargs"
4821 command, use the -0 option to both this command and "xargs". This
4750 command, use the -0 option to both this command and "xargs". This
4822 will avoid the problem of "xargs" treating single filenames that
4751 will avoid the problem of "xargs" treating single filenames that
4823 contain whitespace as multiple filenames.
4752 contain whitespace as multiple filenames.
4824
4753
4825 See :hg:`help files` for a more versatile command.
4754 See :hg:`help files` for a more versatile command.
4826
4755
4827 Returns 0 if a match is found, 1 otherwise.
4756 Returns 0 if a match is found, 1 otherwise.
4828 """
4757 """
4829 if opts.get('print0'):
4758 if opts.get('print0'):
4830 end = '\0'
4759 end = '\0'
4831 else:
4760 else:
4832 end = '\n'
4761 end = '\n'
4833 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4762 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4834
4763
4835 ret = 1
4764 ret = 1
4836 ctx = repo[rev]
4765 ctx = repo[rev]
4837 m = scmutil.match(ctx, pats, opts, default='relglob',
4766 m = scmutil.match(ctx, pats, opts, default='relglob',
4838 badfn=lambda x, y: False)
4767 badfn=lambda x, y: False)
4839
4768
4840 for abs in ctx.matches(m):
4769 for abs in ctx.matches(m):
4841 if opts.get('fullpath'):
4770 if opts.get('fullpath'):
4842 ui.write(repo.wjoin(abs), end)
4771 ui.write(repo.wjoin(abs), end)
4843 else:
4772 else:
4844 ui.write(((pats and m.rel(abs)) or abs), end)
4773 ui.write(((pats and m.rel(abs)) or abs), end)
4845 ret = 0
4774 ret = 0
4846
4775
4847 return ret
4776 return ret
4848
4777
4849 @command('^log|history',
4778 @command('^log|history',
4850 [('f', 'follow', None,
4779 [('f', 'follow', None,
4851 _('follow changeset history, or file history across copies and renames')),
4780 _('follow changeset history, or file history across copies and renames')),
4852 ('', 'follow-first', None,
4781 ('', 'follow-first', None,
4853 _('only follow the first parent of merge changesets (DEPRECATED)')),
4782 _('only follow the first parent of merge changesets (DEPRECATED)')),
4854 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4783 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4855 ('C', 'copies', None, _('show copied files')),
4784 ('C', 'copies', None, _('show copied files')),
4856 ('k', 'keyword', [],
4785 ('k', 'keyword', [],
4857 _('do case-insensitive search for a given text'), _('TEXT')),
4786 _('do case-insensitive search for a given text'), _('TEXT')),
4858 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4787 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4859 ('', 'removed', None, _('include revisions where files were removed')),
4788 ('', 'removed', None, _('include revisions where files were removed')),
4860 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4789 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4861 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4790 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4862 ('', 'only-branch', [],
4791 ('', 'only-branch', [],
4863 _('show only changesets within the given named branch (DEPRECATED)'),
4792 _('show only changesets within the given named branch (DEPRECATED)'),
4864 _('BRANCH')),
4793 _('BRANCH')),
4865 ('b', 'branch', [],
4794 ('b', 'branch', [],
4866 _('show changesets within the given named branch'), _('BRANCH')),
4795 _('show changesets within the given named branch'), _('BRANCH')),
4867 ('P', 'prune', [],
4796 ('P', 'prune', [],
4868 _('do not display revision or any of its ancestors'), _('REV')),
4797 _('do not display revision or any of its ancestors'), _('REV')),
4869 ] + logopts + walkopts,
4798 ] + logopts + walkopts,
4870 _('[OPTION]... [FILE]'),
4799 _('[OPTION]... [FILE]'),
4871 inferrepo=True)
4800 inferrepo=True)
4872 def log(ui, repo, *pats, **opts):
4801 def log(ui, repo, *pats, **opts):
4873 """show revision history of entire repository or files
4802 """show revision history of entire repository or files
4874
4803
4875 Print the revision history of the specified files or the entire
4804 Print the revision history of the specified files or the entire
4876 project.
4805 project.
4877
4806
4878 If no revision range is specified, the default is ``tip:0`` unless
4807 If no revision range is specified, the default is ``tip:0`` unless
4879 --follow is set, in which case the working directory parent is
4808 --follow is set, in which case the working directory parent is
4880 used as the starting revision.
4809 used as the starting revision.
4881
4810
4882 File history is shown without following rename or copy history of
4811 File history is shown without following rename or copy history of
4883 files. Use -f/--follow with a filename to follow history across
4812 files. Use -f/--follow with a filename to follow history across
4884 renames and copies. --follow without a filename will only show
4813 renames and copies. --follow without a filename will only show
4885 ancestors or descendants of the starting revision.
4814 ancestors or descendants of the starting revision.
4886
4815
4887 By default this command prints revision number and changeset id,
4816 By default this command prints revision number and changeset id,
4888 tags, non-trivial parents, user, date and time, and a summary for
4817 tags, non-trivial parents, user, date and time, and a summary for
4889 each commit. When the -v/--verbose switch is used, the list of
4818 each commit. When the -v/--verbose switch is used, the list of
4890 changed files and full commit message are shown.
4819 changed files and full commit message are shown.
4891
4820
4892 With --graph the revisions are shown as an ASCII art DAG with the most
4821 With --graph the revisions are shown as an ASCII art DAG with the most
4893 recent changeset at the top.
4822 recent changeset at the top.
4894 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4823 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4895 and '+' represents a fork where the changeset from the lines below is a
4824 and '+' represents a fork where the changeset from the lines below is a
4896 parent of the 'o' merge on the same line.
4825 parent of the 'o' merge on the same line.
4897
4826
4898 .. note::
4827 .. note::
4899
4828
4900 :hg:`log --patch` may generate unexpected diff output for merge
4829 :hg:`log --patch` may generate unexpected diff output for merge
4901 changesets, as it will only compare the merge changeset against
4830 changesets, as it will only compare the merge changeset against
4902 its first parent. Also, only files different from BOTH parents
4831 its first parent. Also, only files different from BOTH parents
4903 will appear in files:.
4832 will appear in files:.
4904
4833
4905 .. note::
4834 .. note::
4906
4835
4907 For performance reasons, :hg:`log FILE` may omit duplicate changes
4836 For performance reasons, :hg:`log FILE` may omit duplicate changes
4908 made on branches and will not show removals or mode changes. To
4837 made on branches and will not show removals or mode changes. To
4909 see all such changes, use the --removed switch.
4838 see all such changes, use the --removed switch.
4910
4839
4911 .. container:: verbose
4840 .. container:: verbose
4912
4841
4913 Some examples:
4842 Some examples:
4914
4843
4915 - changesets with full descriptions and file lists::
4844 - changesets with full descriptions and file lists::
4916
4845
4917 hg log -v
4846 hg log -v
4918
4847
4919 - changesets ancestral to the working directory::
4848 - changesets ancestral to the working directory::
4920
4849
4921 hg log -f
4850 hg log -f
4922
4851
4923 - last 10 commits on the current branch::
4852 - last 10 commits on the current branch::
4924
4853
4925 hg log -l 10 -b .
4854 hg log -l 10 -b .
4926
4855
4927 - changesets showing all modifications of a file, including removals::
4856 - changesets showing all modifications of a file, including removals::
4928
4857
4929 hg log --removed file.c
4858 hg log --removed file.c
4930
4859
4931 - all changesets that touch a directory, with diffs, excluding merges::
4860 - all changesets that touch a directory, with diffs, excluding merges::
4932
4861
4933 hg log -Mp lib/
4862 hg log -Mp lib/
4934
4863
4935 - all revision numbers that match a keyword::
4864 - all revision numbers that match a keyword::
4936
4865
4937 hg log -k bug --template "{rev}\\n"
4866 hg log -k bug --template "{rev}\\n"
4938
4867
4939 - the full hash identifier of the working directory parent::
4868 - the full hash identifier of the working directory parent::
4940
4869
4941 hg log -r . --template "{node}\\n"
4870 hg log -r . --template "{node}\\n"
4942
4871
4943 - list available log templates::
4872 - list available log templates::
4944
4873
4945 hg log -T list
4874 hg log -T list
4946
4875
4947 - check if a given changeset is included in a tagged release::
4876 - check if a given changeset is included in a tagged release::
4948
4877
4949 hg log -r "a21ccf and ancestor(1.9)"
4878 hg log -r "a21ccf and ancestor(1.9)"
4950
4879
4951 - find all changesets by some user in a date range::
4880 - find all changesets by some user in a date range::
4952
4881
4953 hg log -k alice -d "may 2008 to jul 2008"
4882 hg log -k alice -d "may 2008 to jul 2008"
4954
4883
4955 - summary of all changesets after the last tag::
4884 - summary of all changesets after the last tag::
4956
4885
4957 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4886 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4958
4887
4959 See :hg:`help dates` for a list of formats valid for -d/--date.
4888 See :hg:`help dates` for a list of formats valid for -d/--date.
4960
4889
4961 See :hg:`help revisions` and :hg:`help revsets` for more about
4890 See :hg:`help revisions` and :hg:`help revsets` for more about
4962 specifying and ordering revisions.
4891 specifying and ordering revisions.
4963
4892
4964 See :hg:`help templates` for more about pre-packaged styles and
4893 See :hg:`help templates` for more about pre-packaged styles and
4965 specifying custom templates.
4894 specifying custom templates.
4966
4895
4967 Returns 0 on success.
4896 Returns 0 on success.
4968
4897
4969 """
4898 """
4970 if opts.get('follow') and opts.get('rev'):
4899 if opts.get('follow') and opts.get('rev'):
4971 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4900 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4972 del opts['follow']
4901 del opts['follow']
4973
4902
4974 if opts.get('graph'):
4903 if opts.get('graph'):
4975 return cmdutil.graphlog(ui, repo, *pats, **opts)
4904 return cmdutil.graphlog(ui, repo, *pats, **opts)
4976
4905
4977 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4906 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4978 limit = cmdutil.loglimit(opts)
4907 limit = cmdutil.loglimit(opts)
4979 count = 0
4908 count = 0
4980
4909
4981 getrenamed = None
4910 getrenamed = None
4982 if opts.get('copies'):
4911 if opts.get('copies'):
4983 endrev = None
4912 endrev = None
4984 if opts.get('rev'):
4913 if opts.get('rev'):
4985 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4914 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4986 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4915 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4987
4916
4988 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4917 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4989 for rev in revs:
4918 for rev in revs:
4990 if count == limit:
4919 if count == limit:
4991 break
4920 break
4992 ctx = repo[rev]
4921 ctx = repo[rev]
4993 copies = None
4922 copies = None
4994 if getrenamed is not None and rev:
4923 if getrenamed is not None and rev:
4995 copies = []
4924 copies = []
4996 for fn in ctx.files():
4925 for fn in ctx.files():
4997 rename = getrenamed(fn, rev)
4926 rename = getrenamed(fn, rev)
4998 if rename:
4927 if rename:
4999 copies.append((fn, rename[0]))
4928 copies.append((fn, rename[0]))
5000 if filematcher:
4929 if filematcher:
5001 revmatchfn = filematcher(ctx.rev())
4930 revmatchfn = filematcher(ctx.rev())
5002 else:
4931 else:
5003 revmatchfn = None
4932 revmatchfn = None
5004 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4933 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5005 if displayer.flush(ctx):
4934 if displayer.flush(ctx):
5006 count += 1
4935 count += 1
5007
4936
5008 displayer.close()
4937 displayer.close()
5009
4938
5010 @command('manifest',
4939 @command('manifest',
5011 [('r', 'rev', '', _('revision to display'), _('REV')),
4940 [('r', 'rev', '', _('revision to display'), _('REV')),
5012 ('', 'all', False, _("list files from all revisions"))]
4941 ('', 'all', False, _("list files from all revisions"))]
5013 + formatteropts,
4942 + formatteropts,
5014 _('[-r REV]'))
4943 _('[-r REV]'))
5015 def manifest(ui, repo, node=None, rev=None, **opts):
4944 def manifest(ui, repo, node=None, rev=None, **opts):
5016 """output the current or given revision of the project manifest
4945 """output the current or given revision of the project manifest
5017
4946
5018 Print a list of version controlled files for the given revision.
4947 Print a list of version controlled files for the given revision.
5019 If no revision is given, the first parent of the working directory
4948 If no revision is given, the first parent of the working directory
5020 is used, or the null revision if no revision is checked out.
4949 is used, or the null revision if no revision is checked out.
5021
4950
5022 With -v, print file permissions, symlink and executable bits.
4951 With -v, print file permissions, symlink and executable bits.
5023 With --debug, print file revision hashes.
4952 With --debug, print file revision hashes.
5024
4953
5025 If option --all is specified, the list of all files from all revisions
4954 If option --all is specified, the list of all files from all revisions
5026 is printed. This includes deleted and renamed files.
4955 is printed. This includes deleted and renamed files.
5027
4956
5028 Returns 0 on success.
4957 Returns 0 on success.
5029 """
4958 """
5030
4959
5031 fm = ui.formatter('manifest', opts)
4960 fm = ui.formatter('manifest', opts)
5032
4961
5033 if opts.get('all'):
4962 if opts.get('all'):
5034 if rev or node:
4963 if rev or node:
5035 raise error.Abort(_("can't specify a revision with --all"))
4964 raise error.Abort(_("can't specify a revision with --all"))
5036
4965
5037 res = []
4966 res = []
5038 prefix = "data/"
4967 prefix = "data/"
5039 suffix = ".i"
4968 suffix = ".i"
5040 plen = len(prefix)
4969 plen = len(prefix)
5041 slen = len(suffix)
4970 slen = len(suffix)
5042 with repo.lock():
4971 with repo.lock():
5043 for fn, b, size in repo.store.datafiles():
4972 for fn, b, size in repo.store.datafiles():
5044 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4973 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5045 res.append(fn[plen:-slen])
4974 res.append(fn[plen:-slen])
5046 for f in res:
4975 for f in res:
5047 fm.startitem()
4976 fm.startitem()
5048 fm.write("path", '%s\n', f)
4977 fm.write("path", '%s\n', f)
5049 fm.end()
4978 fm.end()
5050 return
4979 return
5051
4980
5052 if rev and node:
4981 if rev and node:
5053 raise error.Abort(_("please specify just one revision"))
4982 raise error.Abort(_("please specify just one revision"))
5054
4983
5055 if not node:
4984 if not node:
5056 node = rev
4985 node = rev
5057
4986
5058 char = {'l': '@', 'x': '*', '': ''}
4987 char = {'l': '@', 'x': '*', '': ''}
5059 mode = {'l': '644', 'x': '755', '': '644'}
4988 mode = {'l': '644', 'x': '755', '': '644'}
5060 ctx = scmutil.revsingle(repo, node)
4989 ctx = scmutil.revsingle(repo, node)
5061 mf = ctx.manifest()
4990 mf = ctx.manifest()
5062 for f in ctx:
4991 for f in ctx:
5063 fm.startitem()
4992 fm.startitem()
5064 fl = ctx[f].flags()
4993 fl = ctx[f].flags()
5065 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4994 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5066 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4995 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5067 fm.write('path', '%s\n', f)
4996 fm.write('path', '%s\n', f)
5068 fm.end()
4997 fm.end()
5069
4998
5070 @command('^merge',
4999 @command('^merge',
5071 [('f', 'force', None,
5000 [('f', 'force', None,
5072 _('force a merge including outstanding changes (DEPRECATED)')),
5001 _('force a merge including outstanding changes (DEPRECATED)')),
5073 ('r', 'rev', '', _('revision to merge'), _('REV')),
5002 ('r', 'rev', '', _('revision to merge'), _('REV')),
5074 ('P', 'preview', None,
5003 ('P', 'preview', None,
5075 _('review revisions to merge (no merge is performed)'))
5004 _('review revisions to merge (no merge is performed)'))
5076 ] + mergetoolopts,
5005 ] + mergetoolopts,
5077 _('[-P] [[-r] REV]'))
5006 _('[-P] [[-r] REV]'))
5078 def merge(ui, repo, node=None, **opts):
5007 def merge(ui, repo, node=None, **opts):
5079 """merge another revision into working directory
5008 """merge another revision into working directory
5080
5009
5081 The current working directory is updated with all changes made in
5010 The current working directory is updated with all changes made in
5082 the requested revision since the last common predecessor revision.
5011 the requested revision since the last common predecessor revision.
5083
5012
5084 Files that changed between either parent are marked as changed for
5013 Files that changed between either parent are marked as changed for
5085 the next commit and a commit must be performed before any further
5014 the next commit and a commit must be performed before any further
5086 updates to the repository are allowed. The next commit will have
5015 updates to the repository are allowed. The next commit will have
5087 two parents.
5016 two parents.
5088
5017
5089 ``--tool`` can be used to specify the merge tool used for file
5018 ``--tool`` can be used to specify the merge tool used for file
5090 merges. It overrides the HGMERGE environment variable and your
5019 merges. It overrides the HGMERGE environment variable and your
5091 configuration files. See :hg:`help merge-tools` for options.
5020 configuration files. See :hg:`help merge-tools` for options.
5092
5021
5093 If no revision is specified, the working directory's parent is a
5022 If no revision is specified, the working directory's parent is a
5094 head revision, and the current branch contains exactly one other
5023 head revision, and the current branch contains exactly one other
5095 head, the other head is merged with by default. Otherwise, an
5024 head, the other head is merged with by default. Otherwise, an
5096 explicit revision with which to merge with must be provided.
5025 explicit revision with which to merge with must be provided.
5097
5026
5098 See :hg:`help resolve` for information on handling file conflicts.
5027 See :hg:`help resolve` for information on handling file conflicts.
5099
5028
5100 To undo an uncommitted merge, use :hg:`update --clean .` which
5029 To undo an uncommitted merge, use :hg:`update --clean .` which
5101 will check out a clean copy of the original merge parent, losing
5030 will check out a clean copy of the original merge parent, losing
5102 all changes.
5031 all changes.
5103
5032
5104 Returns 0 on success, 1 if there are unresolved files.
5033 Returns 0 on success, 1 if there are unresolved files.
5105 """
5034 """
5106
5035
5107 if opts.get('rev') and node:
5036 if opts.get('rev') and node:
5108 raise error.Abort(_("please specify just one revision"))
5037 raise error.Abort(_("please specify just one revision"))
5109 if not node:
5038 if not node:
5110 node = opts.get('rev')
5039 node = opts.get('rev')
5111
5040
5112 if node:
5041 if node:
5113 node = scmutil.revsingle(repo, node).node()
5042 node = scmutil.revsingle(repo, node).node()
5114
5043
5115 if not node:
5044 if not node:
5116 node = repo[destutil.destmerge(repo)].node()
5045 node = repo[destutil.destmerge(repo)].node()
5117
5046
5118 if opts.get('preview'):
5047 if opts.get('preview'):
5119 # find nodes that are ancestors of p2 but not of p1
5048 # find nodes that are ancestors of p2 but not of p1
5120 p1 = repo.lookup('.')
5049 p1 = repo.lookup('.')
5121 p2 = repo.lookup(node)
5050 p2 = repo.lookup(node)
5122 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5051 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5123
5052
5124 displayer = cmdutil.show_changeset(ui, repo, opts)
5053 displayer = cmdutil.show_changeset(ui, repo, opts)
5125 for node in nodes:
5054 for node in nodes:
5126 displayer.show(repo[node])
5055 displayer.show(repo[node])
5127 displayer.close()
5056 displayer.close()
5128 return 0
5057 return 0
5129
5058
5130 try:
5059 try:
5131 # ui.forcemerge is an internal variable, do not document
5060 # ui.forcemerge is an internal variable, do not document
5132 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5061 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5133 force = opts.get('force')
5062 force = opts.get('force')
5134 labels = ['working copy', 'merge rev']
5063 labels = ['working copy', 'merge rev']
5135 return hg.merge(repo, node, force=force, mergeforce=force,
5064 return hg.merge(repo, node, force=force, mergeforce=force,
5136 labels=labels)
5065 labels=labels)
5137 finally:
5066 finally:
5138 ui.setconfig('ui', 'forcemerge', '', 'merge')
5067 ui.setconfig('ui', 'forcemerge', '', 'merge')
5139
5068
5140 @command('outgoing|out',
5069 @command('outgoing|out',
5141 [('f', 'force', None, _('run even when the destination is unrelated')),
5070 [('f', 'force', None, _('run even when the destination is unrelated')),
5142 ('r', 'rev', [],
5071 ('r', 'rev', [],
5143 _('a changeset intended to be included in the destination'), _('REV')),
5072 _('a changeset intended to be included in the destination'), _('REV')),
5144 ('n', 'newest-first', None, _('show newest record first')),
5073 ('n', 'newest-first', None, _('show newest record first')),
5145 ('B', 'bookmarks', False, _('compare bookmarks')),
5074 ('B', 'bookmarks', False, _('compare bookmarks')),
5146 ('b', 'branch', [], _('a specific branch you would like to push'),
5075 ('b', 'branch', [], _('a specific branch you would like to push'),
5147 _('BRANCH')),
5076 _('BRANCH')),
5148 ] + logopts + remoteopts + subrepoopts,
5077 ] + logopts + remoteopts + subrepoopts,
5149 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5078 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5150 def outgoing(ui, repo, dest=None, **opts):
5079 def outgoing(ui, repo, dest=None, **opts):
5151 """show changesets not found in the destination
5080 """show changesets not found in the destination
5152
5081
5153 Show changesets not found in the specified destination repository
5082 Show changesets not found in the specified destination repository
5154 or the default push location. These are the changesets that would
5083 or the default push location. These are the changesets that would
5155 be pushed if a push was requested.
5084 be pushed if a push was requested.
5156
5085
5157 See pull for details of valid destination formats.
5086 See pull for details of valid destination formats.
5158
5087
5159 .. container:: verbose
5088 .. container:: verbose
5160
5089
5161 With -B/--bookmarks, the result of bookmark comparison between
5090 With -B/--bookmarks, the result of bookmark comparison between
5162 local and remote repositories is displayed. With -v/--verbose,
5091 local and remote repositories is displayed. With -v/--verbose,
5163 status is also displayed for each bookmark like below::
5092 status is also displayed for each bookmark like below::
5164
5093
5165 BM1 01234567890a added
5094 BM1 01234567890a added
5166 BM2 deleted
5095 BM2 deleted
5167 BM3 234567890abc advanced
5096 BM3 234567890abc advanced
5168 BM4 34567890abcd diverged
5097 BM4 34567890abcd diverged
5169 BM5 4567890abcde changed
5098 BM5 4567890abcde changed
5170
5099
5171 The action taken when pushing depends on the
5100 The action taken when pushing depends on the
5172 status of each bookmark:
5101 status of each bookmark:
5173
5102
5174 :``added``: push with ``-B`` will create it
5103 :``added``: push with ``-B`` will create it
5175 :``deleted``: push with ``-B`` will delete it
5104 :``deleted``: push with ``-B`` will delete it
5176 :``advanced``: push will update it
5105 :``advanced``: push will update it
5177 :``diverged``: push with ``-B`` will update it
5106 :``diverged``: push with ``-B`` will update it
5178 :``changed``: push with ``-B`` will update it
5107 :``changed``: push with ``-B`` will update it
5179
5108
5180 From the point of view of pushing behavior, bookmarks
5109 From the point of view of pushing behavior, bookmarks
5181 existing only in the remote repository are treated as
5110 existing only in the remote repository are treated as
5182 ``deleted``, even if it is in fact added remotely.
5111 ``deleted``, even if it is in fact added remotely.
5183
5112
5184 Returns 0 if there are outgoing changes, 1 otherwise.
5113 Returns 0 if there are outgoing changes, 1 otherwise.
5185 """
5114 """
5186 if opts.get('graph'):
5115 if opts.get('graph'):
5187 cmdutil.checkunsupportedgraphflags([], opts)
5116 cmdutil.checkunsupportedgraphflags([], opts)
5188 o, other = hg._outgoing(ui, repo, dest, opts)
5117 o, other = hg._outgoing(ui, repo, dest, opts)
5189 if not o:
5118 if not o:
5190 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5119 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5191 return
5120 return
5192
5121
5193 revdag = cmdutil.graphrevs(repo, o, opts)
5122 revdag = cmdutil.graphrevs(repo, o, opts)
5194 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5123 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5195 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5124 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5196 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5125 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5197 return 0
5126 return 0
5198
5127
5199 if opts.get('bookmarks'):
5128 if opts.get('bookmarks'):
5200 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5129 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5201 dest, branches = hg.parseurl(dest, opts.get('branch'))
5130 dest, branches = hg.parseurl(dest, opts.get('branch'))
5202 other = hg.peer(repo, opts, dest)
5131 other = hg.peer(repo, opts, dest)
5203 if 'bookmarks' not in other.listkeys('namespaces'):
5132 if 'bookmarks' not in other.listkeys('namespaces'):
5204 ui.warn(_("remote doesn't support bookmarks\n"))
5133 ui.warn(_("remote doesn't support bookmarks\n"))
5205 return 0
5134 return 0
5206 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5135 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5207 return bookmarks.outgoing(ui, repo, other)
5136 return bookmarks.outgoing(ui, repo, other)
5208
5137
5209 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5138 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5210 try:
5139 try:
5211 return hg.outgoing(ui, repo, dest, opts)
5140 return hg.outgoing(ui, repo, dest, opts)
5212 finally:
5141 finally:
5213 del repo._subtoppath
5142 del repo._subtoppath
5214
5143
5215 @command('parents',
5144 @command('parents',
5216 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5145 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5217 ] + templateopts,
5146 ] + templateopts,
5218 _('[-r REV] [FILE]'),
5147 _('[-r REV] [FILE]'),
5219 inferrepo=True)
5148 inferrepo=True)
5220 def parents(ui, repo, file_=None, **opts):
5149 def parents(ui, repo, file_=None, **opts):
5221 """show the parents of the working directory or revision (DEPRECATED)
5150 """show the parents of the working directory or revision (DEPRECATED)
5222
5151
5223 Print the working directory's parent revisions. If a revision is
5152 Print the working directory's parent revisions. If a revision is
5224 given via -r/--rev, the parent of that revision will be printed.
5153 given via -r/--rev, the parent of that revision will be printed.
5225 If a file argument is given, the revision in which the file was
5154 If a file argument is given, the revision in which the file was
5226 last changed (before the working directory revision or the
5155 last changed (before the working directory revision or the
5227 argument to --rev if given) is printed.
5156 argument to --rev if given) is printed.
5228
5157
5229 This command is equivalent to::
5158 This command is equivalent to::
5230
5159
5231 hg log -r "p1()+p2()" or
5160 hg log -r "p1()+p2()" or
5232 hg log -r "p1(REV)+p2(REV)" or
5161 hg log -r "p1(REV)+p2(REV)" or
5233 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5162 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5234 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5163 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5235
5164
5236 See :hg:`summary` and :hg:`help revsets` for related information.
5165 See :hg:`summary` and :hg:`help revsets` for related information.
5237
5166
5238 Returns 0 on success.
5167 Returns 0 on success.
5239 """
5168 """
5240
5169
5241 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5170 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5242
5171
5243 if file_:
5172 if file_:
5244 m = scmutil.match(ctx, (file_,), opts)
5173 m = scmutil.match(ctx, (file_,), opts)
5245 if m.anypats() or len(m.files()) != 1:
5174 if m.anypats() or len(m.files()) != 1:
5246 raise error.Abort(_('can only specify an explicit filename'))
5175 raise error.Abort(_('can only specify an explicit filename'))
5247 file_ = m.files()[0]
5176 file_ = m.files()[0]
5248 filenodes = []
5177 filenodes = []
5249 for cp in ctx.parents():
5178 for cp in ctx.parents():
5250 if not cp:
5179 if not cp:
5251 continue
5180 continue
5252 try:
5181 try:
5253 filenodes.append(cp.filenode(file_))
5182 filenodes.append(cp.filenode(file_))
5254 except error.LookupError:
5183 except error.LookupError:
5255 pass
5184 pass
5256 if not filenodes:
5185 if not filenodes:
5257 raise error.Abort(_("'%s' not found in manifest!") % file_)
5186 raise error.Abort(_("'%s' not found in manifest!") % file_)
5258 p = []
5187 p = []
5259 for fn in filenodes:
5188 for fn in filenodes:
5260 fctx = repo.filectx(file_, fileid=fn)
5189 fctx = repo.filectx(file_, fileid=fn)
5261 p.append(fctx.node())
5190 p.append(fctx.node())
5262 else:
5191 else:
5263 p = [cp.node() for cp in ctx.parents()]
5192 p = [cp.node() for cp in ctx.parents()]
5264
5193
5265 displayer = cmdutil.show_changeset(ui, repo, opts)
5194 displayer = cmdutil.show_changeset(ui, repo, opts)
5266 for n in p:
5195 for n in p:
5267 if n != nullid:
5196 if n != nullid:
5268 displayer.show(repo[n])
5197 displayer.show(repo[n])
5269 displayer.close()
5198 displayer.close()
5270
5199
5271 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5200 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5272 def paths(ui, repo, search=None, **opts):
5201 def paths(ui, repo, search=None, **opts):
5273 """show aliases for remote repositories
5202 """show aliases for remote repositories
5274
5203
5275 Show definition of symbolic path name NAME. If no name is given,
5204 Show definition of symbolic path name NAME. If no name is given,
5276 show definition of all available names.
5205 show definition of all available names.
5277
5206
5278 Option -q/--quiet suppresses all output when searching for NAME
5207 Option -q/--quiet suppresses all output when searching for NAME
5279 and shows only the path names when listing all definitions.
5208 and shows only the path names when listing all definitions.
5280
5209
5281 Path names are defined in the [paths] section of your
5210 Path names are defined in the [paths] section of your
5282 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5211 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5283 repository, ``.hg/hgrc`` is used, too.
5212 repository, ``.hg/hgrc`` is used, too.
5284
5213
5285 The path names ``default`` and ``default-push`` have a special
5214 The path names ``default`` and ``default-push`` have a special
5286 meaning. When performing a push or pull operation, they are used
5215 meaning. When performing a push or pull operation, they are used
5287 as fallbacks if no location is specified on the command-line.
5216 as fallbacks if no location is specified on the command-line.
5288 When ``default-push`` is set, it will be used for push and
5217 When ``default-push`` is set, it will be used for push and
5289 ``default`` will be used for pull; otherwise ``default`` is used
5218 ``default`` will be used for pull; otherwise ``default`` is used
5290 as the fallback for both. When cloning a repository, the clone
5219 as the fallback for both. When cloning a repository, the clone
5291 source is written as ``default`` in ``.hg/hgrc``.
5220 source is written as ``default`` in ``.hg/hgrc``.
5292
5221
5293 .. note::
5222 .. note::
5294
5223
5295 ``default`` and ``default-push`` apply to all inbound (e.g.
5224 ``default`` and ``default-push`` apply to all inbound (e.g.
5296 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5225 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5297 and :hg:`bundle`) operations.
5226 and :hg:`bundle`) operations.
5298
5227
5299 See :hg:`help urls` for more information.
5228 See :hg:`help urls` for more information.
5300
5229
5301 Returns 0 on success.
5230 Returns 0 on success.
5302 """
5231 """
5303 if search:
5232 if search:
5304 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5233 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5305 if name == search]
5234 if name == search]
5306 else:
5235 else:
5307 pathitems = sorted(ui.paths.iteritems())
5236 pathitems = sorted(ui.paths.iteritems())
5308
5237
5309 fm = ui.formatter('paths', opts)
5238 fm = ui.formatter('paths', opts)
5310 if fm.isplain():
5239 if fm.isplain():
5311 hidepassword = util.hidepassword
5240 hidepassword = util.hidepassword
5312 else:
5241 else:
5313 hidepassword = str
5242 hidepassword = str
5314 if ui.quiet:
5243 if ui.quiet:
5315 namefmt = '%s\n'
5244 namefmt = '%s\n'
5316 else:
5245 else:
5317 namefmt = '%s = '
5246 namefmt = '%s = '
5318 showsubopts = not search and not ui.quiet
5247 showsubopts = not search and not ui.quiet
5319
5248
5320 for name, path in pathitems:
5249 for name, path in pathitems:
5321 fm.startitem()
5250 fm.startitem()
5322 fm.condwrite(not search, 'name', namefmt, name)
5251 fm.condwrite(not search, 'name', namefmt, name)
5323 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5252 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5324 for subopt, value in sorted(path.suboptions.items()):
5253 for subopt, value in sorted(path.suboptions.items()):
5325 assert subopt not in ('name', 'url')
5254 assert subopt not in ('name', 'url')
5326 if showsubopts:
5255 if showsubopts:
5327 fm.plain('%s:%s = ' % (name, subopt))
5256 fm.plain('%s:%s = ' % (name, subopt))
5328 fm.condwrite(showsubopts, subopt, '%s\n', value)
5257 fm.condwrite(showsubopts, subopt, '%s\n', value)
5329
5258
5330 fm.end()
5259 fm.end()
5331
5260
5332 if search and not pathitems:
5261 if search and not pathitems:
5333 if not ui.quiet:
5262 if not ui.quiet:
5334 ui.warn(_("not found!\n"))
5263 ui.warn(_("not found!\n"))
5335 return 1
5264 return 1
5336 else:
5265 else:
5337 return 0
5266 return 0
5338
5267
5339 @command('phase',
5268 @command('phase',
5340 [('p', 'public', False, _('set changeset phase to public')),
5269 [('p', 'public', False, _('set changeset phase to public')),
5341 ('d', 'draft', False, _('set changeset phase to draft')),
5270 ('d', 'draft', False, _('set changeset phase to draft')),
5342 ('s', 'secret', False, _('set changeset phase to secret')),
5271 ('s', 'secret', False, _('set changeset phase to secret')),
5343 ('f', 'force', False, _('allow to move boundary backward')),
5272 ('f', 'force', False, _('allow to move boundary backward')),
5344 ('r', 'rev', [], _('target revision'), _('REV')),
5273 ('r', 'rev', [], _('target revision'), _('REV')),
5345 ],
5274 ],
5346 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5275 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5347 def phase(ui, repo, *revs, **opts):
5276 def phase(ui, repo, *revs, **opts):
5348 """set or show the current phase name
5277 """set or show the current phase name
5349
5278
5350 With no argument, show the phase name of the current revision(s).
5279 With no argument, show the phase name of the current revision(s).
5351
5280
5352 With one of -p/--public, -d/--draft or -s/--secret, change the
5281 With one of -p/--public, -d/--draft or -s/--secret, change the
5353 phase value of the specified revisions.
5282 phase value of the specified revisions.
5354
5283
5355 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5284 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5356 lower phase to an higher phase. Phases are ordered as follows::
5285 lower phase to an higher phase. Phases are ordered as follows::
5357
5286
5358 public < draft < secret
5287 public < draft < secret
5359
5288
5360 Returns 0 on success, 1 if some phases could not be changed.
5289 Returns 0 on success, 1 if some phases could not be changed.
5361
5290
5362 (For more information about the phases concept, see :hg:`help phases`.)
5291 (For more information about the phases concept, see :hg:`help phases`.)
5363 """
5292 """
5364 # search for a unique phase argument
5293 # search for a unique phase argument
5365 targetphase = None
5294 targetphase = None
5366 for idx, name in enumerate(phases.phasenames):
5295 for idx, name in enumerate(phases.phasenames):
5367 if opts[name]:
5296 if opts[name]:
5368 if targetphase is not None:
5297 if targetphase is not None:
5369 raise error.Abort(_('only one phase can be specified'))
5298 raise error.Abort(_('only one phase can be specified'))
5370 targetphase = idx
5299 targetphase = idx
5371
5300
5372 # look for specified revision
5301 # look for specified revision
5373 revs = list(revs)
5302 revs = list(revs)
5374 revs.extend(opts['rev'])
5303 revs.extend(opts['rev'])
5375 if not revs:
5304 if not revs:
5376 # display both parents as the second parent phase can influence
5305 # display both parents as the second parent phase can influence
5377 # the phase of a merge commit
5306 # the phase of a merge commit
5378 revs = [c.rev() for c in repo[None].parents()]
5307 revs = [c.rev() for c in repo[None].parents()]
5379
5308
5380 revs = scmutil.revrange(repo, revs)
5309 revs = scmutil.revrange(repo, revs)
5381
5310
5382 lock = None
5311 lock = None
5383 ret = 0
5312 ret = 0
5384 if targetphase is None:
5313 if targetphase is None:
5385 # display
5314 # display
5386 for r in revs:
5315 for r in revs:
5387 ctx = repo[r]
5316 ctx = repo[r]
5388 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5317 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5389 else:
5318 else:
5390 tr = None
5319 tr = None
5391 lock = repo.lock()
5320 lock = repo.lock()
5392 try:
5321 try:
5393 tr = repo.transaction("phase")
5322 tr = repo.transaction("phase")
5394 # set phase
5323 # set phase
5395 if not revs:
5324 if not revs:
5396 raise error.Abort(_('empty revision set'))
5325 raise error.Abort(_('empty revision set'))
5397 nodes = [repo[r].node() for r in revs]
5326 nodes = [repo[r].node() for r in revs]
5398 # moving revision from public to draft may hide them
5327 # moving revision from public to draft may hide them
5399 # We have to check result on an unfiltered repository
5328 # We have to check result on an unfiltered repository
5400 unfi = repo.unfiltered()
5329 unfi = repo.unfiltered()
5401 getphase = unfi._phasecache.phase
5330 getphase = unfi._phasecache.phase
5402 olddata = [getphase(unfi, r) for r in unfi]
5331 olddata = [getphase(unfi, r) for r in unfi]
5403 phases.advanceboundary(repo, tr, targetphase, nodes)
5332 phases.advanceboundary(repo, tr, targetphase, nodes)
5404 if opts['force']:
5333 if opts['force']:
5405 phases.retractboundary(repo, tr, targetphase, nodes)
5334 phases.retractboundary(repo, tr, targetphase, nodes)
5406 tr.close()
5335 tr.close()
5407 finally:
5336 finally:
5408 if tr is not None:
5337 if tr is not None:
5409 tr.release()
5338 tr.release()
5410 lock.release()
5339 lock.release()
5411 getphase = unfi._phasecache.phase
5340 getphase = unfi._phasecache.phase
5412 newdata = [getphase(unfi, r) for r in unfi]
5341 newdata = [getphase(unfi, r) for r in unfi]
5413 changes = sum(newdata[r] != olddata[r] for r in unfi)
5342 changes = sum(newdata[r] != olddata[r] for r in unfi)
5414 cl = unfi.changelog
5343 cl = unfi.changelog
5415 rejected = [n for n in nodes
5344 rejected = [n for n in nodes
5416 if newdata[cl.rev(n)] < targetphase]
5345 if newdata[cl.rev(n)] < targetphase]
5417 if rejected:
5346 if rejected:
5418 ui.warn(_('cannot move %i changesets to a higher '
5347 ui.warn(_('cannot move %i changesets to a higher '
5419 'phase, use --force\n') % len(rejected))
5348 'phase, use --force\n') % len(rejected))
5420 ret = 1
5349 ret = 1
5421 if changes:
5350 if changes:
5422 msg = _('phase changed for %i changesets\n') % changes
5351 msg = _('phase changed for %i changesets\n') % changes
5423 if ret:
5352 if ret:
5424 ui.status(msg)
5353 ui.status(msg)
5425 else:
5354 else:
5426 ui.note(msg)
5355 ui.note(msg)
5427 else:
5356 else:
5428 ui.warn(_('no phases changed\n'))
5357 ui.warn(_('no phases changed\n'))
5429 return ret
5358 return ret
5430
5359
5431 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5360 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5432 """Run after a changegroup has been added via pull/unbundle
5361 """Run after a changegroup has been added via pull/unbundle
5433
5362
5434 This takes arguments below:
5363 This takes arguments below:
5435
5364
5436 :modheads: change of heads by pull/unbundle
5365 :modheads: change of heads by pull/unbundle
5437 :optupdate: updating working directory is needed or not
5366 :optupdate: updating working directory is needed or not
5438 :checkout: update destination revision (or None to default destination)
5367 :checkout: update destination revision (or None to default destination)
5439 :brev: a name, which might be a bookmark to be activated after updating
5368 :brev: a name, which might be a bookmark to be activated after updating
5440 """
5369 """
5441 if modheads == 0:
5370 if modheads == 0:
5442 return
5371 return
5443 if optupdate:
5372 if optupdate:
5444 try:
5373 try:
5445 return hg.updatetotally(ui, repo, checkout, brev)
5374 return hg.updatetotally(ui, repo, checkout, brev)
5446 except error.UpdateAbort as inst:
5375 except error.UpdateAbort as inst:
5447 msg = _("not updating: %s") % str(inst)
5376 msg = _("not updating: %s") % str(inst)
5448 hint = inst.hint
5377 hint = inst.hint
5449 raise error.UpdateAbort(msg, hint=hint)
5378 raise error.UpdateAbort(msg, hint=hint)
5450 if modheads > 1:
5379 if modheads > 1:
5451 currentbranchheads = len(repo.branchheads())
5380 currentbranchheads = len(repo.branchheads())
5452 if currentbranchheads == modheads:
5381 if currentbranchheads == modheads:
5453 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5382 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5454 elif currentbranchheads > 1:
5383 elif currentbranchheads > 1:
5455 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5384 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5456 "merge)\n"))
5385 "merge)\n"))
5457 else:
5386 else:
5458 ui.status(_("(run 'hg heads' to see heads)\n"))
5387 ui.status(_("(run 'hg heads' to see heads)\n"))
5459 else:
5388 else:
5460 ui.status(_("(run 'hg update' to get a working copy)\n"))
5389 ui.status(_("(run 'hg update' to get a working copy)\n"))
5461
5390
5462 @command('^pull',
5391 @command('^pull',
5463 [('u', 'update', None,
5392 [('u', 'update', None,
5464 _('update to new branch head if changesets were pulled')),
5393 _('update to new branch head if changesets were pulled')),
5465 ('f', 'force', None, _('run even when remote repository is unrelated')),
5394 ('f', 'force', None, _('run even when remote repository is unrelated')),
5466 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5395 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5467 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5396 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5468 ('b', 'branch', [], _('a specific branch you would like to pull'),
5397 ('b', 'branch', [], _('a specific branch you would like to pull'),
5469 _('BRANCH')),
5398 _('BRANCH')),
5470 ] + remoteopts,
5399 ] + remoteopts,
5471 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5400 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5472 def pull(ui, repo, source="default", **opts):
5401 def pull(ui, repo, source="default", **opts):
5473 """pull changes from the specified source
5402 """pull changes from the specified source
5474
5403
5475 Pull changes from a remote repository to a local one.
5404 Pull changes from a remote repository to a local one.
5476
5405
5477 This finds all changes from the repository at the specified path
5406 This finds all changes from the repository at the specified path
5478 or URL and adds them to a local repository (the current one unless
5407 or URL and adds them to a local repository (the current one unless
5479 -R is specified). By default, this does not update the copy of the
5408 -R is specified). By default, this does not update the copy of the
5480 project in the working directory.
5409 project in the working directory.
5481
5410
5482 Use :hg:`incoming` if you want to see what would have been added
5411 Use :hg:`incoming` if you want to see what would have been added
5483 by a pull at the time you issued this command. If you then decide
5412 by a pull at the time you issued this command. If you then decide
5484 to add those changes to the repository, you should use :hg:`pull
5413 to add those changes to the repository, you should use :hg:`pull
5485 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5414 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5486
5415
5487 If SOURCE is omitted, the 'default' path will be used.
5416 If SOURCE is omitted, the 'default' path will be used.
5488 See :hg:`help urls` for more information.
5417 See :hg:`help urls` for more information.
5489
5418
5490 Specifying bookmark as ``.`` is equivalent to specifying the active
5419 Specifying bookmark as ``.`` is equivalent to specifying the active
5491 bookmark's name.
5420 bookmark's name.
5492
5421
5493 Returns 0 on success, 1 if an update had unresolved files.
5422 Returns 0 on success, 1 if an update had unresolved files.
5494 """
5423 """
5495 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5424 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5496 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5425 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5497 other = hg.peer(repo, opts, source)
5426 other = hg.peer(repo, opts, source)
5498 try:
5427 try:
5499 revs, checkout = hg.addbranchrevs(repo, other, branches,
5428 revs, checkout = hg.addbranchrevs(repo, other, branches,
5500 opts.get('rev'))
5429 opts.get('rev'))
5501
5430
5502
5431
5503 pullopargs = {}
5432 pullopargs = {}
5504 if opts.get('bookmark'):
5433 if opts.get('bookmark'):
5505 if not revs:
5434 if not revs:
5506 revs = []
5435 revs = []
5507 # The list of bookmark used here is not the one used to actually
5436 # The list of bookmark used here is not the one used to actually
5508 # update the bookmark name. This can result in the revision pulled
5437 # update the bookmark name. This can result in the revision pulled
5509 # not ending up with the name of the bookmark because of a race
5438 # not ending up with the name of the bookmark because of a race
5510 # condition on the server. (See issue 4689 for details)
5439 # condition on the server. (See issue 4689 for details)
5511 remotebookmarks = other.listkeys('bookmarks')
5440 remotebookmarks = other.listkeys('bookmarks')
5512 pullopargs['remotebookmarks'] = remotebookmarks
5441 pullopargs['remotebookmarks'] = remotebookmarks
5513 for b in opts['bookmark']:
5442 for b in opts['bookmark']:
5514 b = repo._bookmarks.expandname(b)
5443 b = repo._bookmarks.expandname(b)
5515 if b not in remotebookmarks:
5444 if b not in remotebookmarks:
5516 raise error.Abort(_('remote bookmark %s not found!') % b)
5445 raise error.Abort(_('remote bookmark %s not found!') % b)
5517 revs.append(remotebookmarks[b])
5446 revs.append(remotebookmarks[b])
5518
5447
5519 if revs:
5448 if revs:
5520 try:
5449 try:
5521 # When 'rev' is a bookmark name, we cannot guarantee that it
5450 # When 'rev' is a bookmark name, we cannot guarantee that it
5522 # will be updated with that name because of a race condition
5451 # will be updated with that name because of a race condition
5523 # server side. (See issue 4689 for details)
5452 # server side. (See issue 4689 for details)
5524 oldrevs = revs
5453 oldrevs = revs
5525 revs = [] # actually, nodes
5454 revs = [] # actually, nodes
5526 for r in oldrevs:
5455 for r in oldrevs:
5527 node = other.lookup(r)
5456 node = other.lookup(r)
5528 revs.append(node)
5457 revs.append(node)
5529 if r == checkout:
5458 if r == checkout:
5530 checkout = node
5459 checkout = node
5531 except error.CapabilityError:
5460 except error.CapabilityError:
5532 err = _("other repository doesn't support revision lookup, "
5461 err = _("other repository doesn't support revision lookup, "
5533 "so a rev cannot be specified.")
5462 "so a rev cannot be specified.")
5534 raise error.Abort(err)
5463 raise error.Abort(err)
5535
5464
5536 pullopargs.update(opts.get('opargs', {}))
5465 pullopargs.update(opts.get('opargs', {}))
5537 modheads = exchange.pull(repo, other, heads=revs,
5466 modheads = exchange.pull(repo, other, heads=revs,
5538 force=opts.get('force'),
5467 force=opts.get('force'),
5539 bookmarks=opts.get('bookmark', ()),
5468 bookmarks=opts.get('bookmark', ()),
5540 opargs=pullopargs).cgresult
5469 opargs=pullopargs).cgresult
5541
5470
5542 # brev is a name, which might be a bookmark to be activated at
5471 # brev is a name, which might be a bookmark to be activated at
5543 # the end of the update. In other words, it is an explicit
5472 # the end of the update. In other words, it is an explicit
5544 # destination of the update
5473 # destination of the update
5545 brev = None
5474 brev = None
5546
5475
5547 if checkout:
5476 if checkout:
5548 checkout = str(repo.changelog.rev(checkout))
5477 checkout = str(repo.changelog.rev(checkout))
5549
5478
5550 # order below depends on implementation of
5479 # order below depends on implementation of
5551 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5480 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5552 # because 'checkout' is determined without it.
5481 # because 'checkout' is determined without it.
5553 if opts.get('rev'):
5482 if opts.get('rev'):
5554 brev = opts['rev'][0]
5483 brev = opts['rev'][0]
5555 elif opts.get('branch'):
5484 elif opts.get('branch'):
5556 brev = opts['branch'][0]
5485 brev = opts['branch'][0]
5557 else:
5486 else:
5558 brev = branches[0]
5487 brev = branches[0]
5559 repo._subtoppath = source
5488 repo._subtoppath = source
5560 try:
5489 try:
5561 ret = postincoming(ui, repo, modheads, opts.get('update'),
5490 ret = postincoming(ui, repo, modheads, opts.get('update'),
5562 checkout, brev)
5491 checkout, brev)
5563
5492
5564 finally:
5493 finally:
5565 del repo._subtoppath
5494 del repo._subtoppath
5566
5495
5567 finally:
5496 finally:
5568 other.close()
5497 other.close()
5569 return ret
5498 return ret
5570
5499
5571 @command('^push',
5500 @command('^push',
5572 [('f', 'force', None, _('force push')),
5501 [('f', 'force', None, _('force push')),
5573 ('r', 'rev', [],
5502 ('r', 'rev', [],
5574 _('a changeset intended to be included in the destination'),
5503 _('a changeset intended to be included in the destination'),
5575 _('REV')),
5504 _('REV')),
5576 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5505 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5577 ('b', 'branch', [],
5506 ('b', 'branch', [],
5578 _('a specific branch you would like to push'), _('BRANCH')),
5507 _('a specific branch you would like to push'), _('BRANCH')),
5579 ('', 'new-branch', False, _('allow pushing a new branch')),
5508 ('', 'new-branch', False, _('allow pushing a new branch')),
5580 ] + remoteopts,
5509 ] + remoteopts,
5581 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5510 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5582 def push(ui, repo, dest=None, **opts):
5511 def push(ui, repo, dest=None, **opts):
5583 """push changes to the specified destination
5512 """push changes to the specified destination
5584
5513
5585 Push changesets from the local repository to the specified
5514 Push changesets from the local repository to the specified
5586 destination.
5515 destination.
5587
5516
5588 This operation is symmetrical to pull: it is identical to a pull
5517 This operation is symmetrical to pull: it is identical to a pull
5589 in the destination repository from the current one.
5518 in the destination repository from the current one.
5590
5519
5591 By default, push will not allow creation of new heads at the
5520 By default, push will not allow creation of new heads at the
5592 destination, since multiple heads would make it unclear which head
5521 destination, since multiple heads would make it unclear which head
5593 to use. In this situation, it is recommended to pull and merge
5522 to use. In this situation, it is recommended to pull and merge
5594 before pushing.
5523 before pushing.
5595
5524
5596 Use --new-branch if you want to allow push to create a new named
5525 Use --new-branch if you want to allow push to create a new named
5597 branch that is not present at the destination. This allows you to
5526 branch that is not present at the destination. This allows you to
5598 only create a new branch without forcing other changes.
5527 only create a new branch without forcing other changes.
5599
5528
5600 .. note::
5529 .. note::
5601
5530
5602 Extra care should be taken with the -f/--force option,
5531 Extra care should be taken with the -f/--force option,
5603 which will push all new heads on all branches, an action which will
5532 which will push all new heads on all branches, an action which will
5604 almost always cause confusion for collaborators.
5533 almost always cause confusion for collaborators.
5605
5534
5606 If -r/--rev is used, the specified revision and all its ancestors
5535 If -r/--rev is used, the specified revision and all its ancestors
5607 will be pushed to the remote repository.
5536 will be pushed to the remote repository.
5608
5537
5609 If -B/--bookmark is used, the specified bookmarked revision, its
5538 If -B/--bookmark is used, the specified bookmarked revision, its
5610 ancestors, and the bookmark will be pushed to the remote
5539 ancestors, and the bookmark will be pushed to the remote
5611 repository. Specifying ``.`` is equivalent to specifying the active
5540 repository. Specifying ``.`` is equivalent to specifying the active
5612 bookmark's name.
5541 bookmark's name.
5613
5542
5614 Please see :hg:`help urls` for important details about ``ssh://``
5543 Please see :hg:`help urls` for important details about ``ssh://``
5615 URLs. If DESTINATION is omitted, a default path will be used.
5544 URLs. If DESTINATION is omitted, a default path will be used.
5616
5545
5617 Returns 0 if push was successful, 1 if nothing to push.
5546 Returns 0 if push was successful, 1 if nothing to push.
5618 """
5547 """
5619
5548
5620 if opts.get('bookmark'):
5549 if opts.get('bookmark'):
5621 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5550 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5622 for b in opts['bookmark']:
5551 for b in opts['bookmark']:
5623 # translate -B options to -r so changesets get pushed
5552 # translate -B options to -r so changesets get pushed
5624 b = repo._bookmarks.expandname(b)
5553 b = repo._bookmarks.expandname(b)
5625 if b in repo._bookmarks:
5554 if b in repo._bookmarks:
5626 opts.setdefault('rev', []).append(b)
5555 opts.setdefault('rev', []).append(b)
5627 else:
5556 else:
5628 # if we try to push a deleted bookmark, translate it to null
5557 # if we try to push a deleted bookmark, translate it to null
5629 # this lets simultaneous -r, -b options continue working
5558 # this lets simultaneous -r, -b options continue working
5630 opts.setdefault('rev', []).append("null")
5559 opts.setdefault('rev', []).append("null")
5631
5560
5632 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5561 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5633 if not path:
5562 if not path:
5634 raise error.Abort(_('default repository not configured!'),
5563 raise error.Abort(_('default repository not configured!'),
5635 hint=_("see 'hg help config.paths'"))
5564 hint=_("see 'hg help config.paths'"))
5636 dest = path.pushloc or path.loc
5565 dest = path.pushloc or path.loc
5637 branches = (path.branch, opts.get('branch') or [])
5566 branches = (path.branch, opts.get('branch') or [])
5638 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5567 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5639 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5568 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5640 other = hg.peer(repo, opts, dest)
5569 other = hg.peer(repo, opts, dest)
5641
5570
5642 if revs:
5571 if revs:
5643 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5572 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5644 if not revs:
5573 if not revs:
5645 raise error.Abort(_("specified revisions evaluate to an empty set"),
5574 raise error.Abort(_("specified revisions evaluate to an empty set"),
5646 hint=_("use different revision arguments"))
5575 hint=_("use different revision arguments"))
5647 elif path.pushrev:
5576 elif path.pushrev:
5648 # It doesn't make any sense to specify ancestor revisions. So limit
5577 # It doesn't make any sense to specify ancestor revisions. So limit
5649 # to DAG heads to make discovery simpler.
5578 # to DAG heads to make discovery simpler.
5650 expr = revset.formatspec('heads(%r)', path.pushrev)
5579 expr = revset.formatspec('heads(%r)', path.pushrev)
5651 revs = scmutil.revrange(repo, [expr])
5580 revs = scmutil.revrange(repo, [expr])
5652 revs = [repo[rev].node() for rev in revs]
5581 revs = [repo[rev].node() for rev in revs]
5653 if not revs:
5582 if not revs:
5654 raise error.Abort(_('default push revset for path evaluates to an '
5583 raise error.Abort(_('default push revset for path evaluates to an '
5655 'empty set'))
5584 'empty set'))
5656
5585
5657 repo._subtoppath = dest
5586 repo._subtoppath = dest
5658 try:
5587 try:
5659 # push subrepos depth-first for coherent ordering
5588 # push subrepos depth-first for coherent ordering
5660 c = repo['']
5589 c = repo['']
5661 subs = c.substate # only repos that are committed
5590 subs = c.substate # only repos that are committed
5662 for s in sorted(subs):
5591 for s in sorted(subs):
5663 result = c.sub(s).push(opts)
5592 result = c.sub(s).push(opts)
5664 if result == 0:
5593 if result == 0:
5665 return not result
5594 return not result
5666 finally:
5595 finally:
5667 del repo._subtoppath
5596 del repo._subtoppath
5668 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5597 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5669 newbranch=opts.get('new_branch'),
5598 newbranch=opts.get('new_branch'),
5670 bookmarks=opts.get('bookmark', ()),
5599 bookmarks=opts.get('bookmark', ()),
5671 opargs=opts.get('opargs'))
5600 opargs=opts.get('opargs'))
5672
5601
5673 result = not pushop.cgresult
5602 result = not pushop.cgresult
5674
5603
5675 if pushop.bkresult is not None:
5604 if pushop.bkresult is not None:
5676 if pushop.bkresult == 2:
5605 if pushop.bkresult == 2:
5677 result = 2
5606 result = 2
5678 elif not result and pushop.bkresult:
5607 elif not result and pushop.bkresult:
5679 result = 2
5608 result = 2
5680
5609
5681 return result
5610 return result
5682
5611
5683 @command('recover', [])
5612 @command('recover', [])
5684 def recover(ui, repo):
5613 def recover(ui, repo):
5685 """roll back an interrupted transaction
5614 """roll back an interrupted transaction
5686
5615
5687 Recover from an interrupted commit or pull.
5616 Recover from an interrupted commit or pull.
5688
5617
5689 This command tries to fix the repository status after an
5618 This command tries to fix the repository status after an
5690 interrupted operation. It should only be necessary when Mercurial
5619 interrupted operation. It should only be necessary when Mercurial
5691 suggests it.
5620 suggests it.
5692
5621
5693 Returns 0 if successful, 1 if nothing to recover or verify fails.
5622 Returns 0 if successful, 1 if nothing to recover or verify fails.
5694 """
5623 """
5695 if repo.recover():
5624 if repo.recover():
5696 return hg.verify(repo)
5625 return hg.verify(repo)
5697 return 1
5626 return 1
5698
5627
5699 @command('^remove|rm',
5628 @command('^remove|rm',
5700 [('A', 'after', None, _('record delete for missing files')),
5629 [('A', 'after', None, _('record delete for missing files')),
5701 ('f', 'force', None,
5630 ('f', 'force', None,
5702 _('forget added files, delete modified files')),
5631 _('forget added files, delete modified files')),
5703 ] + subrepoopts + walkopts,
5632 ] + subrepoopts + walkopts,
5704 _('[OPTION]... FILE...'),
5633 _('[OPTION]... FILE...'),
5705 inferrepo=True)
5634 inferrepo=True)
5706 def remove(ui, repo, *pats, **opts):
5635 def remove(ui, repo, *pats, **opts):
5707 """remove the specified files on the next commit
5636 """remove the specified files on the next commit
5708
5637
5709 Schedule the indicated files for removal from the current branch.
5638 Schedule the indicated files for removal from the current branch.
5710
5639
5711 This command schedules the files to be removed at the next commit.
5640 This command schedules the files to be removed at the next commit.
5712 To undo a remove before that, see :hg:`revert`. To undo added
5641 To undo a remove before that, see :hg:`revert`. To undo added
5713 files, see :hg:`forget`.
5642 files, see :hg:`forget`.
5714
5643
5715 .. container:: verbose
5644 .. container:: verbose
5716
5645
5717 -A/--after can be used to remove only files that have already
5646 -A/--after can be used to remove only files that have already
5718 been deleted, -f/--force can be used to force deletion, and -Af
5647 been deleted, -f/--force can be used to force deletion, and -Af
5719 can be used to remove files from the next revision without
5648 can be used to remove files from the next revision without
5720 deleting them from the working directory.
5649 deleting them from the working directory.
5721
5650
5722 The following table details the behavior of remove for different
5651 The following table details the behavior of remove for different
5723 file states (columns) and option combinations (rows). The file
5652 file states (columns) and option combinations (rows). The file
5724 states are Added [A], Clean [C], Modified [M] and Missing [!]
5653 states are Added [A], Clean [C], Modified [M] and Missing [!]
5725 (as reported by :hg:`status`). The actions are Warn, Remove
5654 (as reported by :hg:`status`). The actions are Warn, Remove
5726 (from branch) and Delete (from disk):
5655 (from branch) and Delete (from disk):
5727
5656
5728 ========= == == == ==
5657 ========= == == == ==
5729 opt/state A C M !
5658 opt/state A C M !
5730 ========= == == == ==
5659 ========= == == == ==
5731 none W RD W R
5660 none W RD W R
5732 -f R RD RD R
5661 -f R RD RD R
5733 -A W W W R
5662 -A W W W R
5734 -Af R R R R
5663 -Af R R R R
5735 ========= == == == ==
5664 ========= == == == ==
5736
5665
5737 .. note::
5666 .. note::
5738
5667
5739 :hg:`remove` never deletes files in Added [A] state from the
5668 :hg:`remove` never deletes files in Added [A] state from the
5740 working directory, not even if ``--force`` is specified.
5669 working directory, not even if ``--force`` is specified.
5741
5670
5742 Returns 0 on success, 1 if any warnings encountered.
5671 Returns 0 on success, 1 if any warnings encountered.
5743 """
5672 """
5744
5673
5745 after, force = opts.get('after'), opts.get('force')
5674 after, force = opts.get('after'), opts.get('force')
5746 if not pats and not after:
5675 if not pats and not after:
5747 raise error.Abort(_('no files specified'))
5676 raise error.Abort(_('no files specified'))
5748
5677
5749 m = scmutil.match(repo[None], pats, opts)
5678 m = scmutil.match(repo[None], pats, opts)
5750 subrepos = opts.get('subrepos')
5679 subrepos = opts.get('subrepos')
5751 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5680 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5752
5681
5753 @command('rename|move|mv',
5682 @command('rename|move|mv',
5754 [('A', 'after', None, _('record a rename that has already occurred')),
5683 [('A', 'after', None, _('record a rename that has already occurred')),
5755 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5684 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5756 ] + walkopts + dryrunopts,
5685 ] + walkopts + dryrunopts,
5757 _('[OPTION]... SOURCE... DEST'))
5686 _('[OPTION]... SOURCE... DEST'))
5758 def rename(ui, repo, *pats, **opts):
5687 def rename(ui, repo, *pats, **opts):
5759 """rename files; equivalent of copy + remove
5688 """rename files; equivalent of copy + remove
5760
5689
5761 Mark dest as copies of sources; mark sources for deletion. If dest
5690 Mark dest as copies of sources; mark sources for deletion. If dest
5762 is a directory, copies are put in that directory. If dest is a
5691 is a directory, copies are put in that directory. If dest is a
5763 file, there can only be one source.
5692 file, there can only be one source.
5764
5693
5765 By default, this command copies the contents of files as they
5694 By default, this command copies the contents of files as they
5766 exist in the working directory. If invoked with -A/--after, the
5695 exist in the working directory. If invoked with -A/--after, the
5767 operation is recorded, but no copying is performed.
5696 operation is recorded, but no copying is performed.
5768
5697
5769 This command takes effect at the next commit. To undo a rename
5698 This command takes effect at the next commit. To undo a rename
5770 before that, see :hg:`revert`.
5699 before that, see :hg:`revert`.
5771
5700
5772 Returns 0 on success, 1 if errors are encountered.
5701 Returns 0 on success, 1 if errors are encountered.
5773 """
5702 """
5774 with repo.wlock(False):
5703 with repo.wlock(False):
5775 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5704 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5776
5705
5777 @command('resolve',
5706 @command('resolve',
5778 [('a', 'all', None, _('select all unresolved files')),
5707 [('a', 'all', None, _('select all unresolved files')),
5779 ('l', 'list', None, _('list state of files needing merge')),
5708 ('l', 'list', None, _('list state of files needing merge')),
5780 ('m', 'mark', None, _('mark files as resolved')),
5709 ('m', 'mark', None, _('mark files as resolved')),
5781 ('u', 'unmark', None, _('mark files as unresolved')),
5710 ('u', 'unmark', None, _('mark files as unresolved')),
5782 ('n', 'no-status', None, _('hide status prefix'))]
5711 ('n', 'no-status', None, _('hide status prefix'))]
5783 + mergetoolopts + walkopts + formatteropts,
5712 + mergetoolopts + walkopts + formatteropts,
5784 _('[OPTION]... [FILE]...'),
5713 _('[OPTION]... [FILE]...'),
5785 inferrepo=True)
5714 inferrepo=True)
5786 def resolve(ui, repo, *pats, **opts):
5715 def resolve(ui, repo, *pats, **opts):
5787 """redo merges or set/view the merge status of files
5716 """redo merges or set/view the merge status of files
5788
5717
5789 Merges with unresolved conflicts are often the result of
5718 Merges with unresolved conflicts are often the result of
5790 non-interactive merging using the ``internal:merge`` configuration
5719 non-interactive merging using the ``internal:merge`` configuration
5791 setting, or a command-line merge tool like ``diff3``. The resolve
5720 setting, or a command-line merge tool like ``diff3``. The resolve
5792 command is used to manage the files involved in a merge, after
5721 command is used to manage the files involved in a merge, after
5793 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5722 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5794 working directory must have two parents). See :hg:`help
5723 working directory must have two parents). See :hg:`help
5795 merge-tools` for information on configuring merge tools.
5724 merge-tools` for information on configuring merge tools.
5796
5725
5797 The resolve command can be used in the following ways:
5726 The resolve command can be used in the following ways:
5798
5727
5799 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5728 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5800 files, discarding any previous merge attempts. Re-merging is not
5729 files, discarding any previous merge attempts. Re-merging is not
5801 performed for files already marked as resolved. Use ``--all/-a``
5730 performed for files already marked as resolved. Use ``--all/-a``
5802 to select all unresolved files. ``--tool`` can be used to specify
5731 to select all unresolved files. ``--tool`` can be used to specify
5803 the merge tool used for the given files. It overrides the HGMERGE
5732 the merge tool used for the given files. It overrides the HGMERGE
5804 environment variable and your configuration files. Previous file
5733 environment variable and your configuration files. Previous file
5805 contents are saved with a ``.orig`` suffix.
5734 contents are saved with a ``.orig`` suffix.
5806
5735
5807 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5736 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5808 (e.g. after having manually fixed-up the files). The default is
5737 (e.g. after having manually fixed-up the files). The default is
5809 to mark all unresolved files.
5738 to mark all unresolved files.
5810
5739
5811 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5740 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5812 default is to mark all resolved files.
5741 default is to mark all resolved files.
5813
5742
5814 - :hg:`resolve -l`: list files which had or still have conflicts.
5743 - :hg:`resolve -l`: list files which had or still have conflicts.
5815 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5744 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5816
5745
5817 .. note::
5746 .. note::
5818
5747
5819 Mercurial will not let you commit files with unresolved merge
5748 Mercurial will not let you commit files with unresolved merge
5820 conflicts. You must use :hg:`resolve -m ...` before you can
5749 conflicts. You must use :hg:`resolve -m ...` before you can
5821 commit after a conflicting merge.
5750 commit after a conflicting merge.
5822
5751
5823 Returns 0 on success, 1 if any files fail a resolve attempt.
5752 Returns 0 on success, 1 if any files fail a resolve attempt.
5824 """
5753 """
5825
5754
5826 flaglist = 'all mark unmark list no_status'.split()
5755 flaglist = 'all mark unmark list no_status'.split()
5827 all, mark, unmark, show, nostatus = \
5756 all, mark, unmark, show, nostatus = \
5828 [opts.get(o) for o in flaglist]
5757 [opts.get(o) for o in flaglist]
5829
5758
5830 if (show and (mark or unmark)) or (mark and unmark):
5759 if (show and (mark or unmark)) or (mark and unmark):
5831 raise error.Abort(_("too many options specified"))
5760 raise error.Abort(_("too many options specified"))
5832 if pats and all:
5761 if pats and all:
5833 raise error.Abort(_("can't specify --all and patterns"))
5762 raise error.Abort(_("can't specify --all and patterns"))
5834 if not (all or pats or show or mark or unmark):
5763 if not (all or pats or show or mark or unmark):
5835 raise error.Abort(_('no files or directories specified'),
5764 raise error.Abort(_('no files or directories specified'),
5836 hint=('use --all to re-merge all unresolved files'))
5765 hint=('use --all to re-merge all unresolved files'))
5837
5766
5838 if show:
5767 if show:
5839 fm = ui.formatter('resolve', opts)
5768 fm = ui.formatter('resolve', opts)
5840 ms = mergemod.mergestate.read(repo)
5769 ms = mergemod.mergestate.read(repo)
5841 m = scmutil.match(repo[None], pats, opts)
5770 m = scmutil.match(repo[None], pats, opts)
5842 for f in ms:
5771 for f in ms:
5843 if not m(f):
5772 if not m(f):
5844 continue
5773 continue
5845 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5774 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5846 'd': 'driverresolved'}[ms[f]]
5775 'd': 'driverresolved'}[ms[f]]
5847 fm.startitem()
5776 fm.startitem()
5848 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5777 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5849 fm.write('path', '%s\n', f, label=l)
5778 fm.write('path', '%s\n', f, label=l)
5850 fm.end()
5779 fm.end()
5851 return 0
5780 return 0
5852
5781
5853 with repo.wlock():
5782 with repo.wlock():
5854 ms = mergemod.mergestate.read(repo)
5783 ms = mergemod.mergestate.read(repo)
5855
5784
5856 if not (ms.active() or repo.dirstate.p2() != nullid):
5785 if not (ms.active() or repo.dirstate.p2() != nullid):
5857 raise error.Abort(
5786 raise error.Abort(
5858 _('resolve command not applicable when not merging'))
5787 _('resolve command not applicable when not merging'))
5859
5788
5860 wctx = repo[None]
5789 wctx = repo[None]
5861
5790
5862 if ms.mergedriver and ms.mdstate() == 'u':
5791 if ms.mergedriver and ms.mdstate() == 'u':
5863 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5792 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5864 ms.commit()
5793 ms.commit()
5865 # allow mark and unmark to go through
5794 # allow mark and unmark to go through
5866 if not mark and not unmark and not proceed:
5795 if not mark and not unmark and not proceed:
5867 return 1
5796 return 1
5868
5797
5869 m = scmutil.match(wctx, pats, opts)
5798 m = scmutil.match(wctx, pats, opts)
5870 ret = 0
5799 ret = 0
5871 didwork = False
5800 didwork = False
5872 runconclude = False
5801 runconclude = False
5873
5802
5874 tocomplete = []
5803 tocomplete = []
5875 for f in ms:
5804 for f in ms:
5876 if not m(f):
5805 if not m(f):
5877 continue
5806 continue
5878
5807
5879 didwork = True
5808 didwork = True
5880
5809
5881 # don't let driver-resolved files be marked, and run the conclude
5810 # don't let driver-resolved files be marked, and run the conclude
5882 # step if asked to resolve
5811 # step if asked to resolve
5883 if ms[f] == "d":
5812 if ms[f] == "d":
5884 exact = m.exact(f)
5813 exact = m.exact(f)
5885 if mark:
5814 if mark:
5886 if exact:
5815 if exact:
5887 ui.warn(_('not marking %s as it is driver-resolved\n')
5816 ui.warn(_('not marking %s as it is driver-resolved\n')
5888 % f)
5817 % f)
5889 elif unmark:
5818 elif unmark:
5890 if exact:
5819 if exact:
5891 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5820 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5892 % f)
5821 % f)
5893 else:
5822 else:
5894 runconclude = True
5823 runconclude = True
5895 continue
5824 continue
5896
5825
5897 if mark:
5826 if mark:
5898 ms.mark(f, "r")
5827 ms.mark(f, "r")
5899 elif unmark:
5828 elif unmark:
5900 ms.mark(f, "u")
5829 ms.mark(f, "u")
5901 else:
5830 else:
5902 # backup pre-resolve (merge uses .orig for its own purposes)
5831 # backup pre-resolve (merge uses .orig for its own purposes)
5903 a = repo.wjoin(f)
5832 a = repo.wjoin(f)
5904 try:
5833 try:
5905 util.copyfile(a, a + ".resolve")
5834 util.copyfile(a, a + ".resolve")
5906 except (IOError, OSError) as inst:
5835 except (IOError, OSError) as inst:
5907 if inst.errno != errno.ENOENT:
5836 if inst.errno != errno.ENOENT:
5908 raise
5837 raise
5909
5838
5910 try:
5839 try:
5911 # preresolve file
5840 # preresolve file
5912 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5841 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5913 'resolve')
5842 'resolve')
5914 complete, r = ms.preresolve(f, wctx)
5843 complete, r = ms.preresolve(f, wctx)
5915 if not complete:
5844 if not complete:
5916 tocomplete.append(f)
5845 tocomplete.append(f)
5917 elif r:
5846 elif r:
5918 ret = 1
5847 ret = 1
5919 finally:
5848 finally:
5920 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5849 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5921 ms.commit()
5850 ms.commit()
5922
5851
5923 # replace filemerge's .orig file with our resolve file, but only
5852 # replace filemerge's .orig file with our resolve file, but only
5924 # for merges that are complete
5853 # for merges that are complete
5925 if complete:
5854 if complete:
5926 try:
5855 try:
5927 util.rename(a + ".resolve",
5856 util.rename(a + ".resolve",
5928 scmutil.origpath(ui, repo, a))
5857 scmutil.origpath(ui, repo, a))
5929 except OSError as inst:
5858 except OSError as inst:
5930 if inst.errno != errno.ENOENT:
5859 if inst.errno != errno.ENOENT:
5931 raise
5860 raise
5932
5861
5933 for f in tocomplete:
5862 for f in tocomplete:
5934 try:
5863 try:
5935 # resolve file
5864 # resolve file
5936 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5865 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5937 'resolve')
5866 'resolve')
5938 r = ms.resolve(f, wctx)
5867 r = ms.resolve(f, wctx)
5939 if r:
5868 if r:
5940 ret = 1
5869 ret = 1
5941 finally:
5870 finally:
5942 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5871 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5943 ms.commit()
5872 ms.commit()
5944
5873
5945 # replace filemerge's .orig file with our resolve file
5874 # replace filemerge's .orig file with our resolve file
5946 a = repo.wjoin(f)
5875 a = repo.wjoin(f)
5947 try:
5876 try:
5948 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5877 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5949 except OSError as inst:
5878 except OSError as inst:
5950 if inst.errno != errno.ENOENT:
5879 if inst.errno != errno.ENOENT:
5951 raise
5880 raise
5952
5881
5953 ms.commit()
5882 ms.commit()
5954 ms.recordactions()
5883 ms.recordactions()
5955
5884
5956 if not didwork and pats:
5885 if not didwork and pats:
5957 hint = None
5886 hint = None
5958 if not any([p for p in pats if p.find(':') >= 0]):
5887 if not any([p for p in pats if p.find(':') >= 0]):
5959 pats = ['path:%s' % p for p in pats]
5888 pats = ['path:%s' % p for p in pats]
5960 m = scmutil.match(wctx, pats, opts)
5889 m = scmutil.match(wctx, pats, opts)
5961 for f in ms:
5890 for f in ms:
5962 if not m(f):
5891 if not m(f):
5963 continue
5892 continue
5964 flags = ''.join(['-%s ' % o[0] for o in flaglist
5893 flags = ''.join(['-%s ' % o[0] for o in flaglist
5965 if opts.get(o)])
5894 if opts.get(o)])
5966 hint = _("(try: hg resolve %s%s)\n") % (
5895 hint = _("(try: hg resolve %s%s)\n") % (
5967 flags,
5896 flags,
5968 ' '.join(pats))
5897 ' '.join(pats))
5969 break
5898 break
5970 ui.warn(_("arguments do not match paths that need resolving\n"))
5899 ui.warn(_("arguments do not match paths that need resolving\n"))
5971 if hint:
5900 if hint:
5972 ui.warn(hint)
5901 ui.warn(hint)
5973 elif ms.mergedriver and ms.mdstate() != 's':
5902 elif ms.mergedriver and ms.mdstate() != 's':
5974 # run conclude step when either a driver-resolved file is requested
5903 # run conclude step when either a driver-resolved file is requested
5975 # or there are no driver-resolved files
5904 # or there are no driver-resolved files
5976 # we can't use 'ret' to determine whether any files are unresolved
5905 # we can't use 'ret' to determine whether any files are unresolved
5977 # because we might not have tried to resolve some
5906 # because we might not have tried to resolve some
5978 if ((runconclude or not list(ms.driverresolved()))
5907 if ((runconclude or not list(ms.driverresolved()))
5979 and not list(ms.unresolved())):
5908 and not list(ms.unresolved())):
5980 proceed = mergemod.driverconclude(repo, ms, wctx)
5909 proceed = mergemod.driverconclude(repo, ms, wctx)
5981 ms.commit()
5910 ms.commit()
5982 if not proceed:
5911 if not proceed:
5983 return 1
5912 return 1
5984
5913
5985 # Nudge users into finishing an unfinished operation
5914 # Nudge users into finishing an unfinished operation
5986 unresolvedf = list(ms.unresolved())
5915 unresolvedf = list(ms.unresolved())
5987 driverresolvedf = list(ms.driverresolved())
5916 driverresolvedf = list(ms.driverresolved())
5988 if not unresolvedf and not driverresolvedf:
5917 if not unresolvedf and not driverresolvedf:
5989 ui.status(_('(no more unresolved files)\n'))
5918 ui.status(_('(no more unresolved files)\n'))
5990 cmdutil.checkafterresolved(repo)
5919 cmdutil.checkafterresolved(repo)
5991 elif not unresolvedf:
5920 elif not unresolvedf:
5992 ui.status(_('(no more unresolved files -- '
5921 ui.status(_('(no more unresolved files -- '
5993 'run "hg resolve --all" to conclude)\n'))
5922 'run "hg resolve --all" to conclude)\n'))
5994
5923
5995 return ret
5924 return ret
5996
5925
5997 @command('revert',
5926 @command('revert',
5998 [('a', 'all', None, _('revert all changes when no arguments given')),
5927 [('a', 'all', None, _('revert all changes when no arguments given')),
5999 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5928 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6000 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5929 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6001 ('C', 'no-backup', None, _('do not save backup copies of files')),
5930 ('C', 'no-backup', None, _('do not save backup copies of files')),
6002 ('i', 'interactive', None,
5931 ('i', 'interactive', None,
6003 _('interactively select the changes (EXPERIMENTAL)')),
5932 _('interactively select the changes (EXPERIMENTAL)')),
6004 ] + walkopts + dryrunopts,
5933 ] + walkopts + dryrunopts,
6005 _('[OPTION]... [-r REV] [NAME]...'))
5934 _('[OPTION]... [-r REV] [NAME]...'))
6006 def revert(ui, repo, *pats, **opts):
5935 def revert(ui, repo, *pats, **opts):
6007 """restore files to their checkout state
5936 """restore files to their checkout state
6008
5937
6009 .. note::
5938 .. note::
6010
5939
6011 To check out earlier revisions, you should use :hg:`update REV`.
5940 To check out earlier revisions, you should use :hg:`update REV`.
6012 To cancel an uncommitted merge (and lose your changes),
5941 To cancel an uncommitted merge (and lose your changes),
6013 use :hg:`update --clean .`.
5942 use :hg:`update --clean .`.
6014
5943
6015 With no revision specified, revert the specified files or directories
5944 With no revision specified, revert the specified files or directories
6016 to the contents they had in the parent of the working directory.
5945 to the contents they had in the parent of the working directory.
6017 This restores the contents of files to an unmodified
5946 This restores the contents of files to an unmodified
6018 state and unschedules adds, removes, copies, and renames. If the
5947 state and unschedules adds, removes, copies, and renames. If the
6019 working directory has two parents, you must explicitly specify a
5948 working directory has two parents, you must explicitly specify a
6020 revision.
5949 revision.
6021
5950
6022 Using the -r/--rev or -d/--date options, revert the given files or
5951 Using the -r/--rev or -d/--date options, revert the given files or
6023 directories to their states as of a specific revision. Because
5952 directories to their states as of a specific revision. Because
6024 revert does not change the working directory parents, this will
5953 revert does not change the working directory parents, this will
6025 cause these files to appear modified. This can be helpful to "back
5954 cause these files to appear modified. This can be helpful to "back
6026 out" some or all of an earlier change. See :hg:`backout` for a
5955 out" some or all of an earlier change. See :hg:`backout` for a
6027 related method.
5956 related method.
6028
5957
6029 Modified files are saved with a .orig suffix before reverting.
5958 Modified files are saved with a .orig suffix before reverting.
6030 To disable these backups, use --no-backup. It is possible to store
5959 To disable these backups, use --no-backup. It is possible to store
6031 the backup files in a custom directory relative to the root of the
5960 the backup files in a custom directory relative to the root of the
6032 repository by setting the ``ui.origbackuppath`` configuration
5961 repository by setting the ``ui.origbackuppath`` configuration
6033 option.
5962 option.
6034
5963
6035 See :hg:`help dates` for a list of formats valid for -d/--date.
5964 See :hg:`help dates` for a list of formats valid for -d/--date.
6036
5965
6037 See :hg:`help backout` for a way to reverse the effect of an
5966 See :hg:`help backout` for a way to reverse the effect of an
6038 earlier changeset.
5967 earlier changeset.
6039
5968
6040 Returns 0 on success.
5969 Returns 0 on success.
6041 """
5970 """
6042
5971
6043 if opts.get("date"):
5972 if opts.get("date"):
6044 if opts.get("rev"):
5973 if opts.get("rev"):
6045 raise error.Abort(_("you can't specify a revision and a date"))
5974 raise error.Abort(_("you can't specify a revision and a date"))
6046 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5975 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6047
5976
6048 parent, p2 = repo.dirstate.parents()
5977 parent, p2 = repo.dirstate.parents()
6049 if not opts.get('rev') and p2 != nullid:
5978 if not opts.get('rev') and p2 != nullid:
6050 # revert after merge is a trap for new users (issue2915)
5979 # revert after merge is a trap for new users (issue2915)
6051 raise error.Abort(_('uncommitted merge with no revision specified'),
5980 raise error.Abort(_('uncommitted merge with no revision specified'),
6052 hint=_("use 'hg update' or see 'hg help revert'"))
5981 hint=_("use 'hg update' or see 'hg help revert'"))
6053
5982
6054 ctx = scmutil.revsingle(repo, opts.get('rev'))
5983 ctx = scmutil.revsingle(repo, opts.get('rev'))
6055
5984
6056 if (not (pats or opts.get('include') or opts.get('exclude') or
5985 if (not (pats or opts.get('include') or opts.get('exclude') or
6057 opts.get('all') or opts.get('interactive'))):
5986 opts.get('all') or opts.get('interactive'))):
6058 msg = _("no files or directories specified")
5987 msg = _("no files or directories specified")
6059 if p2 != nullid:
5988 if p2 != nullid:
6060 hint = _("uncommitted merge, use --all to discard all changes,"
5989 hint = _("uncommitted merge, use --all to discard all changes,"
6061 " or 'hg update -C .' to abort the merge")
5990 " or 'hg update -C .' to abort the merge")
6062 raise error.Abort(msg, hint=hint)
5991 raise error.Abort(msg, hint=hint)
6063 dirty = any(repo.status())
5992 dirty = any(repo.status())
6064 node = ctx.node()
5993 node = ctx.node()
6065 if node != parent:
5994 if node != parent:
6066 if dirty:
5995 if dirty:
6067 hint = _("uncommitted changes, use --all to discard all"
5996 hint = _("uncommitted changes, use --all to discard all"
6068 " changes, or 'hg update %s' to update") % ctx.rev()
5997 " changes, or 'hg update %s' to update") % ctx.rev()
6069 else:
5998 else:
6070 hint = _("use --all to revert all files,"
5999 hint = _("use --all to revert all files,"
6071 " or 'hg update %s' to update") % ctx.rev()
6000 " or 'hg update %s' to update") % ctx.rev()
6072 elif dirty:
6001 elif dirty:
6073 hint = _("uncommitted changes, use --all to discard all changes")
6002 hint = _("uncommitted changes, use --all to discard all changes")
6074 else:
6003 else:
6075 hint = _("use --all to revert all files")
6004 hint = _("use --all to revert all files")
6076 raise error.Abort(msg, hint=hint)
6005 raise error.Abort(msg, hint=hint)
6077
6006
6078 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6007 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6079
6008
6080 @command('rollback', dryrunopts +
6009 @command('rollback', dryrunopts +
6081 [('f', 'force', False, _('ignore safety measures'))])
6010 [('f', 'force', False, _('ignore safety measures'))])
6082 def rollback(ui, repo, **opts):
6011 def rollback(ui, repo, **opts):
6083 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6012 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6084
6013
6085 Please use :hg:`commit --amend` instead of rollback to correct
6014 Please use :hg:`commit --amend` instead of rollback to correct
6086 mistakes in the last commit.
6015 mistakes in the last commit.
6087
6016
6088 This command should be used with care. There is only one level of
6017 This command should be used with care. There is only one level of
6089 rollback, and there is no way to undo a rollback. It will also
6018 rollback, and there is no way to undo a rollback. It will also
6090 restore the dirstate at the time of the last transaction, losing
6019 restore the dirstate at the time of the last transaction, losing
6091 any dirstate changes since that time. This command does not alter
6020 any dirstate changes since that time. This command does not alter
6092 the working directory.
6021 the working directory.
6093
6022
6094 Transactions are used to encapsulate the effects of all commands
6023 Transactions are used to encapsulate the effects of all commands
6095 that create new changesets or propagate existing changesets into a
6024 that create new changesets or propagate existing changesets into a
6096 repository.
6025 repository.
6097
6026
6098 .. container:: verbose
6027 .. container:: verbose
6099
6028
6100 For example, the following commands are transactional, and their
6029 For example, the following commands are transactional, and their
6101 effects can be rolled back:
6030 effects can be rolled back:
6102
6031
6103 - commit
6032 - commit
6104 - import
6033 - import
6105 - pull
6034 - pull
6106 - push (with this repository as the destination)
6035 - push (with this repository as the destination)
6107 - unbundle
6036 - unbundle
6108
6037
6109 To avoid permanent data loss, rollback will refuse to rollback a
6038 To avoid permanent data loss, rollback will refuse to rollback a
6110 commit transaction if it isn't checked out. Use --force to
6039 commit transaction if it isn't checked out. Use --force to
6111 override this protection.
6040 override this protection.
6112
6041
6113 The rollback command can be entirely disabled by setting the
6042 The rollback command can be entirely disabled by setting the
6114 ``ui.rollback`` configuration setting to false. If you're here
6043 ``ui.rollback`` configuration setting to false. If you're here
6115 because you want to use rollback and it's disabled, you can
6044 because you want to use rollback and it's disabled, you can
6116 re-enable the command by setting ``ui.rollback`` to true.
6045 re-enable the command by setting ``ui.rollback`` to true.
6117
6046
6118 This command is not intended for use on public repositories. Once
6047 This command is not intended for use on public repositories. Once
6119 changes are visible for pull by other users, rolling a transaction
6048 changes are visible for pull by other users, rolling a transaction
6120 back locally is ineffective (someone else may already have pulled
6049 back locally is ineffective (someone else may already have pulled
6121 the changes). Furthermore, a race is possible with readers of the
6050 the changes). Furthermore, a race is possible with readers of the
6122 repository; for example an in-progress pull from the repository
6051 repository; for example an in-progress pull from the repository
6123 may fail if a rollback is performed.
6052 may fail if a rollback is performed.
6124
6053
6125 Returns 0 on success, 1 if no rollback data is available.
6054 Returns 0 on success, 1 if no rollback data is available.
6126 """
6055 """
6127 if not ui.configbool('ui', 'rollback', True):
6056 if not ui.configbool('ui', 'rollback', True):
6128 raise error.Abort(_('rollback is disabled because it is unsafe'),
6057 raise error.Abort(_('rollback is disabled because it is unsafe'),
6129 hint=('see `hg help -v rollback` for information'))
6058 hint=('see `hg help -v rollback` for information'))
6130 return repo.rollback(dryrun=opts.get('dry_run'),
6059 return repo.rollback(dryrun=opts.get('dry_run'),
6131 force=opts.get('force'))
6060 force=opts.get('force'))
6132
6061
6133 @command('root', [])
6062 @command('root', [])
6134 def root(ui, repo):
6063 def root(ui, repo):
6135 """print the root (top) of the current working directory
6064 """print the root (top) of the current working directory
6136
6065
6137 Print the root directory of the current repository.
6066 Print the root directory of the current repository.
6138
6067
6139 Returns 0 on success.
6068 Returns 0 on success.
6140 """
6069 """
6141 ui.write(repo.root + "\n")
6070 ui.write(repo.root + "\n")
6142
6071
6143 @command('^serve',
6072 @command('^serve',
6144 [('A', 'accesslog', '', _('name of access log file to write to'),
6073 [('A', 'accesslog', '', _('name of access log file to write to'),
6145 _('FILE')),
6074 _('FILE')),
6146 ('d', 'daemon', None, _('run server in background')),
6075 ('d', 'daemon', None, _('run server in background')),
6147 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6076 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
6148 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6077 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6149 # use string type, then we can check if something was passed
6078 # use string type, then we can check if something was passed
6150 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6079 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6151 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6080 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6152 _('ADDR')),
6081 _('ADDR')),
6153 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6082 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6154 _('PREFIX')),
6083 _('PREFIX')),
6155 ('n', 'name', '',
6084 ('n', 'name', '',
6156 _('name to show in web pages (default: working directory)'), _('NAME')),
6085 _('name to show in web pages (default: working directory)'), _('NAME')),
6157 ('', 'web-conf', '',
6086 ('', 'web-conf', '',
6158 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6087 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
6159 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6088 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6160 _('FILE')),
6089 _('FILE')),
6161 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6090 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6162 ('', 'stdio', None, _('for remote clients')),
6091 ('', 'stdio', None, _('for remote clients')),
6163 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6092 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6164 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6093 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6165 ('', 'style', '', _('template style to use'), _('STYLE')),
6094 ('', 'style', '', _('template style to use'), _('STYLE')),
6166 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6095 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6167 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6096 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6168 _('[OPTION]...'),
6097 _('[OPTION]...'),
6169 optionalrepo=True)
6098 optionalrepo=True)
6170 def serve(ui, repo, **opts):
6099 def serve(ui, repo, **opts):
6171 """start stand-alone webserver
6100 """start stand-alone webserver
6172
6101
6173 Start a local HTTP repository browser and pull server. You can use
6102 Start a local HTTP repository browser and pull server. You can use
6174 this for ad-hoc sharing and browsing of repositories. It is
6103 this for ad-hoc sharing and browsing of repositories. It is
6175 recommended to use a real web server to serve a repository for
6104 recommended to use a real web server to serve a repository for
6176 longer periods of time.
6105 longer periods of time.
6177
6106
6178 Please note that the server does not implement access control.
6107 Please note that the server does not implement access control.
6179 This means that, by default, anybody can read from the server and
6108 This means that, by default, anybody can read from the server and
6180 nobody can write to it by default. Set the ``web.allow_push``
6109 nobody can write to it by default. Set the ``web.allow_push``
6181 option to ``*`` to allow everybody to push to the server. You
6110 option to ``*`` to allow everybody to push to the server. You
6182 should use a real web server if you need to authenticate users.
6111 should use a real web server if you need to authenticate users.
6183
6112
6184 By default, the server logs accesses to stdout and errors to
6113 By default, the server logs accesses to stdout and errors to
6185 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6114 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6186 files.
6115 files.
6187
6116
6188 To have the server choose a free port number to listen on, specify
6117 To have the server choose a free port number to listen on, specify
6189 a port number of 0; in this case, the server will print the port
6118 a port number of 0; in this case, the server will print the port
6190 number it uses.
6119 number it uses.
6191
6120
6192 Returns 0 on success.
6121 Returns 0 on success.
6193 """
6122 """
6194
6123
6195 if opts["stdio"] and opts["cmdserver"]:
6124 if opts["stdio"] and opts["cmdserver"]:
6196 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6125 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6197
6126
6198 if opts["stdio"]:
6127 if opts["stdio"]:
6199 if repo is None:
6128 if repo is None:
6200 raise error.RepoError(_("there is no Mercurial repository here"
6129 raise error.RepoError(_("there is no Mercurial repository here"
6201 " (.hg not found)"))
6130 " (.hg not found)"))
6202 s = sshserver.sshserver(ui, repo)
6131 s = sshserver.sshserver(ui, repo)
6203 s.serve_forever()
6132 s.serve_forever()
6204
6133
6205 service = server.createservice(ui, repo, opts)
6134 service = server.createservice(ui, repo, opts)
6206 return server.runservice(opts, initfn=service.init, runfn=service.run)
6135 return server.runservice(opts, initfn=service.init, runfn=service.run)
6207
6136
6208 @command('^status|st',
6137 @command('^status|st',
6209 [('A', 'all', None, _('show status of all files')),
6138 [('A', 'all', None, _('show status of all files')),
6210 ('m', 'modified', None, _('show only modified files')),
6139 ('m', 'modified', None, _('show only modified files')),
6211 ('a', 'added', None, _('show only added files')),
6140 ('a', 'added', None, _('show only added files')),
6212 ('r', 'removed', None, _('show only removed files')),
6141 ('r', 'removed', None, _('show only removed files')),
6213 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6142 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6214 ('c', 'clean', None, _('show only files without changes')),
6143 ('c', 'clean', None, _('show only files without changes')),
6215 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6144 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6216 ('i', 'ignored', None, _('show only ignored files')),
6145 ('i', 'ignored', None, _('show only ignored files')),
6217 ('n', 'no-status', None, _('hide status prefix')),
6146 ('n', 'no-status', None, _('hide status prefix')),
6218 ('C', 'copies', None, _('show source of copied files')),
6147 ('C', 'copies', None, _('show source of copied files')),
6219 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6148 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6220 ('', 'rev', [], _('show difference from revision'), _('REV')),
6149 ('', 'rev', [], _('show difference from revision'), _('REV')),
6221 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6150 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6222 ] + walkopts + subrepoopts + formatteropts,
6151 ] + walkopts + subrepoopts + formatteropts,
6223 _('[OPTION]... [FILE]...'),
6152 _('[OPTION]... [FILE]...'),
6224 inferrepo=True)
6153 inferrepo=True)
6225 def status(ui, repo, *pats, **opts):
6154 def status(ui, repo, *pats, **opts):
6226 """show changed files in the working directory
6155 """show changed files in the working directory
6227
6156
6228 Show status of files in the repository. If names are given, only
6157 Show status of files in the repository. If names are given, only
6229 files that match are shown. Files that are clean or ignored or
6158 files that match are shown. Files that are clean or ignored or
6230 the source of a copy/move operation, are not listed unless
6159 the source of a copy/move operation, are not listed unless
6231 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6160 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6232 Unless options described with "show only ..." are given, the
6161 Unless options described with "show only ..." are given, the
6233 options -mardu are used.
6162 options -mardu are used.
6234
6163
6235 Option -q/--quiet hides untracked (unknown and ignored) files
6164 Option -q/--quiet hides untracked (unknown and ignored) files
6236 unless explicitly requested with -u/--unknown or -i/--ignored.
6165 unless explicitly requested with -u/--unknown or -i/--ignored.
6237
6166
6238 .. note::
6167 .. note::
6239
6168
6240 :hg:`status` may appear to disagree with diff if permissions have
6169 :hg:`status` may appear to disagree with diff if permissions have
6241 changed or a merge has occurred. The standard diff format does
6170 changed or a merge has occurred. The standard diff format does
6242 not report permission changes and diff only reports changes
6171 not report permission changes and diff only reports changes
6243 relative to one merge parent.
6172 relative to one merge parent.
6244
6173
6245 If one revision is given, it is used as the base revision.
6174 If one revision is given, it is used as the base revision.
6246 If two revisions are given, the differences between them are
6175 If two revisions are given, the differences between them are
6247 shown. The --change option can also be used as a shortcut to list
6176 shown. The --change option can also be used as a shortcut to list
6248 the changed files of a revision from its first parent.
6177 the changed files of a revision from its first parent.
6249
6178
6250 The codes used to show the status of files are::
6179 The codes used to show the status of files are::
6251
6180
6252 M = modified
6181 M = modified
6253 A = added
6182 A = added
6254 R = removed
6183 R = removed
6255 C = clean
6184 C = clean
6256 ! = missing (deleted by non-hg command, but still tracked)
6185 ! = missing (deleted by non-hg command, but still tracked)
6257 ? = not tracked
6186 ? = not tracked
6258 I = ignored
6187 I = ignored
6259 = origin of the previous file (with --copies)
6188 = origin of the previous file (with --copies)
6260
6189
6261 .. container:: verbose
6190 .. container:: verbose
6262
6191
6263 Examples:
6192 Examples:
6264
6193
6265 - show changes in the working directory relative to a
6194 - show changes in the working directory relative to a
6266 changeset::
6195 changeset::
6267
6196
6268 hg status --rev 9353
6197 hg status --rev 9353
6269
6198
6270 - show changes in the working directory relative to the
6199 - show changes in the working directory relative to the
6271 current directory (see :hg:`help patterns` for more information)::
6200 current directory (see :hg:`help patterns` for more information)::
6272
6201
6273 hg status re:
6202 hg status re:
6274
6203
6275 - show all changes including copies in an existing changeset::
6204 - show all changes including copies in an existing changeset::
6276
6205
6277 hg status --copies --change 9353
6206 hg status --copies --change 9353
6278
6207
6279 - get a NUL separated list of added files, suitable for xargs::
6208 - get a NUL separated list of added files, suitable for xargs::
6280
6209
6281 hg status -an0
6210 hg status -an0
6282
6211
6283 Returns 0 on success.
6212 Returns 0 on success.
6284 """
6213 """
6285
6214
6286 revs = opts.get('rev')
6215 revs = opts.get('rev')
6287 change = opts.get('change')
6216 change = opts.get('change')
6288
6217
6289 if revs and change:
6218 if revs and change:
6290 msg = _('cannot specify --rev and --change at the same time')
6219 msg = _('cannot specify --rev and --change at the same time')
6291 raise error.Abort(msg)
6220 raise error.Abort(msg)
6292 elif change:
6221 elif change:
6293 node2 = scmutil.revsingle(repo, change, None).node()
6222 node2 = scmutil.revsingle(repo, change, None).node()
6294 node1 = repo[node2].p1().node()
6223 node1 = repo[node2].p1().node()
6295 else:
6224 else:
6296 node1, node2 = scmutil.revpair(repo, revs)
6225 node1, node2 = scmutil.revpair(repo, revs)
6297
6226
6298 if pats:
6227 if pats:
6299 cwd = repo.getcwd()
6228 cwd = repo.getcwd()
6300 else:
6229 else:
6301 cwd = ''
6230 cwd = ''
6302
6231
6303 if opts.get('print0'):
6232 if opts.get('print0'):
6304 end = '\0'
6233 end = '\0'
6305 else:
6234 else:
6306 end = '\n'
6235 end = '\n'
6307 copy = {}
6236 copy = {}
6308 states = 'modified added removed deleted unknown ignored clean'.split()
6237 states = 'modified added removed deleted unknown ignored clean'.split()
6309 show = [k for k in states if opts.get(k)]
6238 show = [k for k in states if opts.get(k)]
6310 if opts.get('all'):
6239 if opts.get('all'):
6311 show += ui.quiet and (states[:4] + ['clean']) or states
6240 show += ui.quiet and (states[:4] + ['clean']) or states
6312 if not show:
6241 if not show:
6313 if ui.quiet:
6242 if ui.quiet:
6314 show = states[:4]
6243 show = states[:4]
6315 else:
6244 else:
6316 show = states[:5]
6245 show = states[:5]
6317
6246
6318 m = scmutil.match(repo[node2], pats, opts)
6247 m = scmutil.match(repo[node2], pats, opts)
6319 stat = repo.status(node1, node2, m,
6248 stat = repo.status(node1, node2, m,
6320 'ignored' in show, 'clean' in show, 'unknown' in show,
6249 'ignored' in show, 'clean' in show, 'unknown' in show,
6321 opts.get('subrepos'))
6250 opts.get('subrepos'))
6322 changestates = zip(states, 'MAR!?IC', stat)
6251 changestates = zip(states, 'MAR!?IC', stat)
6323
6252
6324 if (opts.get('all') or opts.get('copies')
6253 if (opts.get('all') or opts.get('copies')
6325 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6254 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6326 copy = copies.pathcopies(repo[node1], repo[node2], m)
6255 copy = copies.pathcopies(repo[node1], repo[node2], m)
6327
6256
6328 fm = ui.formatter('status', opts)
6257 fm = ui.formatter('status', opts)
6329 fmt = '%s' + end
6258 fmt = '%s' + end
6330 showchar = not opts.get('no_status')
6259 showchar = not opts.get('no_status')
6331
6260
6332 for state, char, files in changestates:
6261 for state, char, files in changestates:
6333 if state in show:
6262 if state in show:
6334 label = 'status.' + state
6263 label = 'status.' + state
6335 for f in files:
6264 for f in files:
6336 fm.startitem()
6265 fm.startitem()
6337 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6266 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6338 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6267 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6339 if f in copy:
6268 if f in copy:
6340 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6269 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6341 label='status.copied')
6270 label='status.copied')
6342 fm.end()
6271 fm.end()
6343
6272
6344 @command('^summary|sum',
6273 @command('^summary|sum',
6345 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6274 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6346 def summary(ui, repo, **opts):
6275 def summary(ui, repo, **opts):
6347 """summarize working directory state
6276 """summarize working directory state
6348
6277
6349 This generates a brief summary of the working directory state,
6278 This generates a brief summary of the working directory state,
6350 including parents, branch, commit status, phase and available updates.
6279 including parents, branch, commit status, phase and available updates.
6351
6280
6352 With the --remote option, this will check the default paths for
6281 With the --remote option, this will check the default paths for
6353 incoming and outgoing changes. This can be time-consuming.
6282 incoming and outgoing changes. This can be time-consuming.
6354
6283
6355 Returns 0 on success.
6284 Returns 0 on success.
6356 """
6285 """
6357
6286
6358 ctx = repo[None]
6287 ctx = repo[None]
6359 parents = ctx.parents()
6288 parents = ctx.parents()
6360 pnode = parents[0].node()
6289 pnode = parents[0].node()
6361 marks = []
6290 marks = []
6362
6291
6363 ms = None
6292 ms = None
6364 try:
6293 try:
6365 ms = mergemod.mergestate.read(repo)
6294 ms = mergemod.mergestate.read(repo)
6366 except error.UnsupportedMergeRecords as e:
6295 except error.UnsupportedMergeRecords as e:
6367 s = ' '.join(e.recordtypes)
6296 s = ' '.join(e.recordtypes)
6368 ui.warn(
6297 ui.warn(
6369 _('warning: merge state has unsupported record types: %s\n') % s)
6298 _('warning: merge state has unsupported record types: %s\n') % s)
6370 unresolved = 0
6299 unresolved = 0
6371 else:
6300 else:
6372 unresolved = [f for f in ms if ms[f] == 'u']
6301 unresolved = [f for f in ms if ms[f] == 'u']
6373
6302
6374 for p in parents:
6303 for p in parents:
6375 # label with log.changeset (instead of log.parent) since this
6304 # label with log.changeset (instead of log.parent) since this
6376 # shows a working directory parent *changeset*:
6305 # shows a working directory parent *changeset*:
6377 # i18n: column positioning for "hg summary"
6306 # i18n: column positioning for "hg summary"
6378 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6307 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6379 label='log.changeset changeset.%s' % p.phasestr())
6308 label='log.changeset changeset.%s' % p.phasestr())
6380 ui.write(' '.join(p.tags()), label='log.tag')
6309 ui.write(' '.join(p.tags()), label='log.tag')
6381 if p.bookmarks():
6310 if p.bookmarks():
6382 marks.extend(p.bookmarks())
6311 marks.extend(p.bookmarks())
6383 if p.rev() == -1:
6312 if p.rev() == -1:
6384 if not len(repo):
6313 if not len(repo):
6385 ui.write(_(' (empty repository)'))
6314 ui.write(_(' (empty repository)'))
6386 else:
6315 else:
6387 ui.write(_(' (no revision checked out)'))
6316 ui.write(_(' (no revision checked out)'))
6388 ui.write('\n')
6317 ui.write('\n')
6389 if p.description():
6318 if p.description():
6390 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6319 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6391 label='log.summary')
6320 label='log.summary')
6392
6321
6393 branch = ctx.branch()
6322 branch = ctx.branch()
6394 bheads = repo.branchheads(branch)
6323 bheads = repo.branchheads(branch)
6395 # i18n: column positioning for "hg summary"
6324 # i18n: column positioning for "hg summary"
6396 m = _('branch: %s\n') % branch
6325 m = _('branch: %s\n') % branch
6397 if branch != 'default':
6326 if branch != 'default':
6398 ui.write(m, label='log.branch')
6327 ui.write(m, label='log.branch')
6399 else:
6328 else:
6400 ui.status(m, label='log.branch')
6329 ui.status(m, label='log.branch')
6401
6330
6402 if marks:
6331 if marks:
6403 active = repo._activebookmark
6332 active = repo._activebookmark
6404 # i18n: column positioning for "hg summary"
6333 # i18n: column positioning for "hg summary"
6405 ui.write(_('bookmarks:'), label='log.bookmark')
6334 ui.write(_('bookmarks:'), label='log.bookmark')
6406 if active is not None:
6335 if active is not None:
6407 if active in marks:
6336 if active in marks:
6408 ui.write(' *' + active, label=activebookmarklabel)
6337 ui.write(' *' + active, label=activebookmarklabel)
6409 marks.remove(active)
6338 marks.remove(active)
6410 else:
6339 else:
6411 ui.write(' [%s]' % active, label=activebookmarklabel)
6340 ui.write(' [%s]' % active, label=activebookmarklabel)
6412 for m in marks:
6341 for m in marks:
6413 ui.write(' ' + m, label='log.bookmark')
6342 ui.write(' ' + m, label='log.bookmark')
6414 ui.write('\n', label='log.bookmark')
6343 ui.write('\n', label='log.bookmark')
6415
6344
6416 status = repo.status(unknown=True)
6345 status = repo.status(unknown=True)
6417
6346
6418 c = repo.dirstate.copies()
6347 c = repo.dirstate.copies()
6419 copied, renamed = [], []
6348 copied, renamed = [], []
6420 for d, s in c.iteritems():
6349 for d, s in c.iteritems():
6421 if s in status.removed:
6350 if s in status.removed:
6422 status.removed.remove(s)
6351 status.removed.remove(s)
6423 renamed.append(d)
6352 renamed.append(d)
6424 else:
6353 else:
6425 copied.append(d)
6354 copied.append(d)
6426 if d in status.added:
6355 if d in status.added:
6427 status.added.remove(d)
6356 status.added.remove(d)
6428
6357
6429 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6358 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6430
6359
6431 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6360 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6432 (ui.label(_('%d added'), 'status.added'), status.added),
6361 (ui.label(_('%d added'), 'status.added'), status.added),
6433 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6362 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6434 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6363 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6435 (ui.label(_('%d copied'), 'status.copied'), copied),
6364 (ui.label(_('%d copied'), 'status.copied'), copied),
6436 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6365 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6437 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6366 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6438 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6367 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6439 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6368 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6440 t = []
6369 t = []
6441 for l, s in labels:
6370 for l, s in labels:
6442 if s:
6371 if s:
6443 t.append(l % len(s))
6372 t.append(l % len(s))
6444
6373
6445 t = ', '.join(t)
6374 t = ', '.join(t)
6446 cleanworkdir = False
6375 cleanworkdir = False
6447
6376
6448 if repo.vfs.exists('graftstate'):
6377 if repo.vfs.exists('graftstate'):
6449 t += _(' (graft in progress)')
6378 t += _(' (graft in progress)')
6450 if repo.vfs.exists('updatestate'):
6379 if repo.vfs.exists('updatestate'):
6451 t += _(' (interrupted update)')
6380 t += _(' (interrupted update)')
6452 elif len(parents) > 1:
6381 elif len(parents) > 1:
6453 t += _(' (merge)')
6382 t += _(' (merge)')
6454 elif branch != parents[0].branch():
6383 elif branch != parents[0].branch():
6455 t += _(' (new branch)')
6384 t += _(' (new branch)')
6456 elif (parents[0].closesbranch() and
6385 elif (parents[0].closesbranch() and
6457 pnode in repo.branchheads(branch, closed=True)):
6386 pnode in repo.branchheads(branch, closed=True)):
6458 t += _(' (head closed)')
6387 t += _(' (head closed)')
6459 elif not (status.modified or status.added or status.removed or renamed or
6388 elif not (status.modified or status.added or status.removed or renamed or
6460 copied or subs):
6389 copied or subs):
6461 t += _(' (clean)')
6390 t += _(' (clean)')
6462 cleanworkdir = True
6391 cleanworkdir = True
6463 elif pnode not in bheads:
6392 elif pnode not in bheads:
6464 t += _(' (new branch head)')
6393 t += _(' (new branch head)')
6465
6394
6466 if parents:
6395 if parents:
6467 pendingphase = max(p.phase() for p in parents)
6396 pendingphase = max(p.phase() for p in parents)
6468 else:
6397 else:
6469 pendingphase = phases.public
6398 pendingphase = phases.public
6470
6399
6471 if pendingphase > phases.newcommitphase(ui):
6400 if pendingphase > phases.newcommitphase(ui):
6472 t += ' (%s)' % phases.phasenames[pendingphase]
6401 t += ' (%s)' % phases.phasenames[pendingphase]
6473
6402
6474 if cleanworkdir:
6403 if cleanworkdir:
6475 # i18n: column positioning for "hg summary"
6404 # i18n: column positioning for "hg summary"
6476 ui.status(_('commit: %s\n') % t.strip())
6405 ui.status(_('commit: %s\n') % t.strip())
6477 else:
6406 else:
6478 # i18n: column positioning for "hg summary"
6407 # i18n: column positioning for "hg summary"
6479 ui.write(_('commit: %s\n') % t.strip())
6408 ui.write(_('commit: %s\n') % t.strip())
6480
6409
6481 # all ancestors of branch heads - all ancestors of parent = new csets
6410 # all ancestors of branch heads - all ancestors of parent = new csets
6482 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6411 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6483 bheads))
6412 bheads))
6484
6413
6485 if new == 0:
6414 if new == 0:
6486 # i18n: column positioning for "hg summary"
6415 # i18n: column positioning for "hg summary"
6487 ui.status(_('update: (current)\n'))
6416 ui.status(_('update: (current)\n'))
6488 elif pnode not in bheads:
6417 elif pnode not in bheads:
6489 # i18n: column positioning for "hg summary"
6418 # i18n: column positioning for "hg summary"
6490 ui.write(_('update: %d new changesets (update)\n') % new)
6419 ui.write(_('update: %d new changesets (update)\n') % new)
6491 else:
6420 else:
6492 # i18n: column positioning for "hg summary"
6421 # i18n: column positioning for "hg summary"
6493 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6422 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6494 (new, len(bheads)))
6423 (new, len(bheads)))
6495
6424
6496 t = []
6425 t = []
6497 draft = len(repo.revs('draft()'))
6426 draft = len(repo.revs('draft()'))
6498 if draft:
6427 if draft:
6499 t.append(_('%d draft') % draft)
6428 t.append(_('%d draft') % draft)
6500 secret = len(repo.revs('secret()'))
6429 secret = len(repo.revs('secret()'))
6501 if secret:
6430 if secret:
6502 t.append(_('%d secret') % secret)
6431 t.append(_('%d secret') % secret)
6503
6432
6504 if draft or secret:
6433 if draft or secret:
6505 ui.status(_('phases: %s\n') % ', '.join(t))
6434 ui.status(_('phases: %s\n') % ', '.join(t))
6506
6435
6507 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6436 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6508 for trouble in ("unstable", "divergent", "bumped"):
6437 for trouble in ("unstable", "divergent", "bumped"):
6509 numtrouble = len(repo.revs(trouble + "()"))
6438 numtrouble = len(repo.revs(trouble + "()"))
6510 # We write all the possibilities to ease translation
6439 # We write all the possibilities to ease translation
6511 troublemsg = {
6440 troublemsg = {
6512 "unstable": _("unstable: %d changesets"),
6441 "unstable": _("unstable: %d changesets"),
6513 "divergent": _("divergent: %d changesets"),
6442 "divergent": _("divergent: %d changesets"),
6514 "bumped": _("bumped: %d changesets"),
6443 "bumped": _("bumped: %d changesets"),
6515 }
6444 }
6516 if numtrouble > 0:
6445 if numtrouble > 0:
6517 ui.status(troublemsg[trouble] % numtrouble + "\n")
6446 ui.status(troublemsg[trouble] % numtrouble + "\n")
6518
6447
6519 cmdutil.summaryhooks(ui, repo)
6448 cmdutil.summaryhooks(ui, repo)
6520
6449
6521 if opts.get('remote'):
6450 if opts.get('remote'):
6522 needsincoming, needsoutgoing = True, True
6451 needsincoming, needsoutgoing = True, True
6523 else:
6452 else:
6524 needsincoming, needsoutgoing = False, False
6453 needsincoming, needsoutgoing = False, False
6525 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6454 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6526 if i:
6455 if i:
6527 needsincoming = True
6456 needsincoming = True
6528 if o:
6457 if o:
6529 needsoutgoing = True
6458 needsoutgoing = True
6530 if not needsincoming and not needsoutgoing:
6459 if not needsincoming and not needsoutgoing:
6531 return
6460 return
6532
6461
6533 def getincoming():
6462 def getincoming():
6534 source, branches = hg.parseurl(ui.expandpath('default'))
6463 source, branches = hg.parseurl(ui.expandpath('default'))
6535 sbranch = branches[0]
6464 sbranch = branches[0]
6536 try:
6465 try:
6537 other = hg.peer(repo, {}, source)
6466 other = hg.peer(repo, {}, source)
6538 except error.RepoError:
6467 except error.RepoError:
6539 if opts.get('remote'):
6468 if opts.get('remote'):
6540 raise
6469 raise
6541 return source, sbranch, None, None, None
6470 return source, sbranch, None, None, None
6542 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6471 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6543 if revs:
6472 if revs:
6544 revs = [other.lookup(rev) for rev in revs]
6473 revs = [other.lookup(rev) for rev in revs]
6545 ui.debug('comparing with %s\n' % util.hidepassword(source))
6474 ui.debug('comparing with %s\n' % util.hidepassword(source))
6546 repo.ui.pushbuffer()
6475 repo.ui.pushbuffer()
6547 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6476 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6548 repo.ui.popbuffer()
6477 repo.ui.popbuffer()
6549 return source, sbranch, other, commoninc, commoninc[1]
6478 return source, sbranch, other, commoninc, commoninc[1]
6550
6479
6551 if needsincoming:
6480 if needsincoming:
6552 source, sbranch, sother, commoninc, incoming = getincoming()
6481 source, sbranch, sother, commoninc, incoming = getincoming()
6553 else:
6482 else:
6554 source = sbranch = sother = commoninc = incoming = None
6483 source = sbranch = sother = commoninc = incoming = None
6555
6484
6556 def getoutgoing():
6485 def getoutgoing():
6557 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6486 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6558 dbranch = branches[0]
6487 dbranch = branches[0]
6559 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6488 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6560 if source != dest:
6489 if source != dest:
6561 try:
6490 try:
6562 dother = hg.peer(repo, {}, dest)
6491 dother = hg.peer(repo, {}, dest)
6563 except error.RepoError:
6492 except error.RepoError:
6564 if opts.get('remote'):
6493 if opts.get('remote'):
6565 raise
6494 raise
6566 return dest, dbranch, None, None
6495 return dest, dbranch, None, None
6567 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6496 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6568 elif sother is None:
6497 elif sother is None:
6569 # there is no explicit destination peer, but source one is invalid
6498 # there is no explicit destination peer, but source one is invalid
6570 return dest, dbranch, None, None
6499 return dest, dbranch, None, None
6571 else:
6500 else:
6572 dother = sother
6501 dother = sother
6573 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6502 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6574 common = None
6503 common = None
6575 else:
6504 else:
6576 common = commoninc
6505 common = commoninc
6577 if revs:
6506 if revs:
6578 revs = [repo.lookup(rev) for rev in revs]
6507 revs = [repo.lookup(rev) for rev in revs]
6579 repo.ui.pushbuffer()
6508 repo.ui.pushbuffer()
6580 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6509 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6581 commoninc=common)
6510 commoninc=common)
6582 repo.ui.popbuffer()
6511 repo.ui.popbuffer()
6583 return dest, dbranch, dother, outgoing
6512 return dest, dbranch, dother, outgoing
6584
6513
6585 if needsoutgoing:
6514 if needsoutgoing:
6586 dest, dbranch, dother, outgoing = getoutgoing()
6515 dest, dbranch, dother, outgoing = getoutgoing()
6587 else:
6516 else:
6588 dest = dbranch = dother = outgoing = None
6517 dest = dbranch = dother = outgoing = None
6589
6518
6590 if opts.get('remote'):
6519 if opts.get('remote'):
6591 t = []
6520 t = []
6592 if incoming:
6521 if incoming:
6593 t.append(_('1 or more incoming'))
6522 t.append(_('1 or more incoming'))
6594 o = outgoing.missing
6523 o = outgoing.missing
6595 if o:
6524 if o:
6596 t.append(_('%d outgoing') % len(o))
6525 t.append(_('%d outgoing') % len(o))
6597 other = dother or sother
6526 other = dother or sother
6598 if 'bookmarks' in other.listkeys('namespaces'):
6527 if 'bookmarks' in other.listkeys('namespaces'):
6599 counts = bookmarks.summary(repo, other)
6528 counts = bookmarks.summary(repo, other)
6600 if counts[0] > 0:
6529 if counts[0] > 0:
6601 t.append(_('%d incoming bookmarks') % counts[0])
6530 t.append(_('%d incoming bookmarks') % counts[0])
6602 if counts[1] > 0:
6531 if counts[1] > 0:
6603 t.append(_('%d outgoing bookmarks') % counts[1])
6532 t.append(_('%d outgoing bookmarks') % counts[1])
6604
6533
6605 if t:
6534 if t:
6606 # i18n: column positioning for "hg summary"
6535 # i18n: column positioning for "hg summary"
6607 ui.write(_('remote: %s\n') % (', '.join(t)))
6536 ui.write(_('remote: %s\n') % (', '.join(t)))
6608 else:
6537 else:
6609 # i18n: column positioning for "hg summary"
6538 # i18n: column positioning for "hg summary"
6610 ui.status(_('remote: (synced)\n'))
6539 ui.status(_('remote: (synced)\n'))
6611
6540
6612 cmdutil.summaryremotehooks(ui, repo, opts,
6541 cmdutil.summaryremotehooks(ui, repo, opts,
6613 ((source, sbranch, sother, commoninc),
6542 ((source, sbranch, sother, commoninc),
6614 (dest, dbranch, dother, outgoing)))
6543 (dest, dbranch, dother, outgoing)))
6615
6544
6616 @command('tag',
6545 @command('tag',
6617 [('f', 'force', None, _('force tag')),
6546 [('f', 'force', None, _('force tag')),
6618 ('l', 'local', None, _('make the tag local')),
6547 ('l', 'local', None, _('make the tag local')),
6619 ('r', 'rev', '', _('revision to tag'), _('REV')),
6548 ('r', 'rev', '', _('revision to tag'), _('REV')),
6620 ('', 'remove', None, _('remove a tag')),
6549 ('', 'remove', None, _('remove a tag')),
6621 # -l/--local is already there, commitopts cannot be used
6550 # -l/--local is already there, commitopts cannot be used
6622 ('e', 'edit', None, _('invoke editor on commit messages')),
6551 ('e', 'edit', None, _('invoke editor on commit messages')),
6623 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6552 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6624 ] + commitopts2,
6553 ] + commitopts2,
6625 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6554 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6626 def tag(ui, repo, name1, *names, **opts):
6555 def tag(ui, repo, name1, *names, **opts):
6627 """add one or more tags for the current or given revision
6556 """add one or more tags for the current or given revision
6628
6557
6629 Name a particular revision using <name>.
6558 Name a particular revision using <name>.
6630
6559
6631 Tags are used to name particular revisions of the repository and are
6560 Tags are used to name particular revisions of the repository and are
6632 very useful to compare different revisions, to go back to significant
6561 very useful to compare different revisions, to go back to significant
6633 earlier versions or to mark branch points as releases, etc. Changing
6562 earlier versions or to mark branch points as releases, etc. Changing
6634 an existing tag is normally disallowed; use -f/--force to override.
6563 an existing tag is normally disallowed; use -f/--force to override.
6635
6564
6636 If no revision is given, the parent of the working directory is
6565 If no revision is given, the parent of the working directory is
6637 used.
6566 used.
6638
6567
6639 To facilitate version control, distribution, and merging of tags,
6568 To facilitate version control, distribution, and merging of tags,
6640 they are stored as a file named ".hgtags" which is managed similarly
6569 they are stored as a file named ".hgtags" which is managed similarly
6641 to other project files and can be hand-edited if necessary. This
6570 to other project files and can be hand-edited if necessary. This
6642 also means that tagging creates a new commit. The file
6571 also means that tagging creates a new commit. The file
6643 ".hg/localtags" is used for local tags (not shared among
6572 ".hg/localtags" is used for local tags (not shared among
6644 repositories).
6573 repositories).
6645
6574
6646 Tag commits are usually made at the head of a branch. If the parent
6575 Tag commits are usually made at the head of a branch. If the parent
6647 of the working directory is not a branch head, :hg:`tag` aborts; use
6576 of the working directory is not a branch head, :hg:`tag` aborts; use
6648 -f/--force to force the tag commit to be based on a non-head
6577 -f/--force to force the tag commit to be based on a non-head
6649 changeset.
6578 changeset.
6650
6579
6651 See :hg:`help dates` for a list of formats valid for -d/--date.
6580 See :hg:`help dates` for a list of formats valid for -d/--date.
6652
6581
6653 Since tag names have priority over branch names during revision
6582 Since tag names have priority over branch names during revision
6654 lookup, using an existing branch name as a tag name is discouraged.
6583 lookup, using an existing branch name as a tag name is discouraged.
6655
6584
6656 Returns 0 on success.
6585 Returns 0 on success.
6657 """
6586 """
6658 wlock = lock = None
6587 wlock = lock = None
6659 try:
6588 try:
6660 wlock = repo.wlock()
6589 wlock = repo.wlock()
6661 lock = repo.lock()
6590 lock = repo.lock()
6662 rev_ = "."
6591 rev_ = "."
6663 names = [t.strip() for t in (name1,) + names]
6592 names = [t.strip() for t in (name1,) + names]
6664 if len(names) != len(set(names)):
6593 if len(names) != len(set(names)):
6665 raise error.Abort(_('tag names must be unique'))
6594 raise error.Abort(_('tag names must be unique'))
6666 for n in names:
6595 for n in names:
6667 scmutil.checknewlabel(repo, n, 'tag')
6596 scmutil.checknewlabel(repo, n, 'tag')
6668 if not n:
6597 if not n:
6669 raise error.Abort(_('tag names cannot consist entirely of '
6598 raise error.Abort(_('tag names cannot consist entirely of '
6670 'whitespace'))
6599 'whitespace'))
6671 if opts.get('rev') and opts.get('remove'):
6600 if opts.get('rev') and opts.get('remove'):
6672 raise error.Abort(_("--rev and --remove are incompatible"))
6601 raise error.Abort(_("--rev and --remove are incompatible"))
6673 if opts.get('rev'):
6602 if opts.get('rev'):
6674 rev_ = opts['rev']
6603 rev_ = opts['rev']
6675 message = opts.get('message')
6604 message = opts.get('message')
6676 if opts.get('remove'):
6605 if opts.get('remove'):
6677 if opts.get('local'):
6606 if opts.get('local'):
6678 expectedtype = 'local'
6607 expectedtype = 'local'
6679 else:
6608 else:
6680 expectedtype = 'global'
6609 expectedtype = 'global'
6681
6610
6682 for n in names:
6611 for n in names:
6683 if not repo.tagtype(n):
6612 if not repo.tagtype(n):
6684 raise error.Abort(_("tag '%s' does not exist") % n)
6613 raise error.Abort(_("tag '%s' does not exist") % n)
6685 if repo.tagtype(n) != expectedtype:
6614 if repo.tagtype(n) != expectedtype:
6686 if expectedtype == 'global':
6615 if expectedtype == 'global':
6687 raise error.Abort(_("tag '%s' is not a global tag") % n)
6616 raise error.Abort(_("tag '%s' is not a global tag") % n)
6688 else:
6617 else:
6689 raise error.Abort(_("tag '%s' is not a local tag") % n)
6618 raise error.Abort(_("tag '%s' is not a local tag") % n)
6690 rev_ = 'null'
6619 rev_ = 'null'
6691 if not message:
6620 if not message:
6692 # we don't translate commit messages
6621 # we don't translate commit messages
6693 message = 'Removed tag %s' % ', '.join(names)
6622 message = 'Removed tag %s' % ', '.join(names)
6694 elif not opts.get('force'):
6623 elif not opts.get('force'):
6695 for n in names:
6624 for n in names:
6696 if n in repo.tags():
6625 if n in repo.tags():
6697 raise error.Abort(_("tag '%s' already exists "
6626 raise error.Abort(_("tag '%s' already exists "
6698 "(use -f to force)") % n)
6627 "(use -f to force)") % n)
6699 if not opts.get('local'):
6628 if not opts.get('local'):
6700 p1, p2 = repo.dirstate.parents()
6629 p1, p2 = repo.dirstate.parents()
6701 if p2 != nullid:
6630 if p2 != nullid:
6702 raise error.Abort(_('uncommitted merge'))
6631 raise error.Abort(_('uncommitted merge'))
6703 bheads = repo.branchheads()
6632 bheads = repo.branchheads()
6704 if not opts.get('force') and bheads and p1 not in bheads:
6633 if not opts.get('force') and bheads and p1 not in bheads:
6705 raise error.Abort(_('working directory is not at a branch head '
6634 raise error.Abort(_('working directory is not at a branch head '
6706 '(use -f to force)'))
6635 '(use -f to force)'))
6707 r = scmutil.revsingle(repo, rev_).node()
6636 r = scmutil.revsingle(repo, rev_).node()
6708
6637
6709 if not message:
6638 if not message:
6710 # we don't translate commit messages
6639 # we don't translate commit messages
6711 message = ('Added tag %s for changeset %s' %
6640 message = ('Added tag %s for changeset %s' %
6712 (', '.join(names), short(r)))
6641 (', '.join(names), short(r)))
6713
6642
6714 date = opts.get('date')
6643 date = opts.get('date')
6715 if date:
6644 if date:
6716 date = util.parsedate(date)
6645 date = util.parsedate(date)
6717
6646
6718 if opts.get('remove'):
6647 if opts.get('remove'):
6719 editform = 'tag.remove'
6648 editform = 'tag.remove'
6720 else:
6649 else:
6721 editform = 'tag.add'
6650 editform = 'tag.add'
6722 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6651 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6723
6652
6724 # don't allow tagging the null rev
6653 # don't allow tagging the null rev
6725 if (not opts.get('remove') and
6654 if (not opts.get('remove') and
6726 scmutil.revsingle(repo, rev_).rev() == nullrev):
6655 scmutil.revsingle(repo, rev_).rev() == nullrev):
6727 raise error.Abort(_("cannot tag null revision"))
6656 raise error.Abort(_("cannot tag null revision"))
6728
6657
6729 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6658 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6730 editor=editor)
6659 editor=editor)
6731 finally:
6660 finally:
6732 release(lock, wlock)
6661 release(lock, wlock)
6733
6662
6734 @command('tags', formatteropts, '')
6663 @command('tags', formatteropts, '')
6735 def tags(ui, repo, **opts):
6664 def tags(ui, repo, **opts):
6736 """list repository tags
6665 """list repository tags
6737
6666
6738 This lists both regular and local tags. When the -v/--verbose
6667 This lists both regular and local tags. When the -v/--verbose
6739 switch is used, a third column "local" is printed for local tags.
6668 switch is used, a third column "local" is printed for local tags.
6740 When the -q/--quiet switch is used, only the tag name is printed.
6669 When the -q/--quiet switch is used, only the tag name is printed.
6741
6670
6742 Returns 0 on success.
6671 Returns 0 on success.
6743 """
6672 """
6744
6673
6745 fm = ui.formatter('tags', opts)
6674 fm = ui.formatter('tags', opts)
6746 hexfunc = fm.hexfunc
6675 hexfunc = fm.hexfunc
6747 tagtype = ""
6676 tagtype = ""
6748
6677
6749 for t, n in reversed(repo.tagslist()):
6678 for t, n in reversed(repo.tagslist()):
6750 hn = hexfunc(n)
6679 hn = hexfunc(n)
6751 label = 'tags.normal'
6680 label = 'tags.normal'
6752 tagtype = ''
6681 tagtype = ''
6753 if repo.tagtype(t) == 'local':
6682 if repo.tagtype(t) == 'local':
6754 label = 'tags.local'
6683 label = 'tags.local'
6755 tagtype = 'local'
6684 tagtype = 'local'
6756
6685
6757 fm.startitem()
6686 fm.startitem()
6758 fm.write('tag', '%s', t, label=label)
6687 fm.write('tag', '%s', t, label=label)
6759 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6688 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6760 fm.condwrite(not ui.quiet, 'rev node', fmt,
6689 fm.condwrite(not ui.quiet, 'rev node', fmt,
6761 repo.changelog.rev(n), hn, label=label)
6690 repo.changelog.rev(n), hn, label=label)
6762 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6691 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6763 tagtype, label=label)
6692 tagtype, label=label)
6764 fm.plain('\n')
6693 fm.plain('\n')
6765 fm.end()
6694 fm.end()
6766
6695
6767 @command('tip',
6696 @command('tip',
6768 [('p', 'patch', None, _('show patch')),
6697 [('p', 'patch', None, _('show patch')),
6769 ('g', 'git', None, _('use git extended diff format')),
6698 ('g', 'git', None, _('use git extended diff format')),
6770 ] + templateopts,
6699 ] + templateopts,
6771 _('[-p] [-g]'))
6700 _('[-p] [-g]'))
6772 def tip(ui, repo, **opts):
6701 def tip(ui, repo, **opts):
6773 """show the tip revision (DEPRECATED)
6702 """show the tip revision (DEPRECATED)
6774
6703
6775 The tip revision (usually just called the tip) is the changeset
6704 The tip revision (usually just called the tip) is the changeset
6776 most recently added to the repository (and therefore the most
6705 most recently added to the repository (and therefore the most
6777 recently changed head).
6706 recently changed head).
6778
6707
6779 If you have just made a commit, that commit will be the tip. If
6708 If you have just made a commit, that commit will be the tip. If
6780 you have just pulled changes from another repository, the tip of
6709 you have just pulled changes from another repository, the tip of
6781 that repository becomes the current tip. The "tip" tag is special
6710 that repository becomes the current tip. The "tip" tag is special
6782 and cannot be renamed or assigned to a different changeset.
6711 and cannot be renamed or assigned to a different changeset.
6783
6712
6784 This command is deprecated, please use :hg:`heads` instead.
6713 This command is deprecated, please use :hg:`heads` instead.
6785
6714
6786 Returns 0 on success.
6715 Returns 0 on success.
6787 """
6716 """
6788 displayer = cmdutil.show_changeset(ui, repo, opts)
6717 displayer = cmdutil.show_changeset(ui, repo, opts)
6789 displayer.show(repo['tip'])
6718 displayer.show(repo['tip'])
6790 displayer.close()
6719 displayer.close()
6791
6720
6792 @command('unbundle',
6721 @command('unbundle',
6793 [('u', 'update', None,
6722 [('u', 'update', None,
6794 _('update to new branch head if changesets were unbundled'))],
6723 _('update to new branch head if changesets were unbundled'))],
6795 _('[-u] FILE...'))
6724 _('[-u] FILE...'))
6796 def unbundle(ui, repo, fname1, *fnames, **opts):
6725 def unbundle(ui, repo, fname1, *fnames, **opts):
6797 """apply one or more changegroup files
6726 """apply one or more changegroup files
6798
6727
6799 Apply one or more compressed changegroup files generated by the
6728 Apply one or more compressed changegroup files generated by the
6800 bundle command.
6729 bundle command.
6801
6730
6802 Returns 0 on success, 1 if an update has unresolved files.
6731 Returns 0 on success, 1 if an update has unresolved files.
6803 """
6732 """
6804 fnames = (fname1,) + fnames
6733 fnames = (fname1,) + fnames
6805
6734
6806 with repo.lock():
6735 with repo.lock():
6807 for fname in fnames:
6736 for fname in fnames:
6808 f = hg.openpath(ui, fname)
6737 f = hg.openpath(ui, fname)
6809 gen = exchange.readbundle(ui, f, fname)
6738 gen = exchange.readbundle(ui, f, fname)
6810 if isinstance(gen, bundle2.unbundle20):
6739 if isinstance(gen, bundle2.unbundle20):
6811 tr = repo.transaction('unbundle')
6740 tr = repo.transaction('unbundle')
6812 try:
6741 try:
6813 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6742 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6814 url='bundle:' + fname)
6743 url='bundle:' + fname)
6815 tr.close()
6744 tr.close()
6816 except error.BundleUnknownFeatureError as exc:
6745 except error.BundleUnknownFeatureError as exc:
6817 raise error.Abort(_('%s: unknown bundle feature, %s')
6746 raise error.Abort(_('%s: unknown bundle feature, %s')
6818 % (fname, exc),
6747 % (fname, exc),
6819 hint=_("see https://mercurial-scm.org/"
6748 hint=_("see https://mercurial-scm.org/"
6820 "wiki/BundleFeature for more "
6749 "wiki/BundleFeature for more "
6821 "information"))
6750 "information"))
6822 finally:
6751 finally:
6823 if tr:
6752 if tr:
6824 tr.release()
6753 tr.release()
6825 changes = [r.get('return', 0)
6754 changes = [r.get('return', 0)
6826 for r in op.records['changegroup']]
6755 for r in op.records['changegroup']]
6827 modheads = changegroup.combineresults(changes)
6756 modheads = changegroup.combineresults(changes)
6828 elif isinstance(gen, streamclone.streamcloneapplier):
6757 elif isinstance(gen, streamclone.streamcloneapplier):
6829 raise error.Abort(
6758 raise error.Abort(
6830 _('packed bundles cannot be applied with '
6759 _('packed bundles cannot be applied with '
6831 '"hg unbundle"'),
6760 '"hg unbundle"'),
6832 hint=_('use "hg debugapplystreamclonebundle"'))
6761 hint=_('use "hg debugapplystreamclonebundle"'))
6833 else:
6762 else:
6834 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6763 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6835
6764
6836 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
6765 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
6837
6766
6838 @command('^update|up|checkout|co',
6767 @command('^update|up|checkout|co',
6839 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6768 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6840 ('c', 'check', None, _('require clean working directory')),
6769 ('c', 'check', None, _('require clean working directory')),
6841 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6770 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6842 ('r', 'rev', '', _('revision'), _('REV'))
6771 ('r', 'rev', '', _('revision'), _('REV'))
6843 ] + mergetoolopts,
6772 ] + mergetoolopts,
6844 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6773 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6845 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6774 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6846 tool=None):
6775 tool=None):
6847 """update working directory (or switch revisions)
6776 """update working directory (or switch revisions)
6848
6777
6849 Update the repository's working directory to the specified
6778 Update the repository's working directory to the specified
6850 changeset. If no changeset is specified, update to the tip of the
6779 changeset. If no changeset is specified, update to the tip of the
6851 current named branch and move the active bookmark (see :hg:`help
6780 current named branch and move the active bookmark (see :hg:`help
6852 bookmarks`).
6781 bookmarks`).
6853
6782
6854 Update sets the working directory's parent revision to the specified
6783 Update sets the working directory's parent revision to the specified
6855 changeset (see :hg:`help parents`).
6784 changeset (see :hg:`help parents`).
6856
6785
6857 If the changeset is not a descendant or ancestor of the working
6786 If the changeset is not a descendant or ancestor of the working
6858 directory's parent, the update is aborted. With the -c/--check
6787 directory's parent, the update is aborted. With the -c/--check
6859 option, the working directory is checked for uncommitted changes; if
6788 option, the working directory is checked for uncommitted changes; if
6860 none are found, the working directory is updated to the specified
6789 none are found, the working directory is updated to the specified
6861 changeset.
6790 changeset.
6862
6791
6863 .. container:: verbose
6792 .. container:: verbose
6864
6793
6865 The following rules apply when the working directory contains
6794 The following rules apply when the working directory contains
6866 uncommitted changes:
6795 uncommitted changes:
6867
6796
6868 1. If neither -c/--check nor -C/--clean is specified, and if
6797 1. If neither -c/--check nor -C/--clean is specified, and if
6869 the requested changeset is an ancestor or descendant of
6798 the requested changeset is an ancestor or descendant of
6870 the working directory's parent, the uncommitted changes
6799 the working directory's parent, the uncommitted changes
6871 are merged into the requested changeset and the merged
6800 are merged into the requested changeset and the merged
6872 result is left uncommitted. If the requested changeset is
6801 result is left uncommitted. If the requested changeset is
6873 not an ancestor or descendant (that is, it is on another
6802 not an ancestor or descendant (that is, it is on another
6874 branch), the update is aborted and the uncommitted changes
6803 branch), the update is aborted and the uncommitted changes
6875 are preserved.
6804 are preserved.
6876
6805
6877 2. With the -c/--check option, the update is aborted and the
6806 2. With the -c/--check option, the update is aborted and the
6878 uncommitted changes are preserved.
6807 uncommitted changes are preserved.
6879
6808
6880 3. With the -C/--clean option, uncommitted changes are discarded and
6809 3. With the -C/--clean option, uncommitted changes are discarded and
6881 the working directory is updated to the requested changeset.
6810 the working directory is updated to the requested changeset.
6882
6811
6883 To cancel an uncommitted merge (and lose your changes), use
6812 To cancel an uncommitted merge (and lose your changes), use
6884 :hg:`update --clean .`.
6813 :hg:`update --clean .`.
6885
6814
6886 Use null as the changeset to remove the working directory (like
6815 Use null as the changeset to remove the working directory (like
6887 :hg:`clone -U`).
6816 :hg:`clone -U`).
6888
6817
6889 If you want to revert just one file to an older revision, use
6818 If you want to revert just one file to an older revision, use
6890 :hg:`revert [-r REV] NAME`.
6819 :hg:`revert [-r REV] NAME`.
6891
6820
6892 See :hg:`help dates` for a list of formats valid for -d/--date.
6821 See :hg:`help dates` for a list of formats valid for -d/--date.
6893
6822
6894 Returns 0 on success, 1 if there are unresolved files.
6823 Returns 0 on success, 1 if there are unresolved files.
6895 """
6824 """
6896 if rev and node:
6825 if rev and node:
6897 raise error.Abort(_("please specify just one revision"))
6826 raise error.Abort(_("please specify just one revision"))
6898
6827
6899 if rev is None or rev == '':
6828 if rev is None or rev == '':
6900 rev = node
6829 rev = node
6901
6830
6902 if date and rev is not None:
6831 if date and rev is not None:
6903 raise error.Abort(_("you can't specify a revision and a date"))
6832 raise error.Abort(_("you can't specify a revision and a date"))
6904
6833
6905 if check and clean:
6834 if check and clean:
6906 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
6835 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
6907
6836
6908 with repo.wlock():
6837 with repo.wlock():
6909 cmdutil.clearunfinished(repo)
6838 cmdutil.clearunfinished(repo)
6910
6839
6911 if date:
6840 if date:
6912 rev = cmdutil.finddate(ui, repo, date)
6841 rev = cmdutil.finddate(ui, repo, date)
6913
6842
6914 # if we defined a bookmark, we have to remember the original name
6843 # if we defined a bookmark, we have to remember the original name
6915 brev = rev
6844 brev = rev
6916 rev = scmutil.revsingle(repo, rev, rev).rev()
6845 rev = scmutil.revsingle(repo, rev, rev).rev()
6917
6846
6918 if check:
6847 if check:
6919 cmdutil.bailifchanged(repo, merge=False)
6848 cmdutil.bailifchanged(repo, merge=False)
6920
6849
6921 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6850 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6922
6851
6923 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
6852 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
6924
6853
6925 @command('verify', [])
6854 @command('verify', [])
6926 def verify(ui, repo):
6855 def verify(ui, repo):
6927 """verify the integrity of the repository
6856 """verify the integrity of the repository
6928
6857
6929 Verify the integrity of the current repository.
6858 Verify the integrity of the current repository.
6930
6859
6931 This will perform an extensive check of the repository's
6860 This will perform an extensive check of the repository's
6932 integrity, validating the hashes and checksums of each entry in
6861 integrity, validating the hashes and checksums of each entry in
6933 the changelog, manifest, and tracked files, as well as the
6862 the changelog, manifest, and tracked files, as well as the
6934 integrity of their crosslinks and indices.
6863 integrity of their crosslinks and indices.
6935
6864
6936 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6865 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6937 for more information about recovery from corruption of the
6866 for more information about recovery from corruption of the
6938 repository.
6867 repository.
6939
6868
6940 Returns 0 on success, 1 if errors are encountered.
6869 Returns 0 on success, 1 if errors are encountered.
6941 """
6870 """
6942 return hg.verify(repo)
6871 return hg.verify(repo)
6943
6872
6944 @command('version', [] + formatteropts, norepo=True)
6873 @command('version', [] + formatteropts, norepo=True)
6945 def version_(ui, **opts):
6874 def version_(ui, **opts):
6946 """output version and copyright information"""
6875 """output version and copyright information"""
6947 fm = ui.formatter("version", opts)
6876 fm = ui.formatter("version", opts)
6948 fm.startitem()
6877 fm.startitem()
6949 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6878 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6950 util.version())
6879 util.version())
6951 license = _(
6880 license = _(
6952 "(see https://mercurial-scm.org for more information)\n"
6881 "(see https://mercurial-scm.org for more information)\n"
6953 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
6882 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
6954 "This is free software; see the source for copying conditions. "
6883 "This is free software; see the source for copying conditions. "
6955 "There is NO\nwarranty; "
6884 "There is NO\nwarranty; "
6956 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6885 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6957 )
6886 )
6958 if not ui.quiet:
6887 if not ui.quiet:
6959 fm.plain(license)
6888 fm.plain(license)
6960
6889
6961 if ui.verbose:
6890 if ui.verbose:
6962 fm.plain(_("\nEnabled extensions:\n\n"))
6891 fm.plain(_("\nEnabled extensions:\n\n"))
6963 # format names and versions into columns
6892 # format names and versions into columns
6964 names = []
6893 names = []
6965 vers = []
6894 vers = []
6966 isinternals = []
6895 isinternals = []
6967 for name, module in extensions.extensions():
6896 for name, module in extensions.extensions():
6968 names.append(name)
6897 names.append(name)
6969 vers.append(extensions.moduleversion(module) or None)
6898 vers.append(extensions.moduleversion(module) or None)
6970 isinternals.append(extensions.ismoduleinternal(module))
6899 isinternals.append(extensions.ismoduleinternal(module))
6971 fn = fm.nested("extensions")
6900 fn = fm.nested("extensions")
6972 if names:
6901 if names:
6973 namefmt = " %%-%ds " % max(len(n) for n in names)
6902 namefmt = " %%-%ds " % max(len(n) for n in names)
6974 places = [_("external"), _("internal")]
6903 places = [_("external"), _("internal")]
6975 for n, v, p in zip(names, vers, isinternals):
6904 for n, v, p in zip(names, vers, isinternals):
6976 fn.startitem()
6905 fn.startitem()
6977 fn.condwrite(ui.verbose, "name", namefmt, n)
6906 fn.condwrite(ui.verbose, "name", namefmt, n)
6978 if ui.verbose:
6907 if ui.verbose:
6979 fn.plain("%s " % places[p])
6908 fn.plain("%s " % places[p])
6980 fn.data(bundled=p)
6909 fn.data(bundled=p)
6981 fn.condwrite(ui.verbose and v, "ver", "%s", v)
6910 fn.condwrite(ui.verbose and v, "ver", "%s", v)
6982 if ui.verbose:
6911 if ui.verbose:
6983 fn.plain("\n")
6912 fn.plain("\n")
6984 fn.end()
6913 fn.end()
6985 fm.end()
6914 fm.end()
6986
6915
6987 def loadcmdtable(ui, name, cmdtable):
6916 def loadcmdtable(ui, name, cmdtable):
6988 """Load command functions from specified cmdtable
6917 """Load command functions from specified cmdtable
6989 """
6918 """
6990 overrides = [cmd for cmd in cmdtable if cmd in table]
6919 overrides = [cmd for cmd in cmdtable if cmd in table]
6991 if overrides:
6920 if overrides:
6992 ui.warn(_("extension '%s' overrides commands: %s\n")
6921 ui.warn(_("extension '%s' overrides commands: %s\n")
6993 % (name, " ".join(overrides)))
6922 % (name, " ".join(overrides)))
6994 table.update(cmdtable)
6923 table.update(cmdtable)
@@ -1,453 +1,525
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 import random
11
12
12 from .i18n import _
13 from .i18n import _
13 from .node import (
14 from .node import (
14 hex,
15 hex,
16 short,
15 )
17 )
16 from . import (
18 from . import (
17 bundle2,
19 bundle2,
18 changegroup,
20 changegroup,
19 cmdutil,
21 cmdutil,
20 commands,
22 commands,
21 context,
23 context,
22 dagparser,
24 dagparser,
25 dagutil,
23 error,
26 error,
24 exchange,
27 exchange,
25 hg,
28 hg,
29 localrepo,
26 lock as lockmod,
30 lock as lockmod,
27 revlog,
31 revlog,
28 scmutil,
32 scmutil,
33 setdiscovery,
29 simplemerge,
34 simplemerge,
30 streamclone,
35 streamclone,
36 treediscovery,
31 util,
37 util,
32 )
38 )
33
39
34 release = lockmod.release
40 release = lockmod.release
35
41
36 # We reuse the command table from commands because it is easier than
42 # We reuse the command table from commands because it is easier than
37 # teaching dispatch about multiple tables.
43 # teaching dispatch about multiple tables.
38 command = cmdutil.command(commands.table)
44 command = cmdutil.command(commands.table)
39
45
40 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
46 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
41 def debugancestor(ui, repo, *args):
47 def debugancestor(ui, repo, *args):
42 """find the ancestor revision of two revisions in a given index"""
48 """find the ancestor revision of two revisions in a given index"""
43 if len(args) == 3:
49 if len(args) == 3:
44 index, rev1, rev2 = args
50 index, rev1, rev2 = args
45 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
51 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
46 lookup = r.lookup
52 lookup = r.lookup
47 elif len(args) == 2:
53 elif len(args) == 2:
48 if not repo:
54 if not repo:
49 raise error.Abort(_('there is no Mercurial repository here '
55 raise error.Abort(_('there is no Mercurial repository here '
50 '(.hg not found)'))
56 '(.hg not found)'))
51 rev1, rev2 = args
57 rev1, rev2 = args
52 r = repo.changelog
58 r = repo.changelog
53 lookup = repo.lookup
59 lookup = repo.lookup
54 else:
60 else:
55 raise error.Abort(_('either two or three arguments required'))
61 raise error.Abort(_('either two or three arguments required'))
56 a = r.ancestor(lookup(rev1), lookup(rev2))
62 a = r.ancestor(lookup(rev1), lookup(rev2))
57 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
63 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
58
64
59 @command('debugbuilddag',
65 @command('debugbuilddag',
60 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
66 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
61 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
67 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
62 ('n', 'new-file', None, _('add new file at each rev'))],
68 ('n', 'new-file', None, _('add new file at each rev'))],
63 _('[OPTION]... [TEXT]'))
69 _('[OPTION]... [TEXT]'))
64 def debugbuilddag(ui, repo, text=None,
70 def debugbuilddag(ui, repo, text=None,
65 mergeable_file=False,
71 mergeable_file=False,
66 overwritten_file=False,
72 overwritten_file=False,
67 new_file=False):
73 new_file=False):
68 """builds a repo with a given DAG from scratch in the current empty repo
74 """builds a repo with a given DAG from scratch in the current empty repo
69
75
70 The description of the DAG is read from stdin if not given on the
76 The description of the DAG is read from stdin if not given on the
71 command line.
77 command line.
72
78
73 Elements:
79 Elements:
74
80
75 - "+n" is a linear run of n nodes based on the current default parent
81 - "+n" is a linear run of n nodes based on the current default parent
76 - "." is a single node based on the current default parent
82 - "." is a single node based on the current default parent
77 - "$" resets the default parent to null (implied at the start);
83 - "$" resets the default parent to null (implied at the start);
78 otherwise the default parent is always the last node created
84 otherwise the default parent is always the last node created
79 - "<p" sets the default parent to the backref p
85 - "<p" sets the default parent to the backref p
80 - "*p" is a fork at parent p, which is a backref
86 - "*p" is a fork at parent p, which is a backref
81 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
87 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
82 - "/p2" is a merge of the preceding node and p2
88 - "/p2" is a merge of the preceding node and p2
83 - ":tag" defines a local tag for the preceding node
89 - ":tag" defines a local tag for the preceding node
84 - "@branch" sets the named branch for subsequent nodes
90 - "@branch" sets the named branch for subsequent nodes
85 - "#...\\n" is a comment up to the end of the line
91 - "#...\\n" is a comment up to the end of the line
86
92
87 Whitespace between the above elements is ignored.
93 Whitespace between the above elements is ignored.
88
94
89 A backref is either
95 A backref is either
90
96
91 - a number n, which references the node curr-n, where curr is the current
97 - a number n, which references the node curr-n, where curr is the current
92 node, or
98 node, or
93 - the name of a local tag you placed earlier using ":tag", or
99 - the name of a local tag you placed earlier using ":tag", or
94 - empty to denote the default parent.
100 - empty to denote the default parent.
95
101
96 All string valued-elements are either strictly alphanumeric, or must
102 All string valued-elements are either strictly alphanumeric, or must
97 be enclosed in double quotes ("..."), with "\\" as escape character.
103 be enclosed in double quotes ("..."), with "\\" as escape character.
98 """
104 """
99
105
100 if text is None:
106 if text is None:
101 ui.status(_("reading DAG from stdin\n"))
107 ui.status(_("reading DAG from stdin\n"))
102 text = ui.fin.read()
108 text = ui.fin.read()
103
109
104 cl = repo.changelog
110 cl = repo.changelog
105 if len(cl) > 0:
111 if len(cl) > 0:
106 raise error.Abort(_('repository is not empty'))
112 raise error.Abort(_('repository is not empty'))
107
113
108 # determine number of revs in DAG
114 # determine number of revs in DAG
109 total = 0
115 total = 0
110 for type, data in dagparser.parsedag(text):
116 for type, data in dagparser.parsedag(text):
111 if type == 'n':
117 if type == 'n':
112 total += 1
118 total += 1
113
119
114 if mergeable_file:
120 if mergeable_file:
115 linesperrev = 2
121 linesperrev = 2
116 # make a file with k lines per rev
122 # make a file with k lines per rev
117 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
123 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
118 initialmergedlines.append("")
124 initialmergedlines.append("")
119
125
120 tags = []
126 tags = []
121
127
122 wlock = lock = tr = None
128 wlock = lock = tr = None
123 try:
129 try:
124 wlock = repo.wlock()
130 wlock = repo.wlock()
125 lock = repo.lock()
131 lock = repo.lock()
126 tr = repo.transaction("builddag")
132 tr = repo.transaction("builddag")
127
133
128 at = -1
134 at = -1
129 atbranch = 'default'
135 atbranch = 'default'
130 nodeids = []
136 nodeids = []
131 id = 0
137 id = 0
132 ui.progress(_('building'), id, unit=_('revisions'), total=total)
138 ui.progress(_('building'), id, unit=_('revisions'), total=total)
133 for type, data in dagparser.parsedag(text):
139 for type, data in dagparser.parsedag(text):
134 if type == 'n':
140 if type == 'n':
135 ui.note(('node %s\n' % str(data)))
141 ui.note(('node %s\n' % str(data)))
136 id, ps = data
142 id, ps = data
137
143
138 files = []
144 files = []
139 fctxs = {}
145 fctxs = {}
140
146
141 p2 = None
147 p2 = None
142 if mergeable_file:
148 if mergeable_file:
143 fn = "mf"
149 fn = "mf"
144 p1 = repo[ps[0]]
150 p1 = repo[ps[0]]
145 if len(ps) > 1:
151 if len(ps) > 1:
146 p2 = repo[ps[1]]
152 p2 = repo[ps[1]]
147 pa = p1.ancestor(p2)
153 pa = p1.ancestor(p2)
148 base, local, other = [x[fn].data() for x in (pa, p1,
154 base, local, other = [x[fn].data() for x in (pa, p1,
149 p2)]
155 p2)]
150 m3 = simplemerge.Merge3Text(base, local, other)
156 m3 = simplemerge.Merge3Text(base, local, other)
151 ml = [l.strip() for l in m3.merge_lines()]
157 ml = [l.strip() for l in m3.merge_lines()]
152 ml.append("")
158 ml.append("")
153 elif at > 0:
159 elif at > 0:
154 ml = p1[fn].data().split("\n")
160 ml = p1[fn].data().split("\n")
155 else:
161 else:
156 ml = initialmergedlines
162 ml = initialmergedlines
157 ml[id * linesperrev] += " r%i" % id
163 ml[id * linesperrev] += " r%i" % id
158 mergedtext = "\n".join(ml)
164 mergedtext = "\n".join(ml)
159 files.append(fn)
165 files.append(fn)
160 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
166 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
161
167
162 if overwritten_file:
168 if overwritten_file:
163 fn = "of"
169 fn = "of"
164 files.append(fn)
170 files.append(fn)
165 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
171 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
166
172
167 if new_file:
173 if new_file:
168 fn = "nf%i" % id
174 fn = "nf%i" % id
169 files.append(fn)
175 files.append(fn)
170 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
176 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
171 if len(ps) > 1:
177 if len(ps) > 1:
172 if not p2:
178 if not p2:
173 p2 = repo[ps[1]]
179 p2 = repo[ps[1]]
174 for fn in p2:
180 for fn in p2:
175 if fn.startswith("nf"):
181 if fn.startswith("nf"):
176 files.append(fn)
182 files.append(fn)
177 fctxs[fn] = p2[fn]
183 fctxs[fn] = p2[fn]
178
184
179 def fctxfn(repo, cx, path):
185 def fctxfn(repo, cx, path):
180 return fctxs.get(path)
186 return fctxs.get(path)
181
187
182 if len(ps) == 0 or ps[0] < 0:
188 if len(ps) == 0 or ps[0] < 0:
183 pars = [None, None]
189 pars = [None, None]
184 elif len(ps) == 1:
190 elif len(ps) == 1:
185 pars = [nodeids[ps[0]], None]
191 pars = [nodeids[ps[0]], None]
186 else:
192 else:
187 pars = [nodeids[p] for p in ps]
193 pars = [nodeids[p] for p in ps]
188 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
194 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
189 date=(id, 0),
195 date=(id, 0),
190 user="debugbuilddag",
196 user="debugbuilddag",
191 extra={'branch': atbranch})
197 extra={'branch': atbranch})
192 nodeid = repo.commitctx(cx)
198 nodeid = repo.commitctx(cx)
193 nodeids.append(nodeid)
199 nodeids.append(nodeid)
194 at = id
200 at = id
195 elif type == 'l':
201 elif type == 'l':
196 id, name = data
202 id, name = data
197 ui.note(('tag %s\n' % name))
203 ui.note(('tag %s\n' % name))
198 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
204 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
199 elif type == 'a':
205 elif type == 'a':
200 ui.note(('branch %s\n' % data))
206 ui.note(('branch %s\n' % data))
201 atbranch = data
207 atbranch = data
202 ui.progress(_('building'), id, unit=_('revisions'), total=total)
208 ui.progress(_('building'), id, unit=_('revisions'), total=total)
203 tr.close()
209 tr.close()
204
210
205 if tags:
211 if tags:
206 repo.vfs.write("localtags", "".join(tags))
212 repo.vfs.write("localtags", "".join(tags))
207 finally:
213 finally:
208 ui.progress(_('building'), None)
214 ui.progress(_('building'), None)
209 release(tr, lock, wlock)
215 release(tr, lock, wlock)
210
216
211 @command('debugbundle',
217 @command('debugbundle',
212 [('a', 'all', None, _('show all details')),
218 [('a', 'all', None, _('show all details')),
213 ('', 'spec', None, _('print the bundlespec of the bundle'))],
219 ('', 'spec', None, _('print the bundlespec of the bundle'))],
214 _('FILE'),
220 _('FILE'),
215 norepo=True)
221 norepo=True)
216 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
222 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
217 """lists the contents of a bundle"""
223 """lists the contents of a bundle"""
218 with hg.openpath(ui, bundlepath) as f:
224 with hg.openpath(ui, bundlepath) as f:
219 if spec:
225 if spec:
220 spec = exchange.getbundlespec(ui, f)
226 spec = exchange.getbundlespec(ui, f)
221 ui.write('%s\n' % spec)
227 ui.write('%s\n' % spec)
222 return
228 return
223
229
224 gen = exchange.readbundle(ui, f, bundlepath)
230 gen = exchange.readbundle(ui, f, bundlepath)
225 if isinstance(gen, bundle2.unbundle20):
231 if isinstance(gen, bundle2.unbundle20):
226 return _debugbundle2(ui, gen, all=all, **opts)
232 return _debugbundle2(ui, gen, all=all, **opts)
227 _debugchangegroup(ui, gen, all=all, **opts)
233 _debugchangegroup(ui, gen, all=all, **opts)
228
234
229 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
235 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
230 indent_string = ' ' * indent
236 indent_string = ' ' * indent
231 if all:
237 if all:
232 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
238 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
233 % indent_string)
239 % indent_string)
234
240
235 def showchunks(named):
241 def showchunks(named):
236 ui.write("\n%s%s\n" % (indent_string, named))
242 ui.write("\n%s%s\n" % (indent_string, named))
237 chain = None
243 chain = None
238 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
244 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
239 node = chunkdata['node']
245 node = chunkdata['node']
240 p1 = chunkdata['p1']
246 p1 = chunkdata['p1']
241 p2 = chunkdata['p2']
247 p2 = chunkdata['p2']
242 cs = chunkdata['cs']
248 cs = chunkdata['cs']
243 deltabase = chunkdata['deltabase']
249 deltabase = chunkdata['deltabase']
244 delta = chunkdata['delta']
250 delta = chunkdata['delta']
245 ui.write("%s%s %s %s %s %s %s\n" %
251 ui.write("%s%s %s %s %s %s %s\n" %
246 (indent_string, hex(node), hex(p1), hex(p2),
252 (indent_string, hex(node), hex(p1), hex(p2),
247 hex(cs), hex(deltabase), len(delta)))
253 hex(cs), hex(deltabase), len(delta)))
248 chain = node
254 chain = node
249
255
250 chunkdata = gen.changelogheader()
256 chunkdata = gen.changelogheader()
251 showchunks("changelog")
257 showchunks("changelog")
252 chunkdata = gen.manifestheader()
258 chunkdata = gen.manifestheader()
253 showchunks("manifest")
259 showchunks("manifest")
254 for chunkdata in iter(gen.filelogheader, {}):
260 for chunkdata in iter(gen.filelogheader, {}):
255 fname = chunkdata['filename']
261 fname = chunkdata['filename']
256 showchunks(fname)
262 showchunks(fname)
257 else:
263 else:
258 if isinstance(gen, bundle2.unbundle20):
264 if isinstance(gen, bundle2.unbundle20):
259 raise error.Abort(_('use debugbundle2 for this file'))
265 raise error.Abort(_('use debugbundle2 for this file'))
260 chunkdata = gen.changelogheader()
266 chunkdata = gen.changelogheader()
261 chain = None
267 chain = None
262 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
268 for chunkdata in iter(lambda: gen.deltachunk(chain), {}):
263 node = chunkdata['node']
269 node = chunkdata['node']
264 ui.write("%s%s\n" % (indent_string, hex(node)))
270 ui.write("%s%s\n" % (indent_string, hex(node)))
265 chain = node
271 chain = node
266
272
267 def _debugbundle2(ui, gen, all=None, **opts):
273 def _debugbundle2(ui, gen, all=None, **opts):
268 """lists the contents of a bundle2"""
274 """lists the contents of a bundle2"""
269 if not isinstance(gen, bundle2.unbundle20):
275 if not isinstance(gen, bundle2.unbundle20):
270 raise error.Abort(_('not a bundle2 file'))
276 raise error.Abort(_('not a bundle2 file'))
271 ui.write(('Stream params: %s\n' % repr(gen.params)))
277 ui.write(('Stream params: %s\n' % repr(gen.params)))
272 for part in gen.iterparts():
278 for part in gen.iterparts():
273 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
279 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
274 if part.type == 'changegroup':
280 if part.type == 'changegroup':
275 version = part.params.get('version', '01')
281 version = part.params.get('version', '01')
276 cg = changegroup.getunbundler(version, part, 'UN')
282 cg = changegroup.getunbundler(version, part, 'UN')
277 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
283 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
278
284
279 @command('debugcreatestreamclonebundle', [], 'FILE')
285 @command('debugcreatestreamclonebundle', [], 'FILE')
280 def debugcreatestreamclonebundle(ui, repo, fname):
286 def debugcreatestreamclonebundle(ui, repo, fname):
281 """create a stream clone bundle file
287 """create a stream clone bundle file
282
288
283 Stream bundles are special bundles that are essentially archives of
289 Stream bundles are special bundles that are essentially archives of
284 revlog files. They are commonly used for cloning very quickly.
290 revlog files. They are commonly used for cloning very quickly.
285 """
291 """
286 requirements, gen = streamclone.generatebundlev1(repo)
292 requirements, gen = streamclone.generatebundlev1(repo)
287 changegroup.writechunks(ui, gen, fname)
293 changegroup.writechunks(ui, gen, fname)
288
294
289 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
295 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
290
296
291 @command('debugapplystreamclonebundle', [], 'FILE')
297 @command('debugapplystreamclonebundle', [], 'FILE')
292 def debugapplystreamclonebundle(ui, repo, fname):
298 def debugapplystreamclonebundle(ui, repo, fname):
293 """apply a stream clone bundle file"""
299 """apply a stream clone bundle file"""
294 f = hg.openpath(ui, fname)
300 f = hg.openpath(ui, fname)
295 gen = exchange.readbundle(ui, f, fname)
301 gen = exchange.readbundle(ui, f, fname)
296 gen.apply(repo)
302 gen.apply(repo)
297
303
298 @command('debugcheckstate', [], '')
304 @command('debugcheckstate', [], '')
299 def debugcheckstate(ui, repo):
305 def debugcheckstate(ui, repo):
300 """validate the correctness of the current dirstate"""
306 """validate the correctness of the current dirstate"""
301 parent1, parent2 = repo.dirstate.parents()
307 parent1, parent2 = repo.dirstate.parents()
302 m1 = repo[parent1].manifest()
308 m1 = repo[parent1].manifest()
303 m2 = repo[parent2].manifest()
309 m2 = repo[parent2].manifest()
304 errors = 0
310 errors = 0
305 for f in repo.dirstate:
311 for f in repo.dirstate:
306 state = repo.dirstate[f]
312 state = repo.dirstate[f]
307 if state in "nr" and f not in m1:
313 if state in "nr" and f not in m1:
308 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
314 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
309 errors += 1
315 errors += 1
310 if state in "a" and f in m1:
316 if state in "a" and f in m1:
311 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
317 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
312 errors += 1
318 errors += 1
313 if state in "m" and f not in m1 and f not in m2:
319 if state in "m" and f not in m1 and f not in m2:
314 ui.warn(_("%s in state %s, but not in either manifest\n") %
320 ui.warn(_("%s in state %s, but not in either manifest\n") %
315 (f, state))
321 (f, state))
316 errors += 1
322 errors += 1
317 for f in m1:
323 for f in m1:
318 state = repo.dirstate[f]
324 state = repo.dirstate[f]
319 if state not in "nrm":
325 if state not in "nrm":
320 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
326 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
321 errors += 1
327 errors += 1
322 if errors:
328 if errors:
323 error = _(".hg/dirstate inconsistent with current parent's manifest")
329 error = _(".hg/dirstate inconsistent with current parent's manifest")
324 raise error.Abort(error)
330 raise error.Abort(error)
325
331
326 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
332 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
327 def debugcommands(ui, cmd='', *args):
333 def debugcommands(ui, cmd='', *args):
328 """list all available commands and options"""
334 """list all available commands and options"""
329 for cmd, vals in sorted(commands.table.iteritems()):
335 for cmd, vals in sorted(commands.table.iteritems()):
330 cmd = cmd.split('|')[0].strip('^')
336 cmd = cmd.split('|')[0].strip('^')
331 opts = ', '.join([i[1] for i in vals[1]])
337 opts = ', '.join([i[1] for i in vals[1]])
332 ui.write('%s: %s\n' % (cmd, opts))
338 ui.write('%s: %s\n' % (cmd, opts))
333
339
334 @command('debugcomplete',
340 @command('debugcomplete',
335 [('o', 'options', None, _('show the command options'))],
341 [('o', 'options', None, _('show the command options'))],
336 _('[-o] CMD'),
342 _('[-o] CMD'),
337 norepo=True)
343 norepo=True)
338 def debugcomplete(ui, cmd='', **opts):
344 def debugcomplete(ui, cmd='', **opts):
339 """returns the completion list associated with the given command"""
345 """returns the completion list associated with the given command"""
340
346
341 if opts.get('options'):
347 if opts.get('options'):
342 options = []
348 options = []
343 otables = [commands.globalopts]
349 otables = [commands.globalopts]
344 if cmd:
350 if cmd:
345 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
351 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
346 otables.append(entry[1])
352 otables.append(entry[1])
347 for t in otables:
353 for t in otables:
348 for o in t:
354 for o in t:
349 if "(DEPRECATED)" in o[3]:
355 if "(DEPRECATED)" in o[3]:
350 continue
356 continue
351 if o[0]:
357 if o[0]:
352 options.append('-%s' % o[0])
358 options.append('-%s' % o[0])
353 options.append('--%s' % o[1])
359 options.append('--%s' % o[1])
354 ui.write("%s\n" % "\n".join(options))
360 ui.write("%s\n" % "\n".join(options))
355 return
361 return
356
362
357 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, commands.table)
363 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, commands.table)
358 if ui.verbose:
364 if ui.verbose:
359 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
365 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
360 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
366 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
361
367
362 @command('debugdag',
368 @command('debugdag',
363 [('t', 'tags', None, _('use tags as labels')),
369 [('t', 'tags', None, _('use tags as labels')),
364 ('b', 'branches', None, _('annotate with branch names')),
370 ('b', 'branches', None, _('annotate with branch names')),
365 ('', 'dots', None, _('use dots for runs')),
371 ('', 'dots', None, _('use dots for runs')),
366 ('s', 'spaces', None, _('separate elements by spaces'))],
372 ('s', 'spaces', None, _('separate elements by spaces'))],
367 _('[OPTION]... [FILE [REV]...]'),
373 _('[OPTION]... [FILE [REV]...]'),
368 optionalrepo=True)
374 optionalrepo=True)
369 def debugdag(ui, repo, file_=None, *revs, **opts):
375 def debugdag(ui, repo, file_=None, *revs, **opts):
370 """format the changelog or an index DAG as a concise textual description
376 """format the changelog or an index DAG as a concise textual description
371
377
372 If you pass a revlog index, the revlog's DAG is emitted. If you list
378 If you pass a revlog index, the revlog's DAG is emitted. If you list
373 revision numbers, they get labeled in the output as rN.
379 revision numbers, they get labeled in the output as rN.
374
380
375 Otherwise, the changelog DAG of the current repo is emitted.
381 Otherwise, the changelog DAG of the current repo is emitted.
376 """
382 """
377 spaces = opts.get('spaces')
383 spaces = opts.get('spaces')
378 dots = opts.get('dots')
384 dots = opts.get('dots')
379 if file_:
385 if file_:
380 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
386 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
381 revs = set((int(r) for r in revs))
387 revs = set((int(r) for r in revs))
382 def events():
388 def events():
383 for r in rlog:
389 for r in rlog:
384 yield 'n', (r, list(p for p in rlog.parentrevs(r)
390 yield 'n', (r, list(p for p in rlog.parentrevs(r)
385 if p != -1))
391 if p != -1))
386 if r in revs:
392 if r in revs:
387 yield 'l', (r, "r%i" % r)
393 yield 'l', (r, "r%i" % r)
388 elif repo:
394 elif repo:
389 cl = repo.changelog
395 cl = repo.changelog
390 tags = opts.get('tags')
396 tags = opts.get('tags')
391 branches = opts.get('branches')
397 branches = opts.get('branches')
392 if tags:
398 if tags:
393 labels = {}
399 labels = {}
394 for l, n in repo.tags().items():
400 for l, n in repo.tags().items():
395 labels.setdefault(cl.rev(n), []).append(l)
401 labels.setdefault(cl.rev(n), []).append(l)
396 def events():
402 def events():
397 b = "default"
403 b = "default"
398 for r in cl:
404 for r in cl:
399 if branches:
405 if branches:
400 newb = cl.read(cl.node(r))[5]['branch']
406 newb = cl.read(cl.node(r))[5]['branch']
401 if newb != b:
407 if newb != b:
402 yield 'a', newb
408 yield 'a', newb
403 b = newb
409 b = newb
404 yield 'n', (r, list(p for p in cl.parentrevs(r)
410 yield 'n', (r, list(p for p in cl.parentrevs(r)
405 if p != -1))
411 if p != -1))
406 if tags:
412 if tags:
407 ls = labels.get(r)
413 ls = labels.get(r)
408 if ls:
414 if ls:
409 for l in ls:
415 for l in ls:
410 yield 'l', (r, l)
416 yield 'l', (r, l)
411 else:
417 else:
412 raise error.Abort(_('need repo for changelog dag'))
418 raise error.Abort(_('need repo for changelog dag'))
413
419
414 for line in dagparser.dagtextlines(events(),
420 for line in dagparser.dagtextlines(events(),
415 addspaces=spaces,
421 addspaces=spaces,
416 wraplabels=True,
422 wraplabels=True,
417 wrapannotations=True,
423 wrapannotations=True,
418 wrapnonlinear=dots,
424 wrapnonlinear=dots,
419 usedots=dots,
425 usedots=dots,
420 maxlinewidth=70):
426 maxlinewidth=70):
421 ui.write(line)
427 ui.write(line)
422 ui.write("\n")
428 ui.write("\n")
423
429
424 @command('debugdata', commands.debugrevlogopts, _('-c|-m|FILE REV'))
430 @command('debugdata', commands.debugrevlogopts, _('-c|-m|FILE REV'))
425 def debugdata(ui, repo, file_, rev=None, **opts):
431 def debugdata(ui, repo, file_, rev=None, **opts):
426 """dump the contents of a data file revision"""
432 """dump the contents of a data file revision"""
427 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
433 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
428 if rev is not None:
434 if rev is not None:
429 raise error.CommandError('debugdata', _('invalid arguments'))
435 raise error.CommandError('debugdata', _('invalid arguments'))
430 file_, rev = None, file_
436 file_, rev = None, file_
431 elif rev is None:
437 elif rev is None:
432 raise error.CommandError('debugdata', _('invalid arguments'))
438 raise error.CommandError('debugdata', _('invalid arguments'))
433 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
439 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
434 try:
440 try:
435 ui.write(r.revision(r.lookup(rev)))
441 ui.write(r.revision(r.lookup(rev)))
436 except KeyError:
442 except KeyError:
437 raise error.Abort(_('invalid revision identifier %s') % rev)
443 raise error.Abort(_('invalid revision identifier %s') % rev)
438
444
439 @command('debugdate',
445 @command('debugdate',
440 [('e', 'extended', None, _('try extended date formats'))],
446 [('e', 'extended', None, _('try extended date formats'))],
441 _('[-e] DATE [RANGE]'),
447 _('[-e] DATE [RANGE]'),
442 norepo=True, optionalrepo=True)
448 norepo=True, optionalrepo=True)
443 def debugdate(ui, date, range=None, **opts):
449 def debugdate(ui, date, range=None, **opts):
444 """parse and display a date"""
450 """parse and display a date"""
445 if opts["extended"]:
451 if opts["extended"]:
446 d = util.parsedate(date, util.extendeddateformats)
452 d = util.parsedate(date, util.extendeddateformats)
447 else:
453 else:
448 d = util.parsedate(date)
454 d = util.parsedate(date)
449 ui.write(("internal: %s %s\n") % d)
455 ui.write(("internal: %s %s\n") % d)
450 ui.write(("standard: %s\n") % util.datestr(d))
456 ui.write(("standard: %s\n") % util.datestr(d))
451 if range:
457 if range:
452 m = util.matchdate(range)
458 m = util.matchdate(range)
453 ui.write(("match: %s\n") % m(d[0]))
459 ui.write(("match: %s\n") % m(d[0]))
460
461 @command('debugdiscovery',
462 [('', 'old', None, _('use old-style discovery')),
463 ('', 'nonheads', None,
464 _('use old-style discovery with non-heads included')),
465 ] + commands.remoteopts,
466 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
467 def debugdiscovery(ui, repo, remoteurl="default", **opts):
468 """runs the changeset discovery protocol in isolation"""
469 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
470 opts.get('branch'))
471 remote = hg.peer(repo, opts, remoteurl)
472 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
473
474 # make sure tests are repeatable
475 random.seed(12323)
476
477 def doit(localheads, remoteheads, remote=remote):
478 if opts.get('old'):
479 if localheads:
480 raise error.Abort('cannot use localheads with old style '
481 'discovery')
482 if not util.safehasattr(remote, 'branches'):
483 # enable in-client legacy support
484 remote = localrepo.locallegacypeer(remote.local())
485 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
486 force=True)
487 common = set(common)
488 if not opts.get('nonheads'):
489 ui.write(("unpruned common: %s\n") %
490 " ".join(sorted(short(n) for n in common)))
491 dag = dagutil.revlogdag(repo.changelog)
492 all = dag.ancestorset(dag.internalizeall(common))
493 common = dag.externalizeall(dag.headsetofconnecteds(all))
494 else:
495 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
496 common = set(common)
497 rheads = set(hds)
498 lheads = set(repo.heads())
499 ui.write(("common heads: %s\n") %
500 " ".join(sorted(short(n) for n in common)))
501 if lheads <= common:
502 ui.write(("local is subset\n"))
503 elif rheads <= common:
504 ui.write(("remote is subset\n"))
505
506 serverlogs = opts.get('serverlog')
507 if serverlogs:
508 for filename in serverlogs:
509 with open(filename, 'r') as logfile:
510 line = logfile.readline()
511 while line:
512 parts = line.strip().split(';')
513 op = parts[1]
514 if op == 'cg':
515 pass
516 elif op == 'cgss':
517 doit(parts[2].split(' '), parts[3].split(' '))
518 elif op == 'unb':
519 doit(parts[3].split(' '), parts[2].split(' '))
520 line = logfile.readline()
521 else:
522 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
523 opts.get('remote_head'))
524 localrevs = opts.get('local_head')
525 doit(localrevs, remoterevs)
General Comments 0
You need to be logged in to leave comments. Login now